Curves: Rename "Hair" types, variables, and functions to "Curves"

Based on discussions from T95355 and T94193, the plan is to use
the name "Curves" to describe the data-block container for multiple
curves. Eventually this will replace the existing "Curve" data-block.
However, it will be a while before the curve data-block can be replaced
so in order to distinguish the two curve types in the UI, "Hair Curves"
will be used, but eventually changed back to "Curves".

This patch renames "hair-related" files, functions, types, and variable
names to this convention. A deep rename is preferred to keep code
consistent and to avoid any "hair" terminology from leaking, since the
new data-block is meant for all curve types, not just hair use cases.

The downside of this naming is that the difference between "Curve"
and "Curves" has become important. That was considered during
design discussons and deemed acceptable, especially given the
non-permanent nature of the somewhat common conflict.

Some points of interest:
- All DNA compatibility is lost, just like rBf59767ff9729.
- I renamed `ID_HA` to `ID_CV` so there is no complete mismatch.
- `hair_curves` is used where necessary to distinguish from the
  existing "curves" plural.
- I didn't rename any of the cycles/rendering code function names,
  since that is also used by the old hair particle system.

Differential Revision: https://developer.blender.org/D14007
This commit is contained in:
Hans Goudey 2022-02-07 11:55:54 -06:00
parent b8c764c5d1
commit fe1816f67f
99 changed files with 1051 additions and 1030 deletions

@ -626,11 +626,11 @@ void BlenderSync::sync_particle_hair(
}
}
#ifdef WITH_HAIR_NODES
#ifdef WITH_NEW_CURVES_TYPE
static std::optional<BL::FloatAttribute> find_curves_radius_attribute(BL::Hair b_hair)
static std::optional<BL::FloatAttribute> find_curves_radius_attribute(BL::Curves b_curves)
{
for (BL::Attribute &b_attribute : b_hair.attributes) {
for (BL::Attribute &b_attribute : b_curves.attributes) {
if (b_attribute.name() != "radius") {
continue;
}
@ -645,16 +645,16 @@ static std::optional<BL::FloatAttribute> find_curves_radius_attribute(BL::Hair b
return std::nullopt;
}
static float4 hair_point_as_float4(BL::Hair b_hair,
static float4 hair_point_as_float4(BL::Curves b_curves,
std::optional<BL::FloatAttribute> b_attr_radius,
const int index)
{
float4 mP = float3_to_float4(get_float3(b_hair.position_data[index].vector()));
float4 mP = float3_to_float4(get_float3(b_curves.position_data[index].vector()));
mP.w = b_attr_radius ? b_attr_radius->data[index].value() : 0.0f;
return mP;
}
static float4 interpolate_hair_points(BL::Hair b_hair,
static float4 interpolate_hair_points(BL::Curves b_curves,
std::optional<BL::FloatAttribute> b_attr_radius,
const int first_point_index,
const int num_points,
@ -664,12 +664,12 @@ static float4 interpolate_hair_points(BL::Hair b_hair,
const int point_a = clamp((int)curve_t, 0, num_points - 1);
const int point_b = min(point_a + 1, num_points - 1);
const float t = curve_t - (float)point_a;
return lerp(hair_point_as_float4(b_hair, b_attr_radius, first_point_index + point_a),
hair_point_as_float4(b_hair, b_attr_radius, first_point_index + point_b),
return lerp(hair_point_as_float4(b_curves, b_attr_radius, first_point_index + point_a),
hair_point_as_float4(b_curves, b_attr_radius, first_point_index + point_b),
t);
}
static void export_hair_curves(Scene *scene, Hair *hair, BL::Hair b_hair)
static void export_hair_curves(Scene *scene, Hair *hair, BL::Curves b_curves)
{
/* TODO: optimize so we can straight memcpy arrays from Blender? */
@ -689,19 +689,19 @@ static void export_hair_curves(Scene *scene, Hair *hair, BL::Hair b_hair)
}
/* Reserve memory. */
const int num_keys = b_hair.points.length();
const int num_curves = b_hair.curves.length();
const int num_keys = b_curves.points.length();
const int num_curves = b_curves.curves.length();
hair->reserve_curves(num_curves, num_keys);
std::optional<BL::FloatAttribute> b_attr_radius = find_curves_radius_attribute(b_hair);
std::optional<BL::FloatAttribute> b_attr_radius = find_curves_radius_attribute(b_curves);
/* Export curves and points. */
vector<float> points_length;
for (int i = 0; i < num_curves; i++) {
const int first_point_index = b_hair.curve_offset_data[i].value();
const int num_points = b_hair.curve_offset_data[i + 1].value() - first_point_index;
const int first_point_index = b_curves.curve_offset_data[i].value();
const int num_points = b_curves.curve_offset_data[i + 1].value() - first_point_index;
float3 prev_co = zero_float3();
float length = 0.0f;
@ -712,7 +712,7 @@ static void export_hair_curves(Scene *scene, Hair *hair, BL::Hair b_hair)
/* Position and radius. */
for (int i = 0; i < num_points; i++) {
const float3 co = get_float3(b_hair.position_data[first_point_index + i].vector());
const float3 co = get_float3(b_curves.position_data[first_point_index + i].vector());
const float radius = b_attr_radius ? b_attr_radius->data[first_point_index + i].value() :
0.0f;
hair->add_curve_key(co, radius);
@ -748,7 +748,7 @@ static void export_hair_curves(Scene *scene, Hair *hair, BL::Hair b_hair)
}
}
static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_step)
static void export_hair_curves_motion(Hair *hair, BL::Curves b_curves, int motion_step)
{
/* Find or add attribute. */
Attribute *attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
@ -761,17 +761,17 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st
/* Export motion keys. */
const int num_keys = hair->get_curve_keys().size();
const int num_curves = b_hair.curves.length();
const int num_curves = b_curves.curves.length();
float4 *mP = attr_mP->data_float4() + motion_step * num_keys;
bool have_motion = false;
int num_motion_keys = 0;
int curve_index = 0;
std::optional<BL::FloatAttribute> b_attr_radius = find_curves_radius_attribute(b_hair);
std::optional<BL::FloatAttribute> b_attr_radius = find_curves_radius_attribute(b_curves);
for (int i = 0; i < num_curves; i++) {
const int first_point_index = b_hair.curve_offset_data[i].value();
const int num_points = b_hair.curve_offset_data[i + 1].value() - first_point_index;
const int first_point_index = b_curves.curve_offset_data[i].value();
const int num_points = b_curves.curve_offset_data[i + 1].value() - first_point_index;
Hair::Curve curve = hair->get_curve(curve_index);
curve_index++;
@ -782,7 +782,7 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st
int point_index = first_point_index + i;
if (point_index < num_keys) {
mP[num_motion_keys] = hair_point_as_float4(b_hair, b_attr_radius, point_index);
mP[num_motion_keys] = hair_point_as_float4(b_curves, b_attr_radius, point_index);
num_motion_keys++;
if (!have_motion) {
@ -802,7 +802,7 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st
for (int i = 0; i < curve.num_keys; i++) {
const float step = i * step_size;
mP[num_motion_keys] = interpolate_hair_points(
b_hair, b_attr_radius, first_point_index, num_points, step);
b_curves, b_attr_radius, first_point_index, num_points, step);
num_motion_keys++;
}
have_motion = true;
@ -819,12 +819,12 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st
void BlenderSync::sync_hair(Hair *hair, BObjectInfo &b_ob_info, bool motion, int motion_step)
{
/* Convert Blender hair to Cycles curves. */
BL::Hair b_hair(b_ob_info.object_data);
BL::Curves b_curves(b_ob_info.object_data);
if (motion) {
export_hair_curves_motion(hair, b_hair, motion_step);
export_hair_curves_motion(hair, b_curves, motion_step);
}
else {
export_hair_curves(scene, hair, b_hair);
export_hair_curves(scene, hair, b_curves);
}
}
#else
@ -847,8 +847,8 @@ void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, H
new_hair.set_used_shaders(used_shaders);
if (view_layer.use_hair) {
#ifdef WITH_HAIR_NODES
if (b_ob_info.object_data.is_a(&RNA_Hair)) {
#ifdef WITH_NEW_CURVES_TYPE
if (b_ob_info.object_data.is_a(&RNA_Curves)) {
/* Hair object. */
sync_hair(&new_hair, b_ob_info, false);
}
@ -901,8 +901,8 @@ void BlenderSync::sync_hair_motion(BL::Depsgraph b_depsgraph,
/* Export deformed coordinates. */
if (ccl::BKE_object_is_deform_modified(b_ob_info, b_scene, preview)) {
#ifdef WITH_HAIR_NODES
if (b_ob_info.object_data.is_a(&RNA_Hair)) {
#ifdef WITH_NEW_CURVES_TYPE
if (b_ob_info.object_data.is_a(&RNA_Curves)) {
/* Hair object. */
sync_hair(hair, b_ob_info, true, motion_step);
return;

@ -32,8 +32,8 @@ CCL_NAMESPACE_BEGIN
static Geometry::Type determine_geom_type(BObjectInfo &b_ob_info, bool use_particle_hair)
{
#ifdef WITH_HAIR_NODES
if (b_ob_info.object_data.is_a(&RNA_Hair) || use_particle_hair) {
#ifdef WITH_NEW_CURVES_TYPE
if (b_ob_info.object_data.is_a(&RNA_Curves) || use_particle_hair) {
#else
if (use_particle_hair) {
#endif
@ -231,8 +231,8 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
if (progress.get_cancel())
return;
#ifdef WITH_HAIR_NODES
if (b_ob_info.object_data.is_a(&RNA_Hair) || use_particle_hair) {
#ifdef WITH_NEW_CURVES_TYPE
if (b_ob_info.object_data.is_a(&RNA_Curves) || use_particle_hair) {
#else
if (use_particle_hair) {
#endif

@ -72,7 +72,7 @@ bool BlenderSync::object_is_geometry(BObjectInfo &b_ob_info)
BL::Object::type_enum type = b_ob_info.iter_object.type();
if (type == BL::Object::type_VOLUME || type == BL::Object::type_HAIR ||
if (type == BL::Object::type_VOLUME || type == BL::Object::type_CURVES ||
type == BL::Object::type_POINTCLOUD) {
/* Will be exported attached to mesh. */
return true;
@ -97,7 +97,7 @@ bool BlenderSync::object_can_have_geometry(BL::Object &b_ob)
case BL::Object::type_SURFACE:
case BL::Object::type_META:
case BL::Object::type_FONT:
case BL::Object::type_HAIR:
case BL::Object::type_CURVES:
case BL::Object::type_POINTCLOUD:
case BL::Object::type_VOLUME:
return true;

@ -33,9 +33,9 @@ _modules = [
"properties_data_bone",
"properties_data_camera",
"properties_data_curve",
"properties_data_curves",
"properties_data_empty",
"properties_data_gpencil",
"properties_data_hair",
"properties_data_light",
"properties_data_lattice",
"properties_data_mesh",

@ -30,10 +30,10 @@ class DataButtonsPanel:
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
return hasattr(context, 'hair') and context.hair and (engine in cls.COMPAT_ENGINES)
return hasattr(context, 'curves') and context.curves and (engine in cls.COMPAT_ENGINES)
class DATA_PT_context_hair(DataButtonsPanel, Panel):
class DATA_PT_context_curves(DataButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
@ -42,21 +42,21 @@ class DATA_PT_context_hair(DataButtonsPanel, Panel):
layout = self.layout
ob = context.object
hair = context.hair
curves = context.curves
space = context.space_data
if ob:
layout.template_ID(ob, "data")
elif hair:
elif curves:
layout.template_ID(space, "pin_id")
class HAIR_MT_add_attribute(Menu):
class CURVES_MT_add_attribute(Menu):
bl_label = "Add Attribute"
@staticmethod
def add_standard_attribute(layout, hair, name, data_type, domain):
exists = hair.attributes.get(name) is not None
def add_standard_attribute(layout, curves, name, data_type, domain):
exists = curves.attributes.get(name) is not None
col = layout.column()
col.enabled = not exists
@ -69,10 +69,10 @@ class HAIR_MT_add_attribute(Menu):
def draw(self, context):
layout = self.layout
hair = context.hair
curves = context.curves
self.add_standard_attribute(layout, hair, 'Radius', 'FLOAT', 'POINT')
self.add_standard_attribute(layout, hair, 'Color', 'FLOAT_COLOR', 'POINT')
self.add_standard_attribute(layout, curves, 'radius', 'FLOAT', 'POINT')
self.add_standard_attribute(layout, curves, 'color', 'FLOAT_COLOR', 'POINT')
layout.separator()
@ -80,7 +80,7 @@ class HAIR_MT_add_attribute(Menu):
layout.operator("geometry.attribute_add", text="Custom...")
class HAIR_UL_attributes(UIList):
class CURVES_UL_attributes(UIList):
def draw_item(self, _context, layout, _data, attribute, _icon, _active_data, _active_propname, _index):
data_type = attribute.bl_rna.properties['data_type'].enum_items[attribute.data_type]
domain = attribute.bl_rna.properties['domain'].enum_items[attribute.domain]
@ -96,44 +96,44 @@ class HAIR_UL_attributes(UIList):
sub.label(text=data_type.name)
class DATA_PT_hair_attributes(DataButtonsPanel, Panel):
class DATA_PT_CURVES_attributes(DataButtonsPanel, Panel):
bl_label = "Attributes"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
def draw(self, context):
hair = context.hair
curves = context.curves
layout = self.layout
row = layout.row()
col = row.column()
col.template_list(
"HAIR_UL_attributes",
"CURVES_UL_attributes",
"attributes",
hair,
curves,
"attributes",
hair.attributes,
curves.attributes,
"active_index",
rows=3,
)
col = row.column(align=True)
col.menu("HAIR_MT_add_attribute", icon='ADD', text="")
col.menu("CURVES_MT_add_attribute", icon='ADD', text="")
col.operator("geometry.attribute_remove", icon='REMOVE', text="")
class DATA_PT_custom_props_hair(DataButtonsPanel, PropertyPanel, Panel):
class DATA_PT_custom_props_curves(DataButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
_context_path = "object.data"
_property_type = bpy.types.Hair if hasattr(bpy.types, "Hair") else None
_property_type = bpy.types.Curves if hasattr(bpy.types, "Curves") else None
classes = (
DATA_PT_context_hair,
DATA_PT_hair_attributes,
DATA_PT_custom_props_hair,
HAIR_MT_add_attribute,
HAIR_UL_attributes,
DATA_PT_context_curves,
DATA_PT_CURVES_attributes,
DATA_PT_custom_props_curves,
CURVES_MT_add_attribute,
CURVES_UL_attributes,
)
if __name__ == "__main__": # only for live edit.

@ -127,8 +127,8 @@ class DopesheetFilterPopoverBase:
flow.prop(dopesheet, "show_lattices", text="Lattices")
if bpy.data.metaballs:
flow.prop(dopesheet, "show_metaballs", text="Metaballs")
if hasattr(bpy.data, "hairs") and bpy.data.hairs:
flow.prop(dopesheet, "show_hairs", text="Hairs")
if hasattr(bpy.data, "hair_curves") and bpy.data.hair_curves:
flow.prop(dopesheet, "show_hair_curves", text="Hair Curves")
if hasattr(bpy.data, "pointclouds") and bpy.data.pointclouds:
flow.prop(dopesheet, "show_pointclouds", text="Point Clouds")
if bpy.data.volumes:

@ -448,7 +448,7 @@ class OUTLINER_PT_filter(Panel):
if (
bpy.data.curves or
bpy.data.metaballs or
(hasattr(bpy.data, "hairs") and bpy.data.hairs) or
(hasattr(bpy.data, "hair_curves") and bpy.data.hair_curves) or
(hasattr(bpy.data, "pointclouds") and bpy.data.pointclouds) or
bpy.data.volumes or
bpy.data.lightprobes or

@ -2295,7 +2295,7 @@ class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel):
def draw(self, context):
self._draw_items(
context, (
({"property": "use_new_hair_type"}, "T68981"),
({"property": "use_new_curves_type"}, "T68981"),
({"property": "use_new_point_cloud_type"}, "T75717"),
({"property": "use_full_frame_compositor"}, "T88150"),
),

@ -2148,8 +2148,8 @@ class VIEW3D_MT_add(Menu):
layout.menu("VIEW3D_MT_surface_add", icon='OUTLINER_OB_SURFACE')
layout.menu("VIEW3D_MT_metaball_add", text="Metaball", icon='OUTLINER_OB_META')
layout.operator("object.text_add", text="Text", icon='OUTLINER_OB_FONT')
if context.preferences.experimental.use_new_hair_type:
layout.operator("object.hair_add", text="Hair", icon='OUTLINER_OB_HAIR')
if context.preferences.experimental.use_new_curves_type:
layout.operator("object.hair_curves_add", text="Hair Curves", icon='OUTLINER_OB_CURVES')
if context.preferences.experimental.use_new_point_cloud_type:
layout.operator("object.pointcloud_add", text="Point Cloud", icon='OUTLINER_OB_POINTCLOUD')
layout.menu("VIEW3D_MT_volume_add", text="Volume", icon='OUTLINER_OB_VOLUME')

@ -48,7 +48,7 @@ set(SRC_DNA_INC
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpencil_modifier_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpencil_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpu_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_hair_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_curves_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_image_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_ipo_types.h
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_key_types.h

@ -40,11 +40,11 @@ struct ReportList;
/* Attribute.domain */
typedef enum AttributeDomain {
ATTR_DOMAIN_AUTO = -1, /* Use for nodes to choose automatically based on other data. */
ATTR_DOMAIN_POINT = 0, /* Mesh, Hair or PointCloud Point */
ATTR_DOMAIN_POINT = 0, /* Mesh, Curve or Point Cloud Point */
ATTR_DOMAIN_EDGE = 1, /* Mesh Edge */
ATTR_DOMAIN_FACE = 2, /* Mesh Face */
ATTR_DOMAIN_CORNER = 3, /* Mesh Corner */
ATTR_DOMAIN_CURVE = 4, /* Hair Curve */
ATTR_DOMAIN_CURVE = 4, /* A single curve in a larger curve data-block */
ATTR_DOMAIN_INSTANCE = 5, /* Instance */
ATTR_DOMAIN_NUM

@ -0,0 +1,68 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#pragma once
/** \file
* \ingroup bke
* \brief Low-level operations for curves.
*/
#ifdef __cplusplus
extern "C" {
#endif
struct BoundBox;
struct CustomDataLayer;
struct Depsgraph;
struct Curves;
struct Main;
struct Object;
struct Scene;
void *BKE_curves_add(struct Main *bmain, const char *name);
struct BoundBox *BKE_curves_boundbox_get(struct Object *ob);
void BKE_curves_update_customdata_pointers(struct Curves *curves);
bool BKE_curves_customdata_required(struct Curves *curves, struct CustomDataLayer *layer);
/* Depsgraph */
struct Curves *BKE_curves_new_for_eval(const struct Curves *curves_src,
int totpoint,
int totcurve);
struct Curves *BKE_curves_copy_for_eval(struct Curves *curves_src, bool reference);
void BKE_curves_data_update(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *object);
/* Draw Cache */
enum {
BKE_CURVES_BATCH_DIRTY_ALL = 0,
};
void BKE_curves_batch_cache_dirty_tag(struct Curves *curves, int mode);
void BKE_curves_batch_cache_free(struct Curves *curves);
extern void (*BKE_curves_batch_cache_dirty_tag_cb)(struct Curves *curves, int mode);
extern void (*BKE_curves_batch_cache_free_cb)(struct Curves *curves);
#ifdef __cplusplus
}
#endif

@ -1,63 +0,0 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#pragma once
/** \file
* \ingroup bke
* \brief General operations for hairs.
*/
#ifdef __cplusplus
extern "C" {
#endif
struct BoundBox;
struct CustomDataLayer;
struct Depsgraph;
struct Hair;
struct Main;
struct Object;
struct Scene;
void *BKE_hair_add(struct Main *bmain, const char *name);
struct BoundBox *BKE_hair_boundbox_get(struct Object *ob);
void BKE_hair_update_customdata_pointers(struct Hair *hair);
bool BKE_hair_customdata_required(struct Hair *hair, struct CustomDataLayer *layer);
/* Depsgraph */
struct Hair *BKE_hair_new_for_eval(const struct Hair *hair_src, int totpoint, int totcurve);
struct Hair *BKE_hair_copy_for_eval(struct Hair *hair_src, bool reference);
void BKE_hair_data_update(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *object);
/* Draw Cache */
enum {
BKE_HAIR_BATCH_DIRTY_ALL = 0,
};
void BKE_hair_batch_cache_dirty_tag(struct Hair *hair, int mode);
void BKE_hair_batch_cache_free(struct Hair *hair);
extern void (*BKE_hair_batch_cache_dirty_tag_cb)(struct Hair *hair, int mode);
extern void (*BKE_hair_batch_cache_free_cb)(struct Hair *hair);
#ifdef __cplusplus
}
#endif

@ -278,7 +278,7 @@ extern IDTypeInfo IDType_ID_PC;
extern IDTypeInfo IDType_ID_CF;
extern IDTypeInfo IDType_ID_WS;
extern IDTypeInfo IDType_ID_LP;
extern IDTypeInfo IDType_ID_HA;
extern IDTypeInfo IDType_ID_CV;
extern IDTypeInfo IDType_ID_PT;
extern IDTypeInfo IDType_ID_VO;
extern IDTypeInfo IDType_ID_SIM;

@ -182,7 +182,11 @@ typedef struct Main {
ListBase linestyles;
ListBase cachefiles;
ListBase workspaces;
ListBase hairs;
/**
* \note The name `hair_curves` is chosen to be different than `curves`,
* but they are generic curve data-blocks, not just for hair.
*/
ListBase hair_curves;
ListBase pointclouds;
ListBase volumes;
ListBase simulations;

@ -119,6 +119,7 @@ set(SRC
intern/crazyspace.c
intern/cryptomatte.cc
intern/curve.cc
intern/curves.cc
intern/curve_bevel.c
intern/curve_convert.c
intern/curve_decimate.c
@ -156,7 +157,6 @@ set(SRC
intern/gpencil_curve.c
intern/gpencil_geom.cc
intern/gpencil_modifier.c
intern/hair.cc
intern/icons.cc
intern/icons_rasterize.c
intern/idprop.c
@ -356,6 +356,7 @@ set(SRC
BKE_cryptomatte.h
BKE_cryptomatte.hh
BKE_curve.h
BKE_curves.h
BKE_curve_to_mesh.hh
BKE_curveprofile.h
BKE_customdata.h
@ -384,7 +385,6 @@ set(SRC
BKE_gpencil_curve.h
BKE_gpencil_geom.h
BKE_gpencil_modifier.h
BKE_hair.h
BKE_icons.h
BKE_idprop.h
BKE_idprop.hh

@ -1284,8 +1284,8 @@ void BKE_animdata_main_cb(Main *bmain, ID_AnimData_Edit_Callback func, void *use
/* cache files */
ANIMDATA_IDS_CB(bmain->cachefiles.first);
/* hairs */
ANIMDATA_IDS_CB(bmain->hairs.first);
/* Hair Curves. */
ANIMDATA_IDS_CB(bmain->hair_curves.first);
/* pointclouds */
ANIMDATA_IDS_CB(bmain->pointclouds.first);
@ -1413,8 +1413,8 @@ void BKE_animdata_fix_paths_rename_all_ex(Main *bmain,
/* cache files */
RENAMEFIX_ANIM_IDS(bmain->cachefiles.first);
/* hairs */
RENAMEFIX_ANIM_IDS(bmain->hairs.first);
/* Hair Curves. */
RENAMEFIX_ANIM_IDS(bmain->hair_curves.first);
/* pointclouds */
RENAMEFIX_ANIM_IDS(bmain->pointclouds.first);

@ -3382,8 +3382,8 @@ void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float
/* cache files */
EVAL_ANIM_IDS(main->cachefiles.first, ADT_RECALC_ANIM);
/* hairs */
EVAL_ANIM_IDS(main->hairs.first, ADT_RECALC_ANIM);
/* Hair Curves. */
EVAL_ANIM_IDS(main->hair_curves.first, ADT_RECALC_ANIM);
/* pointclouds */
EVAL_ANIM_IDS(main->pointclouds.first, ADT_RECALC_ANIM);

@ -29,8 +29,8 @@
#include "MEM_guardedalloc.h"
#include "DNA_ID.h"
#include "DNA_curves_types.h"
#include "DNA_customdata_types.h"
#include "DNA_hair_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_pointcloud_types.h"
@ -38,9 +38,9 @@
#include "BLI_string_utf8.h"
#include "BKE_attribute.h"
#include "BKE_curves.h"
#include "BKE_customdata.h"
#include "BKE_editmesh.h"
#include "BKE_hair.h"
#include "BKE_pointcloud.h"
#include "BKE_report.h"
@ -88,12 +88,12 @@ static void get_domains(const ID *id, DomainInfo info[ATTR_DOMAIN_NUM])
}
break;
}
case ID_HA: {
Hair *hair = (Hair *)id;
info[ATTR_DOMAIN_POINT].customdata = &hair->geometry.point_data;
info[ATTR_DOMAIN_POINT].length = hair->geometry.point_size;
info[ATTR_DOMAIN_CURVE].customdata = &hair->geometry.curve_data;
info[ATTR_DOMAIN_CURVE].length = hair->geometry.curve_size;
case ID_CV: {
Curves *curves = (Curves *)id;
info[ATTR_DOMAIN_POINT].customdata = &curves->geometry.point_data;
info[ATTR_DOMAIN_POINT].length = curves->geometry.point_size;
info[ATTR_DOMAIN_CURVE].customdata = &curves->geometry.curve_data;
info[ATTR_DOMAIN_CURVE].length = curves->geometry.curve_size;
break;
}
default:
@ -301,8 +301,8 @@ bool BKE_id_attribute_required(ID *id, CustomDataLayer *layer)
case ID_PT: {
return BKE_pointcloud_customdata_required((PointCloud *)id, layer);
}
case ID_HA: {
return BKE_hair_customdata_required((Hair *)id, layer);
case ID_CV: {
return BKE_curves_customdata_required((Curves *)id, layer);
}
default:
return false;
@ -372,8 +372,8 @@ int *BKE_id_attributes_active_index_p(ID *id)
case ID_ME: {
return &((Mesh *)id)->attributes_active_index;
}
case ID_HA: {
return &((Hair *)id)->attributes_active_index;
case ID_CV: {
return &((Curves *)id)->attributes_active_index;
}
default:
return NULL;

@ -0,0 +1,473 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/** \file
* \ingroup bke
*/
#include <cmath>
#include <cstring>
#include "MEM_guardedalloc.h"
#include "DNA_curves_types.h"
#include "DNA_defaults.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "BLI_index_range.hh"
#include "BLI_listbase.h"
#include "BLI_math_base.h"
#include "BLI_math_vec_types.hh"
#include "BLI_rand.hh"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BKE_anim_data.h"
#include "BKE_curves.h"
#include "BKE_customdata.h"
#include "BKE_global.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_lib_remap.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BLT_translation.h"
#include "DEG_depsgraph_query.h"
#include "BLO_read_write.h"
using blender::float3;
using blender::IndexRange;
using blender::MutableSpan;
using blender::RandomNumberGenerator;
static const char *ATTR_POSITION = "position";
static const char *ATTR_RADIUS = "radius";
static void curves_random(Curves *curves);
static void curves_init_data(ID *id)
{
Curves *curves = (Curves *)id;
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(curves, id));
MEMCPY_STRUCT_AFTER(curves, DNA_struct_default_get(Curves), id);
CustomData_reset(&curves->geometry.point_data);
CustomData_reset(&curves->geometry.curve_data);
CustomData_add_layer_named(&curves->geometry.point_data,
CD_PROP_FLOAT3,
CD_CALLOC,
nullptr,
curves->geometry.point_size,
ATTR_POSITION);
CustomData_add_layer_named(&curves->geometry.point_data,
CD_PROP_FLOAT,
CD_CALLOC,
nullptr,
curves->geometry.point_size,
ATTR_RADIUS);
BKE_curves_update_customdata_pointers(curves);
curves_random(curves);
}
static void curves_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
{
Curves *curves_dst = (Curves *)id_dst;
const Curves *curves_src = (const Curves *)id_src;
curves_dst->mat = static_cast<Material **>(MEM_dupallocN(curves_src->mat));
curves_dst->geometry.point_size = curves_src->geometry.point_size;
curves_dst->geometry.curve_size = curves_src->geometry.curve_size;
const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
CustomData_copy(&curves_src->geometry.point_data,
&curves_dst->geometry.point_data,
CD_MASK_ALL,
alloc_type,
curves_dst->geometry.point_size);
CustomData_copy(&curves_src->geometry.curve_data,
&curves_dst->geometry.curve_data,
CD_MASK_ALL,
alloc_type,
curves_dst->geometry.curve_size);
BKE_curves_update_customdata_pointers(curves_dst);
curves_dst->geometry.offsets = static_cast<int *>(MEM_dupallocN(curves_src->geometry.offsets));
curves_dst->batch_cache = nullptr;
}
static void curves_free_data(ID *id)
{
Curves *curves = (Curves *)id;
BKE_animdata_free(&curves->id, false);
BKE_curves_batch_cache_free(curves);
CustomData_free(&curves->geometry.point_data, curves->geometry.point_size);
CustomData_free(&curves->geometry.curve_data, curves->geometry.curve_size);
MEM_SAFE_FREE(curves->geometry.offsets);
MEM_SAFE_FREE(curves->mat);
}
static void curves_foreach_id(ID *id, LibraryForeachIDData *data)
{
Curves *curves = (Curves *)id;
for (int i = 0; i < curves->totcol; i++) {
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, curves->mat[i], IDWALK_CB_USER);
}
}
static void curves_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Curves *curves = (Curves *)id;
CustomDataLayer *players = nullptr, players_buff[CD_TEMP_CHUNK_SIZE];
CustomDataLayer *clayers = nullptr, clayers_buff[CD_TEMP_CHUNK_SIZE];
CustomData_blend_write_prepare(
&curves->geometry.point_data, &players, players_buff, ARRAY_SIZE(players_buff));
CustomData_blend_write_prepare(
&curves->geometry.curve_data, &clayers, clayers_buff, ARRAY_SIZE(clayers_buff));
/* Write LibData */
BLO_write_id_struct(writer, Curves, id_address, &curves->id);
BKE_id_blend_write(writer, &curves->id);
/* Direct data */
CustomData_blend_write(writer,
&curves->geometry.point_data,
players,
curves->geometry.point_size,
CD_MASK_ALL,
&curves->id);
CustomData_blend_write(writer,
&curves->geometry.curve_data,
clayers,
curves->geometry.curve_size,
CD_MASK_ALL,
&curves->id);
BLO_write_int32_array(writer, curves->geometry.curve_size + 1, curves->geometry.offsets);
BLO_write_pointer_array(writer, curves->totcol, curves->mat);
if (curves->adt) {
BKE_animdata_blend_write(writer, curves->adt);
}
/* Remove temporary data. */
if (players && players != players_buff) {
MEM_freeN(players);
}
if (clayers && clayers != clayers_buff) {
MEM_freeN(clayers);
}
}
static void curves_blend_read_data(BlendDataReader *reader, ID *id)
{
Curves *curves = (Curves *)id;
BLO_read_data_address(reader, &curves->adt);
BKE_animdata_blend_read_data(reader, curves->adt);
/* Geometry */
CustomData_blend_read(reader, &curves->geometry.point_data, curves->geometry.point_size);
CustomData_blend_read(reader, &curves->geometry.curve_data, curves->geometry.point_size);
BKE_curves_update_customdata_pointers(curves);
BLO_read_int32_array(reader, curves->geometry.curve_size + 1, &curves->geometry.offsets);
/* Materials */
BLO_read_pointer_array(reader, (void **)&curves->mat);
}
static void curves_blend_read_lib(BlendLibReader *reader, ID *id)
{
Curves *curves = (Curves *)id;
for (int a = 0; a < curves->totcol; a++) {
BLO_read_id_address(reader, curves->id.lib, &curves->mat[a]);
}
}
static void curves_blend_read_expand(BlendExpander *expander, ID *id)
{
Curves *curves = (Curves *)id;
for (int a = 0; a < curves->totcol; a++) {
BLO_expand(expander, curves->mat[a]);
}
}
IDTypeInfo IDType_ID_CV = {
/*id_code */ ID_CV,
/*id_filter */ FILTER_ID_CV,
/*main_listbase_index */ INDEX_ID_CV,
/*struct_size */ sizeof(Curves),
/*name */ "Hair Curves",
/*name_plural */ "Hair Curves",
/*translation_context */ BLT_I18NCONTEXT_ID_CURVES,
/*flags */ IDTYPE_FLAGS_APPEND_IS_REUSABLE,
/*asset_type_info */ nullptr,
/*init_data */ curves_init_data,
/*copy_data */ curves_copy_data,
/*free_data */ curves_free_data,
/*make_local */ nullptr,
/*foreach_id */ curves_foreach_id,
/*foreach_cache */ nullptr,
/*foreach_path */ nullptr,
/*owner_get */ nullptr,
/*blend_write */ curves_blend_write,
/*blend_read_data */ curves_blend_read_data,
/*blend_read_lib */ curves_blend_read_lib,
/*blend_read_expand */ curves_blend_read_expand,
/*blend_read_undo_preserve */ nullptr,
/*lib_override_apply_post */ nullptr,
};
static void curves_random(Curves *curves)
{
CurvesGeometry &geometry = curves->geometry;
const int numpoints = 8;
geometry.curve_size = 500;
geometry.curve_size = 500;
geometry.point_size = geometry.curve_size * numpoints;
curves->geometry.offsets = (int *)MEM_calloc_arrayN(
curves->geometry.curve_size + 1, sizeof(int), __func__);
CustomData_realloc(&geometry.point_data, geometry.point_size);
CustomData_realloc(&geometry.curve_data, geometry.curve_size);
BKE_curves_update_customdata_pointers(curves);
MutableSpan<int> offsets{geometry.offsets, geometry.curve_size + 1};
MutableSpan<float3> positions{(float3 *)geometry.position, geometry.point_size};
MutableSpan<float> radii{geometry.radius, geometry.point_size};
for (const int i : offsets.index_range()) {
geometry.offsets[i] = numpoints * i;
}
RandomNumberGenerator rng;
for (int i = 0; i < geometry.curve_size; i++) {
const IndexRange curve_range(offsets[i], offsets[i + 1] - offsets[i]);
MutableSpan<float3> curve_positions = positions.slice(curve_range);
MutableSpan<float> curve_radii = radii.slice(curve_range);
const float theta = 2.0f * M_PI * rng.get_float();
const float phi = saacosf(2.0f * rng.get_float() - 1.0f);
float3 no = {std::sin(theta) * std::sin(phi), std::cos(theta) * std::sin(phi), std::cos(phi)};
no = blender::math::normalize(no);
float3 co = no;
for (int key = 0; key < numpoints; key++) {
float t = key / (float)(numpoints - 1);
curve_positions[key] = co;
curve_radii[key] = 0.02f * (1.0f - t);
float3 offset = float3(rng.get_float(), rng.get_float(), rng.get_float()) * 2.0f - 1.0f;
co += (offset + no) / numpoints;
}
}
}
void *BKE_curves_add(Main *bmain, const char *name)
{
Curves *curves = static_cast<Curves *>(BKE_id_new(bmain, ID_CV, name));
return curves;
}
BoundBox *BKE_curves_boundbox_get(Object *ob)
{
BLI_assert(ob->type == OB_CURVES);
Curves *curves = static_cast<Curves *>(ob->data);
if (ob->runtime.bb != nullptr && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) {
return ob->runtime.bb;
}
if (ob->runtime.bb == nullptr) {
ob->runtime.bb = MEM_cnew<BoundBox>(__func__);
float min[3], max[3];
INIT_MINMAX(min, max);
float(*curves_co)[3] = curves->geometry.position;
float *curves_radius = curves->geometry.radius;
for (int a = 0; a < curves->geometry.point_size; a++) {
float *co = curves_co[a];
float radius = (curves_radius) ? curves_radius[a] : 0.0f;
const float co_min[3] = {co[0] - radius, co[1] - radius, co[2] - radius};
const float co_max[3] = {co[0] + radius, co[1] + radius, co[2] + radius};
DO_MIN(co_min, min);
DO_MAX(co_max, max);
}
BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
}
return ob->runtime.bb;
}
void BKE_curves_update_customdata_pointers(Curves *curves)
{
curves->geometry.position = (float(*)[3])CustomData_get_layer_named(
&curves->geometry.point_data, CD_PROP_FLOAT3, ATTR_POSITION);
curves->geometry.radius = (float *)CustomData_get_layer_named(
&curves->geometry.point_data, CD_PROP_FLOAT, ATTR_RADIUS);
}
bool BKE_curves_customdata_required(Curves *UNUSED(curves), CustomDataLayer *layer)
{
return layer->type == CD_PROP_FLOAT3 && STREQ(layer->name, ATTR_POSITION);
}
/* Dependency Graph */
Curves *BKE_curves_new_for_eval(const Curves *curves_src, int totpoint, int totcurve)
{
Curves *curves_dst = static_cast<Curves *>(BKE_id_new_nomain(ID_CV, nullptr));
STRNCPY(curves_dst->id.name, curves_src->id.name);
curves_dst->mat = static_cast<Material **>(MEM_dupallocN(curves_src->mat));
curves_dst->totcol = curves_src->totcol;
curves_dst->geometry.point_size = totpoint;
curves_dst->geometry.curve_size = totcurve;
CustomData_copy(&curves_src->geometry.point_data,
&curves_dst->geometry.point_data,
CD_MASK_ALL,
CD_CALLOC,
totpoint);
CustomData_copy(&curves_src->geometry.curve_data,
&curves_dst->geometry.curve_data,
CD_MASK_ALL,
CD_CALLOC,
totcurve);
BKE_curves_update_customdata_pointers(curves_dst);
return curves_dst;
}
Curves *BKE_curves_copy_for_eval(Curves *curves_src, bool reference)
{
int flags = LIB_ID_COPY_LOCALIZE;
if (reference) {
flags |= LIB_ID_COPY_CD_REFERENCE;
}
Curves *result = (Curves *)BKE_id_copy_ex(nullptr, &curves_src->id, nullptr, flags);
return result;
}
static Curves *curves_evaluate_modifiers(struct Depsgraph *depsgraph,
struct Scene *scene,
Object *object,
Curves *curves_input)
{
Curves *curves = curves_input;
/* Modifier evaluation modes. */
const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE;
const ModifierEvalContext mectx = {depsgraph, object, apply_flag};
/* Get effective list of modifiers to execute. Some effects like shape keys
* are added as virtual modifiers before the user created modifiers. */
VirtualModifierData virtualModifierData;
ModifierData *md = BKE_modifiers_get_virtual_modifierlist(object, &virtualModifierData);
/* Evaluate modifiers. */
for (; md; md = md->next) {
const ModifierTypeInfo *mti = BKE_modifier_get_info(static_cast<ModifierType>(md->type));
if (!BKE_modifier_is_enabled(scene, md, required_mode)) {
continue;
}
if ((mti->type == eModifierTypeType_OnlyDeform) &&
(mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly)) {
/* Ensure we are not modifying the input. */
if (curves == curves_input) {
curves = BKE_curves_copy_for_eval(curves, true);
}
/* Ensure we are not overwriting referenced data. */
CustomData_duplicate_referenced_layer_named(&curves->geometry.point_data,
CD_PROP_FLOAT3,
ATTR_POSITION,
curves->geometry.point_size);
BKE_curves_update_customdata_pointers(curves);
/* Created deformed coordinates array on demand. */
mti->deformVerts(
md, &mectx, nullptr, curves->geometry.position, curves->geometry.point_size);
}
}
return curves;
}
void BKE_curves_data_update(struct Depsgraph *depsgraph, struct Scene *scene, Object *object)
{
/* Free any evaluated data and restore original data. */
BKE_object_free_derived_caches(object);
/* Evaluate modifiers. */
Curves *curves = static_cast<Curves *>(object->data);
Curves *curves_eval = curves_evaluate_modifiers(depsgraph, scene, object, curves);
/* Assign evaluated object. */
const bool is_owned = (curves != curves_eval);
BKE_object_eval_assign_data(object, &curves_eval->id, is_owned);
}
/* Draw Cache */
void (*BKE_curves_batch_cache_dirty_tag_cb)(Curves *curves, int mode) = nullptr;
void (*BKE_curves_batch_cache_free_cb)(Curves *curves) = nullptr;
void BKE_curves_batch_cache_dirty_tag(Curves *curves, int mode)
{
if (curves->batch_cache) {
BKE_curves_batch_cache_dirty_tag_cb(curves, mode);
}
}
void BKE_curves_batch_cache_free(Curves *curves)
{
if (curves->batch_cache) {
BKE_curves_batch_cache_free_cb(curves);
}
}

@ -31,7 +31,6 @@
#include "DNA_ID.h"
#include "DNA_customdata_types.h"
#include "DNA_hair_types.h"
#include "DNA_meshdata_types.h"
#include "BLI_bitmap.h"

@ -1,474 +0,0 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/** \file
* \ingroup bke
*/
#include <cmath>
#include <cstring>
#include "MEM_guardedalloc.h"
#include "DNA_defaults.h"
#include "DNA_hair_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "BLI_index_range.hh"
#include "BLI_listbase.h"
#include "BLI_math_base.h"
#include "BLI_math_vec_types.hh"
#include "BLI_rand.hh"
#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "BKE_anim_data.h"
#include "BKE_customdata.h"
#include "BKE_global.h"
#include "BKE_hair.h"
#include "BKE_idtype.h"
#include "BKE_lib_id.h"
#include "BKE_lib_query.h"
#include "BKE_lib_remap.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BLT_translation.h"
#include "DEG_depsgraph_query.h"
#include "BLO_read_write.h"
using blender::float3;
using blender::IndexRange;
using blender::MutableSpan;
using blender::RandomNumberGenerator;
static const char *HAIR_ATTR_POSITION = "position";
static const char *HAIR_ATTR_RADIUS = "radius";
/* Hair datablock */
static void hair_random(Hair *hair);
static void hair_init_data(ID *id)
{
Hair *hair = (Hair *)id;
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(hair, id));
MEMCPY_STRUCT_AFTER(hair, DNA_struct_default_get(Hair), id);
CustomData_reset(&hair->geometry.point_data);
CustomData_reset(&hair->geometry.curve_data);
CustomData_add_layer_named(&hair->geometry.point_data,
CD_PROP_FLOAT3,
CD_CALLOC,
nullptr,
hair->geometry.point_size,
HAIR_ATTR_POSITION);
CustomData_add_layer_named(&hair->geometry.point_data,
CD_PROP_FLOAT,
CD_CALLOC,
nullptr,
hair->geometry.point_size,
HAIR_ATTR_RADIUS);
BKE_hair_update_customdata_pointers(hair);
hair_random(hair);
}
static void hair_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
{
Hair *hair_dst = (Hair *)id_dst;
const Hair *hair_src = (const Hair *)id_src;
hair_dst->mat = static_cast<Material **>(MEM_dupallocN(hair_src->mat));
hair_dst->geometry.point_size = hair_src->geometry.point_size;
hair_dst->geometry.curve_size = hair_src->geometry.curve_size;
const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
CustomData_copy(&hair_src->geometry.point_data,
&hair_dst->geometry.point_data,
CD_MASK_ALL,
alloc_type,
hair_dst->geometry.point_size);
CustomData_copy(&hair_src->geometry.curve_data,
&hair_dst->geometry.curve_data,
CD_MASK_ALL,
alloc_type,
hair_dst->geometry.curve_size);
BKE_hair_update_customdata_pointers(hair_dst);
hair_dst->geometry.offsets = static_cast<int *>(MEM_dupallocN(hair_src->geometry.offsets));
hair_dst->batch_cache = nullptr;
}
static void hair_free_data(ID *id)
{
Hair *hair = (Hair *)id;
BKE_animdata_free(&hair->id, false);
BKE_hair_batch_cache_free(hair);
CustomData_free(&hair->geometry.point_data, hair->geometry.point_size);
CustomData_free(&hair->geometry.curve_data, hair->geometry.curve_size);
MEM_SAFE_FREE(hair->geometry.offsets);
MEM_SAFE_FREE(hair->mat);
}
static void hair_foreach_id(ID *id, LibraryForeachIDData *data)
{
Hair *hair = (Hair *)id;
for (int i = 0; i < hair->totcol; i++) {
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, hair->mat[i], IDWALK_CB_USER);
}
}
static void hair_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
Hair *hair = (Hair *)id;
CustomDataLayer *players = nullptr, players_buff[CD_TEMP_CHUNK_SIZE];
CustomDataLayer *clayers = nullptr, clayers_buff[CD_TEMP_CHUNK_SIZE];
CustomData_blend_write_prepare(
&hair->geometry.point_data, &players, players_buff, ARRAY_SIZE(players_buff));
CustomData_blend_write_prepare(
&hair->geometry.curve_data, &clayers, clayers_buff, ARRAY_SIZE(clayers_buff));
/* Write LibData */
BLO_write_id_struct(writer, Hair, id_address, &hair->id);
BKE_id_blend_write(writer, &hair->id);
/* Direct data */
CustomData_blend_write(writer,
&hair->geometry.point_data,
players,
hair->geometry.point_size,
CD_MASK_ALL,
&hair->id);
CustomData_blend_write(writer,
&hair->geometry.curve_data,
clayers,
hair->geometry.curve_size,
CD_MASK_ALL,
&hair->id);
BLO_write_int32_array(writer, hair->geometry.curve_size + 1, hair->geometry.offsets);
BLO_write_pointer_array(writer, hair->totcol, hair->mat);
if (hair->adt) {
BKE_animdata_blend_write(writer, hair->adt);
}
/* Remove temporary data. */
if (players && players != players_buff) {
MEM_freeN(players);
}
if (clayers && clayers != clayers_buff) {
MEM_freeN(clayers);
}
}
static void hair_blend_read_data(BlendDataReader *reader, ID *id)
{
Hair *hair = (Hair *)id;
BLO_read_data_address(reader, &hair->adt);
BKE_animdata_blend_read_data(reader, hair->adt);
/* Geometry */
CustomData_blend_read(reader, &hair->geometry.point_data, hair->geometry.point_size);
CustomData_blend_read(reader, &hair->geometry.curve_data, hair->geometry.point_size);
BKE_hair_update_customdata_pointers(hair);
BLO_read_int32_array(reader, hair->geometry.curve_size + 1, &hair->geometry.offsets);
/* Materials */
BLO_read_pointer_array(reader, (void **)&hair->mat);
}
static void hair_blend_read_lib(BlendLibReader *reader, ID *id)
{
Hair *hair = (Hair *)id;
for (int a = 0; a < hair->totcol; a++) {
BLO_read_id_address(reader, hair->id.lib, &hair->mat[a]);
}
}
static void hair_blend_read_expand(BlendExpander *expander, ID *id)
{
Hair *hair = (Hair *)id;
for (int a = 0; a < hair->totcol; a++) {
BLO_expand(expander, hair->mat[a]);
}
}
IDTypeInfo IDType_ID_HA = {
/*id_code */ ID_HA,
/*id_filter */ FILTER_ID_HA,
/*main_listbase_index */ INDEX_ID_HA,
/*struct_size */ sizeof(Hair),
/*name */ "Hair",
/*name_plural */ "hairs",
/*translation_context */ BLT_I18NCONTEXT_ID_HAIR,
/*flags */ IDTYPE_FLAGS_APPEND_IS_REUSABLE,
/*asset_type_info */ nullptr,
/*init_data */ hair_init_data,
/*copy_data */ hair_copy_data,
/*free_data */ hair_free_data,
/*make_local */ nullptr,
/*foreach_id */ hair_foreach_id,
/*foreach_cache */ nullptr,
/*foreach_path */ nullptr,
/*owner_get */ nullptr,
/*blend_write */ hair_blend_write,
/*blend_read_data */ hair_blend_read_data,
/*blend_read_lib */ hair_blend_read_lib,
/*blend_read_expand */ hair_blend_read_expand,
/*blend_read_undo_preserve */ nullptr,
/*lib_override_apply_post */ nullptr,
};
static void hair_random(Hair *hair)
{
CurvesGeometry &geometry = hair->geometry;
const int numpoints = 8;
geometry.curve_size = 500;
geometry.curve_size = 500;
geometry.point_size = geometry.curve_size * numpoints;
hair->geometry.offsets = (int *)MEM_calloc_arrayN(
hair->geometry.curve_size + 1, sizeof(int), __func__);
CustomData_realloc(&geometry.point_data, geometry.point_size);
CustomData_realloc(&geometry.curve_data, geometry.curve_size);
BKE_hair_update_customdata_pointers(hair);
MutableSpan<int> offsets{geometry.offsets, geometry.curve_size + 1};
MutableSpan<float3> positions{(float3 *)geometry.position, geometry.point_size};
MutableSpan<float> radii{geometry.radius, geometry.point_size};
for (const int i : offsets.index_range()) {
geometry.offsets[i] = numpoints * i;
}
RandomNumberGenerator rng;
for (int i = 0; i < geometry.curve_size; i++) {
const IndexRange curve_range(offsets[i], offsets[i + 1] - offsets[i]);
MutableSpan<float3> curve_positions = positions.slice(curve_range);
MutableSpan<float> curve_radii = radii.slice(curve_range);
const float theta = 2.0f * M_PI * rng.get_float();
const float phi = saacosf(2.0f * rng.get_float() - 1.0f);
float3 no = {std::sin(theta) * std::sin(phi), std::cos(theta) * std::sin(phi), std::cos(phi)};
no = blender::math::normalize(no);
float3 co = no;
for (int key = 0; key < numpoints; key++) {
float t = key / (float)(numpoints - 1);
curve_positions[key] = co;
curve_radii[key] = 0.02f * (1.0f - t);
float3 offset = float3(rng.get_float(), rng.get_float(), rng.get_float()) * 2.0f - 1.0f;
co += (offset + no) / numpoints;
}
}
}
void *BKE_hair_add(Main *bmain, const char *name)
{
Hair *hair = static_cast<Hair *>(BKE_id_new(bmain, ID_HA, name));
return hair;
}
BoundBox *BKE_hair_boundbox_get(Object *ob)
{
BLI_assert(ob->type == OB_HAIR);
Hair *hair = static_cast<Hair *>(ob->data);
if (ob->runtime.bb != nullptr && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) {
return ob->runtime.bb;
}
if (ob->runtime.bb == nullptr) {
ob->runtime.bb = MEM_cnew<BoundBox>(__func__);
float min[3], max[3];
INIT_MINMAX(min, max);
float(*hair_co)[3] = hair->geometry.position;
float *hair_radius = hair->geometry.radius;
for (int a = 0; a < hair->geometry.point_size; a++) {
float *co = hair_co[a];
float radius = (hair_radius) ? hair_radius[a] : 0.0f;
const float co_min[3] = {co[0] - radius, co[1] - radius, co[2] - radius};
const float co_max[3] = {co[0] + radius, co[1] + radius, co[2] + radius};
DO_MIN(co_min, min);
DO_MAX(co_max, max);
}
BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
}
return ob->runtime.bb;
}
void BKE_hair_update_customdata_pointers(Hair *hair)
{
hair->geometry.position = (float(*)[3])CustomData_get_layer_named(
&hair->geometry.point_data, CD_PROP_FLOAT3, HAIR_ATTR_POSITION);
hair->geometry.radius = (float *)CustomData_get_layer_named(
&hair->geometry.point_data, CD_PROP_FLOAT, HAIR_ATTR_RADIUS);
}
bool BKE_hair_customdata_required(Hair *UNUSED(hair), CustomDataLayer *layer)
{
return layer->type == CD_PROP_FLOAT3 && STREQ(layer->name, HAIR_ATTR_POSITION);
}
/* Dependency Graph */
Hair *BKE_hair_new_for_eval(const Hair *hair_src, int totpoint, int totcurve)
{
Hair *hair_dst = static_cast<Hair *>(BKE_id_new_nomain(ID_HA, nullptr));
STRNCPY(hair_dst->id.name, hair_src->id.name);
hair_dst->mat = static_cast<Material **>(MEM_dupallocN(hair_src->mat));
hair_dst->totcol = hair_src->totcol;
hair_dst->geometry.point_size = totpoint;
hair_dst->geometry.curve_size = totcurve;
CustomData_copy(&hair_src->geometry.point_data,
&hair_dst->geometry.point_data,
CD_MASK_ALL,
CD_CALLOC,
totpoint);
CustomData_copy(&hair_src->geometry.curve_data,
&hair_dst->geometry.curve_data,
CD_MASK_ALL,
CD_CALLOC,
totcurve);
BKE_hair_update_customdata_pointers(hair_dst);
return hair_dst;
}
Hair *BKE_hair_copy_for_eval(Hair *hair_src, bool reference)
{
int flags = LIB_ID_COPY_LOCALIZE;
if (reference) {
flags |= LIB_ID_COPY_CD_REFERENCE;
}
Hair *result = (Hair *)BKE_id_copy_ex(nullptr, &hair_src->id, nullptr, flags);
return result;
}
static Hair *hair_evaluate_modifiers(struct Depsgraph *depsgraph,
struct Scene *scene,
Object *object,
Hair *hair_input)
{
Hair *hair = hair_input;
/* Modifier evaluation modes. */
const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE;
const ModifierEvalContext mectx = {depsgraph, object, apply_flag};
/* Get effective list of modifiers to execute. Some effects like shape keys
* are added as virtual modifiers before the user created modifiers. */
VirtualModifierData virtualModifierData;
ModifierData *md = BKE_modifiers_get_virtual_modifierlist(object, &virtualModifierData);
/* Evaluate modifiers. */
for (; md; md = md->next) {
const ModifierTypeInfo *mti = BKE_modifier_get_info(static_cast<ModifierType>(md->type));
if (!BKE_modifier_is_enabled(scene, md, required_mode)) {
continue;
}
if ((mti->type == eModifierTypeType_OnlyDeform) &&
(mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly)) {
/* Ensure we are not modifying the input. */
if (hair == hair_input) {
hair = BKE_hair_copy_for_eval(hair, true);
}
/* Ensure we are not overwriting referenced data. */
CustomData_duplicate_referenced_layer_named(&hair->geometry.point_data,
CD_PROP_FLOAT3,
HAIR_ATTR_POSITION,
hair->geometry.point_size);
BKE_hair_update_customdata_pointers(hair);
/* Created deformed coordinates array on demand. */
mti->deformVerts(md, &mectx, nullptr, hair->geometry.position, hair->geometry.point_size);
}
}
return hair;
}
void BKE_hair_data_update(struct Depsgraph *depsgraph, struct Scene *scene, Object *object)
{
/* Free any evaluated data and restore original data. */
BKE_object_free_derived_caches(object);
/* Evaluate modifiers. */
Hair *hair = static_cast<Hair *>(object->data);
Hair *hair_eval = hair_evaluate_modifiers(depsgraph, scene, object, hair);
/* Assign evaluated object. */
const bool is_owned = (hair != hair_eval);
BKE_object_eval_assign_data(object, &hair_eval->id, is_owned);
}
/* Draw Cache */
void (*BKE_hair_batch_cache_dirty_tag_cb)(Hair *hair, int mode) = nullptr;
void (*BKE_hair_batch_cache_free_cb)(Hair *hair) = nullptr;
void BKE_hair_batch_cache_dirty_tag(Hair *hair, int mode)
{
if (hair->batch_cache) {
BKE_hair_batch_cache_dirty_tag_cb(hair, mode);
}
}
void BKE_hair_batch_cache_free(Hair *hair)
{
if (hair->batch_cache) {
BKE_hair_batch_cache_free_cb(hair);
}
}

@ -110,7 +110,7 @@ static void id_type_init(void)
INIT_TYPE(ID_CF);
INIT_TYPE(ID_WS);
INIT_TYPE(ID_LP);
INIT_TYPE(ID_HA);
INIT_TYPE(ID_CV);
INIT_TYPE(ID_PT);
INIT_TYPE(ID_VO);
INIT_TYPE(ID_SIM);
@ -237,7 +237,7 @@ uint64_t BKE_idtype_idcode_to_idfilter(const short idcode)
CASE_IDFILTER(CU);
CASE_IDFILTER(GD);
CASE_IDFILTER(GR);
CASE_IDFILTER(HA);
CASE_IDFILTER(CV);
CASE_IDFILTER(IM);
CASE_IDFILTER(LA);
CASE_IDFILTER(LS);
@ -286,7 +286,7 @@ short BKE_idtype_idcode_from_idfilter(const uint64_t idfilter)
CASE_IDFILTER(CU);
CASE_IDFILTER(GD);
CASE_IDFILTER(GR);
CASE_IDFILTER(HA);
CASE_IDFILTER(CV);
CASE_IDFILTER(IM);
CASE_IDFILTER(LA);
CASE_IDFILTER(LS);
@ -334,7 +334,7 @@ int BKE_idtype_idcode_to_index(const short idcode)
CASE_IDINDEX(CU);
CASE_IDINDEX(GD);
CASE_IDINDEX(GR);
CASE_IDINDEX(HA);
CASE_IDINDEX(CV);
CASE_IDINDEX(IM);
CASE_IDINDEX(IP);
CASE_IDINDEX(KE);
@ -393,7 +393,7 @@ short BKE_idtype_idcode_from_index(const int index)
CASE_IDCODE(CU);
CASE_IDCODE(GD);
CASE_IDCODE(GR);
CASE_IDCODE(HA);
CASE_IDCODE(CV);
CASE_IDCODE(IM);
CASE_IDCODE(IP);
CASE_IDCODE(KE);

@ -471,7 +471,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
return ELEM(id_type_used, ID_MA);
case ID_WS:
return ELEM(id_type_used, ID_SCR, ID_SCE);
case ID_HA:
case ID_CV:
return ELEM(id_type_used, ID_MA);
case ID_PT:
return ELEM(id_type_used, ID_MA);

@ -558,7 +558,7 @@ static void libblock_remap_foreach_idpair_cb(ID *old_id, ID *new_id, void *user_
case ID_ME:
case ID_CU:
case ID_MB:
case ID_HA:
case ID_CV:
case ID_PT:
case ID_VO:
if (new_id) { /* Only affects us in case obdata was relinked (changed). */

@ -643,8 +643,8 @@ ListBase *which_libbase(Main *bmain, short type)
return &(bmain->cachefiles);
case ID_WS:
return &(bmain->workspaces);
case ID_HA:
return &(bmain->hairs);
case ID_CV:
return &(bmain->hair_curves);
case ID_PT:
return &(bmain->pointclouds);
case ID_VO:
@ -688,7 +688,7 @@ int set_listbasepointers(Main *bmain, ListBase *lb[/*INDEX_ID_MAX*/])
lb[INDEX_ID_ME] = &(bmain->meshes);
lb[INDEX_ID_CU] = &(bmain->curves);
lb[INDEX_ID_MB] = &(bmain->metaballs);
lb[INDEX_ID_HA] = &(bmain->hairs);
lb[INDEX_ID_CV] = &(bmain->hair_curves);
lb[INDEX_ID_PT] = &(bmain->pointclouds);
lb[INDEX_ID_VO] = &(bmain->volumes);

@ -36,10 +36,10 @@
#include "DNA_anim_types.h"
#include "DNA_collection_types.h"
#include "DNA_curve_types.h"
#include "DNA_curves_types.h"
#include "DNA_customdata_types.h"
#include "DNA_defaults.h"
#include "DNA_gpencil_types.h"
#include "DNA_hair_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@ -341,9 +341,9 @@ Material ***BKE_object_material_array_p(Object *ob)
bGPdata *gpd = ob->data;
return &(gpd->mat);
}
if (ob->type == OB_HAIR) {
Hair *hair = ob->data;
return &(hair->mat);
if (ob->type == OB_CURVES) {
Curves *curves = ob->data;
return &(curves->mat);
}
if (ob->type == OB_POINTCLOUD) {
PointCloud *pointcloud = ob->data;
@ -374,9 +374,9 @@ short *BKE_object_material_len_p(Object *ob)
bGPdata *gpd = ob->data;
return &(gpd->totcol);
}
if (ob->type == OB_HAIR) {
Hair *hair = ob->data;
return &(hair->totcol);
if (ob->type == OB_CURVES) {
Curves *curves = ob->data;
return &(curves->totcol);
}
if (ob->type == OB_POINTCLOUD) {
PointCloud *pointcloud = ob->data;
@ -403,8 +403,8 @@ Material ***BKE_id_material_array_p(ID *id)
return &(((MetaBall *)id)->mat);
case ID_GD:
return &(((bGPdata *)id)->mat);
case ID_HA:
return &(((Hair *)id)->mat);
case ID_CV:
return &(((Curves *)id)->mat);
case ID_PT:
return &(((PointCloud *)id)->mat);
case ID_VO:
@ -429,8 +429,8 @@ short *BKE_id_material_len_p(ID *id)
return &(((MetaBall *)id)->totcol);
case ID_GD:
return &(((bGPdata *)id)->totcol);
case ID_HA:
return &(((Hair *)id)->totcol);
case ID_CV:
return &(((Curves *)id)->totcol);
case ID_PT:
return &(((PointCloud *)id)->totcol);
case ID_VO:
@ -454,7 +454,7 @@ static void material_data_index_remove_id(ID *id, short index)
BKE_curve_material_index_remove((Curve *)id, index);
break;
case ID_MB:
case ID_HA:
case ID_CV:
case ID_PT:
case ID_VO:
/* No material indices for these object data types. */
@ -509,7 +509,7 @@ static void material_data_index_clear_id(ID *id)
BKE_curve_material_index_clear((Curve *)id);
break;
case ID_MB:
case ID_HA:
case ID_CV:
case ID_PT:
case ID_VO:
/* No material indices for these object data types. */

@ -89,6 +89,7 @@
#include "BKE_constraint.h"
#include "BKE_crazyspace.h"
#include "BKE_curve.h"
#include "BKE_curves.h"
#include "BKE_deform.h"
#include "BKE_displist.h"
#include "BKE_duplilist.h"
@ -103,7 +104,6 @@
#include "BKE_gpencil.h"
#include "BKE_gpencil_geom.h"
#include "BKE_gpencil_modifier.h"
#include "BKE_hair.h"
#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_idtype.h"
@ -1415,7 +1415,7 @@ bool BKE_object_support_modifier_type_check(const Object *ob, int modifier_type)
}
/* Only geometry objects should be able to get modifiers T25291. */
if (ELEM(ob->type, OB_POINTCLOUD, OB_VOLUME, OB_HAIR)) {
if (ELEM(ob->type, OB_POINTCLOUD, OB_VOLUME, OB_CURVES)) {
return (mti->modifyGeometrySet != nullptr);
}
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
@ -2098,8 +2098,8 @@ static const char *get_obdata_defname(int type)
return DATA_("Armature");
case OB_SPEAKER:
return DATA_("Speaker");
case OB_HAIR:
return DATA_("Hair");
case OB_CURVES:
return DATA_("HairCurves");
case OB_POINTCLOUD:
return DATA_("PointCloud");
case OB_VOLUME:
@ -2173,8 +2173,8 @@ void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
return BKE_lightprobe_add(bmain, name);
case OB_GPENCIL:
return BKE_gpencil_data_addnew(bmain, name);
case OB_HAIR:
return BKE_hair_add(bmain, name);
case OB_CURVES:
return BKE_curves_add(bmain, name);
case OB_POINTCLOUD:
return BKE_pointcloud_add_default(bmain, name);
case OB_VOLUME:
@ -2211,8 +2211,8 @@ int BKE_object_obdata_to_type(const ID *id)
return OB_ARMATURE;
case ID_LP:
return OB_LIGHTPROBE;
case ID_HA:
return OB_HAIR;
case ID_CV:
return OB_CURVES;
case ID_PT:
return OB_POINTCLOUD;
case ID_VO:
@ -2729,8 +2729,8 @@ Object *BKE_object_duplicate(Main *bmain, Object *ob, uint dupflag, uint duplica
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
}
break;
case OB_HAIR:
if (dupflag & USER_DUP_HAIR) {
case OB_CURVES:
if (dupflag & USER_DUP_CURVES) {
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
}
break;
@ -3624,8 +3624,8 @@ BoundBox *BKE_object_boundbox_get(Object *ob)
case OB_GPENCIL:
bb = BKE_gpencil_boundbox_get(ob);
break;
case OB_HAIR:
bb = BKE_hair_boundbox_get(ob);
case OB_CURVES:
bb = BKE_curves_boundbox_get(ob);
break;
case OB_POINTCLOUD:
bb = BKE_pointcloud_boundbox_get(ob);
@ -3826,8 +3826,8 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us
}
break;
}
case OB_HAIR: {
BoundBox bb = *BKE_hair_boundbox_get(ob);
case OB_CURVES: {
BoundBox bb = *BKE_curves_boundbox_get(ob);
BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
changed = true;
break;
@ -4941,7 +4941,7 @@ bool BKE_object_supports_material_slots(struct Object *ob)
OB_SURF,
OB_FONT,
OB_MBALL,
OB_HAIR,
OB_CURVES,
OB_POINTCLOUD,
OB_VOLUME,
OB_GPENCIL);

@ -41,12 +41,12 @@
#include "BKE_armature.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
#include "BKE_curves.h"
#include "BKE_displist.h"
#include "BKE_editmesh.h"
#include "BKE_effect.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
#include "BKE_hair.h"
#include "BKE_image.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
@ -214,8 +214,8 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
BKE_gpencil_update_layer_transforms(depsgraph, ob);
break;
}
case OB_HAIR:
BKE_hair_data_update(depsgraph, scene, ob);
case OB_CURVES:
BKE_curves_data_update(depsgraph, scene, ob);
break;
case OB_POINTCLOUD:
BKE_pointcloud_data_update(depsgraph, scene, ob);
@ -326,8 +326,8 @@ void BKE_object_data_batch_cache_dirty_tag(ID *object_data)
case ID_GD:
BKE_gpencil_batch_cache_dirty_tag((struct bGPdata *)object_data);
break;
case ID_HA:
BKE_hair_batch_cache_dirty_tag((struct Hair *)object_data, BKE_HAIR_BATCH_DIRTY_ALL);
case ID_CV:
BKE_curves_batch_cache_dirty_tag((struct Curves *)object_data, BKE_CURVES_BATCH_DIRTY_ALL);
break;
case ID_PT:
BKE_pointcloud_batch_cache_dirty_tag((struct PointCloud *)object_data,

@ -2988,7 +2988,7 @@ static const char *dataname(short id_code)
return "Data from CF";
case ID_WS:
return "Data from WS";
case ID_HA:
case ID_CV:
return "Data from HA";
case ID_PT:
return "Data from PT";

@ -32,11 +32,11 @@
#include "DNA_cachefile_types.h"
#include "DNA_collection_types.h"
#include "DNA_constraint_types.h"
#include "DNA_curves_types.h"
#include "DNA_fluid_types.h"
#include "DNA_genfile.h"
#include "DNA_gpencil_modifier_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_hair_types.h"
#include "DNA_light_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@ -1120,10 +1120,7 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
/* Hair and PointCloud attributes. */
for (Hair *hair = bmain->hairs.first; hair != NULL; hair = hair->id.next) {
do_versions_point_attributes(&hair->geometry.point_data);
}
/* PointCloud attributes. */
for (PointCloud *pointcloud = bmain->pointclouds.first; pointcloud != NULL;
pointcloud = pointcloud->id.next) {
do_versions_point_attributes(&pointcloud->pdata);
@ -1422,10 +1419,7 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
/* Hair and PointCloud attributes names. */
LISTBASE_FOREACH (Hair *, hair, &bmain->hairs) {
do_versions_point_attribute_names(&hair->geometry.point_data);
}
/* PointCloud attributes names. */
LISTBASE_FOREACH (PointCloud *, pointcloud, &bmain->pointclouds) {
do_versions_point_attribute_names(&pointcloud->pdata);
}

@ -111,7 +111,7 @@ bool BLT_lang_is_ime_supported(void);
#define BLT_I18NCONTEXT_ID_CURVE "Curve"
#define BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE "FreestyleLineStyle"
#define BLT_I18NCONTEXT_ID_GPENCIL "GPencil"
#define BLT_I18NCONTEXT_ID_HAIR "Hair"
#define BLT_I18NCONTEXT_ID_CURVES "Curves"
#define BLT_I18NCONTEXT_ID_ID "ID"
#define BLT_I18NCONTEXT_ID_IMAGE "Image"
// #define BLT_I18NCONTEXT_ID_IPO "Ipo" /* DEPRECATED */
@ -173,7 +173,7 @@ typedef struct {
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_CURVE, "id_curve"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE, "id_fs_linestyle"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_GPENCIL, "id_gpencil"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_HAIR, "id_hair"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_CURVES, "id_curves"), \
BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_ID, "id_id"), \
BLT_I18NCONTEXTS_ITEM( \
BLT_I18NCONTEXT_ID_IMAGE, \

@ -599,7 +599,7 @@ void DepsgraphNodeBuilder::build_id(ID *id)
case ID_CU:
case ID_LT:
case ID_GD:
case ID_HA:
case ID_CV:
case ID_PT:
case ID_VO:
build_object_data_geometry_datablock(id);
@ -894,7 +894,7 @@ void DepsgraphNodeBuilder::build_object_data(Object *object)
case OB_MBALL:
case OB_LATTICE:
case OB_GPENCIL:
case OB_HAIR:
case OB_CURVES:
case OB_POINTCLOUD:
case OB_VOLUME:
build_object_data_geometry(object);
@ -1563,7 +1563,7 @@ void DepsgraphNodeBuilder::build_object_data_geometry_datablock(ID *obdata)
op_node->set_as_entry();
break;
}
case ID_HA: {
case ID_CV: {
op_node = add_operation_node(obdata, NodeType::GEOMETRY, OperationCode::GEOMETRY_EVAL);
op_node->set_as_entry();
break;

@ -555,7 +555,7 @@ void DepsgraphRelationBuilder::build_id(ID *id)
case ID_MB:
case ID_CU:
case ID_LT:
case ID_HA:
case ID_CV:
case ID_PT:
case ID_VO:
case ID_GD:
@ -849,7 +849,7 @@ void DepsgraphRelationBuilder::build_object_data(Object *object)
case OB_MBALL:
case OB_LATTICE:
case OB_GPENCIL:
case OB_HAIR:
case OB_CURVES:
case OB_POINTCLOUD:
case OB_VOLUME: {
build_object_data_geometry(object);
@ -2301,7 +2301,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry_datablock(ID *obdata)
}
break;
}
case ID_HA:
case ID_CV:
break;
case ID_PT:
break;
@ -2925,7 +2925,7 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node)
continue;
}
int rel_flag = (RELATION_FLAG_NO_FLUSH | RELATION_FLAG_GODMODE);
if ((ELEM(id_type, ID_ME, ID_HA, ID_PT, ID_VO) && comp_node->type == NodeType::GEOMETRY) ||
if ((ELEM(id_type, ID_ME, ID_CV, ID_PT, ID_VO) && comp_node->type == NodeType::GEOMETRY) ||
(id_type == ID_CF && comp_node->type == NodeType::CACHE)) {
rel_flag &= ~RELATION_FLAG_NO_FLUSH;
}

@ -87,7 +87,7 @@ void depsgraph_geometry_tag_to_component(const ID *id, NodeType *component_type)
bool is_selectable_data_id_type(const ID_Type id_type)
{
return ELEM(id_type, ID_ME, ID_CU, ID_MB, ID_LT, ID_GD, ID_HA, ID_PT, ID_VO);
return ELEM(id_type, ID_ME, ID_CU, ID_MB, ID_LT, ID_GD, ID_CV, ID_PT, ID_VO);
}
void depsgraph_select_tag_to_component_opcode(const ID *id,
@ -591,7 +591,7 @@ NodeType geometry_tag_to_component(const ID *id)
case OB_LATTICE:
case OB_MBALL:
case OB_GPENCIL:
case OB_HAIR:
case OB_CURVES:
case OB_POINTCLOUD:
case OB_VOLUME:
return NodeType::GEOMETRY;
@ -605,7 +605,7 @@ NodeType geometry_tag_to_component(const ID *id)
case ID_CU:
case ID_LT:
case ID_MB:
case ID_HA:
case ID_CV:
case ID_PT:
case ID_VO:
case ID_GR:

@ -127,7 +127,7 @@ void ObjectRuntimeBackup::restore_to_object(Object *object)
}
}
}
else if (ELEM(object->type, OB_HAIR, OB_POINTCLOUD, OB_VOLUME)) {
else if (ELEM(object->type, OB_CURVES, OB_POINTCLOUD, OB_VOLUME)) {
if (object->id.recalc & ID_RECALC_GEOMETRY) {
/* Free evaluated caches. */
object->data = data_orig;

@ -86,9 +86,9 @@ set(SRC
intern/mesh_extractors/extract_mesh_vbo_vcol.cc
intern/mesh_extractors/extract_mesh_vbo_weights.cc
intern/draw_cache_impl_curve.cc
intern/draw_cache_impl_curves.cc
intern/draw_cache_impl_displist.c
intern/draw_cache_impl_gpencil.c
intern/draw_cache_impl_hair.cc
intern/draw_cache_impl_lattice.c
intern/draw_cache_impl_mesh.c
intern/draw_cache_impl_metaball.c

@ -56,7 +56,7 @@
#include "BLI_math_bits.h"
#include "BLI_rect.h"
#include "DNA_hair_types.h"
#include "DNA_curves_types.h"
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_particle_types.h"
@ -248,25 +248,25 @@ static DRWShadingGroup *eevee_cryptomatte_shading_group_create(EEVEE_Data *vedat
return grp;
}
static void eevee_cryptomatte_hair_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob,
ParticleSystem *psys,
ModifierData *md,
Material *material)
static void eevee_cryptomatte_curves_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob,
ParticleSystem *psys,
ModifierData *md,
Material *material)
{
DRWShadingGroup *grp = eevee_cryptomatte_shading_group_create(
vedata, sldata, ob, material, true);
DRW_shgroup_hair_create_sub(ob, psys, md, grp, NULL);
}
void EEVEE_cryptomatte_object_hair_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob)
void EEVEE_cryptomatte_object_curves_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob)
{
BLI_assert(ob->type == OB_HAIR);
Material *material = BKE_object_material_get_eval(ob, HAIR_MATERIAL_NR);
eevee_cryptomatte_hair_cache_populate(vedata, sldata, ob, NULL, NULL, material);
BLI_assert(ob->type == OB_CURVES);
Material *material = BKE_object_material_get_eval(ob, CURVES_MATERIAL_NR);
eevee_cryptomatte_curves_cache_populate(vedata, sldata, ob, NULL, NULL, material);
}
void EEVEE_cryptomatte_particle_hair_cache_populate(EEVEE_Data *vedata,
@ -291,7 +291,7 @@ void EEVEE_cryptomatte_particle_hair_cache_populate(EEVEE_Data *vedata,
continue;
}
Material *material = BKE_object_material_get_eval(ob, part->omat);
eevee_cryptomatte_hair_cache_populate(vedata, sldata, ob, psys, md, material);
eevee_cryptomatte_curves_cache_populate(vedata, sldata, ob, psys, md, material);
}
}
}

@ -177,7 +177,7 @@ static void *motion_blur_deform_data_get(EEVEE_MotionBlurData *mb, Object *ob, b
if (hair) {
EEVEE_HairMotionData *hair_step;
/* Ugly, we allocate for each modifiers and just fill based on modifier index in the list. */
int psys_len = (ob->type != OB_HAIR) ? BLI_listbase_count(&ob->modifiers) : 1;
int psys_len = (ob->type != OB_CURVES) ? BLI_listbase_count(&ob->modifiers) : 1;
hair_step = MEM_callocN(sizeof(EEVEE_HairMotionData) + sizeof(hair_step->psys[0]) * psys_len,
__func__);
hair_step->psys_len = psys_len;

@ -125,7 +125,7 @@ void EEVEE_cache_populate(void *vedata, Object *ob)
if (ELEM(ob->type, OB_MESH, OB_SURF, OB_MBALL)) {
EEVEE_materials_cache_populate(vedata, sldata, ob, &cast_shadow);
}
else if (ob->type == OB_HAIR) {
else if (ob->type == OB_CURVES) {
EEVEE_object_hair_cache_populate(vedata, sldata, ob, &cast_shadow);
}
else if (ob->type == OB_VOLUME) {

@ -33,7 +33,7 @@
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "DNA_hair_types.h"
#include "DNA_curves_types.h"
#include "DNA_modifier_types.h"
#include "DNA_view3d_types.h"
#include "DNA_world_types.h"
@ -925,7 +925,7 @@ void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata,
Object *ob,
bool *cast_shadow)
{
eevee_hair_cache_populate(vedata, sldata, ob, NULL, NULL, HAIR_MATERIAL_NR, cast_shadow);
eevee_hair_cache_populate(vedata, sldata, ob, NULL, NULL, CURVES_MATERIAL_NR, cast_shadow);
}
void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)

@ -1385,9 +1385,9 @@ void EEVEE_cryptomatte_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *s
void EEVEE_cryptomatte_particle_hair_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob);
void EEVEE_cryptomatte_object_hair_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob);
void EEVEE_cryptomatte_object_curves_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob);
void EEVEE_cryptomatte_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
/**
* Register the render passes needed for cryptomatte

@ -244,10 +244,10 @@ void EEVEE_render_cache(void *vedata,
EEVEE_cryptomatte_cache_populate(data, sldata, ob);
}
}
else if (ob->type == OB_HAIR) {
else if (ob->type == OB_CURVES) {
EEVEE_object_hair_cache_populate(vedata, sldata, ob, &cast_shadow);
if (do_cryptomatte) {
EEVEE_cryptomatte_object_hair_cache_populate(data, sldata, ob);
EEVEE_cryptomatte_object_curves_cache_populate(data, sldata, ob);
}
}
else if (ob->type == OB_VOLUME) {

@ -262,7 +262,7 @@ static bool overlay_object_is_edit_mode(const OVERLAY_PrivateData *pd, const Obj
return pd->ctx_mode == CTX_MODE_EDIT_METABALL;
case OB_FONT:
return pd->ctx_mode == CTX_MODE_EDIT_TEXT;
case OB_HAIR:
case OB_CURVES:
case OB_POINTCLOUD:
case OB_VOLUME:
/* No edit mode yet. */
@ -316,7 +316,7 @@ static void OVERLAY_cache_populate(void *vedata, Object *ob)
OB_MBALL,
OB_FONT,
OB_GPENCIL,
OB_HAIR,
OB_CURVES,
OB_POINTCLOUD,
OB_VOLUME);
const bool draw_surface = (ob->dt >= OB_WIRE) && (renderable || (ob->dt == OB_WIRE));

@ -484,7 +484,7 @@ static void OVERLAY_texture_space(OVERLAY_ExtraCallBuffers *cb, Object *ob, cons
texcosize = mb->size;
break;
}
case ID_HA:
case ID_CV:
case ID_PT:
case ID_VO: {
/* No user defined texture space support. */

@ -34,8 +34,8 @@
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "DNA_curves_types.h"
#include "DNA_fluid_types.h"
#include "DNA_hair_types.h"
#include "DNA_image_types.h"
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
@ -419,9 +419,9 @@ void workbench_cache_populate(void *ved, Object *ob)
workbench_shadow_cache_populate(vedata, ob, has_transp_mat);
}
}
else if (ob->type == OB_HAIR) {
else if (ob->type == OB_CURVES) {
int color_type = workbench_color_type_get(wpd, ob, NULL, NULL, NULL);
workbench_cache_hair_populate(wpd, ob, NULL, NULL, color_type, false, HAIR_MATERIAL_NR);
workbench_cache_hair_populate(wpd, ob, NULL, NULL, color_type, false, CURVES_MATERIAL_NR);
}
else if (ob->type == OB_VOLUME) {
if (wpd->shading.type != OB_WIRE) {

@ -19,7 +19,7 @@
*/
#include "DNA_curve_types.h"
#include "DNA_hair_types.h"
#include "DNA_curves_types.h"
#include "DNA_lattice_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
@ -835,7 +835,7 @@ GPUBatch *DRW_cache_object_edge_detection_get(Object *ob, bool *r_is_manifold)
return NULL;
case OB_MBALL:
return DRW_cache_mball_edge_detection_get(ob, r_is_manifold);
case OB_HAIR:
case OB_CURVES:
return NULL;
case OB_POINTCLOUD:
return NULL;
@ -859,7 +859,7 @@ GPUBatch *DRW_cache_object_face_wireframe_get(Object *ob)
return NULL;
case OB_MBALL:
return DRW_cache_mball_face_wireframe_get(ob);
case OB_HAIR:
case OB_CURVES:
return NULL;
case OB_POINTCLOUD:
return DRW_pointcloud_batch_cache_get_dots(ob);
@ -886,7 +886,7 @@ GPUBatch *DRW_cache_object_loose_edges_get(struct Object *ob)
return NULL;
case OB_MBALL:
return NULL;
case OB_HAIR:
case OB_CURVES:
return NULL;
case OB_POINTCLOUD:
return NULL;
@ -910,7 +910,7 @@ GPUBatch *DRW_cache_object_surface_get(Object *ob)
return NULL;
case OB_MBALL:
return DRW_cache_mball_surface_get(ob);
case OB_HAIR:
case OB_CURVES:
return NULL;
case OB_POINTCLOUD:
return DRW_cache_pointcloud_surface_get(ob);
@ -935,7 +935,7 @@ GPUVertBuf *DRW_cache_object_pos_vertbuf_get(Object *ob)
return DRW_curve_batch_cache_pos_vertbuf_get(ob->data);
case OB_MBALL:
return DRW_mball_batch_cache_pos_vertbuf_get(ob);
case OB_HAIR:
case OB_CURVES:
return NULL;
case OB_POINTCLOUD:
return NULL;
@ -967,8 +967,8 @@ int DRW_cache_object_material_count_get(struct Object *ob)
return DRW_curve_material_count_get(ob->data);
case OB_MBALL:
return DRW_metaball_material_count_get(ob->data);
case OB_HAIR:
return DRW_hair_material_count_get(ob->data);
case OB_CURVES:
return DRW_curves_material_count_get(ob->data);
case OB_POINTCLOUD:
return DRW_pointcloud_material_count_get(ob->data);
case OB_VOLUME:
@ -994,7 +994,7 @@ GPUBatch **DRW_cache_object_surface_material_get(struct Object *ob,
return NULL;
case OB_MBALL:
return DRW_cache_mball_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
case OB_HAIR:
case OB_CURVES:
return NULL;
case OB_POINTCLOUD:
return DRW_cache_pointcloud_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
@ -3403,8 +3403,8 @@ void drw_batch_cache_validate(Object *ob)
case OB_LATTICE:
DRW_lattice_batch_cache_validate((Lattice *)ob->data);
break;
case OB_HAIR:
DRW_hair_batch_cache_validate((Hair *)ob->data);
case OB_CURVES:
DRW_curves_batch_cache_validate((Curves *)ob->data);
break;
case OB_POINTCLOUD:
DRW_pointcloud_batch_cache_validate((PointCloud *)ob->data);

@ -246,14 +246,14 @@ struct GPUBatch **DRW_cache_mball_surface_shaded_get(struct Object *ob,
struct GPUBatch *DRW_cache_mball_face_wireframe_get(struct Object *ob);
struct GPUBatch *DRW_cache_mball_edge_detection_get(struct Object *ob, bool *r_is_manifold);
/* Hair */
/* Curves */
struct GPUBatch *DRW_cache_hair_surface_get(struct Object *ob);
struct GPUBatch **DRW_cache_hair_surface_shaded_get(struct Object *ob,
struct GPUMaterial **gpumat_array,
uint gpumat_array_len);
struct GPUBatch *DRW_cache_hair_face_wireframe_get(struct Object *ob);
struct GPUBatch *DRW_cache_hair_edge_detection_get(struct Object *ob, bool *r_is_manifold);
struct GPUBatch *DRW_cache_curves_surface_get(struct Object *ob);
struct GPUBatch **DRW_cache_curves_surface_shaded_get(struct Object *ob,
struct GPUMaterial **gpumat_array,
uint gpumat_array_len);
struct GPUBatch *DRW_cache_curves_face_wireframe_get(struct Object *ob);
struct GPUBatch *DRW_cache_curves_edge_detection_get(struct Object *ob, bool *r_is_manifold);
/* PointCloud */

@ -33,7 +33,7 @@ struct ParticleSystem;
struct TaskGraph;
struct Curve;
struct Hair;
struct Curves;
struct Lattice;
struct Mesh;
struct MetaBall;
@ -73,9 +73,9 @@ void DRW_particle_batch_cache_free(struct ParticleSystem *psys);
void DRW_gpencil_batch_cache_dirty_tag(struct bGPdata *gpd);
void DRW_gpencil_batch_cache_free(struct bGPdata *gpd);
void DRW_hair_batch_cache_dirty_tag(struct Hair *hair, int mode);
void DRW_hair_batch_cache_validate(struct Hair *hair);
void DRW_hair_batch_cache_free(struct Hair *hair);
void DRW_curves_batch_cache_dirty_tag(struct Curves *curves, int mode);
void DRW_curves_batch_cache_validate(struct Curves *curves);
void DRW_curves_batch_cache_free(struct Curves *curves);
void DRW_pointcloud_batch_cache_dirty_tag(struct PointCloud *pointcloud, int mode);
void DRW_pointcloud_batch_cache_validate(struct PointCloud *pointcloud);
@ -188,7 +188,7 @@ struct GPUBatch *DRW_lattice_batch_cache_get_edit_verts(struct Lattice *lt);
/** \name Hair
* \{ */
int DRW_hair_material_count_get(struct Hair *hair);
int DRW_curves_material_count_get(struct Curves *curves);
/** \} */

@ -35,10 +35,10 @@
#include "BLI_span.hh"
#include "BLI_utildefines.h"
#include "DNA_hair_types.h"
#include "DNA_curves_types.h"
#include "DNA_object_types.h"
#include "BKE_hair.h"
#include "BKE_curves.h"
#include "GPU_batch.h"
#include "GPU_material.h"
@ -51,7 +51,7 @@ using blender::float3;
using blender::IndexRange;
using blender::Span;
static void hair_batch_cache_clear(Hair *hair);
static void curves_batch_cache_clear(Curves *curves);
/* ---------------------------------------------------------------------- */
/* Hair GPUBatch Cache */
@ -65,19 +65,19 @@ struct HairBatchCache {
/* GPUBatch cache management. */
static bool hair_batch_cache_valid(Hair *hair)
static bool curves_batch_cache_valid(Curves *curves)
{
HairBatchCache *cache = static_cast<HairBatchCache *>(hair->batch_cache);
HairBatchCache *cache = static_cast<HairBatchCache *>(curves->batch_cache);
return (cache && cache->is_dirty == false);
}
static void hair_batch_cache_init(Hair *hair)
static void curves_batch_cache_init(Curves *curves)
{
HairBatchCache *cache = static_cast<HairBatchCache *>(hair->batch_cache);
HairBatchCache *cache = static_cast<HairBatchCache *>(curves->batch_cache);
if (!cache) {
cache = MEM_cnew<HairBatchCache>(__func__);
hair->batch_cache = cache;
curves->batch_cache = cache;
}
else {
memset(cache, 0, sizeof(*cache));
@ -86,28 +86,28 @@ static void hair_batch_cache_init(Hair *hair)
cache->is_dirty = false;
}
void DRW_hair_batch_cache_validate(Hair *hair)
void DRW_curves_batch_cache_validate(Curves *curves)
{
if (!hair_batch_cache_valid(hair)) {
hair_batch_cache_clear(hair);
hair_batch_cache_init(hair);
if (!curves_batch_cache_valid(curves)) {
curves_batch_cache_clear(curves);
curves_batch_cache_init(curves);
}
}
static HairBatchCache *hair_batch_cache_get(Hair *hair)
static HairBatchCache *curves_batch_cache_get(Curves *curves)
{
DRW_hair_batch_cache_validate(hair);
return static_cast<HairBatchCache *>(hair->batch_cache);
DRW_curves_batch_cache_validate(curves);
return static_cast<HairBatchCache *>(curves->batch_cache);
}
void DRW_hair_batch_cache_dirty_tag(Hair *hair, int mode)
void DRW_curves_batch_cache_dirty_tag(Curves *curves, int mode)
{
HairBatchCache *cache = static_cast<HairBatchCache *>(hair->batch_cache);
HairBatchCache *cache = static_cast<HairBatchCache *>(curves->batch_cache);
if (cache == nullptr) {
return;
}
switch (mode) {
case BKE_HAIR_BATCH_DIRTY_ALL:
case BKE_CURVES_BATCH_DIRTY_ALL:
cache->is_dirty = true;
break;
default:
@ -115,9 +115,9 @@ void DRW_hair_batch_cache_dirty_tag(Hair *hair, int mode)
}
}
static void hair_batch_cache_clear(Hair *hair)
static void curves_batch_cache_clear(Curves *curves)
{
HairBatchCache *cache = static_cast<HairBatchCache *>(hair->batch_cache);
HairBatchCache *cache = static_cast<HairBatchCache *>(curves->batch_cache);
if (!cache) {
return;
}
@ -125,33 +125,33 @@ static void hair_batch_cache_clear(Hair *hair)
particle_batch_cache_clear_hair(&cache->hair);
}
void DRW_hair_batch_cache_free(Hair *hair)
void DRW_curves_batch_cache_free(Curves *curves)
{
hair_batch_cache_clear(hair);
MEM_SAFE_FREE(hair->batch_cache);
curves_batch_cache_clear(curves);
MEM_SAFE_FREE(curves->batch_cache);
}
static void ensure_seg_pt_count(Hair *hair, ParticleHairCache *hair_cache)
static void ensure_seg_pt_count(Curves *curves, ParticleHairCache *curves_cache)
{
if ((hair_cache->pos != nullptr && hair_cache->indices != nullptr) ||
(hair_cache->proc_point_buf != nullptr)) {
if ((curves_cache->pos != nullptr && curves_cache->indices != nullptr) ||
(curves_cache->proc_point_buf != nullptr)) {
return;
}
hair_cache->strands_len = hair->geometry.curve_size;
hair_cache->elems_len = hair->geometry.point_size + hair->geometry.curve_size;
hair_cache->point_len = hair->geometry.point_size;
curves_cache->strands_len = curves->geometry.curve_size;
curves_cache->elems_len = curves->geometry.point_size + curves->geometry.curve_size;
curves_cache->point_len = curves->geometry.point_size;
}
static void hair_batch_cache_fill_segments_proc_pos(Hair *hair,
GPUVertBufRaw *attr_step,
GPUVertBufRaw *length_step)
static void curves_batch_cache_fill_segments_proc_pos(Curves *curves,
GPUVertBufRaw *attr_step,
GPUVertBufRaw *length_step)
{
/* TODO: use hair radius layer if available. */
const int curve_size = hair->geometry.curve_size;
Span<int> offsets{hair->geometry.offsets, hair->geometry.curve_size + 1};
const int curve_size = curves->geometry.curve_size;
Span<int> offsets{curves->geometry.offsets, curves->geometry.curve_size + 1};
Span<float3> positions{(float3 *)hair->geometry.position, hair->geometry.point_size};
Span<float3> positions{(float3 *)curves->geometry.position, curves->geometry.point_size};
for (const int i : IndexRange(curve_size)) {
const IndexRange curve_range(offsets[i], offsets[i + 1] - offsets[i]);
@ -183,9 +183,9 @@ static void hair_batch_cache_fill_segments_proc_pos(Hair *hair,
}
}
static void hair_batch_cache_ensure_procedural_pos(Hair *hair,
ParticleHairCache *cache,
GPUMaterial *gpu_material)
static void curves_batch_cache_ensure_procedural_pos(Curves *curves,
ParticleHairCache *cache,
GPUMaterial *gpu_material)
{
if (cache->proc_point_buf == nullptr) {
/* initialize vertex format */
@ -208,7 +208,7 @@ static void hair_batch_cache_ensure_procedural_pos(Hair *hair,
GPUVertBufRaw length_step;
GPU_vertbuf_attr_get_raw_data(cache->proc_length_buf, length_id, &length_step);
hair_batch_cache_fill_segments_proc_pos(hair, &point_step, &length_step);
curves_batch_cache_fill_segments_proc_pos(curves, &point_step, &length_step);
/* Create vbo immediately to bind to texture buffer. */
GPU_vertbuf_use(cache->proc_point_buf);
@ -227,12 +227,12 @@ static void hair_batch_cache_ensure_procedural_pos(Hair *hair,
}
}
static void hair_batch_cache_fill_strands_data(Hair *hair,
GPUVertBufRaw *data_step,
GPUVertBufRaw *seg_step)
static void curves_batch_cache_fill_strands_data(Curves *curves,
GPUVertBufRaw *data_step,
GPUVertBufRaw *seg_step)
{
const int curve_size = hair->geometry.curve_size;
Span<int> offsets{hair->geometry.offsets, hair->geometry.curve_size + 1};
const int curve_size = curves->geometry.curve_size;
Span<int> offsets{curves->geometry.offsets, curves->geometry.curve_size + 1};
for (const int i : IndexRange(curve_size)) {
const IndexRange curve_range(offsets[i], offsets[i + 1] - offsets[i]);
@ -242,7 +242,8 @@ static void hair_batch_cache_fill_strands_data(Hair *hair,
}
}
static void hair_batch_cache_ensure_procedural_strand_data(Hair *hair, ParticleHairCache *cache)
static void curves_batch_cache_ensure_procedural_strand_data(Curves *curves,
ParticleHairCache *cache)
{
GPUVertBufRaw data_step, seg_step;
@ -261,18 +262,18 @@ static void hair_batch_cache_ensure_procedural_strand_data(Hair *hair, ParticleH
GPU_vertbuf_data_alloc(cache->proc_strand_seg_buf, cache->strands_len);
GPU_vertbuf_attr_get_raw_data(cache->proc_strand_seg_buf, seg_id, &seg_step);
hair_batch_cache_fill_strands_data(hair, &data_step, &seg_step);
curves_batch_cache_fill_strands_data(curves, &data_step, &seg_step);
/* Create vbo immediately to bind to texture buffer. */
GPU_vertbuf_use(cache->proc_strand_buf);
cache->strand_tex = GPU_texture_create_from_vertbuf("hair_strand", cache->proc_strand_buf);
cache->strand_tex = GPU_texture_create_from_vertbuf("curves_strand", cache->proc_strand_buf);
GPU_vertbuf_use(cache->proc_strand_seg_buf);
cache->strand_seg_tex = GPU_texture_create_from_vertbuf("hair_strand_seg",
cache->strand_seg_tex = GPU_texture_create_from_vertbuf("curves_strand_seg",
cache->proc_strand_seg_buf);
}
static void hair_batch_cache_ensure_procedural_final_points(ParticleHairCache *cache, int subdiv)
static void curves_batch_cache_ensure_procedural_final_points(ParticleHairCache *cache, int subdiv)
{
/* Same format as point_tex. */
GPUVertFormat format = {0};
@ -293,11 +294,11 @@ static void hair_batch_cache_ensure_procedural_final_points(ParticleHairCache *c
cache->final[subdiv].proc_buf);
}
static void hair_batch_cache_fill_segments_indices(Hair *hair,
const int res,
GPUIndexBufBuilder *elb)
static void curves_batch_cache_fill_segments_indices(Curves *curves,
const int res,
GPUIndexBufBuilder *elb)
{
const int curve_size = hair->geometry.curve_size;
const int curve_size = curves->geometry.curve_size;
uint curr_point = 0;
@ -309,10 +310,10 @@ static void hair_batch_cache_fill_segments_indices(Hair *hair,
}
}
static void hair_batch_cache_ensure_procedural_indices(Hair *hair,
ParticleHairCache *cache,
int thickness_res,
int subdiv)
static void curves_batch_cache_ensure_procedural_indices(Curves *curves,
ParticleHairCache *cache,
int thickness_res,
int subdiv)
{
BLI_assert(thickness_res <= MAX_THICKRES); /* Cylinder strip not currently supported. */
@ -337,7 +338,7 @@ static void hair_batch_cache_ensure_procedural_indices(Hair *hair,
GPUIndexBufBuilder elb;
GPU_indexbuf_init_ex(&elb, prim_type, element_count, element_count);
hair_batch_cache_fill_segments_indices(hair, verts_per_hair, &elb);
curves_batch_cache_fill_segments_indices(curves, verts_per_hair, &elb);
cache->final[subdiv].proc_hairs[thickness_res - 1] = GPU_batch_create_ex(
prim_type, vbo, GPU_indexbuf_build(&elb), GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX);
@ -350,9 +351,9 @@ bool hair_ensure_procedural_data(Object *object,
int thickness_res)
{
bool need_ft_update = false;
Hair *hair = static_cast<Hair *>(object->data);
Curves *curves = static_cast<Curves *>(object->data);
HairBatchCache *cache = hair_batch_cache_get(hair);
HairBatchCache *cache = curves_batch_cache_get(curves);
*r_hair_cache = &cache->hair;
const int steps = 2; /* TODO: don't hard-code? */
@ -360,29 +361,29 @@ bool hair_ensure_procedural_data(Object *object,
/* Refreshed on combing and simulation. */
if ((*r_hair_cache)->proc_point_buf == nullptr) {
ensure_seg_pt_count(hair, &cache->hair);
hair_batch_cache_ensure_procedural_pos(hair, &cache->hair, gpu_material);
ensure_seg_pt_count(curves, &cache->hair);
curves_batch_cache_ensure_procedural_pos(curves, &cache->hair, gpu_material);
need_ft_update = true;
}
/* Refreshed if active layer or custom data changes. */
if ((*r_hair_cache)->strand_tex == nullptr) {
hair_batch_cache_ensure_procedural_strand_data(hair, &cache->hair);
curves_batch_cache_ensure_procedural_strand_data(curves, &cache->hair);
}
/* Refreshed only on subdiv count change. */
if ((*r_hair_cache)->final[subdiv].proc_buf == nullptr) {
hair_batch_cache_ensure_procedural_final_points(&cache->hair, subdiv);
curves_batch_cache_ensure_procedural_final_points(&cache->hair, subdiv);
need_ft_update = true;
}
if ((*r_hair_cache)->final[subdiv].proc_hairs[thickness_res - 1] == nullptr) {
hair_batch_cache_ensure_procedural_indices(hair, &cache->hair, thickness_res, subdiv);
curves_batch_cache_ensure_procedural_indices(curves, &cache->hair, thickness_res, subdiv);
}
return need_ft_update;
}
int DRW_hair_material_count_get(Hair *hair)
int DRW_curves_material_count_get(Curves *curves)
{
return max_ii(1, hair->totcol);
return max_ii(1, curves->totcol);
}

@ -431,7 +431,7 @@ bool DRW_object_is_flat(Object *ob, int *r_axis)
OB_SURF,
OB_FONT,
OB_MBALL,
OB_HAIR,
OB_CURVES,
OB_POINTCLOUD,
OB_VOLUME)) {
/* Non-meshes object cannot be considered as flat. */

@ -35,11 +35,11 @@
#include "BKE_colortools.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_curves.h"
#include "BKE_duplilist.h"
#include "BKE_editmesh.h"
#include "BKE_global.h"
#include "BKE_gpencil.h"
#include "BKE_hair.h"
#include "BKE_lattice.h"
#include "BKE_main.h"
#include "BKE_mball.h"
@ -2948,8 +2948,8 @@ void DRW_engines_register(void)
BKE_gpencil_batch_cache_dirty_tag_cb = DRW_gpencil_batch_cache_dirty_tag;
BKE_gpencil_batch_cache_free_cb = DRW_gpencil_batch_cache_free;
BKE_hair_batch_cache_dirty_tag_cb = DRW_hair_batch_cache_dirty_tag;
BKE_hair_batch_cache_free_cb = DRW_hair_batch_cache_free;
BKE_curves_batch_cache_dirty_tag_cb = DRW_curves_batch_cache_dirty_tag;
BKE_curves_batch_cache_free_cb = DRW_curves_batch_cache_free;
BKE_pointcloud_batch_cache_dirty_tag_cb = DRW_pointcloud_batch_cache_dirty_tag;
BKE_pointcloud_batch_cache_free_cb = DRW_pointcloud_batch_cache_free;

@ -35,8 +35,8 @@
#include "DNA_armature_types.h"
#include "DNA_cachefile_types.h"
#include "DNA_camera_types.h"
#include "DNA_curves_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_hair_types.h"
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
#include "DNA_light_types.h"
@ -700,8 +700,8 @@ static int acf_object_icon(bAnimListElem *ale)
return ICON_OUTLINER_OB_FONT;
case OB_SURF:
return ICON_OUTLINER_OB_SURFACE;
case OB_HAIR:
return ICON_OUTLINER_OB_HAIR;
case OB_CURVES:
return ICON_OUTLINER_OB_CURVES;
case OB_POINTCLOUD:
return ICON_OUTLINER_OB_POINTCLOUD;
case OB_VOLUME:
@ -2813,15 +2813,15 @@ static bAnimChannelType ACF_DSSPK = {
/* Hair Expander ------------------------------------------- */
/* TODO: just get this from RNA? */
static int acf_dshair_icon(bAnimListElem *UNUSED(ale))
static int acf_dscurves_icon(bAnimListElem *UNUSED(ale))
{
return ICON_HAIR_DATA;
return ICON_CURVES_DATA;
}
/* Get the appropriate flag(s) for the setting when it is valid. */
static int acf_dshair_setting_flag(bAnimContext *UNUSED(ac),
eAnimChannel_Settings setting,
bool *neg)
static int acf_dscurves_setting_flag(bAnimContext *UNUSED(ac),
eAnimChannel_Settings setting,
bool *neg)
{
/* clear extra return data first */
*neg = false;
@ -2846,22 +2846,24 @@ static int acf_dshair_setting_flag(bAnimContext *UNUSED(ac),
}
/* get pointer to the setting */
static void *acf_dshair_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings setting, short *type)
static void *acf_dscurves_setting_ptr(bAnimListElem *ale,
eAnimChannel_Settings setting,
short *type)
{
Hair *hair = (Hair *)ale->data;
Curves *curves = (Curves *)ale->data;
/* clear extra return data first */
*type = 0;
switch (setting) {
case ACHANNEL_SETTING_EXPAND: /* expanded */
return GET_ACF_FLAG_PTR(hair->flag, type);
return GET_ACF_FLAG_PTR(curves->flag, type);
case ACHANNEL_SETTING_SELECT: /* selected */
case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */
case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */
if (hair->adt) {
return GET_ACF_FLAG_PTR(hair->adt->flag, type);
if (curves->adt) {
return GET_ACF_FLAG_PTR(curves->adt->flag, type);
}
return NULL;
@ -2870,9 +2872,9 @@ static void *acf_dshair_setting_ptr(bAnimListElem *ale, eAnimChannel_Settings se
}
}
/* hair expander type define */
/* Curves expander type define */
static bAnimChannelType ACF_DSHAIR = {
"Hair Expander", /* type name */
"Curves Expander", /* type name */
ACHANNEL_ROLE_EXPANDER, /* role */
acf_generic_dataexpand_color, /* backdrop color */
@ -2882,11 +2884,11 @@ static bAnimChannelType ACF_DSHAIR = {
acf_generic_idblock_name, /* name */
acf_generic_idblock_name_prop, /* name prop */
acf_dshair_icon, /* icon */
acf_dscurves_icon, /* icon */
acf_generic_dataexpand_setting_valid, /* has setting */
acf_dshair_setting_flag, /* flag for setting */
acf_dshair_setting_ptr /* pointer for setting */
acf_dscurves_setting_flag, /* flag for setting */
acf_dscurves_setting_ptr /* pointer for setting */
};
/* PointCloud Expander ------------------------------------------- */

@ -47,8 +47,8 @@
#include "DNA_brush_types.h"
#include "DNA_cachefile_types.h"
#include "DNA_camera_types.h"
#include "DNA_curves_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_hair_types.h"
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
#include "DNA_layer_types.h"
@ -791,10 +791,10 @@ static bAnimListElem *make_new_animlistelem(void *data,
break;
}
case ANIMTYPE_DSHAIR: {
Hair *hair = (Hair *)data;
AnimData *adt = hair->adt;
Curves *curves = (Curves *)data;
AnimData *adt = curves->adt;
ale->flag = FILTER_HAIR_OBJD(hair);
ale->flag = FILTER_CURVES_OBJD(curves);
ale->key_data = (adt) ? adt->action : NULL;
ale->datatype = ALE_ACT;
@ -2616,16 +2616,16 @@ static size_t animdata_filter_ds_obdata(
expanded = FILTER_SPK_OBJD(spk);
break;
}
case OB_HAIR: /* ---------- Hair ----------- */
case OB_CURVES: /* ---------- Curves ----------- */
{
Hair *hair = (Hair *)ob->data;
Curves *curves = (Curves *)ob->data;
if (ads->filterflag2 & ADS_FILTER_NOHAIR) {
return 0;
}
type = ANIMTYPE_DSHAIR;
expanded = FILTER_HAIR_OBJD(hair);
expanded = FILTER_CURVES_OBJD(curves);
break;
}
case OB_POINTCLOUD: /* ---------- PointCloud ----------- */

@ -378,7 +378,7 @@ typedef enum eAnimFilter_Flags {
#define FILTER_MESH_OBJD(me) (CHECK_TYPE_INLINE(me, Mesh *), ((me->flag & ME_DS_EXPAND)))
#define FILTER_LATTICE_OBJD(lt) (CHECK_TYPE_INLINE(lt, Lattice *), ((lt->flag & LT_DS_EXPAND)))
#define FILTER_SPK_OBJD(spk) (CHECK_TYPE_INLINE(spk, Speaker *), ((spk->flag & SPK_DS_EXPAND)))
#define FILTER_HAIR_OBJD(ha) (CHECK_TYPE_INLINE(ha, Hair *), ((ha->flag & HA_DS_EXPAND)))
#define FILTER_CURVES_OBJD(ha) (CHECK_TYPE_INLINE(ha, Curves *), ((ha->flag & HA_DS_EXPAND)))
#define FILTER_POINTS_OBJD(pt) (CHECK_TYPE_INLINE(pt, PointCloud *), ((pt->flag & PT_DS_EXPAND)))
#define FILTER_VOLUME_OBJD(vo) (CHECK_TYPE_INLINE(vo, Volume *), ((vo->flag & VO_DS_EXPAND)))
#define FILTER_SIMULATION_OBJD(sim) \

@ -752,9 +752,9 @@ DEF_ICON_BLANK(257)
DEF_ICON_BLANK(257b)
/* ADDITIONAL OBJECT TYPES */
DEF_ICON_OBJECT(OUTLINER_OB_HAIR)
DEF_ICON_OBJECT_DATA(OUTLINER_DATA_HAIR)
DEF_ICON_OBJECT_DATA(HAIR_DATA)
DEF_ICON_OBJECT(OUTLINER_OB_CURVES)
DEF_ICON_OBJECT_DATA(OUTLINER_DATA_CURVES)
DEF_ICON_OBJECT_DATA(CURVES_DATA)
DEF_ICON_OBJECT(OUTLINER_OB_POINTCLOUD)
DEF_ICON_OBJECT_DATA(OUTLINER_DATA_POINTCLOUD)
DEF_ICON_OBJECT_DATA(POINTCLOUD_DATA)
@ -840,7 +840,7 @@ DEF_ICON(MATPLANE)
DEF_ICON(MATSPHERE)
DEF_ICON(MATCUBE)
DEF_ICON(MONKEY)
DEF_ICON(HAIR)
DEF_ICON(CURVES)
DEF_ICON(ALIASED)
DEF_ICON(ANTIALIASED)
DEF_ICON(MAT_SPHERE_SKY)

@ -2335,8 +2335,8 @@ int UI_icon_from_idcode(const int idcode)
return ICON_TEXT;
case ID_VF:
return ICON_FONT_DATA;
case ID_HA:
return ICON_HAIR_DATA;
case ID_CV:
return ICON_CURVES_DATA;
case ID_PT:
return ICON_POINTCLOUD_DATA;
case ID_VO:

@ -792,8 +792,8 @@ static const char *template_id_browse_tip(const StructRNA *type)
return N_("Browse Workspace to be linked");
case ID_LP:
return N_("Browse LightProbe to be linked");
case ID_HA:
return N_("Browse Hair Data to be linked");
case ID_CV:
return N_("Browse Hair Curves Data to be linked");
case ID_PT:
return N_("Browse Point Cloud Data to be linked");
case ID_VO:
@ -874,7 +874,7 @@ static uiBut *template_id_def_new_but(uiBlock *block,
BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE,
BLT_I18NCONTEXT_ID_WORKSPACE,
BLT_I18NCONTEXT_ID_LIGHTPROBE,
BLT_I18NCONTEXT_ID_HAIR,
BLT_I18NCONTEXT_ID_CURVES,
BLT_I18NCONTEXT_ID_POINTCLOUD,
BLT_I18NCONTEXT_ID_VOLUME,
BLT_I18NCONTEXT_ID_SIMULATION, );

@ -88,7 +88,7 @@ endif()
if(WITH_EXPERIMENTAL_FEATURES)
add_definitions(-DWITH_SIMULATION_DATABLOCK)
add_definitions(-DWITH_POINT_CLOUD)
add_definitions(-DWITH_HAIR_NODES)
add_definitions(-DWITH_NEW_CURVES_TYPE)
endif()
blender_add_lib(bf_editor_object "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

@ -62,6 +62,7 @@
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_curves.h"
#include "BKE_displist.h"
#include "BKE_duplilist.h"
#include "BKE_effect.h"
@ -69,7 +70,6 @@
#include "BKE_gpencil_curve.h"
#include "BKE_gpencil_geom.h"
#include "BKE_gpencil_modifier.h"
#include "BKE_hair.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_layer.h"
@ -1894,18 +1894,18 @@ void OBJECT_OT_speaker_add(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Add Hair Operator
/** \name Add Hair Curves Operator
* \{ */
static bool object_hair_add_poll(bContext *C)
static bool object_hair_curves_add_poll(bContext *C)
{
if (!U.experimental.use_new_hair_type) {
if (!U.experimental.use_new_curves_type) {
return false;
}
return ED_operator_objectmode(C);
}
static int object_hair_add_exec(bContext *C, wmOperator *op)
static int object_hair_curves_add_exec(bContext *C, wmOperator *op)
{
ushort local_view_bits;
float loc[3], rot[3];
@ -1913,22 +1913,22 @@ static int object_hair_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
Object *object = ED_object_add_type(C, OB_HAIR, NULL, loc, rot, false, local_view_bits);
Object *object = ED_object_add_type(C, OB_CURVES, NULL, loc, rot, false, local_view_bits);
object->dtx |= OB_DRAWBOUNDOX; /* TODO: remove once there is actual drawing. */
return OPERATOR_FINISHED;
}
void OBJECT_OT_hair_add(wmOperatorType *ot)
void OBJECT_OT_hair_curves_add(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add Hair";
ot->description = "Add a hair object to the scene";
ot->idname = "OBJECT_OT_hair_add";
ot->name = "Add Hair Curves";
ot->description = "Add a hair curves object to the scene";
ot->idname = "OBJECT_OT_hair_curves_add";
/* api callbacks */
ot->exec = object_hair_add_exec;
ot->poll = object_hair_add_poll;
ot->exec = object_hair_curves_add_exec;
ot->poll = object_hair_curves_add_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;

@ -129,7 +129,7 @@ void OBJECT_OT_light_add(struct wmOperatorType *ot);
void OBJECT_OT_effector_add(struct wmOperatorType *ot);
void OBJECT_OT_camera_add(struct wmOperatorType *ot);
void OBJECT_OT_speaker_add(struct wmOperatorType *ot);
void OBJECT_OT_hair_add(struct wmOperatorType *ot);
void OBJECT_OT_hair_curves_add(struct wmOperatorType *ot);
void OBJECT_OT_pointcloud_add(struct wmOperatorType *ot);
/**
* Only used as menu.

@ -53,12 +53,12 @@
#include "BKE_armature.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_curves.h"
#include "BKE_displist.h"
#include "BKE_editmesh.h"
#include "BKE_effect.h"
#include "BKE_global.h"
#include "BKE_gpencil_modifier.h"
#include "BKE_hair.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_lib_id.h"
@ -132,8 +132,8 @@ static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object *
else if (ob->type == OB_GPENCIL) {
BKE_gpencil_modifiers_calc(depsgraph, scene_eval, ob_eval);
}
else if (ob->type == OB_HAIR) {
BKE_hair_data_update(depsgraph, scene_eval, ob);
else if (ob->type == OB_CURVES) {
BKE_curves_data_update(depsgraph, scene_eval, ob);
}
else if (ob->type == OB_POINTCLOUD) {
BKE_pointcloud_data_update(depsgraph, scene_eval, ob);

@ -105,7 +105,7 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_light_add);
WM_operatortype_append(OBJECT_OT_camera_add);
WM_operatortype_append(OBJECT_OT_speaker_add);
WM_operatortype_append(OBJECT_OT_hair_add);
WM_operatortype_append(OBJECT_OT_hair_curves_add);
WM_operatortype_append(OBJECT_OT_pointcloud_add);
WM_operatortype_append(OBJECT_OT_volume_add);
WM_operatortype_append(OBJECT_OT_volume_import);

@ -63,11 +63,11 @@
#include "BKE_constraint.h"
#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_curves.h"
#include "BKE_displist.h"
#include "BKE_editmesh.h"
#include "BKE_fcurve.h"
#include "BKE_gpencil.h"
#include "BKE_hair.h"
#include "BKE_idprop.h"
#include "BKE_idtype.h"
#include "BKE_lattice.h"
@ -1872,7 +1872,7 @@ static void single_obdata_users(
ob->data,
BKE_id_copy_ex(bmain, ob->data, NULL, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS));
break;
case OB_HAIR:
case OB_CURVES:
ob->data = ID_NEW_SET(
ob->data,
BKE_id_copy_ex(bmain, ob->data, NULL, LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ACTIONS));

@ -635,7 +635,7 @@ static int gather_frames_to_render_for_id(LibraryIDLinkCallbackData *cb_data)
case ID_MC: /* MovieClip */
case ID_MSK: /* Mask */
case ID_LP: /* LightProbe */
case ID_HA: /* Hair */
case ID_CV: /* Curves */
case ID_PT: /* PointCloud */
case ID_VO: /* Volume */
case ID_SIM: /* Simulation */

@ -48,7 +48,7 @@ endif()
if(WITH_EXPERIMENTAL_FEATURES)
add_definitions(-DWITH_SIMULATION_DATABLOCK)
add_definitions(-DWITH_POINT_CLOUD)
add_definitions(-DWITH_HAIR_NODES)
add_definitions(-DWITH_NEW_CURVES_TYPE)
endif()
blender_add_lib(bf_editor_space_buttons "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")

@ -273,8 +273,8 @@ static bool buttons_context_path_data(ButsContextPath *path, int type)
if (RNA_struct_is_a(ptr->type, &RNA_GreasePencil) && (ELEM(type, -1, OB_GPENCIL))) {
return true;
}
#ifdef WITH_HAIR_NODES
if (RNA_struct_is_a(ptr->type, &RNA_Hair) && (ELEM(type, -1, OB_HAIR))) {
#ifdef WITH_NEW_CURVES_TYPE
if (RNA_struct_is_a(ptr->type, &RNA_Curves) && (ELEM(type, -1, OB_CURVES))) {
return true;
}
#endif
@ -314,7 +314,7 @@ static bool buttons_context_path_modifier(ButsContextPath *path)
OB_SURF,
OB_LATTICE,
OB_GPENCIL,
OB_HAIR,
OB_CURVES,
OB_POINTCLOUD,
OB_VOLUME)) {
ModifierData *md = BKE_object_active_modifier(ob);
@ -845,8 +845,8 @@ const char *buttons_context_dir[] = {
"line_style",
"collection",
"gpencil",
#ifdef WITH_HAIR_NODES
"hair",
#ifdef WITH_NEW_CURVES_TYPE
"curves",
#endif
#ifdef WITH_POINT_CLOUD
"pointcloud",
@ -941,9 +941,9 @@ int /*eContextResult*/ buttons_context(const bContext *C,
set_pointer_type(path, result, &RNA_LightProbe);
return CTX_RESULT_OK;
}
#ifdef WITH_HAIR_NODES
if (CTX_data_equals(member, "hair")) {
set_pointer_type(path, result, &RNA_Hair);
#ifdef WITH_NEW_CURVES_TYPE
if (CTX_data_equals(member, "curves")) {
set_pointer_type(path, result, &RNA_Curves);
return CTX_RESULT_OK;
}
#endif

@ -219,7 +219,7 @@ static void stats_object(Object *ob,
}
break;
}
case OB_HAIR:
case OB_CURVES:
case OB_POINTCLOUD:
case OB_VOLUME: {
break;

@ -2632,8 +2632,8 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
case OB_LIGHTPROBE:
data.icon = ICON_OUTLINER_OB_LIGHTPROBE;
break;
case OB_HAIR:
data.icon = ICON_OUTLINER_OB_HAIR;
case OB_CURVES:
data.icon = ICON_OUTLINER_OB_CURVES;
break;
case OB_POINTCLOUD:
data.icon = ICON_OUTLINER_OB_POINTCLOUD;
@ -2746,8 +2746,8 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
case ID_GR:
data.icon = ICON_OUTLINER_COLLECTION;
break;
case ID_HA:
data.icon = ICON_OUTLINER_DATA_HAIR;
case ID_CV:
data.icon = ICON_OUTLINER_DATA_CURVES;
break;
case ID_PT:
data.icon = ICON_OUTLINER_DATA_POINTCLOUD;

@ -145,7 +145,7 @@ typedef struct TreeElementIcon {
ID_GD, \
ID_LS, \
ID_LP, \
ID_HA, \
ID_CV, \
ID_PT, \
ID_VO, \
ID_SIM) || /* Only in 'blendfile' mode ... :/ */ \

@ -1198,7 +1198,7 @@ static void outliner_set_properties_tab(bContext *C, TreeElement *te, TreeStoreE
case ID_AR:
case ID_GD:
case ID_LP:
case ID_HA:
case ID_CV:
case ID_PT:
case ID_VO:
context = BCONTEXT_DATA;

@ -29,8 +29,8 @@
#include "DNA_armature_types.h"
#include "DNA_collection_types.h"
#include "DNA_constraint_types.h"
#include "DNA_curves_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_hair_types.h"
#include "DNA_light_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_material_types.h"
@ -164,7 +164,7 @@ static void get_element_operation_type(
case ID_CF:
case ID_WS:
case ID_LP:
case ID_HA:
case ID_CV:
case ID_PT:
case ID_VO:
case ID_SIM:
@ -262,10 +262,10 @@ static void unlink_material_fn(bContext *UNUSED(C),
totcol = mb->totcol;
matar = mb->mat;
}
else if (GS(tsep->id->name) == ID_HA) {
Hair *hair = (Hair *)tsep->id;
totcol = hair->totcol;
matar = hair->mat;
else if (GS(tsep->id->name) == ID_CV) {
Curves *curves = (Curves *)tsep->id;
totcol = curves->totcol;
matar = curves->mat;
}
else if (GS(tsep->id->name) == ID_PT) {
PointCloud *pointcloud = (PointCloud *)tsep->id;

@ -32,9 +32,9 @@
#include "DNA_camera_types.h"
#include "DNA_collection_types.h"
#include "DNA_constraint_types.h"
#include "DNA_curves_types.h"
#include "DNA_gpencil_modifier_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_hair_types.h"
#include "DNA_key_types.h"
#include "DNA_light_types.h"
#include "DNA_lightprobe_types.h"
@ -773,10 +773,10 @@ static void outliner_add_id_contents(SpaceOutliner *space_outliner,
}
break;
}
case ID_HA: {
Hair *hair = (Hair *)id;
if (outliner_animdata_test(hair->adt)) {
outliner_add_element(space_outliner, &te->subtree, hair, te, TSE_ANIM_DATA, 0);
case ID_CV: {
Curves *curves = (Curves *)id;
if (outliner_animdata_test(curves->adt)) {
outliner_add_element(space_outliner, &te->subtree, curves, te, TSE_ANIM_DATA, 0);
}
break;
}

@ -69,7 +69,7 @@ std::unique_ptr<TreeElementID> TreeElementID::createFromID(TreeElement &legacy_t
case ID_LP:
case ID_GD:
case ID_WS:
case ID_HA:
case ID_CV:
case ID_PT:
case ID_VO:
case ID_SIM:

@ -1764,7 +1764,7 @@ static void view3d_panel_transform(const bContext *C, Panel *panel)
v3d_transform_butsR(col, &obptr);
/* Dimensions and editmode are mostly the same check. */
if (OB_TYPE_SUPPORT_EDITMODE(ob->type) || ELEM(ob->type, OB_VOLUME, OB_HAIR, OB_POINTCLOUD)) {
if (OB_TYPE_SUPPORT_EDITMODE(ob->type) || ELEM(ob->type, OB_VOLUME, OB_CURVES, OB_POINTCLOUD)) {
View3D *v3d = CTX_wm_view3d(C);
v3d_object_dimension_buts(NULL, col, v3d, ob);
}

@ -890,7 +890,7 @@ typedef enum IDRecalcFlag {
#define FILTER_ID_CF (1ULL << 28)
#define FILTER_ID_WS (1ULL << 29)
#define FILTER_ID_LP (1ULL << 31)
#define FILTER_ID_HA (1ULL << 32)
#define FILTER_ID_CV (1ULL << 32)
#define FILTER_ID_PT (1ULL << 33)
#define FILTER_ID_VO (1ULL << 34)
#define FILTER_ID_SIM (1ULL << 35)
@ -901,7 +901,7 @@ typedef enum IDRecalcFlag {
FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME | FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB | \
FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_SCE | FILTER_ID_SPK | FILTER_ID_SO | \
FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | FILTER_ID_CF | FILTER_ID_WS | \
FILTER_ID_LP | FILTER_ID_HA | FILTER_ID_PT | FILTER_ID_VO | FILTER_ID_SIM)
FILTER_ID_LP | FILTER_ID_CV | FILTER_ID_PT | FILTER_ID_VO | FILTER_ID_SIM)
/**
* This enum defines the index assigned to each type of IDs in the array returned by
@ -984,7 +984,7 @@ enum {
INDEX_ID_ME,
INDEX_ID_CU,
INDEX_ID_MB,
INDEX_ID_HA,
INDEX_ID_CV,
INDEX_ID_PT,
INDEX_ID_VO,
INDEX_ID_LT,

@ -90,7 +90,7 @@ typedef enum ID_Type {
ID_CF = MAKE_ID2('C', 'F'), /* CacheFile */
ID_WS = MAKE_ID2('W', 'S'), /* WorkSpace */
ID_LP = MAKE_ID2('L', 'P'), /* LightProbe */
ID_HA = MAKE_ID2('H', 'A'), /* Hair */
ID_CV = MAKE_ID2('C', 'V'), /* Curves */
ID_PT = MAKE_ID2('P', 'T'), /* PointCloud */
ID_VO = MAKE_ID2('V', 'O'), /* Volume */
ID_SIM = MAKE_ID2('S', 'I'), /* Simulation (geometry node groups) */

@ -24,10 +24,10 @@
/* clang-format off */
/* -------------------------------------------------------------------- */
/** \name Hair Struct
/** \name Curves Struct
* \{ */
#define _DNA_DEFAULT_Hair \
#define _DNA_DEFAULT_Curves \
{ \
.flag = 0, \
}

@ -76,7 +76,7 @@ typedef struct CurvesGeometry {
int curve_size;
} CurvesGeometry;
typedef struct Hair {
typedef struct Curves {
ID id;
/* Animation data (must be immediately after id). */
struct AnimData *adt;
@ -93,15 +93,15 @@ typedef struct Hair {
/* Draw Cache. */
void *batch_cache;
} Hair;
} Curves;
/* Hair.flag */
/* Curves.flag */
enum {
HA_DS_EXPAND = (1 << 0),
};
/* Only one material supported currently. */
#define HAIR_MATERIAL_NR 1
#define CURVES_MATERIAL_NR 1
#ifdef __cplusplus
}

@ -505,7 +505,7 @@ enum {
/** Grease Pencil object used in 3D view but not used for annotation in 2D. */
OB_GPENCIL = 26,
OB_HAIR = 27,
OB_CURVES = 27,
OB_POINTCLOUD = 28,
@ -520,7 +520,15 @@ enum {
(((_type) >= OB_MESH && (_type) <= OB_MBALL) || ((_type) >= OB_GPENCIL && (_type) <= OB_VOLUME))
/** Does the object have some render-able geometry (unlike empties, cameras, etc.). */
#define OB_TYPE_IS_GEOMETRY(_type) \
(ELEM(_type, OB_MESH, OB_SURF, OB_FONT, OB_MBALL, OB_GPENCIL, OB_HAIR, OB_POINTCLOUD, OB_VOLUME))
(ELEM(_type, \
OB_MESH, \
OB_SURF, \
OB_FONT, \
OB_MBALL, \
OB_GPENCIL, \
OB_CURVES, \
OB_POINTCLOUD, \
OB_VOLUME))
#define OB_TYPE_SUPPORT_VGROUP(_type) (ELEM(_type, OB_MESH, OB_LATTICE, OB_GPENCIL))
#define OB_TYPE_SUPPORT_EDITMODE(_type) \
(ELEM(_type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL, OB_LATTICE, OB_ARMATURE))
@ -542,7 +550,7 @@ enum {
ID_LT, \
ID_GD, \
ID_AR, \
ID_HA, \
ID_CV, \
ID_PT, \
ID_VO))
@ -557,7 +565,7 @@ enum {
case ID_LT: \
case ID_GD: \
case ID_AR: \
case ID_HA: \
case ID_CV: \
case ID_PT: \
case ID_VO

@ -658,7 +658,7 @@ typedef struct UserDef_Experimental {
char SANITIZE_AFTER_HERE;
/* The following options are automatically sanitized (set to 0)
* when the release cycle is not alpha. */
char use_new_hair_type;
char use_new_curves_type;
char use_new_point_cloud_type;
char use_full_frame_compositor;
char use_sculpt_vertex_colors;
@ -1252,7 +1252,7 @@ typedef enum eDupli_ID_Flags {
USER_DUP_PSYS = (1 << 11),
USER_DUP_LIGHTPROBE = (1 << 12),
USER_DUP_GPENCIL = (1 << 13),
USER_DUP_HAIR = (1 << 14),
USER_DUP_CURVES = (1 << 14),
USER_DUP_POINTCLOUD = (1 << 15),
USER_DUP_VOLUME = (1 << 16),
USER_DUP_LATTICE = (1 << 17),

@ -142,7 +142,7 @@ set(SRC
../DNA_defaults.h
../DNA_fluid_defaults.h
../DNA_gpencil_modifier_defaults.h
../DNA_hair_defaults.h
../DNA_curves_defaults.h
../DNA_image_defaults.h
../DNA_lattice_defaults.h
../DNA_light_defaults.h

@ -94,9 +94,9 @@
#include "DNA_cloth_types.h"
#include "DNA_collection_types.h"
#include "DNA_curve_types.h"
#include "DNA_curves_types.h"
#include "DNA_fluid_types.h"
#include "DNA_gpencil_modifier_types.h"
#include "DNA_hair_types.h"
#include "DNA_image_types.h"
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
@ -127,9 +127,9 @@
#include "DNA_camera_defaults.h"
#include "DNA_collection_defaults.h"
#include "DNA_curve_defaults.h"
#include "DNA_curves_defaults.h"
#include "DNA_fluid_defaults.h"
#include "DNA_gpencil_modifier_defaults.h"
#include "DNA_hair_defaults.h"
#include "DNA_image_defaults.h"
#include "DNA_lattice_defaults.h"
#include "DNA_light_defaults.h"
@ -184,8 +184,8 @@ SDNA_DEFAULT_DECL_STRUCT(FluidEffectorSettings);
/* DNA_image_defaults.h */
SDNA_DEFAULT_DECL_STRUCT(Image);
/* DNA_hair_defaults.h */
SDNA_DEFAULT_DECL_STRUCT(Hair);
/* DNA_curves_defaults.h */
SDNA_DEFAULT_DECL_STRUCT(Curves);
/* DNA_lattice_defaults.h */
SDNA_DEFAULT_DECL_STRUCT(Lattice);
@ -392,8 +392,8 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = {
/* DNA_image_defaults.h */
SDNA_DEFAULT_DECL(Image),
/* DNA_hair_defaults.h */
SDNA_DEFAULT_DECL(Hair),
/* DNA_curves_defaults.h */
SDNA_DEFAULT_DECL(Curves),
/* DNA_lattice_defaults.h */
SDNA_DEFAULT_DECL(Lattice),

@ -134,7 +134,7 @@ static const char *includefiles[] = {
"DNA_lightprobe_types.h",
"DNA_curveprofile_types.h",
"DNA_xr_types.h",
"DNA_hair_types.h",
"DNA_curves_types.h",
"DNA_pointcloud_types.h",
"DNA_volume_types.h",
"DNA_simulation_types.h",
@ -1644,7 +1644,7 @@ int main(int argc, char **argv)
#include "DNA_freestyle_types.h"
#include "DNA_gpencil_modifier_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_hair_types.h"
#include "DNA_curves_types.h"
#include "DNA_image_types.h"
#include "DNA_ipo_types.h"
#include "DNA_key_types.h"

@ -308,7 +308,7 @@ extern StructRNA RNA_GizmoProperties;
extern StructRNA RNA_GlowSequence;
extern StructRNA RNA_GpencilModifier;
extern StructRNA RNA_GreasePencil;
extern StructRNA RNA_Hair;
extern StructRNA RNA_Curves;
extern StructRNA RNA_Header;
extern StructRNA RNA_Histogram;
extern StructRNA RNA_HookGpencilModifier;

@ -101,9 +101,9 @@ set(DEFSRC
if(WITH_EXPERIMENTAL_FEATURES)
add_definitions(-DWITH_SIMULATION_DATABLOCK)
add_definitions(-DWITH_HAIR_NODES)
add_definitions(-DWITH_NEW_CURVES_TYPE)
list(APPEND DEFSRC
rna_hair.c
rna_curves.c
rna_simulation.c
)
endif()

@ -4376,8 +4376,8 @@ static RNAProcessItem PROCESS_ITEMS[] = {
{"rna_dynamicpaint.c", NULL, RNA_def_dynamic_paint},
{"rna_fcurve.c", "rna_fcurve_api.c", RNA_def_fcurve},
{"rna_gpencil.c", NULL, RNA_def_gpencil},
#ifdef WITH_HAIR_NODES
{"rna_hair.c", NULL, RNA_def_hair},
#ifdef WITH_NEW_CURVES_TYPE
{"rna_curves.c", NULL, RNA_def_curves},
#endif
{"rna_image.c", "rna_image_api.c", RNA_def_image},
{"rna_key.c", NULL, RNA_def_key},

@ -76,7 +76,7 @@ const EnumPropertyItem rna_enum_id_type_items[] = {
{ID_SPK, "SPEAKER", ICON_SPEAKER, "Speaker", ""},
{ID_TXT, "TEXT", ICON_TEXT, "Text", ""},
{ID_TE, "TEXTURE", ICON_TEXTURE_DATA, "Texture", ""},
{ID_HA, "HAIR", ICON_HAIR_DATA, "Hair", ""},
{ID_CV, "CURVES", ICON_CURVES_DATA, "Hair Curves", ""},
{ID_PT, "POINTCLOUD", ICON_POINTCLOUD_DATA, "Point Cloud", ""},
{ID_VO, "VOLUME", ICON_VOLUME_DATA, "Volume", ""},
{ID_WM, "WINDOWMANAGER", ICON_WINDOW, "Window Manager", ""},
@ -151,7 +151,7 @@ const struct IDFilterEnumPropertyItem rna_enum_id_type_filter_items[] = {
ICON_OUTLINER_COLLECTION,
"Collections",
"Show Collection data-blocks"},
{FILTER_ID_HA, "filter_hair", ICON_HAIR_DATA, "Hairs", "Show/hide Hair data-blocks"},
{FILTER_ID_CV, "filter_hair", ICON_CURVES_DATA, "Hairs", "Show/hide Hair data-blocks"},
{FILTER_ID_IM, "filter_image", ICON_IMAGE_DATA, "Images", "Show Image data-blocks"},
{FILTER_ID_LA, "filter_light", ICON_LIGHT_DATA, "Lights", "Show Light data-blocks"},
{FILTER_ID_LP,
@ -385,9 +385,9 @@ short RNA_type_to_ID_code(const StructRNA *type)
if (base_type == &RNA_FreestyleLineStyle) {
return ID_LS;
}
# ifdef WITH_HAIR_NODES
if (base_type == &RNA_Hair) {
return ID_HA;
# ifdef WITH_NEW_CURVES_TYPE
if (base_type == &RNA_Curves) {
return ID_CV;
}
# endif
if (base_type == &RNA_Lattice) {
@ -492,9 +492,9 @@ StructRNA *ID_code_to_RNA_type(short idcode)
return &RNA_GreasePencil;
case ID_GR:
return &RNA_Collection;
case ID_HA:
# ifdef WITH_HAIR_NODES
return &RNA_Hair;
case ID_CV:
# ifdef WITH_NEW_CURVES_TYPE
return &RNA_Curves;
# else
return &RNA_ID;
# endif

@ -625,11 +625,11 @@ static void rna_def_dopesheet(BlenderRNA *brna)
RNA_def_property_ui_icon(prop, ICON_FILE, 0);
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
prop = RNA_def_property(srna, "show_hairs", PROP_BOOLEAN, PROP_NONE);
prop = RNA_def_property(srna, "show_hair_curves", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "filterflag2", ADS_FILTER_NOHAIR);
RNA_def_property_ui_text(
prop, "Display Hair", "Include visualization of hair related animation data");
RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_HAIR, 0);
RNA_def_property_ui_icon(prop, ICON_OUTLINER_OB_CURVES, 0);
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL);
prop = RNA_def_property(srna, "show_pointclouds", PROP_BOOLEAN, PROP_NONE);

@ -26,8 +26,8 @@
#include "rna_internal.h"
#include "DNA_curves_types.h"
#include "DNA_customdata_types.h"
#include "DNA_hair_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_pointcloud_types.h"
@ -188,7 +188,7 @@ const EnumPropertyItem *rna_enum_attribute_domain_itemf(ID *id,
if (id_type == ID_PT && !ELEM(domain_item->value, ATTR_DOMAIN_POINT)) {
continue;
}
if (id_type == ID_HA && !ELEM(domain_item->value, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE)) {
if (id_type == ID_CV && !ELEM(domain_item->value, ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE)) {
continue;
}
if (id_type == ID_ME && ELEM(domain_item->value, ATTR_DOMAIN_CURVE)) {

@ -25,7 +25,7 @@
#include "rna_internal.h"
#include "DNA_hair_types.h"
#include "DNA_curves_types.h"
#include "BLI_math_base.h"
#include "BLI_string.h"
@ -35,27 +35,27 @@
# include "BLI_math_vector.h"
# include "BKE_attribute.h"
# include "BKE_hair.h"
# include "BKE_curves.h"
# include "DEG_depsgraph.h"
# include "WM_api.h"
# include "WM_types.h"
static Hair *rna_hair(PointerRNA *ptr)
static Curves *rna_curves(PointerRNA *ptr)
{
return (Hair *)ptr->owner_id;
return (Curves *)ptr->owner_id;
}
static int rna_Hair_curve_offset_data_length(PointerRNA *ptr)
static int rna_Curves_curve_offset_data_length(PointerRNA *ptr)
{
const Hair *curves = rna_hair(ptr);
const Curves *curves = rna_curves(ptr);
return curves->geometry.curve_size + 1;
}
static void rna_Hair_curve_offset_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
static void rna_Curves_curve_offset_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
const Hair *curves = rna_hair(ptr);
const Curves *curves = rna_curves(ptr);
rna_iterator_array_begin(iter,
(void *)curves->geometry.offsets,
sizeof(int),
@ -66,9 +66,9 @@ static void rna_Hair_curve_offset_data_begin(CollectionPropertyIterator *iter, P
static int rna_CurvePoint_index_get(PointerRNA *ptr)
{
const Hair *hair = rna_hair(ptr);
const Curves *curves = rna_curves(ptr);
const float(*co)[3] = ptr->data;
return (int)(co - hair->geometry.position);
return (int)(co - curves->geometry.position);
}
static void rna_CurvePoint_location_get(PointerRNA *ptr, float value[3])
@ -83,22 +83,22 @@ static void rna_CurvePoint_location_set(PointerRNA *ptr, const float value[3])
static float rna_CurvePoint_radius_get(PointerRNA *ptr)
{
const Hair *hair = rna_hair(ptr);
if (hair->geometry.radius == NULL) {
const Curves *curves = rna_curves(ptr);
if (curves->geometry.radius == NULL) {
return 0.0f;
}
const float(*co)[3] = ptr->data;
return hair->geometry.radius[co - hair->geometry.position];
return curves->geometry.radius[co - curves->geometry.position];
}
static void rna_CurvePoint_radius_set(PointerRNA *ptr, float value)
{
const Hair *hair = rna_hair(ptr);
if (hair->geometry.radius == NULL) {
const Curves *curves = rna_curves(ptr);
if (curves->geometry.radius == NULL) {
return;
}
const float(*co)[3] = ptr->data;
hair->geometry.radius[co - hair->geometry.position] = value;
curves->geometry.radius[co - curves->geometry.position] = value;
}
static char *rna_CurvePoint_path(PointerRNA *ptr)
@ -108,8 +108,8 @@ static char *rna_CurvePoint_path(PointerRNA *ptr)
static int rna_CurveSlice_index_get(PointerRNA *ptr)
{
Hair *hair = rna_hair(ptr);
return (int)((int *)ptr->data - hair->geometry.offsets);
Curves *curves = rna_curves(ptr);
return (int)((int *)ptr->data - curves->geometry.offsets);
}
static char *rna_CurveSlice_path(PointerRNA *ptr)
@ -119,11 +119,11 @@ static char *rna_CurveSlice_path(PointerRNA *ptr)
static void rna_CurveSlice_points_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Hair *hair = rna_hair(ptr);
Curves *curves = rna_curves(ptr);
const int *offset_ptr = (int *)ptr->data;
const int offset = *offset_ptr;
const int size = *(offset_ptr + 1) - offset;
float(*co)[3] = hair->geometry.position + *offset_ptr;
float(*co)[3] = curves->geometry.position + *offset_ptr;
rna_iterator_array_begin(iter, co, sizeof(float[3]), size, 0, NULL);
}
@ -140,9 +140,9 @@ static int rna_CurveSlice_points_length_get(PointerRNA *ptr)
return *(offset_ptr + 1) - offset;
}
static void rna_Hair_update_data(struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
PointerRNA *ptr)
static void rna_Curves_update_data(struct Main *UNUSED(bmain),
struct Scene *UNUSED(scene),
PointerRNA *ptr)
{
ID *id = ptr->owner_id;
@ -155,7 +155,7 @@ static void rna_Hair_update_data(struct Main *UNUSED(bmain),
#else
static void rna_def_hair_point(BlenderRNA *brna)
static void rna_def_curves_point(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
@ -169,13 +169,13 @@ static void rna_def_hair_point(BlenderRNA *brna)
RNA_def_property_float_funcs(
prop, "rna_CurvePoint_location_get", "rna_CurvePoint_location_set", NULL);
RNA_def_property_ui_text(prop, "Position", "");
RNA_def_property_update(prop, 0, "rna_Hair_update_data");
RNA_def_property_update(prop, 0, "rna_Curves_update_data");
prop = RNA_def_property(srna, "radius", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_funcs(
prop, "rna_CurvePoint_radius_get", "rna_CurvePoint_radius_set", NULL);
RNA_def_property_ui_text(prop, "Radius", "");
RNA_def_property_update(prop, 0, "rna_Hair_update_data");
RNA_def_property_update(prop, 0, "rna_Curves_update_data");
prop = RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@ -183,7 +183,7 @@ static void rna_def_hair_point(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Index", "Index of this points");
}
static void rna_def_hair_curve(BlenderRNA *brna)
static void rna_def_curves_curve(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
@ -222,21 +222,21 @@ static void rna_def_hair_curve(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Index", "Index of this curve");
}
static void rna_def_hair(BlenderRNA *brna)
static void rna_def_curves(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "Hair", "ID");
RNA_def_struct_ui_text(srna, "Hair", "Hair data-block for hair curves");
RNA_def_struct_ui_icon(srna, ICON_HAIR_DATA);
srna = RNA_def_struct(brna, "Curves", "ID");
RNA_def_struct_ui_text(srna, "Hair Curves", "Hair data-block for hair curves");
RNA_def_struct_ui_icon(srna, ICON_CURVES_DATA);
/* Point and Curve RNA API helpers. */
prop = RNA_def_property(srna, "curves", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "geometry.offsets", "geometry.curve_size");
RNA_def_property_struct_type(prop, "CurveSlice");
RNA_def_property_ui_text(prop, "Curves", "All hair curves");
RNA_def_property_ui_text(prop, "Curves", "All curves in the data-block");
/* TODO: better solution for (*co)[3] parsing issue. */
@ -244,7 +244,7 @@ static void rna_def_hair(BlenderRNA *brna)
prop = RNA_def_property(srna, "points", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "geometry.position", "geometry.point_size");
RNA_def_property_struct_type(prop, "CurvePoint");
RNA_def_property_ui_text(prop, "Points", "Control points of all hair curves");
RNA_def_property_ui_text(prop, "Points", "Control points of all curves");
RNA_define_verify_sdna(1);
/* Direct access to built-in attributes. */
@ -253,22 +253,22 @@ static void rna_def_hair(BlenderRNA *brna)
prop = RNA_def_property(srna, "position_data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "geometry.position", "geometry.point_size");
RNA_def_property_struct_type(prop, "FloatVectorAttributeValue");
RNA_def_property_update(prop, 0, "rna_Hair_update_data");
RNA_def_property_update(prop, 0, "rna_Curves_update_data");
RNA_define_verify_sdna(1);
prop = RNA_def_property(srna, "curve_offset_data", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "geometry.offsets", NULL);
RNA_def_property_struct_type(prop, "IntAttributeValue");
RNA_def_property_collection_funcs(prop,
"rna_Hair_curve_offset_data_begin",
"rna_Curves_curve_offset_data_begin",
"rna_iterator_array_next",
"rna_iterator_array_end",
"rna_iterator_array_get",
"rna_Hair_curve_offset_data_length",
"rna_Curves_curve_offset_data_length",
NULL,
NULL,
NULL);
RNA_def_property_update(prop, 0, "rna_Hair_update_data");
RNA_def_property_update(prop, 0, "rna_Curves_update_data");
/* materials */
prop = RNA_def_property(srna, "materials", PROP_COLLECTION, PROP_NONE);
@ -286,11 +286,11 @@ static void rna_def_hair(BlenderRNA *brna)
rna_def_animdata_common(srna);
}
void RNA_def_hair(BlenderRNA *brna)
void RNA_def_curves(BlenderRNA *brna)
{
rna_def_hair_point(brna);
rna_def_hair_curve(brna);
rna_def_hair(brna);
rna_def_curves_point(brna);
rna_def_curves_curve(brna);
rna_def_curves(brna);
}
#endif

@ -170,7 +170,7 @@ void RNA_def_fcurve(struct BlenderRNA *brna);
void RNA_def_gpencil(struct BlenderRNA *brna);
void RNA_def_greasepencil_modifier(struct BlenderRNA *brna);
void RNA_def_shader_fx(struct BlenderRNA *brna);
void RNA_def_hair(struct BlenderRNA *brna);
void RNA_def_curves(struct BlenderRNA *brna);
void RNA_def_image(struct BlenderRNA *brna);
void RNA_def_key(struct BlenderRNA *brna);
void RNA_def_light(struct BlenderRNA *brna);
@ -496,8 +496,8 @@ void RNA_def_main_cachefiles(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_paintcurves(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_workspaces(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_lightprobes(BlenderRNA *brna, PropertyRNA *cprop);
#ifdef WITH_HAIR_NODES
void RNA_def_main_hairs(BlenderRNA *brna, PropertyRNA *cprop);
#ifdef WITH_NEW_CURVES_TYPE
void RNA_def_main_hair_curves(BlenderRNA *brna, PropertyRNA *cprop);
#endif
void RNA_def_main_pointclouds(BlenderRNA *brna, PropertyRNA *cprop);
void RNA_def_main_volumes(BlenderRNA *brna, PropertyRNA *cprop);

@ -110,8 +110,8 @@ RNA_MAIN_LISTBASE_FUNCS_DEF(collections)
RNA_MAIN_LISTBASE_FUNCS_DEF(curves)
RNA_MAIN_LISTBASE_FUNCS_DEF(fonts)
RNA_MAIN_LISTBASE_FUNCS_DEF(gpencils)
# ifdef WITH_HAIR_NODES
RNA_MAIN_LISTBASE_FUNCS_DEF(hairs)
# ifdef WITH_NEW_CURVES_TYPE
RNA_MAIN_LISTBASE_FUNCS_DEF(hair_curves)
# endif
RNA_MAIN_LISTBASE_FUNCS_DEF(images)
RNA_MAIN_LISTBASE_FUNCS_DEF(lattices)
@ -389,8 +389,17 @@ void RNA_def_main(BlenderRNA *brna)
"Light Probes",
"Light Probe data-blocks",
RNA_def_main_lightprobes},
# ifdef WITH_HAIR_NODES
{"hairs", "Hair", "rna_Main_hairs_begin", "Hairs", "Hair data-blocks", RNA_def_main_hairs},
# ifdef WITH_NEW_CURVES_TYPE
/**
* \note The name `hair_curves` is chosen to be different than `curves`,
* but they are generic curve data-blocks, not just for hair.
*/
{"hair_curves",
"Curves",
"rna_Main_hair_curves_begin",
"Hair Curves",
"Hair curve data-blocks",
RNA_def_main_hair_curves},
# endif
{"pointclouds",
"PointCloud",

@ -46,9 +46,9 @@
# include "BKE_camera.h"
# include "BKE_collection.h"
# include "BKE_curve.h"
# include "BKE_curves.h"
# include "BKE_displist.h"
# include "BKE_gpencil.h"
# include "BKE_hair.h"
# include "BKE_icons.h"
# include "BKE_idtype.h"
# include "BKE_image.h"
@ -86,8 +86,8 @@
# include "DNA_camera_types.h"
# include "DNA_collection_types.h"
# include "DNA_curve_types.h"
# include "DNA_curves_types.h"
# include "DNA_gpencil_types.h"
# include "DNA_hair_types.h"
# include "DNA_lattice_types.h"
# include "DNA_light_types.h"
# include "DNA_lightprobe_types.h"
@ -763,18 +763,18 @@ static bGPdata *rna_Main_gpencils_new(Main *bmain, const char *name)
return gpd;
}
# ifdef WITH_HAIR_NODES
static Hair *rna_Main_hairs_new(Main *bmain, const char *name)
# ifdef WITH_NEW_CURVES_TYPE
static Curves *rna_Main_hair_curves_new(Main *bmain, const char *name)
{
char safe_name[MAX_ID_NAME - 2];
rna_idname_validate(name, safe_name);
Hair *hair = BKE_hair_add(bmain, safe_name);
id_us_min(&hair->id);
Curves *curves = BKE_curves_add(bmain, safe_name);
id_us_min(&curves->id);
WM_main_add_notifier(NC_ID | NA_ADDED, NULL);
return hair;
return curves;
}
# endif
@ -861,8 +861,8 @@ RNA_MAIN_ID_TAG_FUNCS_DEF(cachefiles, cachefiles, ID_CF)
RNA_MAIN_ID_TAG_FUNCS_DEF(paintcurves, paintcurves, ID_PC)
RNA_MAIN_ID_TAG_FUNCS_DEF(workspaces, workspaces, ID_WS)
RNA_MAIN_ID_TAG_FUNCS_DEF(lightprobes, lightprobes, ID_LP)
# ifdef WITH_HAIR_NODES
RNA_MAIN_ID_TAG_FUNCS_DEF(hairs, hairs, ID_HA)
# ifdef WITH_NEW_CURVES_TYPE
RNA_MAIN_ID_TAG_FUNCS_DEF(hair_curves, hair_curves, ID_CV)
# endif
RNA_MAIN_ID_TAG_FUNCS_DEF(pointclouds, pointclouds, ID_PT)
RNA_MAIN_ID_TAG_FUNCS_DEF(volumes, volumes, ID_VO)
@ -2269,47 +2269,47 @@ void RNA_def_main_lightprobes(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
}
# ifdef WITH_HAIR_NODES
void RNA_def_main_hairs(BlenderRNA *brna, PropertyRNA *cprop)
# ifdef WITH_NEW_CURVES_TYPE
void RNA_def_main_hair_curves(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
FunctionRNA *func;
PropertyRNA *parm;
RNA_def_property_srna(cprop, "BlendDataHairs");
srna = RNA_def_struct(brna, "BlendDataHairs", NULL);
RNA_def_property_srna(cprop, "BlendDataHairCurves");
srna = RNA_def_struct(brna, "BlendDataHairCurves", NULL);
RNA_def_struct_sdna(srna, "Main");
RNA_def_struct_ui_text(srna, "Main Hairs", "Collection of hairs");
RNA_def_struct_ui_text(srna, "Main Hair Curves", "Collection of hair curves");
func = RNA_def_function(srna, "new", "rna_Main_hairs_new");
func = RNA_def_function(srna, "new", "rna_Main_hair_curves_new");
RNA_def_function_ui_description(func, "Add a new hair to the main database");
parm = RNA_def_string(func, "name", "Hair", 0, "", "New name for the data-block");
parm = RNA_def_string(func, "name", "Curves", 0, "", "New name for the data-block");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
/* return type */
parm = RNA_def_pointer(func, "hair", "Hair", "", "New hair data-block");
parm = RNA_def_pointer(func, "curves", "Curves", "", "New curves data-block");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "remove", "rna_Main_ID_remove");
RNA_def_function_flag(func, FUNC_USE_REPORTS);
RNA_def_function_ui_description(func, "Remove a hair from the current blendfile");
parm = RNA_def_pointer(func, "hair", "Hair", "", "Hair to remove");
RNA_def_function_ui_description(func, "Remove a curves data-block from the current blendfile");
parm = RNA_def_pointer(func, "curves", "Curves", "", "Curves data-block to remove");
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0);
RNA_def_boolean(func,
"do_unlink",
true,
"",
"Unlink all usages of this hair before deleting it "
"(WARNING: will also delete objects instancing that hair data)");
"Unlink all usages of this curves before deleting it "
"(WARNING: will also delete objects instancing that curves data)");
RNA_def_boolean(func,
"do_id_user",
true,
"",
"Decrement user counter of all datablocks used by this hair data");
"Decrement user counter of all datablocks used by this curves data");
RNA_def_boolean(
func, "do_ui_user", true, "", "Make sure interface does not reference this hair data");
func, "do_ui_user", true, "", "Make sure interface does not reference this curves data");
func = RNA_def_function(srna, "tag", "rna_Main_hairs_tag");
func = RNA_def_function(srna, "tag", "rna_Main_hair_curves_tag");
parm = RNA_def_boolean(func, "value", 0, "Value", "");
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
}

@ -718,7 +718,7 @@ void RNA_def_material(BlenderRNA *brna)
{MA_FLAT, "FLAT", ICON_MATPLANE, "Flat", "Flat XY plane"},
{MA_SPHERE, "SPHERE", ICON_MATSPHERE, "Sphere", "Sphere"},
{MA_CUBE, "CUBE", ICON_MATCUBE, "Cube", "Cube"},
{MA_HAIR, "HAIR", ICON_HAIR, "Hair", "Hair strands"},
{MA_HAIR, "HAIR", ICON_CURVES, "Hair", "Hair strands"},
{MA_SHADERBALL, "SHADERBALL", ICON_MATSHADERBALL, "Shader Ball", "Shader ball"},
{MA_CLOTH, "CLOTH", ICON_MATCLOTH, "Cloth", "Cloth"},
{MA_FLUID, "FLUID", ICON_MATFLUID, "Fluid", "Fluid"},

@ -271,7 +271,7 @@ const EnumPropertyItem rna_enum_object_type_items[] = {
OBTYPE_CU_SURF,
{OB_MBALL, "META", ICON_OUTLINER_OB_META, "Metaball", ""},
OBTYPE_CU_FONT,
{OB_HAIR, "HAIR", ICON_OUTLINER_OB_HAIR, "Hair", ""},
{OB_CURVES, "CURVES", ICON_OUTLINER_OB_CURVES, "Hair Curves", ""},
{OB_POINTCLOUD, "POINTCLOUD", ICON_OUTLINER_OB_POINTCLOUD, "Point Cloud", ""},
{OB_VOLUME, "VOLUME", ICON_OUTLINER_OB_VOLUME, "Volume", ""},
{OB_GPENCIL, "GPENCIL", ICON_OUTLINER_OB_GREASEPENCIL, "Grease Pencil", ""},
@ -613,9 +613,9 @@ static StructRNA *rna_Object_data_typef(PointerRNA *ptr)
return &RNA_LightProbe;
case OB_GPENCIL:
return &RNA_GreasePencil;
case OB_HAIR:
# ifdef WITH_HAIR_NODES
return &RNA_Hair;
case OB_CURVES:
# ifdef WITH_NEW_CURVES_TYPE
return &RNA_Curves;
# else
return &RNA_ID;
# endif

@ -3277,7 +3277,7 @@ static struct IDFilterEnumPropertyItem rna_enum_space_file_id_filter_categories[
ICON_OUTLINER_COLLECTION,
"Objects & Collections",
"Show objects and collections"},
{FILTER_ID_AR | FILTER_ID_CU | FILTER_ID_LT | FILTER_ID_MB | FILTER_ID_ME | FILTER_ID_HA |
{FILTER_ID_AR | FILTER_ID_CU | FILTER_ID_LT | FILTER_ID_MB | FILTER_ID_ME | FILTER_ID_CV |
FILTER_ID_PT | FILTER_ID_VO,
"category_geometry",
ICON_NODETREE,
@ -5004,7 +5004,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
{"Surface", (1 << OB_SURF), {"show_object_viewport_surf", "show_object_select_surf"}},
{"Meta", (1 << OB_MBALL), {"show_object_viewport_meta", "show_object_select_meta"}},
{"Font", (1 << OB_FONT), {"show_object_viewport_font", "show_object_select_font"}},
{"Hair", (1 << OB_HAIR), {"show_object_viewport_hair", "show_object_select_hair"}},
{"Hair", (1 << OB_CURVES), {"show_object_viewport_hair", "show_object_select_hair"}},
{"Point Cloud",
(1 << OB_POINTCLOUD),
{"show_object_viewport_pointcloud", "show_object_select_pointcloud"}},

@ -5293,7 +5293,7 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
prop, "Duplicate GPencil", "Causes grease pencil data to be duplicated with the object");
prop = RNA_def_property(srna, "use_duplicate_hair", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_HAIR);
RNA_def_property_boolean_sdna(prop, NULL, "dupflag", USER_DUP_CURVES);
RNA_def_property_ui_text(
prop, "Duplicate Hair", "Causes hair data to be duplicated with the object");
@ -6399,9 +6399,9 @@ static void rna_def_userdef_experimental(BlenderRNA *brna)
"reduces execution time and memory usage)");
RNA_def_property_update(prop, 0, "rna_userdef_update");
prop = RNA_def_property(srna, "use_new_hair_type", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_new_hair_type", 1);
RNA_def_property_ui_text(prop, "New Hair Type", "Enable the new hair type in the ui");
prop = RNA_def_property(srna, "use_new_curves_type", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_new_curves_type", 1);
RNA_def_property_ui_text(prop, "New Curves Type", "Enable the new curves data type in the UI");
prop = RNA_def_property(srna, "use_cycles_debug", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "use_cycles_debug", 1);

@ -232,7 +232,7 @@ endif()
if(WITH_EXPERIMENTAL_FEATURES)
add_definitions(-DWITH_SIMULATION_DATABLOCK)
add_definitions(-DWITH_HAIR_NODES)
add_definitions(-DWITH_NEW_CURVES_TYPE)
endif()
# So we can have special tricks in modifier system.