From 28a84a2c3a204bfab21541df0d6a78d718248f42 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 27 Feb 2013 23:34:29 +0000 Subject: Code Maintenance - Splitting up Armature/Pose Editing Files This commit splits editarmature.c and poseobject.c into several files, such that certain types of functionality are (mostly) self-contained within particular files (instead of being mixed in with other functionality in a large file). In particular, this was done so that: 1) Armature EditMode tools are now in the armature_*.c files only, and Pose Mode tools in pose_*.c files only. - In one or two cases, this hasn't been possible as the two modes rely on much of the same shared infrastructure. 2) The "clear loc/rot/scale" operators and pose show/hide are no longer housed in editarmature.c 3) Selection operators, Transform operators, structural (add/delete) operators, and supporting utilities for the modes (enter/exit/roll-calculations) are not all interleaved in an ad-hoc manner Notes: * I've tried to ensure that the history of the new files has been maintained by doing svn copy {editarmature.c/poseobject.c} {armature_*.c/pose_*.c} Unfortunately, this means that the diffs are a bit messy. * There should be no functional/logic changes here. Just code moving around and cosmetic comment tweaks where needed. * #includes have largely been untouched for now, but could be cleaned up later * CMake changes untested, but should work in theory. --- source/blender/editors/armature/armature_naming.c | 395 ++++++++++++++++++++++ 1 file changed, 395 insertions(+) create mode 100644 source/blender/editors/armature/armature_naming.c (limited to 'source/blender/editors/armature/armature_naming.c') diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c new file mode 100644 index 00000000000..db2eba8556d --- /dev/null +++ b/source/blender/editors/armature/armature_naming.c @@ -0,0 +1,395 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * 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. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): Blender Foundation, 2002-2009 full recode. + * + * ***** END GPL LICENSE BLOCK ***** + * + * Operators and API's for renaming bones both in and out of Edit Mode + */ + +/** \file blender/editors/armature/armature_naming.c + * \ingroup edarmature + */ + + +#include +#include +#include +#include +#include +#include + + +#include "DNA_anim_types.h" +#include "DNA_armature_types.h" +#include "DNA_constraint_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_modifier_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" +#include "BLI_ghash.h" + +#include "BKE_animsys.h" +#include "BKE_action.h" +#include "BKE_armature.h" +#include "BKE_constraint.h" +#include "BKE_context.h" +#include "BKE_deform.h" +#include "BKE_depsgraph.h" +#include "BKE_DerivedMesh.h" +#include "BKE_global.h" +#include "BKE_idprop.h" +#include "BKE_main.h" +#include "BKE_object.h" +#include "BKE_report.h" +#include "BKE_modifier.h" + +#include "BIF_gl.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_armature.h" +#include "ED_keyframing.h" +#include "ED_object.h" +#include "ED_screen.h" +#include "ED_util.h" +#include "ED_view3d.h" + +#include "UI_interface.h" +#include "UI_resources.h" + +#include "armature_intern.h" + +/* This file contains functions/API's for renaming bones and/or working with them */ + +/* ************************************************** */ +/* EditBone Names */ + +/* checks if an EditBone with a matching name already, returning the matching bone if it exists */ +EditBone *editbone_name_exists(ListBase *edbo, const char *name) +{ + return BLI_findstring(edbo, name, offsetof(EditBone, name)); +} + +/* note: there's a unique_bone_name() too! */ +static int editbone_unique_check(void *arg, const char *name) +{ + struct {ListBase *lb; void *bone; } *data = arg; + EditBone *dupli = editbone_name_exists(data->lb, name); + return dupli && dupli != data->bone; +} + +void unique_editbone_name(ListBase *edbo, char *name, EditBone *bone) +{ + struct {ListBase *lb; void *bone; } data; + data.lb = edbo; + data.bone = bone; + + BLI_uniquename_cb(editbone_unique_check, &data, "Bone", '.', name, sizeof(bone->name)); +} + +/* ************************************************** */ +/* Bone Renaming - API */ + +static int bone_unique_check(void *arg, const char *name) +{ + return BKE_armature_find_bone_name((bArmature *)arg, name) != NULL; +} + +static void unique_bone_name(bArmature *arm, char *name) +{ + BLI_uniquename_cb(bone_unique_check, (void *)arm, "Bone", '.', name, sizeof(((Bone *)NULL)->name)); +} + +/* helper call for armature_bone_rename */ +static void constraint_bone_name_fix(Object *ob, ListBase *conlist, char *oldname, char *newname) +{ + bConstraint *curcon; + bConstraintTarget *ct; + + for (curcon = conlist->first; curcon; curcon = curcon->next) { + bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(curcon); + ListBase targets = {NULL, NULL}; + + if (cti && cti->get_constraint_targets) { + cti->get_constraint_targets(curcon, &targets); + + for (ct = targets.first; ct; ct = ct->next) { + if (ct->tar == ob) { + if (!strcmp(ct->subtarget, oldname) ) + BLI_strncpy(ct->subtarget, newname, MAXBONENAME); + } + } + + if (cti->flush_constraint_targets) + cti->flush_constraint_targets(curcon, &targets, 0); + } + } +} + +/* called by UI for renaming a bone */ +/* warning: make sure the original bone was not renamed yet! */ +/* seems messy, but thats what you get with not using pointers but channel names :) */ +void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *newnamep) +{ + Object *ob; + char newname[MAXBONENAME]; + char oldname[MAXBONENAME]; + + /* names better differ! */ + if (strncmp(oldnamep, newnamep, MAXBONENAME)) { + + /* we alter newname string... so make copy */ + BLI_strncpy(newname, newnamep, MAXBONENAME); + /* we use oldname for search... so make copy */ + BLI_strncpy(oldname, oldnamep, MAXBONENAME); + + /* now check if we're in editmode, we need to find the unique name */ + if (arm->edbo) { + EditBone *eBone = editbone_name_exists(arm->edbo, oldname); + + if (eBone) { + unique_editbone_name(arm->edbo, newname, NULL); + BLI_strncpy(eBone->name, newname, MAXBONENAME); + } + else return; + } + else { + Bone *bone = BKE_armature_find_bone_name(arm, oldname); + + if (bone) { + unique_bone_name(arm, newname); + BLI_strncpy(bone->name, newname, MAXBONENAME); + } + else return; + } + + /* do entire dbase - objects */ + for (ob = G.main->object.first; ob; ob = ob->id.next) { + ModifierData *md; + + /* we have the object using the armature */ + if (arm == ob->data) { + Object *cob; + + /* Rename the pose channel, if it exists */ + if (ob->pose) { + bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, oldname); + if (pchan) { + BLI_strncpy(pchan->name, newname, MAXBONENAME); + + if (ob->pose->chanhash) { + GHash *gh = ob->pose->chanhash; + + /* remove the old hash entry, and replace with the new name */ + BLI_ghash_remove(gh, oldname, NULL, NULL); + BLI_ghash_insert(gh, pchan->name, pchan); + } + } + } + + /* Update any object constraints to use the new bone name */ + for (cob = G.main->object.first; cob; cob = cob->id.next) { + if (cob->constraints.first) + constraint_bone_name_fix(ob, &cob->constraints, oldname, newname); + if (cob->pose) { + bPoseChannel *pchan; + for (pchan = cob->pose->chanbase.first; pchan; pchan = pchan->next) { + constraint_bone_name_fix(ob, &pchan->constraints, oldname, newname); + } + } + } + } + + /* See if an object is parented to this armature */ + if (ob->parent && (ob->parent->data == arm)) { + if (ob->partype == PARBONE) { + /* bone name in object */ + if (!strcmp(ob->parsubstr, oldname)) + BLI_strncpy(ob->parsubstr, newname, MAXBONENAME); + } + } + + if (modifiers_usesArmature(ob, arm)) { + bDeformGroup *dg = defgroup_find_name(ob, oldname); + if (dg) { + BLI_strncpy(dg->name, newname, MAXBONENAME); + } + } + + /* fix modifiers that might be using this name */ + for (md = ob->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_Hook) { + HookModifierData *hmd = (HookModifierData *)md; + + /* uses armature, so may use the affected bone name */ + if (hmd->object && (hmd->object->data == arm)) { + if (!strcmp(hmd->subtarget, oldname)) + BLI_strncpy(hmd->subtarget, newname, MAXBONENAME); + } + } + } + } + + /* Fix all animdata that may refer to this bone - we can't just do the ones attached to objects, since + * other ID-blocks may have drivers referring to this bone [#29822] + */ + { + + BKE_all_animdata_fix_paths_rename(&arm->id, "pose.bones", oldname, newname); + } + + /* correct view locking */ + { + bScreen *screen; + for (screen = G.main->screen.first; screen; screen = screen->id.next) { + ScrArea *sa; + /* add regions */ + for (sa = screen->areabase.first; sa; sa = sa->next) { + SpaceLink *sl; + for (sl = sa->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_VIEW3D) { + View3D *v3d = (View3D *)sl; + if (v3d->ob_centre && v3d->ob_centre->data == arm) { + if (!strcmp(v3d->ob_centre_bone, oldname)) { + BLI_strncpy(v3d->ob_centre_bone, newname, MAXBONENAME); + } + } + } + } + } + } + } + } +} + +/* ************************************************** */ +/* Bone Renaming - EditMode */ + +static int armature_flip_names_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = CTX_data_edit_object(C); + bArmature *arm; + char newname[MAXBONENAME]; + + /* paranoia checks */ + if (ELEM(NULL, ob, ob->pose)) + return OPERATOR_CANCELLED; + arm = ob->data; + + /* loop through selected bones, auto-naming them */ + CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) + { + flip_side_name(newname, ebone->name, TRUE); // 1 = do strip off number extensions + ED_armature_bone_rename(arm, ebone->name, newname); + } + CTX_DATA_END; + + /* since we renamed stuff... */ + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + + /* note, notifier might evolve */ + WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); + + return OPERATOR_FINISHED; +} + +void ARMATURE_OT_flip_names(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Flip Names"; + ot->idname = "ARMATURE_OT_flip_names"; + ot->description = "Flips (and corrects) the axis suffixes of the names of selected bones"; + + /* api callbacks */ + ot->exec = armature_flip_names_exec; + ot->poll = ED_operator_editarmature; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + + +static int armature_autoside_names_exec(bContext *C, wmOperator *op) +{ + Object *ob = CTX_data_edit_object(C); + bArmature *arm; + char newname[MAXBONENAME]; + short axis = RNA_enum_get(op->ptr, "type"); + + /* paranoia checks */ + if (ELEM(NULL, ob, ob->pose)) + return OPERATOR_CANCELLED; + arm = ob->data; + + /* loop through selected bones, auto-naming them */ + CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) + { + BLI_strncpy(newname, ebone->name, sizeof(newname)); + if (bone_autoside_name(newname, 1, axis, ebone->head[axis], ebone->tail[axis])) + ED_armature_bone_rename(arm, ebone->name, newname); + } + CTX_DATA_END; + + /* since we renamed stuff... */ + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + + /* note, notifier might evolve */ + WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); + + return OPERATOR_FINISHED; +} + +void ARMATURE_OT_autoside_names(wmOperatorType *ot) +{ + static EnumPropertyItem axis_items[] = { + {0, "XAXIS", 0, "X-Axis", "Left/Right"}, + {1, "YAXIS", 0, "Y-Axis", "Front/Back"}, + {2, "ZAXIS", 0, "Z-Axis", "Top/Bottom"}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name = "AutoName by Axis"; + ot->idname = "ARMATURE_OT_autoside_names"; + ot->description = "Automatically renames the selected bones according to which side of the target axis they fall on"; + + /* api callbacks */ + ot->invoke = WM_menu_invoke; + ot->exec = armature_autoside_names_exec; + ot->poll = ED_operator_editarmature; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* settings */ + ot->prop = RNA_def_enum(ot->srna, "type", axis_items, 0, "Axis", "Axis tag names with"); +} + -- cgit v1.2.3