mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-22 15:37:53 -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/Log.hpp"
|
||||||
#include "loader/Mod.hpp"
|
#include "loader/Mod.hpp"
|
||||||
#include "loader/ModEvent.hpp"
|
#include "loader/ModEvent.hpp"
|
||||||
#include "loader/Setting.hpp"
|
#include "loader/SettingV3.hpp"
|
||||||
#include "loader/Dirs.hpp"
|
#include "loader/Dirs.hpp"
|
||||||
|
|
||||||
#include <Geode/DefaultInclude.hpp>
|
#include <Geode/DefaultInclude.hpp>
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
#include "ui/EnterLayerEvent.hpp"
|
#include "ui/EnterLayerEvent.hpp"
|
||||||
#include "ui/BasedButtonSprite.hpp"
|
#include "ui/BasedButtonSprite.hpp"
|
||||||
#include "ui/IconButtonSprite.hpp"
|
#include "ui/IconButtonSprite.hpp"
|
||||||
#include "ui/InputNode.hpp"
|
#include "ui/Layout.hpp"
|
||||||
|
#include "ui/SpacerNode.hpp"
|
||||||
#include "ui/General.hpp"
|
#include "ui/General.hpp"
|
||||||
#include "ui/ListView.hpp"
|
#include "ui/ListView.hpp"
|
||||||
#include "ui/MDPopup.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 "../kazmath/include/kazmath/kazmath.h"
|
||||||
#include "../script_support/CCScriptSupport.h"
|
#include "../script_support/CCScriptSupport.h"
|
||||||
#include "../include/CCProtocols.h"
|
#include "../include/CCProtocols.h"
|
||||||
#include "Layout.hpp"
|
|
||||||
#include "../../loader/Event.hpp"
|
#include "../../loader/Event.hpp"
|
||||||
#include <Geode/utils/casts.hpp>
|
#include <Geode/utils/casts.hpp>
|
||||||
|
|
||||||
|
@ -45,6 +44,12 @@
|
||||||
#include <matjson.hpp>
|
#include <matjson.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace geode {
|
||||||
|
class Layout;
|
||||||
|
class LayoutOptions;
|
||||||
|
enum class Anchor;
|
||||||
|
}
|
||||||
|
|
||||||
NS_CC_BEGIN
|
NS_CC_BEGIN
|
||||||
|
|
||||||
class CCCamera;
|
class CCCamera;
|
||||||
|
@ -871,25 +876,13 @@ public:
|
||||||
private:
|
private:
|
||||||
friend class geode::modifier::FieldContainer;
|
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 geode::modifier::FieldContainer* getFieldContainer(char const* forClass);
|
||||||
GEODE_DLL void addEventListenerInternal(
|
GEODE_DLL void addEventListenerInternal(
|
||||||
std::string const& id,
|
std::string const& id,
|
||||||
geode::EventListenerProtocol* protocol
|
geode::EventListenerProtocol* protocol
|
||||||
);
|
);
|
||||||
|
|
||||||
#ifdef GEODE_EXPORTING
|
public:
|
||||||
[[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
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the string ID of this node
|
* Get the string ID of this node
|
||||||
* @returns The ID, or an empty string if the node has no ID.
|
* @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
|
* CCLayers / CCMenus, this will change where the children are located
|
||||||
* @note Geode addition
|
* @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
|
* Get the Layout for this node
|
||||||
* @returns The current layout, or nullptr if no layout is set
|
* @returns The current layout, or nullptr if no layout is set
|
||||||
* @note Geode addition
|
* @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
|
* Update the layout of this node using the current Layout. If no layout is
|
||||||
* set, nothing happens
|
* set, nothing happens
|
||||||
|
@ -1011,13 +1004,13 @@ public:
|
||||||
* @param apply Whether to update the layout of the parent node
|
* @param apply Whether to update the layout of the parent node
|
||||||
* @note Geode addition
|
* @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
|
* Get the layout options for this node
|
||||||
* @returns The current layout options, or nullptr if no options are set
|
* @returns The current layout options, or nullptr if no options are set
|
||||||
* @note Geode addition
|
* @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
|
* 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
|
* 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
|
* if no other layout is already specified
|
||||||
* @note Geode addition
|
* @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
|
* 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
|
* in its parent where the anchor specifies, and then the offset is used to
|
||||||
|
@ -1044,7 +1037,7 @@ public:
|
||||||
*/
|
*/
|
||||||
GEODE_DLL void addChildAtPosition(
|
GEODE_DLL void addChildAtPosition(
|
||||||
CCNode* child,
|
CCNode* child,
|
||||||
Anchor anchor,
|
geode::Anchor anchor,
|
||||||
CCPoint const& offset,
|
CCPoint const& offset,
|
||||||
CCPoint const& nodeAnchor,
|
CCPoint const& nodeAnchor,
|
||||||
bool useAnchorLayout = true
|
bool useAnchorLayout = true
|
||||||
|
@ -1057,7 +1050,7 @@ public:
|
||||||
* @param offset Where to place the child relative to the anchor
|
* @param offset Where to place the child relative to the anchor
|
||||||
* @note Geode addition
|
* @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
|
* Updates the anchored position of a child. Requires the child to already
|
||||||
* have a parent; if the child already has AnchorLayoutOptions set, those
|
* have a parent; if the child already has AnchorLayoutOptions set, those
|
||||||
|
@ -1068,7 +1061,7 @@ public:
|
||||||
* @note Geode addition
|
* @note Geode addition
|
||||||
*/
|
*/
|
||||||
GEODE_DLL void updateAnchoredPosition(
|
GEODE_DLL void updateAnchoredPosition(
|
||||||
Anchor anchor,
|
geode::Anchor anchor,
|
||||||
CCPoint const& offset,
|
CCPoint const& offset,
|
||||||
CCPoint const& nodeAnchor
|
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
|
// base_nodes
|
||||||
#include "../base_nodes/CCNode.h"
|
#include "../base_nodes/CCNode.h"
|
||||||
#include "../base_nodes/CCAtlasNode.h"
|
#include "../base_nodes/CCAtlasNode.h"
|
||||||
#include "../base_nodes/SpacerNode.hpp"
|
|
||||||
|
|
||||||
// cocoa
|
// cocoa
|
||||||
#include "../cocoa/CCAffineTransform.h"
|
#include "../cocoa/CCAffineTransform.h"
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include "Loader.hpp" // very nice circular dependency fix
|
#include "Loader.hpp" // very nice circular dependency fix
|
||||||
#include "Hook.hpp"
|
#include "Hook.hpp"
|
||||||
#include "ModMetadata.hpp"
|
#include "ModMetadata.hpp"
|
||||||
#include "Setting.hpp"
|
|
||||||
#include "SettingV3.hpp"
|
#include "SettingV3.hpp"
|
||||||
#include "Types.hpp"
|
#include "Types.hpp"
|
||||||
#include "Loader.hpp"
|
#include "Loader.hpp"
|
||||||
|
@ -108,8 +107,6 @@ namespace geode {
|
||||||
|
|
||||||
std::string getID() const;
|
std::string getID() const;
|
||||||
std::string getName() const;
|
std::string getName() const;
|
||||||
[[deprecated("Use Mod::getDevelopers instead")]]
|
|
||||||
std::string getDeveloper() const;
|
|
||||||
std::vector<std::string> getDevelopers() const;
|
std::vector<std::string> getDevelopers() const;
|
||||||
std::optional<std::string> getDescription() const;
|
std::optional<std::string> getDescription() const;
|
||||||
std::optional<std::string> getDetails() const;
|
std::optional<std::string> getDetails() const;
|
||||||
|
@ -137,17 +134,6 @@ namespace geode {
|
||||||
std::vector<Mod*> getDependants() const;
|
std::vector<Mod*> getDependants() const;
|
||||||
#endif
|
#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>>;
|
using CheckUpdatesTask = Task<Result<std::optional<VersionInfo>, std::string>>;
|
||||||
/**
|
/**
|
||||||
* Check if this Mod has updates available on the mods index. If
|
* Check if this Mod has updates available on the mods index. If
|
||||||
|
@ -189,12 +175,6 @@ namespace geode {
|
||||||
std::vector<std::string> getSettingKeys() const;
|
std::vector<std::string> getSettingKeys() const;
|
||||||
bool hasSetting(std::string_view const key) 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?
|
// todo in v4: possibly rename this to getSetting?
|
||||||
/**
|
/**
|
||||||
* Get the definition of a setting, or null if the setting was not found,
|
* 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;
|
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
|
* Register a custom setting type. See
|
||||||
* [the setting docs](https://docs.geode-sdk.org/mods/settings) for more
|
* [the setting docs](https://docs.geode-sdk.org/mods/settings) for more
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include "../utils/Result.hpp"
|
#include "../utils/Result.hpp"
|
||||||
#include "../utils/VersionInfo.hpp"
|
#include "../utils/VersionInfo.hpp"
|
||||||
#include "Setting.hpp"
|
|
||||||
#include "Types.hpp"
|
#include "Types.hpp"
|
||||||
|
|
||||||
#include <matjson.hpp>
|
#include <matjson.hpp>
|
||||||
|
@ -123,13 +122,6 @@ namespace geode {
|
||||||
* character set.
|
* character set.
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] std::string getName() const;
|
[[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
|
* The developers of this mod
|
||||||
*/
|
*/
|
||||||
|
@ -155,11 +147,6 @@ namespace geode {
|
||||||
* (see MDTextArea for more info)
|
* (see MDTextArea for more info)
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] std::optional<std::string> getSupportInfo() const;
|
[[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
|
* Get the links (related websites / servers / etc.) for this mod
|
||||||
*/
|
*/
|
||||||
|
@ -180,11 +167,6 @@ namespace geode {
|
||||||
* Mod spritesheet names
|
* Mod spritesheet names
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] std::vector<std::string> getSpritesheets() const;
|
[[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
|
* Mod settings
|
||||||
* @note Not a map because insertion order must be preserved
|
* @note Not a map because insertion order must be preserved
|
||||||
|
@ -237,8 +219,6 @@ namespace geode {
|
||||||
void setDependencies(std::vector<Dependency> const& value);
|
void setDependencies(std::vector<Dependency> const& value);
|
||||||
void setIncompatibilities(std::vector<Incompatibility> const& value);
|
void setIncompatibilities(std::vector<Incompatibility> const& value);
|
||||||
void setSpritesheets(std::vector<std::string> 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 setSettings(std::vector<std::pair<std::string, matjson::Value>> const& value);
|
||||||
void setTags(std::unordered_set<std::string> const& value);
|
void setTags(std::unordered_set<std::string> const& value);
|
||||||
void setNeedsEarlyLoad(bool 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 "../DefaultInclude.hpp"
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <cocos2d.h>
|
#include <cocos2d.h>
|
||||||
// todo: remove this header in 4.0.0
|
|
||||||
#include "Setting.hpp"
|
|
||||||
#include "../utils/cocos.hpp"
|
#include "../utils/cocos.hpp"
|
||||||
|
#include "../utils/file.hpp"
|
||||||
// this unfortunately has to be included because of C++ templates
|
// this unfortunately has to be included because of C++ templates
|
||||||
#include "../utils/JsonValidation.hpp"
|
#include "../utils/JsonValidation.hpp"
|
||||||
#include "../utils/function.hpp"
|
#include "../utils/function.hpp"
|
||||||
|
|
||||||
// todo in v4: this can be removed as well as the friend decl in LegacyCustomSettingV3
|
|
||||||
class LegacyCustomSettingToV3Node;
|
|
||||||
class ModSettingsPopup;
|
class ModSettingsPopup;
|
||||||
|
|
||||||
namespace geode {
|
namespace geode {
|
||||||
|
@ -183,17 +180,6 @@ namespace geode {
|
||||||
* Reset this setting's value back to its original value
|
* Reset this setting's value back to its original value
|
||||||
*/
|
*/
|
||||||
virtual void reset() = 0;
|
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>>(
|
using SettingGenerator = std::function<Result<std::shared_ptr<SettingV3>>(
|
||||||
|
@ -357,37 +343,6 @@ namespace geode {
|
||||||
void reset() override;
|
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> {
|
class GEODE_DLL BoolSettingV3 final : public SettingBaseValueV3<bool> {
|
||||||
private:
|
private:
|
||||||
class Impl;
|
class Impl;
|
||||||
|
@ -404,9 +359,6 @@ namespace geode {
|
||||||
Result<> isValid(bool value) const override;
|
Result<> isValid(bool value) const override;
|
||||||
|
|
||||||
SettingNodeV3* createNode(float width) 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> {
|
class GEODE_DLL IntSettingV3 final : public SettingBaseValueV3<int64_t> {
|
||||||
|
@ -436,9 +388,6 @@ namespace geode {
|
||||||
bool isInputEnabled() const;
|
bool isInputEnabled() const;
|
||||||
|
|
||||||
SettingNodeV3* createNode(float width) override;
|
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> {
|
class GEODE_DLL FloatSettingV3 final : public SettingBaseValueV3<double> {
|
||||||
|
@ -468,9 +417,6 @@ namespace geode {
|
||||||
bool isInputEnabled() const;
|
bool isInputEnabled() const;
|
||||||
|
|
||||||
SettingNodeV3* createNode(float width) override;
|
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> {
|
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;
|
std::optional<std::vector<std::string>> getEnumOptions() const;
|
||||||
|
|
||||||
SettingNodeV3* createNode(float width) override;
|
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&> {
|
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;
|
std::optional<std::vector<utils::file::FilePickOptions::Filter>> getFilters() const;
|
||||||
|
|
||||||
SettingNodeV3* createNode(float width) override;
|
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> {
|
class GEODE_DLL Color3BSettingV3 final : public SettingBaseValueV3<cocos2d::ccColor3B> {
|
||||||
|
@ -540,9 +480,6 @@ namespace geode {
|
||||||
Result<> isValid(cocos2d::ccColor3B value) const override;
|
Result<> isValid(cocos2d::ccColor3B value) const override;
|
||||||
|
|
||||||
SettingNodeV3* createNode(float width) 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> {
|
class GEODE_DLL Color4BSettingV3 final : public SettingBaseValueV3<cocos2d::ccColor4B> {
|
||||||
|
@ -561,9 +498,6 @@ namespace geode {
|
||||||
Result<> isValid(cocos2d::ccColor4B value) const override;
|
Result<> isValid(cocos2d::ccColor4B value) const override;
|
||||||
|
|
||||||
SettingNodeV3* createNode(float width) 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 {
|
class GEODE_DLL SettingNodeV3 : public cocos2d::CCNode {
|
||||||
|
|
|
@ -133,11 +133,6 @@ namespace geode {
|
||||||
*/
|
*/
|
||||||
GEODE_DLL void openSupportPopup(Mod* mod);
|
GEODE_DLL void openSupportPopup(Mod* mod);
|
||||||
GEODE_DLL void openSupportPopup(ModMetadata const& metadata);
|
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)
|
* 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
|
#pragma once
|
||||||
|
|
||||||
#include "../include/ccMacros.h"
|
#include <cocos2d.h>
|
||||||
#include "../cocoa/CCAffineTransform.h"
|
#include <Geode/platform/platform.hpp>
|
||||||
#include "../cocoa/CCArray.h"
|
#include <optional>
|
||||||
#include <Geode/platform/platform.hpp>
|
#include <memory>
|
||||||
#include <optional>
|
|
||||||
#include <memory>
|
namespace geode {
|
||||||
|
|
||||||
NS_CC_BEGIN
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable: 4275)
|
||||||
class CCNode;
|
|
||||||
|
/**
|
||||||
#pragma warning(push)
|
* Layouts automatically handle the positioning of nodes. Use CCNode::setLayout
|
||||||
#pragma warning(disable: 4275)
|
* 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
|
||||||
* Layouts automatically handle the positioning of nodes. Use CCNode::setLayout
|
* of layout you can inherit from the Layout class.
|
||||||
* 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
|
class GEODE_DLL Layout : public cocos2d::CCObject {
|
||||||
* RowLayout, ColumnLayout, and GridLayout, but if you need a different kind
|
protected:
|
||||||
* of layout you can inherit from the Layout class.
|
cocos2d::CCArray* getNodesToPosition(cocos2d::CCNode* forNode) const;
|
||||||
*/
|
|
||||||
class GEODE_DLL Layout : public CCObject {
|
bool m_ignoreInvisibleChildren = false;
|
||||||
protected:
|
|
||||||
CCArray* getNodesToPosition(CCNode* forNode) const;
|
public:
|
||||||
|
/**
|
||||||
bool m_ignoreInvisibleChildren = false;
|
* 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
|
||||||
public:
|
* 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
|
||||||
* Automatically apply the layout's positioning on a set of nodes
|
* rescaled to better fit its contents
|
||||||
* @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
|
virtual void apply(cocos2d::CCNode* on) = 0;
|
||||||
* respected as a boundary the layout shouldn't overflow. The node may be
|
|
||||||
* rescaled to better fit its contents
|
/**
|
||||||
*/
|
* Get how much space this layout would like to take up for a given target
|
||||||
virtual void apply(CCNode* on) = 0;
|
*/
|
||||||
|
virtual cocos2d::CCSize getSizeHint(cocos2d::CCNode* on) const = 0;
|
||||||
/**
|
|
||||||
* Get how much space this layout would like to take up for a given target
|
void ignoreInvisibleChildren(bool ignore);
|
||||||
*/
|
bool isIgnoreInvisibleChildren() const;
|
||||||
virtual CCSize getSizeHint(CCNode* on) const = 0;
|
|
||||||
|
virtual ~Layout() = default;
|
||||||
void ignoreInvisibleChildren(bool ignore);
|
};
|
||||||
bool isIgnoreInvisibleChildren() const;
|
|
||||||
|
class GEODE_DLL LayoutOptions : public cocos2d::CCObject {
|
||||||
virtual ~Layout() = default;
|
public:
|
||||||
};
|
virtual ~LayoutOptions() = default;
|
||||||
|
};
|
||||||
class GEODE_DLL LayoutOptions : public CCObject {
|
|
||||||
public:
|
/**
|
||||||
virtual ~LayoutOptions() = default;
|
* The direction of an AxisLayout
|
||||||
};
|
*/
|
||||||
|
enum class Axis {
|
||||||
/**
|
Row,
|
||||||
* The direction of an AxisLayout
|
Column,
|
||||||
*/
|
};
|
||||||
enum class Axis {
|
|
||||||
Row,
|
/**
|
||||||
Column,
|
* Specifies the alignment of something in an AxisLayout
|
||||||
};
|
*/
|
||||||
|
enum class AxisAlignment {
|
||||||
/**
|
// Align items to the start
|
||||||
* Specifies the alignment of something in an AxisLayout
|
// |ooo......|
|
||||||
*/
|
Start,
|
||||||
enum class AxisAlignment {
|
// All items are centered
|
||||||
// Align items to the start
|
// |...ooo...|
|
||||||
// |ooo......|
|
Center,
|
||||||
Start,
|
// Align items to the end
|
||||||
// All items are centered
|
// |......ooo|
|
||||||
// |...ooo...|
|
End,
|
||||||
Center,
|
// Each item gets the same portion from the layout (disregards gap)
|
||||||
// Align items to the end
|
// |.o..o..o.|
|
||||||
// |......ooo|
|
Even,
|
||||||
End,
|
// Space between each item is the same (disregards gap)
|
||||||
// Each item gets the same portion from the layout (disregards gap)
|
// |o...o...o|
|
||||||
// |.o..o..o.|
|
Between,
|
||||||
Even,
|
};
|
||||||
// Space between each item is the same (disregards gap)
|
|
||||||
// |o...o...o|
|
constexpr float AXISLAYOUT_DEFAULT_MIN_SCALE = 0.65f;
|
||||||
Between,
|
constexpr int AXISLAYOUT_DEFAULT_PRIORITY = 0;
|
||||||
};
|
|
||||||
|
/**
|
||||||
constexpr float AXISLAYOUT_DEFAULT_MIN_SCALE = 0.65f;
|
* Options for controlling the behaviour of individual nodes in an AxisLayout
|
||||||
constexpr int AXISLAYOUT_DEFAULT_PRIORITY = 0;
|
* @example
|
||||||
|
* auto node = CCNode::create();
|
||||||
/**
|
* // this node will have 10 units of spacing between it and the next one
|
||||||
* Options for controlling the behaviour of individual nodes in an AxisLayout
|
* node->setLayoutOptions(
|
||||||
* @example
|
* AxisLayoutOptions::create()
|
||||||
* auto node = CCNode::create();
|
* ->setNextGap(10.f)
|
||||||
* // this node will have 10 units of spacing between it and the next one
|
* );
|
||||||
* node->setLayoutOptions(
|
* someNodeWithALayout->addChild(node);
|
||||||
* AxisLayoutOptions::create()
|
*/
|
||||||
* ->setNextGap(10.f)
|
class GEODE_DLL AxisLayoutOptions : public LayoutOptions {
|
||||||
* );
|
protected:
|
||||||
* someNodeWithALayout->addChild(node);
|
class Impl;
|
||||||
*/
|
|
||||||
class GEODE_DLL AxisLayoutOptions : public LayoutOptions {
|
std::unique_ptr<Impl> m_impl;
|
||||||
protected:
|
|
||||||
class Impl;
|
AxisLayoutOptions();
|
||||||
|
|
||||||
std::unique_ptr<Impl> m_impl;
|
public:
|
||||||
|
static AxisLayoutOptions* create();
|
||||||
AxisLayoutOptions();
|
|
||||||
|
virtual ~AxisLayoutOptions();
|
||||||
public:
|
|
||||||
static AxisLayoutOptions* create();
|
std::optional<bool> getAutoScale() const;
|
||||||
|
// @note Use hasExplicitMaxScale to know if the default scale has been overwritten
|
||||||
virtual ~AxisLayoutOptions();
|
float getMaxScale() const;
|
||||||
|
// @note Use hasExplicitMinScale to know if the default scale has been overwritten
|
||||||
std::optional<bool> getAutoScale() const;
|
float getMinScale() const;
|
||||||
// @note Use hasExplicitMaxScale to know if the default scale has been overwritten
|
bool hasExplicitMaxScale() const;
|
||||||
float getMaxScale() const;
|
bool hasExplicitMinScale() const;
|
||||||
// @note Use hasExplicitMinScale to know if the default scale has been overwritten
|
float getRelativeScale() const;
|
||||||
float getMinScale() const;
|
std::optional<float> getLength() const;
|
||||||
bool hasExplicitMaxScale() const;
|
std::optional<float> getPrevGap() const;
|
||||||
bool hasExplicitMinScale() const;
|
std::optional<float> getNextGap() const;
|
||||||
float getRelativeScale() const;
|
bool getBreakLine() const;
|
||||||
std::optional<float> getLength() const;
|
bool getSameLine() const;
|
||||||
std::optional<float> getPrevGap() const;
|
int getScalePriority() const;
|
||||||
std::optional<float> getNextGap() const;
|
std::optional<AxisAlignment> getCrossAxisAlignment() const;
|
||||||
bool getBreakLine() const;
|
|
||||||
bool getSameLine() const;
|
/**
|
||||||
int getScalePriority() const;
|
* Set the limits to what the node can be scaled to. Passing `std::nullopt`
|
||||||
std::optional<AxisAlignment> getCrossAxisAlignment() const;
|
* uses the parent layout's default min / max scales
|
||||||
|
*/
|
||||||
/**
|
AxisLayoutOptions* setScaleLimits(std::optional<float> min, std::optional<float> max);
|
||||||
* Set the maximum scale this node can be if it's contained in an
|
|
||||||
* auto-scaled layout. Default is 1
|
/**
|
||||||
*/
|
* Set the relative scale of this node compared to other nodes if it's
|
||||||
[[deprecated("Use AxisLayoutOptions::setScaleLimits")]]
|
* contained in an auto-scaled layout. Default is 1
|
||||||
AxisLayoutOptions* setMaxScale(float scale);
|
*/
|
||||||
|
AxisLayoutOptions* setRelativeScale(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
|
* Set auto-scaling for this node, overriding the layout's auto-scale
|
||||||
*/
|
* setting. If nullopt, the layout's auto-scale options will be used
|
||||||
[[deprecated("Use AxisLayoutOptions::setScaleLimits")]]
|
*/
|
||||||
AxisLayoutOptions* setMinScale(float scale);
|
AxisLayoutOptions* setAutoScale(std::optional<bool> enabled);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the limits to what the node can be scaled to. Passing `std::nullopt`
|
* Set an absolute length for this node. If nullopt, the length will be
|
||||||
* uses the parent layout's default min / max scales
|
* dynamically calculated based on content size
|
||||||
*/
|
*/
|
||||||
AxisLayoutOptions* setScaleLimits(std::optional<float> min, std::optional<float> max);
|
AxisLayoutOptions* setLength(std::optional<float> length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the relative scale of this node compared to other nodes if it's
|
* Override the default gap in the layout between this node and the
|
||||||
* contained in an auto-scaled layout. Default is 1
|
* previous one. If nullopt, the default gap of the layout will be used
|
||||||
*/
|
*/
|
||||||
AxisLayoutOptions* setRelativeScale(float scale);
|
AxisLayoutOptions* setPrevGap(std::optional<float> gap);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set auto-scaling for this node, overriding the layout's auto-scale
|
* Override the default gap in the layout between this node and the next
|
||||||
* setting. If nullopt, the layout's auto-scale options will be used
|
* one. If nullopt, the default gap of the layout will be used
|
||||||
*/
|
*/
|
||||||
AxisLayoutOptions* setAutoScale(std::optional<bool> enabled);
|
AxisLayoutOptions* setNextGap(std::optional<float> gap);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set an absolute length for this node. If nullopt, the length will be
|
* If enabled, the node will always cause a growable axis layout to break
|
||||||
* dynamically calculated based on content size
|
* into a new line even if the current line could've fit the next node
|
||||||
*/
|
*/
|
||||||
AxisLayoutOptions* setLength(std::optional<float> length);
|
AxisLayoutOptions* setBreakLine(bool enable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override the default gap in the layout between this node and the
|
* If enabled, the node will be forced to be on the same line as the
|
||||||
* previous one. If nullopt, the default gap of the layout will be used
|
* previous node even if doing this would overflow
|
||||||
*/
|
*/
|
||||||
AxisLayoutOptions* setPrevGap(std::optional<float> gap);
|
AxisLayoutOptions* setSameLine(bool enable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override the default gap in the layout between this node and the next
|
* Set the scale priority of this node. Nodes with higher priority will be
|
||||||
* one. If nullopt, the default gap of the layout will be used
|
* scaled down first before nodes with lower priority when an auto-scaled
|
||||||
*/
|
* layout attempts to fit its contents. Default is
|
||||||
AxisLayoutOptions* setNextGap(std::optional<float> gap);
|
* AXISLAYOUT_DEFAULT_PRIORITY
|
||||||
|
* @note For optimal performance, the priorities should all be close to
|
||||||
/**
|
* each other with no gaps
|
||||||
* 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* setScalePriority(int priority);
|
||||||
*/
|
|
||||||
AxisLayoutOptions* setBreakLine(bool enable);
|
/**
|
||||||
|
* Override the cross axis alignment for this node in the layout
|
||||||
/**
|
*/
|
||||||
* If enabled, the node will be forced to be on the same line as the
|
AxisLayoutOptions* setCrossAxisAlignment(std::optional<AxisAlignment> alignment);
|
||||||
* previous node even if doing this would overflow
|
};
|
||||||
*/
|
|
||||||
AxisLayoutOptions* setSameLine(bool enable);
|
/**
|
||||||
|
* 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
|
||||||
* Set the scale priority of this node. Nodes with higher priority will be
|
* RowLayout and ColumnLayout classes function as simple thin wrappers over
|
||||||
* scaled down first before nodes with lower priority when an auto-scaled
|
* AxisLayout. The positioning of individual nodes in the layout can be
|
||||||
* layout attempts to fit its contents. Default is
|
* further controlled using AxisLayoutOptions
|
||||||
* AXISLAYOUT_DEFAULT_PRIORITY
|
* @warning Calculating layouts can get increasingly expensive for large
|
||||||
* @note For optimal performance, the priorities should all be close to
|
* amounts of child nodes being fit into a small space - while this should
|
||||||
* each other with no gaps
|
* 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
|
||||||
AxisLayoutOptions* setScalePriority(int priority);
|
* call CCNode::updateLayout every frame for a menu with thousands of children
|
||||||
|
* @example
|
||||||
/**
|
* auto menu = CCMenu::create();
|
||||||
* Override the cross axis alignment for this node in the layout
|
* // 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
|
||||||
AxisLayoutOptions* setCrossAxisAlignment(std::optional<AxisAlignment> alignment);
|
* // aligned to the left. The menu automatically will automatically grow in
|
||||||
};
|
* // height to fit all the rows
|
||||||
|
* menu->setLayout(
|
||||||
/**
|
* RowLayout::create()
|
||||||
* A multi-purpose dynamic layout for arranging nodes along an axis. Can be
|
* ->setGap(10.f)
|
||||||
* used to arrange nodes in a single line, a grid, or a flex layout. The
|
* ->setGrowCrossAxis(true)
|
||||||
* RowLayout and ColumnLayout classes function as simple thin wrappers over
|
* ->setAxisAlignment(AxisAlignment::Start)
|
||||||
* AxisLayout. The positioning of individual nodes in the layout can be
|
* );
|
||||||
* further controlled using AxisLayoutOptions
|
* menu->setContentSize({ 200.f, 0.f });
|
||||||
* @warning Calculating layouts can get increasingly expensive for large
|
* menu->addChild(...);
|
||||||
* amounts of child nodes being fit into a small space - while this should
|
* menu->updateLayout();
|
||||||
* 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
|
class GEODE_DLL AxisLayout : public Layout {
|
||||||
* call CCNode::updateLayout every frame for a menu with thousands of children
|
protected:
|
||||||
* @example
|
class Impl;
|
||||||
* auto menu = CCMenu::create();
|
|
||||||
* // The menu's children will be arranged horizontally, unless they overflow
|
std::unique_ptr<Impl> m_impl;
|
||||||
* // 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
|
AxisLayout(Axis);
|
||||||
* // height to fit all the rows
|
|
||||||
* menu->setLayout(
|
public:
|
||||||
* RowLayout::create()
|
/**
|
||||||
* ->setGap(10.f)
|
* Create a new AxisLayout. Note that this class is not automatically
|
||||||
* ->setGrowCrossAxis(true)
|
* managed by default, so you must assign it to a CCNode or manually
|
||||||
* ->setAxisAlignment(AxisAlignment::Start)
|
* manage the memory yourself. See the chainable setters on AxisLayout for
|
||||||
* );
|
* what options you can customize for the layout
|
||||||
* menu->setContentSize({ 200.f, 0.f });
|
* @param axis The direction of the layout
|
||||||
* menu->addChild(...);
|
* @note For convenience, you can use the RowLayout and ColumnLayout
|
||||||
* menu->updateLayout();
|
* classes, which are just thin wrappers over AxisLayout
|
||||||
*/
|
* @returns Created AxisLayout
|
||||||
class GEODE_DLL AxisLayout : public Layout {
|
*/
|
||||||
protected:
|
static AxisLayout* create(Axis axis = Axis::Row);
|
||||||
class Impl;
|
|
||||||
|
virtual ~AxisLayout();
|
||||||
std::unique_ptr<Impl> m_impl;
|
|
||||||
|
void apply(cocos2d::CCNode* on) override;
|
||||||
AxisLayout(Axis);
|
cocos2d::CCSize getSizeHint(cocos2d::CCNode* on) const override;
|
||||||
|
|
||||||
public:
|
Axis getAxis() const;
|
||||||
/**
|
AxisAlignment getAxisAlignment() const;
|
||||||
* Create a new AxisLayout. Note that this class is not automatically
|
AxisAlignment getCrossAxisAlignment() const;
|
||||||
* managed by default, so you must assign it to a CCNode or manually
|
AxisAlignment getCrossAxisLineAlignment() const;
|
||||||
* manage the memory yourself. See the chainable setters on AxisLayout for
|
float getGap() const;
|
||||||
* what options you can customize for the layout
|
bool getAxisReverse() const;
|
||||||
* @param axis The direction of the layout
|
bool getCrossAxisReverse() const;
|
||||||
* @note For convenience, you can use the RowLayout and ColumnLayout
|
bool getAutoScale() const;
|
||||||
* classes, which are just thin wrappers over AxisLayout
|
bool getGrowCrossAxis() const;
|
||||||
* @returns Created AxisLayout
|
bool getCrossAxisOverflow() const;
|
||||||
*/
|
std::optional<float> getAutoGrowAxis() const;
|
||||||
static AxisLayout* create(Axis axis = Axis::Row);
|
float getDefaultMinScale() const;
|
||||||
|
float getDefaultMaxScale() const;
|
||||||
virtual ~AxisLayout();
|
|
||||||
|
AxisLayout* setAxis(Axis axis);
|
||||||
void apply(CCNode* on) override;
|
/**
|
||||||
CCSize getSizeHint(CCNode* on) const override;
|
* Sets where to align the target node's children on the main axis (X-axis
|
||||||
|
* for Row, Y-axis for Column)
|
||||||
Axis getAxis() const;
|
*/
|
||||||
AxisAlignment getAxisAlignment() const;
|
AxisLayout* setAxisAlignment(AxisAlignment align);
|
||||||
AxisAlignment getCrossAxisAlignment() const;
|
/**
|
||||||
AxisAlignment getCrossAxisLineAlignment() const;
|
* Sets where to align the target node's children on the cross-axis (Y-axis
|
||||||
float getGap() const;
|
* for Row, X-axis for Column)
|
||||||
bool getAxisReverse() const;
|
*/
|
||||||
bool getCrossAxisReverse() const;
|
AxisLayout* setCrossAxisAlignment(AxisAlignment align);
|
||||||
bool getAutoScale() const;
|
/**
|
||||||
bool getGrowCrossAxis() const;
|
* Sets where to align the target node's children on the cross-axis for
|
||||||
bool getCrossAxisOverflow() const;
|
* each row (Y-axis for Row, X-axis for Column)
|
||||||
std::optional<float> getAutoGrowAxis() const;
|
*/
|
||||||
float getDefaultMinScale() const;
|
AxisLayout* setCrossAxisLineAlignment(AxisAlignment align);
|
||||||
float getDefaultMaxScale() const;
|
/**
|
||||||
|
* The spacing between the children of the node this layout applies to.
|
||||||
AxisLayout* setAxis(Axis axis);
|
* Measured as the space between their edges, not centres. Does not apply
|
||||||
/**
|
* on the main / cross axis if their alignment is AxisAlignment::Even
|
||||||
* Sets where to align the target node's children on the main axis (X-axis
|
*/
|
||||||
* for Row, Y-axis for Column)
|
AxisLayout* setGap(float gap);
|
||||||
*/
|
/**
|
||||||
AxisLayout* setAxisAlignment(AxisAlignment align);
|
* Whether to reverse the direction of the children in this layout or not
|
||||||
/**
|
*/
|
||||||
* Sets where to align the target node's children on the cross-axis (Y-axis
|
AxisLayout* setAxisReverse(bool reverse);
|
||||||
* for Row, X-axis for Column)
|
/**
|
||||||
*/
|
* Whether to reverse the direction of the rows on the cross-axis or not
|
||||||
AxisLayout* setCrossAxisAlignment(AxisAlignment align);
|
*/
|
||||||
/**
|
AxisLayout* setCrossAxisReverse(bool reverse);
|
||||||
* Sets where to align the target node's children on the cross-axis for
|
/**
|
||||||
* each row (Y-axis for Row, X-axis for Column)
|
* 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* setCrossAxisLineAlignment(AxisAlignment align);
|
*/
|
||||||
/**
|
AxisLayout* setAutoScale(bool enable);
|
||||||
* The spacing between the children of the node this layout applies to.
|
/**
|
||||||
* Measured as the space between their edges, not centres. Does not apply
|
* If true, if the main axis overflows extra nodes will be placed on new
|
||||||
* on the main / cross axis if their alignment is AxisAlignment::Even
|
* rows/columns on the cross-axis
|
||||||
*/
|
*/
|
||||||
AxisLayout* setGap(float gap);
|
AxisLayout* setGrowCrossAxis(bool expand);
|
||||||
/**
|
/**
|
||||||
* Whether to reverse the direction of the children in this layout or not
|
* If true, the cross-axis content size of the target node will be
|
||||||
*/
|
* automatically adjusted to fit the children
|
||||||
AxisLayout* setAxisReverse(bool reverse);
|
*/
|
||||||
/**
|
AxisLayout* setCrossAxisOverflow(bool allow);
|
||||||
* Whether to reverse the direction of the rows on the cross-axis or not
|
/**
|
||||||
*/
|
* If not `std::nullopt`, then the axis will be automatically extended to
|
||||||
AxisLayout* setCrossAxisReverse(bool reverse);
|
* fit all items in a single row whose minimum length is the specified.
|
||||||
/**
|
* Useful for scrollable list layer contents
|
||||||
* 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* setAutoGrowAxis(std::optional<float> allowAndMinLength);
|
||||||
*/
|
/**
|
||||||
AxisLayout* setAutoScale(bool enable);
|
* Set the default minimum/maximum scales for nodes in the layout
|
||||||
/**
|
*/
|
||||||
* If true, if the main axis overflows extra nodes will be placed on new
|
AxisLayout* setDefaultScaleLimits(float min, float max);
|
||||||
* rows/columns on the cross-axis
|
};
|
||||||
*/
|
|
||||||
AxisLayout* setGrowCrossAxis(bool expand);
|
/**
|
||||||
/**
|
* Simple layout for arranging nodes in a row (horizontal line)
|
||||||
* If true, the cross-axis content size of the target node will be
|
*/
|
||||||
* automatically adjusted to fit the children
|
class GEODE_DLL RowLayout : public AxisLayout {
|
||||||
*/
|
protected:
|
||||||
AxisLayout* setCrossAxisOverflow(bool allow);
|
RowLayout();
|
||||||
/**
|
|
||||||
* If not `std::nullopt`, then the axis will be automatically extended to
|
public:
|
||||||
* fit all items in a single row whose minimum length is the specified.
|
/**
|
||||||
* Useful for scrollable list layer contents
|
* Create a new RowLayout. See the chainable setters on RowLayout for
|
||||||
*/
|
* what options you can customize for the layout
|
||||||
AxisLayout* setAutoGrowAxis(std::optional<float> allowAndMinLength);
|
* @returns Created RowLayout
|
||||||
/**
|
*/
|
||||||
* Set the default minimum/maximum scales for nodes in the layout
|
static RowLayout* create();
|
||||||
*/
|
};
|
||||||
AxisLayout* setDefaultScaleLimits(float min, float max);
|
|
||||||
};
|
/**
|
||||||
|
* Simple layout for arranging nodes in a column (vertical line)
|
||||||
/**
|
*/
|
||||||
* Simple layout for arranging nodes in a row (horizontal line)
|
class GEODE_DLL ColumnLayout : public AxisLayout {
|
||||||
*/
|
protected:
|
||||||
class GEODE_DLL RowLayout : public AxisLayout {
|
ColumnLayout();
|
||||||
protected:
|
|
||||||
RowLayout();
|
public:
|
||||||
|
/**
|
||||||
public:
|
* Create a new ColumnLayout. See the chainable setters on RowLayout for
|
||||||
/**
|
* what options you can customize for the layout
|
||||||
* Create a new RowLayout. See the chainable setters on RowLayout for
|
* @returns Created ColumnLayout
|
||||||
* what options you can customize for the layout
|
*/
|
||||||
* @returns Created RowLayout
|
static ColumnLayout* create();
|
||||||
*/
|
};
|
||||||
static RowLayout* create();
|
|
||||||
};
|
/**
|
||||||
|
* The relative position of a node to its parent in an AnchorLayout
|
||||||
/**
|
*/
|
||||||
* Simple layout for arranging nodes in a column (vertical line)
|
enum class Anchor {
|
||||||
*/
|
Center,
|
||||||
class GEODE_DLL ColumnLayout : public AxisLayout {
|
TopLeft,
|
||||||
protected:
|
Top,
|
||||||
ColumnLayout();
|
TopRight,
|
||||||
|
Right,
|
||||||
public:
|
BottomRight,
|
||||||
/**
|
Bottom,
|
||||||
* Create a new ColumnLayout. See the chainable setters on RowLayout for
|
BottomLeft,
|
||||||
* what options you can customize for the layout
|
Left,
|
||||||
* @returns Created ColumnLayout
|
};
|
||||||
*/
|
|
||||||
static ColumnLayout* create();
|
/**
|
||||||
};
|
* Options for customizing a node's position in an AnchorLayout
|
||||||
|
*/
|
||||||
/**
|
class GEODE_DLL AnchorLayoutOptions : public LayoutOptions {
|
||||||
* The relative position of a node to its parent in an AnchorLayout
|
protected:
|
||||||
*/
|
Anchor m_anchor = Anchor::Center;
|
||||||
enum class Anchor {
|
cocos2d::CCPoint m_offset = cocos2d::CCPointZero;
|
||||||
Center,
|
|
||||||
TopLeft,
|
public:
|
||||||
Top,
|
static AnchorLayoutOptions* create();
|
||||||
TopRight,
|
|
||||||
Right,
|
Anchor getAnchor() const;
|
||||||
BottomRight,
|
cocos2d::CCPoint getOffset() const;
|
||||||
Bottom,
|
|
||||||
BottomLeft,
|
AnchorLayoutOptions* setAnchor(Anchor anchor);
|
||||||
Left,
|
AnchorLayoutOptions* setOffset(cocos2d::CCPoint const& offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options for customizing a node's position in an AnchorLayout
|
* A layout for positioning nodes at specific positions relative to their
|
||||||
*/
|
* parent's content size. See `Anchor` for available anchoring options. Useful
|
||||||
class GEODE_DLL AnchorLayoutOptions : public LayoutOptions {
|
* for example for popups, where a popup using `AnchorLayout` can be
|
||||||
protected:
|
* automatically resized without needing to manually shuffle nodes around
|
||||||
Anchor m_anchor = Anchor::Center;
|
*/
|
||||||
CCPoint m_offset = CCPointZero;
|
class GEODE_DLL AnchorLayout : public Layout {
|
||||||
|
public:
|
||||||
public:
|
static AnchorLayout* create();
|
||||||
static AnchorLayoutOptions* create();
|
|
||||||
|
void apply(cocos2d::CCNode* on) override;
|
||||||
Anchor getAnchor() const;
|
cocos2d::CCSize getSizeHint(cocos2d::CCNode* on) const override;
|
||||||
CCPoint getOffset() const;
|
|
||||||
|
/**
|
||||||
AnchorLayoutOptions* setAnchor(Anchor anchor);
|
* Get a position according to anchoring rules, with the same algorithm as
|
||||||
AnchorLayoutOptions* setOffset(CCPoint const& offset);
|
* `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
|
||||||
* A layout for positioning nodes at specific positions relative to their
|
* @returns A position in `in` for the anchored and offsetted location
|
||||||
* parent's content size. See `Anchor` for available anchoring options. Useful
|
*/
|
||||||
* for example for popups, where a popup using `AnchorLayout` can be
|
static cocos2d::CCPoint getAnchoredPosition(cocos2d::CCNode* in, Anchor anchor, cocos2d::CCPoint const& offset);
|
||||||
* automatically resized without needing to manually shuffle nodes around
|
};
|
||||||
*/
|
|
||||||
class GEODE_DLL AnchorLayout : public Layout {
|
/**
|
||||||
public:
|
* A layout for automatically copying the content size of a node to other nodes.
|
||||||
static AnchorLayout* create();
|
* Basically main use case is for FLAlertLayers (setting the size of the
|
||||||
|
* background and `m_buttonMenu` based on `m_mainLayer`)
|
||||||
void apply(CCNode* on) override;
|
*/
|
||||||
CCSize getSizeHint(CCNode* on) const override;
|
class GEODE_DLL CopySizeLayout : public AnchorLayout {
|
||||||
|
protected:
|
||||||
/**
|
cocos2d::CCArray* m_targets;
|
||||||
* Get a position according to anchoring rules, with the same algorithm as
|
|
||||||
* `AnchorLayout` uses to position its nodes
|
public:
|
||||||
* @param in The node whose content size to use as a reference
|
static CopySizeLayout* create();
|
||||||
* @param anchor The anchor position
|
virtual ~CopySizeLayout();
|
||||||
* @param offset Offset from the anchor
|
|
||||||
* @returns A position in `in` for the anchored and offsetted location
|
/**
|
||||||
*/
|
* Add a target to be automatically resized. Any targets' layouts will
|
||||||
static CCPoint getAnchoredPosition(CCNode* in, Anchor anchor, CCPoint const& offset);
|
* also be updated when this layout is updated
|
||||||
};
|
*/
|
||||||
|
CopySizeLayout* add(cocos2d::CCNode* target);
|
||||||
/**
|
/**
|
||||||
* A layout for automatically copying the content size of a node to other nodes.
|
* Remove a target from being automatically resized
|
||||||
* Basically main use case is for FLAlertLayers (setting the size of the
|
*/
|
||||||
* background and `m_buttonMenu` based on `m_mainLayer`)
|
CopySizeLayout* remove(cocos2d::CCNode* target);
|
||||||
*/
|
|
||||||
class GEODE_DLL CopySizeLayout : public cocos2d::AnchorLayout {
|
void apply(cocos2d::CCNode* in) override;
|
||||||
protected:
|
cocos2d::CCSize getSizeHint(cocos2d::CCNode* in) const override;
|
||||||
cocos2d::CCArray* m_targets;
|
};
|
||||||
|
|
||||||
public:
|
#pragma warning(pop)
|
||||||
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
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <Geode/binding/FLAlertLayer.hpp>
|
#include <Geode/binding/FLAlertLayer.hpp>
|
||||||
#include <Geode/utils/MiniFunction.hpp>
|
#include <Geode/utils/MiniFunction.hpp>
|
||||||
#include <Geode/utils/cocos.hpp>
|
#include <Geode/utils/cocos.hpp>
|
||||||
|
#include <Geode/ui/Layout.hpp>
|
||||||
|
|
||||||
namespace geode {
|
namespace geode {
|
||||||
template <class... InitArgs>
|
template <class... InitArgs>
|
||||||
|
@ -104,7 +105,7 @@ namespace geode {
|
||||||
m_mainLayer->setPosition(winSize / 2);
|
m_mainLayer->setPosition(winSize / 2);
|
||||||
m_mainLayer->setContentSize(m_size);
|
m_mainLayer->setContentSize(m_size);
|
||||||
m_mainLayer->setLayout(
|
m_mainLayer->setLayout(
|
||||||
cocos2d::CopySizeLayout::create()
|
geode::CopySizeLayout::create()
|
||||||
->add(m_buttonMenu)
|
->add(m_buttonMenu)
|
||||||
->add(m_bgSprite)
|
->add(m_bgSprite)
|
||||||
);
|
);
|
||||||
|
@ -119,7 +120,7 @@ namespace geode {
|
||||||
closeSpr, this, (cocos2d::SEL_MenuHandler)(&Popup::onClose)
|
closeSpr, this, (cocos2d::SEL_MenuHandler)(&Popup::onClose)
|
||||||
);
|
);
|
||||||
if (dynamic) {
|
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 {
|
else {
|
||||||
m_closeBtn->setPosition(-m_size.width / 2 + 3.f, m_size.height / 2 - 3.f);
|
m_closeBtn->setPosition(-m_size.width / 2 + 3.f, m_size.height / 2 - 3.f);
|
||||||
|
@ -137,14 +138,6 @@ namespace geode {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
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
|
* Init with AnchorLayout and the content size of `m_buttonMenu` and
|
||||||
* `m_bgSprite` being tied to the size of `m_mainLayer` (rather than
|
* `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 = cocos2d::CCLabelBMFont::create(title.c_str(), font);
|
||||||
m_title->setZOrder(2);
|
m_title->setZOrder(2);
|
||||||
if (m_dynamic) {
|
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 {
|
else {
|
||||||
auto winSize = cocos2d::CCDirector::get()->getWinSize();
|
auto winSize = cocos2d::CCDirector::get()->getWinSize();
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CCNode.h"
|
#include <cocos2d.h>
|
||||||
|
|
||||||
NS_CC_BEGIN
|
namespace geode {
|
||||||
|
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable: 4275)
|
#pragma warning(disable: 4275)
|
||||||
|
@ -22,7 +22,7 @@ NS_CC_BEGIN
|
||||||
* @note If you want to specify a minimum width for a SpacerNode, add
|
* @note If you want to specify a minimum width for a SpacerNode, add
|
||||||
* AxisLayoutOptions for it and use setLength
|
* AxisLayoutOptions for it and use setLength
|
||||||
*/
|
*/
|
||||||
class GEODE_DLL SpacerNode : public CCNode {
|
class GEODE_DLL SpacerNode : public cocos2d::CCNode {
|
||||||
protected:
|
protected:
|
||||||
size_t m_grow;
|
size_t m_grow;
|
||||||
|
|
||||||
|
@ -61,9 +61,9 @@ public:
|
||||||
*/
|
*/
|
||||||
class GEODE_DLL SpacerNodeChild : public SpacerNode {
|
class GEODE_DLL SpacerNodeChild : public SpacerNode {
|
||||||
protected:
|
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:
|
public:
|
||||||
/**
|
/**
|
||||||
|
@ -73,11 +73,11 @@ public:
|
||||||
* factors (akin to CSS flew grow)
|
* factors (akin to CSS flew grow)
|
||||||
* @param grow The grow factor for this node. Default is 1
|
* @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)
|
#pragma warning(pop)
|
||||||
|
|
||||||
NS_CC_END
|
}
|
|
@ -78,226 +78,6 @@ namespace geode {
|
||||||
struct JsonMaybeObject;
|
struct JsonMaybeObject;
|
||||||
struct JsonMaybeValue;
|
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 {
|
class GEODE_DLL JsonExpectedValue final {
|
||||||
protected:
|
protected:
|
||||||
class Impl;
|
class Impl;
|
||||||
|
|
|
@ -186,8 +186,6 @@ namespace geode {
|
||||||
std::tie(other.m_major, other.m_minor, other.m_patch, other.m_tag);
|
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 toVString(bool includeTag = true) const;
|
||||||
std::string toNonVString(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));
|
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
|
* Return a node, or create a default one if it's
|
||||||
* nullptr. Syntactic sugar function
|
* 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};
|
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
|
* Parse a ccColor3B from a hexadecimal string. The string may contain
|
||||||
* a leading '#'
|
* a leading '#'
|
||||||
|
|
|
@ -17,15 +17,6 @@
|
||||||
namespace geode {
|
namespace geode {
|
||||||
using ByteVector = std::vector<uint8_t>;
|
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>
|
template <typename T>
|
||||||
ByteVector toBytes(T const& a) {
|
ByteVector toBytes(T const& a) {
|
||||||
ByteVector out;
|
ByteVector out;
|
||||||
|
|
|
@ -1026,14 +1026,6 @@ std::optional<AxisAlignment> AxisLayoutOptions::getCrossAxisAlignment() const {
|
||||||
return m_impl->m_crossAxisAlignment;
|
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) {
|
AxisLayoutOptions* AxisLayoutOptions::setScaleLimits(std::optional<float> min, std::optional<float> max) {
|
||||||
m_impl->m_scaleLimits = { min, max };
|
m_impl->m_scaleLimits = { min, max };
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -62,10 +62,6 @@ public:
|
||||||
return meta;
|
return meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldContainer* getFieldContainer() {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
FieldContainer* getFieldContainer(char const* forClass) {
|
FieldContainer* getFieldContainer(char const* forClass) {
|
||||||
if (!m_classFieldContainers.count(forClass)) {
|
if (!m_classFieldContainers.count(forClass)) {
|
||||||
m_classFieldContainers[forClass] = new FieldContainer();
|
m_classFieldContainers[forClass] = new FieldContainer();
|
||||||
|
@ -104,11 +100,6 @@ size_t modifier::getFieldIndexForClass(char const* name) {
|
||||||
return s_nextIndex[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) {
|
FieldContainer* CCNode::getFieldContainer(char const* forClass) {
|
||||||
return GeodeNodeMetadata::set(this)->getFieldContainer(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)
|
#pragma warning(pop)
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include <Geode/loader/Loader.hpp>
|
#include <Geode/loader/Loader.hpp>
|
||||||
#include <Geode/loader/Log.hpp>
|
#include <Geode/loader/Log.hpp>
|
||||||
#include <Geode/loader/Mod.hpp>
|
#include <Geode/loader/Mod.hpp>
|
||||||
#include <Geode/loader/SettingEvent.hpp>
|
|
||||||
#include <Geode/utils/JsonValidation.hpp>
|
#include <Geode/utils/JsonValidation.hpp>
|
||||||
#include <loader/LogImpl.hpp>
|
#include <loader/LogImpl.hpp>
|
||||||
|
|
||||||
|
@ -30,8 +29,7 @@ $on_mod(Loaded) {
|
||||||
std::vector<matjson::Value> res;
|
std::vector<matjson::Value> res;
|
||||||
|
|
||||||
auto args = *event->messageData;
|
auto args = *event->messageData;
|
||||||
JsonChecker checker(args);
|
auto root = checkJson(args, "[ipc/list-mods]");
|
||||||
auto root = checker.root("[ipc/list-mods]").obj();
|
|
||||||
|
|
||||||
auto includeRunTimeInfo = root.has("include-runtime-info").get<bool>();
|
auto includeRunTimeInfo = root.has("include-runtime-info").get<bool>();
|
||||||
auto dontIncludeLoader = root.has("dont-include-loader").get<bool>();
|
auto dontIncludeLoader = root.has("dont-include-loader").get<bool>();
|
||||||
|
|
|
@ -20,10 +20,6 @@ std::string Mod::getName() const {
|
||||||
return m_impl->getName();
|
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 {
|
std::vector<std::string> Mod::getDevelopers() const {
|
||||||
return m_impl->getDevelopers();
|
return m_impl->getDevelopers();
|
||||||
}
|
}
|
||||||
|
@ -101,9 +97,6 @@ std::vector<Mod*> Mod::getDependants() const {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::optional<VersionInfo> Mod::hasAvailableUpdate() const {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
Mod::CheckUpdatesTask Mod::checkUpdates() const {
|
Mod::CheckUpdatesTask Mod::checkUpdates() const {
|
||||||
return server::checkUpdates(this).map(
|
return server::checkUpdates(this).map(
|
||||||
[](auto* result) -> Mod::CheckUpdatesTask::Value {
|
[](auto* result) -> Mod::CheckUpdatesTask::Value {
|
||||||
|
@ -159,24 +152,10 @@ bool Mod::hasSetting(std::string_view const key) const {
|
||||||
return m_impl->hasSetting(key);
|
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 {
|
std::shared_ptr<SettingV3> Mod::getSettingV3(std::string_view const key) const {
|
||||||
return m_impl->m_settings->get(std::string(key));
|
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) {
|
Result<> Mod::registerCustomSettingType(std::string_view type, SettingGenerator generator) {
|
||||||
return m_impl->m_settings->registerCustomSettingType(type, 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 {
|
std::vector<std::string> ModMetadata::getSpritesheets() const {
|
||||||
return m_impl->m_spritesheets;
|
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 {
|
std::vector<std::pair<std::string, matjson::Value>> ModMetadata::getSettingsV3() const {
|
||||||
return m_impl->m_settings;
|
return m_impl->m_settings;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,6 @@ private:
|
||||||
std::unordered_map<std::string, SettingGenerator> m_types;
|
std::unordered_map<std::string, SettingGenerator> m_types;
|
||||||
|
|
||||||
SharedSettingTypesPool() : m_types({
|
SharedSettingTypesPool() : m_types({
|
||||||
// todo in v4: remove this
|
|
||||||
{ "custom", &LegacyCustomSettingV3::parse },
|
|
||||||
{ "title", &TitleSettingV3::parse },
|
{ "title", &TitleSettingV3::parse },
|
||||||
{ "bool", &BoolSettingV3::parse },
|
{ "bool", &BoolSettingV3::parse },
|
||||||
{ "int", &IntSettingV3::parse },
|
{ "int", &IntSettingV3::parse },
|
||||||
|
@ -202,19 +200,6 @@ Result<> ModSettingsManager::registerLegacyCustomSetting(std::string_view key, s
|
||||||
if (!m_impl->settings.count(id)) {
|
if (!m_impl->settings.count(id)) {
|
||||||
return Err("No such setting '{}' in mod {}", id, m_impl->modID);
|
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();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,33 +229,6 @@ std::shared_ptr<SettingV3> ModSettingsManager::get(std::string_view key) {
|
||||||
auto id = std::string(key);
|
auto id = std::string(key);
|
||||||
return m_impl->settings.count(id) ? m_impl->settings.at(id).v3 : nullptr;
|
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 {
|
bool ModSettingsManager::restartRequired() const {
|
||||||
return m_impl->restartRequired;
|
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 "SettingNodeV3.hpp"
|
||||||
#include <Geode/loader/SettingNode.hpp>
|
|
||||||
#include <Geode/utils/ColorProvider.hpp>
|
#include <Geode/utils/ColorProvider.hpp>
|
||||||
#include <Geode/utils/ranges.hpp>
|
#include <Geode/utils/ranges.hpp>
|
||||||
#include <Geode/loader/Dirs.hpp>
|
#include <Geode/loader/Dirs.hpp>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Geode/loader/SettingV3.hpp>
|
#include <Geode/loader/SettingV3.hpp>
|
||||||
#include <Geode/loader/SettingNode.hpp>
|
|
||||||
#include <Geode/binding/CCMenuItemToggler.hpp>
|
#include <Geode/binding/CCMenuItemToggler.hpp>
|
||||||
#include <Geode/binding/ColorChannelSprite.hpp>
|
#include <Geode/binding/ColorChannelSprite.hpp>
|
||||||
#include <Geode/binding/Slider.hpp>
|
#include <Geode/binding/Slider.hpp>
|
||||||
|
@ -314,25 +313,3 @@ public:
|
||||||
bool hasNonDefaultValue() const override;
|
bool hasNonDefaultValue() const override;
|
||||||
void onResetToDefault() 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/SettingV3.hpp>
|
||||||
#include <Geode/loader/SettingEvent.hpp>
|
|
||||||
#include <Geode/loader/ModSettingsManager.hpp>
|
#include <Geode/loader/ModSettingsManager.hpp>
|
||||||
#include <Geode/utils/ranges.hpp>
|
#include <Geode/utils/ranges.hpp>
|
||||||
#include <Geode/utils/string.hpp>
|
#include <Geode/utils/string.hpp>
|
||||||
|
@ -574,19 +573,12 @@ void SettingV3::markChanged() {
|
||||||
}
|
}
|
||||||
SettingChangedEventV3(shared_from_this()).post();
|
SettingChangedEventV3(shared_from_this()).post();
|
||||||
if (manager) {
|
if (manager) {
|
||||||
|
// TODO: v4
|
||||||
// Use ModSettingsManager rather than convertToLegacyValue since it
|
// Use ModSettingsManager rather than convertToLegacyValue since it
|
||||||
// caches the result and we want to have that for performance
|
// 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 {
|
class TitleSettingV3::Impl final {
|
||||||
public:
|
public:
|
||||||
};
|
};
|
||||||
|
@ -666,15 +658,6 @@ bool LegacyCustomSettingV3::isDefaultValue() const {
|
||||||
}
|
}
|
||||||
void LegacyCustomSettingV3::reset() {}
|
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 {
|
class BoolSettingV3::Impl final {
|
||||||
public:
|
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 {
|
class IntSettingV3::Impl final {
|
||||||
public:
|
public:
|
||||||
std::optional<int64_t> minValue;
|
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 {
|
class FloatSettingV3::Impl final {
|
||||||
public:
|
public:
|
||||||
std::optional<double> minValue;
|
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 {
|
class StringSettingV3::Impl final {
|
||||||
public:
|
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 {
|
class FileSettingV3::Impl final {
|
||||||
public:
|
public:
|
||||||
bool folder = false;
|
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 {
|
class Color3BSettingV3::Impl final {
|
||||||
public:
|
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 {
|
class Color4BSettingV3::Impl final {
|
||||||
public:
|
public:
|
||||||
};
|
};
|
||||||
|
@ -1223,14 +1115,3 @@ SettingNodeV3* Color4BSettingV3::createNode(float width) {
|
||||||
std::static_pointer_cast<Color4BSettingV3>(shared_from_this()), 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());
|
log::debug("Downloading latest resources", Loader::get()->getVersion().toVString());
|
||||||
fetchLatestGithubRelease(
|
fetchLatestGithubRelease(
|
||||||
[](matjson::Value const& raw) {
|
[](matjson::Value const& raw) {
|
||||||
auto json = raw;
|
auto root = checkJson(raw, "[]");
|
||||||
JsonChecker checker(json);
|
|
||||||
auto root = checker.root("[]").obj();
|
|
||||||
|
|
||||||
// find release asset
|
// find release asset
|
||||||
for (auto asset : root.needs("assets").iterate()) {
|
for (auto asset : root.needs("assets").iterate()) {
|
||||||
|
@ -206,9 +204,7 @@ void updater::downloadLoaderResources(bool useLatestRelease) {
|
||||||
RUNNING_REQUESTS.erase("@downloadLoaderResources");
|
RUNNING_REQUESTS.erase("@downloadLoaderResources");
|
||||||
if (response->ok()) {
|
if (response->ok()) {
|
||||||
if (auto ok = response->json()) {
|
if (auto ok = response->json()) {
|
||||||
auto json = ok.unwrap();
|
auto root = checkJson(ok.unwrap(), "[]");
|
||||||
JsonChecker checker(json);
|
|
||||||
auto root = checker.root("[]").obj();
|
|
||||||
|
|
||||||
// find release asset
|
// find release asset
|
||||||
for (auto asset : root.needs("assets").iterate()) {
|
for (auto asset : root.needs("assets").iterate()) {
|
||||||
|
@ -362,9 +358,7 @@ void updater::checkForLoaderUpdates() {
|
||||||
// Check for updates in the background
|
// Check for updates in the background
|
||||||
fetchLatestGithubRelease(
|
fetchLatestGithubRelease(
|
||||||
[](matjson::Value const& raw) {
|
[](matjson::Value const& raw) {
|
||||||
auto json = raw;
|
auto root = checkJson(raw, "[]");
|
||||||
JsonChecker checker(json);
|
|
||||||
auto root = checker.root("[]").obj();
|
|
||||||
|
|
||||||
VersionInfo ver { 0, 0, 0 };
|
VersionInfo ver { 0, 0, 0 };
|
||||||
root.needs("tag_name").into(ver);
|
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) {
|
Result<ServerModVersion> ServerModVersion::parse(matjson::Value const& raw) {
|
||||||
auto json = raw;
|
auto root = checkJson(raw, "ServerModVersion");
|
||||||
JsonChecker checker(json);
|
|
||||||
auto root = checker.root("ServerModVersion").obj();
|
|
||||||
|
|
||||||
auto res = ServerModVersion();
|
auto res = ServerModVersion();
|
||||||
|
|
||||||
|
@ -356,9 +354,7 @@ Result<ServerModVersion> ServerModVersion::parse(matjson::Value const& raw) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<ServerModReplacement> ServerModReplacement::parse(matjson::Value const& raw) {
|
Result<ServerModReplacement> ServerModReplacement::parse(matjson::Value const& raw) {
|
||||||
auto json = raw;
|
auto root = checkJson(raw, "ServerModReplacement");
|
||||||
JsonChecker checker(json);
|
|
||||||
auto root = checker.root("ServerModReplacement").obj();
|
|
||||||
auto res = ServerModReplacement();
|
auto res = ServerModReplacement();
|
||||||
|
|
||||||
root.needs("id").into(res.id);
|
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) {
|
Result<ServerModUpdate> ServerModUpdate::parse(matjson::Value const& raw) {
|
||||||
auto json = raw;
|
auto root = checkJson(raw, "ServerModUpdate");
|
||||||
JsonChecker checker(json);
|
|
||||||
auto root = checker.root("ServerModUpdate").obj();
|
|
||||||
|
|
||||||
auto res = 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) {
|
Result<std::vector<ServerModUpdate>> ServerModUpdate::parseList(matjson::Value const& raw) {
|
||||||
auto json = raw;
|
auto payload = checkJson(raw, "ServerModUpdatesList");
|
||||||
JsonChecker checker(json);
|
|
||||||
auto payload = checker.root("ServerModUpdatesList").array();
|
|
||||||
|
|
||||||
std::vector<ServerModUpdate> list {};
|
std::vector<ServerModUpdate> list {};
|
||||||
for (auto item : payload.iterate()) {
|
for (auto item : payload.iterate()) {
|
||||||
|
@ -421,9 +413,7 @@ bool ServerModUpdate::hasUpdateForInstalledMod() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<ServerModMetadata> ServerModMetadata::parse(matjson::Value const& raw) {
|
Result<ServerModMetadata> ServerModMetadata::parse(matjson::Value const& raw) {
|
||||||
auto json = raw;
|
auto root = checkJson(raw, "ServerModMetadata");
|
||||||
JsonChecker checker(json);
|
|
||||||
auto root = checker.root("ServerModMetadata").obj();
|
|
||||||
|
|
||||||
auto res = ServerModMetadata();
|
auto res = ServerModMetadata();
|
||||||
root.needs("id").into(res.id);
|
root.needs("id").into(res.id);
|
||||||
|
@ -501,9 +491,7 @@ std::string ServerModMetadata::formatDevelopersToString() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<ServerModsList> ServerModsList::parse(matjson::Value const& raw) {
|
Result<ServerModsList> ServerModsList::parse(matjson::Value const& raw) {
|
||||||
auto json = raw;
|
auto payload = checkJson(raw, "ServerModsList");
|
||||||
JsonChecker checker(json);
|
|
||||||
auto payload = checker.root("ServerModsList").obj();
|
|
||||||
|
|
||||||
auto list = ServerModsList();
|
auto list = ServerModsList();
|
||||||
for (auto item : payload.needs("data").iterate()) {
|
for (auto item : payload.needs("data").iterate()) {
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include "Geode/utils/VersionInfo.hpp"
|
#include "Geode/utils/VersionInfo.hpp"
|
||||||
#include <Geode/DefaultInclude.hpp>
|
#include <Geode/DefaultInclude.hpp>
|
||||||
#include <Geode/utils/web.hpp>
|
#include <Geode/utils/web.hpp>
|
||||||
#include <Geode/loader/SettingEvent.hpp>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <matjson.hpp>
|
#include <matjson.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "GeodeStyle.hpp"
|
#include "GeodeStyle.hpp"
|
||||||
#include <Geode/utils/cocos.hpp>
|
#include <Geode/utils/cocos.hpp>
|
||||||
#include <Geode/utils/ColorProvider.hpp>
|
#include <Geode/utils/ColorProvider.hpp>
|
||||||
#include <Geode/loader/SettingEvent.hpp>
|
|
||||||
#include <Geode/binding/ButtonSprite.hpp>
|
#include <Geode/binding/ButtonSprite.hpp>
|
||||||
#include <Geode/ui/LoadingSpinner.hpp>
|
#include <Geode/ui/LoadingSpinner.hpp>
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "ModDeveloperItem.hpp"
|
#include "ModDeveloperItem.hpp"
|
||||||
|
|
||||||
#include <Geode/cocos/base_nodes/CCNode.h>
|
#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/cocoa/CCGeometry.h>
|
||||||
#include <Geode/cocos/label_nodes/CCLabelBMFont.h>
|
#include <Geode/cocos/label_nodes/CCLabelBMFont.h>
|
||||||
#include <Geode/cocos/platform/CCPlatformMacros.h>
|
#include <Geode/cocos/platform/CCPlatformMacros.h>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "ModDeveloperList.hpp"
|
#include "ModDeveloperList.hpp"
|
||||||
|
|
||||||
#include <Geode/cocos/base_nodes/CCNode.h>
|
#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/cocoa/CCGeometry.h>
|
||||||
#include <Geode/cocos/platform/CCPlatformMacros.h>
|
#include <Geode/cocos/platform/CCPlatformMacros.h>
|
||||||
#include <Geode/utils/cocos.hpp>
|
#include <Geode/utils/cocos.hpp>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "ModProblemItem.hpp"
|
#include "ModProblemItem.hpp"
|
||||||
|
|
||||||
#include <Geode/cocos/base_nodes/CCNode.h>
|
#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/cocoa/CCGeometry.h>
|
||||||
#include <Geode/cocos/label_nodes/CCLabelBMFont.h>
|
#include <Geode/cocos/label_nodes/CCLabelBMFont.h>
|
||||||
#include <Geode/cocos/platform/CCPlatformMacros.h>
|
#include <Geode/cocos/platform/CCPlatformMacros.h>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "ModProblemList.hpp"
|
#include "ModProblemList.hpp"
|
||||||
|
|
||||||
#include <Geode/cocos/base_nodes/CCNode.h>
|
#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/cocoa/CCGeometry.h>
|
||||||
#include <Geode/cocos/platform/CCPlatformMacros.h>
|
#include <Geode/cocos/platform/CCPlatformMacros.h>
|
||||||
#include <Geode/utils/cocos.hpp>
|
#include <Geode/utils/cocos.hpp>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "ModErrorPopup.hpp"
|
#include "ModErrorPopup.hpp"
|
||||||
#include "Geode/cocos/base_nodes/Layout.hpp"
|
#include <Geode/ui/Layout.hpp>
|
||||||
#include "ui/mods/GeodeStyle.hpp"
|
#include "ui/mods/GeodeStyle.hpp"
|
||||||
#include "ui/mods/list/ModProblemList.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 "ModSettingsPopup.hpp"
|
||||||
#include <Geode/binding/ButtonSprite.hpp>
|
#include <Geode/binding/ButtonSprite.hpp>
|
||||||
#include <Geode/loader/Mod.hpp>
|
#include <Geode/loader/Mod.hpp>
|
||||||
#include <Geode/loader/Setting.hpp>
|
|
||||||
#include <Geode/loader/ModSettingsManager.hpp>
|
#include <Geode/loader/ModSettingsManager.hpp>
|
||||||
#include <Geode/ui/ScrollLayer.hpp>
|
#include <Geode/ui/ScrollLayer.hpp>
|
||||||
#include <Geode/utils/cocos.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, '?');
|
auto split = splitOnce(s_lastImage, '?');
|
||||||
s_lastImage = split.first;
|
s_lastImage = split.first;
|
||||||
|
|
||||||
// TODO: remove this in v4.0.0
|
imgArguments = ranges::map<decltype(imgArguments)>(utils::string::split(split.second, "&"), [&](auto str) {
|
||||||
// check if this image is using the old format "my.mod/image.png&scale:0.5"
|
return splitOnce(str, '=');
|
||||||
// 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, '=');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
float spriteScale = 1.0f;
|
float spriteScale = 1.0f;
|
||||||
float spriteWidth = 0.0f;
|
float spriteWidth = 0.0f;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include <Geode/Loader.hpp>
|
#include <Geode/Loader.hpp>
|
||||||
#include <Geode/modify/MenuLayer.hpp>
|
#include <Geode/modify/MenuLayer.hpp>
|
||||||
#include <Geode/loader/SettingNode.hpp>
|
|
||||||
#include <Geode/loader/Dispatch.hpp>
|
#include <Geode/loader/Dispatch.hpp>
|
||||||
#include <Geode/Bindings.hpp>
|
#include <Geode/Bindings.hpp>
|
||||||
#include "main.hpp"
|
#include "main.hpp"
|
||||||
|
@ -30,119 +29,120 @@ constexpr Icon DEFAULT_ICON = Icon::Steve;
|
||||||
|
|
||||||
class MySettingValue;
|
class MySettingValue;
|
||||||
|
|
||||||
class MySettingValue : public SettingValue {
|
// TODO: v4 (port to new settings)
|
||||||
protected:
|
// class MySettingValue : public SettingValue {
|
||||||
Icon m_icon;
|
// protected:
|
||||||
|
// Icon m_icon;
|
||||||
|
|
||||||
public:
|
// public:
|
||||||
MySettingValue(std::string const& key, std::string const& modID, Icon icon)
|
// MySettingValue(std::string const& key, std::string const& modID, Icon icon)
|
||||||
: SettingValue(key, modID), m_icon(icon) {}
|
// : SettingValue(key, modID), m_icon(icon) {}
|
||||||
|
|
||||||
bool load(matjson::Value const& json) override {
|
// bool load(matjson::Value const& json) override {
|
||||||
if (!json.is<int>()) return false;
|
// if (!json.is<int>()) return false;
|
||||||
m_icon = static_cast<Icon>(json.as<int>());
|
// m_icon = static_cast<Icon>(json.as<int>());
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
bool save(matjson::Value& json) const override {
|
// bool save(matjson::Value& json) const override {
|
||||||
json = static_cast<int>(m_icon);
|
// json = static_cast<int>(m_icon);
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
SettingNode* createNode(float width) override;
|
// SettingNode* createNode(float width) override;
|
||||||
|
|
||||||
void setIcon(Icon icon) {
|
// void setIcon(Icon icon) {
|
||||||
m_icon = icon;
|
// m_icon = icon;
|
||||||
}
|
// }
|
||||||
Icon getIcon() const {
|
// Icon getIcon() const {
|
||||||
return m_icon;
|
// return m_icon;
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
class MySettingNode : public SettingNode {
|
// class MySettingNode : public SettingNode {
|
||||||
protected:
|
// protected:
|
||||||
Icon m_currentIcon;
|
// Icon m_currentIcon;
|
||||||
std::vector<CCSprite*> m_sprites;
|
// std::vector<CCSprite*> m_sprites;
|
||||||
|
|
||||||
bool init(MySettingValue* value, float width) {
|
// bool init(MySettingValue* value, float width) {
|
||||||
if (!SettingNode::init(value))
|
// if (!SettingNode::init(value))
|
||||||
return false;
|
// return false;
|
||||||
|
|
||||||
m_currentIcon = value->getIcon();
|
// m_currentIcon = value->getIcon();
|
||||||
this->setContentSize({ width, 40.f });
|
// this->setContentSize({ width, 40.f });
|
||||||
|
|
||||||
auto menu = CCMenu::create();
|
// auto menu = CCMenu::create();
|
||||||
menu->setPosition(width / 2, 20.f);
|
// menu->setPosition(width / 2, 20.f);
|
||||||
|
|
||||||
float x = -75.f;
|
// float x = -75.f;
|
||||||
|
|
||||||
for (auto& [spr, icon] : {
|
// for (auto& [spr, icon] : {
|
||||||
std::pair { "GJ_square01.png", Icon::Steve, },
|
// std::pair { "GJ_square01.png", Icon::Steve, },
|
||||||
std::pair { "GJ_square02.png", Icon::Mike, },
|
// std::pair { "GJ_square02.png", Icon::Mike, },
|
||||||
std::pair { "GJ_square03.png", Icon::LazarithTheDestroyerOfForsakenSouls, },
|
// std::pair { "GJ_square03.png", Icon::LazarithTheDestroyerOfForsakenSouls, },
|
||||||
std::pair { "GJ_square04.png", Icon::Geoff, },
|
// std::pair { "GJ_square04.png", Icon::Geoff, },
|
||||||
}) {
|
// }) {
|
||||||
auto btnSpr = CCSprite::create(spr);
|
// auto btnSpr = CCSprite::create(spr);
|
||||||
btnSpr->setScale(.7f);
|
// btnSpr->setScale(.7f);
|
||||||
m_sprites.push_back(btnSpr);
|
// m_sprites.push_back(btnSpr);
|
||||||
if (icon == m_currentIcon) {
|
// if (icon == m_currentIcon) {
|
||||||
btnSpr->setColor({ 0, 255, 0 });
|
// btnSpr->setColor({ 0, 255, 0 });
|
||||||
} else {
|
// } else {
|
||||||
btnSpr->setColor({ 200, 200, 200 });
|
// btnSpr->setColor({ 200, 200, 200 });
|
||||||
}
|
// }
|
||||||
auto btn = CCMenuItemSpriteExtra::create(
|
// auto btn = CCMenuItemSpriteExtra::create(
|
||||||
btnSpr, this, menu_selector(MySettingNode::onSelect)
|
// btnSpr, this, menu_selector(MySettingNode::onSelect)
|
||||||
);
|
// );
|
||||||
btn->setTag(static_cast<int>(icon));
|
// btn->setTag(static_cast<int>(icon));
|
||||||
btn->setPosition(x, 0);
|
// btn->setPosition(x, 0);
|
||||||
menu->addChild(btn);
|
// menu->addChild(btn);
|
||||||
|
|
||||||
x += 50.f;
|
// x += 50.f;
|
||||||
}
|
// }
|
||||||
|
|
||||||
this->addChild(menu);
|
// this->addChild(menu);
|
||||||
|
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
void onSelect(CCObject* sender) {
|
// void onSelect(CCObject* sender) {
|
||||||
for (auto& spr : m_sprites) {
|
// for (auto& spr : m_sprites) {
|
||||||
spr->setColor({ 200, 200, 200 });
|
// spr->setColor({ 200, 200, 200 });
|
||||||
}
|
// }
|
||||||
m_currentIcon = static_cast<Icon>(sender->getTag());
|
// m_currentIcon = static_cast<Icon>(sender->getTag());
|
||||||
static_cast<CCSprite*>(
|
// static_cast<CCSprite*>(
|
||||||
static_cast<CCMenuItemSpriteExtra*>(sender)->getNormalImage()
|
// static_cast<CCMenuItemSpriteExtra*>(sender)->getNormalImage()
|
||||||
)->setColor({ 0, 255, 0 });
|
// )->setColor({ 0, 255, 0 });
|
||||||
this->dispatchChanged();
|
// this->dispatchChanged();
|
||||||
}
|
// }
|
||||||
|
|
||||||
public:
|
// public:
|
||||||
void commit() override {
|
// void commit() override {
|
||||||
static_cast<MySettingValue*>(m_value)->setIcon(m_currentIcon);
|
// static_cast<MySettingValue*>(m_value)->setIcon(m_currentIcon);
|
||||||
this->dispatchCommitted();
|
// this->dispatchCommitted();
|
||||||
}
|
// }
|
||||||
bool hasUncommittedChanges() override {
|
// bool hasUncommittedChanges() override {
|
||||||
return m_currentIcon != static_cast<MySettingValue*>(m_value)->getIcon();
|
// return m_currentIcon != static_cast<MySettingValue*>(m_value)->getIcon();
|
||||||
}
|
// }
|
||||||
bool hasNonDefaultValue() override {
|
// bool hasNonDefaultValue() override {
|
||||||
return m_currentIcon != DEFAULT_ICON;
|
// return m_currentIcon != DEFAULT_ICON;
|
||||||
}
|
// }
|
||||||
void resetToDefault() override {
|
// void resetToDefault() override {
|
||||||
m_currentIcon = DEFAULT_ICON;
|
// m_currentIcon = DEFAULT_ICON;
|
||||||
}
|
// }
|
||||||
|
|
||||||
static MySettingNode* create(MySettingValue* value, float width) {
|
// static MySettingNode* create(MySettingValue* value, float width) {
|
||||||
auto ret = new MySettingNode;
|
// auto ret = new MySettingNode;
|
||||||
if (ret->init(value, width)) {
|
// if (ret->init(value, width)) {
|
||||||
ret->autorelease();
|
// ret->autorelease();
|
||||||
return ret;
|
// return ret;
|
||||||
}
|
// }
|
||||||
delete ret;
|
// delete ret;
|
||||||
return nullptr;
|
// return nullptr;
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
SettingNode* MySettingValue::createNode(float width) {
|
// SettingNode* MySettingValue::createNode(float width) {
|
||||||
return MySettingNode::create(this, width);
|
// return MySettingNode::create(this, width);
|
||||||
}
|
// }
|
||||||
|
|
||||||
struct MyMenuLayer : Modify<MyMenuLayer, MenuLayer> {
|
struct MyMenuLayer : Modify<MyMenuLayer, MenuLayer> {
|
||||||
void onMoreGames(CCObject*) {
|
void onMoreGames(CCObject*) {
|
||||||
|
@ -161,7 +161,7 @@ struct MyMenuLayer : Modify<MyMenuLayer, MenuLayer> {
|
||||||
};
|
};
|
||||||
|
|
||||||
$on_mod(Loaded) {
|
$on_mod(Loaded) {
|
||||||
Mod::get()->addCustomSetting<MySettingValue>("overcast-skies", DEFAULT_ICON);
|
// Mod::get()->addCustomSetting<MySettingValue>("overcast-skies", DEFAULT_ICON);
|
||||||
|
|
||||||
(void)new EventListener(+[](GJGarageLayer* gl) {
|
(void)new EventListener(+[](GJGarageLayer* gl) {
|
||||||
auto label = CCLabelBMFont::create("Dispatcher works!", "bigFont.fnt");
|
auto label = CCLabelBMFont::create("Dispatcher works!", "bigFont.fnt");
|
||||||
|
|
Loading…
Reference in a new issue