tornavis/source/blender/editors/object/object_add.cc

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

4476 lines
139 KiB
C++
Raw Normal View History

/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edobj
2011-02-27 21:29:51 +01:00
*/
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <optional>
#include "MEM_guardedalloc.h"
#include "DNA_anim_types.h"
#include "DNA_camera_types.h"
#include "DNA_collection_types.h"
#include "DNA_curve_types.h"
#include "DNA_gpencil_legacy_types.h"
#include "DNA_gpencil_modifier_types.h"
#include "DNA_key_types.h"
#include "DNA_light_types.h"
#include "DNA_lightprobe_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
Curves: support deforming curves on surface Curves that are attached to a surface can now follow the surface when it is modified using shape keys or modifiers (but not when the original surface is deformed in edit or sculpt mode). The surface is allowed to be changed in any way that keeps uv maps intact. So deformation is allowed, but also some topology changes like subdivision. The following features are added: * A new `Deform Curves on Surface` node, which deforms curves with attachment information based on the surface object and uv map set in the properties panel. * A new `Add Rest Position` checkbox in the shape keys panel. When checked, a new `rest_position` vector attribute is added to the mesh before shape keys and modifiers are applied. This is necessary to support proper deformation of the curves, but can also be used for other purposes. * The `Add > Curve > Empty Hair` operator now sets up a simple geometry nodes setup that deforms the hair. It also makes sure that the rest position attribute is added to the surface. * A new `Object (Attach Curves to Surface)` operator in the `Set Parent To` (ctrl+P) menu, which attaches existing curves to the surface and sets the surface object as parent. Limitations: * Sculpting the procedurally deformed curves will be implemented separately. * The `Deform Curves on Surface` node is not generic and can only be used for one specific purpose currently. We plan to generalize this more in the future by adding support by exposing more inputs and/or by turning it into a node group. Differential Revision: https://developer.blender.org/D14864
2022-07-08 14:45:48 +02:00
#include "DNA_modifier_types.h"
#include "DNA_object_fluidsim_types.h"
#include "DNA_object_force_types.h"
#include "DNA_object_types.h"
#include "DNA_pointcloud_types.h"
#include "DNA_scene_types.h"
#include "DNA_vfont_types.h"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
#include "BLI_math_matrix.h"
#include "BLI_math_rotation.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_utildefines.h"
#include "BLI_vector.hh"
#include "BLT_translation.h"
#include "BKE_action.h"
#include "BKE_anim_data.h"
#include "BKE_armature.hh"
#include "BKE_camera.h"
Render Layers and Collections (merge from render-layers) Design Documents ---------------- * https://wiki.blender.org/index.php/Dev:2.8/Source/Layers * https://wiki.blender.org/index.php/Dev:2.8/Source/DataDesignRevised User Commit Log --------------- * New Layer and Collection system to replace render layers and viewport layers. * A layer is a set of collections of objects (and their drawing options) required for specific tasks. * A collection is a set of objects, equivalent of the old layers in Blender. A collection can be shared across multiple layers. * All Scenes have a master collection that all other collections are children of. * New collection "context" tab (in Properties Editor) * New temporary viewport "collections" panel to control per-collection visibility Missing User Features --------------------- * Collection "Filter" Option to add objects based on their names * Collection Manager operators The existing buttons are placeholders * Collection Manager drawing The editor main region is empty * Collection Override * Per-Collection engine settings This will come as a separate commit, as part of the clay-engine branch Dev Commit Log -------------- * New DNA file (DNA_layer_types.h) with the new structs We are replacing Base by a new extended Base while keeping it backward compatible with some legacy settings (i.e., lay, flag_legacy). Renamed all Base to BaseLegacy to make it clear the areas of code that still need to be converted Note: manual changes were required on - deg_builder_nodes.h, rna_object.c, KX_Light.cpp * Unittesting for main syncronization requirements - read, write, add/copy/remove objects, copy scene, collection link/unlinking, context) * New Editor: Collection Manager Based on patch by Julian Eisel This is extracted from the layer-manager branch. With the following changes: - Renamed references of layer manager to collections manager - I doesn't include the editors/space_collections/ draw and util files - The drawing code itself will be implemented separately by Julian * Base / Object: A little note about them. Original Blender code would try to keep them in sync through the code, juggling flags back and forth. This will now be handled by Depsgraph, keeping Object and Bases more separated throughout the non-rendering code. Scene.base is being cleared in doversion, and the old viewport drawing code was poorly converted to use the new bases while the new viewport code doesn't get merged and replace the old one. Python API Changes ------------------ ``` - scene.layers + # no longer exists - scene.objects + scene.scene_layers.active.objects - scene.objects.active + scene.render_layers.active.objects.active - bpy.context.scene.objects.link() + bpy.context.scene_collection.objects.link() - bpy_extras.object_utils.object_data_add(context, obdata, operator=None, use_active_layer=True, name=None) + bpy_extras.object_utils.object_data_add(context, obdata, operator=None, name=None) - bpy.context.object.select + bpy.context.object.select = True + bpy.context.object.select = False + bpy.context.object.select_get() + bpy.context.object.select_set(action='SELECT') + bpy.context.object.select_set(action='DESELECT') -AddObjectHelper.layers + # no longer exists ```
2017-02-07 10:18:38 +01:00
#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_context.hh"
#include "BKE_curve.hh"
#include "BKE_curve_to_mesh.hh"
#include "BKE_curves.h"
#include "BKE_displist.h"
#include "BKE_duplilist.h"
Unified effector functionality for particles, cloth and softbody * Unified scene wide gravity (currently in scene buttons) instead of each simulation having it's own gravity. * Weight parameters for all effectors and an effector group setting. * Every effector can use noise. * Most effectors have "shapes" point, plane, surface, every point. - "Point" is most like the old effectors and uses the effector location as the effector point. - "Plane" uses the closest point on effectors local xy-plane as the effector point. - "Surface" uses the closest point on an effector object's surface as the effector point. - "Every Point" uses every point in a mesh effector object as an effector point. - The falloff is calculated from this point, so for example with "surface" shape and "use only negative z axis" it's possible to apply force only "inside" the effector object. * Spherical effector is now renamed as "force" as it's no longer just spherical. * New effector parameter "flow", which makes the effector act as surrounding air velocity, so the resulting force is proportional to the velocity difference of the point and "air velocity". For example a wind field with flow=1.0 results in proper non-accelerating wind. * New effector fields "turbulence", which creates nice random flow paths, and "drag", which slows the points down. * Much improved vortex field. * Effectors can now effect particle rotation as well as location. * Use full, or only positive/negative z-axis to apply force (note. the z-axis is the surface normal in the case of effector shape "surface") * New "force field" submenu in add menu, which adds an empty with the chosen effector (curve object for corve guides). * Other dynamics should be quite easy to add to the effector system too if wanted. * "Unified" doesn't mean that force fields give the exact same results for particles, softbody & cloth, since their final effect depends on many external factors, like for example the surface area of the effected faces. Code changes * Subversion bump for correct handling of global gravity. * Separate ui py file for common dynamics stuff. * Particle settings updating is flushed with it's id through DAG_id_flush_update(..). Known issues * Curve guides don't yet have all ui buttons in place, but they should work none the less. * Hair dynamics don't yet respect force fields. Other changes * Particle emission defaults now to frames 1-200 with life of 50 frames to fill the whole default timeline. * Many particles drawing related crashes fixed. * Sometimes particles didn't update on first frame properly. * Hair with object/group visualization didn't work properly. * Memory leaks with PointCacheID lists (Genscher, remember to free pidlists after use :).
2009-10-01 00:10:14 +02:00
#include "BKE_effect.h"
#include "BKE_geometry_set.hh"
#include "BKE_geometry_set_instances.hh"
#include "BKE_gpencil_curve_legacy.h"
#include "BKE_gpencil_geom_legacy.h"
#include "BKE_gpencil_legacy.h"
#include "BKE_gpencil_modifier_legacy.h"
#include "BKE_grease_pencil.hh"
#include "BKE_key.h"
#include "BKE_lattice.hh"
Render Layers and Collections (merge from render-layers) Design Documents ---------------- * https://wiki.blender.org/index.php/Dev:2.8/Source/Layers * https://wiki.blender.org/index.php/Dev:2.8/Source/DataDesignRevised User Commit Log --------------- * New Layer and Collection system to replace render layers and viewport layers. * A layer is a set of collections of objects (and their drawing options) required for specific tasks. * A collection is a set of objects, equivalent of the old layers in Blender. A collection can be shared across multiple layers. * All Scenes have a master collection that all other collections are children of. * New collection "context" tab (in Properties Editor) * New temporary viewport "collections" panel to control per-collection visibility Missing User Features --------------------- * Collection "Filter" Option to add objects based on their names * Collection Manager operators The existing buttons are placeholders * Collection Manager drawing The editor main region is empty * Collection Override * Per-Collection engine settings This will come as a separate commit, as part of the clay-engine branch Dev Commit Log -------------- * New DNA file (DNA_layer_types.h) with the new structs We are replacing Base by a new extended Base while keeping it backward compatible with some legacy settings (i.e., lay, flag_legacy). Renamed all Base to BaseLegacy to make it clear the areas of code that still need to be converted Note: manual changes were required on - deg_builder_nodes.h, rna_object.c, KX_Light.cpp * Unittesting for main syncronization requirements - read, write, add/copy/remove objects, copy scene, collection link/unlinking, context) * New Editor: Collection Manager Based on patch by Julian Eisel This is extracted from the layer-manager branch. With the following changes: - Renamed references of layer manager to collections manager - I doesn't include the editors/space_collections/ draw and util files - The drawing code itself will be implemented separately by Julian * Base / Object: A little note about them. Original Blender code would try to keep them in sync through the code, juggling flags back and forth. This will now be handled by Depsgraph, keeping Object and Bases more separated throughout the non-rendering code. Scene.base is being cleared in doversion, and the old viewport drawing code was poorly converted to use the new bases while the new viewport code doesn't get merged and replace the old one. Python API Changes ------------------ ``` - scene.layers + # no longer exists - scene.objects + scene.scene_layers.active.objects - scene.objects.active + scene.render_layers.active.objects.active - bpy.context.scene.objects.link() + bpy.context.scene_collection.objects.link() - bpy_extras.object_utils.object_data_add(context, obdata, operator=None, use_active_layer=True, name=None) + bpy_extras.object_utils.object_data_add(context, obdata, operator=None, name=None) - bpy.context.object.select + bpy.context.object.select = True + bpy.context.object.select = False + bpy.context.object.select_get() + bpy.context.object.select_set(action='SELECT') + bpy.context.object.select_set(action='DESELECT') -AddObjectHelper.layers + # no longer exists ```
2017-02-07 10:18:38 +01:00
#include "BKE_layer.h"
#include "BKE_lib_id.h"
#include "BKE_lib_override.hh"
#include "BKE_lib_query.h"
#include "BKE_lib_remap.h"
#include "BKE_light.h"
#include "BKE_lightprobe.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mball.h"
#include "BKE_mesh.hh"
#include "BKE_mesh_runtime.hh"
#include "BKE_nla.h"
#include "BKE_node.hh"
#include "BKE_object.hh"
#include "BKE_object_types.hh"
#include "BKE_particle.h"
#include "BKE_pointcloud.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_speaker.h"
#include "BKE_vfont.h"
#include "BKE_volume.hh"
2023-11-22 22:50:16 +01:00
#include "BKE_scene.h"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_build.hh"
#include "DEG_depsgraph_query.hh"
#include "RNA_access.hh"
#include "RNA_define.hh"
#include "RNA_enum_types.hh"
#include "UI_interface.hh"
#include "WM_api.hh"
#include "WM_types.hh"
#include "ED_armature.hh"
#include "ED_curve.hh"
#include "ED_curves.hh"
#include "ED_gpencil_legacy.hh"
#include "ED_grease_pencil.hh"
#include "ED_mball.hh"
#include "ED_mesh.hh"
#include "ED_node.hh"
#include "ED_object.hh"
#include "ED_outliner.hh"
#include "ED_physics.hh"
#include "ED_render.hh"
#include "ED_screen.hh"
#include "ED_select_utils.hh"
#include "ED_transform.hh"
#include "ED_view3d.hh"
#include "ANIM_bone_collections.h"
#include "UI_resources.hh"
#include "object_intern.h"
2023-11-22 22:50:16 +01:00
#include "transform_orientations.hh"
Curves: support deforming curves on surface Curves that are attached to a surface can now follow the surface when it is modified using shape keys or modifiers (but not when the original surface is deformed in edit or sculpt mode). The surface is allowed to be changed in any way that keeps uv maps intact. So deformation is allowed, but also some topology changes like subdivision. The following features are added: * A new `Deform Curves on Surface` node, which deforms curves with attachment information based on the surface object and uv map set in the properties panel. * A new `Add Rest Position` checkbox in the shape keys panel. When checked, a new `rest_position` vector attribute is added to the mesh before shape keys and modifiers are applied. This is necessary to support proper deformation of the curves, but can also be used for other purposes. * The `Add > Curve > Empty Hair` operator now sets up a simple geometry nodes setup that deforms the hair. It also makes sure that the rest position attribute is added to the surface. * A new `Object (Attach Curves to Surface)` operator in the `Set Parent To` (ctrl+P) menu, which attaches existing curves to the surface and sets the surface object as parent. Limitations: * Sculpting the procedurally deformed curves will be implemented separately. * The `Deform Curves on Surface` node is not generic and can only be used for one specific purpose currently. We plan to generalize this more in the future by adding support by exposing more inputs and/or by turning it into a node group. Differential Revision: https://developer.blender.org/D14864
2022-07-08 14:45:48 +02:00
using blender::float3;
using blender::float4x4;
using blender::Vector;
/* -------------------------------------------------------------------- */
/** \name Local Enum Declarations
* \{ */
/* This is an exact copy of the define in `rna_light.cc`
2012-10-05 09:05:52 +02:00
* kept here because of linking order.
* Icons are only defined here. */
const EnumPropertyItem rna_enum_light_type_items[] = {
{LA_LOCAL, "POINT", ICON_LIGHT_POINT, "Point", "Omnidirectional point light source"},
{LA_SUN, "SUN", ICON_LIGHT_SUN, "Sun", "Constant direction parallel ray light source"},
{LA_SPOT, "SPOT", ICON_LIGHT_SPOT, "Spot", "Directional cone light source"},
{LA_AREA, "AREA", ICON_LIGHT_AREA, "Area", "Directional area light source"},
{0, nullptr, 0, nullptr, nullptr},
};
/* copy from rna_object_force.cc */
static const EnumPropertyItem field_type_items[] = {
2012-10-05 09:05:52 +02:00
{PFIELD_FORCE, "FORCE", ICON_FORCE_FORCE, "Force", ""},
{PFIELD_WIND, "WIND", ICON_FORCE_WIND, "Wind", ""},
{PFIELD_VORTEX, "VORTEX", ICON_FORCE_VORTEX, "Vortex", ""},
{PFIELD_MAGNET, "MAGNET", ICON_FORCE_MAGNETIC, "Magnetic", ""},
{PFIELD_HARMONIC, "HARMONIC", ICON_FORCE_HARMONIC, "Harmonic", ""},
{PFIELD_CHARGE, "CHARGE", ICON_FORCE_CHARGE, "Charge", ""},
{PFIELD_LENNARDJ, "LENNARDJ", ICON_FORCE_LENNARDJONES, "Lennard-Jones", ""},
{PFIELD_TEXTURE, "TEXTURE", ICON_FORCE_TEXTURE, "Texture", ""},
{PFIELD_GUIDE, "GUIDE", ICON_FORCE_CURVE, "Curve Guide", ""},
{PFIELD_BOID, "BOID", ICON_FORCE_BOID, "Boid", ""},
{PFIELD_TURBULENCE, "TURBULENCE", ICON_FORCE_TURBULENCE, "Turbulence", ""},
{PFIELD_DRAG, "DRAG", ICON_FORCE_DRAG, "Drag", ""},
{PFIELD_FLUIDFLOW, "FLUID", ICON_FORCE_FLUIDFLOW, "Fluid Flow", ""},
{0, nullptr, 0, nullptr, nullptr},
2012-10-05 09:05:52 +02:00
};
static EnumPropertyItem lightprobe_type_items[] = {
{LIGHTPROBE_TYPE_SPHERE,
"SPHERE",
ICON_LIGHTPROBE_SPHERE,
"Sphere",
"Light probe that captures precise lighting from all directions at a single point in space"},
{LIGHTPROBE_TYPE_PLANE,
"PLANE",
ICON_LIGHTPROBE_PLANE,
"Plane",
"Light probe that captures incoming light from a single direction on a plane"},
{LIGHTPROBE_TYPE_VOLUME,
"VOLUME",
ICON_LIGHTPROBE_VOLUME,
"Volume",
"Light probe that captures low frequency lighting inside a volume"},
{0, nullptr, 0, nullptr, nullptr},
};
2019-05-16 05:54:32 +02:00
enum {
ALIGN_WORLD = 0,
ALIGN_VIEW,
ALIGN_CURSOR,
2019-05-16 05:54:32 +02:00
};
static const EnumPropertyItem align_options[] = {
{ALIGN_WORLD, "WORLD", 0, "World", "Align the new object to the world"},
{ALIGN_VIEW, "VIEW", 0, "View", "Align the new object to the view"},
{ALIGN_CURSOR, "CURSOR", 0, "3D Cursor", "Use the 3D cursor orientation for the new object"},
{0, nullptr, 0, nullptr, nullptr},
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name Local Helpers
* \{ */
/**
* Operator properties for creating an object under a screen space (2D) coordinate.
* Used for object dropping like behavior (drag object and drop into 3D View).
*/
static void object_add_drop_xy_props(wmOperatorType *ot)
{
PropertyRNA *prop;
prop = RNA_def_int(ot->srna,
"drop_x",
0,
INT_MIN,
INT_MAX,
"Drop X",
"X-coordinate (screen space) to place the new object under",
INT_MIN,
INT_MAX);
RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE));
prop = RNA_def_int(ot->srna,
"drop_y",
0,
INT_MIN,
INT_MAX,
"Drop Y",
"Y-coordinate (screen space) to place the new object under",
INT_MIN,
INT_MAX);
RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE));
}
static bool object_add_drop_xy_is_set(const wmOperator *op)
{
return RNA_struct_property_is_set(op->ptr, "drop_x") &&
RNA_struct_property_is_set(op->ptr, "drop_y");
}
/**
* Query the currently set X- and Y-coordinate to position the new object under.
* \param r_mval: Returned pointer to the coordinate in region-space.
*/
static bool object_add_drop_xy_get(bContext *C, wmOperator *op, int (*r_mval)[2])
{
if (!object_add_drop_xy_is_set(op)) {
(*r_mval)[0] = 0.0f;
(*r_mval)[1] = 0.0f;
return false;
}
const ARegion *region = CTX_wm_region(C);
(*r_mval)[0] = RNA_int_get(op->ptr, "drop_x") - region->winrct.xmin;
(*r_mval)[1] = RNA_int_get(op->ptr, "drop_y") - region->winrct.ymin;
return true;
}
/**
* Set the drop coordinate to the mouse position (if not already set) and call the operator's
* `exec()` callback.
*/
static int object_add_drop_xy_generic_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (!object_add_drop_xy_is_set(op)) {
RNA_int_set(op->ptr, "drop_x", event->xy[0]);
RNA_int_set(op->ptr, "drop_y", event->xy[1]);
}
return op->type->exec(C, op);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Public Add Object API
* \{ */
void ED_object_location_from_view(bContext *C, float loc[3])
{
const Scene *scene = CTX_data_scene(C);
copy_v3_v3(loc, scene->cursor.location);
}
void ED_object_rotation_from_quat(float rot[3], const float viewquat[4], const char align_axis)
{
BLI_assert(align_axis >= 'X' && align_axis <= 'Z');
switch (align_axis) {
case 'X': {
/* Same as 'rv3d->viewinv[1]' */
const float axis_y[4] = {0.0f, 1.0f, 0.0f};
float quat_y[4], quat[4];
axis_angle_to_quat(quat_y, axis_y, M_PI_2);
mul_qt_qtqt(quat, viewquat, quat_y);
quat_to_eul(rot, quat);
break;
}
case 'Y': {
quat_to_eul(rot, viewquat);
rot[0] -= float(M_PI_2);
break;
}
case 'Z': {
quat_to_eul(rot, viewquat);
break;
}
}
}
void ED_object_rotation_from_view(bContext *C, float rot[3], const char align_axis)
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
BLI_assert(align_axis >= 'X' && align_axis <= 'Z');
if (rv3d) {
float viewquat[4];
copy_qt_qt(viewquat, rv3d->viewquat);
viewquat[0] *= -1.0f;
ED_object_rotation_from_quat(rot, viewquat, align_axis);
}
else {
zero_v3(rot);
}
}
void ED_object_base_init_transform_on_add(Object *object, const float loc[3], const float rot[3])
{
2019-04-22 01:19:45 +02:00
if (loc) {
copy_v3_v3(object->loc, loc);
2019-04-22 01:19:45 +02:00
}
2012-10-05 09:05:52 +02:00
2019-04-22 01:19:45 +02:00
if (rot) {
copy_v3_v3(object->rot, rot);
2019-04-22 01:19:45 +02:00
}
2012-10-05 09:05:52 +02:00
BKE_object_to_mat4(object, object->object_to_world);
}
float ED_object_new_primitive_matrix(bContext *C,
Object *obedit,
const float loc[3],
const float rot[3],
const float scale[3],
float r_primmat[4][4])
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
float mat[3][3], rmat[3][3], cmat[3][3], imat[3][3];
2012-10-05 09:05:52 +02:00
2023-11-22 22:50:16 +01:00
float ts_mat[3][3];
char ts_name[MAX_NAME];
//int orientation_index = v3d->twmode - V3D_MANIP_CUSTOM;
TransformOrientation *custom_orientation = nullptr;
if (scene->orientation_slots->type >= V3D_ORIENT_CUSTOM &&
scene->orientation_slots->index_custom != -1)
{
custom_orientation = BKE_scene_transform_orientation_find(
scene, scene->orientation_slots->index_custom);
}
unit_m4(r_primmat);
2012-10-05 09:05:52 +02:00
eul_to_mat3(rmat, rot);
invert_m3(rmat);
2012-10-05 09:05:52 +02:00
2023-11-22 22:50:16 +01:00
if (custom_orientation) {
applyTransformOrientation(custom_orientation, ts_mat, ts_name);
invert_m3(ts_mat);
mul_m3_m3m3(mat, rmat, ts_mat);
copy_m3_m3(rmat, mat);
}
/* inverse transform for initial rotation and object */
copy_m3_m4(mat, obedit->object_to_world);
mul_m3_m3m3(cmat, rmat, mat);
invert_m3_m3(imat, cmat);
2023-11-22 22:50:16 +01:00
copy_m4_m3(r_primmat, imat);
2012-10-05 09:05:52 +02:00
/* center */
copy_v3_v3(r_primmat[3], loc);
sub_v3_v3v3(r_primmat[3], r_primmat[3], obedit->object_to_world[3]);
invert_m3_m3(imat, mat);
mul_m3_v3(imat, r_primmat[3]);
2012-10-05 09:05:52 +02:00
if (scale != nullptr) {
rescale_m4(r_primmat, scale);
}
{
const float dia = v3d ? ED_view3d_grid_scale(scene, v3d, nullptr) :
ED_scene_grid_scale(scene, nullptr);
return dia;
}
// return 1.0f;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Add Object Operator
* \{ */
static void view_align_update(Main * /*main*/, Scene * /*scene*/, PointerRNA *ptr)
{
RNA_struct_idprops_unset(ptr, "rotation");
}
void ED_object_add_unit_props_size(wmOperatorType *ot)
{
RNA_def_float_distance(
ot->srna, "size", 2.0f, 0.0, OBJECT_ADD_SIZE_MAXF, "Size", "", 0.001, 100.00);
}
void ED_object_add_unit_props_radius_ex(wmOperatorType *ot, float default_value)
{
RNA_def_float_distance(
ot->srna, "radius", default_value, 0.0, OBJECT_ADD_SIZE_MAXF, "Radius", "", 0.001, 100.00);
}
void ED_object_add_unit_props_radius(wmOperatorType *ot)
{
ED_object_add_unit_props_radius_ex(ot, 1.0f);
}
void ED_object_add_generic_props(wmOperatorType *ot, bool do_editmode)
{
PropertyRNA *prop;
if (do_editmode) {
2021-01-04 02:00:00 +01:00
prop = RNA_def_boolean(ot->srna,
"enter_editmode",
false,
2021-01-04 02:00:00 +01:00
"Enter Edit Mode",
"Enter edit mode when adding this object");
RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE));
}
/* NOTE: this property gets hidden for add-camera operator. */
prop = RNA_def_enum(
ot->srna, "align", align_options, ALIGN_WORLD, "Align", "The alignment of the new object");
RNA_def_property_update_runtime(prop, view_align_update);
prop = RNA_def_float_vector_xyz(ot->srna,
"location",
3,
nullptr,
-OBJECT_ADD_SIZE_MAXF,
OBJECT_ADD_SIZE_MAXF,
"Location",
"Location for the newly added object",
-1000.0f,
1000.0f);
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_float_rotation(ot->srna,
"rotation",
3,
nullptr,
-OBJECT_ADD_SIZE_MAXF,
OBJECT_ADD_SIZE_MAXF,
"Rotation",
"Rotation for the newly added object",
DEG2RADF(-360.0f),
DEG2RADF(360.0f));
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_float_vector_xyz(ot->srna,
"scale",
3,
nullptr,
-OBJECT_ADD_SIZE_MAXF,
OBJECT_ADD_SIZE_MAXF,
"Scale",
"Scale for the newly added object",
-1000.0f,
1000.0f);
RNA_def_property_flag(prop, (PropertyFlag)(PROP_HIDDEN | PROP_SKIP_SAVE));
}
void ED_object_add_mesh_props(wmOperatorType *ot)
{
RNA_def_boolean(ot->srna, "calc_uvs", true, "Generate UVs", "Generate a default UV map");
}
2018-12-07 02:59:04 +01:00
bool ED_object_add_generic_get_opts(bContext *C,
wmOperator *op,
const char view_align_axis,
float r_loc[3],
float r_rot[3],
float r_scale[3],
bool *r_enter_editmode,
ushort *r_local_view_bits,
bool *r_is_view_aligned)
{
/* Edit Mode! (optional) */
{
bool _enter_editmode;
if (!r_enter_editmode) {
r_enter_editmode = &_enter_editmode;
2019-04-22 01:19:45 +02:00
}
/* Only to ensure the value is _always_ set.
* Typically the property will exist when the argument is non-nullptr. */
*r_enter_editmode = false;
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "enter_editmode");
if (prop != nullptr) {
if (RNA_property_is_set(op->ptr, prop) && r_enter_editmode) {
*r_enter_editmode = RNA_property_boolean_get(op->ptr, prop);
}
else {
*r_enter_editmode = (U.flag & USER_ADD_EDITMODE) != 0;
RNA_property_boolean_set(op->ptr, prop, *r_enter_editmode);
}
}
}
if (r_local_view_bits) {
2018-12-07 02:59:04 +01:00
View3D *v3d = CTX_wm_view3d(C);
*r_local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0;
}
/* Location! */
{
float _loc[3];
if (!r_loc) {
r_loc = _loc;
2019-04-22 01:19:45 +02:00
}
if (RNA_struct_property_is_set(op->ptr, "location")) {
RNA_float_get_array(op->ptr, "location", r_loc);
}
else {
ED_object_location_from_view(C, r_loc);
RNA_float_set_array(op->ptr, "location", r_loc);
}
}
/* Rotation! */
{
bool _is_view_aligned;
float _rot[3];
if (!r_is_view_aligned) {
r_is_view_aligned = &_is_view_aligned;
2019-04-22 01:19:45 +02:00
}
if (!r_rot) {
r_rot = _rot;
2019-04-22 01:19:45 +02:00
}
2019-04-22 01:19:45 +02:00
if (RNA_struct_property_is_set(op->ptr, "rotation")) {
/* If rotation is set, always use it. Alignment (and corresponding user preference)
* can be ignored since this is in world space anyways.
2021-02-09 21:57:52 +01:00
* To not confuse (e.g. on redo), don't set it to #ALIGN_WORLD in the op UI though. */
*r_is_view_aligned = false;
RNA_float_get_array(op->ptr, "rotation", r_rot);
2019-04-22 01:19:45 +02:00
}
else {
int alignment = ALIGN_WORLD;
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "align");
if (RNA_property_is_set(op->ptr, prop)) {
/* If alignment is set, always use it. */
*r_is_view_aligned = alignment == ALIGN_VIEW;
alignment = RNA_property_enum_get(op->ptr, prop);
}
else {
/* If alignment is not set, use User Preferences. */
*r_is_view_aligned = (U.flag & USER_ADD_VIEWALIGNED) != 0;
if (*r_is_view_aligned) {
RNA_property_enum_set(op->ptr, prop, ALIGN_VIEW);
alignment = ALIGN_VIEW;
}
else if ((U.flag & USER_ADD_CURSORALIGNED) != 0) {
RNA_property_enum_set(op->ptr, prop, ALIGN_CURSOR);
alignment = ALIGN_CURSOR;
}
else {
RNA_property_enum_set(op->ptr, prop, ALIGN_WORLD);
alignment = ALIGN_WORLD;
}
}
switch (alignment) {
case ALIGN_WORLD:
RNA_float_get_array(op->ptr, "rotation", r_rot);
break;
case ALIGN_VIEW:
ED_object_rotation_from_view(C, r_rot, view_align_axis);
RNA_float_set_array(op->ptr, "rotation", r_rot);
break;
case ALIGN_CURSOR: {
const Scene *scene = CTX_data_scene(C);
float tmat[3][3];
BKE_scene_cursor_rot_to_mat3(&scene->cursor, tmat);
mat3_normalized_to_eul(r_rot, tmat);
RNA_float_set_array(op->ptr, "rotation", r_rot);
break;
}
}
2019-04-22 01:19:45 +02:00
}
}
/* Scale! */
{
float _scale[3];
if (!r_scale) {
r_scale = _scale;
}
/* For now this is optional, we can make it always use. */
copy_v3_fl(r_scale, 1.0f);
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "scale");
if (prop != nullptr) {
if (RNA_property_is_set(op->ptr, prop)) {
RNA_property_float_get_array(op->ptr, prop, r_scale);
}
else {
copy_v3_fl(r_scale, 1.0f);
RNA_property_float_set_array(op->ptr, prop, r_scale);
}
}
}
return true;
}
Object *ED_object_add_type_with_obdata(bContext *C,
const int type,
const char *name,
const float loc[3],
const float rot[3],
const bool enter_editmode,
const ushort local_view_bits,
ID *obdata)
{
2012-04-28 17:42:27 +02:00
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
{
ViewLayer: Lazy sync of scene data. When a change happens which invalidates view layers the syncing will be postponed until the first usage. This will improve importing or adding many objects in a single operation/script. `BKE_view_layer_need_resync_tag` is used to tag the view layer to be out of sync. Before accessing `BKE_view_layer_active_base_get`, `BKE_view_layer_active_object_get`, `BKE_view_layer_active_collection` or `BKE_view_layer_object_bases` the caller should call `BKE_view_layer_synced_ensure`. Having two functions ensures that partial syncing could be added as smaller patches in the future. Tagging a view layer out of sync could be replaced with a partial sync. Eventually the number of full resyncs could be reduced. After all tagging has been replaced with partial syncs the ensure_sync could be phased out. This patch has been added to discuss the details and consequences of the current approach. For clarity the call to BKE_view_layer_ensure_sync is placed close to the getters. In the future this could be placed in more strategical places to reduce the number of calls or improve performance. Finding those strategical places isn't that clear. When multiple operations are grouped in a single script you might want to always check for resync. Some areas found that can be improved. This list isn't complete. These areas aren't addressed by this patch as these changes would be hard to detect to the reviewer. The idea is to add changes to these areas as a separate patch. It might be that the initial commit would reduce performance compared to master, but will be fixed by the additional patches. **Object duplication** During object duplication the syncing is temporarily disabled. With this patch this isn't useful as when disabled the view_layer is accessed to locate bases. This can be improved by first locating the source bases, then duplicate and sync and locate the new bases. Will be solved in a separate patch for clarity reasons ({D15886}). **Object add** `BKE_object_add` not only adds a new object, but also selects and activates the new base. This requires the view_layer to be resynced. Some callers reverse the selection and activation (See `get_new_constraint_target`). We should make the selection and activation optional. This would make it possible to add multiple objects without having to resync per object. **Postpone Activate Base** Setting the basact is done in many locations. They follow a rule as after an action find the base and set the basact. Finding the base could require a resync. The idea is to store in the view_layer the object which base will be set in the basact during the next sync, reducing the times resyncing needs to happen. Reviewed By: mont29 Maniphest Tasks: T73411 Differential Revision: https://developer.blender.org/D15885
2022-09-14 21:33:51 +02:00
BKE_view_layer_synced_ensure(scene, view_layer);
Object *obedit = BKE_view_layer_edit_object_get(view_layer);
if (obedit != nullptr) {
ED_object_editmode_exit_ex(bmain, scene, obedit, EM_FREEDATA);
}
}
/* deselects all, sets active object */
Object *ob;
if (obdata != nullptr) {
BLI_assert(type == BKE_object_obdata_to_type(obdata));
ob = BKE_object_add_for_data(bmain, scene, view_layer, type, name, obdata, true);
const short *materials_len_p = BKE_id_material_len_p(obdata);
if (materials_len_p && *materials_len_p > 0) {