diff --git a/source/game/StarHumanoid.cpp b/source/game/StarHumanoid.cpp index b19410a..418e88d 100644 --- a/source/game/StarHumanoid.cpp +++ b/source/game/StarHumanoid.cpp @@ -1374,4 +1374,35 @@ Json const& Humanoid::defaultMovementParameters() const { return m_defaultMovementParameters; } +pair Humanoid::extractScaleFromDirectives(Directives const& directives) { + if (!directives) + return make_pair(Vec2F::filled(1.f), Directives()); + + List operations; + size_t totalLength = 0; + Maybe scale; + + for (auto& entry : directives.shared->entries) { + auto string = entry.string(*directives.shared); + const ScaleImageOperation* op = nullptr; + if (string.beginsWith("scalenearest") && string.utf8().find("skip") == NPos) + op = entry.loadOperation(*directives.shared).ptr(); + + if (op) + scale = scale.value(Vec2F::filled(1.f)).piecewiseMultiply(op->scale); + else + totalLength += operations.emplace_back(string).utf8Size(); + } + + if (!scale) + return make_pair(Vec2F::filled(1.f), directives); + + String mergedDirectives; + mergedDirectives.reserve(totalLength); + for (auto& directive : operations) + mergedDirectives.append(directive.utf8Ptr(), directive.utf8Size()); + + return make_pair(*scale, Directives(mergedDirectives)); +} + } diff --git a/source/game/StarHumanoid.hpp b/source/game/StarHumanoid.hpp index e6d89cb..3f8296b 100644 --- a/source/game/StarHumanoid.hpp +++ b/source/game/StarHumanoid.hpp @@ -240,6 +240,10 @@ public: Json const& defaultMovementParameters() const; + // Extracts scalenearest from directives and returns the combined scale and + // a new Directives without those scalenearest directives. + static pair extractScaleFromDirectives(Directives const& directives); + private: struct HandDrawingInfo { List itemDrawables; diff --git a/source/game/StarNpc.cpp b/source/game/StarNpc.cpp index 5450e6f..d45f416 100644 --- a/source/game/StarNpc.cpp +++ b/source/game/StarNpc.cpp @@ -475,10 +475,19 @@ void Npc::render(RenderCallback* renderCallback) { renderLayer = loungeAnchor->loungeRenderLayer; m_tools->setupHumanoidHandItemDrawables(m_humanoid); + + DirectivesGroup humanoidDirectives; + Vec2F scale = Vec2F::filled(1.f); + for (auto& directives : m_statusController->parentDirectives().list()) { + auto result = Humanoid::extractScaleFromDirectives(directives); + scale = scale.piecewiseMultiply(result.first); + humanoidDirectives.append(result.second); + } + for (auto& drawable : m_humanoid.render()) { drawable.translate(position()); if (drawable.isImage()) - drawable.imagePart().addDirectivesGroup(m_statusController->parentDirectives(), true); + drawable.imagePart().addDirectivesGroup(humanoidDirectives, true); renderCallback->addDrawable(std::move(drawable), renderLayer); } diff --git a/source/game/StarPlayer.cpp b/source/game/StarPlayer.cpp index 7d751af..07196b6 100644 --- a/source/game/StarPlayer.cpp +++ b/source/game/StarPlayer.cpp @@ -373,11 +373,25 @@ List Player::drawables() const { drawables.appendAll(m_techController->backDrawables()); if (!m_techController->parentHidden()) { m_tools->setupHumanoidHandItemDrawables(*m_humanoid); + + // Auto-detect any ?scalenearest and apply them as a direct scale on the Humanoid's drawables instead. + DirectivesGroup humanoidDirectives; + Vec2F scale = Vec2F::filled(1.f); + auto extractScale = [&](List const& list) { + for (auto& directives : list) { + auto result = Humanoid::extractScaleFromDirectives(directives); + scale = scale.piecewiseMultiply(result.first); + humanoidDirectives.append(result.second); + } + }; + extractScale(m_techController->parentDirectives().list()); + extractScale(m_statusController->parentDirectives().list()); + for (auto& drawable : m_humanoid->render()) { + drawable.scale(scale); drawable.translate(position() + m_techController->parentOffset()); if (drawable.isImage()) { - drawable.imagePart().addDirectivesGroup(m_techController->parentDirectives(), true); - drawable.imagePart().addDirectivesGroup(m_statusController->parentDirectives(), true); + drawable.imagePart().addDirectivesGroup(humanoidDirectives, true); if (auto anchor = as(m_movementController->entityAnchor())) { if (auto& directives = anchor->directives)