Add PATH .blend file type

This commit is contained in:
Jack Andersen 2018-02-23 20:15:12 -10:00
parent c96dbee40b
commit 06797cd9fc
8 changed files with 213 additions and 20 deletions

View File

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

View File

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

121
hecl/blender/hecl/path.py Normal file
View File

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

View File

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

2
hecl/extern/athena vendored

@ -1 +1 @@
Subproject commit 62b6d6792a04792587f19d8fdf4c34d251fcfce0
Subproject commit 17a0959dbd0a79f9f9630dc616adc79fff65ad80

View File

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

View File

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

View File

@ -608,6 +608,7 @@ static const char* BlendTypeStrs[] =
"MAPAREA",
"MAPUNIVERSE",
"FRAME",
"PATH",
nullptr
};
@ -778,6 +779,22 @@ void PyOutStream::linkBlend(const char* target, const char* objName, bool link)
void PyOutStream::linkBackground(const char* target, const char* 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"
@ -792,6 +809,7 @@ void PyOutStream::linkBackground(const char* target, const char* sceneName)
"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)