more!! more!!!!

This commit is contained in:
Kae 2023-06-25 01:16:40 +10:00
parent 2bd399fd00
commit 008bd6d3df
17 changed files with 125 additions and 73 deletions

View File

@ -147,8 +147,13 @@ bool AssetPath::operator==(AssetPath const& rhs) const {
return tie(basePath, subPath, directives) == tie(rhs.basePath, rhs.subPath, rhs.directives);
}
AssetPath::AssetPath(const char* path) {
*this = move(AssetPath::split(path));
}
AssetPath::AssetPath(String const& path) {
*this = move(AssetPath::split(path)); // split code should probably be in here, but whatever
*this = move(AssetPath::split(path));
}
AssetPath::AssetPath(String&& basePath, Maybe<String>&& subPath, DirectivesGroup&& directives) {
@ -182,4 +187,19 @@ size_t hash<AssetPath>::operator()(AssetPath const& s) const {
return hashOf(s.basePath, s.subPath, s.directives);
}
DataStream& operator>>(DataStream& ds, AssetPath& path) {
String string;
ds.read(string);
path = move(string);
return ds;
}
DataStream& operator<<(DataStream& ds, AssetPath const& path) {
ds.write(AssetPath::join(path));
return ds;
}
}

View File

@ -3,6 +3,7 @@
#include "StarDirectives.hpp"
#include "StarHash.hpp"
#include "StarDataStream.hpp"
namespace Star {
@ -53,6 +54,7 @@ struct AssetPath {
static String relativeTo(String const& sourcePath, String const& givenPath);
AssetPath() = default;
AssetPath(const char* path);
AssetPath(String const& path);
AssetPath(String&& basePath, Maybe<String>&& subPath, DirectivesGroup&& directives);
AssetPath(const String& basePath, const Maybe<String>& subPath, const DirectivesGroup& directives);
@ -63,6 +65,9 @@ struct AssetPath {
bool operator==(AssetPath const& rhs) const;
};
DataStream& operator>>(DataStream& ds, AssetPath& path);
DataStream& operator<<(DataStream& ds, AssetPath const& path);
std::ostream& operator<<(std::ostream& os, AssetPath const& rhs);
template <>

View File

@ -23,23 +23,24 @@ Directives::Entry::Entry(Entry const& other) {
Directives::Directives() : hash(0) {}
Directives::Directives(String const& directives) : hash(0) {
parse(directives);
string = directives;
parse(string);
}
Directives::Directives(String&& directives) : hash(0) {
String mine = move(directives);
parse(mine);
string = move(directives);
parse(string);
}
Directives::Directives(const char* directives) : hash(0) {
String string(directives);
Directives::Directives(const char* directives) : hash(0), string(directives) {
parse(string);
}
Directives::Directives(List<Entry>&& newEntries) {
entries = std::make_shared<List<Entry> const>(move(newEntries));
String directives = toString(); // This needs to be better
hash = XXH3_64bits(directives.utf8Ptr(), directives.utf8Size());
String newString;
string = move(buildString(newString));
hash = XXH3_64bits(string.utf8Ptr(), string.utf8Size());
}
void Directives::parse(String const& directives) {
@ -51,8 +52,12 @@ void Directives::parse(String const& directives) {
newList.reserve(split.size());
for (String& str : split) {
if (!str.empty()) {
try {
ImageOperation operation = imageOperationFromString(str);
newList.emplace_back(move(operation), move(str));
} catch (StarException const& e) {
Logger::logf(LogLevel::Error, "Error parsing image operation: %s", e.what());
}
}
}
@ -65,27 +70,29 @@ void Directives::parse(String const& directives) {
// Logger::logf(LogLevel::Debug, "Directives: Parsed %u character long string", directives.utf8Size());
}
void Directives::buildString(String& out) const {
String& Directives::buildString(String& out) const {
if (entries) {
for (auto& entry : *entries) {
out += "?";
out += entry.string;
}
}
return out;
}
String Directives::toString() const {
String result;
buildString(result);
//if (result.utf8Size() > 1000)
// Logger::logf(LogLevel::Debug, "Directives: Rebuilt %u character long string", result.utf8Size());
return result;
return string;
}
inline bool Directives::empty() const {
return !entries || entries->empty();
}
inline Directives::operator bool() const {
return !empty();
}
DataStream& operator>>(DataStream& ds, Directives& directives) {
String string;
@ -103,19 +110,37 @@ DataStream& operator<<(DataStream& ds, Directives const& directives) {
}
DirectivesGroup::DirectivesGroup() : m_count(0) {}
DirectivesGroup::DirectivesGroup(String const& directives) {
m_directives.emplace_back(directives);
DirectivesGroup::DirectivesGroup(String const& directives) : m_count(0) {
if (directives.empty())
return;
Directives parsed(directives);
if (parsed) {
m_directives.emplace_back(move(parsed));
m_count = m_directives.back().entries->size();
}
DirectivesGroup::DirectivesGroup(String&& directives) {
m_directives.emplace_back(move(directives));
}
DirectivesGroup::DirectivesGroup(String&& directives) : m_count(0) {
if (directives.empty()) {
directives.clear();
return;
}
Directives parsed(move(directives));
if (parsed) {
m_directives.emplace_back(move(parsed));
m_count = m_directives.back().entries->size();
}
}
inline bool DirectivesGroup::empty() const {
return m_count == 0;
}
inline DirectivesGroup::operator bool() const {
return empty();
}
inline bool DirectivesGroup::compare(DirectivesGroup const& other) const {
if (m_count != other.m_count)
return false;
@ -156,7 +181,7 @@ inline String DirectivesGroup::toString() const {
void DirectivesGroup::addToString(String& string) const {
for (auto& directives : m_directives)
directives.buildString(string);
string += directives.string;
}
void DirectivesGroup::forEach(DirectivesCallback callback) const {

View File

@ -12,12 +12,11 @@ STAR_CLASS(DirectivesGroup);
STAR_EXCEPTION(DirectivesException, StarException);
// Kae: My attempt at reducing memory allocation and per-frame string parsing for extremely long directives
// entries must never be a null ptr!
class Directives {
public:
struct Entry {
ImageOperation operation;
String string;
String string; // One day, we can make this a string_view pointing to Entry::string.
Entry(ImageOperation&& newOperation, String&& newString);
Entry(ImageOperation const& newOperation, String const& newString);
@ -31,15 +30,17 @@ public:
Directives(List<Entry>&& entries);
void parse(String const& directives);
void buildString(String& out) const;
String& buildString(String& out) const;
String toString() const;
inline bool empty() const;
inline operator bool() const;
friend DataStream& operator>>(DataStream& ds, Directives& directives);
friend DataStream& operator<<(DataStream& ds, Directives const& directives);
std::shared_ptr<List<Entry> const> entries;
size_t hash = 0;
String string;
};
class DirectivesGroup {
@ -51,6 +52,7 @@ public:
void parseDirectivesIntoLeaf(String const& directives);
inline bool empty() const;
inline operator bool() const;
bool compare(DirectivesGroup const& other) const;
void append(Directives const& other);
void append(List<Directives::Entry>&& entries);

View File

@ -47,7 +47,7 @@ Type lexicalCast(std::string const& s, std::ios_base::fmtflags flags = std::ios_
if (m)
return m.take();
else
throw BadLexicalCast();
throw BadLexicalCast(strf("Lexical cast failed on '%s'", s));
}
template <typename Type>

View File

@ -965,9 +965,8 @@ void MainInterface::renderBreath() {
size_t blocks = round((10 * breath) / breathMax);
if (blocks < 10) {
String path = "/interface/breath/breath.png";
m_guiContext->drawQuad(path,
RectF::withCenter(breathBackgroundCenterPos, Vec2F(imgMetadata->imageSize(path)) * interfaceScale()));
String breathPath = "/interface/breath/breath.png";
m_guiContext->drawQuad(breathPath, RectF::withCenter(breathBackgroundCenterPos, Vec2F(imgMetadata->imageSize(breathPath)) * interfaceScale()));
for (size_t i = 0; i < 10; i++) {
if (i >= blocks) {
if (blocks == 0 && Time::monotonicMilliseconds() % 500 > 250)

View File

@ -43,14 +43,10 @@ void Animation::setAngle(float angle) {
m_angle = angle;
}
void Animation::setProcessing(String processing) {
void Animation::setProcessing(Directives processing) {
m_processing = move(processing);
}
void Animation::addProcessing(String const& processing) {
m_processing = String::joinWith("?", m_processing, processing);
}
void Animation::setColor(Color color) {
m_color = color;
}
@ -73,9 +69,8 @@ Drawable Animation::drawable(float pixelSize) const {
if (m_appendFrame)
baseFrame += ":" + toString(m_frame);
baseFrame = String::joinWith("?", baseFrame, m_processing);
Drawable drawable = Drawable::makeImage(move(baseFrame), pixelSize, m_centered, m_offset);
drawable.imagePart().addDirectives(m_processing);
drawable.rotate(m_angle);
drawable.color = m_color;
return drawable;

View File

@ -15,8 +15,7 @@ public:
void setAngle(float angle);
void setProcessing(String processing);
void addProcessing(String const& processing);
void setProcessing(Directives processing);
void setColor(Color color);
@ -44,7 +43,7 @@ private:
float m_angle;
Vec2F m_offset;
bool m_centered;
String m_processing;
Directives m_processing;
Color m_color;
int m_variantOffset;

View File

@ -10,7 +10,7 @@
namespace Star {
Drawable::ImagePart& Drawable::ImagePart::addDirectives(Directives const& directives, bool keepImageCenterPosition) {
if (!directives.entries || directives.entries->empty())
if (!directives)
return *this;
if (keepImageCenterPosition) {

View File

@ -45,7 +45,6 @@ Particle::Particle() {
trail = false;
flippable = true;
flip = false;
directives = "";
}
Particle::Particle(Json const& config, String const& path) {
@ -69,6 +68,12 @@ Particle::Particle(Json const& config, String const& path) {
if (type == Type::Animated)
initializeAnimation();
auto pathEnd = string.find('?');
if (pathEnd == NPos)
directives = "";
else
directives.parse(string.substr(pathEnd));
if (config.contains("color"))
color = jsonToColor(config.get("color"));
@ -96,9 +101,11 @@ Particle::Particle(Json const& config, String const& path) {
length = config.getFloat("length", 10.0f);
destructionAction = DestructionActionNames.getLeft(config.getString("destructionAction", "None"));
destructionImage = config.getString("destructionImage", "");
String destructionImagePath = config.getString("destructionImage", "");
if (destructionAction == DestructionAction::Image)
destructionImage = AssetPath::relativeTo(path, destructionImage);
destructionImagePath = AssetPath::relativeTo(path, destructionImagePath);
destructionImage = destructionImagePath;
destructionTime = config.getFloat("destructionTime", 0.0f);
timeToLive = config.getFloat("timeToLive", 0.0f);
@ -113,7 +120,6 @@ Particle::Particle(Json const& config, String const& path) {
ignoreWind = config.getBool("ignoreWind", true);
trail = config.getBool("trail", false);
directives = "";
}
Json Particle::toJson() const {
@ -134,7 +140,7 @@ Json Particle::toJson() const {
{"angularVelocity", angularVelocity * 180.0f / Constants::pi},
{"length", length},
{"destructionAction", DestructionActionNames.getRight(destructionAction)},
{"destructionImage", destructionImage},
{"destructionImage", AssetPath::join(destructionImage)},
{"destructionTime", destructionTime},
{"timeToLive", timeToLive},
{"layer", LayerNames.getRight(layer)},
@ -221,7 +227,7 @@ void Particle::destructionUpdate() {
size = 1.0f;
color = Color::White;
type = Particle::Type::Textured;
string = destructionImage;
image = destructionImage;
angularVelocity = 0.0f;
length = 0.0f;
rotation = 0.0f;
@ -232,7 +238,7 @@ void Particle::destructionUpdate() {
void Particle::initializeAnimation() {
if (!animation) {
animation = Animation(AssetPath::removeDirectives(string));
animation->addProcessing(AssetPath::getDirectives(string));
animation->setProcessing(directives);
}
}

View File

@ -5,6 +5,7 @@
#include "StarColor.hpp"
#include "StarBiMap.hpp"
#include "StarAnimation.hpp"
#include "StarAssetPath.hpp"
namespace Star {
@ -75,6 +76,8 @@ struct Particle {
// Used differently depending on the type of the particle.
String string;
AssetPath image;
Directives directives;
Color color;
Color light;
@ -95,7 +98,7 @@ struct Particle {
float length;
DestructionAction destructionAction;
String destructionImage;
AssetPath destructionImage;
float destructionTime;
float timeToLive;
@ -110,7 +113,6 @@ struct Particle {
bool trail;
Maybe<Animation> animation;
String directives;
};
DataStream& operator<<(DataStream& ds, Particle const& particle);

View File

@ -21,7 +21,7 @@ ArmorItem::ArmorItem(Json const& config, String const& directory, Json const& da
m_directives = instanceValue("directives", "").toString();
m_colorOptions = colorDirectivesFromConfig(config.getArray("colorOptions", JsonArray{""}));
if (!m_directives.entries || m_directives.entries->empty())
if (!m_directives)
m_directives = "?" + m_colorOptions.wrap(instanceValue("colorIndex", 0).toUInt());
refreshIconDrawables();

View File

@ -135,7 +135,7 @@ void GuiContext::resetInterfaceScissorRect() {
renderer()->setScissorRect({});
}
Vec2U GuiContext::textureSize(String const& texName) {
Vec2U GuiContext::textureSize(AssetPath const& texName) {
return assetTextureGroup()->loadTexture(texName)->size();
}
@ -143,15 +143,15 @@ void GuiContext::drawQuad(RectF const& screenCoords, Vec4B const& color) {
renderer()->render(renderFlatRect(screenCoords, color, 0.0f));
}
void GuiContext::drawQuad(String const& texName, RectF const& screenCoords, Vec4B const& color) {
void GuiContext::drawQuad(AssetPath const& texName, RectF const& screenCoords, Vec4B const& color) {
renderer()->render(renderTexturedRect(assetTextureGroup()->loadTexture(texName), screenCoords, color, 0.0f));
}
void GuiContext::drawQuad(String const& texName, Vec2F const& screenPos, int pixelRatio, Vec4B const& color) {
void GuiContext::drawQuad(AssetPath const& texName, Vec2F const& screenPos, int pixelRatio, Vec4B const& color) {
renderer()->render(renderTexturedRect(assetTextureGroup()->loadTexture(texName), screenPos, pixelRatio, color, 0.0f));
}
void GuiContext::drawQuad(String const& texName, RectF const& texCoords, RectF const& screenCoords, Vec4B const& color) {
void GuiContext::drawQuad(AssetPath const& texName, RectF const& texCoords, RectF const& screenCoords, Vec4B const& color) {
renderer()->render(RenderQuad{assetTextureGroup()->loadTexture(texName),
RenderVertex{Vec2F(screenCoords.xMin(), screenCoords.yMin()), Vec2F(texCoords.xMin(), texCoords.yMin()), color, 0.0f},
RenderVertex{Vec2F(screenCoords.xMax(), screenCoords.yMin()), Vec2F(texCoords.xMax(), texCoords.yMin()), color, 0.0f},
@ -209,15 +209,15 @@ void GuiContext::drawInterfaceQuad(RectF const& screenCoords, Vec4B const& color
drawQuad(screenCoords.scaled(interfaceScale()), color);
}
void GuiContext::drawInterfaceQuad(String const& texName, Vec2F const& screenCoords, Vec4B const& color) {
void GuiContext::drawInterfaceQuad(AssetPath const& texName, Vec2F const& screenCoords, Vec4B const& color) {
drawQuad(texName, screenCoords * interfaceScale(), interfaceScale(), color);
}
void GuiContext::drawInterfaceQuad(String const& texName, Vec2F const& screenCoords, float scale, Vec4B const& color) {
void GuiContext::drawInterfaceQuad(AssetPath const& texName, Vec2F const& screenCoords, float scale, Vec4B const& color) {
drawQuad(texName, screenCoords * interfaceScale(), interfaceScale() * scale, color);
}
void GuiContext::drawInterfaceQuad(String const& texName, RectF const& texCoords, RectF const& screenCoords, Vec4B const& color) {
void GuiContext::drawInterfaceQuad(AssetPath const& texName, RectF const& texCoords, RectF const& screenCoords, Vec4B const& color) {
drawQuad(texName, texCoords, screenCoords.scaled(interfaceScale()), color);
}

View File

@ -62,12 +62,12 @@ public:
void setInterfaceScissorRect(RectI const& scissor);
void resetInterfaceScissorRect();
Vec2U textureSize(String const& texName);
Vec2U textureSize(AssetPath const& texName);
void drawQuad(RectF const& screenCoords, Vec4B const& color = Vec4B::filled(255));
void drawQuad(String const& texName, RectF const& screenCoords, Vec4B const& color = Vec4B::filled(255));
void drawQuad(String const& texName, Vec2F const& screenPos, int pixelRatio, Vec4B const& color = Vec4B::filled(255));
void drawQuad(String const& texName, RectF const& texCoords, RectF const& screenCoords, Vec4B const& color = Vec4B::filled(255));
void drawQuad(AssetPath const& texName, RectF const& screenCoords, Vec4B const& color = Vec4B::filled(255));
void drawQuad(AssetPath const& texName, Vec2F const& screenPos, int pixelRatio, Vec4B const& color = Vec4B::filled(255));
void drawQuad(AssetPath const& texName, RectF const& texCoords, RectF const& screenCoords, Vec4B const& color = Vec4B::filled(255));
void drawDrawable(Drawable drawable, Vec2F const& screenPos, int pixelRatio, Vec4B const& color = Vec4B::filled(255));
@ -84,9 +84,9 @@ public:
void drawInterfaceTriangles(List<tuple<Vec2F, Vec2F, Vec2F>> const& triangles, Vec4B const& color);
void drawInterfaceQuad(RectF const& screenCoords, Vec4B const& color = Vec4B::filled(255));
void drawInterfaceQuad(String const& texName, Vec2F const& screenPos, Vec4B const& color = Vec4B::filled(255));
void drawInterfaceQuad(String const& texName, Vec2F const& screenPos, float scale, Vec4B const& color = Vec4B::filled(255));
void drawInterfaceQuad(String const& texName, RectF const& texCoords, RectF const& screenCoords, Vec4B const& color = Vec4B::filled(255));
void drawInterfaceQuad(AssetPath const& texName, Vec2F const& screenPos, Vec4B const& color = Vec4B::filled(255));
void drawInterfaceQuad(AssetPath const& texName, Vec2F const& screenPos, float scale, Vec4B const& color = Vec4B::filled(255));
void drawInterfaceQuad(AssetPath const& texName, RectF const& texCoords, RectF const& screenCoords, Vec4B const& color = Vec4B::filled(255));
void drawImageStretchSet(ImageStretchSet const& imageSet, RectF const& screenPos, GuiDirection direction = GuiDirection::Horizontal, Vec4B const& color = Vec4B::filled(255));

View File

@ -153,8 +153,7 @@ void ItemSlotWidget::renderImpl() {
if (m_showLinkIndicator) {
// TODO: Hardcoded
context()->drawInterfaceQuad("/interface/inventory/itemlinkindicator.png",
Vec2F(screenPosition() - Vec2I(1, 1)));
context()->drawInterfaceQuad(String("/interface/inventory/itemlinkindicator.png"), Vec2F(screenPosition() - Vec2I(1, 1)));
}
for (auto i : iconDrawables)
@ -179,7 +178,7 @@ void ItemSlotWidget::renderImpl() {
}
int frame = (int)roundf(m_progress * 18); // TODO: Hardcoded lol
context()->drawInterfaceQuad(strf("/interface/cooldown.png:%d", frame), Vec2F(screenPosition()));
context()->drawInterfaceQuad(String(strf("/interface/cooldown.png:%d", frame)), Vec2F(screenPosition()));
if (m_item->count() > 1 && m_showCount) { // we don't need to tell people that there's only 1 of something
context()->setFont(m_font);
@ -192,7 +191,7 @@ void ItemSlotWidget::renderImpl() {
} else if (m_drawBackingImageWhenEmpty && m_backingImage != "") {
context()->drawInterfaceQuad(m_backingImage, Vec2F(screenPosition()));
int frame = (int)roundf(m_progress * 18); // TODO: Hardcoded lol
context()->drawInterfaceQuad(strf("/interface/cooldown.png:%d", frame), Vec2F(screenPosition()));
context()->drawInterfaceQuad(String(strf("/interface/cooldown.png:%d", frame)), Vec2F(screenPosition()));
}
if (m_highlightEnabled) {

View File

@ -38,7 +38,7 @@ void PortraitWidget::renderImpl() {
}
if (m_entity) {
List<Drawable> portrait = m_entity->portrait(m_portraitMode);
for (auto i : portrait) {
for (auto& i : portrait) {
i.scale(m_scale);
context()->drawInterfaceDrawable(i, Vec2F(screenPosition() + offset));
}

View File

@ -31,12 +31,12 @@ private:
PortraitEntityPtr m_entity;
PortraitMode m_portraitMode;
String m_noEntityImageFull;
String m_noEntityImagePart;
AssetPath m_noEntityImageFull;
AssetPath m_noEntityImagePart;
float m_scale;
bool m_iconMode;
String m_iconImage;
AssetPath m_iconImage;
Vec2I m_iconOffset;
};