mirror of https://github.com/AxioDL/metaforce.git
Work on Gui Frame exporter
This commit is contained in:
parent
521dd69997
commit
2147abfbaa
|
@ -1,4 +1,4 @@
|
||||||
import bpy, struct
|
import bpy, struct, math
|
||||||
|
|
||||||
def draw(layout, context):
|
def draw(layout, context):
|
||||||
if bpy.context.active_object:
|
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_linear', text='Linear')
|
||||||
row.prop(obj.data, 'retro_light_angle_quadratic', text='Quadratic')
|
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 = 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
|
# Registration
|
||||||
def register():
|
def register():
|
||||||
|
|
|
@ -46,6 +46,21 @@ def quitblender():
|
||||||
writepipestr(b'QUITTING')
|
writepipestr(b'QUITTING')
|
||||||
bpy.ops.wm.quit_blender()
|
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
|
# If there's a third argument, use it as the .zip path containing the addon
|
||||||
did_install = False
|
did_install = False
|
||||||
if len(args) >= 4 and args[3] != 'SKIPINSTALL':
|
if len(args) >= 4 and args[3] != 'SKIPINSTALL':
|
||||||
|
@ -235,7 +250,8 @@ def dataout_loop():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
writepipestr(b'OK')
|
writepipestr(b'OK')
|
||||||
hecl.frme.cook(pathOut, version)
|
hecl.frme.cook(pathOut, version, PathHasher())
|
||||||
|
writepipestr(b'FRAMEDONE')
|
||||||
|
|
||||||
elif cmdargs[0] == 'LIGHTCOMPILEALL':
|
elif cmdargs[0] == 'LIGHTCOMPILEALL':
|
||||||
writepipestr(b'OK')
|
writepipestr(b'OK')
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <Shlwapi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace std
|
namespace std
|
||||||
|
@ -1332,6 +1333,17 @@ std::vector<BlenderConnection::DataStream::Light> BlenderConnection::DataStream:
|
||||||
return ret;
|
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)
|
void BlenderConnection::DataStream::compileGuiFrame(const std::string& pathOut, int version)
|
||||||
{
|
{
|
||||||
if (m_parent->m_loadedType != BlendType::Frame)
|
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);
|
snprintf(req, 512, "FRAMECOMPILE %s %d", pathOut.c_str(), version);
|
||||||
m_parent->_writeStr(req);
|
m_parent->_writeStr(req);
|
||||||
|
|
||||||
char readBuf[256];
|
char readBuf[1024];
|
||||||
m_parent->_readStr(readBuf, 256);
|
m_parent->_readStr(readBuf, 1024);
|
||||||
if (strcmp(readBuf, "OK"))
|
if (strcmp(readBuf, "OK"))
|
||||||
BlenderLog.report(logvisor::Fatal, "unable to compile frame: %s", readBuf);
|
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()
|
std::vector<ProjectPath> BlenderConnection::DataStream::getTextures()
|
||||||
|
|
Loading…
Reference in New Issue