############################################################################################################ # # Copyright (c) 2012 Kofi Garbrah # # Provided under The MIT License http://opensource.org/licenses/mit-license.php # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Description: # This blender add-on finds the lowest point on the selected object(s) and aligns that lowest point # to the ground plane (y = 0 in most 3D software; z = 0 in blender) while maintaining relationships # between selected objects. # # 1) Imports and Global variables # 2) Model # 3) View (Panel) # 4) Controller (button) # ############################################################################################################ bl_info = { "name": "Bring 2 Floor", "author": "Kofi Garbrah", "version": (2,0), "blender": (2, 63, 0), "location": "View3D > Properties > Bring2Floor", "description": "Brings the selected item to the floor. Moves attached items as well.", "warning": "", "wiki_url": "http://www.4colorgrafix.net/bpy#B2F", "tracker_url": "http://www.4colorgrafix.net/bpy#B2F", "category": "System"} # # 1) Imports and Global variables # import bpy from bpy.props import * import math from math import * from mathutils import * from mathutils import Vector from mathutils import Matrix import time ############################################################################################################ # # 2) Model # class Drop2FloorModel: # # Set location to the ground. # def drop( self, context): print( "\n\nSet mesh location to the ground" ) maxY = float("-inf") minY = float("inf") i = 0 # Set orientation of figure bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) # find highest point and lowest point in the selected meshes for obj in context.selected_objects: if obj.type == "MESH": for v in obj.data.vertices: vec = self.transpose_yz( v.co ) y = vec[1] if maxY < y: maxY = y if minY > y: minY = y # Drop figure to ground for obj in context.selected_objects: if obj.type == "MESH": old_loc = self.transpose_yz( obj.location ) obj.location = old_loc - self.transpose_yz( Vector( (0.0, minY, 0.0) ) ) bpy.ops.object.transform_apply(location=True, rotation=False, scale=False) # # Transposes Y-axis with Z-axis. # # In most 3d software, the Z-axis represents depth not height. For example # look at ZBrush, Silo, Maya, Cinema4D, and OpenGL. Also look up the terms # Z-Buffering and Z-Culling. # # Blender uses the Z-axis to represent height on the screen but the camera in # Blender uses the Z-axis to represent depth for rendering. This routine # compensates for Blender's quirk. # def transpose_yz( self, v ): return Vector( (v[0], v[2], v[1] ) ) ############################################################################################################ # # 3) View # d2f = Drop2FloorModel() # Panel class Drop2FloorView(bpy.types.Panel): """Creates a Panel in the VIEW 3D UI""" bl_idname = "Drop 2 Floor" bl_label = "Bring 2 Floor" bl_space_type = "VIEW_3D" bl_region_type = "UI" bl_context = "object" # Draws layout for Panel def draw(self, context): layout = self.layout if len(context.selected_objects) > 0: row = layout.row() row.alignment = "EXPAND" row.operator("drop2floor.button", text="Bring Selected Figures To Floor") ############################################################################################################ # # 4) Controller # # Button class Drop2FloorController(bpy.types.Operator): bl_idname = "drop2floor.button" bl_label = "D2F Button" def execute(self, context): time_start = time.time() d2f.drop(context) print("Execution time: {:.4} sec".format(time.time() - time_start) ) return{'FINISHED'} # Registration def register(): bpy.utils.register_module(__name__) def unregister(): bpy.utils.unregister_module(__name__) if __name__ == '__main__': register()