You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
6.1 KiB
193 lines
6.1 KiB
5 years ago
|
print("How to use: paste into a Blender Text Editor panel, select object, Run Script")
|
||
|
|
||
|
y_up = True
|
||
|
enable_minetest = False
|
||
|
|
||
|
|
||
|
import bpy
|
||
|
#from mathutils import Matrix
|
||
|
from mathutils import Vector
|
||
|
#from mathutils import Euler
|
||
|
|
||
|
ob1 = None
|
||
|
try:
|
||
|
ob1 = obj.select_get()
|
||
|
except:
|
||
|
# < 2.8
|
||
|
ob1 = bpy.context.scene.objects.active
|
||
|
|
||
|
|
||
|
class MessageBox(bpy.types.Operator):
|
||
|
bl_idname = "message.messagebox"
|
||
|
bl_label = ""
|
||
|
message = bpy.props.StringProperty(
|
||
|
name = "message",
|
||
|
description = "message",
|
||
|
default = ''
|
||
|
)
|
||
|
|
||
|
def execute(self, context):
|
||
|
self.report({'INFO'}, self.message)
|
||
|
print(self.message)
|
||
|
return {'FINISHED'}
|
||
|
|
||
|
def invoke(self, context, event):
|
||
|
return context.window_manager.invoke_props_dialog(self, width = 400)
|
||
|
|
||
|
def draw(self, context):
|
||
|
self.layout.label(self.message)
|
||
|
self.layout.label("")
|
||
|
#col = self.layout.column(align = True)
|
||
|
#col.prop(context.scene, "my_string_prop")
|
||
|
|
||
|
|
||
|
bpy.utils.register_class(MessageBox)
|
||
|
|
||
|
msgSuffix = ""
|
||
|
|
||
|
mesh = None
|
||
|
if ob1 is not None:
|
||
|
mesh = ob1.data
|
||
|
|
||
|
if ob1 is None:
|
||
|
msg = "Nothing is selected."
|
||
|
bpy.ops.message.messagebox('INVOKE_DEFAULT', message = msg)
|
||
|
if (mesh is not None) and (not hasattr(mesh, 'vertices')):
|
||
|
msg = "Collision box for armatures cannot be calculated."
|
||
|
bpy.ops.message.messagebox('INVOKE_DEFAULT', message = msg)
|
||
|
else:
|
||
|
#print(str(thisO))
|
||
|
#extents1 = ob1.dimensions.copy()
|
||
|
#if (extents1.x == 0.0) and (extents1.y == 0.0) and (extents1.z == 0.0) and (ob1.scale.x > 0.0):
|
||
|
#extents1.x = extents1.x / 10.0
|
||
|
#extents1.y = extents1.y / 10.0
|
||
|
#extents1.z = extents1.z / 10.0
|
||
|
obj1Loc = ob1.location
|
||
|
#obj1Loc = ob1.matrix_world.translation
|
||
|
#print(str(extents1))
|
||
|
|
||
|
#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]
|
||
|
|
||
|
|
||
|
#use ground as bottom
|
||
|
#if zMin < 0.0:
|
||
|
# yMax -= yMin
|
||
|
# yMin = 0.0
|
||
|
|
||
|
#print(
|
||
|
# " collisionbox = {{{:.2f}, {:.2f}, {:.2f}, {:.2f}, {:.2f}, {:.2f}}}".format(xMin, yMin, zMin, xMax, yMax, zMax)
|
||
|
#)
|
||
|
|
||
|
#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')))]
|
||
|
xMin = None
|
||
|
if mesh is not None:
|
||
|
xMin = None
|
||
|
yMin = None
|
||
|
zMin = None
|
||
|
xMax = None
|
||
|
yMax = None
|
||
|
zMax = 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
|
||
|
# switch y and z for Minetest (y-up)
|
||
|
if (xMin is None) or (loc.x < xMin):
|
||
|
xMin = loc.x
|
||
|
if (xMax is None) or (loc.x > xMax):
|
||
|
xMax = loc.x
|
||
|
if (yMin is None) or (loc.y < yMin):
|
||
|
yMin = loc.y
|
||
|
if (yMax is None) or (loc.y > yMax):
|
||
|
yMax = loc.y
|
||
|
if (zMin is None) or (loc.z < zMin):
|
||
|
zMin = loc.z
|
||
|
if (zMax is None) or (loc.z > zMax):
|
||
|
zMax = loc.z
|
||
|
# print(str(extents1))
|
||
|
# print("--by vertices (raw):")
|
||
|
# print(
|
||
|
# " collisionbox = {{{:.2f}, {:.2f}, {:.2f}, {:.2f}, {:.2f}, {:.2f}}}".format(xMin, yMin, zMin, xMax, yMax, zMax)
|
||
|
#)
|
||
|
|
||
|
# use ob1.matrix_world instead of incrementing location.
|
||
|
# xMax += ob1.location.x
|
||
|
# xMin += ob1.location.x
|
||
|
# yMax += ob1.location.y
|
||
|
# yMin += ob1.location.y
|
||
|
# zMax += ob1.location.z
|
||
|
# zMin += ob1.location.z
|
||
|
|
||
|
|
||
|
# print("--by vertices:")
|
||
|
newNamePrefix = "Empty.EDGE." + ob1.name
|
||
|
i = 0
|
||
|
wm = ob1.matrix_world
|
||
|
for vert in mesh.vertices:
|
||
|
newName = newNamePrefix + "." + str(i)
|
||
|
try:
|
||
|
loc = mat @ vert.co # NOT transitive
|
||
|
except TypeError:
|
||
|
loc = mat * vert.co # Blender <2.8
|
||
|
isFar = True
|
||
|
if loc.x == xMax or loc.y == yMax or loc.z == zMax:
|
||
|
isFar = True
|
||
|
elif loc.x == xMin or loc.y == yMin or loc.z == zMin:
|
||
|
isFar = True
|
||
|
if isFar:
|
||
|
# 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:
|
||
|
extents1 = ob1.scale.copy()
|
||
|
# Object is an empty, so scale up for Minetest
|
||
|
extents1.x = extents1.x * 2.0
|
||
|
extents1.y = extents1.y * 2.0
|
||
|
extents1.z = extents1.z * 2.0
|
||
|
xMin = obj1Loc.x - extents1.x / 2.0
|
||
|
xMax = obj1Loc.x + extents1.x / 2.0
|
||
|
yMin = obj1Loc.y - extents1.y / 2.0
|
||
|
yMax = obj1Loc.y + extents1.y / 2.0
|
||
|
zMin = obj1Loc.z - extents1.z / 2.0
|
||
|
zMax = obj1Loc.z + extents1.z / 2.0
|
||
|
msgSuffix = " (using Empty object's scale)"
|
||
|
# print("--using empty object:")
|
||
|
#switch y and z for Minetest (y-up):
|
||
|
if enable_minetest:
|
||
|
xMin /= 10.0
|
||
|
xMax /= 10.0
|
||
|
yMin /= 10.0
|
||
|
yMax /= 10.0
|
||
|
zMin /= 10.0
|
||
|
zMax /= 10.0
|
||
|
|
||
|
msg = 'Size is not available. Make sure you have a mesh object selected.'
|
||
|
|
||
|
if xMin is not None:
|
||
|
if y_up:
|
||
|
tmp = yMin
|
||
|
yMin = zMin
|
||
|
zMin = tmp
|
||
|
tmp = yMax
|
||
|
yMax = zMax
|
||
|
zMax = tmp
|
||
|
msg = " collisionbox = {{{:.2f}, {:.2f}, {:.2f}, {:.2f}, {:.2f}, {:.2f}}}".format(xMin, yMin, zMin, xMax, yMax, zMax)
|
||
|
msg += msgSuffix
|
||
|
if enable_minetest:
|
||
|
msg += " #*10"
|
||
|
print(msg)
|
||
|
|
||
|
bpy.ops.message.messagebox('INVOKE_DEFAULT', message = msg)
|
||
|
|
||
|
# Unregistering before user clicks the MessageBox will crash Blender!
|
||
|
# bpy.utils.unregister_class(MessageBox)
|