Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2024-04-23 11:48:51 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2024-04-23 11:48:51 +1000
commit7136c929cea0ddf955ab69a8ff5a4394bedacea8 (patch)
treed17322f98b5614eadeb086dae70d6fbd81d84934
parented3793ab004e1c6d21225f34c8369d12f6525334 (diff)
micro-opt NetworkedAnimator drawables
sort before creating drawables
-rw-r--r--source/base/StarAnimatedPartSet.cpp10
-rw-r--r--source/base/StarAnimatedPartSet.hpp85
-rw-r--r--source/game/StarNetworkedAnimator.cpp174
-rw-r--r--source/game/StarNetworkedAnimator.hpp4
-rw-r--r--source/game/items/StarActiveItem.cpp2
5 files changed, 155 insertions, 120 deletions
diff --git a/source/base/StarAnimatedPartSet.cpp b/source/base/StarAnimatedPartSet.cpp
index 9133921..5ffc68f 100644
--- a/source/base/StarAnimatedPartSet.cpp
+++ b/source/base/StarAnimatedPartSet.cpp
@@ -106,7 +106,7 @@ StringList AnimatedPartSet::states(String const& stateTypeName) const {
return m_stateTypes.get(stateTypeName).states.keys();
}
-StringList AnimatedPartSet::parts() const {
+StringList AnimatedPartSet::partNames() const {
return m_parts.keys();
}
@@ -148,6 +148,14 @@ AnimatedPartSet::ActivePartInformation const& AnimatedPartSet::activePart(String
return part.activePart;
}
+StringMap<AnimatedPartSet::Part> const& AnimatedPartSet::constParts() const {
+ return m_parts;
+}
+
+StringMap<AnimatedPartSet::Part>& AnimatedPartSet::parts() {
+ return m_parts;
+}
+
void AnimatedPartSet::forEachActiveState(function<void(String const&, ActiveStateInformation const&)> callback) const {
for (auto const& p : m_stateTypes) {
const_cast<AnimatedPartSet*>(this)->freshenActiveState(const_cast<StateType&>(p.second));
diff --git a/source/base/StarAnimatedPartSet.hpp b/source/base/StarAnimatedPartSet.hpp
index 8cc2ef3..a608924 100644
--- a/source/base/StarAnimatedPartSet.hpp
+++ b/source/base/StarAnimatedPartSet.hpp
@@ -56,6 +56,46 @@ public:
JsonObject properties;
};
+ enum AnimationMode {
+ End,
+ Loop,
+ Transition
+ };
+
+ struct State {
+ unsigned frames;
+ float cycle;
+ AnimationMode animationMode;
+ String transitionState;
+ JsonObject stateProperties;
+ JsonObject stateFrameProperties;
+ };
+
+ struct StateType {
+ float priority;
+ bool enabled;
+ String defaultState;
+ JsonObject stateTypeProperties;
+ OrderedHashMap<String, shared_ptr<State const>> states;
+
+ ActiveStateInformation activeState;
+ State const* activeStatePointer;
+ bool activeStateDirty;
+ };
+
+ struct PartState {
+ JsonObject partStateProperties;
+ JsonObject partStateFrameProperties;
+ };
+
+ struct Part {
+ JsonObject partProperties;
+ StringMap<StringMap<PartState>> partStates;
+
+ ActivePartInformation activePart;
+ bool activePartDirty;
+ };
+
AnimatedPartSet();
AnimatedPartSet(Json config);
@@ -71,7 +111,7 @@ public:
// Returns the available states for the given state type.
StringList states(String const& stateTypeName) const;
- StringList parts() const;
+ StringList partNames() const;
// Sets the active state for this state type. If the state is different than
// the previously set state, will start the new states animation off at the
@@ -86,6 +126,9 @@ public:
ActiveStateInformation const& activeState(String const& stateTypeName) const;
ActivePartInformation const& activePart(String const& partName) const;
+ StringMap<Part> const& constParts() const;
+ StringMap<Part>& parts();
+
// Function will be given the name of each state type, and the
// ActiveStateInformation for the active state for that state type.
void forEachActiveState(function<void(String const&, ActiveStateInformation const&)> callback) const;
@@ -108,46 +151,6 @@ public:
void finishAnimations();
private:
- enum AnimationMode {
- End,
- Loop,
- Transition
- };
-
- struct State {
- unsigned frames;
- float cycle;
- AnimationMode animationMode;
- String transitionState;
- JsonObject stateProperties;
- JsonObject stateFrameProperties;
- };
-
- struct StateType {
- float priority;
- bool enabled;
- String defaultState;
- JsonObject stateTypeProperties;
- OrderedHashMap<String, shared_ptr<State const>> states;
-
- ActiveStateInformation activeState;
- State const* activeStatePointer;
- bool activeStateDirty;
- };
-
- struct PartState {
- JsonObject partStateProperties;
- JsonObject partStateFrameProperties;
- };
-
- struct Part {
- JsonObject partProperties;
- StringMap<StringMap<PartState>> partStates;
-
- ActivePartInformation activePart;
- bool activePartDirty;
- };
-
static AnimationMode stringToAnimationMode(String const& string);
void freshenActiveState(StateType& stateType);
diff --git a/source/game/StarNetworkedAnimator.cpp b/source/game/StarNetworkedAnimator.cpp
index ccec4fd..a974a3a 100644
--- a/source/game/StarNetworkedAnimator.cpp
+++ b/source/game/StarNetworkedAnimator.cpp
@@ -307,10 +307,18 @@ String NetworkedAnimator::state(String const& stateType) const {
return m_animatedParts.activeState(stateType).stateName;
}
-StringList NetworkedAnimator::parts() const {
+StringMap<AnimatedPartSet::Part> const& NetworkedAnimator::constParts() const {
+ return m_animatedParts.constParts();
+}
+
+StringMap<AnimatedPartSet::Part>& NetworkedAnimator::parts() {
return m_animatedParts.parts();
}
+StringList NetworkedAnimator::partNames() const {
+ return m_animatedParts.partNames();
+}
+
Json NetworkedAnimator::stateProperty(String const& stateType, String const& propertyName) const {
return m_animatedParts.activeState(stateType).properties.value(propertyName);
}
@@ -573,6 +581,10 @@ List<Drawable> NetworkedAnimator::drawables(Vec2F const& position) const {
}
List<pair<Drawable, float>> NetworkedAnimator::drawablesWithZLevel(Vec2F const& position) const {
+ size_t partCount = m_animatedParts.constParts().size();
+ if (!partCount)
+ return {};
+
List<Directives> baseProcessingDirectives = { m_processingDirectives.get() };
for (auto& pair : m_effects) {
auto const& effectState = pair.second;
@@ -591,93 +603,103 @@ List<pair<Drawable, float>> NetworkedAnimator::drawablesWithZLevel(Vec2F const&
}
}
- List<pair<Drawable, float>> drawables;
-
+ List<tuple<AnimatedPartSet::ActivePartInformation const*, String const*, float>> parts;
+ parts.reserve(partCount);
m_animatedParts.forEachActivePart([&](String const& partName, AnimatedPartSet::ActivePartInformation const& activePart) {
- // Make sure we don't copy the original image
- String fallback = "";
- Json jImage = activePart.properties.value("image", {});
- String const& image = jImage.isType(Json::Type::String) ? *jImage.stringPtr() : fallback;
+ Maybe<float> maybeZLevel;
+ if (m_flipped.get()) {
+ if (auto maybeFlipped = activePart.properties.value("flippedZLevel").optFloat())
+ maybeZLevel = *maybeFlipped;
+ }
+ if (!maybeZLevel)
+ maybeZLevel = activePart.properties.value("zLevel").optFloat();
- bool centered = activePart.properties.value("centered").optBool().value(true);
- bool fullbright = activePart.properties.value("fullbright").optBool().value(false);
+ parts.append(make_tuple(&activePart, &partName, maybeZLevel.value(0.0f)));
+ });
- auto maybeZLevel = activePart.properties.value("zLevel").optFloat();
- if (m_flipped.get())
- maybeZLevel = activePart.properties.value("flippedZLevel").optFloat().orMaybe(maybeZLevel);
- float zLevel = maybeZLevel.value(0.0f);
+ sort(parts, [](auto const& a, auto const& b) { return get<2>(a) < get<2>(b); });
+
+ List<pair<Drawable, float>> drawables;
+ drawables.reserve(partCount);
+ for (auto& entry : parts) {
+ auto& activePart = *get<0>(entry);
+ auto& partName = *get<1>(entry);
+ // Make sure we don't copy the original image
+ String fallback = "";
+ Json jImage = activePart.properties.value("image", {});
+ String const& image = jImage.isType(Json::Type::String) ? *jImage.stringPtr() : fallback;
+
+ bool centered = activePart.properties.value("centered").optBool().value(true);
+ bool fullbright = activePart.properties.value("fullbright").optBool().value(false);
+
+ size_t originalDirectivesSize = baseProcessingDirectives.size();
+ if (auto directives = activePart.properties.value("processingDirectives").optString()) {
+ baseProcessingDirectives.append(*directives);
+ }
- size_t originalDirectivesSize = baseProcessingDirectives.size();
- if (auto directives = activePart.properties.value("processingDirectives").optString()) {
+ Maybe<unsigned> frame;
+ String frameStr;
+ String frameIndexStr;
+ if (activePart.activeState) {
+ unsigned stateFrame = activePart.activeState->frame;
+ frame = stateFrame;
+ frameStr = static_cast<String>(toString(stateFrame + 1));
+ frameIndexStr = static_cast<String>(toString(stateFrame));
+
+ if (auto directives = activePart.activeState->properties.value("processingDirectives").optString()) {
baseProcessingDirectives.append(*directives);
}
+ }
- Maybe<unsigned> frame;
- String frameStr;
- String frameIndexStr;
- if (activePart.activeState) {
- unsigned stateFrame = activePart.activeState->frame;
- frame = stateFrame;
- frameStr = static_cast<String>(toString(stateFrame + 1));
- frameIndexStr = static_cast<String>(toString(stateFrame));
-
- if (auto directives = activePart.activeState->properties.value("processingDirectives").optString()) {
- baseProcessingDirectives.append(*directives);
- }
+ auto const& partTags = m_partTags.get(partName);
+ Maybe<String> processedImage = image.maybeLookupTagsView([&](StringView tag) -> StringView {
+ if (tag == "frame") {
+ if (frame)
+ return frameStr;
+ } else if (tag == "frameIndex") {
+ if (frame)
+ return frameIndexStr;
+ } else if (auto p = partTags.ptr(tag)) {
+ return StringView(*p);
+ } else if (auto p = m_globalTags.ptr(tag)) {
+ return StringView(*p);
}
- auto const& partTags = m_partTags.get(partName);
- Maybe<String> processedImage = image.maybeLookupTagsView([&](StringView tag) -> StringView {
- if (tag == "frame") {
- if (frame)
- return frameStr;
- } else if (tag == "frameIndex") {
- if (frame)
- return frameIndexStr;
- } else if (auto p = partTags.ptr(tag)) {
- return StringView(*p);
- } else if (auto p = m_globalTags.ptr(tag)) {
- return StringView(*p);
- }
-
- return StringView("default");
- });
- String const& usedImage = processedImage ? processedImage.get() : image;
-
- if (!usedImage.empty() && usedImage[0] != ':' && usedImage[0] != '?') {
- size_t hash = hashOf(usedImage);
- auto find = m_cachedPartDrawables.find(partName);
- bool fail = find == m_cachedPartDrawables.end() || find->second.first != hash;
- if (fail) {
- String relativeImage;
- if (usedImage[0] != '/')
- relativeImage = AssetPath::relativeTo(m_relativePath, usedImage);
-
- Drawable drawable = Drawable::makeImage(!relativeImage.empty() ? relativeImage : usedImage, 1.0f / TilePixels, centered, Vec2F());
- if (find == m_cachedPartDrawables.end())
- find = m_cachedPartDrawables.emplace(partName, std::pair{ hash, std::move(drawable) }).first;
- else {
- find->second.first = hash;
- find->second.second = std::move(drawable);
- }
+ return StringView("default");
+ });
+ String const& usedImage = processedImage ? processedImage.get() : image;
+
+ if (!usedImage.empty() && usedImage[0] != ':' && usedImage[0] != '?') {
+ size_t hash = hashOf(usedImage);
+ auto find = m_cachedPartDrawables.find(partName);
+ if (find == m_cachedPartDrawables.end() || find->second.first != hash) {
+ String relativeImage;
+ if (usedImage[0] != '/')
+ relativeImage = AssetPath::relativeTo(m_relativePath, usedImage);
+
+ Drawable drawable = Drawable::makeImage(!relativeImage.empty() ? relativeImage : usedImage, 1.0f / TilePixels, centered, Vec2F());
+ if (find == m_cachedPartDrawables.end())
+ find = m_cachedPartDrawables.emplace(partName, std::pair{ hash, std::move(drawable) }).first;
+ else {
+ find->second.first = hash;
+ find->second.second = std::move(drawable);
}
+ }
- Drawable drawable = find->second.second;
- auto& imagePart = drawable.imagePart();
- for (Directives const& directives : baseProcessingDirectives)
- imagePart.addDirectives(directives, centered);
- drawable.transform(partTransformation(partName));
- drawable.transform(globalTransformation());
- drawable.fullbright = fullbright;
- drawable.translate(position);
+ Drawable drawable = find->second.second;
+ auto& imagePart = drawable.imagePart();
+ for (Directives const& directives : baseProcessingDirectives)
+ imagePart.addDirectives(directives, centered);
+ drawable.transform(partTransformation(partName));
+ drawable.transform(globalTransformation());
+ drawable.fullbright = fullbright;
+ drawable.translate(position);
- drawables.append({std::move(drawable), zLevel});
- }
+ drawables.append({std::move(drawable), get<2>(entry)});
+ }
- baseProcessingDirectives.resize(originalDirectivesSize);
- });
-
- sort(drawables, [](auto const& a, auto const& b) { return a.second < b.second; });
+ baseProcessingDirectives.resize(originalDirectivesSize);
+ }
return drawables;
}
@@ -981,7 +1003,7 @@ void NetworkedAnimator::setupNetStates() {
addNetElement(&m_globalTags);
- for (auto const& part : sorted(m_animatedParts.parts()))
+ for (auto const& part : sorted(m_animatedParts.partNames()))
addNetElement(&m_partTags[part]);
for (auto& pair : m_stateInfo) {
diff --git a/source/game/StarNetworkedAnimator.hpp b/source/game/StarNetworkedAnimator.hpp
index feee8bf..8265011 100644
--- a/source/game/StarNetworkedAnimator.hpp
+++ b/source/game/StarNetworkedAnimator.hpp
@@ -82,7 +82,9 @@ public:
bool setState(String const& stateType, String const& state, bool startNew = false);
String state(String const& stateType) const;
- StringList parts() const;
+ StringMap<AnimatedPartSet::Part> const& constParts() const;
+ StringMap<AnimatedPartSet::Part>& parts();
+ StringList partNames() const;
// Queries, if it exists, a property value from the underlying
// AnimatedPartSet for the given state or part. If the property does not
diff --git a/source/game/items/StarActiveItem.cpp b/source/game/items/StarActiveItem.cpp
index 102ad16..725ea27 100644
--- a/source/game/items/StarActiveItem.cpp
+++ b/source/game/items/StarActiveItem.cpp
@@ -251,7 +251,7 @@ Maybe<Direction> ActiveItem::facingDirection() const {
}
List<Drawable> ActiveItem::handDrawables() const {
- if (m_itemAnimator.parts().empty()) {
+ if (m_itemAnimator.constParts().empty()) {
auto drawables = Item::iconDrawables();
Drawable::scaleAll(drawables, 1.0f / TilePixels);
return drawables;