Browse Source

move blender script code into functions

master
poikilos 5 years ago
committed by Jacob Gustafson
parent
commit
ee31727094
  1. 340
      utilities/blender/generate_lua_collisionbox.py

340
utilities/blender/generate_lua_collisionbox.py

@ -42,12 +42,14 @@ import bpy
from mathutils import Vector from mathutils import Vector
# from mathutils import Euler # from mathutils import Euler
ob1 = None def calculate_one():
try: ob1 = None
ob1 = obj.select_get() try:
except: ob1 = obj.select_get()
# < 2.8 except:
ob1 = bpy.context.scene.objects.active # < 2.8
ob1 = bpy.context.scene.objects.active
calculate_collisionbox(ob1)
class MessageBox(bpy.types.Operator): class MessageBox(bpy.types.Operator):
@ -79,169 +81,173 @@ bpy.utils.register_class(MessageBox)
msgSuffix = "" msgSuffix = ""
mesh = None def calculate_collisionbox(ob1):
if ob1 is not None: global msgSuffix
mesh = ob1.data mesh = None
if ob1 is not None:
if ob1 is None: mesh = ob1.data
msg = "Nothing is selected."
bpy.ops.message.messagebox('INVOKE_DEFAULT', message = msg) if ob1 is None:
elif (mesh is not None) and (not hasattr(mesh, 'vertices')): msg = "Nothing is selected."
msg = "Collision box for armatures cannot be calculated." bpy.ops.message.messagebox('INVOKE_DEFAULT', message = msg)
bpy.ops.message.messagebox('INVOKE_DEFAULT', message = msg) elif (mesh is not None) and (not hasattr(mesh, 'vertices')):
else: msg = "Collision box for armatures cannot be calculated."
# extents1 = ob1.dimensions.copy() bpy.ops.message.messagebox('INVOKE_DEFAULT', message = msg)
obj1Loc = ob1.location
# See https://blender.stackexchange.com/questions/8459/get-blender-x-y-z-and-bounding-box-with-script
# bbox_corners = [ob1.matrix_world * Vector(corner) for corner in ob1.bound_box]
# See https://blender.stackexchange.com/questions/6139/how-to-iterate-through-all-vertices-of-an-object-that-contains-multiple-meshes
# print("mesh:" + str(mesh))
# print("hasattr(mesh, 'vertices'):"
# + str(hasattr(mesh, 'vertices')))]
mins = [None, None, None] # minimums; in outer scope for checks.
maxes = [None, None, None] # minimums; in outer scope for checks.
if mesh is not None:
wm = ob1.matrix_world
for vert in mesh.vertices:
# This matrix multiplication is NOT transitive.
try:
loc = wm @ vert.co
except TypeError:
loc = wm * vert.co # Blender <2.8
# NOTE: swap y and z for Minetest (y-up) LATER
coords = (loc.x, loc.y, loc.z)
for i in range(3):
if (mins[i] is None) or (coords[i] < mins[i]):
mins[i] = coords[i]
if (maxes[i] is None) or (coords[i] > maxes[i]):
maxes[i] = coords[i]
# print(str(extents1))
# print("--by vertices (raw):")
# print(" collisionbox = {{{:.2f}, {:.2f}, {:.2f}, {:.2f},"
# " {:.2f}, {:.2f}}}".format(mins[0], mins[2], mins[1],
# maxes[0], maxes[2], maxes[1]))
# Use ob1.matrix_world (above) instead of incrementing
# ob1.location.x, y, and z
# newNamePrefix = "Empty.EDGE." + ob1.name
# i = 0
# wm = ob1.matrix_world
# for vert in mesh.vertices:
# newName = newNamePrefix + "." + str(i)
# # This matrix multiplication is NOT transitive.
# try:
# loc = wm @ vert.co
# except TypeError:
# loc = wm * vert.co # Blender <2.8
# isFar = False
# if loc.x == maxes[0] or loc.y == maxes[1] or loc.z == maxes[2]:
# isFar = True
# elif loc.x == mins[0] or loc.y == mins[1] or loc.z == mins[2]:
# isFar = True
# if isFar:
# pass
# # result = bpy.ops.object.add(type='EMPTY', radius=.25,
# # location=loc)
# # NOTE: result is merely {'FINISHED'}
# # print("{:.2f}, {:.2f}, {:.2f}".format(loc.x, loc.y,
# # loc.z))
# bpy.ops.object.add_named(name=newName, type='EMPTY',
# radius=.25, location=loc)
# i += 1
else: else:
extents1 = ob1.scale.copy() # extents1 = ob1.dimensions.copy()
# Object is an empty, so scale up for Minetest obj1Loc = ob1.location
extents1.x = extents1.x * (ob1.empty_draw_size * 2.0)
extents1.y = extents1.y * (ob1.empty_draw_size * 2.0) # See https://blender.stackexchange.com/questions/8459/get-blender-x-y-z-and-bounding-box-with-script
extents1.z = extents1.z * (ob1.empty_draw_size * 2.0) # bbox_corners = [ob1.matrix_world * Vector(corner) for corner in ob1.bound_box]
mins[0] = obj1Loc.x - extents1.x / 2.0
maxes[0] = obj1Loc.x + extents1.x / 2.0
mins[1] = obj1Loc.y - extents1.y / 2.0 # See https://blender.stackexchange.com/questions/6139/how-to-iterate-through-all-vertices-of-an-object-that-contains-multiple-meshes
maxes[1] = obj1Loc.y + extents1.y / 2.0 # print("mesh:" + str(mesh))
mins[2] = obj1Loc.z - extents1.z / 2.0 # print("hasattr(mesh, 'vertices'):"
maxes[2] = obj1Loc.z + extents1.z / 2.0 # + str(hasattr(mesh, 'vertices')))]
msgSuffix = " (using Empty object's scale)" mins = [None, None, None] # minimums; in outer scope for checks.
# print("--using empty object:") maxes = [None, None, None] # minimums; in outer scope for checks.
if mesh is not None:
# use ground as bottom (don't do this--it is not the Minetest way) wm = ob1.matrix_world
# if mins[2] < 0.0: for vert in mesh.vertices:
# maxes[1] -= mins[1] # This matrix multiplication is NOT transitive.
# mins[1] = 0.0 try:
loc = wm @ vert.co
# print(" collisionbox = {{{:.2f}, {:.2f}, {:.2f}, {:.2f}, {:.2f}," except TypeError:
# " {:.2f}}}".format(mins[0], mins[1], mins[2], maxes[0], maxes[1], maxes[2])) loc = wm * vert.co # Blender <2.8
sizes = [None, None, None] # NOTE: swap y and z for Minetest (y-up) LATER
centers = [None, None, None] coords = (loc.x, loc.y, loc.z)
for i in range(3): for i in range(3):
sizes[i] = maxes[i] - mins[i] if (mins[i] is None) or (coords[i] < mins[i]):
centers[i] = mins[i] + sizes[i] / 2.0 mins[i] = coords[i]
if (maxes[i] is None) or (coords[i] > maxes[i]):
if enable_lowest_h: maxes[i] = coords[i]
# OK to use z as up, since will y&z will be swapped if y_up # print(str(extents1))
hSize = None # print("--by vertices (raw):")
for i in range(len(hs)): # print(" collisionbox = {{{:.2f}, {:.2f}, {:.2f}, {:.2f},"
axis_i = hs[i] # " {:.2f}, {:.2f}}}".format(mins[0], mins[2], mins[1],
if (hSize is None) or (sizes[axis_i] < hSize): # maxes[0], maxes[2], maxes[1]))
hSize = sizes[axis_i]
for i in range(len(hs)): # Use ob1.matrix_world (above) instead of incrementing
axis_i = hs[i] # ob1.location.x, y, and z
sizes[axis_i] = hSize
mins[axis_i] = centers[axis_i] - hSize / 2 # newNamePrefix = "Empty.EDGE." + ob1.name
maxes[axis_i] = mins[axis_i] + hSize # i = 0
# wm = ob1.matrix_world
if enable_center_h: # for vert in mesh.vertices:
for i in range(len(hs)): # newName = newNamePrefix + "." + str(i)
axis_i = hs[i] # # This matrix multiplication is NOT transitive.
centers[i] = 0 # try:
mins[axis_i] = centers[axis_i] - sizes[axis_i] / 2 # loc = wm @ vert.co
maxes[axis_i] = mins[axis_i] + sizes[axis_i] # except TypeError:
# loc = wm * vert.co # Blender <2.8
loc = (centers[0], centers[1], centers[2]) # isFar = False
bpy.ops.object.add(type='EMPTY', radius=.5, location=loc) # if loc.x == maxes[0] or loc.y == maxes[1] or loc.z == maxes[2]:
collisionboxName = "Empty.collisionbox." + ob1.name # isFar = True
newEmpty = bpy.context.scene.objects.active # elif loc.x == mins[0] or loc.y == mins[1] or loc.z == mins[2]:
newEmpty.name = collisionboxName # isFar = True
newEmpty.location = (centers[0], centers[1], centers[2]) # if isFar:
newEmpty.empty_draw_type = 'CUBE' # pass
# newEmpty.empty_draw_size = (sizes[0], sizes[1], sizes[2]) # # result = bpy.ops.object.add(type='EMPTY', radius=.25,
# newEmpty.dimensions = (sizes[0], sizes[1], sizes[2]) # # location=loc)
# newEmpty.scale = (sizes[0]/2.0, sizes[1]/2.0, sizes[2]/2.0) # # NOTE: result is merely {'FINISHED'}
newEmpty.scale = (sizes[0], sizes[1], sizes[2]) # # print("{:.2f}, {:.2f}, {:.2f}".format(loc.x, loc.y,
# # loc.z))
if enable_minetest:
# bpy.ops.object.add_named(name=newName, type='EMPTY',
# radius=.25, location=loc)
# i += 1
else:
extents1 = ob1.scale.copy()
# Object is an empty, so scale up for Minetest
extents1.x = extents1.x * (ob1.empty_draw_size * 2.0)
extents1.y = extents1.y * (ob1.empty_draw_size * 2.0)
extents1.z = extents1.z * (ob1.empty_draw_size * 2.0)
mins[0] = obj1Loc.x - extents1.x / 2.0
maxes[0] = obj1Loc.x + extents1.x / 2.0
mins[1] = obj1Loc.y - extents1.y / 2.0
maxes[1] = obj1Loc.y + extents1.y / 2.0
mins[2] = obj1Loc.z - extents1.z / 2.0
maxes[2] = obj1Loc.z + extents1.z / 2.0
msgSuffix = " (using Empty object's scale)"
# print("--using empty object:")
# use ground as bottom (don't do this--it is not the Minetest way)
# if mins[2] < 0.0:
# maxes[1] -= mins[1]
# mins[1] = 0.0
# print(" collisionbox = {{{:.2f}, {:.2f}, {:.2f}, {:.2f}, {:.2f},"
# " {:.2f}}}".format(mins[0], mins[1], mins[2], maxes[0], maxes[1], maxes[2]))
sizes = [None, None, None]
centers = [None, None, None]
for i in range(3): for i in range(3):
mins[i] /= 10.0 sizes[i] = maxes[i] - mins[i]
maxes[i] /= 10.0 centers[i] = mins[i] + sizes[i] / 2.0
msg = ('Size is not available. Make sure you have a mesh object' if enable_lowest_h:
' selected.') # OK to use z as up, since will y&z will be swapped if y_up
hSize = None
if mins[0] is not None: for i in range(len(hs)):
# swap y and z for Minetest (y-up): axis_i = hs[i]
if y_up: if (hSize is None) or (sizes[axis_i] < hSize):
tmp = mins[1] hSize = sizes[axis_i]
mins[1] = mins[2] for i in range(len(hs)):
mins[2] = tmp axis_i = hs[i]
tmp = maxes[1] sizes[axis_i] = hSize
maxes[1] = maxes[2] mins[axis_i] = centers[axis_i] - hSize / 2
maxes[2] = tmp maxes[axis_i] = mins[axis_i] + hSize
msg = (" collisionbox = {{{:.2f}, {:.2f}, {:.2f}, {:.2f},"
" {:.2f}, {:.2f}}}".format(mins[0], mins[1], mins[2], if enable_center_h:
maxes[0], maxes[1], maxes[2])) for i in range(len(hs)):
if len(msgSuffix) > 0: axis_i = hs[i]
msgSuffix = " -- " + msgSuffix centers[i] = 0
bpy.context.window_manager.clipboard = msg + msgSuffix mins[axis_i] = centers[axis_i] - sizes[axis_i] / 2
msg += " --copied to clipboard" maxes[axis_i] = mins[axis_i] + sizes[axis_i]
# if enable_minetest:
# msg += " -- *10" loc = (centers[0], centers[1], centers[2])
print(msg) bpy.ops.object.add(type='EMPTY', radius=.5, location=loc)
collisionboxName = "Empty.collisionbox." + ob1.name
bpy.ops.message.messagebox('INVOKE_DEFAULT', message=msg) newEmpty = bpy.context.scene.objects.active
newEmpty.name = collisionboxName
newEmpty.location = (centers[0], centers[1], centers[2])
newEmpty.empty_draw_type = 'CUBE'
# newEmpty.empty_draw_size = (sizes[0], sizes[1], sizes[2])
# newEmpty.dimensions = (sizes[0], sizes[1], sizes[2])
# newEmpty.scale = (sizes[0]/2.0, sizes[1]/2.0, sizes[2]/2.0)
newEmpty.scale = (sizes[0], sizes[1], sizes[2])
if enable_minetest:
for i in range(3):
mins[i] /= 10.0
maxes[i] /= 10.0
msg = ('Size is not available. Make sure you have a mesh object'
' selected.')
if mins[0] is not None:
# swap y and z for Minetest (y-up):
if y_up:
tmp = mins[1]
mins[1] = mins[2]
mins[2] = tmp
tmp = maxes[1]
maxes[1] = maxes[2]
maxes[2] = tmp
msg = (" collisionbox = {{{:.2f}, {:.2f}, {:.2f}, {:.2f},"
" {:.2f}, {:.2f}}}".format(mins[0], mins[1], mins[2],
maxes[0], maxes[1], maxes[2]))
if len(msgSuffix) > 0:
msgSuffix = " -- " + msgSuffix
bpy.context.window_manager.clipboard = msg + msgSuffix
msg += " --copied to clipboard"
# if enable_minetest:
# msg += " -- *10"
print(msg)
bpy.ops.message.messagebox('INVOKE_DEFAULT', message=msg)
# Unregistering before user clicks the MessageBox will crash Blender! # Unregistering before user clicks the MessageBox will crash Blender!
# bpy.utils.unregister_class(MessageBox) # bpy.utils.unregister_class(MessageBox)
calculate_one()

Loading…
Cancel
Save