I have multiple object in blender. There is an object ,lets called it “Obj1” ,which is the object I have to edit.
The model compile process does not allow to change the indices and vert-count (vertex 's ordinal number) of that object “Obj1” during modification,
so I won’t add/delete vertices ,faces ,edges to it during my modification.
All others transform (rotate ,scale ,move) are fine (but of course we can freely do anything with others object).
All faces are triangle.
Here is what I am asking for :
(1)
I want to save those information of “Obj1” into a file (for restore in the future which I describe in the part (2) below):
-The location(x,y,z) of all vertices,and their ordinal numbers (vertex orders)
-The information of all the edges (the edge connect which vertices with which vertices)
-The information of all face (the face was created by which vertices)
-The normal vector is not saved
(2).
After modify the object ,if I want to restore the selected vertices (only restore the selected vertices).
The script will allow me to choose the file to import ,and after importing,it would :
-Restore the selected vertices into position that saved in file
-And also restore the edges/faces that connect to them
-Indices and vert-count are unchanged
zeffii has wrote a script for me ,it works fine.
However if I rotated the edge (by using Mesh => Faces => Rotate Edges) ,
When I restore , this script can’t restore the edge to original.
I really appreciate if somebody can help me to complete it.
Here is the script :
bl_info = {
"name": "CloneRestore",
"author": "Dealga McArdle",
"version": (0, 2),
"blender": (2, 7, 6),
"location": "Object -> Tools -> Misc",
"description": "clones and restores from clone",
"warning": "20 Nov 2015",
"wiki_url": "",
"tracker_url": "",
"category": "3D View"
}
import os
import json
import bpy
from bpy_extras.io_utils import ExportHelper
mode_set = bpy.ops.object.mode_set
def io_import():
ctx = bpy.context
ob, directory = ctx.active_object, ctx.scene.clone_io_directory
full_path = os.path.join(directory, ob.name + '.json')
with open(full_path) as ofile:
text_str = ''.join(ofile.readlines())
my_json = json.loads(text_str)
verts, faces = my_json['verts'], my_json['faces']
mesh = bpy.data.meshes.new(ob.name + "_clone")
mesh.from_pydata(verts, [], faces)
mesh.use_fake_user = True
mesh.update()
def io_export():
ctx = bpy.context
ob, directory = ctx.active_object, ctx.scene.clone_io_directory
full_path = os.path.join(directory, ob.name + '.json')
with open(full_path, 'w') as ofile:
verts = ob.data.vertices
polygons = ob.data.polygons
my_dict = {
'verts': [v.co[:] for v in verts],
'faces': [f.vertices[:] for f in polygons]
}
m = json.dumps(my_dict, sort_keys=True)
ofile.write(m)
def clone():
ob = bpy.context.active_object
mode_set(mode='OBJECT')
clone_mesh = ob.data.copy()
clone_mesh.name = ob.name + '_clone'
clone_mesh.use_fake_user = True
mode_set(mode='EDIT')
def restore():
ob = bpy.context.active_object
mode_set(mode='OBJECT')
clone_mesh = bpy.data.meshes.get(ob.name + '_clone')
clone_verts = clone_mesh.vertices
for v in ob.data.vertices:
if v.select:
v.co = clone_verts[v.index].co
mode_set(mode='EDIT')
def changed():
ob = bpy.context.active_object
bpy.ops.mesh.select_all(action='DESELECT')
mode_set(mode='OBJECT')
clone_mesh = bpy.data.meshes.get(ob.name + '_clone')
clone_verts = clone_mesh.vertices
for v in ob.data.vertices:
if (v.co - clone_verts[v.index].co).length > 0.0001:
v.select = True
mode_set(mode='EDIT')
class ClonedRestoreOpsDirectorySelector(bpy.types.Operator, ExportHelper):
bl_idname = "object.io_folder_selector"
bl_label = "json folder"
filename_ext = "."
use_filter_folder = True
def execute(self, context):
# even if you pick a file i'll strip it and get the dirname
fdir = self.properties.filepath
dp = os.path.dirname(fdir)
context.scene.clone_io_directory = dp
return{'FINISHED'}
class ClonedRestoreOps(bpy.types.Operator):
bl_idname = "object.cloned_restore_op"
bl_label = "Short Name"
fn_name = bpy.props.StringProperty(default='')
def execute(self, context):
if self.fn_name in {'io_import', 'io_export'}:
if not os.path.isdir(context.scene.clone_io_directory):
return {'CANCELLED'}
exec(self.fn_name + '()')
return {'FINISHED'}
class ClonedRestore(bpy.types.Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "Clone Restore Panel"
bl_idname = "OBJECT_PT_clone_restore"
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS'
def draw(self, context):
layout = self.layout
obj = context.object
col = layout.column()
operators = 'clone', 'restore', 'changed'
for op in operators:
ob = context.active_object
if op == 'clone' and ob and (ob.name + '_clone' in bpy.data.meshes):
col.label('cloned as: ' + ob.name + '_clone')
else:
col.operator("object.cloned_restore_op", text=op).fn_name = op
scn = context.scene
col.label('I / O')
row = col.row(align=True)
row.prop(scn, 'clone_io_directory', text='directory:')
row.operator("object.io_folder_selector", icon="FILE_FOLDER", text="")
col.operator("object.cloned_restore_op", text='import').fn_name = 'io_import'
col.operator("object.cloned_restore_op", text='export').fn_name = 'io_export'
def register():
bpy.types.Scene.clone_io_directory = bpy.props.StringProperty()
bpy.utils.register_module(__name__)
def unregister():
bpy.utils.unregister_module(__name__)
del bpy.types.Scene.clone_io_directory
if __name__ == "__main__":
register()
Thanks
P/S : Here 's what zeffi describe about his script (if anybody interested) :
You can either pick a directory using the selector or paste it in manually. Even if you pick a file from the FileBrowser it will strip the path to just be a Folder/Directory.
It appears in the Misc panel:
If you have the Suzanne Object selected it can clone the object and make a hidden mesh, or look in the directory provided for a Suzanne.json, which it can load as the clone mesh.
- clone: Clones the Object’s mesh as a hidden mesh called <object_name>_clone
- restore: Restores the locations of the vertices currently selected
- changed: Selects only those vertices which changed their locations
- import: Tries to import a hidden mesh. The currently selected object’s name is used to find the json: directory/<object_name>.json
- export: Makes a <object_name>.json in the directory pointed at.