mirror of https://github.com/AxioDL/metaforce.git
Add PATH .blend file type
This commit is contained in:
parent
c96dbee40b
commit
06797cd9fc
|
@ -12,7 +12,8 @@ list(APPEND PY_SOURCES
|
|||
hecl/swld/__init__.py
|
||||
hecl/mapa.py
|
||||
hecl/mapu.py
|
||||
hecl/frme.py)
|
||||
hecl/frme.py
|
||||
hecl/path.py)
|
||||
|
||||
bintoc(hecl_blendershell.cpp hecl_blendershell.py HECL_BLENDERSHELL)
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ bl_info = {
|
|||
"category": "System"}
|
||||
|
||||
# Package import
|
||||
from . import hmdl, sact, srea, swld, mapa, mapu, frme, Nodegrid, Patching
|
||||
from . import hmdl, sact, srea, swld, mapa, mapu, frme, path, Nodegrid, Patching
|
||||
Nodegrid = Nodegrid.Nodegrid
|
||||
import bpy, os, sys, struct
|
||||
from bpy.app.handlers import persistent
|
||||
|
@ -26,7 +26,8 @@ hecl_typeS = [
|
|||
('WORLD', "World", "Active scene represents a HECL World", swld.draw),
|
||||
('MAPAREA', "Map Area", "Active scene represents a HECL Map Area", mapa.draw),
|
||||
('MAPUNIVERSE', "Map Universe", "Active scene represents a HECL Map Universe", mapu.draw),
|
||||
('FRAME', "Gui Frame", "Active scene represents a HECL Gui Frame", frme.draw)]
|
||||
('FRAME', "Gui Frame", "Active scene represents a HECL Gui Frame", frme.draw),
|
||||
('PATH', "Path Mesh", "Active scene represents a HECL Path Mesh", path.draw)]
|
||||
|
||||
# Main Scene Panel
|
||||
class hecl_scene_panel(bpy.types.Panel):
|
||||
|
@ -115,6 +116,15 @@ def scene_loaded(dummy):
|
|||
if o.library:
|
||||
o.hide = True
|
||||
|
||||
# Show PATH library objects as wireframes
|
||||
if bpy.context.scene.hecl_type == 'PATH':
|
||||
if bpy.context.scene.background_set:
|
||||
for o in bpy.context.scene.background_set.objects:
|
||||
o.draw_type = 'WIRE'
|
||||
if bpy.context.scene.hecl_path_obj in bpy.context.scene.objects:
|
||||
path_obj = bpy.context.scene.objects[bpy.context.scene.hecl_path_obj]
|
||||
path_obj.show_wire = True
|
||||
|
||||
# Linked-Child Detection
|
||||
for scene in bpy.data.scenes:
|
||||
if scene.hecl_type == 'ACTOR':
|
||||
|
@ -149,6 +159,7 @@ def register():
|
|||
frme.register()
|
||||
mapa.register()
|
||||
mapu.register()
|
||||
path.register()
|
||||
bpy.utils.register_class(hecl_scene_panel)
|
||||
bpy.types.Scene.hecl_auto_select = bpy.props.BoolProperty(name='HECL Auto Select', default=True)
|
||||
bpy.app.handlers.load_post.append(scene_loaded)
|
||||
|
@ -159,6 +170,7 @@ def unregister():
|
|||
hmdl.unregister()
|
||||
sact.unregister()
|
||||
srea.unregister()
|
||||
path.unregister()
|
||||
bpy.utils.unregister_class(hecl_scene_panel)
|
||||
Patching.unregister()
|
||||
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
import bpy
|
||||
|
||||
def draw(layout, context):
|
||||
layout.prop_search(context.scene, 'hecl_path_obj', context.scene, 'objects')
|
||||
layout.operator('view3d.toggle_path_height_visualization', text='Toggle Height Viz', icon='MANIPUL')
|
||||
layout.operator('view3d.toggle_path_background_wireframe', text='Toggle Background Wire', icon='WIRE')
|
||||
|
||||
def cook(writebuf, mesh_obj):
|
||||
pass
|
||||
|
||||
import bpy, bgl
|
||||
from mathutils import Vector, Matrix
|
||||
from mathutils.geometry import intersect_ray_tri, tessellate_polygon
|
||||
|
||||
def correlate_polygon_heights(context, obj):
|
||||
ret = {}
|
||||
if obj.type != 'MESH':
|
||||
return ret
|
||||
for p in obj.data.polygons:
|
||||
pl = [obj.matrix_world * obj.data.vertices[vert].co for vert in p.vertices]
|
||||
tpl = tessellate_polygon((pl,))
|
||||
found = False
|
||||
for eobj in context.scene.objects:
|
||||
for tri in tpl:
|
||||
if eobj.type == 'EMPTY' and eobj.library is None:
|
||||
intersect = intersect_ray_tri(pl[tri[0]], pl[tri[1]], pl[tri[2]],
|
||||
Vector((0.0, 0.0, -999.0)),
|
||||
eobj.location)
|
||||
if intersect is not None:
|
||||
ret[p] = abs(intersect.z - eobj.location.z)
|
||||
found = True
|
||||
break
|
||||
if found:
|
||||
break
|
||||
return ret
|
||||
|
||||
def draw_line_3d(color, start, end):
|
||||
bgl.glColor4f(*color)
|
||||
bgl.glBegin(bgl.GL_LINES)
|
||||
bgl.glVertex3f(*start)
|
||||
bgl.glVertex3f(*end)
|
||||
|
||||
def draw_callback_3d(self, context):
|
||||
# object locations
|
||||
if context.scene.hecl_path_obj not in context.scene.objects:
|
||||
return
|
||||
obj = context.scene.objects[context.scene.hecl_path_obj]
|
||||
if obj.type != 'MESH':
|
||||
return
|
||||
heights = correlate_polygon_heights(context, obj)
|
||||
obj_mtx = obj.matrix_world
|
||||
|
||||
for p in obj.data.polygons:
|
||||
height = 1.0
|
||||
if p in heights:
|
||||
height = heights[p]
|
||||
for ek in p.edge_keys:
|
||||
co0 = obj_mtx * obj.data.vertices[ek[0]].co
|
||||
co1 = obj_mtx * obj.data.vertices[ek[1]].co
|
||||
draw_line_3d((0.0, 0.0, 1.0, 0.7), co0 + Vector((0.0, 0.0, height)),
|
||||
co1 + Vector((0.0, 0.0, height)))
|
||||
for vk in p.vertices:
|
||||
co = obj_mtx * obj.data.vertices[vk].co
|
||||
draw_line_3d((1.0, 0.0, 0.0, 0.7), co, co + Vector((0.0, 0.0, height)))
|
||||
|
||||
bgl.glEnd()
|
||||
# restore opengl defaults
|
||||
bgl.glColor4f(0.0, 0.0, 0.0, 1.0)
|
||||
|
||||
class PathHeightDrawOperator(bpy.types.Operator):
|
||||
bl_idname = "view3d.toggle_path_height_visualization"
|
||||
bl_label = "Toggle PATH height visualization"
|
||||
_handle_3d = None
|
||||
|
||||
def execute(self, context):
|
||||
#heights = correlate_polygon_heights(context, bpy.data.objects['Plane'])
|
||||
# the arguments we pass the the callback
|
||||
args = (self, context)
|
||||
# Add the region OpenGL drawing callback
|
||||
# draw in view space with 'POST_VIEW' and 'PRE_VIEW'
|
||||
if self._handle_3d is None:
|
||||
PathHeightDrawOperator._handle_3d = bpy.types.SpaceView3D.draw_handler_add(draw_callback_3d, args, 'WINDOW', 'POST_VIEW')
|
||||
else:
|
||||
bpy.types.SpaceView3D.draw_handler_remove(PathHeightDrawOperator._handle_3d, 'WINDOW')
|
||||
PathHeightDrawOperator._handle_3d = None
|
||||
|
||||
for ar in bpy.context.screen.areas:
|
||||
ar.tag_redraw()
|
||||
return {'FINISHED'}
|
||||
|
||||
class PathBackgroundWireframeOperator(bpy.types.Operator):
|
||||
bl_idname = "view3d.toggle_path_background_wireframe"
|
||||
bl_label = "Toggle PATH background wireframe"
|
||||
_handle_3d = None
|
||||
|
||||
def execute(self, context):
|
||||
if context.scene.background_set:
|
||||
to_wire = False
|
||||
for o in context.scene.background_set.objects:
|
||||
if o.draw_type != 'WIRE':
|
||||
to_wire = True
|
||||
break
|
||||
if to_wire:
|
||||
for o in context.scene.background_set.objects:
|
||||
o.draw_type = 'WIRE'
|
||||
else:
|
||||
for o in context.scene.background_set.objects:
|
||||
o.draw_type = 'TEXTURED'
|
||||
return {'FINISHED'}
|
||||
|
||||
# Registration
|
||||
def register():
|
||||
bpy.types.Scene.hecl_path_obj = bpy.props.StringProperty(
|
||||
name='HECL Path Object',
|
||||
description='Blender Mesh Object to export during PATH\'s cook process')
|
||||
bpy.utils.register_class(PathHeightDrawOperator)
|
||||
bpy.utils.register_class(PathBackgroundWireframeOperator)
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(PathHeightDrawOperator)
|
||||
bpy.utils.unregister_class(PathBackgroundWireframeOperator)
|
|
@ -267,6 +267,15 @@ def dataout_loop():
|
|||
bpy.data.objects.remove(join_obj)
|
||||
bpy.data.meshes.remove(join_mesh)
|
||||
|
||||
elif cmdargs[0] == 'MESHCOMPILEPATH':
|
||||
meshName = bpy.context.scene.hecl_path_obj
|
||||
if meshName not in bpy.data.objects:
|
||||
writepipestr(('mesh %s not found' % meshName).encode())
|
||||
continue
|
||||
|
||||
writepipestr(b'OK')
|
||||
hecl.path.cook(writepipebuf, bpy.data.objects[meshName])
|
||||
|
||||
elif cmdargs[0] == 'WORLDCOMPILE':
|
||||
writepipestr(b'OK')
|
||||
hecl.swld.cook(writepipebuf)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 62b6d6792a04792587f19d8fdf4c34d251fcfce0
|
||||
Subproject commit 17a0959dbd0a79f9f9630dc616adc79fff65ad80
|
|
@ -99,7 +99,7 @@ public:
|
|||
#endif
|
||||
void format(const char* fmt, ...);
|
||||
void linkBlend(const char* target, const char* objName, bool link=true);
|
||||
void linkBackground(const char* target, const char* sceneName);
|
||||
void linkBackground(const char* target, const char* sceneName=nullptr);
|
||||
void AABBToBMesh(const atVec3f& min, const atVec3f& max);
|
||||
void centerView();
|
||||
|
||||
|
@ -509,6 +509,12 @@ struct Actor
|
|||
Actor(Connection& conn);
|
||||
};
|
||||
|
||||
/** Intermediate pathfinding representation prepared by blender */
|
||||
struct PathMesh
|
||||
{
|
||||
PathMesh(Connection& conn);
|
||||
};
|
||||
|
||||
class DataStream
|
||||
{
|
||||
friend class Connection;
|
||||
|
@ -549,6 +555,9 @@ public:
|
|||
/** Gather all lights in scene (AREA blends only) */
|
||||
std::vector<Light> compileLights();
|
||||
|
||||
/** Get PathMesh from scene (PATH blends only) */
|
||||
PathMesh compilePathMesh();
|
||||
|
||||
/** Compile GUI into FRME data (FRAME blends only) */
|
||||
void compileGuiFrame(std::string_view pathOut, int version);
|
||||
|
||||
|
|
|
@ -59,7 +59,8 @@ enum class BlendType
|
|||
World,
|
||||
MapArea,
|
||||
MapUniverse,
|
||||
Frame
|
||||
Frame,
|
||||
PathMesh
|
||||
};
|
||||
|
||||
class Connection;
|
||||
|
@ -78,6 +79,7 @@ struct Actor;
|
|||
struct Armature;
|
||||
struct Action;
|
||||
struct Bone;
|
||||
struct PathMesh;
|
||||
struct Matrix3f;
|
||||
struct PoolSkinIndex;
|
||||
|
||||
|
|
|
@ -608,6 +608,7 @@ static const char* BlendTypeStrs[] =
|
|||
"MAPAREA",
|
||||
"MAPUNIVERSE",
|
||||
"FRAME",
|
||||
"PATH",
|
||||
nullptr
|
||||
};
|
||||
|
||||
|
@ -778,20 +779,37 @@ void PyOutStream::linkBlend(const char* target, const char* objName, bool link)
|
|||
|
||||
void PyOutStream::linkBackground(const char* target, const char* sceneName)
|
||||
{
|
||||
format("if '%s' not in bpy.data.scenes:\n"
|
||||
" with bpy.data.libraries.load('''%s''', link=True, relative=True) as (data_from, data_to):\n"
|
||||
" data_to.scenes = data_from.scenes\n"
|
||||
" obj_scene = None\n"
|
||||
" for scene in data_to.scenes:\n"
|
||||
" if scene.name == '%s':\n"
|
||||
" obj_scene = scene\n"
|
||||
" break\n"
|
||||
" if not obj_scene:\n"
|
||||
" raise RuntimeError('''unable to find %s in %s. try deleting it and restart the extract.''')\n"
|
||||
"\n"
|
||||
"bpy.context.scene.background_set = bpy.data.scenes['%s']\n",
|
||||
sceneName, target,
|
||||
sceneName, sceneName, target, sceneName);
|
||||
if (!sceneName)
|
||||
{
|
||||
format("with bpy.data.libraries.load('''%s''', link=True, relative=True) as (data_from, data_to):\n"
|
||||
" data_to.scenes = data_from.scenes\n"
|
||||
"obj_scene = None\n"
|
||||
"for scene in data_to.scenes:\n"
|
||||
" obj_scene = scene\n"
|
||||
" break\n"
|
||||
"if not obj_scene:\n"
|
||||
" raise RuntimeError('''unable to find %s. try deleting it and restart the extract.''')\n"
|
||||
"\n"
|
||||
"bpy.context.scene.background_set = obj_scene\n",
|
||||
target, target);
|
||||
}
|
||||
else
|
||||
{
|
||||
format("if '%s' not in bpy.data.scenes:\n"
|
||||
" with bpy.data.libraries.load('''%s''', link=True, relative=True) as (data_from, data_to):\n"
|
||||
" data_to.scenes = data_from.scenes\n"
|
||||
" obj_scene = None\n"
|
||||
" for scene in data_to.scenes:\n"
|
||||
" if scene.name == '%s':\n"
|
||||
" obj_scene = scene\n"
|
||||
" break\n"
|
||||
" if not obj_scene:\n"
|
||||
" raise RuntimeError('''unable to find %s in %s. try deleting it and restart the extract.''')\n"
|
||||
"\n"
|
||||
"bpy.context.scene.background_set = bpy.data.scenes['%s']\n",
|
||||
sceneName, target,
|
||||
sceneName, sceneName, target, sceneName);
|
||||
}
|
||||
}
|
||||
|
||||
void PyOutStream::AABBToBMesh(const atVec3f& min, const atVec3f& max)
|
||||
|
@ -1502,6 +1520,11 @@ Actor::Actor(Connection& conn)
|
|||
actions.emplace_back(conn);
|
||||
}
|
||||
|
||||
PathMesh::PathMesh(Connection& conn)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const Bone* Armature::lookupBone(const char* name) const
|
||||
{
|
||||
for (const Bone& b : bones)
|
||||
|
@ -1895,6 +1918,22 @@ std::vector<Light> DataStream::compileLights()
|
|||
return ret;
|
||||
}
|
||||
|
||||
PathMesh DataStream::compilePathMesh()
|
||||
{
|
||||
if (m_parent->getBlendType() != BlendType::PathMesh)
|
||||
BlenderLog.report(logvisor::Fatal, _S("%s is not a PATH blend"),
|
||||
m_parent->getBlendPath().getAbsolutePath().data());
|
||||
|
||||
m_parent->_writeStr("MESHCOMPILEPATH");
|
||||
|
||||
char readBuf[256];
|
||||
m_parent->_readStr(readBuf, 256);
|
||||
if (strcmp(readBuf, "OK"))
|
||||
BlenderLog.report(logvisor::Fatal, "unable to path collision mesh: %s", readBuf);
|
||||
|
||||
return PathMesh(*m_parent);
|
||||
}
|
||||
|
||||
void DataStream::compileGuiFrame(std::string_view pathOut, int version)
|
||||
{
|
||||
if (m_parent->getBlendType() != BlendType::Frame)
|
||||
|
|
Loading…
Reference in New Issue