diff --git a/Editor/ProjectResourceFactoryBase.cpp b/Editor/ProjectResourceFactoryBase.cpp index a7c892d1f..1de0f70de 100644 --- a/Editor/ProjectResourceFactoryBase.cpp +++ b/Editor/ProjectResourceFactoryBase.cpp @@ -11,15 +11,6 @@ void ProjectResourceFactoryBase::Clear() m_catalogNameToTag.clear(); } -hecl::BlenderConnection& ProjectResourceFactoryBase::GetBackgroundBlender() const -{ - std::experimental::optional& shareConn = - ((ProjectResourceFactoryBase*)this)->m_backgroundBlender; - if (!shareConn) - shareConn.emplace(hecl::VerbosityLevel); - return *shareConn; -} - void ProjectResourceFactoryBase::ReadCatalog(const hecl::ProjectPath& catalogPath, athena::io::YAMLDocWriter& nameWriter) { @@ -40,7 +31,7 @@ void ProjectResourceFactoryBase::ReadCatalog(const hecl::ProjectPath& catalogPat hecl::ProjectPath path(m_proj->getProjectWorkingPath(), p.second->m_scalarString); if (path.getPathType() != hecl::ProjectPath::Type::File) continue; - SObjectTag pathTag = TagFromPath(path); + SObjectTag pathTag = TagFromPath(path, m_backgroundBlender); if (pathTag) { std::unique_lock lk(m_backgroundIndexMutex); @@ -119,7 +110,7 @@ void ProjectResourceFactoryBase::BackgroundIndexRecursiveProc(const hecl::Projec } /* Classify intermediate into tag */ - SObjectTag pathTag = TagFromPath(path); + SObjectTag pathTag = TagFromPath(path, m_backgroundBlender); if (pathTag) { std::unique_lock lk(m_backgroundIndexMutex); @@ -232,11 +223,7 @@ void ProjectResourceFactoryBase::BackgroundIndexProc() nameWriter.finish(); fclose(nameFile); - if (m_backgroundBlender) - { - m_backgroundBlender->quitBlender(); - m_backgroundBlender = std::experimental::nullopt; - } + m_backgroundBlender.shutdown(); Log.report(logvisor::Info, _S("Background index of '%s' complete; %d tags, %d names"), m_origSpec->m_name, m_tagToPath.size(), m_catalogNameToTag.size()); m_backgroundRunning = false; @@ -293,6 +280,16 @@ CFactoryFnReturn ProjectResourceFactoryBase::BuildSync(const SObjectTag& tag, return {}; } + /* Last chance type validation */ + urde::SObjectTag verifyTag = TagFromPath(path, hecl::SharedBlenderToken); + if (verifyTag.type != tag.type) + { + Log.report(logvisor::Error, _S("%s: expected type '%.4s', found '%.4s'"), + path.getRelativePath().c_str(), + tag.type.toString().c_str(), verifyTag.type.toString().c_str()); + return {}; + } + /* Get cooked representation path */ hecl::ProjectPath cooked = GetCookedPath(path, true); @@ -329,7 +326,8 @@ CFactoryFnReturn ProjectResourceFactoryBase::BuildSync(const SObjectTag& tag, return m_factoryMgr.MakeObject(tag, fr, paramXfer); } -void ProjectResourceFactoryBase::AsyncTask::EnsurePath(const hecl::ProjectPath& path) +void ProjectResourceFactoryBase::AsyncTask::EnsurePath(const urde::SObjectTag& tag, + const hecl::ProjectPath& path) { if (!m_workingPath) { @@ -339,7 +337,18 @@ void ProjectResourceFactoryBase::AsyncTask::EnsurePath(const hecl::ProjectPath& if (path.getPathType() != hecl::ProjectPath::Type::File) { Log.report(logvisor::Error, _S("unable to find resource path '%s'"), - path.getAbsolutePath().c_str()); + path.getRelativePath().c_str()); + m_failed = true; + return; + } + + /* Last chance type validation */ + urde::SObjectTag verifyTag = m_parent.TagFromPath(path, hecl::SharedBlenderToken); + if (verifyTag.type != tag.type) + { + Log.report(logvisor::Error, _S("%s: expected type '%.4s', found '%.4s'"), + path.getRelativePath().c_str(), + tag.type.toString().c_str(), verifyTag.type.toString().c_str()); m_failed = true; return; } @@ -425,6 +434,7 @@ std::unique_ptr ProjectResourceFactoryBase::Build(const urde::SObjec else return {}; } + lk.unlock(); return BuildSync(tag, search->second, paramXfer); } @@ -526,7 +536,8 @@ void ProjectResourceFactoryBase::AsyncIdle() } continue; } - task.EnsurePath(search->second); + lk.unlock(); + task.EnsurePath(task.x0_tag, search->second); /* Pump load pipeline (cooking if needed) */ if (task.AsyncPump()) diff --git a/Editor/ProjectResourceFactoryBase.hpp b/Editor/ProjectResourceFactoryBase.hpp index 72e7bae28..a21caf8c3 100644 --- a/Editor/ProjectResourceFactoryBase.hpp +++ b/Editor/ProjectResourceFactoryBase.hpp @@ -29,7 +29,7 @@ protected: std::unique_ptr m_cookSpec; urde::CFactoryMgr m_factoryMgr; - std::experimental::optional m_backgroundBlender; + hecl::BlenderToken m_backgroundBlender; std::thread m_backgroundIndexTh; std::mutex m_backgroundIndexMutex; bool m_backgroundRunning = false; @@ -56,15 +56,15 @@ protected: IObj** ptr, const CVParamTransfer& xfer) : m_parent(parent), x0_tag(tag), xc_targetPtr(ptr), x18_cvXfer(xfer) {} - void EnsurePath(const hecl::ProjectPath& path); + void EnsurePath(const urde::SObjectTag& tag, + const hecl::ProjectPath& path); void CookComplete(); bool AsyncPump(); }; std::unordered_map m_asyncLoadList; - virtual SObjectTag TagFromPath(const hecl::ProjectPath& path) const=0; + virtual SObjectTag TagFromPath(const hecl::ProjectPath& path, hecl::BlenderToken& btok) const=0; - hecl::BlenderConnection& GetBackgroundBlender() const; void ReadCatalog(const hecl::ProjectPath& catalogPath, athena::io::YAMLDocWriter& nameWriter); void BackgroundIndexRecursiveProc(const hecl::ProjectPath& path, diff --git a/Editor/ProjectResourceFactoryMP1.cpp b/Editor/ProjectResourceFactoryMP1.cpp index b9fcbf37f..0586934f5 100644 --- a/Editor/ProjectResourceFactoryMP1.cpp +++ b/Editor/ProjectResourceFactoryMP1.cpp @@ -36,11 +36,11 @@ void ProjectResourceFactoryMP1::IndexMP1Resources(hecl::Database::Project& proj) BeginBackgroundIndex(proj, DataSpec::SpecEntMP1, DataSpec::SpecEntMP1PC); } -SObjectTag ProjectResourceFactoryMP1::TagFromPath(const hecl::ProjectPath& path) const +SObjectTag ProjectResourceFactoryMP1::TagFromPath(const hecl::ProjectPath& path, hecl::BlenderToken& btok) const { if (hecl::IsPathBlend(path)) { - hecl::BlenderConnection& conn = GetBackgroundBlender(); + hecl::BlenderConnection& conn = btok.getBlenderConnection(); if (!conn.openBlend(path)) return {}; diff --git a/Editor/ProjectResourceFactoryMP1.hpp b/Editor/ProjectResourceFactoryMP1.hpp index ad458f8ee..a5db6dd93 100644 --- a/Editor/ProjectResourceFactoryMP1.hpp +++ b/Editor/ProjectResourceFactoryMP1.hpp @@ -11,7 +11,7 @@ class ProjectResourceFactoryMP1 : public ProjectResourceFactoryBase public: ProjectResourceFactoryMP1(hecl::ClientProcess& clientProc); void IndexMP1Resources(hecl::Database::Project& proj); - SObjectTag TagFromPath(const hecl::ProjectPath& path) const; + SObjectTag TagFromPath(const hecl::ProjectPath& path, hecl::BlenderToken& btok) const; }; } diff --git a/Editor/main.cpp b/Editor/main.cpp index 80e6ca8e8..6c587e654 100644 --- a/Editor/main.cpp +++ b/Editor/main.cpp @@ -61,6 +61,7 @@ struct Application : boo::IApplicationCallback void initialize(boo::IApplication* app) { zeus::detectCPU(); + //hecl::VerbosityLevel = 1; const zeus::CPUInfo& cpuInf = zeus::cpuFeatures(); Log.report(logvisor::Info, "CPU Name: %s", cpuInf.cpuBrand); diff --git a/Runtime/Graphics/CGraphics.hpp b/Runtime/Graphics/CGraphics.hpp index f4a2d838d..26bf73825 100644 --- a/Runtime/Graphics/CGraphics.hpp +++ b/Runtime/Graphics/CGraphics.hpp @@ -137,17 +137,18 @@ struct SClipScreenRect enum class ETexelFormat { - I4 = 0, - I8 = 1, - IA4 = 2, - IA8 = 3, - C4 = 4, - C8 = 5, - C14X2 = 6, - RGB565 = 7, - RGB5A3 = 8, - RGBA8 = 9, - CMPR = 10 + I4 = 0, + I8 = 1, + IA4 = 2, + IA8 = 3, + C4 = 4, + C8 = 5, + C14X2 = 6, + RGB565 = 7, + RGB5A3 = 8, + RGBA8 = 9, + CMPR = 10, + RGBA8PC = 16 }; class CGraphics diff --git a/Runtime/Graphics/CModel.hpp b/Runtime/Graphics/CModel.hpp index 56af7efff..48a877423 100644 --- a/Runtime/Graphics/CModel.hpp +++ b/Runtime/Graphics/CModel.hpp @@ -82,6 +82,7 @@ private: void ProcessAnimation(const UVAnimation& anim); void PadOutBuffer(); void Update(const MaterialSet* matSet); + operator bool() const {return m_buffer.size() != 0;} } m_uvAnimBuffer; /* urde addition: boo! */ diff --git a/Runtime/Graphics/CModelBoo.cpp b/Runtime/Graphics/CModelBoo.cpp index 22bd83174..42664c583 100644 --- a/Runtime/Graphics/CModelBoo.cpp +++ b/Runtime/Graphics/CModelBoo.cpp @@ -290,9 +290,12 @@ void CBooModel::UpdateUniformData() const unskinnedXf.proj = CGraphics::GetPerspectiveProjectionMatrix(); m_unskinnedXfBuffer->load(&unskinnedXf, sizeof(unskinnedXf)); - ((CBooModel*)this)->m_uvAnimBuffer.Update(x4_matSet); - m_uvMtxBuffer->load(m_uvAnimBuffer.m_buffer.data(), - m_uvAnimBuffer.m_buffer.size() * 64); + if (m_uvAnimBuffer) + { + ((CBooModel*)this)->m_uvAnimBuffer.Update(x4_matSet); + m_uvMtxBuffer->load(m_uvAnimBuffer.m_buffer.data(), + m_uvAnimBuffer.m_buffer.size() * 64); + } } void CBooModel::DrawAlpha(const CModelFlags& flags) const @@ -331,7 +334,7 @@ CModel::CModel(std::unique_ptr&& in, u32 dataLen, IObjectStore* store) { u32 version = hecl::SBig(*reinterpret_cast(x0_data.get() + 0x4)); u32 flags = hecl::SBig(*reinterpret_cast(x0_data.get() + 0x8)); - if (version != 16) + if (version != 0x10002) Log.report(logvisor::Fatal, "invalid CMDL for loading with boo"); u32 secCount = hecl::SBig(*reinterpret_cast(x0_data.get() + 0x24)); @@ -395,7 +398,7 @@ CModel::CModel(std::unique_ptr&& in, u32 dataLen, IObjectStore* store) surf.m_data.read(r); } - const float* aabbPtr = reinterpret_cast(x0_data.get() + 0x18); + const float* aabbPtr = reinterpret_cast(x0_data.get() + 0xc); zeus::CAABox aabb(hecl::SBig(aabbPtr[0]), hecl::SBig(aabbPtr[1]), hecl::SBig(aabbPtr[2]), hecl::SBig(aabbPtr[3]), hecl::SBig(aabbPtr[4]), hecl::SBig(aabbPtr[5])); x28_modelInst = std::make_unique(&x8_surfaces, x18_matSets[0], diff --git a/Runtime/Graphics/CTexture.hpp b/Runtime/Graphics/CTexture.hpp index b49f86e0f..c869cd6fd 100644 --- a/Runtime/Graphics/CTexture.hpp +++ b/Runtime/Graphics/CTexture.hpp @@ -34,6 +34,7 @@ class CTexture void BuildRGB5A3FromGCN(CInputStream& in); void BuildRGBA8FromGCN(CInputStream& in); void BuildDXT1FromGCN(CInputStream& in); + void BuildRGBA8(CInputStream& in); public: CTexture(CInputStream& in); diff --git a/Runtime/Graphics/CTextureBoo.cpp b/Runtime/Graphics/CTextureBoo.cpp index 36220d7f3..b52325595 100644 --- a/Runtime/Graphics/CTextureBoo.cpp +++ b/Runtime/Graphics/CTextureBoo.cpp @@ -5,6 +5,7 @@ namespace urde { +static logvisor::Module Log("urde::CTextureBoo"); /* GX uses this upsampling technique to prevent banding on downsampled texture formats */ static inline uint8_t Convert3To8(uint8_t v) @@ -647,6 +648,19 @@ void CTexture::BuildDXT1FromGCN(CInputStream& in) }); } +void CTexture::BuildRGBA8(CInputStream& in) +{ + size_t texelCount = ComputeMippedTexelCount(); + std::unique_ptr buf = in.readBytes(texelCount * 4); + + m_booToken = CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool + { + m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, + buf.get(), texelCount * 4); + return true; + }); +} + CTexture::CTexture(CInputStream& in) { x0_fmt = ETexelFormat(in.readUint32Big()); @@ -689,6 +703,11 @@ CTexture::CTexture(CInputStream& in) case ETexelFormat::CMPR: BuildDXT1FromGCN(in); break; + case ETexelFormat::RGBA8PC: + BuildRGBA8(in); + break; + default: + Log.report(logvisor::Fatal, "invalid texture type %d for boo", int(x0_fmt)); } } diff --git a/hecl b/hecl index d3c1e6590..51349be32 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit d3c1e65900b309c3d4c805e99c03dd1fc91818bb +Subproject commit 51349be32ab052618e02a82a8e21b495b5b00432