Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/object/object_add.c')
-rw-r--r--source/blender/editors/object/object_add.c237
1 files changed, 185 insertions, 52 deletions
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index 8289f52b0c8..8073d87080f 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -65,6 +65,7 @@
#include "BKE_effect.h"
#include "BKE_font.h"
#include "BKE_gpencil_curve.h"
+#include "BKE_gpencil_geom.h"
#include "BKE_hair.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
@@ -96,6 +97,8 @@
#include "RNA_define.h"
#include "RNA_enum_types.h"
+#include "UI_interface.h"
+
#include "WM_api.h"
#include "WM_types.h"
@@ -857,7 +860,7 @@ static int object_metaball_add_exec(bContext *C, wmOperator *op)
* we want to pass in 1 so other values such as resolution are scaled by 1.0. */
dia = RNA_float_get(op->ptr, "radius") / 2;
- ED_mball_add_primitive(C, obedit, mat, dia, RNA_enum_get(op->ptr, "type"));
+ ED_mball_add_primitive(C, obedit, newob, mat, dia, RNA_enum_get(op->ptr, "type"));
/* userdef */
if (newob && !enter_editmode) {
@@ -1508,6 +1511,14 @@ void OBJECT_OT_speaker_add(wmOperatorType *ot)
/** \name Add Hair Operator
* \{ */
+static bool object_hair_add_poll(bContext *C)
+{
+ if (!U.experimental.use_new_hair_type) {
+ return false;
+ }
+ return ED_operator_objectmode(C);
+}
+
static int object_hair_add_exec(bContext *C, wmOperator *op)
{
ushort local_view_bits;
@@ -1531,7 +1542,7 @@ void OBJECT_OT_hair_add(wmOperatorType *ot)
/* api callbacks */
ot->exec = object_hair_add_exec;
- ot->poll = ED_operator_objectmode;
+ ot->poll = object_hair_add_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -1545,6 +1556,14 @@ void OBJECT_OT_hair_add(wmOperatorType *ot)
/** \name Add Point Cloud Operator
* \{ */
+static bool object_pointcloud_add_poll(bContext *C)
+{
+ if (!U.experimental.use_new_particle_system) {
+ return false;
+ }
+ return ED_operator_objectmode(C);
+}
+
static int object_pointcloud_add_exec(bContext *C, wmOperator *op)
{
ushort local_view_bits;
@@ -1568,7 +1587,7 @@ void OBJECT_OT_pointcloud_add(wmOperatorType *ot)
/* api callbacks */
ot->exec = object_pointcloud_add_exec;
- ot->poll = ED_operator_objectmode;
+ ot->poll = object_pointcloud_add_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -2129,11 +2148,11 @@ void OBJECT_OT_duplicates_make_real(wmOperatorType *ot)
static const EnumPropertyItem convert_target_items[] = {
{OB_CURVE, "CURVE", ICON_OUTLINER_OB_CURVE, "Curve from Mesh/Text", ""},
{OB_MESH, "MESH", ICON_OUTLINER_OB_MESH, "Mesh from Curve/Meta/Surf/Text", ""},
- {OB_GPENCIL, "GPENCIL", ICON_OUTLINER_OB_GREASEPENCIL, "Grease Pencil from Curve", ""},
+ {OB_GPENCIL, "GPENCIL", ICON_OUTLINER_OB_GREASEPENCIL, "Grease Pencil from Curve/Mesh", ""},
{0, NULL, 0, NULL, NULL},
};
-static void convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Object *ob)
+static void object_data_convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
if (ob->runtime.curve_cache == NULL) {
/* Force creation. This is normally not needed but on operator
@@ -2152,7 +2171,7 @@ static void convert_ensure_curve_cache(Depsgraph *depsgraph, Scene *scene, Objec
}
}
-static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Object *ob)
+static void object_data_convert_curve_to_mesh(Main *bmain, Depsgraph *depsgraph, Object *ob)
{
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
Curve *curve = ob->data;
@@ -2185,17 +2204,22 @@ static void curvetomesh(Main *bmain, Depsgraph *depsgraph, Object *ob)
}
}
-static bool convert_poll(bContext *C)
+static bool object_convert_poll(bContext *C)
{
Scene *scene = CTX_data_scene(C);
Base *base_act = CTX_data_active_base(C);
Object *obact = base_act ? base_act->object : NULL;
- return (!ID_IS_LINKED(scene) && obact && (BKE_object_is_in_editmode(obact) == false) &&
- (base_act->flag & BASE_SELECTED) && !ID_IS_LINKED(obact));
+ if (obact == NULL || obact->data == NULL || ID_IS_LINKED(obact) ||
+ ID_IS_OVERRIDE_LIBRARY(obact) || ID_IS_OVERRIDE_LIBRARY(obact->data)) {
+ return false;
+ }
+
+ return (!ID_IS_LINKED(scene) && (BKE_object_is_in_editmode(obact) == false) &&
+ (base_act->flag & BASE_SELECTED));
}
-/* Helper for convert_exec */
+/* Helper for object_convert_exec */
static Base *duplibase_for_convert(
Main *bmain, Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer, Base *base, Object *ob)
{
@@ -2230,7 +2254,7 @@ static Base *duplibase_for_convert(
* time we need to duplicate an object to convert it. Even worse, this is not 100% correct, since
* we do not yet have duplicated obdata.
* However, that is a safe solution for now. Proper, longer-term solution is to refactor
- * convert_exec to:
+ * object_convert_exec to:
* - duplicate all data it needs to in a first loop.
* - do a single update.
* - convert data in a second loop. */
@@ -2248,7 +2272,7 @@ static Base *duplibase_for_convert(
return basen;
}
-static int convert_exec(bContext *C, wmOperator *op)
+static int object_convert_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
@@ -2261,9 +2285,16 @@ static int convert_exec(bContext *C, wmOperator *op)
Nurb *nu;
MetaBall *mb;
Mesh *me;
- Object *gpencil_ob = NULL;
+ Object *ob_gpencil = NULL;
const short target = RNA_enum_get(op->ptr, "target");
bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
+
+ const float angle = RNA_float_get(op->ptr, "angle");
+ const int thickness = RNA_int_get(op->ptr, "thickness");
+ const bool use_seams = RNA_boolean_get(op->ptr, "seams");
+ const bool use_faces = RNA_boolean_get(op->ptr, "faces");
+ const float offset = RNA_float_get(op->ptr, "offset");
+
int a, mballConverted = 0;
bool gpencilConverted = false;
@@ -2375,6 +2406,54 @@ static int convert_exec(bContext *C, wmOperator *op)
ED_rigidbody_object_remove(bmain, scene, newob);
}
}
+ else if (ob->type == OB_MESH && target == OB_GPENCIL) {
+ ob->flag |= OB_DONE;
+
+ /* Create a new grease pencil object and copy transformations. */
+ ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0;
+ float loc[3], size[3], rot[3][3], eul[3];
+ float matrix[4][4];
+ mat4_to_loc_rot_size(loc, rot, size, ob->obmat);
+ mat3_to_eul(eul, rot);
+
+ ob_gpencil = ED_gpencil_add_object(C, loc, local_view_bits);
+ copy_v3_v3(ob_gpencil->loc, loc);
+ copy_v3_v3(ob_gpencil->rot, eul);
+ copy_v3_v3(ob_gpencil->scale, size);
+ unit_m4(matrix);
+ /* Set object in 3D mode. */
+ bGPdata *gpd = (bGPdata *)ob_gpencil->data;
+ gpd->draw_mode = GP_DRAWMODE_3D;
+
+ BKE_gpencil_convert_mesh(bmain,
+ depsgraph,
+ scene,
+ ob_gpencil,
+ ob,
+ angle,
+ thickness,
+ offset,
+ matrix,
+ 0,
+ use_seams,
+ use_faces);
+ gpencilConverted = true;
+
+ /* Remove unused materials. */
+ int actcol = ob_gpencil->actcol;
+ for (int slot = 1; slot <= ob_gpencil->totcol; slot++) {
+ while (slot <= ob_gpencil->totcol &&
+ !BKE_object_material_slot_used(ob_gpencil->data, slot)) {
+ ob_gpencil->actcol = slot;
+ BKE_object_material_slot_remove(CTX_data_main(C), ob_gpencil);
+
+ if (actcol >= slot) {
+ actcol--;
+ }
+ }
+ }
+ ob_gpencil->actcol = actcol;
+ }
else if (ob->type == OB_MESH) {
ob->flag |= OB_DONE;
@@ -2470,7 +2549,7 @@ static int convert_exec(bContext *C, wmOperator *op)
if (target == OB_MESH) {
/* No assumption should be made that the resulting objects is a mesh, as conversion can
* fail. */
- curvetomesh(bmain, depsgraph, newob);
+ object_data_convert_curve_to_mesh(bmain, depsgraph, newob);
/* meshes doesn't use displist */
BKE_object_free_curve_cache(newob);
}
@@ -2495,7 +2574,7 @@ static int convert_exec(bContext *C, wmOperator *op)
/* No assumption should be made that the resulting objects is a mesh, as conversion can
* fail. */
- curvetomesh(bmain, depsgraph, newob);
+ object_data_convert_curve_to_mesh(bmain, depsgraph, newob);
/* meshes doesn't use displist */
BKE_object_free_curve_cache(newob);
}
@@ -2509,10 +2588,10 @@ static int convert_exec(bContext *C, wmOperator *op)
* Nurbs Surface are not supported.
*/
ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0;
- gpencil_ob = ED_gpencil_add_object(C, ob->loc, local_view_bits);
- copy_v3_v3(gpencil_ob->rot, ob->rot);
- copy_v3_v3(gpencil_ob->scale, ob->scale);
- BKE_gpencil_convert_curve(bmain, scene, gpencil_ob, ob, false, false, true);
+ ob_gpencil = ED_gpencil_add_object(C, ob->loc, local_view_bits);
+ copy_v3_v3(ob_gpencil->rot, ob->rot);
+ copy_v3_v3(ob_gpencil->scale, ob->scale);
+ BKE_gpencil_convert_curve(bmain, scene, ob_gpencil, ob, false, false, true);
gpencilConverted = true;
}
}
@@ -2549,7 +2628,7 @@ static int convert_exec(bContext *C, wmOperator *op)
}
}
- convert_ensure_curve_cache(depsgraph, scene, baseob);
+ object_data_convert_ensure_curve_cache(depsgraph, scene, baseob);
BKE_mesh_from_metaball(&baseob->runtime.curve_cache->disp, newob->data);
if (obact->type == OB_MBALL) {
@@ -2618,12 +2697,12 @@ static int convert_exec(bContext *C, wmOperator *op)
}
FOREACH_SCENE_OBJECT_END;
}
- /* Remove curves converted to Grease Pencil object. */
+ /* Remove curves and meshes converted to Grease Pencil object. */
if (gpencilConverted) {
- FOREACH_SCENE_OBJECT_BEGIN (scene, ob_curve) {
- if (ob_curve->type == OB_CURVE) {
- if (ob_curve->flag & OB_DONE) {
- ED_object_base_free_and_unlink(bmain, scene, ob_curve);
+ FOREACH_SCENE_OBJECT_BEGIN (scene, ob_delete) {
+ if ((ob_delete->type == OB_CURVE) || (ob_delete->type == OB_MESH)) {
+ if (ob_delete->flag & OB_DONE) {
+ ED_object_base_free_and_unlink(bmain, scene, ob_delete);
}
}
}
@@ -2652,8 +2731,28 @@ static int convert_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
+static void object_convert_ui(bContext *UNUSED(C), wmOperator *op)
+{
+ uiLayout *layout = op->layout;
+ PointerRNA ptr;
+
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+ uiItemR(layout, &ptr, "target", 0, NULL, ICON_NONE);
+ uiItemR(layout, &ptr, "keep_original", 0, NULL, ICON_NONE);
+
+ if (RNA_enum_get(&ptr, "target") == OB_GPENCIL) {
+ uiItemR(layout, &ptr, "thickness", 0, NULL, ICON_NONE);
+ uiItemR(layout, &ptr, "angle", 0, NULL, ICON_NONE);
+ uiItemR(layout, &ptr, "offset", 0, NULL, ICON_NONE);
+ uiItemR(layout, &ptr, "seams", 0, NULL, ICON_NONE);
+ uiItemR(layout, &ptr, "faces", 0, NULL, ICON_NONE);
+ }
+}
+
void OBJECT_OT_convert(wmOperatorType *ot)
{
+ PropertyRNA *prop;
+
/* identifiers */
ot->name = "Convert to";
ot->description = "Convert selected objects to another type";
@@ -2661,8 +2760,9 @@ void OBJECT_OT_convert(wmOperatorType *ot)
/* api callbacks */
ot->invoke = WM_menu_invoke;
- ot->exec = convert_exec;
- ot->poll = convert_poll;
+ ot->exec = object_convert_exec;
+ ot->poll = object_convert_poll;
+ ot->ui = object_convert_ui;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -2675,6 +2775,31 @@ void OBJECT_OT_convert(wmOperatorType *ot)
0,
"Keep Original",
"Keep original objects instead of replacing them");
+
+ prop = RNA_def_float_rotation(ot->srna,
+ "angle",
+ 0,
+ NULL,
+ DEG2RADF(0.0f),
+ DEG2RADF(180.0f),
+ "Threshold Angle",
+ "Threshold to determine ends of the strokes",
+ DEG2RADF(0.0f),
+ DEG2RADF(180.0f));
+ RNA_def_property_float_default(prop, DEG2RADF(70.0f));
+
+ RNA_def_int(ot->srna, "thickness", 5, 1, 100, "Thickness", "", 1, 100);
+ RNA_def_boolean(ot->srna, "seams", 0, "Only Seam Edges", "Convert only seam edges");
+ RNA_def_boolean(ot->srna, "faces", 1, "Export Faces", "Export faces as filled strokes");
+ RNA_def_float_distance(ot->srna,
+ "offset",
+ 0.01f,
+ 0.0,
+ OBJECT_ADD_SIZE_MAXF,
+ "Stroke Offset",
+ "Offset strokes from fill",
+ 0.0,
+ 100.00);
}
/** \} */
@@ -2693,8 +2818,12 @@ void OBJECT_OT_convert(wmOperatorType *ot)
/* used below, assumes id.new is correct */
/* leaves selection of base/object unaltered */
/* Does set ID->newid pointers. */
-static Base *object_add_duplicate_internal(
- Main *bmain, Scene *scene, ViewLayer *view_layer, Object *ob, int dupflag)
+static Base *object_add_duplicate_internal(Main *bmain,
+ Scene *scene,
+ ViewLayer *view_layer,
+ Object *ob,
+ const eDupli_ID_Flags dupflag,
+ const eLibIDDuplicateFlags duplicate_options)
{
Base *base, *basen = NULL;
Object *obn;
@@ -2703,7 +2832,7 @@ static Base *object_add_duplicate_internal(
/* nothing? */
}
else {
- obn = ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag));
+ obn = ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag, duplicate_options));
DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
base = BKE_view_layer_base_find(view_layer, ob);
@@ -2742,12 +2871,13 @@ static Base *object_add_duplicate_internal(
* note: caller must do DAG_relations_tag_update(bmain);
* this is not done automatic since we may duplicate many objects in a batch */
Base *ED_object_add_duplicate(
- Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, int dupflag)
+ Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, const eDupli_ID_Flags dupflag)
{
Base *basen;
Object *ob;
- basen = object_add_duplicate_internal(bmain, scene, view_layer, base->object, dupflag);
+ basen = object_add_duplicate_internal(
+ bmain, scene, view_layer, base->object, dupflag, LIB_ID_DUPLICATE_IS_SUBPROCESS);
if (basen == NULL) {
return NULL;
}
@@ -2775,10 +2905,11 @@ static int duplicate_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
const bool linked = RNA_boolean_get(op->ptr, "linked");
- int dupflag = (linked) ? 0 : U.dupflag;
+ const eDupli_ID_Flags dupflag = (linked) ? 0 : (eDupli_ID_Flags)U.dupflag;
CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
- Base *basen = object_add_duplicate_internal(bmain, scene, view_layer, base->object, dupflag);
+ Base *basen = object_add_duplicate_internal(
+ bmain, scene, view_layer, base->object, dupflag, 0);
/* note that this is safe to do with this context iterator,
* the list is made in advance */
@@ -2849,7 +2980,7 @@ void OBJECT_OT_duplicate(wmOperatorType *ot)
* Use for drag & drop.
* \{ */
-static int add_named_exec(bContext *C, wmOperator *op)
+static int object_add_named_exec(bContext *C, wmOperator *op)
{
wmWindow *win = CTX_wm_window(C);
const wmEvent *event = win ? win->eventstate : NULL;
@@ -2859,7 +2990,7 @@ static int add_named_exec(bContext *C, wmOperator *op)
Base *basen;
Object *ob;
const bool linked = RNA_boolean_get(op->ptr, "linked");
- int dupflag = (linked) ? 0 : U.dupflag;
+ const eDupli_ID_Flags dupflag = (linked) ? 0 : (eDupli_ID_Flags)U.dupflag;
char name[MAX_ID_NAME - 2];
/* find object, create fake base */
@@ -2872,7 +3003,7 @@ static int add_named_exec(bContext *C, wmOperator *op)
}
/* prepare dupli */
- basen = object_add_duplicate_internal(bmain, scene, view_layer, ob, dupflag);
+ basen = object_add_duplicate_internal(bmain, scene, view_layer, ob, dupflag, 0);
if (basen == NULL) {
BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated");
@@ -2912,7 +3043,7 @@ void OBJECT_OT_add_named(wmOperatorType *ot)
ot->idname = "OBJECT_OT_add_named";
/* api callbacks */
- ot->exec = add_named_exec;
+ ot->exec = object_add_named_exec;
ot->poll = ED_operator_objectmode;
/* flags */
@@ -2933,23 +3064,24 @@ void OBJECT_OT_add_named(wmOperatorType *ot)
*
* \{ */
-static bool join_poll(bContext *C)
+static bool object_join_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
- if (!ob || ID_IS_LINKED(ob)) {
- return 0;
+ if (ob == NULL || ob->data == NULL || ID_IS_LINKED(ob) || ID_IS_OVERRIDE_LIBRARY(ob) ||
+ ID_IS_OVERRIDE_LIBRARY(ob->data)) {
+ return false;
}
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_ARMATURE, OB_GPENCIL)) {
return ED_operator_screenactive(C);
}
else {
- return 0;
+ return false;
}
}
-static int join_exec(bContext *C, wmOperator *op)
+static int object_join_exec(bContext *C, wmOperator *op)
{
Object *ob = CTX_data_active_object(C);
@@ -2970,13 +3102,13 @@ static int join_exec(bContext *C, wmOperator *op)
}
if (ob->type == OB_MESH) {
- return join_mesh_exec(C, op);
+ return ED_mesh_join_objects_exec(C, op);
}
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
- return join_curve_exec(C, op);
+ return ED_curve_join_objects_exec(C, op);
}
else if (ob->type == OB_ARMATURE) {
- return join_armature_exec(C, op);
+ return ED_armature_join_objects_exec(C, op);
}
else if (ob->type == OB_GPENCIL) {
return ED_gpencil_join_objects_exec(C, op);
@@ -2993,8 +3125,8 @@ void OBJECT_OT_join(wmOperatorType *ot)
ot->idname = "OBJECT_OT_join";
/* api callbacks */
- ot->exec = join_exec;
- ot->poll = join_poll;
+ ot->exec = object_join_exec;
+ ot->poll = object_join_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -3010,8 +3142,9 @@ static bool join_shapes_poll(bContext *C)
{
Object *ob = CTX_data_active_object(C);
- if (!ob || ID_IS_LINKED(ob)) {
- return 0;
+ if (ob == NULL || ob->data == NULL || ID_IS_LINKED(ob) || ID_IS_OVERRIDE_LIBRARY(ob) ||
+ ID_IS_OVERRIDE_LIBRARY(ob->data)) {
+ return false;
}
/* only meshes supported at the moment */
@@ -3019,7 +3152,7 @@ static bool join_shapes_poll(bContext *C)
return ED_operator_screenactive(C);
}
else {
- return 0;
+ return false;
}
}
@@ -3037,7 +3170,7 @@ static int join_shapes_exec(bContext *C, wmOperator *op)
}
if (ob->type == OB_MESH) {
- return join_mesh_shapes_exec(C, op);
+ return ED_mesh_shapes_join_objects_exec(C, op);
}
return OPERATOR_CANCELLED;