mirror of
https://github.com/geode-sdk/geode.git
synced 2025-02-17 00:30:26 -05:00
commit
61015be6b1
23 changed files with 451 additions and 69 deletions
|
@ -146,7 +146,7 @@ endif()
|
|||
|
||||
add_library(GeodeCodegenSources ${GEODE_CODEGEN_PATH}/Geode/GeneratedSource.cpp ${GEODE_CODEGEN_PATH}/Geode/GeneratedAddress.cpp)
|
||||
target_link_directories(GeodeCodegenSources PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/loader/include/link)
|
||||
target_link_libraries(GeodeCodegenSources PRIVATE ghc_filesystem GeodeFilesystemImpl fmt TulipHookInclude)
|
||||
target_link_libraries(GeodeCodegenSources PRIVATE ghc_filesystem GeodeFilesystemImpl fmt TulipHookInclude mat-json)
|
||||
target_include_directories(GeodeCodegenSources PRIVATE
|
||||
${GEODE_CODEGEN_PATH}
|
||||
${GEODE_LOADER_PATH}/include
|
||||
|
|
|
@ -408,12 +408,12 @@ class cocos2d::CCMenu {
|
|||
virtual auto registerWithTouchDispatcher() = mac 0x438cd0, ios 0x131f8c;
|
||||
virtual auto onExit() = mac 0x438bd0, ios 0x131ed4;
|
||||
virtual auto removeChild(cocos2d::CCNode*, bool) = mac 0x438c20, ios 0x15e630;
|
||||
auto initWithArray(cocos2d::CCArray*) = mac 0x4389f0, ios 0x131d04;
|
||||
auto itemForTouch(cocos2d::CCTouch*) = mac 0x438dd0;
|
||||
bool initWithArray(cocos2d::CCArray*) = mac 0x4389f0, ios 0x131d04;
|
||||
cocos2d::CCMenuItem* itemForTouch(cocos2d::CCTouch*) = mac 0x438dd0;
|
||||
}
|
||||
|
||||
class cocos2d::CCMenuItem {
|
||||
auto initWithTarget(cocos2d::CCObject*, cocos2d::SEL_MenuHandler) = mac 0x1fb7f0;
|
||||
bool initWithTarget(cocos2d::CCObject*, cocos2d::SEL_MenuHandler) = mac 0x1fb7f0;
|
||||
virtual ~CCMenuItem() = mac 0x1fb8e0, ios 0x2cdf4;
|
||||
virtual auto activate() = mac 0x1fba70, ios 0x2ceb0;
|
||||
virtual auto selected() = mac 0x1fb9e0, ios 0x2ce2e;
|
||||
|
@ -636,9 +636,6 @@ class cocos2d::CCObject {
|
|||
auto isEqual(cocos2d::CCObject const*) = mac 0x250f20, ios 0x439e4;
|
||||
auto release() = mac 0x250ea0, ios 0x43984;
|
||||
auto retain() = mac 0x250ec0, ios 0x439a8;
|
||||
unsigned int retainCount() const {
|
||||
return m_uReference;
|
||||
}
|
||||
|
||||
virtual auto setTag(int) = mac 0x250f60, ios 0x43a10;
|
||||
~CCObject() = mac 0x250d20, ios 0x6ac0;
|
||||
|
|
|
@ -97,7 +97,10 @@ class AppDelegate : cocos2d::CCApplication, cocos2d::CCSceneDelegate {
|
|||
void resumeSound() = win 0x3d4d0;
|
||||
void setupGLView() = win 0x3c950;
|
||||
|
||||
PAD = win 0x4;
|
||||
cocos2d::CCScene* m_runningScene;
|
||||
bool m_loadingFinished;
|
||||
// there's 0x18 more on Windows
|
||||
}
|
||||
|
||||
class ArtistCell : TableViewCell {
|
||||
|
@ -1245,7 +1248,7 @@ class EditorUI : cocos2d::CCLayer, FLAlertLayerProtocol, ColorSelectDelegate, GJ
|
|||
virtual void scaleChanged(float) = mac 0x25490, win 0x88df0;
|
||||
virtual void scaleChangeEnded() = win 0x88de0;
|
||||
void scaleObjects(cocos2d::CCArray*, float, cocos2d::CCPoint) = mac 0x252e0, win 0x8f150;
|
||||
void selectObjects(cocos2d::CCArray*, bool) = mac 0x23940, win 0x864a0;
|
||||
void selectObjects(cocos2d::CCArray* objs, bool ignoreFilters) = mac 0x23940, win 0x864a0;
|
||||
void setupCreateMenu() = mac 0xcb50, win 0x7caf0;
|
||||
void undoLastAction(cocos2d::CCObject*) = mac 0xb830, win 0x87070;
|
||||
void updateButtons() = mac 0x1a300, win 0x78280;
|
||||
|
@ -2355,7 +2358,12 @@ class GJGroundLayer : cocos2d::CCLayer {
|
|||
void updateGroundWidth() = mac 0x356790, win 0x12dda0;
|
||||
}
|
||||
|
||||
class GJItemIcon {
|
||||
class GJItemIcon : cocos2d::CCSprite {
|
||||
bool init(
|
||||
UnlockType, int, cocos2d::ccColor3B, cocos2d::ccColor3B,
|
||||
bool, bool, bool, cocos2d::ccColor3B
|
||||
) = win 0x12ccf0;
|
||||
|
||||
GJItemIcon* createBrowserIcon(UnlockType _type, int _id) {
|
||||
return GJItemIcon::create(_type, _id,
|
||||
{ 0xaf, 0xaf, 0xaf }, { 0xff, 0xff, 0xff },
|
||||
|
@ -3183,8 +3191,8 @@ class GameObject : CCSpritePlus {
|
|||
bool m_isEffectObject;
|
||||
bool m_randomisedAnimStart;
|
||||
float m_animSpeed;
|
||||
bool m_blackChild;
|
||||
bool m_unkOutlineMaybe;
|
||||
bool m_isBlackObject;
|
||||
bool m_isBlackObjectWithOutline;
|
||||
float m_blackChildOpacity;
|
||||
bool field_21C;
|
||||
bool m_editor;
|
||||
|
@ -3387,6 +3395,7 @@ class GameStatsManager : cocos2d::CCNode {
|
|||
void storePendingUserCoin(char const*) = mac 0x42940;
|
||||
void storeSecretCoin(char const*) = mac 0x42a10;
|
||||
void storeUserCoin(char const*) = mac 0x42890;
|
||||
bool isItemUnlocked(UnlockType type, int id) = win 0xfbb80;
|
||||
|
||||
PAD = win 0x28;
|
||||
cocos2d::CCDictionary* m_dailyChests;
|
||||
|
|
|
@ -168,7 +168,7 @@ std::string generateBindingHeader(Root& root, ghc::filesystem::path const& singl
|
|||
}
|
||||
|
||||
std::string supers = str_if(
|
||||
fmt::format(" : public {}", fmt::join(cls.superclasses, ", ")),
|
||||
fmt::format(" : public {}", fmt::join(cls.superclasses, ", public ")),
|
||||
!cls.superclasses.empty()
|
||||
);
|
||||
|
||||
|
|
6
loader/include/Geode/cocos/CCScheduler.h
vendored
6
loader/include/Geode/cocos/CCScheduler.h
vendored
|
@ -285,6 +285,12 @@ public:
|
|||
*/
|
||||
void resumeTargets(CCSet* targetsToResume);
|
||||
|
||||
/**
|
||||
* Get the shared scheduler from CCDirector
|
||||
* @note Geode addition
|
||||
*/
|
||||
static GEODE_DLL CCScheduler* get();
|
||||
|
||||
private:
|
||||
void removeHashElement(struct _hashSelectorEntry *pElement);
|
||||
void removeUpdateFromHash(struct _listEntry *entry);
|
||||
|
|
73
loader/include/Geode/cocos/base_nodes/CCNode.h
vendored
73
loader/include/Geode/cocos/base_nodes/CCNode.h
vendored
|
@ -38,7 +38,8 @@
|
|||
#include "../script_support/CCScriptSupport.h"
|
||||
#include "../include/CCProtocols.h"
|
||||
#include "Layout.hpp"
|
||||
#include <any>
|
||||
#include "../../loader/Event.hpp"
|
||||
#include <json.hpp>
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
|
@ -850,7 +851,11 @@ private:
|
|||
friend class geode::modifier::FieldContainer;
|
||||
|
||||
GEODE_DLL geode::modifier::FieldContainer* getFieldContainer();
|
||||
GEODE_DLL std::optional<std::any> getAttributeInternal(std::string const& attribute);
|
||||
GEODE_DLL std::optional<json::Value> getAttributeInternal(std::string const& attribute);
|
||||
GEODE_DLL void addEventListenerInternal(
|
||||
std::string const& id,
|
||||
geode::EventListenerProtocol* protocol
|
||||
);
|
||||
|
||||
public:
|
||||
/**
|
||||
|
@ -892,6 +897,7 @@ public:
|
|||
* @param before The child the node is added before of. If this is null or
|
||||
* not a child of this node, the new child will be placed at the start of the
|
||||
* child list
|
||||
* @note Geode addition
|
||||
*/
|
||||
GEODE_DLL void insertBefore(CCNode* child, CCNode* before);
|
||||
|
||||
|
@ -902,9 +908,20 @@ public:
|
|||
* @param after The child the node is added after of. If this is null or
|
||||
* not a child of this node, the new child will be placed at the end of the
|
||||
* child list
|
||||
* @note Geode addition
|
||||
*/
|
||||
GEODE_DLL void insertAfter(CCNode* child, CCNode* after);
|
||||
|
||||
/**
|
||||
* Check if this node's parent or its parents' parent is the given node
|
||||
* @param ancestor The node whose child or subchild this node should be. If
|
||||
* nullptr, returns true if the node is in the current scene, otherwise
|
||||
* false.
|
||||
* @returns True if ancestor is an ancestor of this node
|
||||
* @note Geode addition
|
||||
*/
|
||||
GEODE_DLL bool hasAncestor(CCNode* ancestor);
|
||||
|
||||
/**
|
||||
* Set an attribute on a node. Attributes are a system added by Geode,
|
||||
* where a node may have any sort of extra data associated with it. Used
|
||||
|
@ -917,7 +934,7 @@ public:
|
|||
* @param value The value of the attribute
|
||||
* @note Geode addition
|
||||
*/
|
||||
GEODE_DLL void setAttribute(std::string const& attribute, std::any value);
|
||||
GEODE_DLL void setAttribute(std::string const& attribute, json::Value const& value);
|
||||
/**
|
||||
* Get an attribute from the node. Attributes may be anything
|
||||
* @param attribute The attribute key
|
||||
|
@ -929,7 +946,7 @@ public:
|
|||
std::optional<T> getAttribute(std::string const& attribute) {
|
||||
if (auto value = this->getAttributeInternal(attribute)) {
|
||||
try {
|
||||
return std::any_cast<T>(value.value());
|
||||
return value.value().template as<T>();
|
||||
} catch(...) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
@ -986,6 +1003,31 @@ public:
|
|||
* @note Geode addition
|
||||
*/
|
||||
GEODE_DLL void swapChildIndices(CCNode* first, CCNode* second);
|
||||
|
||||
template <class Filter, class... Args>
|
||||
geode::EventListenerProtocol* addEventListener(
|
||||
std::string const& id,
|
||||
geode::utils::MiniFunction<typename Filter::Callback> callback,
|
||||
Args&&... args
|
||||
) {
|
||||
auto listener = new geode::EventListener<Filter>(
|
||||
callback, Filter(this, std::forward<Args>(args)...)
|
||||
);
|
||||
this->addEventListenerInternal(id, listener);
|
||||
return listener;
|
||||
}
|
||||
template <class Filter, class... Args>
|
||||
geode::EventListenerProtocol* addEventListener(
|
||||
geode::utils::MiniFunction<typename Filter::Callback> callback,
|
||||
Args&&... args
|
||||
) {
|
||||
return this->template addEventListener<Filter, Args...>(
|
||||
"", callback, std::forward<Args>(args)...
|
||||
);
|
||||
}
|
||||
GEODE_DLL void removeEventListener(geode::EventListenerProtocol* listener);
|
||||
GEODE_DLL void removeEventListener(std::string const& id);
|
||||
GEODE_DLL geode::EventListenerProtocol* getEventListener(std::string const& id);
|
||||
|
||||
/// @{
|
||||
/// @name Shader Program
|
||||
|
@ -1690,4 +1732,27 @@ protected:
|
|||
|
||||
NS_CC_END
|
||||
|
||||
namespace geode {
|
||||
struct GEODE_DLL AttributeSetEvent : public Event {
|
||||
cocos2d::CCNode* node;
|
||||
const std::string id;
|
||||
json::Value& value;
|
||||
|
||||
AttributeSetEvent(cocos2d::CCNode* node, std::string const& id, json::Value& value);
|
||||
};
|
||||
|
||||
class GEODE_DLL AttributeSetFilter : public EventFilter<AttributeSetEvent> {
|
||||
public:
|
||||
using Callback = void(AttributeSetEvent*);
|
||||
|
||||
protected:
|
||||
std::string m_targetID;
|
||||
|
||||
public:
|
||||
ListenerResult handle(utils::MiniFunction<Callback> fn, AttributeSetEvent* event);
|
||||
|
||||
AttributeSetFilter(std::string const& id);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // __PLATFORM_CCNODE_H__
|
||||
|
|
12
loader/include/Geode/cocos/cocoa/CCObject.h
vendored
12
loader/include/Geode/cocos/cocoa/CCObject.h
vendored
|
@ -100,16 +100,14 @@ public:
|
|||
int m_nLuaID;
|
||||
protected:
|
||||
// the object's tag
|
||||
RT_ADD( int m_nTag; )
|
||||
int m_nTag;
|
||||
// count of references
|
||||
unsigned int m_uReference;
|
||||
// count of autorelease
|
||||
unsigned int m_uAutoReleaseCount;
|
||||
|
||||
RT_ADD(
|
||||
CCObjectType m_eObjType;
|
||||
int m_nUnknown;
|
||||
)
|
||||
CCObjectType m_eObjType;
|
||||
int m_nUnknown;
|
||||
public:
|
||||
GEODE_CUSTOM_CONSTRUCTOR_BEGIN(CCObject)
|
||||
CCObject(void);
|
||||
|
@ -123,7 +121,9 @@ public:
|
|||
CCObject* autorelease(void);
|
||||
CCObject* copy(void);
|
||||
bool isSingleReference(void) const;
|
||||
inline unsigned int retainCount(void) const;
|
||||
inline unsigned int retainCount(void) const {
|
||||
return m_uReference;
|
||||
}
|
||||
virtual bool isEqual(const CCObject* pObject);
|
||||
|
||||
virtual void acceptVisitor(CCDataVisitor &visitor);
|
||||
|
|
|
@ -71,17 +71,19 @@ public:
|
|||
virtual ~CCScene();
|
||||
bool init();
|
||||
|
||||
static CCScene *create(void);
|
||||
static CCScene* create(void);
|
||||
/**
|
||||
* Get the running scene
|
||||
* @note Geode addition
|
||||
*/
|
||||
static GEODE_DLL CCScene* get();
|
||||
|
||||
RT_ADD(
|
||||
CCScene(const CCScene&);
|
||||
|
||||
CCScene& operator=(const CCScene&);
|
||||
CCScene(const CCScene&);
|
||||
CCScene& operator=(const CCScene&);
|
||||
|
||||
int getHighestChildZ(void);
|
||||
int getHighestChildZ(void);
|
||||
|
||||
CCSceneDelegate* m_pDelegate;
|
||||
)
|
||||
CCSceneDelegate* m_pDelegate;
|
||||
};
|
||||
|
||||
// end of scene group
|
||||
|
|
|
@ -42,14 +42,11 @@ public:
|
|||
*/
|
||||
virtual TargetPlatform getTargetPlatform();
|
||||
|
||||
RT_ADD(
|
||||
virtual void openURL(const char* url);
|
||||
virtual int run();
|
||||
virtual void setupGLView();
|
||||
virtual void platformShutdown();
|
||||
void toggleVerticalSync(bool);
|
||||
bool getVerticalSyncEnabled() const;
|
||||
)
|
||||
virtual void openURL(const char* url);
|
||||
virtual int run();
|
||||
virtual void setupGLView();
|
||||
virtual void platformShutdown();
|
||||
void toggleVerticalSync(bool);
|
||||
|
||||
/**
|
||||
* Sets the Resource root path.
|
||||
|
@ -65,8 +62,6 @@ public:
|
|||
|
||||
void setStartupScriptFilename(const gd::string& startupScriptFile);
|
||||
|
||||
bool getControllerConnected() const;
|
||||
|
||||
const gd::string& getStartupScriptFilename(void)
|
||||
{
|
||||
return m_startupScriptFilename;
|
||||
|
@ -76,8 +71,24 @@ protected:
|
|||
HINSTANCE m_hInstance;
|
||||
HACCEL m_hAccelTable;
|
||||
LARGE_INTEGER m_nAnimationInterval;
|
||||
gd::string m_resourceRootPath;
|
||||
gd::string m_startupScriptFilename;
|
||||
PAD(4);
|
||||
std::string m_resourceRootPath;
|
||||
std::string m_startupScriptFilename;
|
||||
void* m_pUnknown;
|
||||
bool m_bUpdateController;
|
||||
CC_SYNTHESIZE_NV(bool, m_bShutdownCalled, ShutdownCalled);
|
||||
INPUT m_iInput;
|
||||
CCPoint m_obUnknown1;
|
||||
CCPoint m_obUnknown2;
|
||||
bool m_bMouseControl;
|
||||
float m_fOldAnimationInterval;
|
||||
float m_fAnimationInterval;
|
||||
CC_SYNTHESIZE_READONLY_NV(bool, m_bVerticalSyncEnabled, VerticalSyncEnabled);
|
||||
CC_SYNTHESIZE_READONLY_NV(bool, m_bControllerConnected, ControllerConnected);
|
||||
CC_SYNTHESIZE_NV(bool, m_bSleepMode, SleepMode);
|
||||
CC_SYNTHESIZE_NV(bool, m_bForceTimer, ForceTimer);
|
||||
CC_SYNTHESIZE_NV(bool, m_bSmoothFix, SmoothFix);
|
||||
CC_SYNTHESIZE_NV(bool, m_bFullscreen, Fullscreen);
|
||||
|
||||
static CCApplication * sm_pSharedApplication;
|
||||
};
|
||||
|
|
|
@ -47,13 +47,13 @@ typedef enum
|
|||
} ccTouchSelectorFlag;
|
||||
|
||||
|
||||
enum {
|
||||
CCTOUCHBEGAN,
|
||||
CCTOUCHMOVED,
|
||||
CCTOUCHENDED,
|
||||
CCTOUCHCANCELLED,
|
||||
enum ccTouchType {
|
||||
CCTOUCHBEGAN = 0,
|
||||
CCTOUCHMOVED = 1,
|
||||
CCTOUCHENDED = 2,
|
||||
CCTOUCHCANCELLED = 3,
|
||||
|
||||
ccTouchMax,
|
||||
ccTouchMax = 4,
|
||||
};
|
||||
|
||||
class CCSet;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../utils/casts.hpp"
|
||||
#include "../utils/MiniFunction.hpp"
|
||||
|
||||
#include <Geode/DefaultInclude.hpp>
|
||||
#include <type_traits>
|
||||
|
@ -119,6 +120,10 @@ namespace geode {
|
|||
m_filter = filter;
|
||||
}
|
||||
|
||||
T getFilter() const {
|
||||
return m_filter;
|
||||
}
|
||||
|
||||
protected:
|
||||
utils::MiniFunction<Callback> m_callback = nullptr;
|
||||
T m_filter;
|
||||
|
@ -126,7 +131,6 @@ namespace geode {
|
|||
|
||||
class GEODE_DLL [[nodiscard]] Event {
|
||||
private:
|
||||
static std::unordered_set<EventListenerProtocol*>& listeners();
|
||||
friend EventListenerProtocol;
|
||||
|
||||
public:
|
||||
|
@ -137,7 +141,14 @@ namespace geode {
|
|||
void post() {
|
||||
postFrom(getMod());
|
||||
}
|
||||
|
||||
|
||||
virtual ~Event();
|
||||
|
||||
static std::vector<EventListenerProtocol*>& listeners();
|
||||
/**
|
||||
* Move an event listener to the front of the queue so it is always hit
|
||||
* first
|
||||
*/
|
||||
static void prioritize(EventListenerProtocol* listener);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -71,6 +71,24 @@ namespace geode {
|
|||
return "nullopt";
|
||||
}
|
||||
|
||||
template <class T>
|
||||
requires requires(T t) {
|
||||
parse(t);
|
||||
}
|
||||
std::string parse(std::vector<T> const& thing) {
|
||||
std::string res = "[";
|
||||
bool first = true;
|
||||
for (auto& t : thing) {
|
||||
if (!first) {
|
||||
res += ", ";
|
||||
}
|
||||
first = false;
|
||||
res += parse(t);
|
||||
}
|
||||
res += "]";
|
||||
return res;
|
||||
}
|
||||
|
||||
template <class A, class B>
|
||||
requires requires(A a, B b) {
|
||||
parse(a);
|
||||
|
|
|
@ -203,6 +203,7 @@ namespace geode {
|
|||
CircleBaseColor color = CircleBaseColor::Green,
|
||||
CircleBaseSize size = CircleBaseSize::Medium
|
||||
);
|
||||
cocos2d::CCSize getMaxTopSize() const override;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -356,6 +356,151 @@ namespace geode {
|
|||
}
|
||||
};
|
||||
|
||||
class GEODE_DLL WeakRefPool {
|
||||
std::unordered_set<cocos2d::CCObject*> m_pool;
|
||||
|
||||
public:
|
||||
static WeakRefPool* get();
|
||||
|
||||
bool isManaged(cocos2d::CCObject* obj);
|
||||
void manage(cocos2d::CCObject* obj);
|
||||
void check(cocos2d::CCObject* obj);
|
||||
};
|
||||
|
||||
/**
|
||||
* A smart pointer to a managed CCObject-deriving class. Like Ref, except
|
||||
* only holds a weak reference to the targeted object. When all non-weak
|
||||
* references (Refs, manual retain() calls) to the object are dropped, so
|
||||
* are all weak references.
|
||||
*
|
||||
* In essence, WeakRef is like a raw pointer, except that you can know if
|
||||
* the pointer is still valid or not, as WeakRef::lock() returns nullptr if
|
||||
* the pointed-to-object has already been freed.
|
||||
*
|
||||
* Note that an object pointed to by WeakRef is only released once some
|
||||
* WeakRef pointing to it checks for it after all other references to the
|
||||
* object have been dropped. If you store WeakRefs in a global map, you may
|
||||
* want to periodically lock all of them to make sure any memory that should
|
||||
* be freed is freed.
|
||||
*
|
||||
* @tparam T A type that inherits from CCObject.
|
||||
*/
|
||||
template <class T>
|
||||
class WeakRef final {
|
||||
static_assert(
|
||||
std::is_base_of_v<cocos2d::CCObject, T>,
|
||||
"WeakRef can only be used with a CCObject-inheriting class!"
|
||||
);
|
||||
|
||||
T* m_obj = nullptr;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Construct a WeakRef of an object. A weak reference is one that will
|
||||
* be valid as long as the object is referenced by other strong
|
||||
* references (such as Ref or manual retain calls), but once all strong
|
||||
* references are dropped, so are all weak references. The object is
|
||||
* freed once no strong references exist to it, and any WeakRef pointing
|
||||
* to it is freed or locked
|
||||
* @param obj Object to construct the WeakRef from
|
||||
*/
|
||||
WeakRef(T* obj) : m_obj(obj) {
|
||||
WeakRefPool::get()->manage(obj);
|
||||
}
|
||||
|
||||
WeakRef(WeakRef<T> const& other) : WeakRef(other.m_obj) {}
|
||||
|
||||
WeakRef(WeakRef<T>&& other) : m_obj(other.m_obj) {
|
||||
other.m_obj = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an empty WeakRef (the object will be null)
|
||||
*/
|
||||
WeakRef() = default;
|
||||
~WeakRef() {
|
||||
WeakRefPool::get()->check(m_obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock the WeakRef, returning a Ref if the pointed object is valid or
|
||||
* a null Ref if the object has been freed
|
||||
*/
|
||||
Ref<T> lock() const {
|
||||
if (WeakRefPool::get()->isManaged(m_obj)) {
|
||||
return Ref(m_obj);
|
||||
}
|
||||
return Ref<T>(nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the WeakRef points to a valid object
|
||||
*/
|
||||
bool valid() const {
|
||||
return WeakRefPool::get()->isManaged(m_obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Swap the managed object with another object. The managed object
|
||||
* will be released, and the new object retained
|
||||
* @param other The new object to swap to
|
||||
*/
|
||||
void swap(T* other) {
|
||||
WeakRefPool::get()->check(m_obj);
|
||||
m_obj = other;
|
||||
WeakRefPool::get()->manage(other);
|
||||
}
|
||||
|
||||
Ref<T> operator=(T* obj) {
|
||||
this->swap(obj);
|
||||
return this->lock();
|
||||
}
|
||||
|
||||
WeakRef<T>& operator=(WeakRef<T> const& other) {
|
||||
this->swap(other.m_obj);
|
||||
return *this;
|
||||
}
|
||||
|
||||
WeakRef<T>& operator=(WeakRef<T>&& other) {
|
||||
this->swap(other.m_obj);
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const noexcept {
|
||||
return this->valid();
|
||||
}
|
||||
|
||||
bool operator==(T* other) const {
|
||||
return m_obj == other;
|
||||
}
|
||||
|
||||
bool operator==(WeakRef<T> const& other) const {
|
||||
return m_obj == other.m_obj;
|
||||
}
|
||||
|
||||
bool operator!=(T* other) const {
|
||||
return m_obj != other;
|
||||
}
|
||||
|
||||
bool operator!=(WeakRef<T> const& other) const {
|
||||
return m_obj != other.m_obj;
|
||||
}
|
||||
|
||||
// for containers
|
||||
bool operator<(WeakRef<T> const& other) const {
|
||||
return m_obj < other.m_obj;
|
||||
}
|
||||
bool operator<=(WeakRef<T> const& other) const {
|
||||
return m_obj <= other.m_obj;
|
||||
}
|
||||
bool operator>(WeakRef<T> const& other) const {
|
||||
return m_obj > other.m_obj;
|
||||
}
|
||||
bool operator>=(WeakRef<T> const& other) const {
|
||||
return m_obj >= other.m_obj;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Filter>
|
||||
class EventListenerNode : public cocos2d::CCNode {
|
||||
protected:
|
||||
|
@ -375,8 +520,8 @@ namespace geode {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static EventListenerNode* create(typename Filter::Callback callback) {
|
||||
auto ret = new EventListenerNode(EventListener<Filter>(callback));
|
||||
static EventListenerNode* create(typename Filter::Callback callback, Filter filter = Filter()) {
|
||||
auto ret = new EventListenerNode(EventListener<Filter>(callback, filter));
|
||||
if (ret && ret->init()) {
|
||||
ret->autorelease();
|
||||
return ret;
|
||||
|
@ -385,7 +530,6 @@ namespace geode {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
template <class C>
|
||||
static EventListenerNode* create(
|
||||
C* cls, typename EventListener<Filter>::template MemberFn<C> callback
|
||||
|
|
|
@ -37,4 +37,12 @@ CCTextureCache* CCTextureCache::get() {
|
|||
return CCTextureCache::sharedTextureCache();
|
||||
}
|
||||
|
||||
CCScene* CCScene::get() {
|
||||
return CCDirector::get()->getRunningScene();
|
||||
}
|
||||
|
||||
CCScheduler* CCScheduler::get() {
|
||||
return CCDirector::get()->getScheduler();
|
||||
}
|
||||
|
||||
#pragma warning(pop)
|
||||
|
|
|
@ -37,6 +37,19 @@ void CCNode::insertAfter(CCNode* child, CCNode* after) {
|
|||
}
|
||||
}
|
||||
|
||||
bool CCNode::hasAncestor(CCNode* ancestor) {
|
||||
if (!ancestor) {
|
||||
ancestor = CCScene::get();
|
||||
}
|
||||
if (m_pParent == ancestor) {
|
||||
return true;
|
||||
}
|
||||
if (m_pParent) {
|
||||
return m_pParent->hasAncestor(ancestor);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CCArray* Layout::getNodesToPosition(CCNode* on) {
|
||||
if (!on->getChildren()) {
|
||||
return CCArray::create();
|
||||
|
|
|
@ -21,7 +21,9 @@ private:
|
|||
std::string m_id = "";
|
||||
Ref<Layout> m_layout = nullptr;
|
||||
std::unique_ptr<LayoutOptions> m_layoutOptions = nullptr;
|
||||
std::unordered_map<std::string, std::any> m_attributes;
|
||||
std::unordered_map<std::string, json::Value> m_attributes;
|
||||
std::unordered_set<std::unique_ptr<EventListenerProtocol>> m_eventListeners;
|
||||
std::unordered_map<std::string, std::unique_ptr<EventListenerProtocol>> m_idEventListeners;
|
||||
|
||||
friend class ProxyCCNode;
|
||||
friend class cocos2d::CCNode;
|
||||
|
@ -165,11 +167,25 @@ void CCNode::updateLayout(bool updateChildOrder) {
|
|||
}
|
||||
}
|
||||
|
||||
void CCNode::setAttribute(std::string const& attr, std::any value) {
|
||||
GeodeNodeMetadata::set(this)->m_attributes[attr] = value;
|
||||
AttributeSetEvent::AttributeSetEvent(CCNode* node, std::string const& id, json::Value& value)
|
||||
: node(node), id(id), value(value) {}
|
||||
|
||||
ListenerResult AttributeSetFilter::handle(MiniFunction<Callback> fn, AttributeSetEvent* event) {
|
||||
if (event->id == m_targetID) {
|
||||
fn(event);
|
||||
}
|
||||
return ListenerResult::Propagate;
|
||||
}
|
||||
|
||||
std::optional<std::any> CCNode::getAttributeInternal(std::string const& attr) {
|
||||
AttributeSetFilter::AttributeSetFilter(std::string const& id) : m_targetID(id) {}
|
||||
|
||||
void CCNode::setAttribute(std::string const& attr, json::Value const& value) {
|
||||
auto meta = GeodeNodeMetadata::set(this);
|
||||
meta->m_attributes[attr] = value;
|
||||
AttributeSetEvent(this, attr, meta->m_attributes.at(attr)).post();
|
||||
}
|
||||
|
||||
std::optional<json::Value> CCNode::getAttributeInternal(std::string const& attr) {
|
||||
auto meta = GeodeNodeMetadata::set(this);
|
||||
if (meta->m_attributes.count(attr)) {
|
||||
return meta->m_attributes.at(attr);
|
||||
|
@ -177,4 +193,44 @@ std::optional<std::any> CCNode::getAttributeInternal(std::string const& attr) {
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
void CCNode::addEventListenerInternal(std::string const& id, EventListenerProtocol* listener) {
|
||||
auto meta = GeodeNodeMetadata::set(this);
|
||||
if (id.size()) {
|
||||
if (meta->m_idEventListeners.contains(id)) {
|
||||
meta->m_idEventListeners.at(id).reset(listener);
|
||||
}
|
||||
else {
|
||||
meta->m_idEventListeners.emplace(id, listener);
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::erase_if(meta->m_eventListeners, [=](auto& l) {
|
||||
return l.get() == listener;
|
||||
});
|
||||
meta->m_eventListeners.emplace(listener);
|
||||
}
|
||||
}
|
||||
|
||||
void CCNode::removeEventListener(EventListenerProtocol* listener) {
|
||||
auto meta = GeodeNodeMetadata::set(this);
|
||||
std::erase_if(meta->m_eventListeners, [=](auto& l) {
|
||||
return l.get() == listener;
|
||||
});
|
||||
std::erase_if(meta->m_idEventListeners, [=](auto& l) {
|
||||
return l.second.get() == listener;
|
||||
});
|
||||
}
|
||||
|
||||
void CCNode::removeEventListener(std::string const& id) {
|
||||
GeodeNodeMetadata::set(this)->m_idEventListeners.erase(id);
|
||||
}
|
||||
|
||||
EventListenerProtocol* CCNode::getEventListener(std::string const& id) {
|
||||
auto meta = GeodeNodeMetadata::set(this);
|
||||
if (meta->m_idEventListeners.contains(id)) {
|
||||
return meta->m_idEventListeners.at(id).get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#pragma warning(pop)
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
#include <Geode/loader/Event.hpp>
|
||||
#include <Geode/utils/ranges.hpp>
|
||||
|
||||
using namespace geode::prelude;
|
||||
|
||||
void EventListenerProtocol::enable() {
|
||||
Event::listeners().insert(this);
|
||||
Event::listeners().push_back(this);
|
||||
}
|
||||
|
||||
void EventListenerProtocol::disable() {
|
||||
Event::listeners().erase(this);
|
||||
ranges::remove(Event::listeners(), this);
|
||||
}
|
||||
|
||||
EventListenerProtocol::~EventListenerProtocol() {
|
||||
|
@ -19,7 +20,7 @@ Event::~Event() {}
|
|||
void Event::postFrom(Mod* m) {
|
||||
if (m) this->sender = m;
|
||||
|
||||
std::unordered_set<EventListenerProtocol*> listeners_copy = Event::listeners();
|
||||
std::vector<EventListenerProtocol*> listeners_copy = Event::listeners();
|
||||
|
||||
for (auto h : listeners_copy) {
|
||||
if (h->passThrough(this) == ListenerResult::Stop) {
|
||||
|
@ -28,7 +29,11 @@ void Event::postFrom(Mod* m) {
|
|||
}
|
||||
}
|
||||
|
||||
std::unordered_set<EventListenerProtocol*>& Event::listeners() {
|
||||
static std::unordered_set<EventListenerProtocol*> listeners;
|
||||
std::vector<EventListenerProtocol*>& Event::listeners() {
|
||||
static std::vector<EventListenerProtocol*> listeners;
|
||||
return listeners;
|
||||
}
|
||||
|
||||
void Event::prioritize(EventListenerProtocol* listener) {
|
||||
ranges::move(Event::listeners(), listener, 0);
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ ghc::filesystem::path Mod::getBinaryPath() const {
|
|||
}
|
||||
|
||||
ghc::filesystem::path Mod::getResourcesDir() const {
|
||||
return dirs::getModRuntimeDir() / this->getID() / "resources";
|
||||
return dirs::getModRuntimeDir() / this->getID() / "resources" / this->getID();
|
||||
}
|
||||
|
||||
Result<> Mod::saveData() {
|
||||
|
|
|
@ -303,6 +303,10 @@ DECL_BASED_CREATE_FUNS(Leaderboard);
|
|||
DECL_BASED_CREATE_FUNS(Editor);
|
||||
DECL_BASED_CREATE_FUNS(Category);
|
||||
|
||||
CCSize CircleButtonSprite::getMaxTopSize() const {
|
||||
return m_obContentSize * .65f;
|
||||
}
|
||||
|
||||
CCSize EditorButtonSprite::getMaxTopSize() const {
|
||||
return m_obContentSize - CCSize { 8.f, 8.f };
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@ using namespace geode::prelude;
|
|||
bool Scrollbar::ccTouchBegan(CCTouch* touch, CCEvent* event) {
|
||||
// hitbox
|
||||
auto rect = this->boundingBox();
|
||||
// since anchor point is 0.5, 0.5 it's offset
|
||||
rect.origin -= this->getScaledContentSize() / 2;
|
||||
if (!m_target || !rect.containsPoint(touch->getLocation())) return false;
|
||||
|
||||
// trigger scrollbar thumb move
|
||||
|
@ -40,7 +38,7 @@ void Scrollbar::ccTouchMoved(CCTouch* touch, CCEvent*) {
|
|||
auto thumbHeight = m_resizeThumb ? std::min(p, 1.f) * targetHeight / .4f : 0;
|
||||
|
||||
auto posY = h *
|
||||
((-pos.y - targetHeight / 2 + thumbHeight / 4 - 5) / (targetHeight - thumbHeight / 2 + 10));
|
||||
((-pos.y + thumbHeight / 4 - 5) / (targetHeight - thumbHeight / 2 + 10));
|
||||
|
||||
if (posY > 0.0f) posY = 0.0f;
|
||||
if (posY < -h) posY = -h;
|
||||
|
@ -73,7 +71,7 @@ void Scrollbar::draw() {
|
|||
m_track->setContentSize({ m_width / m_track->getScale(),
|
||||
targetHeight / m_track->getScale() });
|
||||
}
|
||||
m_track->setPosition(.0f, .0f);
|
||||
m_track->setPosition(m_obContentSize / 2);
|
||||
|
||||
this->setContentSize({ m_width, targetHeight });
|
||||
|
||||
|
@ -113,15 +111,21 @@ void Scrollbar::draw() {
|
|||
|
||||
if (fHeightTop() > 0.0f) {
|
||||
thumbHeight -= fHeightTop();
|
||||
if (thumbHeight < 15.f) {
|
||||
thumbHeight = 15.f;
|
||||
}
|
||||
thumbPosY -= fHeightTop();
|
||||
}
|
||||
|
||||
if (fHeightBottom() < 0.f) {
|
||||
thumbHeight += fHeightBottom();
|
||||
if (thumbHeight < 15.f) {
|
||||
thumbHeight = 15.f;
|
||||
}
|
||||
thumbPosY -= fHeightBottom();
|
||||
}
|
||||
|
||||
m_thumb->setPosition(0.f, thumbPosY);
|
||||
m_thumb->setPosition(m_obContentSize / 2 + ccp(0.f, thumbPosY));
|
||||
if (m_resizeThumb) {
|
||||
m_thumb->setContentSize({ m_width, thumbHeight });
|
||||
}
|
||||
|
@ -134,6 +138,8 @@ void Scrollbar::setTarget(CCScrollLayerExt* target) {
|
|||
bool Scrollbar::init(CCScrollLayerExt* target) {
|
||||
if (!this->CCLayer::init()) return false;
|
||||
|
||||
this->ignoreAnchorPointForPosition(false);
|
||||
|
||||
m_target = target;
|
||||
|
||||
if (cocos::fileExistsInSearchPaths("scrollbar.png"_spr)) {
|
||||
|
|
|
@ -233,6 +233,32 @@ std::string geode::cocos::cc4bToHexString(ccColor4B const& color) {
|
|||
return output;
|
||||
}
|
||||
|
||||
WeakRefPool* WeakRefPool::get() {
|
||||
static auto inst = new WeakRefPool();
|
||||
return inst;
|
||||
}
|
||||
|
||||
void WeakRefPool::check(CCObject* obj) {
|
||||
// if this object's only reference is the WeakRefPool aka only weak
|
||||
// references exist to it, then release it
|
||||
if (m_pool.contains(obj) && obj->retainCount() == 1) {
|
||||
obj->release();
|
||||
m_pool.erase(obj);
|
||||
}
|
||||
}
|
||||
|
||||
bool WeakRefPool::isManaged(CCObject* obj) {
|
||||
this->check(obj);
|
||||
return m_pool.contains(obj);
|
||||
}
|
||||
|
||||
void WeakRefPool::manage(CCObject* obj) {
|
||||
if (obj && !m_pool.contains(obj)) {
|
||||
obj->retain();
|
||||
m_pool.insert(obj);
|
||||
}
|
||||
}
|
||||
|
||||
CCRect geode::cocos::calculateNodeCoverage(std::vector<CCNode*> const& nodes) {
|
||||
CCRect coverage;
|
||||
for (auto child : nodes) {
|
||||
|
|
|
@ -17,6 +17,6 @@ target_include_directories(${PROJECT_NAME} PRIVATE
|
|||
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE -DGEODE_DONT_WARN_INCORRECT_MEMBERS)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ghc_filesystem)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ghc_filesystem mat-json)
|
||||
|
||||
add_dependencies(${PROJECT_NAME} CodegenRun)
|
Loading…
Reference in a new issue