Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 129 additions & 39 deletions MultiEdit_05.py → __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,22 @@

bl_info = {
"name": "MultiEdit",
"author": "Antonis Karvelas",
"version": (0, 5),
"author": "Antonis Karvelas, Dimitris Chloupis",
"version": (1, 0),
"blender": (2, 7, 8),
"location": "VIEW 3D > Tools > Multiple Objects Editing ",
"description": "Allows you to edit multiple objects together in edit mode without destroying data",
"warning": "Alpha Version 0.5, maybe has a few problems...",
"description": "Allows you to edit multiple objects together in edit mode without destroying data.",
"warning": "Could still have a few issues, be careful.",
"wiki_url": "",
"tracker_url": "",
"category": "Mesh"}

#Imports:
import bpy
import math
from mathutils import Vector
from bpy.props import FloatVectorProperty
import time

#Create a list to put the names of the selected objects:
name_list = []
Expand All @@ -44,6 +47,7 @@
#Create a dictionary to put the parents
parents_list = {}


class MultiEdit_Enter(bpy.types.Operator):
bl_label = "MultiEdit Enter"
bl_idname = "objects.multiedit_enter_operator"
Expand Down Expand Up @@ -127,8 +131,8 @@ def Create_Vertex_Groups(self, object):
###Create the necessary vertex groups:###
bpy.context.scene.objects.active = object
for vertex_group in object.vertex_groups:
special_vgroups_list.append(vertex_group.name)
special_vgroups_list.append(vertex_group.name)

#Create vertex groups containting all the vertices:
object.vertex_groups.new(object.name)
vertex_group = object.vertex_groups[-1]
Expand Down Expand Up @@ -168,22 +172,6 @@ def Duplicate_Object(self, scene, name, old_object):
#Link new object to the given scene and select it
scene.objects.link(ob_new)

#Copy all the modifiers:
for mod in old_object.modifiers:
mod_new = ob_new.modifiers.new(mod.name, mod.type)
properties = [p.identifier for p in mod.bl_rna.properties
if not p.is_readonly]
for prop in properties:
setattr(mod_new, prop, getattr(mod, prop))

#Copy all the constraints:
for constr in old_object.constraints:
constr_new = ob_new.constraints.new(constr.type)
properties = [p.identifier for p in constr.bl_rna.properties
if not p.is_readonly]
for prop in properties:
setattr(constr_new, prop, getattr(constr, prop))

#Copy all the vertex groups:
for vertex_g in old_object.vertex_groups:
vert_g_new = ob_new.vertex_groups.new(vertex_g.name)
Expand All @@ -196,12 +184,29 @@ def Duplicate_Object(self, scene, name, old_object):
for group in old_object.users_group:
bpy.context.scene.objects.active = ob_new
bpy.ops.object.group_link(group=group.name)

#Copy parent object value
try:
parents_list[old_object.name] = (old_object.parent).name
except:
pass

#Copy all the modifiers:
for mod in old_object.modifiers:
mod_new = ob_new.modifiers.new(mod.name, mod.type)
properties = [p.identifier for p in mod.bl_rna.properties
if not p.is_readonly]
for prop in properties:
setattr(mod_new, prop, getattr(mod, prop))

#Copy all the constraints:
for constr in old_object.constraints:
constr_new = ob_new.constraints.new(constr.type)
properties = [p.identifier for p in constr.bl_rna.properties
if not p.is_readonly]
for prop in properties:
setattr(constr_new, prop, getattr(constr, prop))

#Finally, return the new object:
return ob_new

Expand Down Expand Up @@ -288,7 +293,7 @@ def Fix_Objects(self, active_object, name, vgroup_index):
existing_vg.append(object.vertex_groups[vgroup_index].name)

vgroup_index += 1

#RENAME OBJECTS, ORGANIZES MATERIALS
if len(existing_vg) < 2 and len(existing_vg) > 0:
# try:
Expand Down Expand Up @@ -320,7 +325,7 @@ def Fix_Objects(self, active_object, name, vgroup_index):

#Call the Copy_Data function:
self.Copy_Data(wanted_object_name, object)

else:
object.name = "New Geometry"

Expand All @@ -334,10 +339,9 @@ def Fix_Objects(self, active_object, name, vgroup_index):
bpy.ops.object.hide_view_clear()

#Delete duplicated objects
bpy.ops.object.select_all(action="SELECT")
for obj in bpy.context.selected_objects:
if "dupl" not in obj.name:
obj.select = False
obj.hide = True
bpy.ops.object.delete()

#Empty lists for future use
Expand Down Expand Up @@ -373,14 +377,14 @@ def Copy_Data(self, wanted_object_name, object):
for group in bpy.data.objects[wanted_object_name].users_group:
bpy.context.scene.objects.active = object
bpy.ops.object.group_link(group=group.name)

#Delete unnecessary vertex groups:
for vg in object.vertex_groups:
if vg.name in bpy.data.objects[(duplicated_list[(name_list.index(object.name))])].vertex_groups:
pass
else:
object.vertex_groups.remove(vg)
object.vertex_groups.remove(vg)

#Copy constraints:
for constr in bpy.data.objects[wanted_object_name].constraints:
constr_new = object.constraints.new(constr.type)
Expand Down Expand Up @@ -459,7 +463,7 @@ def Preserve_Data(self):

else:
pass

else:
for obj in bpy.data.objects:
for nam in name_list:
Expand All @@ -475,8 +479,8 @@ def Preserve_Data(self):

else:
pass
#A function to preserve an object's parent:

#A function to preserve an object's parent:
def Preserve_Parents(self, obj):
try:
obj.parent = bpy.data.objects[parents_list[obj.name]]
Expand Down Expand Up @@ -534,21 +538,98 @@ def Clear_New_Geometry_Data(self, obj_name):
main_object.data.materials.pop()


"""
This Operator is modal and checks automatically if it should enter or exit
MultiEdit mode
"""


class MultiEditModal(bpy.types.Operator):
"""Translate the view using mouse events"""

bl_label = "MultiEdit mode start"
bl_idname = "objects.multieditmodal"
bl_context = "editmode"
multiEditMode= False
editingObjects =[]
timeLapse = 0

def execute(self, context):
pass
return

def modal(self, context, event):



# do not check anything if the mouse cursor is not in Viewport
if context.space_data.type == 'VIEW_3D':

# check every one second
if time.time() > self.timeLapse + 0.3:
self.timeLapse = round(time.time())
self.editingObjects = []

for obj in bpy.data.objects:

if obj.mode == 'EDIT' and bpy.context.scene.multi_edit_enable:
self.editingObjects.append(obj)

# if in edit mode and multiple selected enter MultiEdit mode
if obj.select and len(
self.editingObjects) > 0 and self.multiEditMode == False and bpy.context.scene.multi_edit_enable:
self.editingObjects.append(obj)
self.multiEditMode = True
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.objects.multiedit_enter_operator()

# if in object mode , no objects selected and MulitEditMode previously
# enabled , then exit MultiEdit mode
if len(self.editingObjects) == 0 and self.multiEditMode:
self.multiEditMode = False
bpy.ops.objects.multiedit_exit_operator()




# do not capture any key or mouse event
return {'PASS_THROUGH'}

def invoke(self, context, event):

if context.space_data.type == 'VIEW_3D':
v3d = context.space_data
rv3d = v3d.region_3d



context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
else:
self.report({'WARNING'}, "Active space must be a View3d")
return {'CANCELLED'}



# Main Panel for MultiEdit mode
class MultiEdit_Panel(bpy.types.Panel):
bl_label = "Multiple Objects Editing"
bl_idname = "MultiEdit"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
bl_category = "Tools"
first_draw=True

def draw(self, context):
layout = self.layout
sce = bpy.context.scene
layout = self.layout
sce = bpy.context.scene

layout.operator(MultiEdit_Enter.bl_idname)
layout.operator(MultiEdit_Exit.bl_idname)
layout.operator(MultiEditModal.bl_idname)
layout.prop(sce, "Preserve_Location_Rotation_Scale", toggle=True, icon='ROTATE')
layout.prop(sce, "multi_edit_enable",toggle=True,icon='EDIT')

layout.operator(MultiEdit_Enter.bl_idname)
layout.operator(MultiEdit_Exit.bl_idname)
layout.prop(sce, "Preserve_Location_Rotation_Scale")

def register():
bpy.utils.register_class(MultiEdit_Enter)
Expand All @@ -560,11 +641,20 @@ def register():
description = "Preserve the Location/Rotation/Scale values of the objects.",
default = True
)
# Is MultiEdit enabled
bpy.types.Scene.multi_edit_enable = bpy.props.BoolProperty \
(
name = "Enable Multi Edit mode",
description = "Can automatically detect if multiple objects are selected and edit them together.",
default = True
)
bpy.utils.register_class(MultiEditModal)

def unregister():
bpy.utils.unregister_class(MultiEdit_Enter);
bpy.utils.unregister_class(MultiEdit_Exit);
bpy.utils.unregister_class(MultiEdit_Panel);
bpy.utils.unregister_class(MultiEditModal)

if __name__ == "__main__":
register()
register()