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/armature/editarmature.c')
-rw-r--r--source/blender/editors/armature/editarmature.c200
1 files changed, 65 insertions, 135 deletions
diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c
index ead5d44d393..c8c0a4e6980 100644
--- a/source/blender/editors/armature/editarmature.c
+++ b/source/blender/editors/armature/editarmature.c
@@ -558,7 +558,7 @@ static void applyarmature_fix_boneparents (Scene *scene, Object *armob)
static int apply_armature_pose2bones_exec (bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_active_object(C); // must be active object, not edit-object
+ Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); // must be active object, not edit-object
bArmature *arm= get_armature(ob);
bPose *pose;
bPoseChannel *pchan;
@@ -655,10 +655,10 @@ void POSE_OT_armature_apply (wmOperatorType *ot)
/* set the current pose as the restpose */
-static int pose_visual_transform_apply_exec (bContext *C, wmOperator *op)
+static int pose_visual_transform_apply_exec (bContext *C, wmOperator *UNUSED(op))
{
Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_active_object(C); // must be active object, not edit-object
+ Object *ob= ED_object_pose_armature(CTX_data_active_object(C)); // must be active object, not edit-object
/* don't check if editmode (should be done by caller) */
if (ob->type!=OB_ARMATURE)
@@ -817,7 +817,7 @@ static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChann
}
/* join armature exec is exported for use in object->join objects operator... */
-int join_armature_exec(bContext *C, wmOperator *op)
+int join_armature_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain= CTX_data_main(C);
Scene *scene= CTX_data_scene(C);
@@ -1075,7 +1075,7 @@ static void separated_armature_fix_links(Object *origArm, Object *newArm)
* sel: remove selected bones from the armature, otherwise the unselected bones are removed
* (ob is not in editmode)
*/
-static void separate_armature_bones (Scene *scene, Object *ob, short sel)
+static void separate_armature_bones(Object *ob, short sel)
{
bArmature *arm= (bArmature *)ob->data;
bPoseChannel *pchan, *pchann;
@@ -1127,7 +1127,7 @@ static void separate_armature_bones (Scene *scene, Object *ob, short sel)
}
/* separate selected bones into their armature */
-static int separate_armature_exec (bContext *C, wmOperator *op)
+static int separate_armature_exec (bContext *C, wmOperator *UNUSED(op))
{
Main *bmain= CTX_data_main(C);
Scene *scene= CTX_data_scene(C);
@@ -1176,8 +1176,8 @@ static int separate_armature_exec (bContext *C, wmOperator *op)
/* 3) remove bones that shouldn't still be around on both armatures */
- separate_armature_bones(scene, oldob, 1);
- separate_armature_bones(scene, newob, 0);
+ separate_armature_bones(oldob, 1);
+ separate_armature_bones(newob, 0);
/* 4) fix links before depsgraph flushes */ // err... or after?
@@ -1389,7 +1389,7 @@ static int pose_setflag_exec (bContext *C, wmOperator *op)
CTX_DATA_END;
/* note, notifier might evolve */
- WM_event_add_notifier(C, NC_OBJECT|ND_POSE, CTX_data_active_object(C));
+ WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ED_object_pose_armature(CTX_data_active_object(C)));
return OPERATOR_FINISHED;
}
@@ -1787,7 +1787,7 @@ EditBone *ED_armature_bone_get_mirrored(ListBase *edbo, EditBone *ebo)
/* previously delete_armature */
/* only editmode! */
-static int armature_delete_selected_exec(bContext *C, wmOperator *op)
+static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
{
bArmature *arm;
EditBone *curBone, *next;
@@ -2087,7 +2087,7 @@ float ED_rollBoneToVector(EditBone *bone, float new_up_axis[3])
/* Set roll value for given bone -> Z-Axis Point up (original method) */
-static void auto_align_ebone_zaxisup(Scene *scene, View3D *v3d, EditBone *ebone)
+static void auto_align_ebone_zaxisup(Scene *UNUSED(scene), View3D *UNUSED(v3d), EditBone *ebone)
{
float delta[3], curmat[3][3];
float xaxis[3]={1.0f, 0.0f, 0.0f}, yaxis[3], zaxis[3]={0.0f, 0.0f, 1.0f};
@@ -2377,7 +2377,7 @@ void add_primitive_bone(Scene *scene, View3D *v3d, RegionView3D *rv3d)
/* previously addvert_armature */
/* the ctrl-click method */
-static int armature_click_extrude_exec(bContext *C, wmOperator *op)
+static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op))
{
View3D *v3d;
bArmature *arm;
@@ -2691,7 +2691,7 @@ EditBone *duplicateEditBone(EditBone *curBone, char *name, ListBase *editbones,
}
/* previously adduplicate_armature */
-static int armature_duplicate_selected_exec(bContext *C, wmOperator *op)
+static int armature_duplicate_selected_exec(bContext *C, wmOperator *UNUSED(op))
{
bArmature *arm;
EditBone *eBone = NULL;
@@ -3262,7 +3262,7 @@ void ARMATURE_OT_merge (wmOperatorType *ot)
/* ************** END Add/Remove stuff in editmode ************ */
/* *************** Tools in editmode *********** */
-static int armature_hide_exec(bContext *C, wmOperator *op)
+static int armature_hide_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *obedit= CTX_data_edit_object(C);
bArmature *arm= obedit->data;
@@ -3302,7 +3302,7 @@ void ARMATURE_OT_hide(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
-static int armature_reveal_exec(bContext *C, wmOperator *op)
+static int armature_reveal_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *obedit= CTX_data_edit_object(C);
bArmature *arm= obedit->data;
@@ -3632,10 +3632,7 @@ static int armature_subdivide_exec(bContext *C, wmOperator *op)
int numcuts, i;
/* there may not be a number_cuts property defined (for 'simple' subdivide) */
- if (RNA_property_is_set(op->ptr, "number_cuts"))
- numcuts= RNA_int_get(op->ptr, "number_cuts");
- else
- numcuts= 1;
+ numcuts= RNA_int_get(op->ptr, "number_cuts");
/* loop over all editable bones */
// XXX the old code did this in reverse order though!
@@ -3690,26 +3687,11 @@ static int armature_subdivide_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-
-void ARMATURE_OT_subdivide_simple(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name= "Subdivide Simple";
- ot->idname= "ARMATURE_OT_subdivide_simple";
-
- /* api callbacks */
- ot->exec = armature_subdivide_exec;
- ot->poll = ED_operator_editarmature;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-}
-
-void ARMATURE_OT_subdivide_multi(wmOperatorType *ot)
+void ARMATURE_OT_subdivide(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Subdivide Multi";
- ot->idname= "ARMATURE_OT_subdivide_multi";
+ ot->idname= "ARMATURE_OT_subdivide";
/* api callbacks */
ot->exec = armature_subdivide_exec;
@@ -3719,65 +3701,7 @@ void ARMATURE_OT_subdivide_multi(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
/* Properties */
- RNA_def_int(ot->srna, "number_cuts", 2, 1, INT_MAX, "Number of Cuts", "", 1, 10);
-}
-
-
-
-static int armature_subdivs_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
- uiPopupMenu *pup;
- uiLayout *layout;
-
- pup= uiPupMenuBegin(C, "Subdivision Type", 0);
- layout= uiPupMenuLayout(pup);
- uiItemsEnumO(layout, "ARMATURE_OT_subdivs", "type");
- uiPupMenuEnd(C, pup);
-
- return OPERATOR_CANCELLED;
-}
-
-static int armature_subdivs_exec(bContext *C, wmOperator *op)
-{
- switch (RNA_int_get(op->ptr, "type"))
- {
- case 0: /* simple */
- RNA_int_set(op->ptr, "number_cuts", 1);
- armature_subdivide_exec(C, op);
- break;
- case 1: /* multi */
- armature_subdivide_exec(C, op);
- break;
- }
-
- return OPERATOR_FINISHED;
-}
-
-void ARMATURE_OT_subdivs(wmOperatorType *ot)
-{
- static EnumPropertyItem type_items[]= {
- {0, "SIMPLE", 0, "Simple", ""},
- {1, "MULTI", 0, "Multi", ""},
- {0, NULL, 0, NULL, NULL}};
-
- /* identifiers */
- ot->name= "subdivs";
- ot->idname= "ARMATURE_OT_subdivs";
-
- /* api callbacks */
- ot->invoke= armature_subdivs_invoke;
- ot->exec= armature_subdivs_exec;
-
- ot->poll= ED_operator_editarmature;
-
- /* flags */
- ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* props */
- RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "");
-
- /* this is temp, the ops are different, but they are called from subdivs, so all the possible props should be here as well*/
- RNA_def_int(ot->srna, "number_cuts", 2, 1, INT_MAX, "Number of Cuts", "", 1, 10);
+ RNA_def_int(ot->srna, "number_cuts", 1, 1, INT_MAX, "Number of Cuts", "", 1, 10);
}
/* ----------- */
@@ -3788,7 +3712,7 @@ void ARMATURE_OT_subdivs(wmOperatorType *ot)
* this to be done easily.
*/
-static int armature_switch_direction_exec(bContext *C, wmOperator *op)
+static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *ob= CTX_data_edit_object(C);
bArmature *arm= (bArmature *)ob->data;
@@ -4009,7 +3933,7 @@ static int armature_parent_set_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int armature_parent_set_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int armature_parent_set_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event))
{
EditBone *actbone = CTX_data_active_bone(C);
uiPopupMenu *pup= uiPupMenuBegin(C, "Make Parent ", 0);
@@ -4106,7 +4030,7 @@ void ARMATURE_OT_parent_clear(wmOperatorType *ot)
/* **************** Selections ******************/
-static int armature_select_inverse_exec(bContext *C, wmOperator *op)
+static int armature_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
{
/* Set the flags */
CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones) {
@@ -4552,7 +4476,7 @@ void ED_pose_deselectall (Object *ob, int test)
arm->act_bone= NULL;
}
-static int bone_skinnable(Object *ob, Bone *bone, void *datap)
+static int bone_skinnable_cb(Object *ob, Bone *bone, void *datap)
{
/* Bones that are deforming
* are regarded to be "skinnable" and are eligible for
@@ -4601,7 +4525,7 @@ static int bone_skinnable(Object *ob, Bone *bone, void *datap)
return 0;
}
-static int ED_vgroup_add_unique_bone(Object *ob, Bone *bone, void *data)
+static int vgroup_add_unique_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
{
/* This group creates a vertex group to ob that has the
* same name as bone (provided the bone is skinnable).
@@ -4616,7 +4540,7 @@ static int ED_vgroup_add_unique_bone(Object *ob, Bone *bone, void *data)
return 0;
}
-static int dgroup_skinnable(Object *ob, Bone *bone, void *datap)
+static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap)
{
/* Bones that are deforming
* are regarded to be "skinnable" and are eligible for
@@ -4672,7 +4596,7 @@ static int dgroup_skinnable(Object *ob, Bone *bone, void *datap)
return 0;
}
-static void add_vgroups__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s)
+static void add_vgroups__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
{
/* DerivedMesh mapFunc for getting final coords in weight paint mode */
@@ -4723,7 +4647,7 @@ static void envelope_bone_weighting(Object *ob, Mesh *mesh, float (*verts)[3], i
}
}
-void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int mirror)
+void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob, Object *par, int heat, int mirror)
{
/* This functions implements the automatic computation of vertex group
* weights, either through envelopes or using a heat equilibrium.
@@ -4755,7 +4679,7 @@ void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int m
looper_data.list= NULL;
/* count the number of skinnable bones */
- numbones = bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable);
+ numbones = bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
if (numbones == 0)
return;
@@ -4764,7 +4688,7 @@ void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int m
* and fill it with all of the skinnable bones */
bonelist = MEM_callocN(numbones*sizeof(Bone *), "bonelist");
looper_data.list= bonelist;
- bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable);
+ bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb);
/* create an array of pointers to the deform groups that
* coorespond to the skinnable bones (creating them
@@ -4773,7 +4697,7 @@ void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int m
dgroupflip = MEM_callocN(numbones*sizeof(bDeformGroup *), "dgroupflip");
looper_data.list= dgrouplist;
- bone_looper(ob, arm->bonebase.first, &looper_data, dgroup_skinnable);
+ bone_looper(ob, arm->bonebase.first, &looper_data, dgroup_skinnable_cb);
/* create an array of root and tip positions transformed into
* global coords */
@@ -4870,14 +4794,22 @@ void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int m
/* compute the weights based on gathered vertices and bones */
if (heat) {
+ const char *error= NULL;
heat_bone_weighting(ob, mesh, verts, numbones, dgrouplist, dgroupflip,
- root, tip, selected);
+ root, tip, selected, &error);
+
+ if(error) {
+ BKE_report(reports, RPT_WARNING, error);
+ }
}
else {
envelope_bone_weighting(ob, mesh, verts, numbones, bonelist, dgrouplist,
dgroupflip, root, tip, selected, mat4_to_scale(par->obmat));
}
-
+
+ /* only generated in some cases but can call anyway */
+ mesh_octree_table(ob, NULL, NULL, 'e');
+
/* free the memory allocated */
MEM_freeN(bonelist);
MEM_freeN(dgrouplist);
@@ -4888,7 +4820,7 @@ void add_verts_to_dgroups(Scene *scene, Object *ob, Object *par, int heat, int m
MEM_freeN(verts);
}
-void create_vgroups_from_armature(Scene *scene, Object *ob, Object *par, int mode, int mirror)
+void create_vgroups_from_armature(ReportList *reports, Scene *scene, Object *ob, Object *par, int mode, int mirror)
{
/* Lets try to create some vertex groups
* based on the bones of the parent armature.
@@ -4899,7 +4831,7 @@ void create_vgroups_from_armature(Scene *scene, Object *ob, Object *par, int mod
/* Traverse the bone list, trying to create empty vertex
* groups cooresponding to the bone.
*/
- bone_looper(ob, arm->bonebase.first, NULL, ED_vgroup_add_unique_bone);
+ bone_looper(ob, arm->bonebase.first, NULL, vgroup_add_unique_bone_cb);
if (ob->type == OB_MESH)
ED_vgroup_data_create(ob->data);
@@ -4909,15 +4841,15 @@ void create_vgroups_from_armature(Scene *scene, Object *ob, Object *par, int mod
* that are populated with the vertices for which the
* bone is closest.
*/
- add_verts_to_dgroups(scene, ob, par, (mode == ARM_GROUPS_AUTO), mirror);
+ add_verts_to_dgroups(reports, scene, ob, par, (mode == ARM_GROUPS_AUTO), mirror);
}
}
/* ************* Clear Pose *****************************/
-static int pose_clear_scale_exec(bContext *C, wmOperator *op)
+static int pose_clear_scale_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_active_object(C);
+ Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
short autokey = 0;
/* only clear those channels that are not locked */
@@ -4956,7 +4888,7 @@ static int pose_clear_scale_exec(bContext *C, wmOperator *op)
/* now recalculate paths */
if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS))
- ED_pose_recalculate_paths(C, scene, ob);
+ ED_pose_recalculate_paths(scene, ob);
}
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
@@ -4982,10 +4914,10 @@ void POSE_OT_scale_clear(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
-static int pose_clear_loc_exec(bContext *C, wmOperator *op)
+static int pose_clear_loc_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_active_object(C);
+ Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
short autokey = 0;
/* only clear those channels that are not locked */
@@ -5025,7 +4957,7 @@ static int pose_clear_loc_exec(bContext *C, wmOperator *op)
/* now recalculate paths */
if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS))
- ED_pose_recalculate_paths(C, scene, ob);
+ ED_pose_recalculate_paths(scene, ob);
}
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
@@ -5051,10 +4983,10 @@ void POSE_OT_loc_clear(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
-static int pose_clear_rot_exec(bContext *C, wmOperator *op)
+static int pose_clear_rot_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene= CTX_data_scene(C);
- Object *ob= CTX_data_active_object(C);
+ Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
short autokey = 0;
/* only clear those channels that are not locked */
@@ -5178,7 +5110,7 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op)
/* now recalculate paths */
if ((ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS))
- ED_pose_recalculate_paths(C, scene, ob);
+ ED_pose_recalculate_paths(scene, ob);
}
DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
@@ -5207,7 +5139,7 @@ void POSE_OT_rot_clear(wmOperatorType *ot)
/* ***************** selections ********************** */
-static int pose_select_inverse_exec(bContext *C, wmOperator *op)
+static int pose_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
{
/* Set the flags */
@@ -5304,9 +5236,9 @@ void POSE_OT_select_all(wmOperatorType *ot)
WM_operator_properties_select_all(ot);
}
-static int pose_select_parent_exec(bContext *C, wmOperator *op)
+static int pose_select_parent_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob= CTX_data_active_object(C);
+ Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
bPoseChannel *pchan,*parent;
/* Determine if there is an active bone */
@@ -5348,7 +5280,7 @@ void POSE_OT_select_parent(wmOperatorType *ot)
/* ************* hide/unhide pose bones ******************* */
-static int hide_selected_pose_bone(Object *ob, Bone *bone, void *ptr)
+static int hide_selected_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
{
bArmature *arm= ob->data;
@@ -5363,7 +5295,7 @@ static int hide_selected_pose_bone(Object *ob, Bone *bone, void *ptr)
return 0;
}
-static int hide_unselected_pose_bone(Object *ob, Bone *bone, void *ptr)
+static int hide_unselected_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
{
bArmature *arm= ob->data;
@@ -5381,15 +5313,13 @@ static int hide_unselected_pose_bone(Object *ob, Bone *bone, void *ptr)
/* active object is armature in posemode, poll checked */
static int pose_hide_exec(bContext *C, wmOperator *op)
{
- Object *ob= CTX_data_active_object(C);
+ Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
bArmature *arm= ob->data;
if(RNA_boolean_get(op->ptr, "unselected"))
- bone_looper(ob, arm->bonebase.first, NULL,
- hide_unselected_pose_bone);
+ bone_looper(ob, arm->bonebase.first, NULL, hide_unselected_pose_bone_cb);
else
- bone_looper(ob, arm->bonebase.first, NULL,
- hide_selected_pose_bone);
+ bone_looper(ob, arm->bonebase.first, NULL, hide_selected_pose_bone_cb);
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
@@ -5414,7 +5344,7 @@ void POSE_OT_hide(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "");
}
-static int show_pose_bone(Object *ob, Bone *bone, void *ptr)
+static int show_pose_bone_cb(Object *ob, Bone *bone, void *UNUSED(ptr))
{
bArmature *arm= ob->data;
@@ -5429,12 +5359,12 @@ static int show_pose_bone(Object *ob, Bone *bone, void *ptr)
}
/* active object is armature in posemode, poll checked */
-static int pose_reveal_exec(bContext *C, wmOperator *op)
+static int pose_reveal_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *ob= CTX_data_active_object(C);
+ Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
bArmature *arm= ob->data;
- bone_looper(ob, arm->bonebase.first, NULL, show_pose_bone);
+ bone_looper(ob, arm->bonebase.first, NULL, show_pose_bone_cb);
/* note, notifier might evolve */
WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
@@ -5626,7 +5556,7 @@ void ED_armature_bone_rename(bArmature *arm, char *oldnamep, char *newnamep)
}
-static int armature_flip_names_exec (bContext *C, wmOperator *op)
+static int armature_flip_names_exec (bContext *C, wmOperator *UNUSED(op))
{
Object *ob= CTX_data_edit_object(C);
bArmature *arm;