Changeset View
Standalone View
source/blender/editors/object/object_select.c
| Context not available. | |||||
| return changed; | return changed; | ||||
| } | } | ||||
| static bool select_grouped_parent(bContext *C) /* Makes parent active and de-selected OBACT */ | static bool select_grouped_parent(bContext *C, Object *ob) /* Makes parent active */ | ||||
| { | { | ||||
| if (!ob->parent) | |||||
| return 0; | |||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| View3D *v3d = CTX_wm_view3d(C); | View3D *v3d = CTX_wm_view3d(C); | ||||
| bool changed = false; | bool changed = false; | ||||
| Base *baspar, *basact = CTX_data_active_base(C); | |||||
| if (!basact || !(basact->object->parent)) return 0; /* we know OBACT is valid */ | |||||
| baspar = BKE_scene_base_find(scene, basact->object->parent); | Base * baspar = BKE_scene_base_find(scene, ob->parent); | ||||
| /* can be NULL if parent in other scene */ | /* can be NULL if parent in other scene */ | ||||
| if (baspar && BASE_SELECTABLE(v3d, baspar)) { | if (baspar && BASE_SELECTABLE(v3d, baspar)) { | ||||
| ED_base_object_select(basact, BA_DESELECT); | |||||
| ED_base_object_select(baspar, BA_SELECT); | ED_base_object_select(baspar, BA_SELECT); | ||||
| ED_base_object_activate(C, baspar); | ED_base_object_activate(C, baspar); | ||||
| changed = true; | changed = true; | ||||
| Context not available. | |||||
| static int object_select_grouped_exec(bContext *C, wmOperator *op) | static int object_select_grouped_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| Object *ob; | Object *obact; | ||||
| const int type = RNA_enum_get(op->ptr, "type"); | const int type = RNA_enum_get(op->ptr, "type"); | ||||
| bool changed = false, extend; | bool changed = false, extend, active_only; | ||||
| extend = RNA_boolean_get(op->ptr, "extend"); | extend = RNA_boolean_get(op->ptr, "extend"); | ||||
| active_only = RNA_boolean_get(op->ptr, "active_only"); | |||||
| if (extend == 0) { | obact = OBACT; | ||||
| CTX_DATA_BEGIN (C, Base *, base, visible_bases) | if (obact == NULL) { | ||||
| { | |||||
| ED_base_object_select(base, BA_DESELECT); | |||||
| changed = true; | |||||
| } | |||||
| CTX_DATA_END; | |||||
| } | |||||
| ob = OBACT; | |||||
| if (ob == NULL) { | |||||
| BKE_report(op->reports, RPT_ERROR, "No active object"); | BKE_report(op->reports, RPT_ERROR, "No active object"); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
campbellbarton: This is no longer correct - when operating on the selection theres no need for an active object. | |||||
| } | } | ||||
| ListBase ctx_selected_base_list; | |||||
| CollectionPointerLink *ctx_base; | |||||
| CTX_data_selected_bases(C, &ctx_selected_base_list); | |||||
| bool recursive = false; | |||||
| switch (type) { | switch (type) { | ||||
| case OBJECT_GRPSEL_CHILDREN_RECURSIVE: | case OBJECT_GRPSEL_CHILDREN_RECURSIVE: | ||||
| changed |= select_grouped_children(C, ob, true); | recursive = true; | ||||
| break; | /* fall-through */ | ||||
| case OBJECT_GRPSEL_CHILDREN: | case OBJECT_GRPSEL_CHILDREN: | ||||
| changed |= select_grouped_children(C, ob, false); | if (!active_only) { | ||||
| for (ctx_base = ctx_selected_base_list.first; ctx_base; ctx_base = ctx_base->next) { | |||||
| changed |= select_grouped_children(C, ((Base *)ctx_base->ptr.data)->object, recursive); | |||||
| } | |||||
| } | |||||
| else { | |||||
| changed |= select_grouped_children(C, obact, recursive); | |||||
| } | |||||
| break; | break; | ||||
| case OBJECT_GRPSEL_PARENT: | case OBJECT_GRPSEL_PARENT: | ||||
| changed |= select_grouped_parent(C); | if (!active_only) { | ||||
| for (ctx_base = ctx_selected_base_list.first; ctx_base; ctx_base = ctx_base->next) { | |||||
| changed |= select_grouped_parent(C, ((Base *)ctx_base->ptr.data)->object); | |||||
| } | |||||
| } | |||||
| else { | |||||
| changed |= select_grouped_parent(C, obact); | |||||
| } | |||||
| break; | break; | ||||
| case OBJECT_GRPSEL_SIBLINGS: | case OBJECT_GRPSEL_SIBLINGS: | ||||
| changed |= select_grouped_siblings(C, ob); | if (!active_only) { | ||||
| break; | for (ctx_base = ctx_selected_base_list.first; ctx_base; ctx_base = ctx_base->next) { | ||||
| changed |= select_grouped_siblings(C, ((Base *)ctx_base->ptr.data)->object); | |||||
| } | |||||
| } | |||||
| else { | |||||
| changed |= select_grouped_siblings(C, obact); | |||||
| } break; | |||||
| case OBJECT_GRPSEL_TYPE: | case OBJECT_GRPSEL_TYPE: | ||||
| changed |= select_grouped_type(C, ob); | changed |= select_grouped_type(C, obact); | ||||
| break; | break; | ||||
| case OBJECT_GRPSEL_LAYER: | case OBJECT_GRPSEL_LAYER: | ||||
| changed |= select_grouped_layer(C, ob); | changed |= select_grouped_layer(C, obact); | ||||
| break; | break; | ||||
| case OBJECT_GRPSEL_GROUP: | case OBJECT_GRPSEL_GROUP: | ||||
| changed |= select_grouped_group(C, ob); | if (!active_only) { | ||||
| for (ctx_base = ctx_selected_base_list.first; ctx_base; ctx_base = ctx_base->next) { | |||||
| changed |= select_grouped_group(C, ((Base *)ctx_base->ptr.data)->object); | |||||
| } | |||||
| } | |||||
| else { | |||||
| changed |= select_grouped_group(C, obact); | |||||
Not Done Inline ActionsThis may popup a menu for every object that has multiple groups. Probably better to show a menu with all groups used by the current selection? campbellbarton: This may popup a menu for every object that has multiple groups.
Probably better to show a… | |||||
Not Done Inline ActionsHave not yet looked into the popup menu for the selection by groups, i guess that would be done via uiPopupMenu. Do predefined layouts already exist for the groups or what structs / enums could they be generated from? mangostaniko: Have not yet looked into the popup menu for the selection by groups, i guess that would be done… | |||||
| } | |||||
| break; | break; | ||||
| case OBJECT_GRPSEL_HOOK: | case OBJECT_GRPSEL_HOOK: | ||||
| changed |= select_grouped_object_hooks(C, ob); | changed |= select_grouped_object_hooks(C, obact); | ||||
| break; | break; | ||||
| case OBJECT_GRPSEL_PASS: | case OBJECT_GRPSEL_PASS: | ||||
| changed |= select_grouped_index_object(C, ob); | changed |= select_grouped_index_object(C, obact); | ||||
| break; | break; | ||||
| case OBJECT_GRPSEL_COLOR: | case OBJECT_GRPSEL_COLOR: | ||||
| changed |= select_grouped_color(C, ob); | changed |= select_grouped_color(C, obact); | ||||
| break; | break; | ||||
| case OBJECT_GRPSEL_PROPERTIES: | case OBJECT_GRPSEL_PROPERTIES: | ||||
| changed |= select_grouped_gameprops(C, ob); | changed |= select_grouped_gameprops(C, obact); | ||||
Done Inline ActionsColor and pass could use all objects in the selection. campbellbarton: Color and pass could use all objects in the selection. | |||||
| break; | break; | ||||
| case OBJECT_GRPSEL_KEYINGSET: | case OBJECT_GRPSEL_KEYINGSET: | ||||
| changed |= select_grouped_keyingset(C, ob, op->reports); | changed |= select_grouped_keyingset(C, obact, op->reports); | ||||
| break; | break; | ||||
| case OBJECT_GRPSEL_LAMP_TYPE: | case OBJECT_GRPSEL_LAMP_TYPE: | ||||
| if (ob->type != OB_LAMP) { | if (obact->type != OB_LAMP) { | ||||
| BKE_report(op->reports, RPT_ERROR, "Active object must be a lamp"); | BKE_report(op->reports, RPT_ERROR, "Active object must be a lamp"); | ||||
| break; | break; | ||||
| } | } | ||||
| changed |= select_grouped_lamptype(C, ob); | changed |= select_grouped_lamptype(C, obact); | ||||
| break; | break; | ||||
| default: | default: | ||||
| break; | break; | ||||
| } | } | ||||
| if (extend == 0) { | |||||
| for (ctx_base = ctx_selected_base_list.first; ctx_base; ctx_base = ctx_base->next) { | |||||
Done Inline ActionsLogic in this function could be simplified by making the active-object case a list of one. So: if (!only_active) {
for (ctx_base = ctx_selected_base_list.first; ctx_base; ctx_base = ctx_base->next) {
changed |= ...;
}
}
else {
changed |= ...;
}Can be replaced with: for (ctx_base = ctx_selected_base_list.first; ctx_base; ctx_base = ctx_base->next) {
changed |= ...;
}campbellbarton: Logic in this function could be simplified by making the active-object case a list of one.
So… | |||||
| ED_base_object_select((Base *)ctx_base->ptr.data, BA_DESELECT); | |||||
| changed = true; | |||||
| } | |||||
| } | |||||
| BLI_freelistN(&ctx_selected_base_list); | |||||
Done Inline ActionsDon't think this is correct, since its possible objects from the original selection would have been de-selected, then reselected based on matching properties. Best move this directly below CTX_data_selected_bases(C, &ctx_selected_base_list); campbellbarton: Don't think this is correct, since its possible objects from the original selection would have… | |||||
| if (changed) { | if (changed) { | ||||
| WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); | WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| Context not available. | |||||
| /* properties */ | /* properties */ | ||||
| RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first"); | RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first"); | ||||
| RNA_def_boolean(ot->srna, "active_only", true, "Active Only", "Apply to active object only instead of whole selection"); | |||||
| ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", ""); | ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", ""); | ||||
| } | } | ||||
| Context not available. | |||||
This is no longer correct - when operating on the selection theres no need for an active object.