Browse Source

Add script to add Empties at verts and use on duck (replace stride Grid)

master
poikilos 5 years ago
committed by Jacob Gustafson
parent
commit
ecbd91fc47
  1. BIN
      Bucket_Game-branches/duck--add-190814/mods/codermobs/codermobs/src/duck3-feathers-collapsed.blend
  2. 91
      utilities/blender/generate_Empty_at_each_vertex.py
  3. 192
      utilities/blender/generate_lua_collisionbox.py
  4. 145
      utilities/generate_collision_box.py

BIN
Bucket_Game-branches/duck--add-190814/mods/codermobs/codermobs/src/duck3-feathers-collapsed.blend

Binary file not shown.

91
utilities/blender/generate_Empty_at_each_vertex.py

@ -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)

192
utilities/blender/generate_lua_collisionbox.py

@ -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)

145
utilities/generate_collision_box.py

@ -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…
Cancel
Save