mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-22 07:27:59 -05:00
removing deprecated things, part 1 (does not compile)
This commit is contained in:
parent
4dcac338f9
commit
50ab4ebed7
45 changed files with 580 additions and 3306 deletions
|
@ -5,7 +5,7 @@
|
|||
#include "loader/Log.hpp"
|
||||
#include "loader/Mod.hpp"
|
||||
#include "loader/ModEvent.hpp"
|
||||
#include "loader/Setting.hpp"
|
||||
#include "loader/SettingV3.hpp"
|
||||
#include "loader/Dirs.hpp"
|
||||
|
||||
#include <Geode/DefaultInclude.hpp>
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
#include "ui/EnterLayerEvent.hpp"
|
||||
#include "ui/BasedButtonSprite.hpp"
|
||||
#include "ui/IconButtonSprite.hpp"
|
||||
#include "ui/InputNode.hpp"
|
||||
#include "ui/Layout.hpp"
|
||||
#include "ui/SpacerNode.hpp"
|
||||
#include "ui/General.hpp"
|
||||
#include "ui/ListView.hpp"
|
||||
#include "ui/MDPopup.hpp"
|
||||
|
|
37
loader/include/Geode/cocos/base_nodes/CCNode.h
vendored
37
loader/include/Geode/cocos/base_nodes/CCNode.h
vendored
|
@ -37,7 +37,6 @@
|
|||
#include "../kazmath/include/kazmath/kazmath.h"
|
||||
#include "../script_support/CCScriptSupport.h"
|
||||
#include "../include/CCProtocols.h"
|
||||
#include "Layout.hpp"
|
||||
#include "../../loader/Event.hpp"
|
||||
#include <Geode/utils/casts.hpp>
|
||||
|
||||
|
@ -45,6 +44,12 @@
|
|||
#include <matjson.hpp>
|
||||
#endif
|
||||
|
||||
namespace geode {
|
||||
class Layout;
|
||||
class LayoutOptions;
|
||||
enum class Anchor;
|
||||
}
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
class CCCamera;
|
||||
|
@ -871,25 +876,13 @@ public:
|
|||
private:
|
||||
friend class geode::modifier::FieldContainer;
|
||||
|
||||
[[deprecated("Will be removed, it's an ABI break")]]
|
||||
GEODE_DLL geode::modifier::FieldContainer* getFieldContainer();
|
||||
GEODE_DLL geode::modifier::FieldContainer* getFieldContainer(char const* forClass);
|
||||
GEODE_DLL void addEventListenerInternal(
|
||||
std::string const& id,
|
||||
geode::EventListenerProtocol* protocol
|
||||
);
|
||||
|
||||
#ifdef GEODE_EXPORTING
|
||||
[[deprecated("Will be removed, it's an ABI break")]]
|
||||
GEODE_DLL std::optional<matjson::Value> getAttributeInternal(std::string const& attribute);
|
||||
#endif
|
||||
|
||||
public:
|
||||
#ifdef GEODE_EXPORTING
|
||||
[[deprecated("Will be removed, it's an ABI break")]]
|
||||
GEODE_DLL void setAttribute(std::string const& attribute, matjson::Value const& value);
|
||||
#endif
|
||||
|
||||
public:
|
||||
/**
|
||||
* Get the string ID of this node
|
||||
* @returns The ID, or an empty string if the node has no ID.
|
||||
|
@ -990,13 +983,13 @@ public:
|
|||
* CCLayers / CCMenus, this will change where the children are located
|
||||
* @note Geode addition
|
||||
*/
|
||||
GEODE_DLL void setLayout(Layout* layout, bool apply = true, bool respectAnchor = true);
|
||||
GEODE_DLL void setLayout(geode::Layout* layout, bool apply = true, bool respectAnchor = true);
|
||||
/**
|
||||
* Get the Layout for this node
|
||||
* @returns The current layout, or nullptr if no layout is set
|
||||
* @note Geode addition
|
||||
*/
|
||||
GEODE_DLL Layout* getLayout();
|
||||
GEODE_DLL geode::Layout* getLayout();
|
||||
/**
|
||||
* Update the layout of this node using the current Layout. If no layout is
|
||||
* set, nothing happens
|
||||
|
@ -1011,13 +1004,13 @@ public:
|
|||
* @param apply Whether to update the layout of the parent node
|
||||
* @note Geode addition
|
||||
*/
|
||||
GEODE_DLL void setLayoutOptions(LayoutOptions* options, bool apply = true);
|
||||
GEODE_DLL void setLayoutOptions(geode::LayoutOptions* options, bool apply = true);
|
||||
/**
|
||||
* Get the layout options for this node
|
||||
* @returns The current layout options, or nullptr if no options are set
|
||||
* @note Geode addition
|
||||
*/
|
||||
GEODE_DLL LayoutOptions* getLayoutOptions();
|
||||
GEODE_DLL geode::LayoutOptions* getLayoutOptions();
|
||||
/**
|
||||
* Adds a child at an anchored position with an offset. The node is placed
|
||||
* in its parent where the anchor specifies, and then the offset is used to
|
||||
|
@ -1029,7 +1022,7 @@ public:
|
|||
* if no other layout is already specified
|
||||
* @note Geode addition
|
||||
*/
|
||||
GEODE_DLL void addChildAtPosition(CCNode* child, Anchor anchor, CCPoint const& offset = CCPointZero, bool useAnchorLayout = true);
|
||||
GEODE_DLL void addChildAtPosition(CCNode* child, geode::Anchor anchor, CCPoint const& offset = CCPointZero, bool useAnchorLayout = true);
|
||||
/**
|
||||
* Adds a child at an anchored position with an offset. The node is placed
|
||||
* in its parent where the anchor specifies, and then the offset is used to
|
||||
|
@ -1044,7 +1037,7 @@ public:
|
|||
*/
|
||||
GEODE_DLL void addChildAtPosition(
|
||||
CCNode* child,
|
||||
Anchor anchor,
|
||||
geode::Anchor anchor,
|
||||
CCPoint const& offset,
|
||||
CCPoint const& nodeAnchor,
|
||||
bool useAnchorLayout = true
|
||||
|
@ -1057,7 +1050,7 @@ public:
|
|||
* @param offset Where to place the child relative to the anchor
|
||||
* @note Geode addition
|
||||
*/
|
||||
GEODE_DLL void updateAnchoredPosition(Anchor anchor, CCPoint const& offset = CCPointZero);
|
||||
GEODE_DLL void updateAnchoredPosition(geode::Anchor anchor, CCPoint const& offset = CCPointZero);
|
||||
/**
|
||||
* Updates the anchored position of a child. Requires the child to already
|
||||
* have a parent; if the child already has AnchorLayoutOptions set, those
|
||||
|
@ -1068,7 +1061,7 @@ public:
|
|||
* @note Geode addition
|
||||
*/
|
||||
GEODE_DLL void updateAnchoredPosition(
|
||||
Anchor anchor,
|
||||
geode::Anchor anchor,
|
||||
CCPoint const& offset,
|
||||
CCPoint const& nodeAnchor
|
||||
);
|
||||
|
|
1
loader/include/Geode/cocos/include/cocos2d.h
vendored
1
loader/include/Geode/cocos/include/cocos2d.h
vendored
|
@ -59,7 +59,6 @@ THE SOFTWARE.
|
|||
// base_nodes
|
||||
#include "../base_nodes/CCNode.h"
|
||||
#include "../base_nodes/CCAtlasNode.h"
|
||||
#include "../base_nodes/SpacerNode.hpp"
|
||||
|
||||
// cocoa
|
||||
#include "../cocoa/CCAffineTransform.h"
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "Loader.hpp" // very nice circular dependency fix
|
||||
#include "Hook.hpp"
|
||||
#include "ModMetadata.hpp"
|
||||
#include "Setting.hpp"
|
||||
#include "SettingV3.hpp"
|
||||
#include "Types.hpp"
|
||||
#include "Loader.hpp"
|
||||
|
@ -108,8 +107,6 @@ namespace geode {
|
|||
|
||||
std::string getID() const;
|
||||
std::string getName() const;
|
||||
[[deprecated("Use Mod::getDevelopers instead")]]
|
||||
std::string getDeveloper() const;
|
||||
std::vector<std::string> getDevelopers() const;
|
||||
std::optional<std::string> getDescription() const;
|
||||
std::optional<std::string> getDetails() const;
|
||||
|
@ -137,17 +134,6 @@ namespace geode {
|
|||
std::vector<Mod*> getDependants() const;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Check if this Mod has updates available on the mods index. If
|
||||
* you're using this for automatic update checking, use
|
||||
* `openInfoPopup` or `openIndexPopup` from the `ui/GeodeUI.hpp`
|
||||
* header to open the Mod's page to let the user install the update
|
||||
* @returns The latest available version on the index if there are
|
||||
* updates for this mod
|
||||
*/
|
||||
[[deprecated("Use Mod::checkUpdates instead; this function always returns nullopt")]]
|
||||
std::optional<VersionInfo> hasAvailableUpdate() const;
|
||||
|
||||
using CheckUpdatesTask = Task<Result<std::optional<VersionInfo>, std::string>>;
|
||||
/**
|
||||
* Check if this Mod has updates available on the mods index. If
|
||||
|
@ -189,12 +175,6 @@ namespace geode {
|
|||
std::vector<std::string> getSettingKeys() const;
|
||||
bool hasSetting(std::string_view const key) const;
|
||||
|
||||
// todo in v4: remove these
|
||||
[[deprecated("Use Mod::getSettingV3")]]
|
||||
std::optional<Setting> getSettingDefinition(std::string_view const key) const;
|
||||
[[deprecated("Use Mod::getSettingV3")]]
|
||||
SettingValue* getSetting(std::string_view const key) const;
|
||||
|
||||
// todo in v4: possibly rename this to getSetting?
|
||||
/**
|
||||
* Get the definition of a setting, or null if the setting was not found,
|
||||
|
@ -204,36 +184,6 @@ namespace geode {
|
|||
*/
|
||||
std::shared_ptr<SettingV3> getSettingV3(std::string_view const key) const;
|
||||
|
||||
/**
|
||||
* Register a custom setting's value class. See Mod::addCustomSetting
|
||||
* for a convenience wrapper that creates the value in-place to avoid
|
||||
* code duplication. Also see
|
||||
* [the tutorial page](https://docs.geode-sdk.org/mods/settings) for
|
||||
* more information about custom settings
|
||||
* @param key The setting's key
|
||||
* @param value The SettingValue class that shall handle this setting
|
||||
* @see addCustomSetting
|
||||
*/
|
||||
[[deprecated("Use Mod::registerCustomSettingType")]]
|
||||
void registerCustomSetting(std::string_view const key, std::unique_ptr<SettingValue> value);
|
||||
/**
|
||||
* Register a custom setting's value class. The new SettingValue class
|
||||
* will be created in-place using `std::make_unique`. See
|
||||
* [the tutorial page](https://docs.geode-sdk.org/mods/settings) for
|
||||
* more information about custom settings
|
||||
* @param key The setting's key
|
||||
* @param value The value of the custom setting
|
||||
* @example
|
||||
* $on_mod(Loaded) {
|
||||
* Mod::get()->addCustomSetting<MySettingValue>("setting-key", DEFAULT_VALUE);
|
||||
* }
|
||||
*/
|
||||
template <class T, class V>
|
||||
[[deprecated("Use Mod::registerCustomSettingType")]]
|
||||
void addCustomSetting(std::string_view const key, V const& value) {
|
||||
this->registerCustomSetting(key, std::make_unique<T>(std::string(key), this->getID(), value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a custom setting type. See
|
||||
* [the setting docs](https://docs.geode-sdk.org/mods/settings) for more
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include "../utils/Result.hpp"
|
||||
#include "../utils/VersionInfo.hpp"
|
||||
#include "Setting.hpp"
|
||||
#include "Types.hpp"
|
||||
|
||||
#include <matjson.hpp>
|
||||
|
@ -123,13 +122,6 @@ namespace geode {
|
|||
* character set.
|
||||
*/
|
||||
[[nodiscard]] std::string getName() const;
|
||||
/**
|
||||
* The name of the head developer.
|
||||
* If the mod has multiple * developers, this will return the first
|
||||
* developer in the list.
|
||||
*/
|
||||
[[nodiscard, deprecated("Use ModMetadata::getDevelopers() instead")]]
|
||||
std::string getDeveloper() const;
|
||||
/**
|
||||
* The developers of this mod
|
||||
*/
|
||||
|
@ -155,11 +147,6 @@ namespace geode {
|
|||
* (see MDTextArea for more info)
|
||||
*/
|
||||
[[nodiscard]] std::optional<std::string> getSupportInfo() const;
|
||||
/**
|
||||
* Git Repository of the mod
|
||||
*/
|
||||
[[nodiscard, deprecated("Use ModMetadata::getLinks instead")]]
|
||||
std::optional<std::string> getRepository() const;
|
||||
/**
|
||||
* Get the links (related websites / servers / etc.) for this mod
|
||||
*/
|
||||
|
@ -180,11 +167,6 @@ namespace geode {
|
|||
* Mod spritesheet names
|
||||
*/
|
||||
[[nodiscard]] std::vector<std::string> getSpritesheets() const;
|
||||
/**
|
||||
* Mod settings
|
||||
* @note Not a map because insertion order must be preserved
|
||||
*/
|
||||
[[nodiscard, deprecated("Use getSettingsV3")]] std::vector<std::pair<std::string, Setting>> getSettings() const;
|
||||
/**
|
||||
* Mod settings
|
||||
* @note Not a map because insertion order must be preserved
|
||||
|
@ -237,8 +219,6 @@ namespace geode {
|
|||
void setDependencies(std::vector<Dependency> const& value);
|
||||
void setIncompatibilities(std::vector<Incompatibility> const& value);
|
||||
void setSpritesheets(std::vector<std::string> const& value);
|
||||
[[deprecated("This function does NOTHING")]]
|
||||
void setSettings(std::vector<std::pair<std::string, Setting>> const& value);
|
||||
void setSettings(std::vector<std::pair<std::string, matjson::Value>> const& value);
|
||||
void setTags(std::unordered_set<std::string> const& value);
|
||||
void setNeedsEarlyLoad(bool const& value);
|
||||
|
|
|
@ -1,324 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "Types.hpp"
|
||||
#include "../DefaultInclude.hpp"
|
||||
#include "../utils/Result.hpp"
|
||||
#include "../utils/file.hpp"
|
||||
#include <matjson.hpp>
|
||||
#include <optional>
|
||||
#include <unordered_set>
|
||||
#include <cocos2d.h>
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4275)
|
||||
|
||||
namespace geode {
|
||||
class SettingNode;
|
||||
class SettingValue;
|
||||
|
||||
struct JsonMaybeObject;
|
||||
struct JsonMaybeValue;
|
||||
|
||||
/**
|
||||
* A Setting for a boolean value. Represented in-game as a simple toggle
|
||||
*/
|
||||
struct GEODE_DLL BoolSetting final {
|
||||
using ValueType = bool;
|
||||
|
||||
std::optional<std::string> name;
|
||||
std::optional<std::string> description;
|
||||
bool defaultValue;
|
||||
|
||||
static Result<BoolSetting> parse(JsonMaybeObject& obj);
|
||||
};
|
||||
|
||||
/**
|
||||
* A Setting for an integer value. The value can be limited using the min
|
||||
* and max options
|
||||
*/
|
||||
struct GEODE_DLL IntSetting final {
|
||||
using ValueType = int64_t;
|
||||
|
||||
std::optional<std::string> name;
|
||||
std::optional<std::string> description;
|
||||
ValueType defaultValue;
|
||||
std::optional<ValueType> min;
|
||||
std::optional<ValueType> max;
|
||||
struct {
|
||||
bool arrows = true;
|
||||
bool bigArrows = false;
|
||||
size_t arrowStep = 1;
|
||||
size_t bigArrowStep = 5;
|
||||
bool slider = true;
|
||||
std::optional<ValueType> sliderStep = std::nullopt;
|
||||
bool input = true;
|
||||
} controls;
|
||||
|
||||
static Result<IntSetting> parse(JsonMaybeObject& obj);
|
||||
};
|
||||
|
||||
/**
|
||||
* A Setting for a float value. The value can be limited using the min
|
||||
* and max options
|
||||
*/
|
||||
struct GEODE_DLL FloatSetting final {
|
||||
using ValueType = double;
|
||||
|
||||
std::optional<std::string> name;
|
||||
std::optional<std::string> description;
|
||||
ValueType defaultValue;
|
||||
std::optional<ValueType> min;
|
||||
std::optional<ValueType> max;
|
||||
struct {
|
||||
bool arrows = true;
|
||||
bool bigArrows = false;
|
||||
size_t arrowStep = 1;
|
||||
size_t bigArrowStep = 5;
|
||||
bool slider = true;
|
||||
std::optional<ValueType> sliderStep = std::nullopt;
|
||||
bool input = true;
|
||||
} controls;
|
||||
|
||||
static Result<FloatSetting> parse(JsonMaybeObject& obj);
|
||||
};
|
||||
|
||||
/**
|
||||
* A Setting for a string value
|
||||
*/
|
||||
struct GEODE_DLL StringSetting final {
|
||||
using ValueType = std::string;
|
||||
|
||||
std::optional<std::string> name;
|
||||
std::optional<std::string> description;
|
||||
ValueType defaultValue;
|
||||
struct Data {
|
||||
/**
|
||||
* A regex the string must successfully match against
|
||||
*/
|
||||
std::optional<std::string> match;
|
||||
|
||||
/**
|
||||
* The CCTextInputNode's allowed character filter
|
||||
*/
|
||||
std::optional<std::string> filter;
|
||||
|
||||
/**
|
||||
* A list of options the user can choose from
|
||||
*/
|
||||
std::optional<std::vector<std::string>> options;
|
||||
};
|
||||
std::unique_ptr<Data> controls;
|
||||
|
||||
std::array<uint8_t, sizeof(Data::match) + sizeof(Data::filter) - sizeof(controls)> m_padding;
|
||||
|
||||
StringSetting();
|
||||
StringSetting(StringSetting const& other);
|
||||
StringSetting(StringSetting&& other) noexcept;
|
||||
StringSetting& operator=(StringSetting const& other);
|
||||
StringSetting& operator=(StringSetting&& other) noexcept;
|
||||
~StringSetting();
|
||||
|
||||
|
||||
static Result<StringSetting> parse(JsonMaybeObject& obj);
|
||||
};
|
||||
|
||||
/**
|
||||
* A Setting for a file input. Lets the user select a file from their
|
||||
* local device
|
||||
*/
|
||||
struct GEODE_DLL FileSetting final {
|
||||
using ValueType = std::filesystem::path;
|
||||
using Filter = utils::file::FilePickOptions::Filter;
|
||||
|
||||
std::optional<std::string> name;
|
||||
std::optional<std::string> description;
|
||||
ValueType defaultValue;
|
||||
struct {
|
||||
std::vector<Filter> filters;
|
||||
} controls;
|
||||
|
||||
static Result<FileSetting> parse(JsonMaybeObject& obj);
|
||||
};
|
||||
|
||||
/**
|
||||
* A Setting for an RGB color. See ColorAlphaSetting for a setting that
|
||||
* also allows customizing alpha
|
||||
*/
|
||||
struct GEODE_DLL ColorSetting final {
|
||||
using ValueType = cocos2d::ccColor3B;
|
||||
|
||||
std::optional<std::string> name;
|
||||
std::optional<std::string> description;
|
||||
ValueType defaultValue;
|
||||
|
||||
static Result<ColorSetting> parse(JsonMaybeObject& obj);
|
||||
};
|
||||
|
||||
/**
|
||||
* A Setting for an RGBA color. See ColorSetting for a setting that doesn't
|
||||
* have alpha
|
||||
*/
|
||||
struct GEODE_DLL ColorAlphaSetting final {
|
||||
using ValueType = cocos2d::ccColor4B;
|
||||
|
||||
std::optional<std::string> name;
|
||||
std::optional<std::string> description;
|
||||
ValueType defaultValue;
|
||||
|
||||
static Result<ColorAlphaSetting> parse(JsonMaybeObject& obj);
|
||||
};
|
||||
|
||||
/**
|
||||
* A custom setting, defined by the mod. See
|
||||
* [the tutorial page](https://docs.geode-sdk.org/mods/settings) for more
|
||||
* information about how to create custom settings
|
||||
*/
|
||||
struct GEODE_DLL CustomSetting final {
|
||||
std::shared_ptr<ModJson> json;
|
||||
};
|
||||
|
||||
using SettingKind = std::variant<
|
||||
BoolSetting,
|
||||
IntSetting,
|
||||
FloatSetting,
|
||||
StringSetting,
|
||||
FileSetting,
|
||||
ColorSetting,
|
||||
ColorAlphaSetting,
|
||||
CustomSetting
|
||||
>;
|
||||
|
||||
/**
|
||||
* Represents a saved value for a mod that can be customized by the user
|
||||
* through an in-game UI. This class is for modeling the setting's
|
||||
* definition - what values are accepted, its name etc.
|
||||
* See [the tutorial page](https://docs.geode-sdk.org/mods/settings)
|
||||
* for more information about how settings work
|
||||
* @see SettingValue
|
||||
* @see SettingNode
|
||||
*/
|
||||
struct GEODE_DLL Setting final {
|
||||
private:
|
||||
std::string m_key;
|
||||
std::string m_modID;
|
||||
SettingKind m_kind;
|
||||
|
||||
Setting() = default;
|
||||
|
||||
public:
|
||||
static Result<Setting> parse(
|
||||
std::string const& key,
|
||||
std::string const& mod,
|
||||
JsonMaybeValue& obj
|
||||
);
|
||||
Setting(
|
||||
std::string const& key,
|
||||
std::string const& mod,
|
||||
SettingKind const& kind
|
||||
);
|
||||
|
||||
template<class T>
|
||||
std::optional<T> get() {
|
||||
if (std::holds_alternative<T>(m_kind)) {
|
||||
return std::get<T>(m_kind);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::unique_ptr<SettingValue> createDefaultValue() const;
|
||||
bool isCustom() const;
|
||||
std::string getDisplayName() const;
|
||||
std::optional<std::string> getDescription() const;
|
||||
std::string getModID() const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stores the actual, current value of a Setting. See
|
||||
* [the tutorial page](https://docs.geode-sdk.org/mods/settings) for more
|
||||
* information, and how to create custom settings
|
||||
*/
|
||||
class GEODE_DLL SettingValue {
|
||||
protected:
|
||||
std::string m_key;
|
||||
std::string m_modID;
|
||||
|
||||
SettingValue(std::string const& key, std::string const& mod);
|
||||
|
||||
void valueChanged();
|
||||
|
||||
public:
|
||||
virtual ~SettingValue() = default;
|
||||
virtual bool load(matjson::Value const& json) = 0;
|
||||
virtual bool save(matjson::Value& json) const = 0;
|
||||
virtual SettingNode* createNode(float width) = 0;
|
||||
|
||||
std::string getKey() const;
|
||||
std::string getModID() const;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class GeodeSettingValue final : public SettingValue {
|
||||
public:
|
||||
using ValueType = typename T::ValueType;
|
||||
|
||||
protected:
|
||||
ValueType m_value;
|
||||
T m_definition;
|
||||
|
||||
using Valid = std::pair<ValueType, std::optional<std::string>>;
|
||||
|
||||
GEODE_DLL Valid toValid(ValueType const& value) const;
|
||||
|
||||
public:
|
||||
GeodeSettingValue(std::string const& key, std::string const& modID, T const& definition)
|
||||
: SettingValue(key, modID),
|
||||
m_definition(definition),
|
||||
m_value(definition.defaultValue) {}
|
||||
|
||||
bool load(matjson::Value const& json) override;
|
||||
bool save(matjson::Value& json) const;
|
||||
|
||||
GEODE_DLL SettingNode* createNode(float width) override;
|
||||
T castDefinition() const {
|
||||
return m_definition;
|
||||
}
|
||||
Setting getDefinition() const {
|
||||
return Setting(m_key, m_modID, m_definition);
|
||||
}
|
||||
|
||||
GEODE_DLL ValueType getValue() const;
|
||||
GEODE_DLL void setValue(ValueType const& value);
|
||||
GEODE_DLL Result<> validate(ValueType const& value) const;
|
||||
};
|
||||
|
||||
using BoolSettingValue = GeodeSettingValue<BoolSetting>;
|
||||
using IntSettingValue = GeodeSettingValue<IntSetting>;
|
||||
using FloatSettingValue = GeodeSettingValue<FloatSetting>;
|
||||
using StringSettingValue = GeodeSettingValue<StringSetting>;
|
||||
using FileSettingValue = GeodeSettingValue<FileSetting>;
|
||||
using ColorSettingValue = GeodeSettingValue<ColorSetting>;
|
||||
using ColorAlphaSettingValue = GeodeSettingValue<ColorAlphaSetting>;
|
||||
|
||||
// todo: remove in v3
|
||||
|
||||
template<class T>
|
||||
struct [[deprecated("Use SettingTypeForValueType from SettingV3 instead")]] GEODE_DLL SettingValueSetter {
|
||||
static T get(SettingValue* setting);
|
||||
static void set(SettingValue* setting, T const& value);
|
||||
};
|
||||
|
||||
template<class T>
|
||||
bool GeodeSettingValue<T>::load(matjson::Value const& json) {
|
||||
if (!json.is<ValueType>()) return false;
|
||||
m_value = json.as<ValueType>();
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool GeodeSettingValue<T>::save(matjson::Value& json) const {
|
||||
json = m_value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning(pop)
|
|
@ -1,63 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "Event.hpp"
|
||||
#include "Loader.hpp"
|
||||
#include "Setting.hpp"
|
||||
#include "Mod.hpp"
|
||||
#include "SettingV3.hpp"
|
||||
#include <optional>
|
||||
|
||||
namespace geode {
|
||||
struct GEODE_DLL [[deprecated("Use SettingChangedEventV3 from SettingV3.hpp instead")]] SettingChangedEvent : public Event {
|
||||
Mod* mod;
|
||||
SettingValue* value;
|
||||
|
||||
SettingChangedEvent(Mod* mod, SettingValue* value);
|
||||
};
|
||||
|
||||
class GEODE_DLL [[deprecated("Use SettingChangedEventV3 from SettingV3.hpp instead")]] SettingChangedFilter : public EventFilter<SettingChangedEvent> {
|
||||
protected:
|
||||
std::string m_modID;
|
||||
std::optional<std::string> m_targetKey;
|
||||
|
||||
public:
|
||||
using Callback = void(SettingValue*);
|
||||
|
||||
ListenerResult handle(utils::MiniFunction<Callback> fn, SettingChangedEvent* event);
|
||||
/**
|
||||
* Listen to changes on a setting, or all settings
|
||||
* @param modID Mod whose settings to listen to
|
||||
* @param settingID Setting to listen to, or all settings if nullopt
|
||||
*/
|
||||
SettingChangedFilter(
|
||||
std::string const& modID,
|
||||
std::optional<std::string> const& settingKey
|
||||
);
|
||||
SettingChangedFilter(SettingChangedFilter const&) = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* Listen for built-in setting changes
|
||||
*/
|
||||
template<class T>
|
||||
class [[deprecated("Use SettingChangedEventV3 from SettingV3.hpp instead")]] GeodeSettingChangedFilter : public SettingChangedFilter {
|
||||
public:
|
||||
using Callback = void(T);
|
||||
|
||||
ListenerResult handle(utils::MiniFunction<Callback> fn, SettingChangedEvent* event) {
|
||||
if (
|
||||
m_modID == event->mod->getID() &&
|
||||
(!m_targetKey || m_targetKey.value() == event->value->getKey())
|
||||
) {
|
||||
fn(SettingValueSetter<T>::get(event->value));
|
||||
}
|
||||
return ListenerResult::Propagate;
|
||||
}
|
||||
|
||||
GeodeSettingChangedFilter(
|
||||
std::string const& modID,
|
||||
std::string const& settingID
|
||||
) : SettingChangedFilter(modID, settingID) {}
|
||||
GeodeSettingChangedFilter(GeodeSettingChangedFilter const&) = default;
|
||||
};
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "Setting.hpp"
|
||||
|
||||
#include <cocos2d.h>
|
||||
|
||||
namespace geode {
|
||||
class SettingNode;
|
||||
|
||||
struct SettingNodeDelegate {
|
||||
virtual void settingValueChanged(SettingNode* node) {}
|
||||
virtual void settingValueCommitted(SettingNode* node) {}
|
||||
};
|
||||
|
||||
class GEODE_DLL SettingNode : public cocos2d::CCNode {
|
||||
protected:
|
||||
SettingValue* m_value;
|
||||
SettingNodeDelegate* m_delegate = nullptr;
|
||||
|
||||
bool init(SettingValue* value);
|
||||
void dispatchChanged();
|
||||
void dispatchCommitted();
|
||||
|
||||
public:
|
||||
void setDelegate(SettingNodeDelegate* delegate);
|
||||
|
||||
virtual void commit() = 0;
|
||||
virtual bool hasUncommittedChanges() = 0;
|
||||
virtual bool hasNonDefaultValue() = 0;
|
||||
virtual void resetToDefault() = 0;
|
||||
};
|
||||
}
|
|
@ -3,15 +3,12 @@
|
|||
#include "../DefaultInclude.hpp"
|
||||
#include <optional>
|
||||
#include <cocos2d.h>
|
||||
// todo: remove this header in 4.0.0
|
||||
#include "Setting.hpp"
|
||||
#include "../utils/cocos.hpp"
|
||||
#include "../utils/file.hpp"
|
||||
// this unfortunately has to be included because of C++ templates
|
||||
#include "../utils/JsonValidation.hpp"
|
||||
#include "../utils/function.hpp"
|
||||
|
||||
// todo in v4: this can be removed as well as the friend decl in LegacyCustomSettingV3
|
||||
class LegacyCustomSettingToV3Node;
|
||||
class ModSettingsPopup;
|
||||
|
||||
namespace geode {
|
||||
|
@ -183,17 +180,6 @@ namespace geode {
|
|||
* Reset this setting's value back to its original value
|
||||
*/
|
||||
virtual void reset() = 0;
|
||||
|
||||
[[deprecated(
|
||||
"This function will be removed alongside legacy settings in 4.0.0! "
|
||||
"You should NOT be implementing it for your own custom setting classes"
|
||||
)]]
|
||||
virtual std::optional<Setting> convertToLegacy() const;
|
||||
[[deprecated(
|
||||
"This function will be removed alongside legacy settings in 4.0.0! "
|
||||
"You should NOT be implementing it for your own custom setting classes"
|
||||
)]]
|
||||
virtual std::optional<std::shared_ptr<SettingValue>> convertToLegacyValue() const;
|
||||
};
|
||||
|
||||
using SettingGenerator = std::function<Result<std::shared_ptr<SettingV3>>(
|
||||
|
@ -357,37 +343,6 @@ namespace geode {
|
|||
void reset() override;
|
||||
};
|
||||
|
||||
// todo in v4: remove this class completely
|
||||
class GEODE_DLL LegacyCustomSettingV3 final : public SettingV3 {
|
||||
private:
|
||||
class Impl;
|
||||
std::shared_ptr<Impl> m_impl;
|
||||
|
||||
friend class ::geode::ModSettingsManager;
|
||||
friend class ::LegacyCustomSettingToV3Node;
|
||||
|
||||
private:
|
||||
class PrivateMarker {};
|
||||
friend class SettingV3;
|
||||
|
||||
public:
|
||||
LegacyCustomSettingV3(PrivateMarker);
|
||||
static Result<std::shared_ptr<LegacyCustomSettingV3>> parse(std::string const& key, std::string const& modID, matjson::Value const& json);
|
||||
|
||||
std::shared_ptr<SettingValue> getValue() const;
|
||||
void setValue(std::shared_ptr<SettingValue> value);
|
||||
|
||||
bool load(matjson::Value const& json) override;
|
||||
bool save(matjson::Value& json) const override;
|
||||
SettingNodeV3* createNode(float width) override;
|
||||
|
||||
bool isDefaultValue() const override;
|
||||
void reset() override;
|
||||
|
||||
std::optional<Setting> convertToLegacy() const override;
|
||||
std::optional<std::shared_ptr<SettingValue>> convertToLegacyValue() const override;
|
||||
};
|
||||
|
||||
class GEODE_DLL BoolSettingV3 final : public SettingBaseValueV3<bool> {
|
||||
private:
|
||||
class Impl;
|
||||
|
@ -404,9 +359,6 @@ namespace geode {
|
|||
Result<> isValid(bool value) const override;
|
||||
|
||||
SettingNodeV3* createNode(float width) override;
|
||||
|
||||
std::optional<Setting> convertToLegacy() const override;
|
||||
std::optional<std::shared_ptr<SettingValue>> convertToLegacyValue() const override;
|
||||
};
|
||||
|
||||
class GEODE_DLL IntSettingV3 final : public SettingBaseValueV3<int64_t> {
|
||||
|
@ -436,9 +388,6 @@ namespace geode {
|
|||
bool isInputEnabled() const;
|
||||
|
||||
SettingNodeV3* createNode(float width) override;
|
||||
|
||||
std::optional<Setting> convertToLegacy() const override;
|
||||
std::optional<std::shared_ptr<SettingValue>> convertToLegacyValue() const override;
|
||||
};
|
||||
|
||||
class GEODE_DLL FloatSettingV3 final : public SettingBaseValueV3<double> {
|
||||
|
@ -468,9 +417,6 @@ namespace geode {
|
|||
bool isInputEnabled() const;
|
||||
|
||||
SettingNodeV3* createNode(float width) override;
|
||||
|
||||
std::optional<Setting> convertToLegacy() const override;
|
||||
std::optional<std::shared_ptr<SettingValue>> convertToLegacyValue() const override;
|
||||
};
|
||||
|
||||
class GEODE_DLL StringSettingV3 final : public SettingBaseValueV3<std::string, std::string_view> {
|
||||
|
@ -493,9 +439,6 @@ namespace geode {
|
|||
std::optional<std::vector<std::string>> getEnumOptions() const;
|
||||
|
||||
SettingNodeV3* createNode(float width) override;
|
||||
|
||||
std::optional<Setting> convertToLegacy() const override;
|
||||
std::optional<std::shared_ptr<SettingValue>> convertToLegacyValue() const override;
|
||||
};
|
||||
|
||||
class GEODE_DLL FileSettingV3 final : public SettingBaseValueV3<std::filesystem::path, std::filesystem::path const&> {
|
||||
|
@ -519,9 +462,6 @@ namespace geode {
|
|||
std::optional<std::vector<utils::file::FilePickOptions::Filter>> getFilters() const;
|
||||
|
||||
SettingNodeV3* createNode(float width) override;
|
||||
|
||||
std::optional<Setting> convertToLegacy() const override;
|
||||
std::optional<std::shared_ptr<SettingValue>> convertToLegacyValue() const override;
|
||||
};
|
||||
|
||||
class GEODE_DLL Color3BSettingV3 final : public SettingBaseValueV3<cocos2d::ccColor3B> {
|
||||
|
@ -540,9 +480,6 @@ namespace geode {
|
|||
Result<> isValid(cocos2d::ccColor3B value) const override;
|
||||
|
||||
SettingNodeV3* createNode(float width) override;
|
||||
|
||||
std::optional<Setting> convertToLegacy() const override;
|
||||
std::optional<std::shared_ptr<SettingValue>> convertToLegacyValue() const override;
|
||||
};
|
||||
|
||||
class GEODE_DLL Color4BSettingV3 final : public SettingBaseValueV3<cocos2d::ccColor4B> {
|
||||
|
@ -561,9 +498,6 @@ namespace geode {
|
|||
Result<> isValid(cocos2d::ccColor4B value) const override;
|
||||
|
||||
SettingNodeV3* createNode(float width) override;
|
||||
|
||||
std::optional<Setting> convertToLegacy() const override;
|
||||
std::optional<std::shared_ptr<SettingValue>> convertToLegacyValue() const override;
|
||||
};
|
||||
|
||||
class GEODE_DLL SettingNodeV3 : public cocos2d::CCNode {
|
||||
|
|
|
@ -133,11 +133,6 @@ namespace geode {
|
|||
*/
|
||||
GEODE_DLL void openSupportPopup(Mod* mod);
|
||||
GEODE_DLL void openSupportPopup(ModMetadata const& metadata);
|
||||
/**
|
||||
* Open the store page for a mod (if it exists)
|
||||
*/
|
||||
[[deprecated("Will be removed, use openInfoPopup instead")]]
|
||||
GEODE_DLL void openIndexPopup(Mod* mod);
|
||||
/**
|
||||
* Open the settings popup for a mod (if it has any settings)
|
||||
*/
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/DefaultInclude.hpp>
|
||||
#include <Geode/binding/CCTextInputNode.hpp>
|
||||
#include <cocos2d.h>
|
||||
|
||||
namespace geode {
|
||||
class GEODE_DLL InputNode : public cocos2d::CCMenuItem {
|
||||
protected:
|
||||
cocos2d::extension::CCScale9Sprite* m_bgSprite;
|
||||
CCTextInputNode* m_input;
|
||||
|
||||
bool init(float, float, char const*, char const*, std::string const&, int);
|
||||
bool init(float, char const*, char const*, std::string const&, int);
|
||||
|
||||
public:
|
||||
[[deprecated("Use geode::TextInput from the ui/TextInput.hpp header instead")]]
|
||||
static InputNode* create(
|
||||
float width, char const* placeholder, char const* fontFile, std::string const& filter,
|
||||
int limit
|
||||
);
|
||||
[[deprecated("Use geode::TextInput from the ui/TextInput.hpp header instead")]]
|
||||
static InputNode* create(
|
||||
float width, char const* placeholder, std::string const& filter, int limit
|
||||
);
|
||||
[[deprecated("Use geode::TextInput from the ui/TextInput.hpp header instead")]]
|
||||
static InputNode* create(float width, char const* placeholder, std::string const& filter);
|
||||
[[deprecated("Use geode::TextInput from the ui/TextInput.hpp header instead")]]
|
||||
static InputNode* create(float width, char const* placeholder, char const* fontFile);
|
||||
[[deprecated("Use geode::TextInput from the ui/TextInput.hpp header instead")]]
|
||||
static InputNode* create(float width, char const* placeholder);
|
||||
|
||||
CCTextInputNode* getInput() const;
|
||||
cocos2d::extension::CCScale9Sprite* getBG() const;
|
||||
|
||||
void setEnabled(bool enabled) override;
|
||||
|
||||
void setString(std::string const&);
|
||||
std::string getString();
|
||||
};
|
||||
}
|
|
@ -1,448 +1,430 @@
|
|||
#pragma once
|
||||
|
||||
#include "../include/ccMacros.h"
|
||||
#include "../cocoa/CCAffineTransform.h"
|
||||
#include "../cocoa/CCArray.h"
|
||||
#include <Geode/platform/platform.hpp>
|
||||
#include <optional>
|
||||
#include <memory>
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
class CCNode;
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4275)
|
||||
|
||||
/**
|
||||
* Layouts automatically handle the positioning of nodes. Use CCNode::setLayout
|
||||
* to apply a layout to a node, and then use CCNode::updateLayout to apply
|
||||
* the layout's positioning. Geode comes with a few default layouts like
|
||||
* RowLayout, ColumnLayout, and GridLayout, but if you need a different kind
|
||||
* of layout you can inherit from the Layout class.
|
||||
*/
|
||||
class GEODE_DLL Layout : public CCObject {
|
||||
protected:
|
||||
CCArray* getNodesToPosition(CCNode* forNode) const;
|
||||
|
||||
bool m_ignoreInvisibleChildren = false;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Automatically apply the layout's positioning on a set of nodes
|
||||
* @param on Node to apply the layout on. Position's the node's children
|
||||
* according to the layout. The content size of the node should be
|
||||
* respected as a boundary the layout shouldn't overflow. The node may be
|
||||
* rescaled to better fit its contents
|
||||
*/
|
||||
virtual void apply(CCNode* on) = 0;
|
||||
|
||||
/**
|
||||
* Get how much space this layout would like to take up for a given target
|
||||
*/
|
||||
virtual CCSize getSizeHint(CCNode* on) const = 0;
|
||||
|
||||
void ignoreInvisibleChildren(bool ignore);
|
||||
bool isIgnoreInvisibleChildren() const;
|
||||
|
||||
virtual ~Layout() = default;
|
||||
};
|
||||
|
||||
class GEODE_DLL LayoutOptions : public CCObject {
|
||||
public:
|
||||
virtual ~LayoutOptions() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* The direction of an AxisLayout
|
||||
*/
|
||||
enum class Axis {
|
||||
Row,
|
||||
Column,
|
||||
};
|
||||
|
||||
/**
|
||||
* Specifies the alignment of something in an AxisLayout
|
||||
*/
|
||||
enum class AxisAlignment {
|
||||
// Align items to the start
|
||||
// |ooo......|
|
||||
Start,
|
||||
// All items are centered
|
||||
// |...ooo...|
|
||||
Center,
|
||||
// Align items to the end
|
||||
// |......ooo|
|
||||
End,
|
||||
// Each item gets the same portion from the layout (disregards gap)
|
||||
// |.o..o..o.|
|
||||
Even,
|
||||
// Space between each item is the same (disregards gap)
|
||||
// |o...o...o|
|
||||
Between,
|
||||
};
|
||||
|
||||
constexpr float AXISLAYOUT_DEFAULT_MIN_SCALE = 0.65f;
|
||||
constexpr int AXISLAYOUT_DEFAULT_PRIORITY = 0;
|
||||
|
||||
/**
|
||||
* Options for controlling the behaviour of individual nodes in an AxisLayout
|
||||
* @example
|
||||
* auto node = CCNode::create();
|
||||
* // this node will have 10 units of spacing between it and the next one
|
||||
* node->setLayoutOptions(
|
||||
* AxisLayoutOptions::create()
|
||||
* ->setNextGap(10.f)
|
||||
* );
|
||||
* someNodeWithALayout->addChild(node);
|
||||
*/
|
||||
class GEODE_DLL AxisLayoutOptions : public LayoutOptions {
|
||||
protected:
|
||||
class Impl;
|
||||
|
||||
std::unique_ptr<Impl> m_impl;
|
||||
|
||||
AxisLayoutOptions();
|
||||
|
||||
public:
|
||||
static AxisLayoutOptions* create();
|
||||
|
||||
virtual ~AxisLayoutOptions();
|
||||
|
||||
std::optional<bool> getAutoScale() const;
|
||||
// @note Use hasExplicitMaxScale to know if the default scale has been overwritten
|
||||
float getMaxScale() const;
|
||||
// @note Use hasExplicitMinScale to know if the default scale has been overwritten
|
||||
float getMinScale() const;
|
||||
bool hasExplicitMaxScale() const;
|
||||
bool hasExplicitMinScale() const;
|
||||
float getRelativeScale() const;
|
||||
std::optional<float> getLength() const;
|
||||
std::optional<float> getPrevGap() const;
|
||||
std::optional<float> getNextGap() const;
|
||||
bool getBreakLine() const;
|
||||
bool getSameLine() const;
|
||||
int getScalePriority() const;
|
||||
std::optional<AxisAlignment> getCrossAxisAlignment() const;
|
||||
|
||||
/**
|
||||
* Set the maximum scale this node can be if it's contained in an
|
||||
* auto-scaled layout. Default is 1
|
||||
*/
|
||||
[[deprecated("Use AxisLayoutOptions::setScaleLimits")]]
|
||||
AxisLayoutOptions* setMaxScale(float scale);
|
||||
|
||||
/**
|
||||
* Set the minimum scale this node can be if it's contained in an
|
||||
* auto-scaled layout. Default is AXISLAYOUT_DEFAULT_MIN_SCALE
|
||||
*/
|
||||
[[deprecated("Use AxisLayoutOptions::setScaleLimits")]]
|
||||
AxisLayoutOptions* setMinScale(float scale);
|
||||
|
||||
/**
|
||||
* Set the limits to what the node can be scaled to. Passing `std::nullopt`
|
||||
* uses the parent layout's default min / max scales
|
||||
*/
|
||||
AxisLayoutOptions* setScaleLimits(std::optional<float> min, std::optional<float> max);
|
||||
|
||||
/**
|
||||
* Set the relative scale of this node compared to other nodes if it's
|
||||
* contained in an auto-scaled layout. Default is 1
|
||||
*/
|
||||
AxisLayoutOptions* setRelativeScale(float scale);
|
||||
|
||||
/**
|
||||
* Set auto-scaling for this node, overriding the layout's auto-scale
|
||||
* setting. If nullopt, the layout's auto-scale options will be used
|
||||
*/
|
||||
AxisLayoutOptions* setAutoScale(std::optional<bool> enabled);
|
||||
|
||||
/**
|
||||
* Set an absolute length for this node. If nullopt, the length will be
|
||||
* dynamically calculated based on content size
|
||||
*/
|
||||
AxisLayoutOptions* setLength(std::optional<float> length);
|
||||
|
||||
/**
|
||||
* Override the default gap in the layout between this node and the
|
||||
* previous one. If nullopt, the default gap of the layout will be used
|
||||
*/
|
||||
AxisLayoutOptions* setPrevGap(std::optional<float> gap);
|
||||
|
||||
/**
|
||||
* Override the default gap in the layout between this node and the next
|
||||
* one. If nullopt, the default gap of the layout will be used
|
||||
*/
|
||||
AxisLayoutOptions* setNextGap(std::optional<float> gap);
|
||||
|
||||
/**
|
||||
* If enabled, the node will always cause a growable axis layout to break
|
||||
* into a new line even if the current line could've fit the next node
|
||||
*/
|
||||
AxisLayoutOptions* setBreakLine(bool enable);
|
||||
|
||||
/**
|
||||
* If enabled, the node will be forced to be on the same line as the
|
||||
* previous node even if doing this would overflow
|
||||
*/
|
||||
AxisLayoutOptions* setSameLine(bool enable);
|
||||
|
||||
/**
|
||||
* Set the scale priority of this node. Nodes with higher priority will be
|
||||
* scaled down first before nodes with lower priority when an auto-scaled
|
||||
* layout attempts to fit its contents. Default is
|
||||
* AXISLAYOUT_DEFAULT_PRIORITY
|
||||
* @note For optimal performance, the priorities should all be close to
|
||||
* each other with no gaps
|
||||
*/
|
||||
AxisLayoutOptions* setScalePriority(int priority);
|
||||
|
||||
/**
|
||||
* Override the cross axis alignment for this node in the layout
|
||||
*/
|
||||
AxisLayoutOptions* setCrossAxisAlignment(std::optional<AxisAlignment> alignment);
|
||||
};
|
||||
|
||||
/**
|
||||
* A multi-purpose dynamic layout for arranging nodes along an axis. Can be
|
||||
* used to arrange nodes in a single line, a grid, or a flex layout. The
|
||||
* RowLayout and ColumnLayout classes function as simple thin wrappers over
|
||||
* AxisLayout. The positioning of individual nodes in the layout can be
|
||||
* further controlled using AxisLayoutOptions
|
||||
* @warning Calculating layouts can get increasingly expensive for large
|
||||
* amounts of child nodes being fit into a small space - while this should
|
||||
* never prove a real performance concern as most layouts only have a few
|
||||
* hundred children at the very most, be aware that you probably shouldn't
|
||||
* call CCNode::updateLayout every frame for a menu with thousands of children
|
||||
* @example
|
||||
* auto menu = CCMenu::create();
|
||||
* // The menu's children will be arranged horizontally, unless they overflow
|
||||
* // the content size width in which case a new line will be inserted and
|
||||
* // aligned to the left. The menu automatically will automatically grow in
|
||||
* // height to fit all the rows
|
||||
* menu->setLayout(
|
||||
* RowLayout::create()
|
||||
* ->setGap(10.f)
|
||||
* ->setGrowCrossAxis(true)
|
||||
* ->setAxisAlignment(AxisAlignment::Start)
|
||||
* );
|
||||
* menu->setContentSize({ 200.f, 0.f });
|
||||
* menu->addChild(...);
|
||||
* menu->updateLayout();
|
||||
*/
|
||||
class GEODE_DLL AxisLayout : public Layout {
|
||||
protected:
|
||||
class Impl;
|
||||
|
||||
std::unique_ptr<Impl> m_impl;
|
||||
|
||||
AxisLayout(Axis);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a new AxisLayout. Note that this class is not automatically
|
||||
* managed by default, so you must assign it to a CCNode or manually
|
||||
* manage the memory yourself. See the chainable setters on AxisLayout for
|
||||
* what options you can customize for the layout
|
||||
* @param axis The direction of the layout
|
||||
* @note For convenience, you can use the RowLayout and ColumnLayout
|
||||
* classes, which are just thin wrappers over AxisLayout
|
||||
* @returns Created AxisLayout
|
||||
*/
|
||||
static AxisLayout* create(Axis axis = Axis::Row);
|
||||
|
||||
virtual ~AxisLayout();
|
||||
|
||||
void apply(CCNode* on) override;
|
||||
CCSize getSizeHint(CCNode* on) const override;
|
||||
|
||||
Axis getAxis() const;
|
||||
AxisAlignment getAxisAlignment() const;
|
||||
AxisAlignment getCrossAxisAlignment() const;
|
||||
AxisAlignment getCrossAxisLineAlignment() const;
|
||||
float getGap() const;
|
||||
bool getAxisReverse() const;
|
||||
bool getCrossAxisReverse() const;
|
||||
bool getAutoScale() const;
|
||||
bool getGrowCrossAxis() const;
|
||||
bool getCrossAxisOverflow() const;
|
||||
std::optional<float> getAutoGrowAxis() const;
|
||||
float getDefaultMinScale() const;
|
||||
float getDefaultMaxScale() const;
|
||||
|
||||
AxisLayout* setAxis(Axis axis);
|
||||
/**
|
||||
* Sets where to align the target node's children on the main axis (X-axis
|
||||
* for Row, Y-axis for Column)
|
||||
*/
|
||||
AxisLayout* setAxisAlignment(AxisAlignment align);
|
||||
/**
|
||||
* Sets where to align the target node's children on the cross-axis (Y-axis
|
||||
* for Row, X-axis for Column)
|
||||
*/
|
||||
AxisLayout* setCrossAxisAlignment(AxisAlignment align);
|
||||
/**
|
||||
* Sets where to align the target node's children on the cross-axis for
|
||||
* each row (Y-axis for Row, X-axis for Column)
|
||||
*/
|
||||
AxisLayout* setCrossAxisLineAlignment(AxisAlignment align);
|
||||
/**
|
||||
* The spacing between the children of the node this layout applies to.
|
||||
* Measured as the space between their edges, not centres. Does not apply
|
||||
* on the main / cross axis if their alignment is AxisAlignment::Even
|
||||
*/
|
||||
AxisLayout* setGap(float gap);
|
||||
/**
|
||||
* Whether to reverse the direction of the children in this layout or not
|
||||
*/
|
||||
AxisLayout* setAxisReverse(bool reverse);
|
||||
/**
|
||||
* Whether to reverse the direction of the rows on the cross-axis or not
|
||||
*/
|
||||
AxisLayout* setCrossAxisReverse(bool reverse);
|
||||
/**
|
||||
* If enabled, then the layout may scale the target's children if they are
|
||||
* about to overflow. Assumes that all the childrens' intended scale is 1
|
||||
*/
|
||||
AxisLayout* setAutoScale(bool enable);
|
||||
/**
|
||||
* If true, if the main axis overflows extra nodes will be placed on new
|
||||
* rows/columns on the cross-axis
|
||||
*/
|
||||
AxisLayout* setGrowCrossAxis(bool expand);
|
||||
/**
|
||||
* If true, the cross-axis content size of the target node will be
|
||||
* automatically adjusted to fit the children
|
||||
*/
|
||||
AxisLayout* setCrossAxisOverflow(bool allow);
|
||||
/**
|
||||
* If not `std::nullopt`, then the axis will be automatically extended to
|
||||
* fit all items in a single row whose minimum length is the specified.
|
||||
* Useful for scrollable list layer contents
|
||||
*/
|
||||
AxisLayout* setAutoGrowAxis(std::optional<float> allowAndMinLength);
|
||||
/**
|
||||
* Set the default minimum/maximum scales for nodes in the layout
|
||||
*/
|
||||
AxisLayout* setDefaultScaleLimits(float min, float max);
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple layout for arranging nodes in a row (horizontal line)
|
||||
*/
|
||||
class GEODE_DLL RowLayout : public AxisLayout {
|
||||
protected:
|
||||
RowLayout();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a new RowLayout. See the chainable setters on RowLayout for
|
||||
* what options you can customize for the layout
|
||||
* @returns Created RowLayout
|
||||
*/
|
||||
static RowLayout* create();
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple layout for arranging nodes in a column (vertical line)
|
||||
*/
|
||||
class GEODE_DLL ColumnLayout : public AxisLayout {
|
||||
protected:
|
||||
ColumnLayout();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a new ColumnLayout. See the chainable setters on RowLayout for
|
||||
* what options you can customize for the layout
|
||||
* @returns Created ColumnLayout
|
||||
*/
|
||||
static ColumnLayout* create();
|
||||
};
|
||||
|
||||
/**
|
||||
* The relative position of a node to its parent in an AnchorLayout
|
||||
*/
|
||||
enum class Anchor {
|
||||
Center,
|
||||
TopLeft,
|
||||
Top,
|
||||
TopRight,
|
||||
Right,
|
||||
BottomRight,
|
||||
Bottom,
|
||||
BottomLeft,
|
||||
Left,
|
||||
};
|
||||
|
||||
/**
|
||||
* Options for customizing a node's position in an AnchorLayout
|
||||
*/
|
||||
class GEODE_DLL AnchorLayoutOptions : public LayoutOptions {
|
||||
protected:
|
||||
Anchor m_anchor = Anchor::Center;
|
||||
CCPoint m_offset = CCPointZero;
|
||||
|
||||
public:
|
||||
static AnchorLayoutOptions* create();
|
||||
|
||||
Anchor getAnchor() const;
|
||||
CCPoint getOffset() const;
|
||||
|
||||
AnchorLayoutOptions* setAnchor(Anchor anchor);
|
||||
AnchorLayoutOptions* setOffset(CCPoint const& offset);
|
||||
};
|
||||
|
||||
/**
|
||||
* A layout for positioning nodes at specific positions relative to their
|
||||
* parent's content size. See `Anchor` for available anchoring options. Useful
|
||||
* for example for popups, where a popup using `AnchorLayout` can be
|
||||
* automatically resized without needing to manually shuffle nodes around
|
||||
*/
|
||||
class GEODE_DLL AnchorLayout : public Layout {
|
||||
public:
|
||||
static AnchorLayout* create();
|
||||
|
||||
void apply(CCNode* on) override;
|
||||
CCSize getSizeHint(CCNode* on) const override;
|
||||
|
||||
/**
|
||||
* Get a position according to anchoring rules, with the same algorithm as
|
||||
* `AnchorLayout` uses to position its nodes
|
||||
* @param in The node whose content size to use as a reference
|
||||
* @param anchor The anchor position
|
||||
* @param offset Offset from the anchor
|
||||
* @returns A position in `in` for the anchored and offsetted location
|
||||
*/
|
||||
static CCPoint getAnchoredPosition(CCNode* in, Anchor anchor, CCPoint const& offset);
|
||||
};
|
||||
|
||||
/**
|
||||
* A layout for automatically copying the content size of a node to other nodes.
|
||||
* Basically main use case is for FLAlertLayers (setting the size of the
|
||||
* background and `m_buttonMenu` based on `m_mainLayer`)
|
||||
*/
|
||||
class GEODE_DLL CopySizeLayout : public cocos2d::AnchorLayout {
|
||||
protected:
|
||||
cocos2d::CCArray* m_targets;
|
||||
|
||||
public:
|
||||
static CopySizeLayout* create();
|
||||
virtual ~CopySizeLayout();
|
||||
|
||||
/**
|
||||
* Add a target to be automatically resized. Any targets' layouts will
|
||||
* also be updated when this layout is updated
|
||||
*/
|
||||
CopySizeLayout* add(cocos2d::CCNode* target);
|
||||
/**
|
||||
* Remove a target from being automatically resized
|
||||
*/
|
||||
CopySizeLayout* remove(cocos2d::CCNode* target);
|
||||
|
||||
void apply(cocos2d::CCNode* in) override;
|
||||
cocos2d::CCSize getSizeHint(cocos2d::CCNode* in) const override;
|
||||
};
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
NS_CC_END
|
||||
#pragma once
|
||||
|
||||
#include <cocos2d.h>
|
||||
#include <Geode/platform/platform.hpp>
|
||||
#include <optional>
|
||||
#include <memory>
|
||||
|
||||
namespace geode {
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4275)
|
||||
|
||||
/**
|
||||
* Layouts automatically handle the positioning of nodes. Use CCNode::setLayout
|
||||
* to apply a layout to a node, and then use CCNode::updateLayout to apply
|
||||
* the layout's positioning. Geode comes with a few default layouts like
|
||||
* RowLayout, ColumnLayout, and GridLayout, but if you need a different kind
|
||||
* of layout you can inherit from the Layout class.
|
||||
*/
|
||||
class GEODE_DLL Layout : public cocos2d::CCObject {
|
||||
protected:
|
||||
cocos2d::CCArray* getNodesToPosition(cocos2d::CCNode* forNode) const;
|
||||
|
||||
bool m_ignoreInvisibleChildren = false;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Automatically apply the layout's positioning on a set of nodes
|
||||
* @param on Node to apply the layout on. Position's the node's children
|
||||
* according to the layout. The content size of the node should be
|
||||
* respected as a boundary the layout shouldn't overflow. The node may be
|
||||
* rescaled to better fit its contents
|
||||
*/
|
||||
virtual void apply(cocos2d::CCNode* on) = 0;
|
||||
|
||||
/**
|
||||
* Get how much space this layout would like to take up for a given target
|
||||
*/
|
||||
virtual cocos2d::CCSize getSizeHint(cocos2d::CCNode* on) const = 0;
|
||||
|
||||
void ignoreInvisibleChildren(bool ignore);
|
||||
bool isIgnoreInvisibleChildren() const;
|
||||
|
||||
virtual ~Layout() = default;
|
||||
};
|
||||
|
||||
class GEODE_DLL LayoutOptions : public cocos2d::CCObject {
|
||||
public:
|
||||
virtual ~LayoutOptions() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* The direction of an AxisLayout
|
||||
*/
|
||||
enum class Axis {
|
||||
Row,
|
||||
Column,
|
||||
};
|
||||
|
||||
/**
|
||||
* Specifies the alignment of something in an AxisLayout
|
||||
*/
|
||||
enum class AxisAlignment {
|
||||
// Align items to the start
|
||||
// |ooo......|
|
||||
Start,
|
||||
// All items are centered
|
||||
// |...ooo...|
|
||||
Center,
|
||||
// Align items to the end
|
||||
// |......ooo|
|
||||
End,
|
||||
// Each item gets the same portion from the layout (disregards gap)
|
||||
// |.o..o..o.|
|
||||
Even,
|
||||
// Space between each item is the same (disregards gap)
|
||||
// |o...o...o|
|
||||
Between,
|
||||
};
|
||||
|
||||
constexpr float AXISLAYOUT_DEFAULT_MIN_SCALE = 0.65f;
|
||||
constexpr int AXISLAYOUT_DEFAULT_PRIORITY = 0;
|
||||
|
||||
/**
|
||||
* Options for controlling the behaviour of individual nodes in an AxisLayout
|
||||
* @example
|
||||
* auto node = CCNode::create();
|
||||
* // this node will have 10 units of spacing between it and the next one
|
||||
* node->setLayoutOptions(
|
||||
* AxisLayoutOptions::create()
|
||||
* ->setNextGap(10.f)
|
||||
* );
|
||||
* someNodeWithALayout->addChild(node);
|
||||
*/
|
||||
class GEODE_DLL AxisLayoutOptions : public LayoutOptions {
|
||||
protected:
|
||||
class Impl;
|
||||
|
||||
std::unique_ptr<Impl> m_impl;
|
||||
|
||||
AxisLayoutOptions();
|
||||
|
||||
public:
|
||||
static AxisLayoutOptions* create();
|
||||
|
||||
virtual ~AxisLayoutOptions();
|
||||
|
||||
std::optional<bool> getAutoScale() const;
|
||||
// @note Use hasExplicitMaxScale to know if the default scale has been overwritten
|
||||
float getMaxScale() const;
|
||||
// @note Use hasExplicitMinScale to know if the default scale has been overwritten
|
||||
float getMinScale() const;
|
||||
bool hasExplicitMaxScale() const;
|
||||
bool hasExplicitMinScale() const;
|
||||
float getRelativeScale() const;
|
||||
std::optional<float> getLength() const;
|
||||
std::optional<float> getPrevGap() const;
|
||||
std::optional<float> getNextGap() const;
|
||||
bool getBreakLine() const;
|
||||
bool getSameLine() const;
|
||||
int getScalePriority() const;
|
||||
std::optional<AxisAlignment> getCrossAxisAlignment() const;
|
||||
|
||||
/**
|
||||
* Set the limits to what the node can be scaled to. Passing `std::nullopt`
|
||||
* uses the parent layout's default min / max scales
|
||||
*/
|
||||
AxisLayoutOptions* setScaleLimits(std::optional<float> min, std::optional<float> max);
|
||||
|
||||
/**
|
||||
* Set the relative scale of this node compared to other nodes if it's
|
||||
* contained in an auto-scaled layout. Default is 1
|
||||
*/
|
||||
AxisLayoutOptions* setRelativeScale(float scale);
|
||||
|
||||
/**
|
||||
* Set auto-scaling for this node, overriding the layout's auto-scale
|
||||
* setting. If nullopt, the layout's auto-scale options will be used
|
||||
*/
|
||||
AxisLayoutOptions* setAutoScale(std::optional<bool> enabled);
|
||||
|
||||
/**
|
||||
* Set an absolute length for this node. If nullopt, the length will be
|
||||
* dynamically calculated based on content size
|
||||
*/
|
||||
AxisLayoutOptions* setLength(std::optional<float> length);
|
||||
|
||||
/**
|
||||
* Override the default gap in the layout between this node and the
|
||||
* previous one. If nullopt, the default gap of the layout will be used
|
||||
*/
|
||||
AxisLayoutOptions* setPrevGap(std::optional<float> gap);
|
||||
|
||||
/**
|
||||
* Override the default gap in the layout between this node and the next
|
||||
* one. If nullopt, the default gap of the layout will be used
|
||||
*/
|
||||
AxisLayoutOptions* setNextGap(std::optional<float> gap);
|
||||
|
||||
/**
|
||||
* If enabled, the node will always cause a growable axis layout to break
|
||||
* into a new line even if the current line could've fit the next node
|
||||
*/
|
||||
AxisLayoutOptions* setBreakLine(bool enable);
|
||||
|
||||
/**
|
||||
* If enabled, the node will be forced to be on the same line as the
|
||||
* previous node even if doing this would overflow
|
||||
*/
|
||||
AxisLayoutOptions* setSameLine(bool enable);
|
||||
|
||||
/**
|
||||
* Set the scale priority of this node. Nodes with higher priority will be
|
||||
* scaled down first before nodes with lower priority when an auto-scaled
|
||||
* layout attempts to fit its contents. Default is
|
||||
* AXISLAYOUT_DEFAULT_PRIORITY
|
||||
* @note For optimal performance, the priorities should all be close to
|
||||
* each other with no gaps
|
||||
*/
|
||||
AxisLayoutOptions* setScalePriority(int priority);
|
||||
|
||||
/**
|
||||
* Override the cross axis alignment for this node in the layout
|
||||
*/
|
||||
AxisLayoutOptions* setCrossAxisAlignment(std::optional<AxisAlignment> alignment);
|
||||
};
|
||||
|
||||
/**
|
||||
* A multi-purpose dynamic layout for arranging nodes along an axis. Can be
|
||||
* used to arrange nodes in a single line, a grid, or a flex layout. The
|
||||
* RowLayout and ColumnLayout classes function as simple thin wrappers over
|
||||
* AxisLayout. The positioning of individual nodes in the layout can be
|
||||
* further controlled using AxisLayoutOptions
|
||||
* @warning Calculating layouts can get increasingly expensive for large
|
||||
* amounts of child nodes being fit into a small space - while this should
|
||||
* never prove a real performance concern as most layouts only have a few
|
||||
* hundred children at the very most, be aware that you probably shouldn't
|
||||
* call CCNode::updateLayout every frame for a menu with thousands of children
|
||||
* @example
|
||||
* auto menu = CCMenu::create();
|
||||
* // The menu's children will be arranged horizontally, unless they overflow
|
||||
* // the content size width in which case a new line will be inserted and
|
||||
* // aligned to the left. The menu automatically will automatically grow in
|
||||
* // height to fit all the rows
|
||||
* menu->setLayout(
|
||||
* RowLayout::create()
|
||||
* ->setGap(10.f)
|
||||
* ->setGrowCrossAxis(true)
|
||||
* ->setAxisAlignment(AxisAlignment::Start)
|
||||
* );
|
||||
* menu->setContentSize({ 200.f, 0.f });
|
||||
* menu->addChild(...);
|
||||
* menu->updateLayout();
|
||||
*/
|
||||
class GEODE_DLL AxisLayout : public Layout {
|
||||
protected:
|
||||
class Impl;
|
||||
|
||||
std::unique_ptr<Impl> m_impl;
|
||||
|
||||
AxisLayout(Axis);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a new AxisLayout. Note that this class is not automatically
|
||||
* managed by default, so you must assign it to a CCNode or manually
|
||||
* manage the memory yourself. See the chainable setters on AxisLayout for
|
||||
* what options you can customize for the layout
|
||||
* @param axis The direction of the layout
|
||||
* @note For convenience, you can use the RowLayout and ColumnLayout
|
||||
* classes, which are just thin wrappers over AxisLayout
|
||||
* @returns Created AxisLayout
|
||||
*/
|
||||
static AxisLayout* create(Axis axis = Axis::Row);
|
||||
|
||||
virtual ~AxisLayout();
|
||||
|
||||
void apply(cocos2d::CCNode* on) override;
|
||||
cocos2d::CCSize getSizeHint(cocos2d::CCNode* on) const override;
|
||||
|
||||
Axis getAxis() const;
|
||||
AxisAlignment getAxisAlignment() const;
|
||||
AxisAlignment getCrossAxisAlignment() const;
|
||||
AxisAlignment getCrossAxisLineAlignment() const;
|
||||
float getGap() const;
|
||||
bool getAxisReverse() const;
|
||||
bool getCrossAxisReverse() const;
|
||||
bool getAutoScale() const;
|
||||
bool getGrowCrossAxis() const;
|
||||
bool getCrossAxisOverflow() const;
|
||||
std::optional<float> getAutoGrowAxis() const;
|
||||
float getDefaultMinScale() const;
|
||||
float getDefaultMaxScale() const;
|
||||
|
||||
AxisLayout* setAxis(Axis axis);
|
||||
/**
|
||||
* Sets where to align the target node's children on the main axis (X-axis
|
||||
* for Row, Y-axis for Column)
|
||||
*/
|
||||
AxisLayout* setAxisAlignment(AxisAlignment align);
|
||||
/**
|
||||
* Sets where to align the target node's children on the cross-axis (Y-axis
|
||||
* for Row, X-axis for Column)
|
||||
*/
|
||||
AxisLayout* setCrossAxisAlignment(AxisAlignment align);
|
||||
/**
|
||||
* Sets where to align the target node's children on the cross-axis for
|
||||
* each row (Y-axis for Row, X-axis for Column)
|
||||
*/
|
||||
AxisLayout* setCrossAxisLineAlignment(AxisAlignment align);
|
||||
/**
|
||||
* The spacing between the children of the node this layout applies to.
|
||||
* Measured as the space between their edges, not centres. Does not apply
|
||||
* on the main / cross axis if their alignment is AxisAlignment::Even
|
||||
*/
|
||||
AxisLayout* setGap(float gap);
|
||||
/**
|
||||
* Whether to reverse the direction of the children in this layout or not
|
||||
*/
|
||||
AxisLayout* setAxisReverse(bool reverse);
|
||||
/**
|
||||
* Whether to reverse the direction of the rows on the cross-axis or not
|
||||
*/
|
||||
AxisLayout* setCrossAxisReverse(bool reverse);
|
||||
/**
|
||||
* If enabled, then the layout may scale the target's children if they are
|
||||
* about to overflow. Assumes that all the childrens' intended scale is 1
|
||||
*/
|
||||
AxisLayout* setAutoScale(bool enable);
|
||||
/**
|
||||
* If true, if the main axis overflows extra nodes will be placed on new
|
||||
* rows/columns on the cross-axis
|
||||
*/
|
||||
AxisLayout* setGrowCrossAxis(bool expand);
|
||||
/**
|
||||
* If true, the cross-axis content size of the target node will be
|
||||
* automatically adjusted to fit the children
|
||||
*/
|
||||
AxisLayout* setCrossAxisOverflow(bool allow);
|
||||
/**
|
||||
* If not `std::nullopt`, then the axis will be automatically extended to
|
||||
* fit all items in a single row whose minimum length is the specified.
|
||||
* Useful for scrollable list layer contents
|
||||
*/
|
||||
AxisLayout* setAutoGrowAxis(std::optional<float> allowAndMinLength);
|
||||
/**
|
||||
* Set the default minimum/maximum scales for nodes in the layout
|
||||
*/
|
||||
AxisLayout* setDefaultScaleLimits(float min, float max);
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple layout for arranging nodes in a row (horizontal line)
|
||||
*/
|
||||
class GEODE_DLL RowLayout : public AxisLayout {
|
||||
protected:
|
||||
RowLayout();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a new RowLayout. See the chainable setters on RowLayout for
|
||||
* what options you can customize for the layout
|
||||
* @returns Created RowLayout
|
||||
*/
|
||||
static RowLayout* create();
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple layout for arranging nodes in a column (vertical line)
|
||||
*/
|
||||
class GEODE_DLL ColumnLayout : public AxisLayout {
|
||||
protected:
|
||||
ColumnLayout();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a new ColumnLayout. See the chainable setters on RowLayout for
|
||||
* what options you can customize for the layout
|
||||
* @returns Created ColumnLayout
|
||||
*/
|
||||
static ColumnLayout* create();
|
||||
};
|
||||
|
||||
/**
|
||||
* The relative position of a node to its parent in an AnchorLayout
|
||||
*/
|
||||
enum class Anchor {
|
||||
Center,
|
||||
TopLeft,
|
||||
Top,
|
||||
TopRight,
|
||||
Right,
|
||||
BottomRight,
|
||||
Bottom,
|
||||
BottomLeft,
|
||||
Left,
|
||||
};
|
||||
|
||||
/**
|
||||
* Options for customizing a node's position in an AnchorLayout
|
||||
*/
|
||||
class GEODE_DLL AnchorLayoutOptions : public LayoutOptions {
|
||||
protected:
|
||||
Anchor m_anchor = Anchor::Center;
|
||||
cocos2d::CCPoint m_offset = cocos2d::CCPointZero;
|
||||
|
||||
public:
|
||||
static AnchorLayoutOptions* create();
|
||||
|
||||
Anchor getAnchor() const;
|
||||
cocos2d::CCPoint getOffset() const;
|
||||
|
||||
AnchorLayoutOptions* setAnchor(Anchor anchor);
|
||||
AnchorLayoutOptions* setOffset(cocos2d::CCPoint const& offset);
|
||||
};
|
||||
|
||||
/**
|
||||
* A layout for positioning nodes at specific positions relative to their
|
||||
* parent's content size. See `Anchor` for available anchoring options. Useful
|
||||
* for example for popups, where a popup using `AnchorLayout` can be
|
||||
* automatically resized without needing to manually shuffle nodes around
|
||||
*/
|
||||
class GEODE_DLL AnchorLayout : public Layout {
|
||||
public:
|
||||
static AnchorLayout* create();
|
||||
|
||||
void apply(cocos2d::CCNode* on) override;
|
||||
cocos2d::CCSize getSizeHint(cocos2d::CCNode* on) const override;
|
||||
|
||||
/**
|
||||
* Get a position according to anchoring rules, with the same algorithm as
|
||||
* `AnchorLayout` uses to position its nodes
|
||||
* @param in The node whose content size to use as a reference
|
||||
* @param anchor The anchor position
|
||||
* @param offset Offset from the anchor
|
||||
* @returns A position in `in` for the anchored and offsetted location
|
||||
*/
|
||||
static cocos2d::CCPoint getAnchoredPosition(cocos2d::CCNode* in, Anchor anchor, cocos2d::CCPoint const& offset);
|
||||
};
|
||||
|
||||
/**
|
||||
* A layout for automatically copying the content size of a node to other nodes.
|
||||
* Basically main use case is for FLAlertLayers (setting the size of the
|
||||
* background and `m_buttonMenu` based on `m_mainLayer`)
|
||||
*/
|
||||
class GEODE_DLL CopySizeLayout : public AnchorLayout {
|
||||
protected:
|
||||
cocos2d::CCArray* m_targets;
|
||||
|
||||
public:
|
||||
static CopySizeLayout* create();
|
||||
virtual ~CopySizeLayout();
|
||||
|
||||
/**
|
||||
* Add a target to be automatically resized. Any targets' layouts will
|
||||
* also be updated when this layout is updated
|
||||
*/
|
||||
CopySizeLayout* add(cocos2d::CCNode* target);
|
||||
/**
|
||||
* Remove a target from being automatically resized
|
||||
*/
|
||||
CopySizeLayout* remove(cocos2d::CCNode* target);
|
||||
|
||||
void apply(cocos2d::CCNode* in) override;
|
||||
cocos2d::CCSize getSizeHint(cocos2d::CCNode* in) const override;
|
||||
};
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
#include <Geode/binding/FLAlertLayer.hpp>
|
||||
#include <Geode/utils/MiniFunction.hpp>
|
||||
#include <Geode/utils/cocos.hpp>
|
||||
#include <Geode/ui/Layout.hpp>
|
||||
|
||||
namespace geode {
|
||||
template <class... InitArgs>
|
||||
|
@ -104,7 +105,7 @@ namespace geode {
|
|||
m_mainLayer->setPosition(winSize / 2);
|
||||
m_mainLayer->setContentSize(m_size);
|
||||
m_mainLayer->setLayout(
|
||||
cocos2d::CopySizeLayout::create()
|
||||
geode::CopySizeLayout::create()
|
||||
->add(m_buttonMenu)
|
||||
->add(m_bgSprite)
|
||||
);
|
||||
|
@ -119,7 +120,7 @@ namespace geode {
|
|||
closeSpr, this, (cocos2d::SEL_MenuHandler)(&Popup::onClose)
|
||||
);
|
||||
if (dynamic) {
|
||||
m_buttonMenu->addChildAtPosition(m_closeBtn, cocos2d::Anchor::TopLeft, { 3.f, -3.f });
|
||||
m_buttonMenu->addChildAtPosition(m_closeBtn, geode::Anchor::TopLeft, { 3.f, -3.f });
|
||||
}
|
||||
else {
|
||||
m_closeBtn->setPosition(-m_size.width / 2 + 3.f, m_size.height / 2 - 3.f);
|
||||
|
@ -137,14 +138,6 @@ namespace geode {
|
|||
}
|
||||
|
||||
protected:
|
||||
[[deprecated("Use Popup::initAnchored instead, as it has more reasonable menu and layer content sizes")]]
|
||||
bool init(
|
||||
float width, float height, InitArgs... args, char const* bg = "GJ_square01.png",
|
||||
cocos2d::CCRect bgRect = { 0, 0, 80, 80 }
|
||||
) {
|
||||
return this->initBase(width, height, std::forward<InitArgs>(args)..., bg, bgRect, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init with AnchorLayout and the content size of `m_buttonMenu` and
|
||||
* `m_bgSprite` being tied to the size of `m_mainLayer` (rather than
|
||||
|
@ -185,7 +178,7 @@ namespace geode {
|
|||
m_title = cocos2d::CCLabelBMFont::create(title.c_str(), font);
|
||||
m_title->setZOrder(2);
|
||||
if (m_dynamic) {
|
||||
m_mainLayer->addChildAtPosition(m_title, cocos2d::Anchor::Top, ccp(0, -offset));
|
||||
m_mainLayer->addChildAtPosition(m_title, geode::Anchor::Top, ccp(0, -offset));
|
||||
}
|
||||
else {
|
||||
auto winSize = cocos2d::CCDirector::get()->getWinSize();
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "CCNode.h"
|
||||
#include <cocos2d.h>
|
||||
|
||||
NS_CC_BEGIN
|
||||
namespace geode {
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4275)
|
||||
|
@ -22,7 +22,7 @@ NS_CC_BEGIN
|
|||
* @note If you want to specify a minimum width for a SpacerNode, add
|
||||
* AxisLayoutOptions for it and use setLength
|
||||
*/
|
||||
class GEODE_DLL SpacerNode : public CCNode {
|
||||
class GEODE_DLL SpacerNode : public cocos2d::CCNode {
|
||||
protected:
|
||||
size_t m_grow;
|
||||
|
||||
|
@ -61,9 +61,9 @@ public:
|
|||
*/
|
||||
class GEODE_DLL SpacerNodeChild : public SpacerNode {
|
||||
protected:
|
||||
CCNode* m_child = nullptr;
|
||||
cocos2d::CCNode* m_child = nullptr;
|
||||
|
||||
bool init(CCNode* child, size_t grow);
|
||||
bool init(cocos2d::CCNode* child, size_t grow);
|
||||
|
||||
public:
|
||||
/**
|
||||
|
@ -73,11 +73,11 @@ public:
|
|||
* factors (akin to CSS flew grow)
|
||||
* @param grow The grow factor for this node. Default is 1
|
||||
*/
|
||||
static SpacerNodeChild* create(CCNode* child, size_t grow = 1);
|
||||
static SpacerNodeChild* create(cocos2d::CCNode* child, size_t grow = 1);
|
||||
|
||||
void setContentSize(CCSize const& size) override;
|
||||
void setContentSize(cocos2d::CCSize const& size) override;
|
||||
};
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
NS_CC_END
|
||||
}
|
|
@ -78,226 +78,6 @@ namespace geode {
|
|||
struct JsonMaybeObject;
|
||||
struct JsonMaybeValue;
|
||||
|
||||
struct GEODE_DLL
|
||||
[[deprecated("Use JsonExpectedValue via the checkJson function instead")]]
|
||||
JsonMaybeSomething {
|
||||
protected:
|
||||
JsonChecker& m_checker;
|
||||
matjson::Value& m_json;
|
||||
std::string m_hierarchy;
|
||||
bool m_hasValue;
|
||||
|
||||
friend struct JsonMaybeObject;
|
||||
friend struct JsonMaybeValue;
|
||||
|
||||
void setError(std::string const& error);
|
||||
|
||||
public:
|
||||
matjson::Value& json();
|
||||
|
||||
JsonMaybeSomething(
|
||||
JsonChecker& checker, matjson::Value& json, std::string const& hierarchy, bool hasValue
|
||||
);
|
||||
|
||||
bool isError() const;
|
||||
std::string getError() const;
|
||||
|
||||
operator bool() const;
|
||||
};
|
||||
|
||||
struct GEODE_DLL
|
||||
[[deprecated("Use JsonExpectedValue via the checkJson function instead")]]
|
||||
JsonMaybeValue : public JsonMaybeSomething {
|
||||
bool m_inferType = true;
|
||||
|
||||
JsonMaybeValue(
|
||||
JsonChecker& checker, matjson::Value& json, std::string const& hierarchy, bool hasValue
|
||||
);
|
||||
|
||||
JsonMaybeSomething& self();
|
||||
|
||||
template <matjson::Type T>
|
||||
JsonMaybeValue& as() {
|
||||
if (this->isError()) return *this;
|
||||
if (!jsonConvertibleTo(self().m_json.type(), T)) {
|
||||
this->setError(
|
||||
self().m_hierarchy + ": Invalid type \"" + jsonValueTypeToString(self().m_json.type()) +
|
||||
"\", expected \"" + jsonValueTypeToString(T) + "\""
|
||||
);
|
||||
}
|
||||
m_inferType = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JsonMaybeValue& array();
|
||||
|
||||
template <matjson::Type... T>
|
||||
JsonMaybeValue& asOneOf() {
|
||||
if (this->isError()) return *this;
|
||||
bool isOneOf = (... || jsonConvertibleTo(self().m_json.type(), T));
|
||||
if (!isOneOf) {
|
||||
this->setError(
|
||||
self().m_hierarchy + ": Invalid type \"" + jsonValueTypeToString(self().m_json.type()) +
|
||||
"\", expected one of \"" + (jsonValueTypeToString(T), ...) + "\""
|
||||
);
|
||||
}
|
||||
m_inferType = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool is() {
|
||||
if (this->isError()) return false;
|
||||
return self().m_json.is<T>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
JsonMaybeValue& validate(JsonValueValidator<T> validator) {
|
||||
if (this->isError()) return *this;
|
||||
if (self().m_json.is<T>()) {
|
||||
if (!validator(self().m_json.as<T>())) {
|
||||
this->setError(self().m_hierarchy + ": Invalid value format");
|
||||
}
|
||||
}
|
||||
else {
|
||||
this->setError(
|
||||
self().m_hierarchy + ": Invalid type \"" +
|
||||
std::string(jsonValueTypeToString(self().m_json.type())) + "\""
|
||||
);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
JsonMaybeValue& inferType() {
|
||||
if (this->isError() || !m_inferType) return *this;
|
||||
return this->as<getJsonType<T>()>();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
JsonMaybeValue& intoRaw(T& target) {
|
||||
if (this->isError()) return *this;
|
||||
target = self().m_json;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
JsonMaybeValue& into(T& target) {
|
||||
return this->intoAs<T, T>(target);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
JsonMaybeValue& into(std::optional<T>& target) {
|
||||
return this->intoAs<T, std::optional<T>>(target);
|
||||
}
|
||||
|
||||
template <class A, class T>
|
||||
JsonMaybeValue& intoAs(T& target) {
|
||||
this->inferType<A>();
|
||||
if (this->isError()) return *this;
|
||||
|
||||
if (self().m_json.is<A>()) {
|
||||
try {
|
||||
target = self().m_json.as<A>();
|
||||
}
|
||||
catch(matjson::JsonException const& e) {
|
||||
this->setError(
|
||||
self().m_hierarchy + ": Error parsing JSON: " + std::string(e.what())
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this->setError(
|
||||
self().m_hierarchy + ": Invalid type \"" +
|
||||
std::string(jsonValueTypeToString(self().m_json.type())) + "\""
|
||||
);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T get() {
|
||||
this->inferType<T>();
|
||||
if (this->isError()) return T();
|
||||
if (self().m_json.is<T>()) {
|
||||
return self().m_json.as<T>();
|
||||
}
|
||||
return T();
|
||||
}
|
||||
|
||||
JsonMaybeObject obj();
|
||||
|
||||
template <class T>
|
||||
struct Iterator {
|
||||
std::vector<T> m_values;
|
||||
|
||||
using iterator = typename std::vector<T>::iterator;
|
||||
using const_iterator = typename std::vector<T>::const_iterator;
|
||||
|
||||
iterator begin() {
|
||||
return m_values.begin();
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
return m_values.end();
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
return m_values.begin();
|
||||
}
|
||||
|
||||
const_iterator end() const {
|
||||
return m_values.end();
|
||||
}
|
||||
};
|
||||
|
||||
JsonMaybeValue at(size_t i);
|
||||
|
||||
Iterator<JsonMaybeValue> iterate();
|
||||
|
||||
Iterator<std::pair<std::string, JsonMaybeValue>> items();
|
||||
};
|
||||
|
||||
struct
|
||||
[[deprecated("Use JsonExpectedValue via the checkJson function instead")]]
|
||||
GEODE_DLL JsonMaybeObject : JsonMaybeSomething {
|
||||
std::set<std::string> m_knownKeys;
|
||||
|
||||
JsonMaybeObject(
|
||||
JsonChecker& checker, matjson::Value& json, std::string const& hierarchy, bool hasValue
|
||||
);
|
||||
|
||||
JsonMaybeSomething& self();
|
||||
|
||||
void addKnownKey(std::string const& key);
|
||||
|
||||
matjson::Value& json();
|
||||
|
||||
JsonMaybeValue emptyValue();
|
||||
|
||||
JsonMaybeValue has(std::string const& key);
|
||||
|
||||
JsonMaybeValue needs(std::string const& key);
|
||||
|
||||
void checkUnknownKeys();
|
||||
};
|
||||
|
||||
struct
|
||||
[[deprecated("Use JsonExpectedValue via the checkJson function instead")]]
|
||||
GEODE_DLL JsonChecker {
|
||||
std::variant<std::monostate, std::string> m_result;
|
||||
matjson::Value& m_json;
|
||||
|
||||
JsonChecker(matjson::Value& json);
|
||||
|
||||
bool isError() const;
|
||||
|
||||
std::string getError() const;
|
||||
|
||||
JsonMaybeValue root(std::string const& hierarchy);
|
||||
};
|
||||
|
||||
class GEODE_DLL JsonExpectedValue final {
|
||||
protected:
|
||||
class Impl;
|
||||
|
|
|
@ -186,8 +186,6 @@ namespace geode {
|
|||
std::tie(other.m_major, other.m_minor, other.m_patch, other.m_tag);
|
||||
}
|
||||
|
||||
[[deprecated("Use toNonVString or toVString instead")]]
|
||||
std::string toString(bool includeTag = true) const;
|
||||
std::string toVString(bool includeTag = true) const;
|
||||
std::string toNonVString(bool includeTag = true) const;
|
||||
|
||||
|
|
|
@ -615,18 +615,6 @@ namespace geode::cocos {
|
|||
return static_cast<T*>(x->getChildren()->objectAtIndex(i));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get nth child that is a given type. Checks bounds.
|
||||
* @returns Child at index cast to the given type,
|
||||
* or nullptr if index exceeds bounds
|
||||
*/
|
||||
|
||||
template <class Type = cocos2d::CCNode>
|
||||
[[deprecated("Use CCNode::getChildByType instead")]]
|
||||
static Type* getChildOfType(cocos2d::CCNode* node, int index) {
|
||||
return node->getChildByType<Type>(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a node, or create a default one if it's
|
||||
* nullptr. Syntactic sugar function
|
||||
|
@ -856,30 +844,6 @@ namespace geode::cocos {
|
|||
return {color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f};
|
||||
}
|
||||
|
||||
[[deprecated("This function may have unintended behavior, use cc3bFromHexString or manually expand the color instead")]]
|
||||
constexpr cocos2d::ccColor3B cc3x(int hexValue) {
|
||||
if (hexValue <= 0xf)
|
||||
return cocos2d::ccColor3B{
|
||||
static_cast<GLubyte>(hexValue * 17),
|
||||
static_cast<GLubyte>(hexValue * 17),
|
||||
static_cast<GLubyte>(hexValue * 17)};
|
||||
if (hexValue <= 0xff)
|
||||
return cocos2d::ccColor3B{
|
||||
static_cast<GLubyte>(hexValue),
|
||||
static_cast<GLubyte>(hexValue),
|
||||
static_cast<GLubyte>(hexValue)};
|
||||
if (hexValue <= 0xfff)
|
||||
return cocos2d::ccColor3B{
|
||||
static_cast<GLubyte>((hexValue >> 8 & 0xf) * 17),
|
||||
static_cast<GLubyte>((hexValue >> 4 & 0xf) * 17),
|
||||
static_cast<GLubyte>((hexValue >> 0 & 0xf) * 17)};
|
||||
else
|
||||
return cocos2d::ccColor3B{
|
||||
static_cast<GLubyte>(hexValue >> 16 & 0xff),
|
||||
static_cast<GLubyte>(hexValue >> 8 & 0xff),
|
||||
static_cast<GLubyte>(hexValue >> 0 & 0xff)};
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a ccColor3B from a hexadecimal string. The string may contain
|
||||
* a leading '#'
|
||||
|
|
|
@ -17,15 +17,6 @@
|
|||
namespace geode {
|
||||
using ByteVector = std::vector<uint8_t>;
|
||||
|
||||
// todo in v4: remove this
|
||||
template <typename T>
|
||||
[[deprecated("Use geode::toBytes instead")]]
|
||||
ByteVector toByteArray(T const& a) {
|
||||
ByteVector out;
|
||||
out.resize(sizeof(T));
|
||||
std::memcpy(out.data(), &a, sizeof(T));
|
||||
return out;
|
||||
}
|
||||
template <typename T>
|
||||
ByteVector toBytes(T const& a) {
|
||||
ByteVector out;
|
||||
|
|
|
@ -1026,14 +1026,6 @@ std::optional<AxisAlignment> AxisLayoutOptions::getCrossAxisAlignment() const {
|
|||
return m_impl->m_crossAxisAlignment;
|
||||
}
|
||||
|
||||
AxisLayoutOptions* AxisLayoutOptions::setMaxScale(float scale) {
|
||||
m_impl->m_scaleLimits.second = scale;
|
||||
return this;
|
||||
}
|
||||
AxisLayoutOptions* AxisLayoutOptions::setMinScale(float scale) {
|
||||
m_impl->m_scaleLimits.first = scale;
|
||||
return this;
|
||||
}
|
||||
AxisLayoutOptions* AxisLayoutOptions::setScaleLimits(std::optional<float> min, std::optional<float> max) {
|
||||
m_impl->m_scaleLimits = { min, max };
|
||||
return this;
|
||||
|
|
|
@ -62,10 +62,6 @@ public:
|
|||
return meta;
|
||||
}
|
||||
|
||||
FieldContainer* getFieldContainer() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FieldContainer* getFieldContainer(char const* forClass) {
|
||||
if (!m_classFieldContainers.count(forClass)) {
|
||||
m_classFieldContainers[forClass] = new FieldContainer();
|
||||
|
@ -104,11 +100,6 @@ size_t modifier::getFieldIndexForClass(char const* name) {
|
|||
return s_nextIndex[name]++;
|
||||
}
|
||||
|
||||
// not const because might modify contents
|
||||
FieldContainer* CCNode::getFieldContainer() {
|
||||
return GeodeNodeMetadata::set(this)->getFieldContainer();
|
||||
}
|
||||
|
||||
FieldContainer* CCNode::getFieldContainer(char const* forClass) {
|
||||
return GeodeNodeMetadata::set(this)->getFieldContainer(forClass);
|
||||
}
|
||||
|
@ -455,13 +446,4 @@ void CCNode::updateAnchoredPosition(Anchor anchor, CCPoint const& offset, CCPoin
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef GEODE_EXPORTING
|
||||
|
||||
void CCNode::setAttribute(std::string const& attr, matjson::Value const& value) {}
|
||||
std::optional<matjson::Value> CCNode::getAttributeInternal(std::string const& attr) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#pragma warning(pop)
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include <Geode/loader/Loader.hpp>
|
||||
#include <Geode/loader/Log.hpp>
|
||||
#include <Geode/loader/Mod.hpp>
|
||||
#include <Geode/loader/SettingEvent.hpp>
|
||||
#include <Geode/utils/JsonValidation.hpp>
|
||||
#include <loader/LogImpl.hpp>
|
||||
|
||||
|
@ -30,8 +29,7 @@ $on_mod(Loaded) {
|
|||
std::vector<matjson::Value> res;
|
||||
|
||||
auto args = *event->messageData;
|
||||
JsonChecker checker(args);
|
||||
auto root = checker.root("[ipc/list-mods]").obj();
|
||||
auto root = checkJson(args, "[ipc/list-mods]");
|
||||
|
||||
auto includeRunTimeInfo = root.has("include-runtime-info").get<bool>();
|
||||
auto dontIncludeLoader = root.has("dont-include-loader").get<bool>();
|
||||
|
|
|
@ -20,10 +20,6 @@ std::string Mod::getName() const {
|
|||
return m_impl->getName();
|
||||
}
|
||||
|
||||
std::string Mod::getDeveloper() const {
|
||||
return m_impl->getDevelopers().empty() ? "" : m_impl->getDevelopers().front();
|
||||
}
|
||||
|
||||
std::vector<std::string> Mod::getDevelopers() const {
|
||||
return m_impl->getDevelopers();
|
||||
}
|
||||
|
@ -101,9 +97,6 @@ std::vector<Mod*> Mod::getDependants() const {
|
|||
}
|
||||
#endif
|
||||
|
||||
std::optional<VersionInfo> Mod::hasAvailableUpdate() const {
|
||||
return std::nullopt;
|
||||
}
|
||||
Mod::CheckUpdatesTask Mod::checkUpdates() const {
|
||||
return server::checkUpdates(this).map(
|
||||
[](auto* result) -> Mod::CheckUpdatesTask::Value {
|
||||
|
@ -159,24 +152,10 @@ bool Mod::hasSetting(std::string_view const key) const {
|
|||
return m_impl->hasSetting(key);
|
||||
}
|
||||
|
||||
std::optional<Setting> Mod::getSettingDefinition(std::string_view const key) const {
|
||||
return m_impl->m_settings->getLegacyDefinition(std::string(key));
|
||||
}
|
||||
|
||||
SettingValue* Mod::getSetting(std::string_view const key) const {
|
||||
return m_impl->m_settings->getLegacy(std::string(key)).get();
|
||||
}
|
||||
|
||||
std::shared_ptr<SettingV3> Mod::getSettingV3(std::string_view const key) const {
|
||||
return m_impl->m_settings->get(std::string(key));
|
||||
}
|
||||
|
||||
void Mod::registerCustomSetting(std::string_view const key, std::unique_ptr<SettingValue> value) {
|
||||
auto reg = m_impl->m_settings->registerLegacyCustomSetting(key, std::move(value));
|
||||
if (!reg) {
|
||||
log::error("Unable to register custom setting: {}", reg.unwrapErr());
|
||||
}
|
||||
}
|
||||
Result<> Mod::registerCustomSettingType(std::string_view type, SettingGenerator generator) {
|
||||
return m_impl->m_settings->registerCustomSettingType(type, generator);
|
||||
}
|
||||
|
|
|
@ -528,18 +528,6 @@ std::vector<ModMetadata::Incompatibility> ModMetadata::getIncompatibilities() co
|
|||
std::vector<std::string> ModMetadata::getSpritesheets() const {
|
||||
return m_impl->m_spritesheets;
|
||||
}
|
||||
std::vector<std::pair<std::string, Setting>> ModMetadata::getSettings() const {
|
||||
std::vector<std::pair<std::string, Setting>> res;
|
||||
for (auto [key, sett] : m_impl->m_settings) {
|
||||
auto checker = JsonChecker(sett);
|
||||
auto value = checker.root("");
|
||||
auto legacy = Setting::parse(key, m_impl->m_id, value);
|
||||
if (!checker.isError() && legacy.isOk()) {
|
||||
res.push_back(std::make_pair(key, *legacy));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
std::vector<std::pair<std::string, matjson::Value>> ModMetadata::getSettingsV3() const {
|
||||
return m_impl->m_settings;
|
||||
}
|
||||
|
|
|
@ -13,8 +13,6 @@ private:
|
|||
std::unordered_map<std::string, SettingGenerator> m_types;
|
||||
|
||||
SharedSettingTypesPool() : m_types({
|
||||
// todo in v4: remove this
|
||||
{ "custom", &LegacyCustomSettingV3::parse },
|
||||
{ "title", &TitleSettingV3::parse },
|
||||
{ "bool", &BoolSettingV3::parse },
|
||||
{ "int", &IntSettingV3::parse },
|
||||
|
@ -202,19 +200,6 @@ Result<> ModSettingsManager::registerLegacyCustomSetting(std::string_view key, s
|
|||
if (!m_impl->settings.count(id)) {
|
||||
return Err("No such setting '{}' in mod {}", id, m_impl->modID);
|
||||
}
|
||||
auto& sett = m_impl->settings.at(id);
|
||||
if (auto custom = typeinfo_pointer_cast<LegacyCustomSettingV3>(sett.v3)) {
|
||||
if (!custom->getValue()) {
|
||||
custom->setValue(std::move(ptr));
|
||||
m_impl->loadSettingValueFromSave(id);
|
||||
}
|
||||
else {
|
||||
return Err("Setting '{}' in mod {} has already been registed", id, m_impl->modID);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return Err("Setting '{}' in mod {} is not a legacy custom setting", id, m_impl->modID);
|
||||
}
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
@ -244,33 +229,6 @@ std::shared_ptr<SettingV3> ModSettingsManager::get(std::string_view key) {
|
|||
auto id = std::string(key);
|
||||
return m_impl->settings.count(id) ? m_impl->settings.at(id).v3 : nullptr;
|
||||
}
|
||||
std::shared_ptr<SettingValue> ModSettingsManager::getLegacy(std::string_view key) {
|
||||
auto id = std::string(key);
|
||||
if (!m_impl->settings.count(id)) {
|
||||
return nullptr;
|
||||
}
|
||||
auto& info = m_impl->settings.at(id);
|
||||
// If this setting has alreay been given a legacy interface, give that
|
||||
if (info.legacy) {
|
||||
return info.legacy;
|
||||
}
|
||||
// Uninitialized settings are null
|
||||
if (!info.v3) {
|
||||
return nullptr;
|
||||
}
|
||||
// Generate new legacy interface
|
||||
if (auto legacy = info.v3->convertToLegacyValue()) {
|
||||
info.legacy.swap(*legacy);
|
||||
return info.legacy;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
std::optional<Setting> ModSettingsManager::getLegacyDefinition(std::string_view key) {
|
||||
if (auto s = this->get(key)) {
|
||||
return s->convertToLegacy();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool ModSettingsManager::restartRequired() const {
|
||||
return m_impl->restartRequired;
|
||||
|
|
|
@ -1,498 +0,0 @@
|
|||
#include <ui/mods/settings/GeodeSettingNode.hpp>
|
||||
#include <Geode/loader/Mod.hpp>
|
||||
#include <Geode/loader/Setting.hpp>
|
||||
#include <Geode/loader/SettingV3.hpp>
|
||||
#include <Geode/loader/SettingEvent.hpp>
|
||||
#include <Geode/loader/SettingNode.hpp>
|
||||
#include <Geode/utils/general.hpp>
|
||||
#include <Geode/utils/JsonValidation.hpp>
|
||||
#include <regex>
|
||||
|
||||
using namespace geode::prelude;
|
||||
|
||||
template<class T>
|
||||
static void parseCommon(T& sett, JsonMaybeObject& obj) {
|
||||
obj.has("name").into(sett.name);
|
||||
obj.has("description").into(sett.description);
|
||||
if (auto defValue = obj.needs("default")) {
|
||||
// Platform-specific default value
|
||||
if (defValue.is<matjson::Object>()) {
|
||||
auto def = defValue.obj();
|
||||
if (auto plat = def.has(PlatformID::toShortString(GEODE_PLATFORM_TARGET, true))) {
|
||||
plat.into(sett.defaultValue);
|
||||
}
|
||||
else {
|
||||
defValue.into(sett.defaultValue);
|
||||
}
|
||||
}
|
||||
else {
|
||||
defValue.into(sett.defaultValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Result<BoolSetting> BoolSetting::parse(JsonMaybeObject& obj) {
|
||||
BoolSetting sett;
|
||||
parseCommon(sett, obj);
|
||||
return Ok(sett);
|
||||
}
|
||||
|
||||
Result<IntSetting> IntSetting::parse(JsonMaybeObject& obj) {
|
||||
IntSetting sett;
|
||||
parseCommon(sett, obj);
|
||||
obj.has("min").into(sett.min);
|
||||
obj.has("max").into(sett.max);
|
||||
if (auto controls = obj.has("control").obj()) {
|
||||
controls.has("arrows").into(sett.controls.arrows);
|
||||
controls.has("big-arrows").into(sett.controls.bigArrows);
|
||||
controls.has("arrow-step").into(sett.controls.arrowStep);
|
||||
controls.has("big-arrow-step").into(sett.controls.bigArrowStep);
|
||||
controls.has("slider").into(sett.controls.slider);
|
||||
controls.has("slider-step").into(sett.controls.sliderStep);
|
||||
controls.has("input").into(sett.controls.input);
|
||||
}
|
||||
return Ok(sett);
|
||||
}
|
||||
|
||||
Result<FloatSetting> FloatSetting::parse(JsonMaybeObject& obj) {
|
||||
FloatSetting sett;
|
||||
parseCommon(sett, obj);
|
||||
obj.has("min").into(sett.min);
|
||||
obj.has("max").into(sett.max);
|
||||
if (auto controls = obj.has("control").obj()) {
|
||||
controls.has("arrows").into(sett.controls.arrows);
|
||||
controls.has("big-arrows").into(sett.controls.bigArrows);
|
||||
controls.has("arrow-step").into(sett.controls.arrowStep);
|
||||
controls.has("big-arrow-step").into(sett.controls.bigArrowStep);
|
||||
controls.has("slider").into(sett.controls.slider);
|
||||
controls.has("slider-step").into(sett.controls.sliderStep);
|
||||
controls.has("input").into(sett.controls.input);
|
||||
}
|
||||
return Ok(sett);
|
||||
}
|
||||
|
||||
Result<StringSetting> StringSetting::parse(JsonMaybeObject& obj) {
|
||||
StringSetting sett;
|
||||
parseCommon(sett, obj);
|
||||
obj.has("match").into(sett.controls->match);
|
||||
obj.has("filter").into(sett.controls->filter);
|
||||
obj.has("one-of").into(sett.controls->options);
|
||||
return Ok(sett);
|
||||
}
|
||||
|
||||
Result<FileSetting> FileSetting::parse(JsonMaybeObject& obj) {
|
||||
FileSetting sett;
|
||||
parseCommon(sett, obj);
|
||||
if (auto controls = obj.has("control").obj()) {
|
||||
for (auto& item : controls.has("filters").iterate()) {
|
||||
if (auto iobj = item.obj()) {
|
||||
Filter filter;
|
||||
iobj.has("description").into(filter.description);
|
||||
|
||||
std::vector<matjson::Value> files;
|
||||
iobj.has("files").into(files);
|
||||
|
||||
for (auto& i : files) {
|
||||
filter.files.insert(i.as<std::string>());
|
||||
}
|
||||
|
||||
sett.controls.filters.push_back(filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Ok(sett);
|
||||
}
|
||||
|
||||
Result<ColorSetting> ColorSetting::parse(JsonMaybeObject& obj) {
|
||||
ColorSetting sett;
|
||||
parseCommon(sett, obj);
|
||||
return Ok(sett);
|
||||
}
|
||||
|
||||
Result<ColorAlphaSetting> ColorAlphaSetting::parse(JsonMaybeObject& obj) {
|
||||
ColorAlphaSetting sett;
|
||||
parseCommon(sett, obj);
|
||||
return Ok(sett);
|
||||
}
|
||||
|
||||
Result<Setting> Setting::parse(
|
||||
std::string const& key,
|
||||
std::string const& mod,
|
||||
JsonMaybeValue& value
|
||||
) {
|
||||
auto sett = Setting();
|
||||
sett.m_key = key;
|
||||
sett.m_modID = mod;
|
||||
if (auto obj = value.obj()) {
|
||||
std::string type;
|
||||
obj.needs("type").into(type);
|
||||
if (type.size()) {
|
||||
switch (hash(type.c_str())) {
|
||||
case hash("bool"): {
|
||||
GEODE_UNWRAP_INTO(sett.m_kind, BoolSetting::parse(obj));
|
||||
} break;
|
||||
|
||||
case hash("int"): {
|
||||
GEODE_UNWRAP_INTO(sett.m_kind, IntSetting::parse(obj));
|
||||
} break;
|
||||
|
||||
case hash("float"): {
|
||||
GEODE_UNWRAP_INTO(sett.m_kind, FloatSetting::parse(obj));
|
||||
} break;
|
||||
|
||||
case hash("string"): {
|
||||
GEODE_UNWRAP_INTO(sett.m_kind, StringSetting::parse(obj));
|
||||
} break;
|
||||
|
||||
case hash("rgb"): case hash("color"): {
|
||||
GEODE_UNWRAP_INTO(sett.m_kind, ColorSetting::parse(obj));
|
||||
} break;
|
||||
|
||||
case hash("rgba"): {
|
||||
GEODE_UNWRAP_INTO(sett.m_kind, ColorAlphaSetting::parse(obj));
|
||||
} break;
|
||||
|
||||
case hash("path"): case hash("file"): {
|
||||
GEODE_UNWRAP_INTO(sett.m_kind, FileSetting::parse(obj));
|
||||
} break;
|
||||
|
||||
case hash("custom"): {
|
||||
sett.m_kind = CustomSetting {
|
||||
.json = std::make_shared<ModJson>(obj.json())
|
||||
};
|
||||
// skip checking unknown keys
|
||||
return Ok(sett);
|
||||
} break;
|
||||
|
||||
default: return Err("Unknown setting type \"" + type + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
// this is handled before the setting is parsed
|
||||
obj.addKnownKey("platforms");
|
||||
|
||||
obj.checkUnknownKeys();
|
||||
}
|
||||
// if the type wasn't an object or a string, the JsonChecker that gave the
|
||||
// JsonMaybeValue will fail eventually so we can continue on
|
||||
return Ok(sett);
|
||||
}
|
||||
|
||||
Setting::Setting(
|
||||
std::string const& key,
|
||||
std::string const& mod,
|
||||
SettingKind const& kind
|
||||
) : m_key(key), m_modID(mod), m_kind(kind) {}
|
||||
|
||||
std::unique_ptr<SettingValue> Setting::createDefaultValue() const {
|
||||
return std::visit(makeVisitor {
|
||||
[&](BoolSetting const& sett) -> std::unique_ptr<SettingValue> {
|
||||
return std::make_unique<BoolSettingValue>(m_key, m_modID, sett);
|
||||
},
|
||||
[&](IntSetting const& sett) -> std::unique_ptr<SettingValue> {
|
||||
return std::make_unique<IntSettingValue>(m_key, m_modID, sett);
|
||||
},
|
||||
[&](FloatSetting const& sett) -> std::unique_ptr<SettingValue> {
|
||||
return std::make_unique<FloatSettingValue>(m_key, m_modID, sett);
|
||||
},
|
||||
[&](StringSetting const& sett) -> std::unique_ptr<SettingValue> {
|
||||
return std::make_unique<StringSettingValue>(m_key, m_modID, sett);
|
||||
},
|
||||
[&](FileSetting const& sett) -> std::unique_ptr<SettingValue> {
|
||||
return std::make_unique<FileSettingValue>(m_key, m_modID, sett);
|
||||
},
|
||||
[&](ColorSetting const& sett) -> std::unique_ptr<SettingValue> {
|
||||
return std::make_unique<ColorSettingValue>(m_key, m_modID, sett);
|
||||
},
|
||||
[&](ColorAlphaSetting const& sett) -> std::unique_ptr<SettingValue> {
|
||||
return std::make_unique<ColorAlphaSettingValue>(m_key, m_modID, sett);
|
||||
},
|
||||
[&](auto const& sett) -> std::unique_ptr<SettingValue> {
|
||||
return nullptr;
|
||||
},
|
||||
}, m_kind);
|
||||
}
|
||||
|
||||
bool Setting::isCustom() const {
|
||||
return std::holds_alternative<CustomSetting>(m_kind);
|
||||
}
|
||||
|
||||
std::string Setting::getDisplayName() const {
|
||||
return std::visit(makeVisitor {
|
||||
[&](CustomSetting const& sett) {
|
||||
return std::string();
|
||||
},
|
||||
[&](auto const& sett) {
|
||||
return sett.name.value_or(m_key);
|
||||
},
|
||||
}, m_kind);
|
||||
}
|
||||
|
||||
std::optional<std::string> Setting::getDescription() const {
|
||||
return std::visit(makeVisitor {
|
||||
[&](CustomSetting const& sett) -> std::optional<std::string> {
|
||||
return std::nullopt;
|
||||
},
|
||||
[&](auto const& sett) {
|
||||
return sett.description;
|
||||
},
|
||||
}, m_kind);
|
||||
}
|
||||
|
||||
std::string Setting::getModID() const {
|
||||
return m_modID;
|
||||
}
|
||||
|
||||
// StringSetting
|
||||
|
||||
StringSetting::StringSetting() : name(), description(), defaultValue(), controls(new Data()) {}
|
||||
StringSetting::StringSetting(StringSetting const& other) : name(other.name), description(other.description),
|
||||
defaultValue(other.defaultValue), controls(new Data(*other.controls)) {}
|
||||
StringSetting::StringSetting(StringSetting&& other) noexcept : name(std::move(other.name)), description(std::move(other.description)),
|
||||
defaultValue(std::move(other.defaultValue)), controls(std::move(other.controls)) {}
|
||||
StringSetting& StringSetting::operator=(StringSetting const& other) {
|
||||
name = other.name;
|
||||
description = other.description;
|
||||
defaultValue = other.defaultValue;
|
||||
*controls = *other.controls;
|
||||
return *this;
|
||||
}
|
||||
StringSetting& StringSetting::operator=(StringSetting&& other) noexcept {
|
||||
name = std::move(other.name);
|
||||
description = std::move(other.description);
|
||||
defaultValue = std::move(other.defaultValue);
|
||||
controls = std::move(other.controls);
|
||||
return *this;
|
||||
}
|
||||
StringSetting::~StringSetting() = default;
|
||||
|
||||
// SettingValue
|
||||
|
||||
SettingValue::SettingValue(std::string const& key, std::string const& mod)
|
||||
: m_key(key), m_modID(mod) {}
|
||||
|
||||
std::string SettingValue::getKey() const {
|
||||
return m_key;
|
||||
}
|
||||
|
||||
std::string SettingValue::getModID() const {
|
||||
return m_modID;
|
||||
}
|
||||
|
||||
void SettingValue::valueChanged() {
|
||||
if (auto mod = Loader::get()->getLoadedMod(m_modID)) {
|
||||
if (auto sett = mod->getSettingV3(m_key)) {
|
||||
sett->markChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GeodeSettingValue & SettingValueSetter specializations
|
||||
|
||||
#define IMPL_NODE_AND_SETTERS(type_) \
|
||||
template<> \
|
||||
SettingNode* GeodeSettingValue< \
|
||||
type_##Setting \
|
||||
>::createNode(float width) { \
|
||||
return type_##SettingNode::create(this, width); \
|
||||
} \
|
||||
template<> \
|
||||
typename GeodeSettingValue<type_##Setting>::ValueType \
|
||||
GeodeSettingValue<type_##Setting>::getValue() const { \
|
||||
using S = typename SettingTypeForValueType<ValueType>::SettingType; \
|
||||
if (auto mod = Loader::get()->getInstalledMod(m_modID)) { \
|
||||
if (auto setting = typeinfo_pointer_cast<S>(mod->getSettingV3(m_key))) {\
|
||||
return setting->getValue(); \
|
||||
} \
|
||||
} \
|
||||
return m_value; \
|
||||
} \
|
||||
template<> \
|
||||
void GeodeSettingValue< \
|
||||
type_##Setting \
|
||||
>::setValue(ValueType const& value) { \
|
||||
using S = typename SettingTypeForValueType<ValueType>::SettingType; \
|
||||
if (auto mod = Loader::get()->getInstalledMod(m_modID)) { \
|
||||
if (auto setting = typeinfo_pointer_cast<S>(mod->getSettingV3(m_key))) {\
|
||||
return setting->setValue(value); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
template<> \
|
||||
Result<> GeodeSettingValue< \
|
||||
type_##Setting \
|
||||
>::validate(ValueType const& value) const { \
|
||||
using S = typename SettingTypeForValueType<ValueType>::SettingType; \
|
||||
if (auto mod = Loader::get()->getInstalledMod(m_modID)) { \
|
||||
if (auto setting = typeinfo_pointer_cast<S>(mod->getSettingV3(m_key))) {\
|
||||
return setting->isValid(value); \
|
||||
} \
|
||||
} \
|
||||
return Ok(); \
|
||||
} \
|
||||
template<> \
|
||||
typename type_##Setting::ValueType SettingValueSetter< \
|
||||
typename type_##Setting::ValueType \
|
||||
>::get(SettingValue* setting) { \
|
||||
using S = typename SettingTypeForValueType<typename type_##Setting::ValueType>::SettingType; \
|
||||
if (auto mod = Loader::get()->getInstalledMod(setting->getModID())) { \
|
||||
if (auto sett = typeinfo_pointer_cast<S>(mod->getSettingV3(setting->getKey()))) { \
|
||||
return sett->getValue(); \
|
||||
} \
|
||||
} \
|
||||
return typename type_##Setting::ValueType(); \
|
||||
} \
|
||||
template<> \
|
||||
void SettingValueSetter< \
|
||||
typename type_##Setting::ValueType \
|
||||
>::set( \
|
||||
SettingValue* setting, \
|
||||
typename type_##Setting::ValueType const& value \
|
||||
) { \
|
||||
using S = typename SettingTypeForValueType<typename type_##Setting::ValueType>::SettingType; \
|
||||
if (auto mod = Loader::get()->getInstalledMod(setting->getModID())) { \
|
||||
if (auto sett = typeinfo_pointer_cast<S>(mod->getSettingV3(setting->getKey()))) { \
|
||||
return sett->setValue(value); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define IMPL_TO_VALID(type_) \
|
||||
template<> \
|
||||
typename GeodeSettingValue<type_##Setting>::Valid \
|
||||
GeodeSettingValue<type_##Setting>::toValid( \
|
||||
typename type_##Setting::ValueType const& value \
|
||||
) const
|
||||
|
||||
// instantiate values
|
||||
|
||||
namespace geode {
|
||||
template class GeodeSettingValue<BoolSetting>;
|
||||
template class GeodeSettingValue<IntSetting>;
|
||||
template class GeodeSettingValue<FloatSetting>;
|
||||
template class GeodeSettingValue<StringSetting>;
|
||||
template class GeodeSettingValue<FileSetting>;
|
||||
template class GeodeSettingValue<ColorSetting>;
|
||||
template class GeodeSettingValue<ColorAlphaSetting>;
|
||||
}
|
||||
|
||||
IMPL_TO_VALID(Bool) {
|
||||
return { value, std::nullopt };
|
||||
}
|
||||
|
||||
IMPL_TO_VALID(Int) {
|
||||
if (m_definition.min && value < m_definition.min) {
|
||||
return { m_definition.min.value(), fmt::format(
|
||||
"Value must be more than or equal to {}",
|
||||
m_definition.min.value()
|
||||
) };
|
||||
}
|
||||
if (m_definition.max && value > m_definition.max) {
|
||||
return { m_definition.max.value(), fmt::format(
|
||||
"Value must be less than or equal to {}",
|
||||
m_definition.max.value()
|
||||
) };
|
||||
}
|
||||
return { value, std::nullopt };
|
||||
}
|
||||
|
||||
IMPL_TO_VALID(Float) {
|
||||
if (m_definition.min && value < m_definition.min) {
|
||||
return { m_definition.min.value(), fmt::format(
|
||||
"Value must be more than or equal to {}",
|
||||
m_definition.min.value()
|
||||
) };
|
||||
}
|
||||
if (m_definition.max && value > m_definition.max) {
|
||||
return { m_definition.max.value(), fmt::format(
|
||||
"Value must be less than or equal to {}",
|
||||
m_definition.max.value()
|
||||
) };
|
||||
}
|
||||
return { value, std::nullopt };
|
||||
}
|
||||
|
||||
IMPL_TO_VALID(String) {
|
||||
if (m_definition.controls->match) {
|
||||
if (!std::regex_match(value, std::regex{m_definition.controls->match.value()})) {
|
||||
return {
|
||||
m_definition.defaultValue,
|
||||
fmt::format(
|
||||
"Value must match regex {}",
|
||||
m_definition.controls->match.value()
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
else if (m_definition.controls->options) {
|
||||
if (std::find(
|
||||
m_definition.controls->options.value().begin(),
|
||||
m_definition.controls->options.value().end(),
|
||||
value
|
||||
) == m_definition.controls->options.value().end()) {
|
||||
return {
|
||||
m_definition.defaultValue,
|
||||
fmt::format(
|
||||
"Value must be one of {}",
|
||||
fmt::join(m_definition.controls->options.value(), ", ")
|
||||
)
|
||||
};
|
||||
}
|
||||
}
|
||||
return { value, std::nullopt };
|
||||
}
|
||||
|
||||
IMPL_TO_VALID(File) {
|
||||
return { value, std::nullopt };
|
||||
}
|
||||
|
||||
IMPL_TO_VALID(Color) {
|
||||
return { value, std::nullopt };
|
||||
}
|
||||
|
||||
IMPL_TO_VALID(ColorAlpha) {
|
||||
return { value, std::nullopt };
|
||||
}
|
||||
|
||||
IMPL_NODE_AND_SETTERS(Bool);
|
||||
IMPL_NODE_AND_SETTERS(Int);
|
||||
IMPL_NODE_AND_SETTERS(Float);
|
||||
IMPL_NODE_AND_SETTERS(String);
|
||||
IMPL_NODE_AND_SETTERS(File);
|
||||
IMPL_NODE_AND_SETTERS(Color);
|
||||
IMPL_NODE_AND_SETTERS(ColorAlpha);
|
||||
|
||||
// instantiate value setters
|
||||
|
||||
namespace geode {
|
||||
template struct SettingValueSetter<typename BoolSetting::ValueType>;
|
||||
template struct SettingValueSetter<typename IntSetting::ValueType>;
|
||||
template struct SettingValueSetter<typename FloatSetting::ValueType>;
|
||||
template struct SettingValueSetter<typename StringSetting::ValueType>;
|
||||
template struct SettingValueSetter<typename FileSetting::ValueType>;
|
||||
template struct SettingValueSetter<typename ColorSetting::ValueType>;
|
||||
template struct SettingValueSetter<typename ColorAlphaSetting::ValueType>;
|
||||
}
|
||||
|
||||
// SettingChangedEvent
|
||||
|
||||
SettingChangedEvent::SettingChangedEvent(Mod* mod, SettingValue* value)
|
||||
: mod(mod), value(value) {}
|
||||
|
||||
// SettingChangedFilter
|
||||
|
||||
ListenerResult SettingChangedFilter::handle(
|
||||
utils::MiniFunction<Callback> fn, SettingChangedEvent* event
|
||||
) {
|
||||
if (m_modID == event->mod->getID() &&
|
||||
(!m_targetKey || m_targetKey.value() == event->value->getKey())
|
||||
) {
|
||||
fn(event->value);
|
||||
}
|
||||
return ListenerResult::Propagate;
|
||||
}
|
||||
|
||||
SettingChangedFilter::SettingChangedFilter(
|
||||
std::string const& modID,
|
||||
std::optional<std::string> const& settingKey
|
||||
) : m_modID(modID), m_targetKey(settingKey) {}
|
|
@ -1,25 +0,0 @@
|
|||
#include <Geode/loader/SettingNode.hpp>
|
||||
#include <Geode/utils/cocos.hpp>
|
||||
|
||||
using namespace geode::prelude;
|
||||
|
||||
void SettingNode::dispatchChanged() {
|
||||
if (m_delegate) {
|
||||
m_delegate->settingValueChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
void SettingNode::dispatchCommitted() {
|
||||
if (m_delegate) {
|
||||
m_delegate->settingValueCommitted(this);
|
||||
}
|
||||
}
|
||||
|
||||
bool SettingNode::init(SettingValue* value) {
|
||||
m_value = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
void SettingNode::setDelegate(SettingNodeDelegate* delegate) {
|
||||
m_delegate = delegate;
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
#include "SettingNodeV3.hpp"
|
||||
#include <Geode/loader/SettingNode.hpp>
|
||||
#include <Geode/utils/ColorProvider.hpp>
|
||||
#include <Geode/utils/ranges.hpp>
|
||||
#include <Geode/loader/Dirs.hpp>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/loader/SettingV3.hpp>
|
||||
#include <Geode/loader/SettingNode.hpp>
|
||||
#include <Geode/binding/CCMenuItemToggler.hpp>
|
||||
#include <Geode/binding/ColorChannelSprite.hpp>
|
||||
#include <Geode/binding/Slider.hpp>
|
||||
|
@ -314,25 +313,3 @@ public:
|
|||
bool hasNonDefaultValue() const override;
|
||||
void onResetToDefault() override;
|
||||
};
|
||||
|
||||
// If these classes do get exposed in headers,
|
||||
// LegacyCustomSettingToV3Node SHOULD NOT BE EXPOSED!!!!!! DO NOT DO THAT!!!!
|
||||
|
||||
class LegacyCustomSettingToV3Node : public SettingNodeV3, public SettingNodeDelegate {
|
||||
protected:
|
||||
SettingNode* m_original;
|
||||
|
||||
bool init(std::shared_ptr<LegacyCustomSettingV3> original, float width);
|
||||
|
||||
void onCommit() override;
|
||||
|
||||
void settingValueChanged(SettingNode*) override;
|
||||
void settingValueCommitted(SettingNode*) override;
|
||||
|
||||
public:
|
||||
static LegacyCustomSettingToV3Node* create(std::shared_ptr<LegacyCustomSettingV3> original, float width);
|
||||
|
||||
bool hasUncommittedChanges() const override;
|
||||
bool hasNonDefaultValue() const override;
|
||||
void onResetToDefault() override;
|
||||
};
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include <Geode/loader/SettingV3.hpp>
|
||||
#include <Geode/loader/SettingEvent.hpp>
|
||||
#include <Geode/loader/ModSettingsManager.hpp>
|
||||
#include <Geode/utils/ranges.hpp>
|
||||
#include <Geode/utils/string.hpp>
|
||||
|
@ -574,19 +573,12 @@ void SettingV3::markChanged() {
|
|||
}
|
||||
SettingChangedEventV3(shared_from_this()).post();
|
||||
if (manager) {
|
||||
// TODO: v4
|
||||
// Use ModSettingsManager rather than convertToLegacyValue since it
|
||||
// caches the result and we want to have that for performance
|
||||
SettingChangedEvent(this->getMod(), manager->getLegacy(this->getKey()).get()).post();
|
||||
// SettingChangedEvent(this->getMod(), manager->getLegacy(this->getKey()).get()).post();
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<Setting> SettingV3::convertToLegacy() const {
|
||||
return std::nullopt;
|
||||
}
|
||||
std::optional<std::shared_ptr<SettingValue>> SettingV3::convertToLegacyValue() const {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
class TitleSettingV3::Impl final {
|
||||
public:
|
||||
};
|
||||
|
@ -666,15 +658,6 @@ bool LegacyCustomSettingV3::isDefaultValue() const {
|
|||
}
|
||||
void LegacyCustomSettingV3::reset() {}
|
||||
|
||||
std::optional<Setting> LegacyCustomSettingV3::convertToLegacy() const {
|
||||
return Setting(this->getKey(), this->getModID(), SettingKind(CustomSetting {
|
||||
.json = std::make_shared<ModJson>(m_impl->json)
|
||||
}));
|
||||
}
|
||||
std::optional<std::shared_ptr<SettingValue>> LegacyCustomSettingV3::convertToLegacyValue() const {
|
||||
return m_impl->legacyValue ? std::optional(m_impl->legacyValue) : std::nullopt;
|
||||
}
|
||||
|
||||
class BoolSettingV3::Impl final {
|
||||
public:
|
||||
};
|
||||
|
@ -699,17 +682,6 @@ SettingNodeV3* BoolSettingV3::createNode(float width) {
|
|||
);
|
||||
}
|
||||
|
||||
std::optional<Setting> BoolSettingV3::convertToLegacy() const {
|
||||
return Setting(this->getKey(), this->getModID(), SettingKind(BoolSetting {
|
||||
.name = this->getName(),
|
||||
.description = this->getDescription(),
|
||||
.defaultValue = this->getDefaultValue(),
|
||||
}));
|
||||
}
|
||||
std::optional<std::shared_ptr<SettingValue>> BoolSettingV3::convertToLegacyValue() const {
|
||||
return this->convertToLegacy()->createDefaultValue();
|
||||
}
|
||||
|
||||
class IntSettingV3::Impl final {
|
||||
public:
|
||||
std::optional<int64_t> minValue;
|
||||
|
@ -819,28 +791,6 @@ SettingNodeV3* IntSettingV3::createNode(float width) {
|
|||
);
|
||||
}
|
||||
|
||||
std::optional<Setting> IntSettingV3::convertToLegacy() const {
|
||||
return Setting(this->getKey(), this->getModID(), SettingKind(IntSetting {
|
||||
.name = this->getName(),
|
||||
.description = this->getDescription(),
|
||||
.defaultValue = this->getDefaultValue(),
|
||||
.min = this->getMinValue(),
|
||||
.max = this->getMaxValue(),
|
||||
.controls = {
|
||||
.arrows = this->isArrowsEnabled(),
|
||||
.bigArrows = this->isBigArrowsEnabled(),
|
||||
.arrowStep = this->getArrowStepSize(),
|
||||
.bigArrowStep = this->getBigArrowStepSize(),
|
||||
.slider = this->isSliderEnabled(),
|
||||
.sliderStep = this->getSliderSnap(),
|
||||
.input = this->isInputEnabled(),
|
||||
},
|
||||
}));
|
||||
}
|
||||
std::optional<std::shared_ptr<SettingValue>> IntSettingV3::convertToLegacyValue() const {
|
||||
return this->convertToLegacy()->createDefaultValue();
|
||||
}
|
||||
|
||||
class FloatSettingV3::Impl final {
|
||||
public:
|
||||
std::optional<double> minValue;
|
||||
|
@ -948,27 +898,6 @@ SettingNodeV3* FloatSettingV3::createNode(float width) {
|
|||
);
|
||||
}
|
||||
|
||||
std::optional<Setting> FloatSettingV3::convertToLegacy() const {
|
||||
return Setting(this->getKey(), this->getModID(), SettingKind(FloatSetting {
|
||||
.name = this->getName(),
|
||||
.description = this->getDescription(),
|
||||
.defaultValue = this->getDefaultValue(),
|
||||
.min = this->getMinValue(),
|
||||
.max = this->getMaxValue(),
|
||||
.controls = {
|
||||
.arrows = this->isArrowsEnabled(),
|
||||
.bigArrows = this->isBigArrowsEnabled(),
|
||||
.arrowStep = static_cast<size_t>(this->getArrowStepSize()),
|
||||
.bigArrowStep = static_cast<size_t>(this->getBigArrowStepSize()),
|
||||
.slider = this->isSliderEnabled(),
|
||||
.sliderStep = this->getSliderSnap(),
|
||||
.input = this->isInputEnabled(),
|
||||
},
|
||||
}));
|
||||
}
|
||||
std::optional<std::shared_ptr<SettingValue>> FloatSettingV3::convertToLegacyValue() const {
|
||||
return this->convertToLegacy()->createDefaultValue();
|
||||
}
|
||||
|
||||
class StringSettingV3::Impl final {
|
||||
public:
|
||||
|
@ -1026,20 +955,6 @@ SettingNodeV3* StringSettingV3::createNode(float width) {
|
|||
);
|
||||
}
|
||||
|
||||
std::optional<Setting> StringSettingV3::convertToLegacy() const {
|
||||
auto setting = StringSetting();
|
||||
setting.name = this->getName();
|
||||
setting.description = this->getDescription();
|
||||
setting.defaultValue = this->getDefaultValue();
|
||||
setting.controls->filter = this->getAllowedCharacters();
|
||||
setting.controls->match = this->getRegexValidator();
|
||||
setting.controls->options = this->getEnumOptions();
|
||||
return Setting(this->getKey(), this->getModID(), SettingKind(setting));
|
||||
}
|
||||
std::optional<std::shared_ptr<SettingValue>> StringSettingV3::convertToLegacyValue() const {
|
||||
return this->convertToLegacy()->createDefaultValue();
|
||||
}
|
||||
|
||||
class FileSettingV3::Impl final {
|
||||
public:
|
||||
bool folder = false;
|
||||
|
@ -1153,18 +1068,6 @@ SettingNodeV3* FileSettingV3::createNode(float width) {
|
|||
);
|
||||
}
|
||||
|
||||
std::optional<Setting> FileSettingV3::convertToLegacy() const {
|
||||
auto setting = FileSetting();
|
||||
setting.name = this->getName();
|
||||
setting.description = this->getDescription();
|
||||
setting.defaultValue = this->getDefaultValue();
|
||||
setting.controls.filters = this->getFilters().value_or(std::vector<utils::file::FilePickOptions::Filter>());
|
||||
return Setting(this->getKey(), this->getModID(), SettingKind(setting));
|
||||
}
|
||||
std::optional<std::shared_ptr<SettingValue>> FileSettingV3::convertToLegacyValue() const {
|
||||
return this->convertToLegacy()->createDefaultValue();
|
||||
}
|
||||
|
||||
class Color3BSettingV3::Impl final {
|
||||
public:
|
||||
};
|
||||
|
@ -1189,17 +1092,6 @@ SettingNodeV3* Color3BSettingV3::createNode(float width) {
|
|||
);
|
||||
}
|
||||
|
||||
std::optional<Setting> Color3BSettingV3::convertToLegacy() const {
|
||||
auto setting = ColorSetting();
|
||||
setting.name = this->getName();
|
||||
setting.description = this->getDescription();
|
||||
setting.defaultValue = this->getDefaultValue();
|
||||
return Setting(this->getKey(), this->getModID(), SettingKind(setting));
|
||||
}
|
||||
std::optional<std::shared_ptr<SettingValue>> Color3BSettingV3::convertToLegacyValue() const {
|
||||
return this->convertToLegacy()->createDefaultValue();
|
||||
}
|
||||
|
||||
class Color4BSettingV3::Impl final {
|
||||
public:
|
||||
};
|
||||
|
@ -1223,14 +1115,3 @@ SettingNodeV3* Color4BSettingV3::createNode(float width) {
|
|||
std::static_pointer_cast<Color4BSettingV3>(shared_from_this()), width
|
||||
);
|
||||
}
|
||||
|
||||
std::optional<Setting> Color4BSettingV3::convertToLegacy() const {
|
||||
auto setting = ColorAlphaSetting();
|
||||
setting.name = this->getName();
|
||||
setting.description = this->getDescription();
|
||||
setting.defaultValue = this->getDefaultValue();
|
||||
return Setting(this->getKey(), this->getModID(), SettingKind(setting));
|
||||
}
|
||||
std::optional<std::shared_ptr<SettingValue>> Color4BSettingV3::convertToLegacyValue() const {
|
||||
return this->convertToLegacy()->createDefaultValue();
|
||||
}
|
||||
|
|
|
@ -102,9 +102,7 @@ void updater::downloadLatestLoaderResources() {
|
|||
log::debug("Downloading latest resources", Loader::get()->getVersion().toVString());
|
||||
fetchLatestGithubRelease(
|
||||
[](matjson::Value const& raw) {
|
||||
auto json = raw;
|
||||
JsonChecker checker(json);
|
||||
auto root = checker.root("[]").obj();
|
||||
auto root = checkJson(raw, "[]");
|
||||
|
||||
// find release asset
|
||||
for (auto asset : root.needs("assets").iterate()) {
|
||||
|
@ -206,9 +204,7 @@ void updater::downloadLoaderResources(bool useLatestRelease) {
|
|||
RUNNING_REQUESTS.erase("@downloadLoaderResources");
|
||||
if (response->ok()) {
|
||||
if (auto ok = response->json()) {
|
||||
auto json = ok.unwrap();
|
||||
JsonChecker checker(json);
|
||||
auto root = checker.root("[]").obj();
|
||||
auto root = checkJson(ok.unwrap(), "[]");
|
||||
|
||||
// find release asset
|
||||
for (auto asset : root.needs("assets").iterate()) {
|
||||
|
@ -362,9 +358,7 @@ void updater::checkForLoaderUpdates() {
|
|||
// Check for updates in the background
|
||||
fetchLatestGithubRelease(
|
||||
[](matjson::Value const& raw) {
|
||||
auto json = raw;
|
||||
JsonChecker checker(json);
|
||||
auto root = checker.root("[]").obj();
|
||||
auto root = checkJson(raw, "[]");
|
||||
|
||||
VersionInfo ver { 0, 0, 0 };
|
||||
root.needs("tag_name").into(ver);
|
||||
|
|
|
@ -258,9 +258,7 @@ Result<ServerDateTime> ServerDateTime::parse(std::string const& str) {
|
|||
}
|
||||
|
||||
Result<ServerModVersion> ServerModVersion::parse(matjson::Value const& raw) {
|
||||
auto json = raw;
|
||||
JsonChecker checker(json);
|
||||
auto root = checker.root("ServerModVersion").obj();
|
||||
auto root = checkJson(raw, "ServerModVersion");
|
||||
|
||||
auto res = ServerModVersion();
|
||||
|
||||
|
@ -356,9 +354,7 @@ Result<ServerModVersion> ServerModVersion::parse(matjson::Value const& raw) {
|
|||
}
|
||||
|
||||
Result<ServerModReplacement> ServerModReplacement::parse(matjson::Value const& raw) {
|
||||
auto json = raw;
|
||||
JsonChecker checker(json);
|
||||
auto root = checker.root("ServerModReplacement").obj();
|
||||
auto root = checkJson(raw, "ServerModReplacement");
|
||||
auto res = ServerModReplacement();
|
||||
|
||||
root.needs("id").into(res.id);
|
||||
|
@ -371,9 +367,7 @@ Result<ServerModReplacement> ServerModReplacement::parse(matjson::Value const& r
|
|||
}
|
||||
|
||||
Result<ServerModUpdate> ServerModUpdate::parse(matjson::Value const& raw) {
|
||||
auto json = raw;
|
||||
JsonChecker checker(json);
|
||||
auto root = checker.root("ServerModUpdate").obj();
|
||||
auto root = checkJson(raw, "ServerModUpdate");
|
||||
|
||||
auto res = ServerModUpdate();
|
||||
|
||||
|
@ -391,9 +385,7 @@ Result<ServerModUpdate> ServerModUpdate::parse(matjson::Value const& raw) {
|
|||
}
|
||||
|
||||
Result<std::vector<ServerModUpdate>> ServerModUpdate::parseList(matjson::Value const& raw) {
|
||||
auto json = raw;
|
||||
JsonChecker checker(json);
|
||||
auto payload = checker.root("ServerModUpdatesList").array();
|
||||
auto payload = checkJson(raw, "ServerModUpdatesList");
|
||||
|
||||
std::vector<ServerModUpdate> list {};
|
||||
for (auto item : payload.iterate()) {
|
||||
|
@ -421,9 +413,7 @@ bool ServerModUpdate::hasUpdateForInstalledMod() const {
|
|||
}
|
||||
|
||||
Result<ServerModMetadata> ServerModMetadata::parse(matjson::Value const& raw) {
|
||||
auto json = raw;
|
||||
JsonChecker checker(json);
|
||||
auto root = checker.root("ServerModMetadata").obj();
|
||||
auto root = checkJson(raw, "ServerModMetadata");
|
||||
|
||||
auto res = ServerModMetadata();
|
||||
root.needs("id").into(res.id);
|
||||
|
@ -501,9 +491,7 @@ std::string ServerModMetadata::formatDevelopersToString() const {
|
|||
}
|
||||
|
||||
Result<ServerModsList> ServerModsList::parse(matjson::Value const& raw) {
|
||||
auto json = raw;
|
||||
JsonChecker checker(json);
|
||||
auto payload = checker.root("ServerModsList").obj();
|
||||
auto payload = checkJson(raw, "ServerModsList");
|
||||
|
||||
auto list = ServerModsList();
|
||||
for (auto item : payload.needs("data").iterate()) {
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include "Geode/utils/VersionInfo.hpp"
|
||||
#include <Geode/DefaultInclude.hpp>
|
||||
#include <Geode/utils/web.hpp>
|
||||
#include <Geode/loader/SettingEvent.hpp>
|
||||
#include <chrono>
|
||||
#include <matjson.hpp>
|
||||
#include <vector>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include "GeodeStyle.hpp"
|
||||
#include <Geode/utils/cocos.hpp>
|
||||
#include <Geode/utils/ColorProvider.hpp>
|
||||
#include <Geode/loader/SettingEvent.hpp>
|
||||
#include <Geode/binding/ButtonSprite.hpp>
|
||||
#include <Geode/ui/LoadingSpinner.hpp>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "ModDeveloperItem.hpp"
|
||||
|
||||
#include <Geode/cocos/base_nodes/CCNode.h>
|
||||
#include <Geode/cocos/base_nodes/Layout.hpp>
|
||||
#include <Geode/ui/Layout.hpp>
|
||||
#include <Geode/cocos/cocoa/CCGeometry.h>
|
||||
#include <Geode/cocos/label_nodes/CCLabelBMFont.h>
|
||||
#include <Geode/cocos/platform/CCPlatformMacros.h>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "ModDeveloperList.hpp"
|
||||
|
||||
#include <Geode/cocos/base_nodes/CCNode.h>
|
||||
#include <Geode/cocos/base_nodes/Layout.hpp>
|
||||
#include <Geode/ui/Layout.hpp>
|
||||
#include <Geode/cocos/cocoa/CCGeometry.h>
|
||||
#include <Geode/cocos/platform/CCPlatformMacros.h>
|
||||
#include <Geode/utils/cocos.hpp>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "ModProblemItem.hpp"
|
||||
|
||||
#include <Geode/cocos/base_nodes/CCNode.h>
|
||||
#include <Geode/cocos/base_nodes/Layout.hpp>
|
||||
#include <Geode/ui/Layout.hpp>
|
||||
#include <Geode/cocos/cocoa/CCGeometry.h>
|
||||
#include <Geode/cocos/label_nodes/CCLabelBMFont.h>
|
||||
#include <Geode/cocos/platform/CCPlatformMacros.h>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "ModProblemList.hpp"
|
||||
|
||||
#include <Geode/cocos/base_nodes/CCNode.h>
|
||||
#include <Geode/cocos/base_nodes/Layout.hpp>
|
||||
#include <Geode/ui/Layout.hpp>
|
||||
#include <Geode/cocos/cocoa/CCGeometry.h>
|
||||
#include <Geode/cocos/platform/CCPlatformMacros.h>
|
||||
#include <Geode/utils/cocos.hpp>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "ModErrorPopup.hpp"
|
||||
#include "Geode/cocos/base_nodes/Layout.hpp"
|
||||
#include <Geode/ui/Layout.hpp>
|
||||
#include "ui/mods/GeodeStyle.hpp"
|
||||
#include "ui/mods/list/ModProblemList.hpp"
|
||||
|
||||
|
|
|
@ -1,558 +0,0 @@
|
|||
#include "GeodeSettingNode.hpp"
|
||||
#include "Geode/binding/FLAlertLayer.hpp"
|
||||
#include "Geode/ui/Popup.hpp"
|
||||
|
||||
#include <Geode/binding/ButtonSprite.hpp>
|
||||
#include <Geode/binding/CCTextInputNode.hpp>
|
||||
#include <Geode/binding/ColorChannelSprite.hpp>
|
||||
#include <Geode/binding/Slider.hpp>
|
||||
#include <Geode/binding/CCMenuItemToggler.hpp>
|
||||
#include <Geode/loader/Loader.hpp>
|
||||
#include <Geode/loader/Dirs.hpp>
|
||||
#include <Geode/utils/general.hpp>
|
||||
#include <charconv>
|
||||
#include <clocale>
|
||||
#include <filesystem>
|
||||
|
||||
// Helpers
|
||||
|
||||
template<class T>
|
||||
static float valueToSlider(T const& setting, typename T::ValueType value) {
|
||||
auto min = setting.min ? setting.min.value() : -100;
|
||||
auto max = setting.max ? setting.max.value() : +100;
|
||||
auto range = max - min;
|
||||
return static_cast<float>(clamp(static_cast<double>(value - min) / range, 0.0, 1.0));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static typename T::ValueType valueFromSlider(T const& setting, float num) {
|
||||
auto min = setting.min ? setting.min.value() : -100;
|
||||
auto max = setting.max ? setting.max.value() : +100;
|
||||
auto range = max - min;
|
||||
auto value = static_cast<typename T::ValueType>(num * range + min);
|
||||
if (auto step = setting.controls.sliderStep) {
|
||||
value = static_cast<typename T::ValueType>(
|
||||
round(value / step.value()) * step.value()
|
||||
);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
template<class C, class T>
|
||||
TextInput* createInput(C* node, GeodeSettingValue<T>* setting, float width) {
|
||||
auto input = TextInput::create(width / 2 - 70.f, "Text", "chatFont.fnt");
|
||||
input->setPosition({
|
||||
-(width / 2 - 70.f) / 2,
|
||||
setting->castDefinition().controls.slider ? 5.f : 0.f
|
||||
});
|
||||
input->setScale(.65f);
|
||||
input->setDelegate(node);
|
||||
return input;
|
||||
}
|
||||
|
||||
template<class C, class T>
|
||||
Slider* createSlider(C* node, GeodeSettingValue<T>* setting, float width) {
|
||||
auto slider = Slider::create(
|
||||
node, menu_selector(C::onSlider), .5f
|
||||
);
|
||||
slider->setPosition(-50.f, -15.f);
|
||||
node->updateSlider();
|
||||
return slider;
|
||||
}
|
||||
|
||||
template<class C, class T>
|
||||
std::pair<
|
||||
CCMenuItemSpriteExtra*, CCMenuItemSpriteExtra*
|
||||
> createArrows(C* node, GeodeSettingValue<T>* setting, float width, bool big) {
|
||||
auto yPos = setting->castDefinition().controls.slider ? 5.f : 0.f;
|
||||
auto decArrowSpr = CCSprite::createWithSpriteFrameName(
|
||||
big ? "double-nav.png"_spr : "navArrowBtn_001.png"
|
||||
);
|
||||
decArrowSpr->setFlipX(true);
|
||||
decArrowSpr->setScale(.3f);
|
||||
|
||||
auto decArrow = CCMenuItemSpriteExtra::create(
|
||||
decArrowSpr, node, menu_selector(C::onArrow)
|
||||
);
|
||||
decArrow->setPosition(-width / 2 + (big ? 65.f : 80.f), yPos);
|
||||
decArrow->setTag(big ?
|
||||
-setting->castDefinition().controls.bigArrowStep :
|
||||
-setting->castDefinition().controls.arrowStep
|
||||
);
|
||||
|
||||
auto incArrowSpr = CCSprite::createWithSpriteFrameName(
|
||||
big ? "double-nav.png"_spr : "navArrowBtn_001.png"
|
||||
);
|
||||
incArrowSpr->setScale(.3f);
|
||||
|
||||
auto incArrow = CCMenuItemSpriteExtra::create(
|
||||
incArrowSpr, node, menu_selector(C::onArrow)
|
||||
);
|
||||
incArrow->setTag(big ?
|
||||
setting->castDefinition().controls.bigArrowStep :
|
||||
setting->castDefinition().controls.arrowStep
|
||||
);
|
||||
incArrow->setPosition(big ? 5.f : -10.f, yPos);
|
||||
|
||||
return { decArrow, incArrow };
|
||||
}
|
||||
|
||||
// BoolSettingNode
|
||||
|
||||
void BoolSettingNode::valueChanged(bool updateText) {
|
||||
GeodeSettingNode::valueChanged(updateText);
|
||||
m_toggle->toggle(m_uncommittedValue);
|
||||
}
|
||||
|
||||
void BoolSettingNode::onToggle(CCObject*) {
|
||||
m_uncommittedValue = !m_toggle->isToggled();
|
||||
this->valueChanged(true);
|
||||
m_toggle->toggle(!m_uncommittedValue);
|
||||
}
|
||||
|
||||
bool BoolSettingNode::setup(BoolSettingValue* setting, float width) {
|
||||
m_toggle = CCMenuItemToggler::createWithStandardSprites(
|
||||
this, menu_selector(BoolSettingNode::onToggle), .6f
|
||||
);
|
||||
m_toggle->toggle(m_uncommittedValue);
|
||||
m_toggle->setPositionX(-10.f);
|
||||
m_menu->addChild(m_toggle);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// IntSettingNode
|
||||
|
||||
float IntSettingNode::setupHeight(IntSettingValue* setting) const {
|
||||
return setting->castDefinition().controls.slider ? 55.f : 40.f;
|
||||
}
|
||||
|
||||
void IntSettingNode::onSlider(CCObject* slider) {
|
||||
m_uncommittedValue = valueFromSlider(
|
||||
setting()->castDefinition(),
|
||||
static_cast<SliderThumb*>(slider)->getValue()
|
||||
);
|
||||
this->valueChanged(true);
|
||||
}
|
||||
|
||||
void IntSettingNode::valueChanged(bool updateText) {
|
||||
GeodeSettingNode::valueChanged(updateText);
|
||||
if (updateText) {
|
||||
this->updateLabel();
|
||||
}
|
||||
this->updateSlider();
|
||||
}
|
||||
|
||||
void IntSettingNode::updateSlider() {
|
||||
if (m_slider) {
|
||||
m_slider->setValue(valueToSlider(
|
||||
setting()->castDefinition(),
|
||||
m_uncommittedValue
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
void IntSettingNode::updateLabel() {
|
||||
if (m_input) {
|
||||
// hacky way to make setString not called textChanged
|
||||
m_input->setString(numToString(m_uncommittedValue), false);
|
||||
}
|
||||
else {
|
||||
m_label->setString(numToString(m_uncommittedValue).c_str());
|
||||
m_label->limitLabelWidth(m_width / 2 - 70.f, .5f, .1f);
|
||||
}
|
||||
}
|
||||
|
||||
void IntSettingNode::onArrow(CCObject* sender) {
|
||||
m_uncommittedValue += sender->getTag();
|
||||
this->valueChanged(true);
|
||||
}
|
||||
|
||||
void IntSettingNode::textChanged(CCTextInputNode* input) {
|
||||
auto res = numFromString<ValueType>(input->getString());
|
||||
if (!res) return;
|
||||
m_uncommittedValue = res.unwrap();
|
||||
this->valueChanged(false);
|
||||
}
|
||||
|
||||
bool IntSettingNode::setup(IntSettingValue* setting, float width) {
|
||||
if (setting->castDefinition().controls.input) {
|
||||
m_menu->addChild(m_input = createInput(this, setting, width));
|
||||
m_input->setCommonFilter(CommonFilter::Int);
|
||||
}
|
||||
else {
|
||||
m_label = CCLabelBMFont::create("", "bigFont.fnt");
|
||||
m_label->setPosition({
|
||||
-(width / 2 - 70.f) / 2,
|
||||
setting->castDefinition().controls.slider ? 5.f : 0.f
|
||||
});
|
||||
m_label->limitLabelWidth(width / 2 - 70.f, .5f, .1f);
|
||||
m_menu->addChild(m_label);
|
||||
}
|
||||
if (setting->castDefinition().controls.slider) {
|
||||
m_menu->addChild(m_slider = createSlider(this, setting, width));
|
||||
}
|
||||
if (setting->castDefinition().controls.arrows) {
|
||||
auto [dec, inc] = createArrows(this, setting, width, false);
|
||||
m_menu->addChild(m_decArrow = dec);
|
||||
m_menu->addChild(m_incArrow = inc);
|
||||
}
|
||||
if (setting->castDefinition().controls.bigArrows) {
|
||||
auto [dec, inc] = createArrows(this, setting, width, true);
|
||||
m_menu->addChild(m_bigDecArrow = dec);
|
||||
m_menu->addChild(m_bigIncArrow = inc);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// FloatSettingNode
|
||||
|
||||
float FloatSettingNode::setupHeight(FloatSettingValue* setting) const {
|
||||
return setting->castDefinition().controls.slider ? 55.f : 40.f;
|
||||
}
|
||||
|
||||
void FloatSettingNode::onSlider(CCObject* slider) {
|
||||
m_uncommittedValue = valueFromSlider(
|
||||
setting()->castDefinition(),
|
||||
static_cast<SliderThumb*>(slider)->getValue()
|
||||
);
|
||||
this->valueChanged(true);
|
||||
}
|
||||
|
||||
void FloatSettingNode::valueChanged(bool updateText) {
|
||||
GeodeSettingNode::valueChanged(updateText);
|
||||
if (updateText) {
|
||||
this->updateLabel();
|
||||
}
|
||||
this->updateSlider();
|
||||
}
|
||||
|
||||
void FloatSettingNode::updateSlider() {
|
||||
if (m_slider) {
|
||||
m_slider->setValue(valueToSlider(
|
||||
setting()->castDefinition(),
|
||||
m_uncommittedValue
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
void FloatSettingNode::updateLabel() {
|
||||
if (m_input) {
|
||||
// hacky way to make setString not called textChanged
|
||||
m_input->setString(numToString(m_uncommittedValue), false);
|
||||
}
|
||||
else {
|
||||
m_label->setString(numToString(m_uncommittedValue).c_str());
|
||||
m_label->limitLabelWidth(m_width / 2 - 70.f, .5f, .1f);
|
||||
}
|
||||
}
|
||||
|
||||
void FloatSettingNode::onArrow(CCObject* sender) {
|
||||
m_uncommittedValue += sender->getTag();
|
||||
this->valueChanged(true);
|
||||
}
|
||||
|
||||
void FloatSettingNode::textChanged(CCTextInputNode* input) {
|
||||
auto res = numFromString<ValueType>(input->getString());
|
||||
if (!res) return;
|
||||
m_uncommittedValue = res.unwrap();
|
||||
this->valueChanged(false);
|
||||
}
|
||||
|
||||
bool FloatSettingNode::setup(FloatSettingValue* setting, float width) {
|
||||
if (setting->castDefinition().controls.input) {
|
||||
m_menu->addChild(m_input = createInput(this, setting, width));
|
||||
m_input->setCommonFilter(CommonFilter::Float);
|
||||
}
|
||||
else {
|
||||
m_label = CCLabelBMFont::create("", "bigFont.fnt");
|
||||
m_label->setPosition({
|
||||
-(width / 2 - 70.f) / 2,
|
||||
setting->castDefinition().controls.slider ? 5.f : 0.f
|
||||
});
|
||||
m_label->limitLabelWidth(width / 2 - 70.f, .5f, .1f);
|
||||
m_menu->addChild(m_label);
|
||||
}
|
||||
if (setting->castDefinition().controls.slider) {
|
||||
m_menu->addChild(m_slider = createSlider(this, setting, width));
|
||||
}
|
||||
if (setting->castDefinition().controls.arrows) {
|
||||
auto [dec, inc] = createArrows(this, setting, width, false);
|
||||
m_menu->addChild(m_decArrow = dec);
|
||||
m_menu->addChild(m_incArrow = inc);
|
||||
}
|
||||
if (setting->castDefinition().controls.bigArrows) {
|
||||
auto [dec, inc] = createArrows(this, setting, width, true);
|
||||
m_menu->addChild(m_bigDecArrow = dec);
|
||||
m_menu->addChild(m_bigIncArrow = inc);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// StringSettingNode
|
||||
|
||||
void StringSettingNode::updateLabel() {
|
||||
if (m_input) m_input->setString(m_uncommittedValue, false);
|
||||
if (m_label) {
|
||||
m_label->setString(m_uncommittedValue.c_str());
|
||||
m_label->limitLabelWidth(m_width / 2 - 80.f, .65f, .1f);
|
||||
}
|
||||
}
|
||||
|
||||
void StringSettingNode::textChanged(CCTextInputNode* input) {
|
||||
m_uncommittedValue = input->getString();
|
||||
this->valueChanged(false);
|
||||
}
|
||||
|
||||
void StringSettingNode::valueChanged(bool updateText) {
|
||||
GeodeSettingNode::valueChanged(updateText);
|
||||
this->updateLabel();
|
||||
}
|
||||
|
||||
void StringSettingNode::onArrow(CCObject* sender) {
|
||||
m_selectedOption += sender->getTag();
|
||||
if (m_selectedOption < 0) {
|
||||
m_selectedOption = m_options.size() - 1;
|
||||
}
|
||||
else if (m_selectedOption >= m_options.size()) {
|
||||
m_selectedOption = 0;
|
||||
}
|
||||
m_uncommittedValue = m_options[m_selectedOption];
|
||||
this->valueChanged(true);
|
||||
}
|
||||
|
||||
bool StringSettingNode::setup(StringSettingValue* setting, float width) {
|
||||
m_width = width;
|
||||
if (setting->castDefinition().controls->options.has_value()) {
|
||||
m_options = setting->castDefinition().controls->options.value();
|
||||
|
||||
m_selectedOption = 0;
|
||||
for (size_t i = 0; i < m_options.size(); i++) {
|
||||
if (m_options[i] == setting->castDefinition().defaultValue) {
|
||||
m_selectedOption = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto prevArrowSpr = CCSprite::createWithSpriteFrameName("navArrowBtn_001.png");
|
||||
prevArrowSpr->setFlipX(true);
|
||||
prevArrowSpr->setScale(.3f);
|
||||
|
||||
m_prevBtn = CCMenuItemSpriteExtra::create(
|
||||
prevArrowSpr, this, menu_selector(StringSettingNode::onArrow)
|
||||
);
|
||||
m_prevBtn->setPosition(-width / 2 + 65.f, 0.f);
|
||||
m_prevBtn->setTag(-1);
|
||||
m_menu->addChild(m_prevBtn);
|
||||
|
||||
auto nextArrowSpr = CCSprite::createWithSpriteFrameName("navArrowBtn_001.png");
|
||||
nextArrowSpr->setScale(.3f);
|
||||
|
||||
m_nextBtn = CCMenuItemSpriteExtra::create(
|
||||
nextArrowSpr, this, menu_selector(StringSettingNode::onArrow)
|
||||
);
|
||||
m_nextBtn->setTag(1);
|
||||
m_nextBtn->setPosition(5.f, 0.f);
|
||||
m_menu->addChild(m_nextBtn);
|
||||
|
||||
m_label = CCLabelBMFont::create("", "bigFont.fnt");
|
||||
m_label->setPosition({ -(width / 2 - 70.f) / 2, .0f });
|
||||
m_menu->addChild(m_label);
|
||||
}
|
||||
else {
|
||||
m_input = TextInput::create(width / 2 - 10.f, "Text", "chatFont.fnt");
|
||||
m_input->setPosition({ -(width / 2 - 70.f) / 2, .0f });
|
||||
m_input->setScale(.65f);
|
||||
|
||||
if (setting->castDefinition().controls->filter.has_value()) {
|
||||
m_input->setFilter(setting->castDefinition().controls->filter.value());
|
||||
}
|
||||
|
||||
m_input->setDelegate(this);
|
||||
m_menu->addChild(m_input);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// FileSettingNode
|
||||
|
||||
void FileSettingNode::updateLabel() {
|
||||
// hacky way to make setString not called textChanged
|
||||
m_input->setString(m_uncommittedValue.string(), false);
|
||||
}
|
||||
|
||||
void FileSettingNode::textChanged(CCTextInputNode* input) {
|
||||
m_uncommittedValue = input->getString().c_str();
|
||||
this->valueChanged(false);
|
||||
}
|
||||
|
||||
void FileSettingNode::valueChanged(bool updateText) {
|
||||
GeodeSettingNode::valueChanged(updateText);
|
||||
this->updateLabel();
|
||||
}
|
||||
|
||||
void FileSettingNode::onPickFile(CCObject*) {
|
||||
m_pickListener.bind(this, &FileSettingNode::onPickFileFinished);
|
||||
m_pickListener.setFilter(file::pick(
|
||||
file::PickMode::OpenFile,
|
||||
{
|
||||
dirs::getGameDir(),
|
||||
setting()->castDefinition().controls.filters
|
||||
}));
|
||||
}
|
||||
|
||||
void FileSettingNode::onPickFileFinished(FileTask::Event* event) {
|
||||
if (!event->getValue()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto value = event->getValue();
|
||||
if (value->isOk()) {
|
||||
m_uncommittedValue = value->unwrap();
|
||||
this->valueChanged(true);
|
||||
} else {
|
||||
FLAlertLayer::create(
|
||||
"Failed",
|
||||
fmt::format("Failed to pick file: {}", value->err().value()).c_str(),
|
||||
"Ok"
|
||||
)->show();
|
||||
}
|
||||
}
|
||||
|
||||
bool FileSettingNode::setup(FileSettingValue* setting, float width) {
|
||||
m_input = TextInput::create(width / 2 - 30.f, "Path to File", "chatFont.fnt");
|
||||
m_input->setPosition({ -(width / 2 - 80.f) / 2 - 15.f, .0f });
|
||||
m_input->setScale(.65f);
|
||||
m_input->setDelegate(this);
|
||||
m_menu->addChild(m_input);
|
||||
|
||||
auto fileBtnSpr = CCSprite::createWithSpriteFrameName("gj_folderBtn_001.png");
|
||||
fileBtnSpr->setScale(.5f);
|
||||
|
||||
auto fileBtn = CCMenuItemSpriteExtra::create(
|
||||
fileBtnSpr, this, menu_selector(FileSettingNode::onPickFile)
|
||||
);
|
||||
fileBtn->setPosition(.0f, .0f);
|
||||
m_menu->addChild(fileBtn);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ColorSettingNode
|
||||
|
||||
void ColorSettingNode::valueChanged(bool updateText) {
|
||||
GeodeSettingNode::valueChanged(updateText);
|
||||
m_colorSpr->setColor(m_uncommittedValue);
|
||||
}
|
||||
|
||||
void ColorSettingNode::updateColor(ccColor4B const& color) {
|
||||
m_uncommittedValue = to3B(color);
|
||||
this->valueChanged(true);
|
||||
}
|
||||
|
||||
void ColorSettingNode::onSelectColor(CCObject*) {
|
||||
auto popup = ColorPickPopup::create(m_uncommittedValue);
|
||||
popup->setDelegate(this);
|
||||
popup->setColorTarget(m_colorSpr);
|
||||
popup->show();
|
||||
}
|
||||
|
||||
bool ColorSettingNode::setup(ColorSettingValue* setting, float width) {
|
||||
m_colorSpr = ColorChannelSprite::create();
|
||||
m_colorSpr->setColor(m_uncommittedValue);
|
||||
m_colorSpr->setScale(.65f);
|
||||
|
||||
auto button = CCMenuItemSpriteExtra::create(
|
||||
m_colorSpr, this, menu_selector(ColorSettingNode::onSelectColor)
|
||||
);
|
||||
button->setPositionX(-10.f);
|
||||
m_menu->addChild(button);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ColorAlphaSettingNode
|
||||
|
||||
void ColorAlphaSettingNode::valueChanged(bool updateText) {
|
||||
GeodeSettingNode::valueChanged(updateText);
|
||||
m_colorSpr->setColor(to3B(m_uncommittedValue));
|
||||
m_colorSpr->updateOpacity(m_uncommittedValue.a / 255.f);
|
||||
}
|
||||
|
||||
void ColorAlphaSettingNode::updateColor(ccColor4B const& color) {
|
||||
m_uncommittedValue = color;
|
||||
this->valueChanged(true);
|
||||
}
|
||||
|
||||
void ColorAlphaSettingNode::onSelectColor(CCObject*) {
|
||||
auto popup = ColorPickPopup::create(m_uncommittedValue);
|
||||
popup->setDelegate(this);
|
||||
popup->setColorTarget(m_colorSpr);
|
||||
popup->show();
|
||||
}
|
||||
|
||||
bool ColorAlphaSettingNode::setup(ColorAlphaSettingValue* setting, float width) {
|
||||
m_colorSpr = ColorChannelSprite::create();
|
||||
m_colorSpr->setColor(to3B(m_uncommittedValue));
|
||||
m_colorSpr->updateOpacity(m_uncommittedValue.a / 255.f);
|
||||
m_colorSpr->setScale(.65f);
|
||||
|
||||
auto button = CCMenuItemSpriteExtra::create(
|
||||
m_colorSpr, this, menu_selector(ColorAlphaSettingNode::onSelectColor)
|
||||
);
|
||||
button->setPositionX(-10.f);
|
||||
m_menu->addChild(button);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// CustomSettingPlaceholderNode
|
||||
|
||||
void CustomSettingPlaceholderNode::commit() {
|
||||
|
||||
}
|
||||
|
||||
bool CustomSettingPlaceholderNode::hasUncommittedChanges() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CustomSettingPlaceholderNode::hasNonDefaultValue() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void CustomSettingPlaceholderNode::resetToDefault() {
|
||||
|
||||
}
|
||||
|
||||
bool CustomSettingPlaceholderNode::init(std::string const& key, float width) {
|
||||
if (!SettingNode::init(nullptr))
|
||||
return false;
|
||||
|
||||
constexpr auto sidePad = 40.f;
|
||||
|
||||
this->setContentSize({ width, 40.f });
|
||||
|
||||
auto info = CCLabelBMFont::create(
|
||||
"You need to enable the mod to modify this setting.",
|
||||
"bigFont.fnt"
|
||||
);
|
||||
info->setAnchorPoint({ .0f, .5f });
|
||||
info->limitLabelWidth(width - sidePad, .5f, .1f);
|
||||
info->setPosition({ sidePad / 2, m_obContentSize.height / 2 });
|
||||
this->addChild(info);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CustomSettingPlaceholderNode* CustomSettingPlaceholderNode::create(
|
||||
std::string const& key, float width
|
||||
) {
|
||||
auto ret = new CustomSettingPlaceholderNode;
|
||||
if (ret->init(key, width)) {
|
||||
ret->autorelease();
|
||||
return ret;
|
||||
}
|
||||
delete ret;
|
||||
return nullptr;
|
||||
}
|
|
@ -1,361 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/loader/Event.hpp>
|
||||
#include <Geode/utils/Result.hpp>
|
||||
#include <Geode/binding/CCMenuItemSpriteExtra.hpp>
|
||||
#include <Geode/binding/CCTextInputNode.hpp>
|
||||
#include <Geode/binding/Slider.hpp>
|
||||
#include <Geode/binding/SliderThumb.hpp>
|
||||
#include <Geode/loader/Setting.hpp>
|
||||
#include <Geode/loader/SettingNode.hpp>
|
||||
#include <Geode/ui/BasedButtonSprite.hpp>
|
||||
#include <Geode/ui/ColorPickPopup.hpp>
|
||||
#include <Geode/ui/InputNode.hpp>
|
||||
#include <Geode/ui/Popup.hpp>
|
||||
#include <Geode/utils/cocos.hpp>
|
||||
#include <Geode/utils/string.hpp>
|
||||
#include <Geode/loader/Mod.hpp>
|
||||
|
||||
using namespace geode::prelude;
|
||||
|
||||
#define IMPL_SETT_CREATE(type_) \
|
||||
static type_##SettingNode* create( \
|
||||
type_##SettingValue* value, float width \
|
||||
) { \
|
||||
auto ret = new type_##SettingNode; \
|
||||
if (ret->init(value, width)) { \
|
||||
ret->autorelease(); \
|
||||
return ret; \
|
||||
} \
|
||||
delete ret; \
|
||||
return nullptr; \
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class GeodeSettingNode : public SettingNode {
|
||||
public:
|
||||
using ValueType = typename T::ValueType;
|
||||
|
||||
protected:
|
||||
float m_width;
|
||||
float m_height;
|
||||
ValueType m_uncommittedValue;
|
||||
CCMenu* m_menu;
|
||||
CCLabelBMFont* m_nameLabel;
|
||||
CCLabelBMFont* m_errorLabel;
|
||||
CCMenuItemSpriteExtra* m_resetBtn;
|
||||
|
||||
bool init(GeodeSettingValue<T>* setting, float width) {
|
||||
if (!SettingNode::init(setting))
|
||||
return false;
|
||||
|
||||
m_width = width;
|
||||
m_height = this->setupHeight(setting);
|
||||
this->setContentSize({ width, m_height });
|
||||
|
||||
constexpr auto sidePad = 40.f;
|
||||
|
||||
m_uncommittedValue = setting->getValue();
|
||||
|
||||
auto name = setting->getDefinition().getDisplayName();
|
||||
|
||||
m_nameLabel = CCLabelBMFont::create(name.c_str(), "bigFont.fnt");
|
||||
m_nameLabel->setAnchorPoint({ .0f, .5f });
|
||||
m_nameLabel->limitLabelWidth(width / 2 - 50.f, .5f, .1f);
|
||||
m_nameLabel->setPosition({ sidePad / 2, m_obContentSize.height / 2 });
|
||||
this->addChild(m_nameLabel);
|
||||
|
||||
m_errorLabel = CCLabelBMFont::create("", "bigFont.fnt");
|
||||
m_errorLabel->setAnchorPoint({ .0f, .5f });
|
||||
m_errorLabel->limitLabelWidth(width / 2 - 50.f, .25f, .1f);
|
||||
m_errorLabel->setPosition({ sidePad / 2, m_obContentSize.height / 2 - 14.f });
|
||||
m_errorLabel->setColor({ 255, 100, 100 });
|
||||
m_errorLabel->setZOrder(5);
|
||||
this->addChild(m_errorLabel);
|
||||
|
||||
m_menu = CCMenu::create();
|
||||
m_menu->setPosition({ m_obContentSize.width - sidePad / 2, m_obContentSize.height / 2 }
|
||||
);
|
||||
this->addChild(m_menu);
|
||||
|
||||
float btnPos = 15.f;
|
||||
|
||||
if (setting->castDefinition().description) {
|
||||
auto infoSpr = CCSprite::createWithSpriteFrameName("GJ_infoIcon_001.png");
|
||||
infoSpr->setScale(.6f);
|
||||
|
||||
auto infoBtn = CCMenuItemSpriteExtra::create(
|
||||
infoSpr, this, menu_selector(GeodeSettingNode::onDescription)
|
||||
);
|
||||
infoBtn->setPosition(
|
||||
-m_obContentSize.width + sidePad + m_nameLabel->getScaledContentSize().width +
|
||||
btnPos,
|
||||
0.f
|
||||
);
|
||||
m_menu->addChild(infoBtn);
|
||||
|
||||
btnPos += 20.f;
|
||||
}
|
||||
|
||||
auto resetBtnSpr = CCSprite::createWithSpriteFrameName("reset-gold.png"_spr);
|
||||
resetBtnSpr->setScale(.5f);
|
||||
|
||||
m_resetBtn = CCMenuItemSpriteExtra::create(
|
||||
resetBtnSpr, this, menu_selector(GeodeSettingNode::onReset)
|
||||
);
|
||||
m_resetBtn->setPosition(
|
||||
-m_obContentSize.width + sidePad + m_nameLabel->getScaledContentSize().width +
|
||||
btnPos,
|
||||
.0f
|
||||
);
|
||||
m_menu->addChild(m_resetBtn);
|
||||
|
||||
m_menu->setTouchEnabled(true);
|
||||
|
||||
if (!this->setup(setting, width)) return false;
|
||||
|
||||
this->valueChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void onDescription(CCObject*) {
|
||||
FLAlertLayer::create(
|
||||
setting()->getDefinition().getDisplayName().c_str(),
|
||||
setting()->castDefinition().description.value(),
|
||||
"OK"
|
||||
)->show();
|
||||
}
|
||||
|
||||
void onReset(CCObject*) {
|
||||
createQuickPopup(
|
||||
"Reset",
|
||||
"Are you sure you want to <cr>reset</c> <cl>" +
|
||||
setting()->getDefinition().getDisplayName() +
|
||||
"</c> to <cy>default</c>?",
|
||||
"Cancel", "Reset",
|
||||
[this](auto, bool btn2) {
|
||||
if (btn2) {
|
||||
this->resetToDefault();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
virtual float setupHeight(GeodeSettingValue<T>* setting) const {
|
||||
return 40.f;
|
||||
}
|
||||
|
||||
virtual bool setup(GeodeSettingValue<T>* setting, float width) = 0;
|
||||
|
||||
virtual void valueChanged(bool updateText = true) {
|
||||
if (this->hasUncommittedChanges()) {
|
||||
m_nameLabel->setColor({0x11, 0xdd, 0x00});
|
||||
}
|
||||
else {
|
||||
m_nameLabel->setColor({0xff, 0xff, 0xff});
|
||||
}
|
||||
if (m_resetBtn) m_resetBtn->setVisible(this->hasNonDefaultValue());
|
||||
auto isValid = setting()->validate(m_uncommittedValue);
|
||||
if (!isValid) {
|
||||
m_errorLabel->setVisible(true);
|
||||
m_errorLabel->setString(isValid.unwrapErr().c_str());
|
||||
}
|
||||
else {
|
||||
m_errorLabel->setVisible(false);
|
||||
}
|
||||
this->dispatchChanged();
|
||||
}
|
||||
|
||||
GeodeSettingValue<T>* setting() {
|
||||
return static_cast<GeodeSettingValue<T>*>(m_value);
|
||||
}
|
||||
|
||||
public:
|
||||
void commit() override {
|
||||
setting()->setValue(m_uncommittedValue);
|
||||
m_uncommittedValue = setting()->getValue();
|
||||
this->valueChanged();
|
||||
this->dispatchCommitted();
|
||||
}
|
||||
|
||||
bool hasUncommittedChanges() override {
|
||||
return m_uncommittedValue != setting()->getValue();
|
||||
}
|
||||
|
||||
bool hasNonDefaultValue() override {
|
||||
return m_uncommittedValue != setting()->castDefinition().defaultValue;
|
||||
}
|
||||
|
||||
void resetToDefault() override {
|
||||
m_uncommittedValue = setting()->castDefinition().defaultValue;
|
||||
this->valueChanged();
|
||||
}
|
||||
};
|
||||
|
||||
class BoolSettingNode : public GeodeSettingNode<BoolSetting> {
|
||||
protected:
|
||||
CCMenuItemToggler* m_toggle;
|
||||
|
||||
void onToggle(CCObject*);
|
||||
void valueChanged(bool updateText) override;
|
||||
bool setup(BoolSettingValue* setting, float width) override;
|
||||
|
||||
public:
|
||||
IMPL_SETT_CREATE(Bool);
|
||||
};
|
||||
|
||||
class IntSettingNode :
|
||||
public GeodeSettingNode<IntSetting>,
|
||||
public TextInputDelegate
|
||||
{
|
||||
protected:
|
||||
TextInput* m_input = nullptr;
|
||||
CCLabelBMFont* m_label = nullptr;
|
||||
Slider* m_slider = nullptr;
|
||||
CCMenuItemSpriteExtra* m_decArrow = nullptr;
|
||||
CCMenuItemSpriteExtra* m_incArrow = nullptr;
|
||||
CCMenuItemSpriteExtra* m_bigDecArrow = nullptr;
|
||||
CCMenuItemSpriteExtra* m_bigIncArrow = nullptr;
|
||||
|
||||
void valueChanged(bool updateText) override;
|
||||
void textChanged(CCTextInputNode* input) override;
|
||||
|
||||
float setupHeight(IntSettingValue* setting) const override;
|
||||
bool setup(IntSettingValue* setting, float width) override;
|
||||
|
||||
public:
|
||||
void updateSlider();
|
||||
void updateLabel();
|
||||
|
||||
void onSlider(CCObject* slider);
|
||||
void onArrow(CCObject* sender);
|
||||
|
||||
IMPL_SETT_CREATE(Int);
|
||||
};
|
||||
|
||||
class FloatSettingNode :
|
||||
public GeodeSettingNode<FloatSetting>,
|
||||
public TextInputDelegate
|
||||
{
|
||||
protected:
|
||||
TextInput* m_input = nullptr;
|
||||
CCLabelBMFont* m_label = nullptr;
|
||||
Slider* m_slider = nullptr;
|
||||
CCMenuItemSpriteExtra* m_decArrow = nullptr;
|
||||
CCMenuItemSpriteExtra* m_incArrow = nullptr;
|
||||
CCMenuItemSpriteExtra* m_bigDecArrow = nullptr;
|
||||
CCMenuItemSpriteExtra* m_bigIncArrow = nullptr;
|
||||
|
||||
void valueChanged(bool updateText) override;
|
||||
void textChanged(CCTextInputNode* input) override;
|
||||
|
||||
float setupHeight(FloatSettingValue* setting) const override;
|
||||
bool setup(FloatSettingValue* setting, float width) override;
|
||||
|
||||
public:
|
||||
void updateSlider();
|
||||
void updateLabel();
|
||||
|
||||
void onSlider(CCObject* slider);
|
||||
void onArrow(CCObject* sender);
|
||||
|
||||
IMPL_SETT_CREATE(Float);
|
||||
};
|
||||
|
||||
class StringSettingNode :
|
||||
public GeodeSettingNode<StringSetting>,
|
||||
public TextInputDelegate
|
||||
{
|
||||
protected:
|
||||
TextInput* m_input = nullptr;
|
||||
CCLabelBMFont* m_label = nullptr;
|
||||
CCMenuItemSpriteExtra* m_prevBtn = nullptr;
|
||||
CCMenuItemSpriteExtra* m_nextBtn = nullptr;
|
||||
std::vector<std::string> m_options;
|
||||
int m_selectedOption = 0;
|
||||
float m_width;
|
||||
|
||||
void textChanged(CCTextInputNode* input) override;
|
||||
void valueChanged(bool updateText) override;
|
||||
void updateLabel();
|
||||
|
||||
void onArrow(CCObject* sender);
|
||||
|
||||
bool setup(StringSettingValue* setting, float width) override;
|
||||
|
||||
public:
|
||||
IMPL_SETT_CREATE(String);
|
||||
};
|
||||
|
||||
class FileSettingNode :
|
||||
public GeodeSettingNode<FileSetting>,
|
||||
public TextInputDelegate
|
||||
{
|
||||
protected:
|
||||
using FileTask = Task<Result<std::filesystem::path>>;
|
||||
|
||||
TextInput* m_input;
|
||||
EventListener<FileTask> m_pickListener;
|
||||
|
||||
void textChanged(CCTextInputNode* input) override;
|
||||
void valueChanged(bool updateText) override;
|
||||
void updateLabel();
|
||||
|
||||
void onPickFile(CCObject*);
|
||||
void onPickFileFinished(FileTask::Event* event);
|
||||
|
||||
bool setup(FileSettingValue* setting, float width) override;
|
||||
|
||||
public:
|
||||
IMPL_SETT_CREATE(File);
|
||||
};
|
||||
|
||||
class ColorSettingNode :
|
||||
public GeodeSettingNode<ColorSetting>,
|
||||
public ColorPickPopupDelegate {
|
||||
protected:
|
||||
ColorChannelSprite* m_colorSpr;
|
||||
|
||||
void valueChanged(bool updateText) override;
|
||||
void updateColor(ccColor4B const& color) override;
|
||||
|
||||
void onSelectColor(CCObject*);
|
||||
|
||||
bool setup(ColorSettingValue* setting, float width) override;
|
||||
|
||||
public:
|
||||
IMPL_SETT_CREATE(Color);
|
||||
};
|
||||
|
||||
class ColorAlphaSettingNode :
|
||||
public GeodeSettingNode<ColorAlphaSetting>,
|
||||
public ColorPickPopupDelegate {
|
||||
protected:
|
||||
ColorChannelSprite* m_colorSpr;
|
||||
|
||||
void valueChanged(bool updateText) override;
|
||||
void updateColor(ccColor4B const& color) override;
|
||||
|
||||
void onSelectColor(CCObject*);
|
||||
|
||||
bool setup(ColorAlphaSettingValue* setting, float width) override;
|
||||
|
||||
public:
|
||||
IMPL_SETT_CREATE(ColorAlpha);
|
||||
};
|
||||
|
||||
class CustomSettingPlaceholderNode : public SettingNode {
|
||||
protected:
|
||||
void commit() override;
|
||||
bool hasUncommittedChanges() override;
|
||||
bool hasNonDefaultValue() override;
|
||||
void resetToDefault() override;
|
||||
|
||||
bool init(std::string const& key, float width);
|
||||
|
||||
public:
|
||||
static CustomSettingPlaceholderNode* create(
|
||||
std::string const& key, float width
|
||||
);
|
||||
};
|
|
@ -1,7 +1,6 @@
|
|||
#include "ModSettingsPopup.hpp"
|
||||
#include <Geode/binding/ButtonSprite.hpp>
|
||||
#include <Geode/loader/Mod.hpp>
|
||||
#include <Geode/loader/Setting.hpp>
|
||||
#include <Geode/loader/ModSettingsManager.hpp>
|
||||
#include <Geode/ui/ScrollLayer.hpp>
|
||||
#include <Geode/utils/cocos.hpp>
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
#include <Geode/binding/CCTextInputNode.hpp>
|
||||
#include <Geode/binding/TextInputDelegate.hpp>
|
||||
#include <Geode/ui/InputNode.hpp>
|
||||
#include <Geode/ui/TextInput.hpp>
|
||||
#include <Geode/utils/cocos.hpp>
|
||||
|
||||
using namespace geode::prelude;
|
||||
|
||||
std::string InputNode::getString() {
|
||||
return m_input->getString();
|
||||
}
|
||||
|
||||
void InputNode::setString(std::string const& str) {
|
||||
m_input->setString(str);
|
||||
}
|
||||
|
||||
CCTextInputNode* InputNode::getInput() const {
|
||||
return m_input;
|
||||
}
|
||||
|
||||
CCScale9Sprite* InputNode::getBG() const {
|
||||
return m_bgSprite;
|
||||
}
|
||||
|
||||
void InputNode::setEnabled(bool enabled) {
|
||||
m_input->setMouseEnabled(enabled);
|
||||
m_input->setTouchEnabled(enabled);
|
||||
}
|
||||
|
||||
bool InputNode::init(
|
||||
float width, float height, char const* placeholder, char const* font, std::string const& filter,
|
||||
int maxCharCount
|
||||
) {
|
||||
if (!CCMenuItem::initWithTarget(this, nullptr)) return false;
|
||||
|
||||
m_bgSprite = cocos2d::extension::CCScale9Sprite::create(
|
||||
"square02b_001.png", { 0.0f, 0.0f, 80.0f, 80.0f }
|
||||
);
|
||||
m_bgSprite->setScale(.5f);
|
||||
m_bgSprite->setColor({ 0, 0, 0 });
|
||||
m_bgSprite->setOpacity(75);
|
||||
m_bgSprite->setContentSize({ width * 2, height * 2 });
|
||||
m_bgSprite->setPosition(width / 2, height / 2);
|
||||
this->addChild(m_bgSprite);
|
||||
|
||||
m_input = CCTextInputNode::create(width - 10.0f, height, placeholder, "Thonburi", 24, font);
|
||||
m_input->setLabelPlaceholderColor({ 150, 150, 150 });
|
||||
m_input->setLabelPlaceholderScale(.75f);
|
||||
m_input->setMaxLabelScale(.85f);
|
||||
m_input->setMaxLabelLength(maxCharCount);
|
||||
m_input->setPosition(width / 2, height / 2);
|
||||
m_input->setUserObject("fix-text-input", CCBool::create(true));
|
||||
if (filter.length()) {
|
||||
m_input->setAllowedChars(filter);
|
||||
}
|
||||
this->addChild(m_input);
|
||||
|
||||
this->setContentSize({ width, height });
|
||||
this->setAnchorPoint({ .5f, .5f });
|
||||
|
||||
this->setCascadeColorEnabled(true);
|
||||
this->setCascadeOpacityEnabled(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InputNode::init(
|
||||
float width, char const* placeholder, char const* font, std::string const& filter,
|
||||
int maxCharCount
|
||||
) {
|
||||
return init(width, 30.0f, placeholder, font, filter, maxCharCount);
|
||||
}
|
||||
|
||||
InputNode* InputNode::create(
|
||||
float width, char const* placeholder, char const* font, std::string const& filter,
|
||||
int maxCharCount
|
||||
) {
|
||||
auto pRet = new InputNode();
|
||||
|
||||
if (pRet->init(width, placeholder, font, filter, maxCharCount)) {
|
||||
pRet->autorelease();
|
||||
return pRet;
|
||||
}
|
||||
|
||||
delete pRet;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
InputNode* InputNode::create(float width, char const* placeholder, std::string const& filter) {
|
||||
return create(width, placeholder, "bigFont.fnt", filter, 69);
|
||||
}
|
||||
|
||||
InputNode* InputNode::create(
|
||||
float width, char const* placeholder, std::string const& filter, int maxCharCount
|
||||
) {
|
||||
return create(width, placeholder, "bigFont.fnt", filter, maxCharCount);
|
||||
}
|
||||
|
||||
InputNode* InputNode::create(float width, char const* placeholder, char const* font) {
|
||||
return create(width, placeholder, font, "", 69);
|
||||
}
|
||||
|
||||
InputNode* InputNode::create(float width, char const* placeholder) {
|
||||
return create(width, placeholder, "bigFont.fnt");
|
||||
}
|
|
@ -317,21 +317,9 @@ struct MDParser {
|
|||
auto split = splitOnce(s_lastImage, '?');
|
||||
s_lastImage = split.first;
|
||||
|
||||
// TODO: remove this in v4.0.0
|
||||
// check if this image is using the old format "my.mod/image.png&scale:0.5"
|
||||
// this will be deprecated and then removed in the future
|
||||
if (utils::string::contains(s_lastImage, "&")) {
|
||||
split = splitOnce(s_lastImage, '&');
|
||||
s_lastImage = split.first;
|
||||
imgArguments = ranges::map<decltype(imgArguments)>(utils::string::split(split.second, "&"), [&](auto str) {
|
||||
return splitOnce(str, ':');
|
||||
});
|
||||
} else {
|
||||
// new format "my.mod/image.png?scale=0.5"
|
||||
imgArguments = ranges::map<decltype(imgArguments)>(utils::string::split(split.second, "&"), [&](auto str) {
|
||||
return splitOnce(str, '=');
|
||||
});
|
||||
}
|
||||
imgArguments = ranges::map<decltype(imgArguments)>(utils::string::split(split.second, "&"), [&](auto str) {
|
||||
return splitOnce(str, '=');
|
||||
});
|
||||
|
||||
float spriteScale = 1.0f;
|
||||
float spriteWidth = 0.0f;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include <Geode/Loader.hpp>
|
||||
#include <Geode/modify/MenuLayer.hpp>
|
||||
#include <Geode/loader/SettingNode.hpp>
|
||||
#include <Geode/loader/Dispatch.hpp>
|
||||
#include <Geode/Bindings.hpp>
|
||||
#include "main.hpp"
|
||||
|
@ -30,119 +29,120 @@ constexpr Icon DEFAULT_ICON = Icon::Steve;
|
|||
|
||||
class MySettingValue;
|
||||
|
||||
class MySettingValue : public SettingValue {
|
||||
protected:
|
||||
Icon m_icon;
|
||||
// TODO: v4 (port to new settings)
|
||||
// class MySettingValue : public SettingValue {
|
||||
// protected:
|
||||
// Icon m_icon;
|
||||
|
||||
public:
|
||||
MySettingValue(std::string const& key, std::string const& modID, Icon icon)
|
||||
: SettingValue(key, modID), m_icon(icon) {}
|
||||
// public:
|
||||
// MySettingValue(std::string const& key, std::string const& modID, Icon icon)
|
||||
// : SettingValue(key, modID), m_icon(icon) {}
|
||||
|
||||
bool load(matjson::Value const& json) override {
|
||||
if (!json.is<int>()) return false;
|
||||
m_icon = static_cast<Icon>(json.as<int>());
|
||||
return true;
|
||||
}
|
||||
bool save(matjson::Value& json) const override {
|
||||
json = static_cast<int>(m_icon);
|
||||
return true;
|
||||
}
|
||||
SettingNode* createNode(float width) override;
|
||||
// bool load(matjson::Value const& json) override {
|
||||
// if (!json.is<int>()) return false;
|
||||
// m_icon = static_cast<Icon>(json.as<int>());
|
||||
// return true;
|
||||
// }
|
||||
// bool save(matjson::Value& json) const override {
|
||||
// json = static_cast<int>(m_icon);
|
||||
// return true;
|
||||
// }
|
||||
// SettingNode* createNode(float width) override;
|
||||
|
||||
void setIcon(Icon icon) {
|
||||
m_icon = icon;
|
||||
}
|
||||
Icon getIcon() const {
|
||||
return m_icon;
|
||||
}
|
||||
};
|
||||
// void setIcon(Icon icon) {
|
||||
// m_icon = icon;
|
||||
// }
|
||||
// Icon getIcon() const {
|
||||
// return m_icon;
|
||||
// }
|
||||
// };
|
||||
|
||||
class MySettingNode : public SettingNode {
|
||||
protected:
|
||||
Icon m_currentIcon;
|
||||
std::vector<CCSprite*> m_sprites;
|
||||
// class MySettingNode : public SettingNode {
|
||||
// protected:
|
||||
// Icon m_currentIcon;
|
||||
// std::vector<CCSprite*> m_sprites;
|
||||
|
||||
bool init(MySettingValue* value, float width) {
|
||||
if (!SettingNode::init(value))
|
||||
return false;
|
||||
// bool init(MySettingValue* value, float width) {
|
||||
// if (!SettingNode::init(value))
|
||||
// return false;
|
||||
|
||||
m_currentIcon = value->getIcon();
|
||||
this->setContentSize({ width, 40.f });
|
||||
// m_currentIcon = value->getIcon();
|
||||
// this->setContentSize({ width, 40.f });
|
||||
|
||||
auto menu = CCMenu::create();
|
||||
menu->setPosition(width / 2, 20.f);
|
||||
// auto menu = CCMenu::create();
|
||||
// menu->setPosition(width / 2, 20.f);
|
||||
|
||||
float x = -75.f;
|
||||
// float x = -75.f;
|
||||
|
||||
for (auto& [spr, icon] : {
|
||||
std::pair { "GJ_square01.png", Icon::Steve, },
|
||||
std::pair { "GJ_square02.png", Icon::Mike, },
|
||||
std::pair { "GJ_square03.png", Icon::LazarithTheDestroyerOfForsakenSouls, },
|
||||
std::pair { "GJ_square04.png", Icon::Geoff, },
|
||||
}) {
|
||||
auto btnSpr = CCSprite::create(spr);
|
||||
btnSpr->setScale(.7f);
|
||||
m_sprites.push_back(btnSpr);
|
||||
if (icon == m_currentIcon) {
|
||||
btnSpr->setColor({ 0, 255, 0 });
|
||||
} else {
|
||||
btnSpr->setColor({ 200, 200, 200 });
|
||||
}
|
||||
auto btn = CCMenuItemSpriteExtra::create(
|
||||
btnSpr, this, menu_selector(MySettingNode::onSelect)
|
||||
);
|
||||
btn->setTag(static_cast<int>(icon));
|
||||
btn->setPosition(x, 0);
|
||||
menu->addChild(btn);
|
||||
// for (auto& [spr, icon] : {
|
||||
// std::pair { "GJ_square01.png", Icon::Steve, },
|
||||
// std::pair { "GJ_square02.png", Icon::Mike, },
|
||||
// std::pair { "GJ_square03.png", Icon::LazarithTheDestroyerOfForsakenSouls, },
|
||||
// std::pair { "GJ_square04.png", Icon::Geoff, },
|
||||
// }) {
|
||||
// auto btnSpr = CCSprite::create(spr);
|
||||
// btnSpr->setScale(.7f);
|
||||
// m_sprites.push_back(btnSpr);
|
||||
// if (icon == m_currentIcon) {
|
||||
// btnSpr->setColor({ 0, 255, 0 });
|
||||
// } else {
|
||||
// btnSpr->setColor({ 200, 200, 200 });
|
||||
// }
|
||||
// auto btn = CCMenuItemSpriteExtra::create(
|
||||
// btnSpr, this, menu_selector(MySettingNode::onSelect)
|
||||
// );
|
||||
// btn->setTag(static_cast<int>(icon));
|
||||
// btn->setPosition(x, 0);
|
||||
// menu->addChild(btn);
|
||||
|
||||
x += 50.f;
|
||||
}
|
||||
// x += 50.f;
|
||||
// }
|
||||
|
||||
this->addChild(menu);
|
||||
// this->addChild(menu);
|
||||
|
||||
return true;
|
||||
}
|
||||
// return true;
|
||||
// }
|
||||
|
||||
void onSelect(CCObject* sender) {
|
||||
for (auto& spr : m_sprites) {
|
||||
spr->setColor({ 200, 200, 200 });
|
||||
}
|
||||
m_currentIcon = static_cast<Icon>(sender->getTag());
|
||||
static_cast<CCSprite*>(
|
||||
static_cast<CCMenuItemSpriteExtra*>(sender)->getNormalImage()
|
||||
)->setColor({ 0, 255, 0 });
|
||||
this->dispatchChanged();
|
||||
}
|
||||
// void onSelect(CCObject* sender) {
|
||||
// for (auto& spr : m_sprites) {
|
||||
// spr->setColor({ 200, 200, 200 });
|
||||
// }
|
||||
// m_currentIcon = static_cast<Icon>(sender->getTag());
|
||||
// static_cast<CCSprite*>(
|
||||
// static_cast<CCMenuItemSpriteExtra*>(sender)->getNormalImage()
|
||||
// )->setColor({ 0, 255, 0 });
|
||||
// this->dispatchChanged();
|
||||
// }
|
||||
|
||||
public:
|
||||
void commit() override {
|
||||
static_cast<MySettingValue*>(m_value)->setIcon(m_currentIcon);
|
||||
this->dispatchCommitted();
|
||||
}
|
||||
bool hasUncommittedChanges() override {
|
||||
return m_currentIcon != static_cast<MySettingValue*>(m_value)->getIcon();
|
||||
}
|
||||
bool hasNonDefaultValue() override {
|
||||
return m_currentIcon != DEFAULT_ICON;
|
||||
}
|
||||
void resetToDefault() override {
|
||||
m_currentIcon = DEFAULT_ICON;
|
||||
}
|
||||
// public:
|
||||
// void commit() override {
|
||||
// static_cast<MySettingValue*>(m_value)->setIcon(m_currentIcon);
|
||||
// this->dispatchCommitted();
|
||||
// }
|
||||
// bool hasUncommittedChanges() override {
|
||||
// return m_currentIcon != static_cast<MySettingValue*>(m_value)->getIcon();
|
||||
// }
|
||||
// bool hasNonDefaultValue() override {
|
||||
// return m_currentIcon != DEFAULT_ICON;
|
||||
// }
|
||||
// void resetToDefault() override {
|
||||
// m_currentIcon = DEFAULT_ICON;
|
||||
// }
|
||||
|
||||
static MySettingNode* create(MySettingValue* value, float width) {
|
||||
auto ret = new MySettingNode;
|
||||
if (ret->init(value, width)) {
|
||||
ret->autorelease();
|
||||
return ret;
|
||||
}
|
||||
delete ret;
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
// static MySettingNode* create(MySettingValue* value, float width) {
|
||||
// auto ret = new MySettingNode;
|
||||
// if (ret->init(value, width)) {
|
||||
// ret->autorelease();
|
||||
// return ret;
|
||||
// }
|
||||
// delete ret;
|
||||
// return nullptr;
|
||||
// }
|
||||
// };
|
||||
|
||||
SettingNode* MySettingValue::createNode(float width) {
|
||||
return MySettingNode::create(this, width);
|
||||
}
|
||||
// SettingNode* MySettingValue::createNode(float width) {
|
||||
// return MySettingNode::create(this, width);
|
||||
// }
|
||||
|
||||
struct MyMenuLayer : Modify<MyMenuLayer, MenuLayer> {
|
||||
void onMoreGames(CCObject*) {
|
||||
|
@ -161,7 +161,7 @@ struct MyMenuLayer : Modify<MyMenuLayer, MenuLayer> {
|
|||
};
|
||||
|
||||
$on_mod(Loaded) {
|
||||
Mod::get()->addCustomSetting<MySettingValue>("overcast-skies", DEFAULT_ICON);
|
||||
// Mod::get()->addCustomSetting<MySettingValue>("overcast-skies", DEFAULT_ICON);
|
||||
|
||||
(void)new EventListener(+[](GJGarageLayer* gl) {
|
||||
auto label = CCLabelBMFont::create("Dispatcher works!", "bigFont.fnt");
|
||||
|
|
Loading…
Reference in a new issue