poikilos
5 years ago
committed by
Jacob Gustafson
4 changed files with 283 additions and 145 deletions
Binary file not shown.
@ -0,0 +1,91 @@ |
|||
print("How to use: paste into a Blender Text Editor panel, select object, Run Script") |
|||
|
|||
y_up = True |
|||
enable_minetest = True |
|||
|
|||
import bpy |
|||
#from mathutils import Matrix |
|||
from mathutils import Vector |
|||
#from mathutils import Euler |
|||
|
|||
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") |
|||
|
|||
|
|||
ob1 = None |
|||
try: |
|||
ob1 = obj.select_get() |
|||
except: |
|||
# < 2.8 |
|||
ob1 = bpy.context.scene.objects.active |
|||
|
|||
bpy.utils.register_class(MessageBox) |
|||
|
|||
if ob1 is None: |
|||
msg = "Nothing is selected." |
|||
# WRONG: https://stackoverflow.com/questions/7697532/how-to-show-a-message-from-a-blender-script |
|||
# self.report({'ERROR'}, msg) |
|||
bpy.ops.message.messagebox('INVOKE_DEFAULT', message = msg) |
|||
else: |
|||
|
|||
loc1 = ob1.location |
|||
#loc1 = ob1.matrix_world.translation |
|||
|
|||
#see https://blender.stackexchange.com/questions/6139/how-to-iterate-through-all-vertices-of-an-object-that-contains-multiple-meshes |
|||
mesh = ob1.data |
|||
# print("mesh:" + str(mesh)) |
|||
# print("hasattr(mesh, 'vertices'):" + str(hasattr(mesh, 'vertices')))] |
|||
xMin = None |
|||
if (mesh is not None) and (not hasattr(mesh, 'vertices')): |
|||
print("--can't calculate collisionbox for skeleton") |
|||
elif mesh is not None: |
|||
xMin = None |
|||
yMin = None |
|||
zMin = None |
|||
xMax = None |
|||
yMax = None |
|||
zMax = None |
|||
# See https://blender.stackexchange.com/questions/6155/how-to-convert-coordinates-from-vertex-to-world-space |
|||
wm = ob1.matrix_world |
|||
newNamePrefix = "Empty.from." + ob1.name |
|||
i = 0 |
|||
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 |
|||
bpy.ops.object.add(type = 'EMPTY', radius = .25, location = loc); |
|||
bpy.context.active_object.name = newName |
|||
# NOTE: add only returns {'FINISHED'} |
|||
# See also vert.co.x (and y and z) |
|||
|
|||
# add_named doesn't work this way--how is unknown: |
|||
# bpy.ops.object.add_named(name = "Empty" + ob1.name, type = 'EMPTY', radius = .25, location = loc) |
|||
i += 1 |
|||
|
|||
# bpy.ops.message.messagebox('INVOKE_DEFAULT', message = msg) |
|||
|
|||
# Unregistering before user clicks the MessageBox will crash Blender! |
|||
# bpy.utils.unregister_class(MessageBox) |
@ -0,0 +1,192 @@ |
|||
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) |
@ -1,145 +0,0 @@ |
|||
print("How to use: paste into a Blender Text Editor panel, select object, Run Script") |
|||
|
|||
y_up = True |
|||
enable_minetest = True |
|||
|
|||
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) |
|||
|
|||
#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 |
|||
loc1 = ob1.location |
|||
#loc1 = 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 |
|||
mesh = ob1.data |
|||
#print("mesh:" + str(mesh)) |
|||
#print("hasattr(mesh, 'vertices'):" + str(hasattr(mesh, 'vertices')))] |
|||
xMin = None |
|||
if (mesh is not None) and (not hasattr(mesh, 'vertices')): |
|||
print("--can't calculate collisionbox for skeleton") |
|||
elif mesh is not None: |
|||
xMin = None |
|||
yMin = None |
|||
zMin = None |
|||
xMax = None |
|||
yMax = None |
|||
zMax = None |
|||
for vert in mesh.vertices: |
|||
# switch y and z for Minetest (y-up) |
|||
if (xMin is None) or (vert.co.x < xMin): |
|||
xMin = vert.co.x |
|||
if (xMax is None) or (vert.co.x > xMax): |
|||
xMax = vert.co.x |
|||
if (yMin is None) or (vert.co.y < yMin): |
|||
yMin = vert.co.y |
|||
if (yMax is None) or (vert.co.y > yMax): |
|||
yMax = vert.co.y |
|||
if (zMin is None) or (vert.co.z < zMin): |
|||
zMin = vert.co.z |
|||
if (zMax is None) or (vert.co.z > zMax): |
|||
zMax = vert.co.z |
|||
#print(str(extents1)) |
|||
#print("--by vertices (raw):") |
|||
#print( |
|||
# " collisionbox = {{{:.2f}, {:.2f}, {:.2f}, {:.2f}, {:.2f}, {:.2f}}}".format(xMin, yMin, zMin, xMax, yMax, zMax) |
|||
#) |
|||
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:") |
|||
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 = loc1.x - extents1.x / 2.0 |
|||
xMax = loc1.x + extents1.x / 2.0 |
|||
yMin = loc1.y - extents1.y / 2.0 |
|||
yMax = loc1.y + extents1.y / 2.0 |
|||
zMin = loc1.z - extents1.z / 2.0 |
|||
zMax = loc1.z + extents1.z / 2.0 |
|||
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) |
|||
# print(msg) |
|||
|
|||
bpy.ops.message.messagebox('INVOKE_DEFAULT', message = msg) |
|||
|
|||
bpy.utils.unregister_class(MessageBox) |
Loading…
Reference in new issue