mirror of
https://github.com/geode-sdk/geode.git
synced 2025-02-17 00:30:26 -05:00
add new ColorProvider utility
This commit is contained in:
parent
5109acf725
commit
36ef4979ed
2 changed files with 154 additions and 0 deletions
89
loader/include/Geode/utils/ColorProvider.hpp
Normal file
89
loader/include/Geode/utils/ColorProvider.hpp
Normal file
|
@ -0,0 +1,89 @@
|
|||
#pragma once
|
||||
|
||||
#include "../DefaultInclude.hpp"
|
||||
#include "../loader/Event.hpp"
|
||||
|
||||
namespace geode {
|
||||
struct GEODE_DLL ColorProvidedEvent : public Event {
|
||||
std::string id;
|
||||
cocos2d::ccColor4B color;
|
||||
|
||||
ColorProvidedEvent(std::string const& id, cocos2d::ccColor4B const& color);
|
||||
};
|
||||
|
||||
class GEODE_DLL ColorProvidedFilter : public EventFilter<ColorProvidedEvent> {
|
||||
public:
|
||||
using Callback = void(ColorProvidedEvent*);
|
||||
|
||||
protected:
|
||||
std::string m_id;
|
||||
|
||||
public:
|
||||
ListenerResult handle(utils::MiniFunction<Callback> fn, ColorProvidedEvent* event);
|
||||
|
||||
ColorProvidedFilter(std::string const& id);
|
||||
};
|
||||
|
||||
/**
|
||||
* GD has a lot of hardcoded colors. In addition, mods may very well also
|
||||
* use hardcoded colors in their UIs, for example for CCLayerColors. This
|
||||
* makes it hard for texture packs to reliably change colors, since they'd
|
||||
* have to manually deal with every mod.
|
||||
*
|
||||
* To help with this, Geode provides the `ColorProvider` class, which is
|
||||
* just an index of colors with associated IDs. Mods should use this to
|
||||
* define their hardcoded colors for their UIs, and texture packs can then
|
||||
* change the color dynamically.
|
||||
*
|
||||
* Mods are not expected to handle in-game color changes, since in nearly
|
||||
* all cases the texture pack will be applied far from the mod's UI and as
|
||||
* such just getting the defined color on layer enter will be more than
|
||||
* enough. However, if the mod does add some static UI that won't be
|
||||
* naturally refreshed after a texture pack is applied, it should listen
|
||||
* for `ColorProvidedEvent`s to react accordingly.
|
||||
*/
|
||||
class GEODE_DLL ColorProvider final {
|
||||
private:
|
||||
class Impl;
|
||||
|
||||
Impl* m_impl;
|
||||
|
||||
ColorProvider();
|
||||
|
||||
public:
|
||||
// @note See class description
|
||||
static ColorProvider* get();
|
||||
|
||||
/**
|
||||
* Define a new color with an associated ID. The ID should be prefixed
|
||||
* with the mod ID. If the color has already been defined, nothing
|
||||
* happens
|
||||
* @param id The ID of the color; should be prefixed with mod ID
|
||||
* @param color The color
|
||||
* @returns The current value of the color with the ID (same as the
|
||||
* `color` function)
|
||||
*/
|
||||
cocos2d::ccColor4B define(std::string const& id, cocos2d::ccColor4B const& color);
|
||||
/**
|
||||
* Override the current value of a color with an associated ID
|
||||
* @param id The ID of the color
|
||||
* @param color The color to override with
|
||||
* @returns The new value of the color, or ccWHITE if the ID doesn't
|
||||
* exist
|
||||
*/
|
||||
cocos2d::ccColor4B override(std::string const& id, cocos2d::ccColor4B const& color);
|
||||
/**
|
||||
* Reset the current value of a color to its original definition
|
||||
* @param id The ID of the color
|
||||
* @returns The original value of the color, or ccWHITE if the ID
|
||||
* doesn't exist
|
||||
*/
|
||||
cocos2d::ccColor4B reset(std::string const& id);
|
||||
/**
|
||||
* Get the current value of a color
|
||||
* @param id The ID of the color
|
||||
* @returns The value of the color, or ccWHITE if the ID doesn't exist
|
||||
*/
|
||||
cocos2d::ccColor4B color(std::string const& id) const;
|
||||
};
|
||||
}
|
65
loader/src/utils/ColorProvider.cpp
Normal file
65
loader/src/utils/ColorProvider.cpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
#include <Geode/utils/ColorProvider.hpp>
|
||||
|
||||
using namespace geode::prelude;
|
||||
|
||||
ColorProvidedEvent::ColorProvidedEvent(std::string const& id, cocos2d::ccColor4B const& color)
|
||||
: id(id), color(color) {}
|
||||
|
||||
ListenerResult ColorProvidedFilter::handle(MiniFunction<Callback> fn, ColorProvidedEvent* event) {
|
||||
if (event->id == m_id) {
|
||||
fn(event);
|
||||
}
|
||||
return ListenerResult::Propagate;
|
||||
}
|
||||
|
||||
ColorProvidedFilter::ColorProvidedFilter(std::string const& id) : m_id(id) {}
|
||||
|
||||
class ColorProvider::Impl {
|
||||
public:
|
||||
std::unordered_map<std::string, std::pair<ccColor4B, std::optional<ccColor4B>>> colors;
|
||||
};
|
||||
|
||||
ColorProvider::ColorProvider() : m_impl(new Impl()) {}
|
||||
|
||||
ColorProvider* ColorProvider::get() {
|
||||
static auto inst = new ColorProvider();
|
||||
return inst;
|
||||
}
|
||||
|
||||
ccColor4B ColorProvider::define(std::string const& id, ccColor4B const& color) {
|
||||
// `insert` doesn't override existing keys, which is what we want
|
||||
m_impl->colors.insert({ id, std::pair(color, std::nullopt) });
|
||||
return this->color(id);
|
||||
}
|
||||
ccColor4B ColorProvider::override(std::string const& id, ccColor4B const& color) {
|
||||
if (m_impl->colors.contains(id)) {
|
||||
m_impl->colors.at(id).second = color;
|
||||
ColorProvidedEvent(id, color).post();
|
||||
return color;
|
||||
}
|
||||
else {
|
||||
log::error("(ColorProvider) Attempted to override color \"{}\", which is not defined", id);
|
||||
return to4B(ccWHITE);
|
||||
}
|
||||
}
|
||||
ccColor4B ColorProvider::reset(std::string const& id) {
|
||||
if (m_impl->colors.contains(id)) {
|
||||
m_impl->colors.at(id).second = std::nullopt;
|
||||
auto def = m_impl->colors.at(id).first;
|
||||
ColorProvidedEvent(id, def).post();
|
||||
return def;
|
||||
}
|
||||
else {
|
||||
log::error("(ColorProvider) Attempted to reset color \"{}\", which is not defined", id);
|
||||
return to4B(ccWHITE);
|
||||
}
|
||||
}
|
||||
ccColor4B ColorProvider::color(std::string const& id) const {
|
||||
if (m_impl->colors.contains(id)) {
|
||||
return m_impl->colors.at(id).second.value_or(m_impl->colors.at(id).first);
|
||||
}
|
||||
else {
|
||||
log::error("(ColorProvider) Attempted to get color \"{}\", which is not defined", id);
|
||||
return to4B(ccWHITE);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue