Work on Gui Frame exporter

This commit is contained in:
Jack Andersen 2017-01-16 21:12:49 -10:00
parent 521dd69997
commit 2147abfbaa
3 changed files with 259 additions and 6 deletions

View File

@ -1,4 +1,4 @@
import bpy, struct
import bpy, struct, math
def draw(layout, context):
if bpy.context.active_object:
@ -63,9 +63,214 @@ def draw(layout, context):
row.prop(obj.data, 'retro_light_angle_linear', text='Linear')
row.prop(obj.data, 'retro_light_angle_quadratic', text='Quadratic')
def cook(path_out, version):
hjustifications = None
vjustifications = None
def recursive_cook(fout, obj, version, path_hasher, parent_name):
fout.write(struct.pack('>4s', retro_widget_type[6:]))
fout.write(obj.name.encode())
fout.write(parent_name.encode())
fout.write(struct.pack('>bbbbffffI',
False,
obj.retro_widget_default_visible,
obj.retro_widget_default_active,
obj.retro_widget_cull_faces,
obj.retro_widget_color[0],
obj.retro_widget_color[1],
obj.retro_widget_color[2],
obj.retro_widget_color[3],
obj.retro_widget_model_draw_flags))
if obj.retro_widget_type == 'RETRO_CAMR':
aspect = bpy.context.scene.render.resolution_x / bpy.context.scene.render.resolution_y
if obj.data.type == 'PERSP':
if aspect > 1.0:
fov = math.degrees(math.atan(math.tan(obj.data.angle / 2.0) / aspect)) * 2.0
elif:
fov = math.degrees(obj.data.angle)
fout.write(struct.pack('>Iffff', 0, fov, aspect, obj.data.clip_start, obj.data.clip_end))
elif obj.data.type == 'ORTHO':
ortho_half = obj.data.ortho_scale / 2.0
fout.write(struct.pack('>Iffffff', 1, -ortho_half, ortho_half, -ortho_half / aspect,
ortho_half / aspect, obj.data.clip_start, obj.data.clip_end))
elif obj.retro_widget_type == 'RETRO_MODL':
if len(obj.children) == 0:
raise RuntimeException('Model Widget must have a child model object')
model_obj = obj.children[0]
if model_obj.type != 'MESH':
raise RuntimeException('Model Widget must have a child MESH')
if not model_obj.data.library:
raise RuntimeException('Model Widget must have a linked library MESH')
path = bpy.path.abspath(model_obj.data.library.filepath)
path_hash = path_hasher.hashpath32(path)
fout.write(struct.pack('>III', path_hash, 0, obj.retro_model_light_mask))
elif obj.retro_widget_type == 'RETRO_PANE':
fout.write(struct.pack('>fffff',
obj.retro_pane_dimensions[0],
obj.retro_pane_dimensions[1],
obj.retro_pane_scale_center[0],
obj.retro_pane_scale_center[1],
obj.retro_pane_scale_center[2]))
elif obj.retro_widget_type == 'RETRO_TXPN':
path_hash = path_hasher.hashpath32(obj.retro_textpane_font_path)
fout.write(struct.pack('>fffffIbbIIffffffffff',
obj.retro_pane_dimensions[0],
obj.retro_pane_dimensions[1],
obj.retro_pane_scale_center[0],
obj.retro_pane_scale_center[1],
obj.retro_pane_scale_center[2],
path_hash,
obj.retro_textpane_word_wrap,
obj.retro_textpane_vertical,
hjustifications[obj.retro_textpane_hjustification],
vjustifications[obj.retro_textpane_vjustification],
obj.retro_textpane_fill_color[0],
obj.retro_textpane_fill_color[1],
obj.retro_textpane_fill_color[2],
obj.retro_textpane_fill_color[3],
obj.retro_textpane_outline_color[0],
obj.retro_textpane_outline_color[1],
obj.retro_textpane_outline_color[2],
obj.retro_textpane_outline_color[3],
obj.retro_textpane_block_extent[0],
obj.retro_textpane_block_extent[1]))
if version >= 1:
path_hash = path_hasher.hashpath32(obj.retro_textpane_jp_font_path)
fout.write(struct.pack('>III',
path_hash,
obj.retro_textpane_jp_font_scale[0],
obj.retro_textpane_jp_font_scale[1]))
elif obj.retro_widget_type == 'RETRO_TBGP':
fout.write(struct.pack('>HHIHHbbffbfHHHH',
obj.retro_tablegroup_elem_count,
0,
0,
obj.retro_tablegroup_elem_default,
0,
obj.retro_tablegroup_wraparound,
False,
0.0,
0.0,
False,
0.0,
0,
0,
0,
0))
elif obj.retro_widget_type == 'RETRO_GRUP':
fout.write(struct.pack('>Hb',
obj.retro_group_default_worker,
False))
elif obj.retro_widget_type == 'RETRO_SLGP':
fout.write(struct.pack('>ffff',
obj.retro_slider_min,
obj.retro_slider_max,
obj.retro_slider_default,
obj.retro_slider_increment))
elif obj.retro_widget_type == 'RETRO_ENRG':
path_hash = path_hasher.hashpath32(obj.retro_energybar_texture_path)
fout.write(struct.pack('>ffff', path_hash))
elif obj.retro_widget_type == 'RETRO_METR':
fout.write(struct.pack('>bbII',
False,
obj.retro_meter_no_round_up,
obj.retro_meter_max_capacity,
obj.retro_meter_worker_count))
elif obj.retro_widget_type == 'RETRO_LITE':
type_enum = 0
constant = 1.0
linear = 0.0
quadratic = 0.0
cutoff = 0.0
if obj.data.type == 'POINT':
type_enum = 4
elif obj.data.type == 'HEMI':
type_enum = 2
elif obj.data.type == 'SPOT':
type_enum = 0
cutoff = obj.data.spot_size
if obj.data.type == 'POINT' or obj.data.type == 'SPOT':
constant = obj.data.constant_coefficient
linear = obj.data.linear_coefficient
quadratic = obj.data.quadratic_coefficient
fout.write(struct.pack('>IffffffIf',
type_enum, constant, linear, quadratic,
obj.retro_light_angle_constant,
obj.retro_light_angle_linear,
obj.retro_light_angle_quadratic,
obj.retro_light_index,
cutoff))
elif obj.retro_widget_type == 'RETRO_IMGP':
if len(obj.children) == 0:
raise RuntimeException('Imagepane Widget must have a child model object')
model_obj = obj.children[0]
if model_obj.type != 'MESH':
raise RuntimeException('Imagepane Widget must have a child MESH')
if len(model_obj.data.loops) < 4:
raise RuntimeException('Imagepane Widget must have a child MESH with 4 verts')
if len(model_obj.data.uv_layers) < 1:
raise RuntimeException('Imagepane Widget must have a child MESH with a UV layer')
if len(model_obj.data.materials) == 0:
raise RuntimeException('Imagepane Widget must have a material')
material = model_obj.data.materials[0]
if len(material.texture_slots) == 0 or not material.texture_slots[0]:
raise RuntimeException('Imagepane Widget must have a texture-slotted material')
tex_slot = material.texture_slots[0]
if tex_slot.texture.type != 'IMAGE' or not tex_slot.texture.image:
raise RuntimeException('Imagepane Widget must have an IMAGE texture-slot')
image = tex_slot.texture.image
path = bpy.path.abspath(image.filepath)
path_hash = path_hasher.hashpath32(path)
fout.write(struct.pack('>IIII', path_hash, 0, 0, 4))
for i in range(4):
vi = model_obj.data.loops[i].vertex_index
co = model_obj.data.vertices[vi].co
fout.write(struct.pack('>fff', co[0], co[1], co[2]))
fout.write(struct.pack('>I', 4))
for i in range(4):
co = model_obj.data.uv_layers[0].data[i].uv
fout.write(struct.pack('>ff', co[0], co[1]))
for ch in obj.children:
if ch.retro_widget_type != 'RETRO_NONE':
recursive_cook(fout, ch, version, path_hasher, obj.name)
def cook(path_out, version, path_hasher):
hjustifications = dict((i[0], i[3]) for i in bpy.types.Object.retro_textpane_hjustification[1]['items'])
vjustifications = dict((i[0], i[3]) for i in bpy.types.Object.retro_textpane_vjustification[1]['items'])
fout = open(path_out, 'wb')
fout.write(struct.pack('>IIIII'))
fout.write(struct.pack('>IIIII', 0, 0, 0, 0))
widget_count = 0
for obj in bpy.data.objects:
if obj.retro_widget_type != 'RETRO_NONE':
widget_count += 1
fout.write(struct.pack('>I', widget_count))
for obj in bpy.data.objects:
if obj.retro_widget_type != 'RETRO_NONE' and not obj.parent:
recursive_cook(fout, obj, version, path_hasher, 'kGSYS_DummyWidgetID')
fout.close()
# Registration
def register():

View File

@ -46,6 +46,21 @@ def quitblender():
writepipestr(b'QUITTING')
bpy.ops.wm.quit_blender()
class PathHasher:
def hashpath32(self, path):
writepipestr(path)
read_str = readpipestr()
if len(read_str) >= 8:
return int(read_str[0:8], 16)
return 0
def hashpath64(self, path):
writepipestr(path)
read_str = readpipestr()
if len(read_str) >= 16:
return int(read_str[0:16], 16)
return 0
# If there's a third argument, use it as the .zip path containing the addon
did_install = False
if len(args) >= 4 and args[3] != 'SKIPINSTALL':
@ -235,7 +250,8 @@ def dataout_loop():
continue
writepipestr(b'OK')
hecl.frme.cook(pathOut, version)
hecl.frme.cook(pathOut, version, PathHasher())
writepipestr(b'FRAMEDONE')
elif cmdargs[0] == 'LIGHTCOMPILEALL':
writepipestr(b'OK')

View File

@ -19,6 +19,7 @@
#if _WIN32
#include <io.h>
#include <fcntl.h>
#include <Shlwapi.h>
#endif
namespace std
@ -1332,6 +1333,17 @@ std::vector<BlenderConnection::DataStream::Light> BlenderConnection::DataStream:
return ret;
}
static bool PathRelative(const SystemString& path)
{
if (path.empty())
return false;
#if _WIN32
return PathIsRelative(path.c_str());
#else
return path[0] != '/';
#endif
}
void BlenderConnection::DataStream::compileGuiFrame(const std::string& pathOut, int version)
{
if (m_parent->m_loadedType != BlendType::Frame)
@ -1342,10 +1354,30 @@ void BlenderConnection::DataStream::compileGuiFrame(const std::string& pathOut,
snprintf(req, 512, "FRAMECOMPILE %s %d", pathOut.c_str(), version);
m_parent->_writeStr(req);
char readBuf[256];
m_parent->_readStr(readBuf, 256);
char readBuf[1024];
m_parent->_readStr(readBuf, 1024);
if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to compile frame: %s", readBuf);
while (true)
{
m_parent->_readStr(readBuf, 1024);
if (!strcmp(readBuf, "FRAMEDONE"))
break;
std::string readStr(readBuf);
SystemStringView absolute(readStr);
auto& proj = m_parent->m_loadedBlend.getProject();
SystemString relative;
if (PathRelative(absolute.sys_str()))
relative = absolute.sys_str();
else
relative = proj.getProjectRootPath().getProjectRelativeFromAbsolute(absolute);
hecl::ProjectPath path(proj.getProjectWorkingPath(), relative);
snprintf(req, 512, "%016llX", path.hash().val64());
m_parent->_writeStr(req);
}
}
std::vector<ProjectPath> BlenderConnection::DataStream::getTextures()