Attachment model support in blender addon

This commit is contained in:
Jack Andersen 2018-10-11 10:48:13 -10:00
parent d1f0450401
commit aef455e1ab
12 changed files with 362 additions and 81 deletions

View File

@ -149,44 +149,50 @@ class SACTAction_load(bpy.types.Operator):
# Set single action into armature
if subtype.linked_armature in bpy.data.objects:
armature_obj = bpy.data.objects[subtype.linked_armature]
armature_objs = [bpy.data.objects[subtype.linked_armature]]
for bone in armature_obj.pose.bones:
bone.location = (0,0,0)
bone.rotation_quaternion = (1,0,0,0)
bone.scale = (1,1,1)
for attachment in actor_data.attachments:
if attachment.linked_armature in bpy.data.objects:
attachment_armature = bpy.data.objects[attachment.linked_armature]
armature_objs.append(attachment_armature)
if action_data.name in bpy.data.actions:
action_obj =\
bpy.data.actions[action_data.name]
armature_obj.animation_data_clear()
armature_obj.animation_data_create()
armature_obj.animation_data.action = action_obj
for armature_obj in armature_objs:
for bone in armature_obj.pose.bones:
bone.location = (0,0,0)
bone.rotation_quaternion = (1,0,0,0)
bone.scale = (1,1,1)
if action_data.name in bpy.data.actions:
action_obj =\
bpy.data.actions[action_data.name]
armature_obj.animation_data_clear()
armature_obj.animation_data_create()
armature_obj.animation_data.action = action_obj
# Time remapping
if context.scene.hecl_auto_remap:
bpy.context.scene.render.fps = 60
bpy.context.scene.render.frame_map_old = action_obj.hecl_fps
bpy.context.scene.render.frame_map_new = 60
bpy.context.scene.frame_start = 0
bpy.context.scene.frame_end = action_obj.frame_range[1] * (60 / action_obj.hecl_fps)
else:
bpy.context.scene.render.fps = action_obj.hecl_fps
bpy.context.scene.render.frame_map_old = action_obj.hecl_fps
bpy.context.scene.render.frame_map_new = action_obj.hecl_fps
bpy.context.scene.frame_start = 0
bpy.context.scene.frame_end = action_obj.frame_range[1]
# Events
#SACTEvent.clear_action_events(self, context, actor_data)
#SACTEvent.load_action_events(self, context, action_obj, 0)
# Time remapping
if context.scene.hecl_auto_remap:
bpy.context.scene.render.fps = 60
bpy.context.scene.render.frame_map_old = action_obj.hecl_fps
bpy.context.scene.render.frame_map_new = 60
bpy.context.scene.frame_start = 0
bpy.context.scene.frame_end = action_obj.frame_range[1] * (60 / action_obj.hecl_fps)
else:
bpy.context.scene.render.fps = action_obj.hecl_fps
bpy.context.scene.render.frame_map_old = action_obj.hecl_fps
bpy.context.scene.render.frame_map_new = action_obj.hecl_fps
bpy.context.scene.frame_start = 0
bpy.context.scene.frame_end = action_obj.frame_range[1]
armature_obj.animation_data_clear()
self.report({'WARNING'}, "Unable to load action; check HECL panel")
return {'FINISHED'}
# Events
#SACTEvent.clear_action_events(self, context, actor_data)
#SACTEvent.load_action_events(self, context, action_obj, 0)
return {'FINISHED'}
else:
armature_obj.animation_data_clear()
self.report({'WARNING'}, "Unable to load action; check HECL panel")
return {'FINISHED'}
return {'FINISHED'}
else:
self.report({'WARNING'}, "Unable to load armature; check HECL panel")

View File

@ -13,18 +13,25 @@ class SACTSubtypeOverlay(bpy.types.PropertyGroup):
linked_mesh = bpy.props.StringProperty(name="Linked Mesh Object Source", update=active_subtype_update)
show_overlay = bpy.props.BoolProperty(name="Show Overlay Mesh", update=active_subtype_update)
# Actor attachment class
class SACTAttachment(bpy.types.PropertyGroup):
name = bpy.props.StringProperty(name="Attachment Name")
linked_armature = bpy.props.StringProperty(name="Linked Armature Object Source", update=active_subtype_update)
linked_mesh = bpy.props.StringProperty(name="Linked Mesh Object Source", update=active_subtype_update)
show_attachment = bpy.props.BoolProperty(name="Show Attachment Mesh", update=active_subtype_update)
# Actor subtype class
class SACTSubtype(bpy.types.PropertyGroup):
name = bpy.props.StringProperty(name="Actor Mesh Name")
linked_armature = bpy.props.StringProperty(name="Linked Armature Object Source", update=active_subtype_update)
linked_mesh = bpy.props.StringProperty(name="Linked Mesh Object Source", update=active_subtype_update)
show_mesh = bpy.props.BoolProperty(name="Show Mesh", default=True, update=active_subtype_update)
overlays =\
bpy.props.CollectionProperty(type=SACTSubtypeOverlay, name="Subtype Overlay List")
active_overlay =\
bpy.props.IntProperty(name="Active Subtype Overlay", default=0, update=active_subtype_update)
# Panel draw
def draw(layout, context):
actor_data = context.scene.hecl_sact_data
@ -70,6 +77,7 @@ def draw(layout, context):
linked_mesh = None
if subtype.linked_mesh in bpy.data.objects:
linked_mesh = bpy.data.objects[subtype.linked_mesh]
layout.prop(subtype, 'show_mesh', text="Show Mesh")
# Mesh overlays
layout.label("Overlay Meshes:")
@ -84,12 +92,33 @@ def draw(layout, context):
if len(subtype.overlays) and subtype.active_overlay >= 0:
overlay = subtype.overlays[subtype.active_overlay]
layout.prop(overlay, 'name', text="Name")
overlay = subtype.overlays[subtype.active_overlay]
layout.prop_search(overlay, 'linked_mesh', bpy.data, 'objects', text="Mesh")
if overlay.linked_mesh in bpy.data.objects:
overlay_mesh = bpy.data.objects[overlay.linked_mesh]
layout.prop(overlay, 'show_overlay', text="Show Overlay")
# Mesh attachments
layout.label("Attachment Meshes:")
row = layout.row()
row.template_list("UI_UL_list", "SCENE_UL_SACTAttachments",
actor_data, 'attachments', actor_data, 'active_attachment')
col = row.column(align=True)
col.operator("scene.sactattachment_add", icon="ZOOMIN", text="")
col.operator("scene.sactattachment_remove", icon="ZOOMOUT", text="")
attachment_armature = linked_armature
attachment_mesh = None
if len(actor_data.attachments) and actor_data.active_attachment >= 0:
attachment = actor_data.attachments[actor_data.active_attachment]
layout.prop(attachment, 'name', text="Name")
layout.prop_search(attachment, 'linked_armature', bpy.data, 'objects', text="Armature")
if attachment.linked_armature in bpy.data.objects:
attachment_armature = bpy.data.objects[attachment.linked_armature]
layout.prop_search(attachment, 'linked_mesh', bpy.data, 'objects', text="Mesh")
if attachment.linked_mesh in bpy.data.objects:
attachment_mesh = bpy.data.objects[attachment.linked_mesh]
layout.prop(attachment, 'show_attachment', text="Show Attachment")
# Validate
if linked_mesh is None:
layout.label("Source mesh not set", icon='ERROR')
@ -103,11 +132,17 @@ def draw(layout, context):
if overlay_mesh:
if overlay_mesh.type != 'MESH':
layout.label("Overlay mesh not 'MESH'", icon='ERROR')
elif linked_armature is not None and overlay_mesh not in linked_armature.children:
layout.label(overlay_mesh.name+" not a child of "+linked_armature.name, icon='ERROR')
elif overlay_mesh.parent_type != 'ARMATURE':
layout.label("Overlay mesh not 'ARMATURE' parent type", icon='ERROR')
if attachment_mesh:
if attachment_mesh.type != 'MESH':
layout.label("Attachment mesh not 'MESH'", icon='ERROR')
elif attachment_armature is not None and attachment_mesh not in attachment_armature.children:
layout.label(attachment_mesh.name+" not a child of "+attachment_armature.name, icon='ERROR')
elif attachment_mesh.parent_type != 'ARMATURE':
layout.label("Attachment mesh not 'ARMATURE' parent type", icon='ERROR')
# Subtype 'add' operator
class SACTSubtype_add(bpy.types.Operator):
@ -190,28 +225,43 @@ class SACTSubtype_load(bpy.types.Operator):
object.hide = True
# Hide all meshes (incl overlays)
for mesh_name in actor_data.subtypes:
if mesh_name.linked_mesh in bpy.data.objects:
mesh = bpy.data.objects[mesh_name.linked_mesh]
for subtype_data in actor_data.subtypes:
if subtype_data.linked_mesh in bpy.data.objects:
mesh = bpy.data.objects[subtype_data.linked_mesh]
if mesh.name in context.scene.objects:
mesh.hide = True
for overlay in mesh_name.overlays:
for overlay in subtype_data.overlays:
if overlay.linked_mesh in bpy.data.objects:
mesh = bpy.data.objects[overlay.linked_mesh]
if mesh.name in context.scene.objects:
mesh.hide = True
# Hide/Show selected attachment meshes
for attachment in actor_data.attachments:
if attachment.linked_mesh in bpy.data.objects:
mesh_obj = bpy.data.objects[attachment.linked_mesh]
if mesh_obj.name in context.scene.objects:
mesh_obj.hide = not attachment.show_attachment
attachment_armature = linked_armature
if attachment.linked_armature in bpy.data.objects:
attachment_armature = bpy.data.objects[attachment.linked_armature]
if mesh_obj != attachment_armature:
mesh_obj.parent = attachment_armature
mesh_obj.parent_type = 'ARMATURE'
# Show only the chosen subtype (and selected overlays)
if subtype.linked_mesh in bpy.data.objects:
mesh_obj = bpy.data.objects[subtype.linked_mesh]
mesh_obj.hide = False
if subtype.show_mesh:
mesh_obj.hide = False
if mesh_obj != linked_armature:
mesh_obj.parent = linked_armature
mesh_obj.parent_type = 'ARMATURE'
for overlay in subtype.overlays:
if overlay.show_overlay and overlay.linked_mesh in bpy.data.objects:
if overlay.linked_mesh in bpy.data.objects:
mesh_obj = bpy.data.objects[overlay.linked_mesh]
mesh_obj.hide = False
if overlay.show_overlay:
mesh_obj.hide = False
if mesh_obj != linked_armature:
mesh_obj.parent = linked_armature
mesh_obj.parent_type = 'ARMATURE'
@ -275,11 +325,65 @@ class SACTSubtypeOverlay_remove(bpy.types.Operator):
subtype.active_overlay = 0
return {'FINISHED'}
# Subtype overlay 'add' operator
class SACTAttachment_add(bpy.types.Operator):
bl_idname = "scene.sactattachment_add"
bl_label = "New HECL Actor Attachment"
bl_description = "Add New HECL Actor Attachment"
@classmethod
def poll(cls, context):
actor_data = context.scene.hecl_sact_data
return (context.scene is not None and
not context.scene.library and
context.scene.hecl_type == 'ACTOR')
def execute(self, context):
actor_data = context.scene.hecl_sact_data
attachment_name = 'ActorAttachment'
if attachment_name in actor_data.attachments:
attachment_name = 'ActorAttachment.001'
attachment_idx = 1
while attachment_name in actor_data.attachments:
attachment_idx += 1
attachment_name = 'ActorAttachment.{:0>3}'.format(attachment_idx)
attachment = actor_data.attachments.add()
attachment.name = attachment_name
actor_data.active_attachment = len(actor_data.attachments)-1
return {'FINISHED'}
# Subtype overlay 'remove' operator
class SACTAttachment_remove(bpy.types.Operator):
bl_idname = "scene.sactattachment_remove"
bl_label = "Remove HECL Actor Attachment"
bl_description = "Remove HECL Actor Attachment"
@classmethod
def poll(cls, context):
actor_data = context.scene.hecl_sact_data
return (context.scene is not None and
not context.scene.library and
context.scene.hecl_type == 'ACTOR' and
actor_data.active_attachment >= 0 and
len(actor_data.attachments))
def execute(self, context):
actor_data = context.scene.hecl_sact_data
actor_data.attachments.remove(actor_data.active_attachment)
actor_data.active_attachment -= 1
if actor_data.active_attachment == -1:
actor_data.active_attachment = 0
return {'FINISHED'}
# Registration
def register():
bpy.utils.register_class(SACTSubtypeOverlay)
bpy.utils.register_class(SACTSubtypeOverlay_add)
bpy.utils.register_class(SACTSubtypeOverlay_remove)
bpy.utils.register_class(SACTAttachment)
bpy.utils.register_class(SACTAttachment_add)
bpy.utils.register_class(SACTAttachment_remove)
bpy.utils.register_class(SACTSubtype)
bpy.utils.register_class(SACTSubtype_add)
bpy.utils.register_class(SACTSubtype_remove)
@ -290,6 +394,9 @@ def unregister():
bpy.utils.unregister_class(SACTSubtype_add)
bpy.utils.unregister_class(SACTSubtype_remove)
bpy.utils.unregister_class(SACTSubtype_load)
bpy.utils.unregister_class(SACTAttachment)
bpy.utils.unregister_class(SACTAttachment_add)
bpy.utils.unregister_class(SACTAttachment_remove)
bpy.utils.unregister_class(SACTSubtypeOverlay)
bpy.utils.unregister_class(SACTSubtypeOverlay_add)
bpy.utils.unregister_class(SACTSubtypeOverlay_remove)

View File

@ -19,6 +19,11 @@ class SACTData(bpy.types.PropertyGroup):
show_subtypes =\
bpy.props.BoolProperty()
attachments = \
bpy.props.CollectionProperty(type=SACTSubtype.SACTAttachment, name="Attachment List")
active_attachment = \
bpy.props.IntProperty(name="Active Attachment", default=0, update=SACTSubtype.active_subtype_update)
actions =\
bpy.props.CollectionProperty(type=SACTAction.SACTAction, name="Actor Action List")
active_action =\
@ -268,6 +273,32 @@ def _out_subtypes(sact_data, writebuf):
else:
writebuf(struct.pack('I', 0))
def _out_attachments(sact_data, writebuf):
writebuf(struct.pack('I', len(sact_data.attachments)))
for attachment in sact_data.attachments:
writebuf(struct.pack('I', len(attachment.name)))
writebuf(attachment.name.encode())
mesh = None
if attachment.linked_mesh in bpy.data.objects:
mesh = bpy.data.objects[attachment.linked_mesh]
if mesh and mesh.library:
mesh_path = bpy.path.abspath(mesh.library.filepath)
writebuf(struct.pack('I', len(mesh_path)))
writebuf(mesh_path.encode())
else:
writebuf(struct.pack('I', 0))
arm = None
if attachment.linked_armature in bpy.data.objects:
arm = bpy.data.objects[attachment.linked_armature]
arm_idx = -1
if arm:
arm_idx = bpy.data.armatures.find(arm.name)
writebuf(struct.pack('i', arm_idx))
def _out_actions(sact_data, writebuf):
writebuf(struct.pack('I', len(sact_data.actions)))
for action_idx in range(len(sact_data.actions)):
@ -335,6 +366,9 @@ def cook(writebuf):
# Output subtypes
_out_subtypes(sact_data, writebuf)
# Output attachments
_out_attachments(sact_data, writebuf)
# Output actions
_out_actions(sact_data, writebuf)
@ -348,6 +382,9 @@ def cook_character_only(writebuf):
# Output subtypes
_out_subtypes(sact_data, writebuf)
# Output attachments
_out_attachments(sact_data, writebuf)
# Output no actions
writebuf(struct.pack('I', 0))
@ -387,6 +424,15 @@ def get_subtype_overlay_names(writebuf, subtypeName):
return
writebuf(struct.pack('I', 0))
# Access contained attachment names
def get_attachment_names(writebuf):
sact_data = bpy.context.scene.hecl_sact_data
writebuf(struct.pack('I', len(sact_data.attachments)))
for att_idx in range(len(sact_data.attachments)):
attachment = sact_data.attachments[att_idx]
writebuf(struct.pack('I', len(attachment.name)))
writebuf(attachment.name.encode())
# Access actor's contained action names
def get_action_names(writebuf):
sact_data = bpy.context.scene.hecl_sact_data

View File

@ -419,6 +419,10 @@ def dataout_loop():
writepipestr(b'OK')
hecl.sact.get_subtype_overlay_names(writepipebuf, subtypeName)
elif cmdargs[0] == 'GETATTACHMENTNAMES':
writepipestr(b'OK')
hecl.sact.get_attachment_names(writepipebuf)
elif cmdargs[0] == 'GETACTIONNAMES':
writepipestr(b'OK')
hecl.sact.get_action_names(writepipebuf)

2
hecl/extern/boo vendored

@ -1 +1 @@
Subproject commit bba2486c15498a307eb1c009edba09ec10a10294
Subproject commit f917d154b2ff38a5cbeea8c536c91e7813be060d

View File

@ -4,6 +4,7 @@
namespace hecl::Backend
{
struct ExtensionSlot;
using IR = Frontend::IR;
using Diagnostics = Frontend::Diagnostics;
@ -159,6 +160,9 @@ public:
return ret;
}
boo::AdditionalPipelineInfo additionalInfo(const ExtensionSlot& ext,
std::pair<BlendFactor, BlendFactor> blendFactors) const;
};
struct Function
@ -226,6 +230,44 @@ struct ExtensionSlot
}
};
inline boo::AdditionalPipelineInfo ShaderTag::additionalInfo(const ExtensionSlot& ext,
std::pair<BlendFactor, BlendFactor> blendFactors) const
{
boo::ZTest zTest;
switch (ext.depthTest)
{
case hecl::Backend::ZTest::Original:
default:
zTest = getDepthTest() ? boo::ZTest::LEqual : boo::ZTest::None;
break;
case hecl::Backend::ZTest::None:
zTest = boo::ZTest::None;
break;
case hecl::Backend::ZTest::LEqual:
zTest = boo::ZTest::LEqual;
break;
case hecl::Backend::ZTest::Greater:
zTest = boo::ZTest::Greater;
break;
case hecl::Backend::ZTest::Equal:
zTest = boo::ZTest::Equal;
break;
case hecl::Backend::ZTest::GEqual:
zTest = boo::ZTest::GEqual;
break;
}
return {
boo::BlendFactor((ext.srcFactor == BlendFactor::Original) ? blendFactors.first : ext.srcFactor),
boo::BlendFactor((ext.dstFactor == BlendFactor::Original) ? blendFactors.second : ext.dstFactor),
getPrimType(), zTest, ext.noDepthWrite ? false : getDepthWrite(),
!ext.noColorWrite, !ext.noAlphaWrite,
(ext.cullMode == hecl::Backend::CullMode::Original) ?
(getBackfaceCulling() ? boo::CullMode::Backface : boo::CullMode::None) :
boo::CullMode(ext.cullMode), !ext.noAlphaOverwrite
};
}
}
namespace std

View File

@ -504,6 +504,14 @@ struct Actor
Subtype(Connection& conn);
};
std::vector<Subtype> subtypes;
struct Attachment
{
std::string name;
ProjectPath mesh;
int32_t armature = -1;
Attachment(Connection& conn);
};
std::vector<Attachment> attachments;
std::vector<Action> actions;
Actor(Connection& conn);
@ -572,6 +580,7 @@ public:
std::vector<std::string> getSubtypeNames();
std::vector<std::string> getActionNames();
std::vector<std::string> getSubtypeOverlayNames(std::string_view name);
std::vector<std::string> getAttachmentNames();
std::unordered_map<std::string, Matrix3f> getBoneMatrices(std::string_view name);

View File

@ -83,6 +83,9 @@ public:
m_extension.texCount, m_extension.texs);
}
const hecl::Backend::ShaderTag& getTag() const { return m_tag; }
const hecl::Backend::ExtensionSlot& extension() const { return m_extension; }
std::pair<hecl::Backend::BlendFactor, hecl::Backend::BlendFactor> blendFactors() const
{ return {m_backend.m_blendSrc, m_backend.m_blendDst}; }
};
template<typename P>
@ -134,6 +137,7 @@ StageCollection<T<P, Rest...>>::StageCollection(PipelineConverter<P>& conv, Fact
m_fragment = conv.getFragmentConverter().convert(ctx, StageSourceText<P, PipelineStage::Fragment>(in.makeFrag()));
m_vtxFmtData = in.getTag().vertexFormat();
m_vtxFmt = boo::VertexFormatInfo(m_vtxFmtData.size(), m_vtxFmtData.data());
m_additionalInfo = in.getTag().additionalInfo(in.extension(), in.blendFactors());
MakeHash();
}

View File

@ -66,9 +66,7 @@ public:
uint64_t Hash() const { return m_hash; }
explicit StageSourceText(std::string_view text)
{
m_hash = XXH64(m_text.data(), m_text.size(), 0);
}
: m_text(text), m_hash(XXH64(m_text.data(), m_text.size(), 0)) {}
std::string_view text() const { return m_text; }
};

View File

@ -834,37 +834,7 @@ public:
* @param replace remove existing extension (if any) before appending new extension
* @return new path with extension
*/
ProjectPath getWithExtension(const SystemChar* ext, bool replace=false) const
{
ProjectPath pp(*this);
if (replace)
{
auto relIt = pp.m_relPath.end();
if (relIt != pp.m_relPath.begin())
--relIt;
auto absIt = pp.m_absPath.end();
if (absIt != pp.m_absPath.begin())
--absIt;
while (relIt != pp.m_relPath.begin() && *relIt != _S('.') && *relIt != _S('/'))
{
--relIt;
--absIt;
}
if (*relIt == _S('.') && relIt != pp.m_relPath.begin())
{
pp.m_relPath.resize(relIt - pp.m_relPath.begin());
pp.m_absPath.resize(absIt - pp.m_absPath.begin());
}
}
if (ext)
{
pp.m_relPath += ext;
pp.m_absPath += ext;
}
pp.ComputeHash();
return pp;
}
ProjectPath getWithExtension(const SystemChar* ext, bool replace=false) const;
/**
* @brief Access fully-canonicalized absolute path
@ -1063,7 +1033,10 @@ public:
*/
ProjectPath ensureAuxInfo(SystemStringView auxStr) const
{
return ProjectPath(getProject(), SystemString(getRelativePath()) + _S('|') + auxStr.data());
if (auxStr.empty())
return ProjectPath(getProject(), getRelativePath());
else
return ProjectPath(getProject(), SystemString(getRelativePath()) + _S('|') + auxStr.data());
}
#if HECL_UCS2

View File

@ -1546,6 +1546,12 @@ Actor::Actor(Connection& conn)
for (uint32_t i=0 ; i<subtypeCount ; ++i)
subtypes.emplace_back(conn);
uint32_t attachmentCount;
conn._readBuf(&attachmentCount, 4);
attachments.reserve(attachmentCount);
for (uint32_t i=0 ; i<attachmentCount ; ++i)
attachments.emplace_back(conn);
uint32_t actionCount;
conn._readBuf(&actionCount, 4);
actions.reserve(actionCount);
@ -1677,6 +1683,29 @@ Actor::Subtype::Subtype(Connection& conn)
}
}
Actor::Attachment::Attachment(Connection& conn)
{
uint32_t bufSz;
conn._readBuf(&bufSz, 4);
name.assign(bufSz, ' ');
conn._readBuf(&name[0], bufSz);
std::string meshPath;
conn._readBuf(&bufSz, 4);
if (bufSz)
{
meshPath.assign(bufSz, ' ');
conn._readBuf(&meshPath[0], bufSz);
SystemStringConv meshPathAbs(meshPath);
SystemString meshPathRel =
conn.getBlendPath().getProject().getProjectRootPath().getProjectRelativeFromAbsolute(meshPathAbs.sys_str());
mesh.assign(conn.getBlendPath().getProject().getProjectWorkingPath(), meshPathRel);
}
conn._readBuf(&armature, 4);
}
Action::Action(Connection& conn)
{
uint32_t bufSz;
@ -2234,6 +2263,37 @@ std::vector<std::string> DataStream::getSubtypeOverlayNames(std::string_view nam
return ret;
}
std::vector<std::string> DataStream::getAttachmentNames()
{
if (m_parent->getBlendType() != BlendType::Actor)
BlenderLog.report(logvisor::Fatal, _S("%s is not an ACTOR blend"),
m_parent->getBlendPath().getAbsolutePath().data());
m_parent->_writeStr("GETATTACHMENTNAMES");
char readBuf[256];
m_parent->_readStr(readBuf, 256);
if (strcmp(readBuf, "OK"))
BlenderLog.report(logvisor::Fatal, "unable to get attachments of actor: %s", readBuf);
std::vector<std::string> ret;
uint32_t attCount;
m_parent->_readBuf(&attCount, 4);
ret.reserve(attCount);
for (uint32_t i=0 ; i<attCount ; ++i)
{
ret.emplace_back();
std::string& name = ret.back();
uint32_t bufSz;
m_parent->_readBuf(&bufSz, 4);
name.assign(bufSz, ' ');
m_parent->_readBuf(&name[0], bufSz);
}
return ret;
}
std::unordered_map<std::string, Matrix3f>
DataStream::getBoneMatrices(std::string_view name)
{

View File

@ -119,6 +119,38 @@ void ProjectPath::assign(const ProjectPath& parentPath, std::string_view path)
}
#endif
ProjectPath ProjectPath::getWithExtension(const SystemChar* ext, bool replace) const
{
ProjectPath pp(*this);
if (replace)
{
auto relIt = pp.m_relPath.end();
if (relIt != pp.m_relPath.begin())
--relIt;
auto absIt = pp.m_absPath.end();
if (absIt != pp.m_absPath.begin())
--absIt;
while (relIt != pp.m_relPath.begin() && *relIt != _S('.') && *relIt != _S('/'))
{
--relIt;
--absIt;
}
if (*relIt == _S('.') && relIt != pp.m_relPath.begin())
{
pp.m_relPath.resize(relIt - pp.m_relPath.begin());
pp.m_absPath.resize(absIt - pp.m_absPath.begin());
}
}
if (ext)
{
pp.m_relPath += ext;
pp.m_absPath += ext;
}
pp.ComputeHash();
return pp;
}
ProjectPath ProjectPath::getCookedPath(const Database::DataSpecEntry& spec) const
{
ProjectPath woExt = getWithExtension(nullptr, true);