Ejemplo n.º 1
0
    def execute(self, context):
        obj = context.active_object
        root = mmd_model.Model.findRoot(obj)
        if root:
            bpy.ops.mmd_tools.clear_temp_materials()
            bpy.ops.mmd_tools.clear_uv_morph_view()
        if root:
            # Store the current material names
            rig = mmd_model.Model(root)
            mat_names = [getattr(mat, 'name', None) for mat in rig.materials()]
        utils.separateByMaterials(obj)
        if self.clean_shape_keys:
            bpy.ops.mmd_tools.clean_shape_keys()
        if root:
            rig = mmd_model.Model(root)
            # The material morphs store the name of the mesh, not of the object.
            # So they will not be out of sync
            for mesh in rig.meshes():
                FnMorph.clean_uv_morph_vertex_groups(mesh)
                if len(mesh.data.materials) > 0:
                    mat = mesh.data.materials[0]
                    idx = mat_names.index(getattr(mat, 'name', None))
                    MoveObject.set_index(mesh, idx)

        if root and len(root.mmd_root.material_morphs) > 0:
            for morph in root.mmd_root.material_morphs:
                mo = FnMorph(morph, mmd_model.Model(root))
                mo.update_mat_related_mesh()
        utils.clearUnusedMeshes()
        return {'FINISHED'}
Ejemplo n.º 2
0
    def execute(self, context):
        obj = context.active_object
        root = mmd_model.Model.findRoot(obj)
        mmd_root = root.mmd_root
        morph_type = mmd_root.active_morph_type
        morph = ItemOp.get_by_index(getattr(mmd_root, morph_type),
                                    mmd_root.active_morph)
        if morph is None:
            return {'CANCELLED'}

        if morph_type.startswith('material'):
            bpy.ops.mmd_tools.clear_temp_materials()

        if self.all:
            if morph_type.startswith('vertex'):
                for obj in mmd_model.Model(root).meshes():
                    FnMorph.remove_shape_key(obj, morph.name)
                return {'FINISHED'}
            elif morph_type.startswith('uv'):
                if morph.data_type == 'VERTEX_GROUP':
                    for obj in mmd_model.Model(root).meshes():
                        FnMorph.store_uv_morph_data(obj, morph)
                    return {'FINISHED'}
            morph.data.clear()
            morph.active_data = 0
        else:
            morph.data.remove(morph.active_data)
            morph.active_data = max(0, morph.active_data - 1)
        return {'FINISHED'}
Ejemplo n.º 3
0
    def execute(self, context):
        obj = context.active_object
        root = mmd_model.Model.findRoot(obj)
        mmd_root = root.mmd_root

        morph_type = mmd_root.active_morph_type
        morphs = getattr(mmd_root, morph_type)
        morph = ItemOp.get_by_index(morphs, mmd_root.active_morph)
        if morph is None:
            return {'CANCELLED'}

        name_orig, name_tmp = morph.name, '_tmp%s' % str(morph.as_pointer())

        if morph_type.startswith('vertex'):
            for obj in mmd_model.Model(root).meshes():
                FnMorph.copy_shape_key(obj, name_orig, name_tmp)

        elif morph_type.startswith('uv'):
            if morph.data_type == 'VERTEX_GROUP':
                for obj in mmd_model.Model(root).meshes():
                    FnMorph.copy_uv_morph_vertex_groups(
                        obj, name_orig, name_tmp)

        morph_new, mmd_root.active_morph = ItemOp.add_after(
            morphs, mmd_root.active_morph)
        for k, v in morph.items():
            morph_new[k] = v if k != 'name' else name_tmp
        morph_new.name = name_orig + '_copy'  # trigger name check
        return {'FINISHED'}
Ejemplo n.º 4
0
    def execute(self, context):
        obj = context.active_object
        root = mmd_model.Model.findRoot(obj)
        rig = mmd_model.Model(root)
        for meshObj in rig.meshes():
            mats_to_delete = []
            for mat in meshObj.data.materials:
                if "_temp" in mat.name:
                    mats_to_delete.append(mat)
            for temp_mat in mats_to_delete:
                base_mat_name = temp_mat.name[0:-1 * len("_temp")]
                base_idx = meshObj.data.materials.find(base_mat_name)
                temp_idx = meshObj.data.materials.find(temp_mat.name)
                for poly in meshObj.data.polygons:
                    if poly.material_index == temp_idx:
                        if base_idx == -1:
                            self.report(
                                {'ERROR'},
                                'Warning! base material for %s was not found' %
                                temp_mat.name)
                        else:
                            poly.material_index = base_idx
                if base_idx != -1:
                    mat = meshObj.data.materials.pop(index=temp_idx)
                    bpy.data.materials.remove(mat)

        return {'FINISHED'}
Ejemplo n.º 5
0
    def execute(self, context):
        obj = context.active_object
        root = mmd_model.Model.findRoot(obj)
        rig = mmd_model.Model(root)
        mmd_root = root.mmd_root
        meshObj = None
        for i in rig.meshes():
            meshObj = i
            break
        if meshObj is None:
            self.report({'ERROR'}, "The model mesh can't be found")
            return {'CANCELLED'}
        morph = mmd_root.material_morphs[mmd_root.active_morph]
        mat_data = morph.data[morph.active_material_data]
        base_mat = meshObj.data.materials[mat_data.material]
        work_mat_name = base_mat.name + "_temp"
        if work_mat_name in meshObj.data.materials.keys():
            work_mat = meshObj.data.materials[work_mat_name]
            base_idx = meshObj.data.materials.find(base_mat.name)
            copy_idx = meshObj.data.materials.find(work_mat.name)

            for poly in meshObj.data.polygons:
                if poly.material_index == copy_idx:
                    poly.material_index = base_idx

            mat = meshObj.data.materials.pop(index=copy_idx)
            bpy.data.materials.remove(mat)
        morph.data.remove(morph.active_material_data)
        morph.active_material_data -= 1
        return {'FINISHED'}
Ejemplo n.º 6
0
    def execute(self, context):
        obj = context.active_object
        root = mmd_model.Model.findRoot(obj)
        rig = mmd_model.Model(root)
        mmd_root = root.mmd_root
        meshObj = None
        for i in rig.meshes():
            meshObj = i
            break
        if meshObj is None:
            self.report({'ERROR'}, "The model mesh can't be found")
            return {'CANCELLED'}
        with bpyutils.select_object(meshObj) as data:
            if meshObj.data.shape_keys is None:
                bpy.ops.object.shape_key_add()
            data.shape_key_add(self.name_j)
        idx = len(meshObj.data.shape_keys.key_blocks) - 1
        meshObj.active_shape_key_index = idx
        vtx_morph = mmd_root.vertex_morphs.add()
        vtx_morph.name = self.name_j
        vtx_morph.name_e = self.name_e
        vtx_morph.category = self.category
        mmd_root.active_morph = len(mmd_root.vertex_morphs) - 1

        frame = mmd_root.display_item_frames[u'表情']
        item = frame.items.add()
        item.name = vtx_morph.name
        item.type = 'MORPH'
        item.morph_category = self.category

        return {'FINISHED'}
    def execute(self, context):
        obj = context.active_object
        root = mmd_model.Model.findRoot(obj)
        rig = mmd_model.Model(root)
        mmd_root = rig.rootObject().mmd_root
        joint = rig.createJoint(
            name='Joint',
            name_e='Joint_e',
            location=[0, 0, 0],
            rotation=[0, 0, 0],
            size=0.5 * mmd_root.scale,
            rigid_a=None,
            rigid_b=None,
            maximum_location=[0, 0, 0],
            minimum_location=[0, 0, 0],
            maximum_rotation=[0, 0, 0],
            minimum_rotation=[0, 0, 0],
            spring_linear=[0, 0, 0],
            spring_angular=[0, 0, 0],
        )
        if mmd_root.show_joints:
            joint.hide = False
            utils.selectAObject(joint)
        else:
            joint.hide = True
            utils.selectAObject(obj)

        if 'mmd_tools.' + mmd_root.name + '_all' in bpy.data.groups.keys(
        ):  # Add Joint to allGroup
            bpy.data.groups['mmd_tools.' + mmd_root.name + '_all'].link(joint)
        if 'mmd_tools.' + mmd_root.name + '_joints' in bpy.data.groups.keys(
        ):  # Add Joint to joints group
            bpy.data.groups['mmd_tools.' + mmd_root.name +
                            '_joints'].link(joint)
        return {'FINISHED'}
Ejemplo n.º 8
0
 def execute(self, context):
     obj = context.active_object
     root = mmd_model.Model.findRoot(obj)
     rig = mmd_model.Model(root)
     mmd_root = root.mmd_root
     meshObj = None
     for i in rig.meshes():
         meshObj = i
         break
     if meshObj is None:
         self.report({ 'ERROR' }, "The model mesh can't be found")
         return { 'CANCELLED' }
     # Let's create a temporary material to edit the offset
     orig_mat = meshObj.active_material
     if "_temp" in orig_mat.name:
         self.report({ 'ERROR' }, 'This material is not valid as a base material')
         return { 'CANCELLED' }
     if orig_mat.name+"_temp" in meshObj.data.materials.keys():
         self.report({ 'ERROR' }, 'Another offset is using this Material, apply it first')
         return { 'CANCELLED' }                    
     copy_mat = orig_mat.copy()
     copy_mat.name = orig_mat.name+"_temp"
     meshObj.data.materials.append(copy_mat)
     orig_idx = meshObj.active_material_index
     copy_idx = meshObj.data.materials.find(copy_mat.name)
     
     for poly in meshObj.data.polygons:
         if poly.material_index == orig_idx:
             poly.material_index = copy_idx
         
     morph = mmd_root.material_morphs[mmd_root.active_morph]
     mat_data = morph.data.add()
     mat_data.material = orig_mat.name
     return { 'FINISHED' }
Ejemplo n.º 9
0
 def execute(self, context):
     obj = context.active_object
     root = mmd_model.Model.findRoot(context.active_object)
     rig = mmd_model.Model(root)
     rig.build()
     context.view_layer.objects.active = obj
     return {'FINISHED'}
Ejemplo n.º 10
0
    def execute(self, context):
        try:
            self.__translator = DictionaryEnum.get_translator(self.dictionary)
        except Exception as e:
            self.report({'ERROR'}, 'Failed to load dictionary: %s' % e)
            return {'CANCELLED'}

        obj = context.active_object
        root = mmd_model.Model.findRoot(obj)
        rig = mmd_model.Model(root)

        if 'MMD' in self.modes:
            for i in self.types:
                getattr(self, 'translate_%s' % i.lower())(rig)

        if 'BLENDER' in self.modes:
            self.translate_blender_names(rig)

        translator = self.__translator
        txt = translator.save_fails()
        if translator.fails:
            self.report(
                {'WARNING'},
                "Failed to translate %d names, see '%s' in text editor" %
                (len(translator.fails), txt.name))
        return {'FINISHED'}
Ejemplo n.º 11
0
    def execute(self, context):
        root = mmd_model.Model.findRoot(context.active_object)
        if root is None:
            self.report({'ERROR'}, 'Select a MMD model')
            return {'CANCELLED'}

        rig = mmd_model.Model(root)
        armObj = rig.armature()
        if armObj is None:
            self.report({'ERROR'}, 'Model Armature not found')
            return {'CANCELLED'}

        def __get_root(mesh):
            if mesh.parent is None:
                return mesh
            return __get_root(mesh.parent)

        meshes_list = (o for o in context.visible_objects
                       if o.type == 'MESH' and o.mmd_type == 'NONE')
        for mesh in meshes_list:
            if mmd_model.Model.findRoot(mesh) is not None:
                # Do not attach meshes from other models
                continue
            mesh = __get_root(mesh)
            m = mesh.matrix_world
            mesh.parent_type = 'OBJECT'
            mesh.parent = armObj
            mesh.matrix_world = m
        return {'FINISHED'}
Ejemplo n.º 12
0
    def execute(self, context):
        obj = context.active_object
        root = mmd_model.Model.findRoot(obj)
        if root is None:
            self.report({'ERROR'}, "The model root can't be found")
            return {'CANCELLED'}

        rig = mmd_model.Model(root)
        selection = set(rig.rigidBodies())

        for prop_name in self.properties:
            prop_value = getattr(obj.mmd_rigid, prop_name)
            if prop_name == 'collision_group_mask':
                prop_value = tuple(prop_value)
                for i in selection.copy():
                    if tuple(i.mmd_rigid.collision_group_mask) != prop_value:
                        selection.remove(i)
                        if self.hide_others:
                            i.select = False
                            i.hide = True
            else:
                for i in selection.copy():
                    if getattr(i.mmd_rigid, prop_name) != prop_value:
                        selection.remove(i)
                        if self.hide_others:
                            i.select = False
                            i.hide = True

        for i in selection:
            i.hide = False
            i.select = True

        return {'FINISHED'}
Ejemplo n.º 13
0
    def execute(self, context):
        obj = context.active_object
        root = mmd_model.Model.findRoot(obj)
        rig = mmd_model.Model(root)

        arm = rig.armature()
        bone_map = {}
        for i in context.selected_objects:
            if mmd_model.isRigidBodyObject(i):
                bone_map[i] = arm.data.bones.get(i.mmd_rigid.bone, None)

        if len(bone_map) < 2:
            self.report({'ERROR'},
                        "Please select two or more mmd rigid objects")
            return {'CANCELLED'}

        utils.selectAObject(root)
        root.select = False
        if context.scene.rigidbody_world is None:
            bpy.ops.rigidbody.world_add()

        for pair in self.__enumerate_rigid_pair(bone_map):
            joint = self.__add_joint(rig, pair, bone_map)
            joint.select = True

        return {'FINISHED'}
Ejemplo n.º 14
0
    def execute(self, context):
        params = {
            'filepath': self.filepath,
            'scale': self.scale,
            'pose_type': self.pose_type,
            'use_pose_mode': self.use_pose_mode,
        }

        obj = context.active_object
        if obj.mmd_type == 'ROOT':
            rig = mmd_model.Model(obj)
            params['mesh'] = rig.morph_slider.placeholder(
                binded=True) or rig.firstMesh()
            params['armature'] = rig.armature()
            params['model_name'] = obj.mmd_root.name or obj.name
        elif getattr(obj.data, 'shape_keys', None):
            params['mesh'] = obj
            params['model_name'] = obj.name
        elif obj.type == 'ARMATURE':
            params['armature'] = obj
            params['model_name'] = obj.name

        try:
            vpd_exporter.VPDExporter().export(**params)
        except Exception as e:
            err_msg = traceback.format_exc()
            logging.error(err_msg)
            self.report({'ERROR'}, err_msg)
        return {'FINISHED'}
Ejemplo n.º 15
0
    def execute(self, context):
        selected_objects = set(context.selected_objects)
        for i in frozenset(selected_objects):
            root = mmd_model.Model.findRoot(i)
            if root == i:
                rig = mmd_model.Model(root)
                selected_objects.add(rig.armature())
                selected_objects.add(rig.morph_slider.placeholder())
                selected_objects |= set(rig.meshes())

        bone_mapper = None
        if self.bone_mapper == 'PMX':
            bone_mapper = makePmxBoneMap
        elif self.bone_mapper == 'RENAMED_BONES':
            bone_mapper = vmd_importer.RenamedBoneMapper(
                rename_LR_bones=self.rename_bones,
                use_underscore=self.use_underscore,
                translator=DictionaryEnum.get_translator(self.dictionary),
            ).init

        for f in self.files:
            importer = vpd_importer.VPDImporter(
                filepath=os.path.join(self.directory, f.name),
                scale=self.scale,
                bone_mapper=bone_mapper,
                use_pose_mode=self.use_pose_mode,
            )
            for i in selected_objects:
                importer.assign(i)
        return {'FINISHED'}
Ejemplo n.º 16
0
    def execute(self, context):
        obj = context.active_object
        root = mmd_model.Model.findRoot(obj)
        rig = mmd_model.Model(root)
        mmd_root = root.mmd_root

        try:
            bpy.ops.object.mode_set(mode='OBJECT')
        except Exception:
            pass

        arm = rig.armature()
        for i in context.scene.objects:
            i.select_set(False)
        arm.hide_set(False)
        arm.select_set(True)
        context.view_layer.objects.active = arm

        bpy.ops.object.mode_set(mode='POSE')
        frame = mmd_root.display_item_frames[
            mmd_root.active_display_item_frame]
        item = frame.items[frame.active_item]
        bone_name = item.name
        for i in arm.pose.bones:
            i.bone.select_set(i.name == bone_name)
        return {'FINISHED'}
Ejemplo n.º 17
0
 def execute(self, context):
     obj = context.active_object
     root = mmd_model.Model.findRoot(obj)
     rig = mmd_model.Model(root)
     rig.applyAdditionalTransformConstraints()
     SceneOp(context).active_object = obj
     return {'FINISHED'}
Ejemplo n.º 18
0
def bakePhysics(self,context,start,end,step):
    root = mmd_model.Model.findRoot(context.active_object)
    if(root==None):
        self.report({'INFO'}, 'Not a MMD armature!')
    if(not root.mmd_root.is_built):
        self.report({'INFO'}, 'Physics is not built!')
        raise MMDPhysicsError('Physics Error')
        
    rig = mmd_model.Model(root)
    arm = rig.armature()
    rigidbodyGroup=[]
    boneGroup=[]
    rigidbodyGroup=rig.rigidBodies()
    bpy.ops.object.posemode_toggle()
    for rb in rigidbodyGroup:
        print(rb)
        boneGroup.append(rb.mmd_rigid.bone)
        bpy.ops.object.mode_set(mode='POSE')
        pbone=arm.data.bones.get(rb.mmd_rigid.bone, None)
        if(int(rb.mmd_rigid.type)==1 or int(rb.mmd_rigid.type)==2):
            pbone.select=True
    
    #bake it
    bpy.ops.nla.bake(frame_start=start \
    , frame_end=end \
    , step=step \
    , only_selected=True \
    , visual_keying=True \
    , clear_constraints=True \
    , clear_parents=False \
    , use_current_action=True \
    , bake_types={'POSE'})
    return { 'FINISHED' }
Ejemplo n.º 19
0
    def execute(self, context):
        obj = context.active_object
        root = mmd_model.Model.findRoot(obj)
        rig = mmd_model.Model(root)
        mmd_root = root.mmd_root
        items_map = {
            "MATMORPH": "material_morphs",
            "BONEMORPH": "bone_morphs",
            "VTXMORPH": "vertex_morphs"
        }
        attr_name = items_map[mmd_root.active_morph_type]
        items = getattr(mmd_root, attr_name)
        if mmd_root.active_morph >= 0 and mmd_root.active_morph < len(items):
            active_morph = items[mmd_root.active_morph]
            if attr_name == "vertex_morphs":
                for meshObj in rig.meshes():
                    with bpyutils.select_object(meshObj) as m:
                        if m.data.shape_keys is not None:
                            i = m.data.shape_keys.key_blocks.find(
                                active_morph.name)
                            m.active_shape_key_index = i
                            bpy.ops.object.shape_key_remove()

            facial_frame = mmd_root.display_item_frames[u'表情']
            idx = facial_frame.items.find(active_morph.name)
            if facial_frame.active_item == idx:
                facial_frame.active_item -= 1
            facial_frame.items.remove(idx)
            items.remove(mmd_root.active_morph)
            mmd_root.active_morph -= 1

        return {'FINISHED'}
Ejemplo n.º 20
0
    def execute(self, context):
        obj = context.active_object
        root = mmd_model.Model.findRoot(obj)
        rig = mmd_model.Model(root)
        for m in rig.meshes():
            mesh = m.data
            uv_textures = getattr(mesh, 'uv_textures', mesh.uv_layers)
            for t in uv_textures:
                if t.name.startswith('__uv.'):
                    uv_textures.remove(t)
            if len(uv_textures) > 0:
                uv_textures[0].active_render = True
                uv_textures.active_index = 0

            animation_data = mesh.animation_data
            if animation_data:
                nla_tracks = animation_data.nla_tracks
                for t in nla_tracks:
                    if t.name.startswith('__uv.'):
                        nla_tracks.remove(t)
                if animation_data.action and animation_data.action.name.startswith(
                        '__uv.'):
                    animation_data.action = None
                if animation_data.action is None and len(nla_tracks) == 0:
                    mesh.animation_data_clear()

        for act in bpy.data.actions:
            if act.name.startswith('__uv.') and act.users < 1:
                bpy.data.actions.remove(act)
        return {'FINISHED'}
Ejemplo n.º 21
0
    def execute(self, context):
        logger = logging.getLogger()
        logger.setLevel(self.log_level)
        if self.save_log:
            handler = log_handler(self.log_level,
                                  filepath=self.filepath +
                                  '.mmd_tools.export.log')
        else:
            handler = log_handler(self.log_level)
        logger.addHandler(handler)

        root = mmd_model.Model.findRoot(context.active_object)
        rig = mmd_model.Model(root)
        rig.clean()
        try:
            pmx_exporter.export(
                filepath=self.filepath,
                scale=root.mmd_root.scale,
                root=rig.rootObject(),
                armature=rig.armature(),
                meshes=rig.meshes(),
                rigid_bodies=rig.rigidBodies(),
                joints=rig.joints(),
                copy_textures=self.copy_textures,
            )
        finally:
            logger.removeHandler(handler)

        return {'FINISHED'}
Ejemplo n.º 22
0
    def draw(self, context):
        active_obj = context.active_object
        root = None
        if active_obj:
            root = mmd_model.Model.findRoot(active_obj)
        if root is None:
            c = self.layout.column()
            c.label(text='Select a MMD Model')
            return

        rig = mmd_model.Model(root)
        root = rig.rootObject()
        mmd_root = root.mmd_root

        col = self.layout.column()
        c = col.column(align=True)

        row = c.row()
        row.template_list(
            "UL_joints",
            "",
            context.scene,
            "objects",
            mmd_root,
            'active_joint_index',
        )
        tb = row.column()
        tb1 = tb.column(align=True)
        tb1.operator(operators.rigid_body.AddJoint.bl_idname,
                     text='',
                     icon='ZOOM_IN')
        tb1.operator(operators.rigid_body.RemoveJoint.bl_idname,
                     text='',
                     icon='ZOOM_OUT')
Ejemplo n.º 23
0
 def execute(self, context):
     obj = context.active_object
     root = mmd_model.Model.findRoot(obj)
     rig = mmd_model.Model(root)
     armature = rig.armature()
     for p_bone in armature.pose.bones:
         p_bone.matrix_basis.identity()
     return {'FINISHED'}
Ejemplo n.º 24
0
def _toggleVisibilityOfTemporaryObjects(self, context):
    root = self.id_data
    rig = mmd_model.Model(root)
    hide = not self.show_temporary_objects
    for i in rig.temporaryObjects(rigid_track_only=True):
        i.hide = hide
    if hide and context.active_object is None:
        SceneOp(context).active_object = root
Ejemplo n.º 25
0
def _toggleVisibilityOfJoints(self, context):
    root = self.id_data
    rig = mmd_model.Model(root)
    hide = not self.show_joints
    for i in rig.joints():
        i.hide = hide
    if hide and context.active_object is None:
        SceneOp(context).active_object = root
Ejemplo n.º 26
0
def _toggleUseSDEF(self, context):
    root = self.id_data
    rig = mmd_model.Model(root)
    mute_sdef = not self.use_sdef
    for i in rig.meshes():
        if FnSDEF.SHAPEKEY_NAME in getattr(i.data.shape_keys, 'key_blocks',
                                           ()):
            i.data.shape_keys.key_blocks[FnSDEF.SHAPEKEY_NAME].mute = mute_sdef
Ejemplo n.º 27
0
def _setActiveRigidbodyObject(prop, v):
    obj = bpy.context.scene.objects[v]
    root = prop.id_data
    rig = mmd_model.Model(root)
    for i in rig.rigidBodies():
        i.hide = False
    if not obj.hide:
        utils.selectAObject(obj)
    prop['active_rigidbody_object_index'] = v
Ejemplo n.º 28
0
def _setActiveJointObject(prop, v):
    obj = bpy.context.scene.objects[v]
    root = prop.id_data
    rig = mmd_model.Model(root)
    for i in rig.joints():
        i.hide = False
    if not obj.hide:
        utils.selectAObject(obj)
    prop['active_joint_object_index'] = v
Ejemplo n.º 29
0
def _toggleUseSphereTexture(self, context):
    root = self.id_data
    rig = mmd_model.Model(root)
    use_sphere = self.use_sphere_texture
    for i in rig.meshes():
        for m in i.data.materials:
            if m is None:
                continue
            FnMaterial(m).use_sphere_texture(use_sphere, i)
Ejemplo n.º 30
0
def _setVisibilityOfMMDRigArmature(prop, v):
    obj = prop.id_data
    rig = mmd_model.Model(obj)
    arm = rig.armature()
    if arm is None:
        return
    if bpy.context.active_object == arm:
        SceneOp(bpy.context).active_object = obj
    arm.hide = not v