Advertisement
Guest User

Untitled

a guest
Apr 23rd, 2017
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 15.69 KB | None | 0 0
  1. import bpy
  2. import bmesh
  3. import math
  4. from mathutils import Vector
  5.  
  6. '''
  7. Copyright (c) 2012 Jorge Hernandez - Melendez
  8. Contributors: Carlos Ruiz Garin
  9. This program is free software: you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation, either version 3 of the License, or
  12. (at your option) any later version.
  13. This program is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. GNU General Public License for more details.
  17. You should have received a copy of the GNU General Public License
  18. along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. '''
  20.  
  21. bl_info = {
  22.     "name": "Chamfer",
  23.     "description": "Similar to 3dmax WorkFlow: LowPoly -> smoothing groups + chamfer + turbosmooth = HightPoly",
  24.     "author": "Jorge Hernandez - Melenedez",
  25.     "version": (1.8),
  26.     "blender": (2, 78),
  27.     "category": "User",
  28.     "location": "Left Toolbar > Chamfer"
  29. }
  30.  
  31. class game_modeling(bpy.types.Panel):
  32.     B = False
  33.     S = False
  34.     bl_label = "Chamfer"
  35.     bl_category = "Chamfer"
  36.     bl_space_type = "VIEW_3D"
  37.     bl_region_type = "TOOLS"
  38.     bl_label = "Game WorkFlow 1.8"
  39.     def draw(self, context):
  40.         layout = self.layout
  41.         ob = bpy.context.active_object
  42.         #
  43.         box = layout.box()
  44.         col = box.column(align=True)
  45.         # col.label(text="Set / Unset bevels:")
  46.         col.operator("add.bevel", text="Add Bevel")
  47.         #
  48.         row = col.row(align=True)
  49.         row.operator("set.edges", text="Edges")
  50.         row.operator("set.faces", text="Faces")
  51.         row.operator("unset.bevel", text="Unset")
  52.         #
  53.         col = col.column(align=True)
  54.         col.operator("add.smooth", text="Add Subsurf")
  55.         #
  56.         row = box.row(align=True)
  57.         row.operator("add.crease", text="Add Crease")
  58.         row.operator("clear.crease", text="Clear Crease")
  59.         #
  60.         box = layout.box()
  61.         col = box.column(align=True)
  62.         row = col.row(align=True)
  63.         # col.label(text="Display:")
  64.         row = col.row(align=True)
  65.         row.operator("object.shade_smooth", text="Smooth")
  66.         row.operator("object.shade_flat", text="Flat")
  67.         col.operator("grid.toggle", text="Hide/Show Grid")
  68.         # col.label(text="Similar to EdgeSplit:")
  69.         # este es mejor que edge split porque no separa los vertices:
  70.         # Similar to EdgeSplit But without detaching vertices:
  71.         mesh = bpy.data.meshes[bpy.context.active_object.name]
  72.         sub1 = col.column()
  73.         sub1.prop(mesh, "use_auto_smooth")
  74.         sub1.active = mesh.use_auto_smooth and not mesh.has_custom_normals
  75.         sub1.prop(mesh, "auto_smooth_angle", text="Angle")
  76.  
  77.         box = layout.box()
  78.         col = box.column(align=True)
  79.         row = col.row(align=True)
  80.         row.prop(context.scene, 'explodeBool')
  81.         row.prop(context.scene, 'explodeDistance')
  82.         row.operator("restore.explode", text="Restore Explode")
  83.         col.prop(context.scene, 'export_obj_path')
  84.         col.operator("export.select", text="Export Selected Objects")
  85.  
  86. # este es el elemento que voy a incluir nuevo en mi ui:
  87. def newElementMenu(self, context):
  88.     ob = bpy.context.active_object
  89.     mod = ob.modifiers["Bevel"]
  90.     if self.B == False:
  91.         self.layout.prop(mod, "width", text="Bevel width")
  92.         self.layout.prop(mod, "segments", text="Bevel segments")
  93.         self.layout.prop(mod, "profile", text="Bevel Outside/Inside")
  94.         self.B = True
  95.  
  96. def newElementMenuSmooth(self, context):
  97.     ob = bpy.context.active_object
  98.     try:
  99.         mod = ob.modifiers["Subsurf"]
  100.     except KeyError:
  101.         pass
  102.     if self.S == False:
  103.         self.layout.prop(mod, "levels", text="Subsurf levels")
  104.         #self.layout.prop(mod, "render_levels", text="Smooth Render levels")
  105.         self.S = True
  106.  
  107. class addBevel(bpy.types.Operator):
  108.     bl_idname = "add.bevel"
  109.     bl_label = "Add Bevel"
  110.     bl_description = "Add Bevel Modifier if not have"
  111.     def execute(self, context):
  112.         ob = bpy.context.active_object
  113.         if "Bevel" not in ob.modifiers:
  114.             bpy.ops.object.modifier_add(type='BEVEL')
  115.             ob.modifiers["Bevel"].width = 0.05
  116.             ob.modifiers["Bevel"].segments = 2
  117.             ob.modifiers["Bevel"].profile = 1
  118.             ob.modifiers["Bevel"].limit_method = 'WEIGHT'
  119.             # Si le ponemos un bevel tambien externalizamos el width para mayor comodidad:
  120.             # bpy.types.game_modeling.prepend(newElementMenu)
  121.             bpy.types.game_modeling.append(newElementMenu)
  122.         else:
  123.             bpy.types.game_modeling.append(newElementMenu)
  124.         return {'FINISHED'}
  125.  
  126. class addSmooth(bpy.types.Operator):
  127.     bl_idname = "add.smooth"
  128.     bl_label = "Add Smooth"
  129.     bl_description = "Add Smooth Modifier if not have"
  130.     def execute(self, context):
  131.         ob = bpy.context.active_object
  132.         if "Bevel" not in ob.modifiers:
  133.             self.report({'WARNING'}, "You need add Bevel first!")
  134.             return {'FINISHED'}
  135.         if "Subsurf" not in ob.modifiers:
  136.             bpy.ops.object.modifier_add(type='SUBSURF')
  137.             ob.modifiers["Subsurf"].levels = 3
  138.             ob.modifiers["Subsurf"].render_levels = 3
  139.             # ob.modifiers["Subsurf"].show_only_control_edges = True
  140.             bpy.types.game_modeling.append(newElementMenuSmooth)
  141.         else:
  142.             bpy.types.game_modeling.append(newElementMenuSmooth)
  143.         return {'FINISHED'}
  144.  
  145. class setBevelE(bpy.types.Operator):
  146.     bl_idname = "set.edges"
  147.     bl_label = "Set to Edges"
  148.     bl_description = "Set to edges weight bevel and sharp"
  149.     def execute(self, context):
  150.         if bpy.context.mode == 'EDIT_MESH':
  151.             ob = bpy.context.active_object
  152.             if "Subsurf" in ob.modifiers:
  153.                 # determinar si solo es un edge loop o un edge o si son caras seleccionadas:
  154.                 me = bpy.context.object.data
  155.                 bm = bmesh.from_edit_mesh(me)
  156.                 edges = []
  157.                 for edge in bm.edges:
  158.                     if edge.select:
  159.                         edges.append(repr(edge.index))
  160.                 if len(edges) < 1 or bpy.context.tool_settings.mesh_select_mode[1] == False: # si son caras (y no son todas las caras del objeto):
  161.                     self.report({'WARNING'}, "This option is only for Edges!")
  162.                     return {'FINISHED'}
  163.                 bpy.ops.transform.edge_bevelweight(value=1)
  164.                 bpy.ops.mesh.mark_sharp()
  165.                 mesh = bpy.data.meshes[ob.name]
  166.                 mesh.use_auto_smooth = True
  167.                 ob.data.auto_smooth_angle = 180
  168.             else:
  169.                 self.report({'WARNING'}, "You need add Subsurf first!")
  170.                 return {'FINISHED'}
  171.         else:
  172.             self.report({'WARNING'}, "This option only work in edit mode!")
  173.         return {'FINISHED'}
  174.  
  175. class setBevelF(bpy.types.Operator):
  176.     bl_idname = "set.faces"
  177.     bl_label = "Set to Faces"
  178.     bl_description = "Set to faces weight bevel and sharp"
  179.     def execute(self, context):
  180.         if bpy.context.mode == 'EDIT_MESH':
  181.             ob = bpy.context.active_object
  182.             if "Subsurf" in ob.modifiers:
  183.                 # determinar si solo es un edge loop o un edge o si son caras seleccionadas:
  184.                 me = bpy.context.object.data
  185.                 bm = bmesh.from_edit_mesh(me)
  186.                 faces = []
  187.                 for face in bm.faces:
  188.                     if face.select:
  189.                         faces.append(repr(face.index))
  190.                 if len(faces) < 1 or bpy.context.tool_settings.mesh_select_mode[2] == False: # si son caras (y no son todas las caras del objeto):
  191.                     self.report({'WARNING'}, "This option is only for Faces!")
  192.                     return {'FINISHED'}
  193.                 if len(faces) != len(bm.faces):
  194.                     bpy.ops.mesh.region_to_loop() # si son caras con esto selecciono solo los contornos
  195.                 bpy.ops.transform.edge_bevelweight(value=1)
  196.                 bpy.ops.mesh.mark_sharp()
  197.                 mesh = bpy.data.meshes[ob.name]
  198.                 mesh.use_auto_smooth = True
  199.                 ob.data.auto_smooth_angle = 180
  200.             else:
  201.                 self.report({'WARNING'}, "You need add Subsurf first!")
  202.                 return {'FINISHED'}
  203.         else:
  204.             self.report({'WARNING'}, "This option only work in edit mode!")
  205.         return {'FINISHED'}
  206.  
  207. class UnsetBevel(bpy.types.Operator):
  208.     bl_idname = "unset.bevel"
  209.     bl_label = "UnSet"
  210.     bl_description = "UnSet weight bevel"
  211.     def execute(self, context):
  212.         if bpy.context.mode == 'EDIT_MESH':
  213.             bpy.ops.transform.edge_bevelweight(value=-1)
  214.             bpy.ops.mesh.mark_sharp(clear=True)
  215.         else:
  216.             self.report({'WARNING'}, "This option only work in edit mode!")
  217.         return {'FINISHED'}
  218.  
  219. class Grid(bpy.types.Operator):
  220.     bl_idname = "grid.toggle"
  221.     bl_label = "grid"
  222.     bl_description = "Hide/Show grid"
  223.     def execute(self, context):
  224.         if bpy.context.space_data.show_floor:
  225.             bpy.context.space_data.show_floor = False
  226.             bpy.context.space_data.show_axis_x = False
  227.             bpy.context.space_data.show_axis_y = False
  228.         else:
  229.             bpy.context.space_data.show_floor = True
  230.             bpy.context.space_data.show_axis_x = True
  231.             bpy.context.space_data.show_axis_y = True
  232.         return {'FINISHED'}
  233.  
  234. class addCrease(bpy.types.Operator):
  235.     bl_idname = "add.crease"
  236.     bl_label = "addcrease"
  237.     bl_description = "Add full hard crease (for example in boundaries)"
  238.     def execute(self, context):
  239.         bpy.ops.transform.edge_crease(value=1)
  240.         return {'FINISHED'}
  241.  
  242. class clearCrease(bpy.types.Operator):
  243.     bl_idname = "clear.crease"
  244.     bl_label = "clearcrease"
  245.     bl_description = "Remove creases"
  246.     def execute(self, context):
  247.         bpy.ops.transform.edge_crease(value=-1)
  248.         return {'FINISHED'}
  249.  
  250. class restoreExplode(bpy.types.Operator):
  251.     bl_idname = "restore.explode"
  252.     bl_label = "restoreExplode"
  253.     bl_description = "Restore initial Explode"
  254.     def execute(self, context):
  255.         for i in bpy.context.scene.originalCoords:
  256.             nombre = i[0]
  257.             x = i[1]
  258.             y = i[2]
  259.             z = i[3]
  260.             bpy.data.objects[nombre].location = (x,y,x)
  261.         bpy.context.scene.E = 0
  262.         bpy.context.scene.originalCoords = []
  263.         return {'FINISHED'}
  264.  
  265.  
  266. def explodeObjects(self, context):
  267.     for area in bpy.context.screen.areas:
  268.         if area.type == 'VIEW_3D':
  269.             ctx = bpy.context.copy()
  270.             ctx['area'] = area
  271.             bpy.ops.view3d.snap_cursor_to_selected(ctx)
  272.             centroid = Vector(bpy.context.scene.cursor_location[:])
  273.  
  274.     for ob in bpy.context.selected_objects:
  275.         if bpy.context.scene.E == 0:
  276.             self.originalCoords.append([ob.name, ob.location.x, ob.location.y, ob.location.z ])
  277.         direccion = ob.location - centroid
  278.         direccion.normalize()
  279.         fuerza = bpy.context.scene.explodeDistance
  280.         ob.location = direccion * fuerza
  281.         bpy.context.scene.E += 1
  282.  
  283.  
  284. class exportSelect(bpy.types.Operator):
  285.     bl_idname = "export.select"
  286.     bl_label = "exportSelect"
  287.     bl_description = "Export Active Object"
  288.     def execute(self, context):
  289.         ob = bpy.context.active_object
  290.         path = bpy.context.scene.export_obj_path
  291.         #path = bpy.path.abspath(bpy.context.scene.export_obj_path)
  292.         if path:
  293.             if path[0:2] != '//':
  294.                 if path[-1] != '/':
  295.                     if path.endswith(('.obj','.fbx','.abc','.dae')):
  296.                         path = path[:-4]
  297.                     if bpy.context.scene.explodeBool:
  298.                         # haciendo el explode y obteniendo las coords originales:
  299.                         explodeObjects()
  300.                         # exportando en baja:
  301.                         bpy.ops.export_scene.obj(filepath=path+"_low.obj", check_existing=True, axis_forward='-Z', axis_up='Y', filter_glob="*.obj;*.mtl", use_selection=True, use_animation=False, use_mesh_modifiers=False, use_edges=True, use_smooth_groups=True, use_smooth_groups_bitflags=False, use_normals=True, use_uvs=True, use_materials=False, use_triangles=False, use_nurbs=False, use_vertex_groups=True, use_blen_objects=True, group_by_object=False, group_by_material=False, keep_vertex_order=False, global_scale=1, path_mode='AUTO')
  302.                         # exportando en alta:
  303.                         bpy.ops.export_scene.obj(filepath=path+"_hight.obj", check_existing=True, axis_forward='-Z', axis_up='Y', filter_glob="*.obj;*.mtl", use_selection=True, use_animation=False, use_mesh_modifiers=True, use_edges=True, use_smooth_groups=True, use_smooth_groups_bitflags=False, use_normals=True, use_uvs=True, use_materials=False, use_triangles=False, use_nurbs=False, use_vertex_groups=True, use_blen_objects=True, group_by_object=False, group_by_material=False, keep_vertex_order=False, global_scale=1, path_mode='AUTO')
  304.                     else:
  305.                         # exportando en baja:
  306.                         bpy.ops.export_scene.obj(filepath=path+"_low.obj", check_existing=True, axis_forward='-Z', axis_up='Y', filter_glob="*.obj;*.mtl", use_selection=True, use_animation=False, use_mesh_modifiers=False, use_edges=True, use_smooth_groups=True, use_smooth_groups_bitflags=False, use_normals=True, use_uvs=True, use_materials=False, use_triangles=False, use_nurbs=False, use_vertex_groups=True, use_blen_objects=True, group_by_object=False, group_by_material=False, keep_vertex_order=False, global_scale=1, path_mode='AUTO')
  307.                         # exportando en alta:
  308.                         bpy.ops.export_scene.obj(filepath=path+"_hight.obj", check_existing=True, axis_forward='-Z', axis_up='Y', filter_glob="*.obj;*.mtl", use_selection=True, use_animation=False, use_mesh_modifiers=True, use_edges=True, use_smooth_groups=True, use_smooth_groups_bitflags=False, use_normals=True, use_uvs=True, use_materials=False, use_triangles=False, use_nurbs=False, use_vertex_groups=True, use_blen_objects=True, group_by_object=False, group_by_material=False, keep_vertex_order=False, global_scale=1, path_mode='AUTO')
  309.                 else:
  310.                     self.report({'WARNING'}, "Bad File Name!")
  311.             else:
  312.                 self.report({'WARNING'}, "Please, Uncheck Relative Path in browser path, before export!")
  313.         else:
  314.             self.report({'WARNING'}, "You need specify one path first!")
  315.         return {'FINISHED'}
  316.  
  317.  
  318. # Registration
  319. def register():
  320.     bpy.utils.register_module(__name__)
  321.     bpy.types.Scene.export_obj_path = bpy.props.StringProperty \
  322.      (
  323.       name = "",
  324.       default = "",
  325.       description = "Export Path: Define the path for export low and hight objs",
  326.       #subtype = 'DIR_PATH'
  327.       subtype = 'FILE_PATH'
  328.       )
  329.     bpy.types.Scene.explodeBool = bpy.props.BoolProperty(name="Explode",description="Explode for better bake",default = False)
  330.     bpy.types.Scene.explodeDistance = bpy.props.FloatProperty(update=explodeObjects, name="Explode Distance", default=1.0, min=1.0, max=30, subtype='FACTOR')
  331.     bpy.types.Scene.originalCoords = []
  332.     bpy.types.Scene.E = bpy.props.IntProperty()
  333.  
  334. def unregister():
  335.     bpy.utils.unregister_module(__name__)
  336.     del bpy.types.Scene.export_obj_path
  337.     del bpy.types.Scene.explodeBool
  338.     del bpy.types.Scene.explodeDistance
  339.     del bpy.types.Scene.originalCoords
  340.     del bpy.types.Scene.E
  341.  
  342. # This allows you to run the script directly from blenders text editor
  343. # to test the addon without having to install it.
  344. if __name__ == "__main__":
  345.     register()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement