|
@ -2,8 +2,19 @@ print("How to use: paste into a Blender Text Editor panel, select" |
|
|
" object, Run Script") |
|
|
" object, Run Script") |
|
|
|
|
|
|
|
|
y_up = True |
|
|
y_up = True |
|
|
enable_minetest = False |
|
|
enable_minetest = True |
|
|
|
|
|
enable_lowest_h = False |
|
|
|
|
|
enable_center_h = False |
|
|
|
|
|
if enable_minetest: |
|
|
|
|
|
enable_lowest_h = True |
|
|
|
|
|
enable_center_h = True |
|
|
|
|
|
|
|
|
|
|
|
hs = (0, 1) # horizontal axis indices |
|
|
|
|
|
v = 2 # vertical axis index |
|
|
|
|
|
# Do NOT swap until end. |
|
|
|
|
|
#if y_up: |
|
|
|
|
|
# hs = (0, 2) |
|
|
|
|
|
# v = 1 |
|
|
|
|
|
|
|
|
import bpy |
|
|
import bpy |
|
|
# from mathutils import Matrix |
|
|
# from mathutils import Matrix |
|
@ -54,7 +65,7 @@ if ob1 is not None: |
|
|
if ob1 is None: |
|
|
if ob1 is None: |
|
|
msg = "Nothing is selected." |
|
|
msg = "Nothing is selected." |
|
|
bpy.ops.message.messagebox('INVOKE_DEFAULT', message = msg) |
|
|
bpy.ops.message.messagebox('INVOKE_DEFAULT', message = msg) |
|
|
if (mesh is not None) and (not hasattr(mesh, 'vertices')): |
|
|
elif (mesh is not None) and (not hasattr(mesh, 'vertices')): |
|
|
msg = "Collision box for armatures cannot be calculated." |
|
|
msg = "Collision box for armatures cannot be calculated." |
|
|
bpy.ops.message.messagebox('INVOKE_DEFAULT', message = msg) |
|
|
bpy.ops.message.messagebox('INVOKE_DEFAULT', message = msg) |
|
|
else: |
|
|
else: |
|
@ -64,26 +75,14 @@ else: |
|
|
# See https://blender.stackexchange.com/questions/8459/get-blender-x-y-z-and-bounding-box-with-script |
|
|
# 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] |
|
|
# bbox_corners = [ob1.matrix_world * Vector(corner) for corner in ob1.bound_box] |
|
|
|
|
|
|
|
|
# use ground as bottom (don't do this--it is not the Minetest way) |
|
|
|
|
|
# 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 |
|
|
# 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("mesh:" + str(mesh)) |
|
|
# print("hasattr(mesh, 'vertices'):" |
|
|
# print("hasattr(mesh, 'vertices'):" |
|
|
# + str(hasattr(mesh, 'vertices')))] |
|
|
# + str(hasattr(mesh, 'vertices')))] |
|
|
xMin = None # Define so None check is possible later. |
|
|
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: |
|
|
if mesh is not None: |
|
|
xMin = None |
|
|
|
|
|
yMin = None |
|
|
|
|
|
zMin = None |
|
|
|
|
|
xMax = None |
|
|
|
|
|
yMax = None |
|
|
|
|
|
zMax = None |
|
|
|
|
|
wm = ob1.matrix_world |
|
|
wm = ob1.matrix_world |
|
|
for vert in mesh.vertices: |
|
|
for vert in mesh.vertices: |
|
|
# This matrix multiplication is NOT transitive. |
|
|
# This matrix multiplication is NOT transitive. |
|
@ -91,24 +90,18 @@ else: |
|
|
loc = wm @ vert.co |
|
|
loc = wm @ vert.co |
|
|
except TypeError: |
|
|
except TypeError: |
|
|
loc = wm * vert.co # Blender <2.8 |
|
|
loc = wm * vert.co # Blender <2.8 |
|
|
# switch y and z for Minetest (y-up) |
|
|
# NOTE: swap y and z for Minetest (y-up) LATER |
|
|
if (xMin is None) or (loc.x < xMin): |
|
|
coords = (loc.x, loc.y, loc.z) |
|
|
xMin = loc.x |
|
|
for i in range(3): |
|
|
if (xMax is None) or (loc.x > xMax): |
|
|
if (mins[i] is None) or (coords[i] < mins[i]): |
|
|
xMax = loc.x |
|
|
mins[i] = coords[i] |
|
|
if (yMin is None) or (loc.y < yMin): |
|
|
if (maxes[i] is None) or (coords[i] > maxes[i]): |
|
|
yMin = loc.y |
|
|
maxes[i] = coords[i] |
|
|
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(str(extents1)) |
|
|
# print("--by vertices (raw):") |
|
|
# print("--by vertices (raw):") |
|
|
print(" collisionbox = {{{:.2f}, {:.2f}, {:.2f}, {:.2f}," |
|
|
# print(" collisionbox = {{{:.2f}, {:.2f}, {:.2f}, {:.2f}," |
|
|
" {:.2f}, {:.2f}}}".format(xMin, yMin, zMin, xMax, yMax, |
|
|
# " {:.2f}, {:.2f}}}".format(mins[0], mins[2], mins[1], |
|
|
zMax)) |
|
|
# maxes[0], maxes[2], maxes[1])) |
|
|
|
|
|
|
|
|
# Use ob1.matrix_world (above) instead of incrementing |
|
|
# Use ob1.matrix_world (above) instead of incrementing |
|
|
# ob1.location.x, y, and z |
|
|
# ob1.location.x, y, and z |
|
@ -124,14 +117,14 @@ else: |
|
|
# except TypeError: |
|
|
# except TypeError: |
|
|
# loc = wm * vert.co # Blender <2.8 |
|
|
# loc = wm * vert.co # Blender <2.8 |
|
|
# isFar = False |
|
|
# isFar = False |
|
|
# if loc.x == xMax or loc.y == yMax or loc.z == zMax: |
|
|
# if loc.x == maxes[0] or loc.y == maxes[1] or loc.z == maxes[2]: |
|
|
# isFar = True |
|
|
# isFar = True |
|
|
# elif loc.x == xMin or loc.y == yMin or loc.z == zMin: |
|
|
# elif loc.x == mins[0] or loc.y == mins[1] or loc.z == mins[2]: |
|
|
# isFar = True |
|
|
# isFar = True |
|
|
# if isFar: |
|
|
# if isFar: |
|
|
# pass |
|
|
# pass |
|
|
# # result = bpy.ops.object.add(type='EMPTY', radius=.25, |
|
|
# # result = bpy.ops.object.add(type='EMPTY', radius=.25, |
|
|
# # location=loc); |
|
|
# # location=loc) |
|
|
# # NOTE: result is merely {'FINISHED'} |
|
|
# # NOTE: result is merely {'FINISHED'} |
|
|
# # print("{:.2f}, {:.2f}, {:.2f}".format(loc.x, loc.y, |
|
|
# # print("{:.2f}, {:.2f}, {:.2f}".format(loc.x, loc.y, |
|
|
# # loc.z)) |
|
|
# # loc.z)) |
|
@ -142,40 +135,83 @@ else: |
|
|
else: |
|
|
else: |
|
|
extents1 = ob1.scale.copy() |
|
|
extents1 = ob1.scale.copy() |
|
|
# Object is an empty, so scale up for Minetest |
|
|
# Object is an empty, so scale up for Minetest |
|
|
extents1.x = extents1.x * 2.0 |
|
|
extents1.x = extents1.x * (ob1.empty_draw_size * 2.0) |
|
|
extents1.y = extents1.y * 2.0 |
|
|
extents1.y = extents1.y * (ob1.empty_draw_size * 2.0) |
|
|
extents1.z = extents1.z * 2.0 |
|
|
extents1.z = extents1.z * (ob1.empty_draw_size * 2.0) |
|
|
xMin = obj1Loc.x - extents1.x / 2.0 |
|
|
mins[0] = obj1Loc.x - extents1.x / 2.0 |
|
|
xMax = obj1Loc.x + extents1.x / 2.0 |
|
|
maxes[0] = obj1Loc.x + extents1.x / 2.0 |
|
|
yMin = obj1Loc.y - extents1.y / 2.0 |
|
|
mins[1] = obj1Loc.y - extents1.y / 2.0 |
|
|
yMax = obj1Loc.y + extents1.y / 2.0 |
|
|
maxes[1] = obj1Loc.y + extents1.y / 2.0 |
|
|
zMin = obj1Loc.z - extents1.z / 2.0 |
|
|
mins[2] = obj1Loc.z - extents1.z / 2.0 |
|
|
zMax = obj1Loc.z + extents1.z / 2.0 |
|
|
maxes[2] = obj1Loc.z + extents1.z / 2.0 |
|
|
msgSuffix = " (using Empty object's scale)" |
|
|
msgSuffix = " (using Empty object's scale)" |
|
|
# print("--using empty object:") |
|
|
# print("--using empty object:") |
|
|
# switch y and z for Minetest (y-up): |
|
|
|
|
|
|
|
|
# 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): |
|
|
|
|
|
sizes[i] = maxes[i] - mins[i] |
|
|
|
|
|
centers[i] = mins[i] + sizes[i] / 2.0 |
|
|
|
|
|
|
|
|
|
|
|
if enable_lowest_h: |
|
|
|
|
|
# OK to use z as up, since will y&z will be swapped if y_up |
|
|
|
|
|
hSize = None |
|
|
|
|
|
for i in range(len(hs)): |
|
|
|
|
|
axis_i = hs[i] |
|
|
|
|
|
if (hSize is None) or (sizes[axis_i] < hSize): |
|
|
|
|
|
hSize = sizes[axis_i] |
|
|
|
|
|
for i in range(len(hs)): |
|
|
|
|
|
axis_i = hs[i] |
|
|
|
|
|
sizes[axis_i] = hSize |
|
|
|
|
|
mins[axis_i] = centers[axis_i] - hSize / 2 |
|
|
|
|
|
maxes[axis_i] = mins[axis_i] + hSize |
|
|
|
|
|
|
|
|
|
|
|
if enable_center_h: |
|
|
|
|
|
for i in range(len(hs)): |
|
|
|
|
|
axis_i = hs[i] |
|
|
|
|
|
centers[i] = 0 |
|
|
|
|
|
mins[axis_i] = centers[axis_i] - sizes[axis_i] / 2 |
|
|
|
|
|
maxes[axis_i] = mins[axis_i] + sizes[axis_i] |
|
|
|
|
|
|
|
|
|
|
|
loc = (centers[0], centers[1], centers[2]) |
|
|
|
|
|
bpy.ops.object.add(type='EMPTY', radius=.5, location=loc) |
|
|
|
|
|
collisionboxName = "Empty.collisionbox." + ob1.name |
|
|
|
|
|
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: |
|
|
if enable_minetest: |
|
|
xMin /= 10.0 |
|
|
for i in range(3): |
|
|
xMax /= 10.0 |
|
|
mins[i] /= 10.0 |
|
|
yMin /= 10.0 |
|
|
maxes[i] /= 10.0 |
|
|
yMax /= 10.0 |
|
|
|
|
|
zMin /= 10.0 |
|
|
|
|
|
zMax /= 10.0 |
|
|
|
|
|
|
|
|
|
|
|
msg = ('Size is not available. Make sure you have a mesh object' |
|
|
msg = ('Size is not available. Make sure you have a mesh object' |
|
|
' selected.') |
|
|
' selected.') |
|
|
|
|
|
|
|
|
if xMin is not None: |
|
|
if mins[0] is not None: |
|
|
|
|
|
# swap y and z for Minetest (y-up): |
|
|
if y_up: |
|
|
if y_up: |
|
|
tmp = yMin |
|
|
tmp = mins[1] |
|
|
yMin = zMin |
|
|
mins[1] = mins[2] |
|
|
zMin = tmp |
|
|
mins[2] = tmp |
|
|
tmp = yMax |
|
|
tmp = maxes[1] |
|
|
yMax = zMax |
|
|
maxes[1] = maxes[2] |
|
|
zMax = tmp |
|
|
maxes[2] = tmp |
|
|
msg = (" collisionbox = {{{:.2f}, {:.2f}, {:.2f}, {:.2f}," |
|
|
msg = (" collisionbox = {{{:.2f}, {:.2f}, {:.2f}, {:.2f}," |
|
|
" {:.2f}, {:.2f}}}".format(xMin, yMin, zMin, xMax, yMax, |
|
|
" {:.2f}, {:.2f}}}".format(mins[0], mins[1], mins[2], |
|
|
zMax)) |
|
|
maxes[0], maxes[1], maxes[2])) |
|
|
if len(msgSuffix) > 0: |
|
|
if len(msgSuffix) > 0: |
|
|
msgSuffix = " -- " + msgSuffix |
|
|
msgSuffix = " -- " + msgSuffix |
|
|
bpy.context.window_manager.clipboard = msg + msgSuffix |
|
|
bpy.context.window_manager.clipboard = msg + msgSuffix |
|
|