mirror of
https://github.com/geode-sdk/geode.git
synced 2025-03-28 13:52:07 -04:00
Merge branch 'main' into new-index-but-better
This commit is contained in:
commit
89273c9458
15 changed files with 309 additions and 25 deletions
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -1,5 +1,17 @@
|
|||
# Geode Changelog
|
||||
|
||||
## v2.0.0-beta.26
|
||||
* Bring in several UI helpers from the `new-index-but-better` branch: `ListBorders`, `addSideArt`, `AxisLayout` improvements, ... (26729c3, 7ff257c)
|
||||
* Make it possible to compile mods in Debug mode (517ad45)
|
||||
* Add `GJDifficultyName` and `GJFeatureState` (#706)
|
||||
* Add `geode::cocos::isSpriteName` and `geode::cocos::getChildBySpriteName` (#725)
|
||||
* Add some Android keycodes (4fa8098)
|
||||
* Update FMOD on Mac (c4a682b)
|
||||
* Bump JSON version (5cc23e7)
|
||||
* Fixes to `InputNode` touches (29b4732)
|
||||
* Fix `file::readFromJson` (77e0f2e)
|
||||
* Fix issues with TulipHook (f2ce7d0)
|
||||
|
||||
## v2.0.0-beta.25
|
||||
* Fix updater sometimes skipping releases (18dd0b7)
|
||||
* Fix resources getting downloaded every time (5f571d9)
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
2.0.0-beta.25
|
||||
2.0.0-beta.26
|
16
loader/include/Geode/cocos/base_nodes/CCNode.h
vendored
16
loader/include/Geode/cocos/base_nodes/CCNode.h
vendored
|
@ -913,6 +913,22 @@ public:
|
|||
*/
|
||||
GEODE_DLL CCNode* getChildByIDRecursive(std::string const& id);
|
||||
|
||||
/**
|
||||
* Get a child based on a query. Searches the child tree for a matching
|
||||
* child. The query currently only supports the following features:
|
||||
* - `node-id`: Match a node with a specific ID
|
||||
* - `node-id-1 node-id-2`: Match a descendant (possibly not immediate)
|
||||
* child of a node with a specific ID
|
||||
* - `node-id-1 > node-id-2`: Match the immediate child of a node with a
|
||||
* specific ID
|
||||
* For example, the query "my-layer button-menu > mod.id/epic-button" is
|
||||
* equivalent to `getChildByIDRecursive("my-layer")
|
||||
* ->getChildByIDRecursive("button-menu")
|
||||
* ->getChildByID("mod.id/epic-button")`
|
||||
* @returns The first matching node, or nullptr if none was found
|
||||
*/
|
||||
GEODE_DLL CCNode* querySelector(std::string const& query);
|
||||
|
||||
/**
|
||||
* Removes a child from the container by its ID.
|
||||
* @param id The ID of the node
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "../cocoa/CCArray.h"
|
||||
#include <Geode/platform/platform.hpp>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
|
|
|
@ -313,7 +313,31 @@ public:
|
|||
virtual bool isBlendAdditive();
|
||||
virtual void setBlendAdditive(bool value);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
RT_ADD(
|
||||
float m_fFadeInTime;
|
||||
float m_fFadeInTimeVar;
|
||||
float m_fFadeOutTime;
|
||||
float m_fFadeOutTimeVar;
|
||||
float m_fFrictionPos;
|
||||
float m_fFrictionPosVar;
|
||||
float m_fFrictionSize;
|
||||
float m_fFrictionSizeVar;
|
||||
float m_fFrictionRot;
|
||||
float m_fFrictionRotVar;
|
||||
float m_fRespawn;
|
||||
float m_fRespawnVar;
|
||||
bool m_bStartSpinEqualToEnd;
|
||||
bool m_bStartSizeEqualToEnd;
|
||||
bool m_bStartRadiusEqualToEnd;
|
||||
bool m_bDynamicRotationIsDir;
|
||||
bool m_bOrderSensitive;
|
||||
bool m_bStartRGBVarSync;
|
||||
bool m_bEndRGBVarSync;
|
||||
bool m_bWasRemoved;
|
||||
bool m_bUsingSchedule;
|
||||
)
|
||||
|
||||
/** start size in pixels of each particle */
|
||||
CC_PROPERTY(float, m_fStartSize, StartSize)
|
||||
/** size variance in pixels of each particle */
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "CCStdC.h"
|
||||
#include "../CCCommon.h"
|
||||
#include "../CCApplicationProtocol.h"
|
||||
#include "CCControllerHandler.h"
|
||||
#include "CXBOXController.h"
|
||||
#include <string>
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
@ -51,7 +51,7 @@ public:
|
|||
RT_ADD(
|
||||
void setupVerticalSync();
|
||||
void updateVerticalSync();
|
||||
void updateControllerKeys();
|
||||
void updateControllerKeys(CXBOXController* controller, int userIndex);
|
||||
|
||||
int getTimeElapsed();
|
||||
void resetForceTimer();
|
||||
|
@ -96,8 +96,8 @@ public:
|
|||
LARGE_INTEGER m_nVsyncInterval;
|
||||
gd::string m_resourceRootPath;
|
||||
gd::string m_startupScriptFilename;
|
||||
CCControllerHandler* m_pControllerHandler;
|
||||
void* m_unk; //might be swapped with m_pControllerHandler
|
||||
CXBOXController* m_pControllerHandler;
|
||||
CXBOXController* m_pController2Handler; //might be swapped with m_pControllerHandler
|
||||
bool m_bUpdateController;
|
||||
CC_SYNTHESIZE_NV(bool, m_bShutdownCalled, ShutdownCalled);
|
||||
INPUT m_iInput;
|
||||
|
@ -114,6 +114,7 @@ public:
|
|||
CC_SYNTHESIZE_NV(bool, m_bFullscreen, Fullscreen);
|
||||
CC_SYNTHESIZE_NV(bool, m_bBorderless, Borderless);
|
||||
|
||||
protected:
|
||||
static CCApplication * sm_pSharedApplication;
|
||||
};
|
||||
|
||||
|
|
|
@ -208,7 +208,9 @@ public:
|
|||
float m_fMouseX;
|
||||
float m_fMouseY;
|
||||
bool m_bIsFullscreen;
|
||||
bool m_bIsBorderless;
|
||||
bool m_bShouldHideCursor;
|
||||
bool m_bCursorLocked;
|
||||
bool m_bShouldCallGLFinish;
|
||||
)
|
||||
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
#ifndef __CC_CONTROLLER_HANDLER_WIN32_H__
|
||||
#define __CC_CONTROLLER_HANDLER_WIN32_H__
|
||||
#ifndef __CXBOXCONTROLLER_WIN32_H__
|
||||
#define __CXBOXCONTROLLER_WIN32_H__
|
||||
|
||||
#include "../../include/ccMacros.h"
|
||||
#include "CCStdC.h"
|
||||
#include "CCControllerState.h"
|
||||
#include <Xinput.h>
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
class CC_DLL CCControllerHandler
|
||||
class CC_DLL CXBOXController
|
||||
{
|
||||
GEODE_FRIEND_MODIFY
|
||||
public:
|
||||
|
@ -35,6 +33,4 @@ public:
|
|||
bool m_buttonY;
|
||||
};
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -27,6 +27,13 @@ namespace geode {
|
|||
return static_cast<bool>(static_cast<int>(a) & static_cast<int>(b));
|
||||
}
|
||||
|
||||
enum class SideArtStyle {
|
||||
Layer,
|
||||
LayerGray,
|
||||
PopupBlue,
|
||||
PopupGold,
|
||||
};
|
||||
|
||||
/**
|
||||
* Add side art (corner pieces) for a layer
|
||||
* @param to Layer to add corner pieces to
|
||||
|
@ -34,7 +41,25 @@ namespace geode {
|
|||
* @param useAnchorLayout If true, `to` is given an `AnchorLayout` and the
|
||||
* corners' positions are dynamically updated
|
||||
*/
|
||||
GEODE_DLL void addSideArt(cocos2d::CCNode* to, SideArt sides = SideArt::All, bool useAnchorLayout = false);
|
||||
GEODE_DLL void addSideArt(
|
||||
cocos2d::CCNode* to,
|
||||
SideArt sides = SideArt::All,
|
||||
bool useAnchorLayout = false
|
||||
);
|
||||
/**
|
||||
* Add side art (corner pieces) for a layer
|
||||
* @param to Layer to add corner pieces to
|
||||
* @param sides Which corners to populate; by default, populates all
|
||||
* @param style Which side art sprites to use
|
||||
* @param useAnchorLayout If true, `to` is given an `AnchorLayout` and the
|
||||
* corners' positions are dynamically updated
|
||||
*/
|
||||
GEODE_DLL void addSideArt(
|
||||
cocos2d::CCNode* to,
|
||||
SideArt sides,
|
||||
SideArtStyle style,
|
||||
bool useAnchorLayout = false
|
||||
);
|
||||
|
||||
/**
|
||||
* Add the rounded comment borders to a node
|
||||
|
|
|
@ -196,6 +196,13 @@ namespace geode {
|
|||
return this->Base::value_or(std::forward<U>(val));
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr decltype(auto) unwrapOrDefault() && requires std::is_default_constructible_v<T> {
|
||||
return this->Base::value_or(T());
|
||||
}
|
||||
[[nodiscard]] constexpr decltype(auto) unwrapOrDefault() const& requires std::is_default_constructible_v<T> {
|
||||
return this->Base::value_or(T());
|
||||
}
|
||||
|
||||
template <class U>
|
||||
[[nodiscard]] constexpr decltype(auto) errorOr(U&& val) && {
|
||||
return this->Base::error_or(std::forward<U>(val));
|
||||
|
|
|
@ -153,6 +153,13 @@ namespace geode {
|
|||
}
|
||||
|
||||
GEODE_DLL std::string timePointAsString(std::chrono::system_clock::time_point const& tp);
|
||||
|
||||
/**
|
||||
* Gets the display pixel factor for the current screen,
|
||||
* i.e. the ratio between physical pixels and logical pixels on one axis.
|
||||
* On most platforms this is 1.0, but on retina displays for example this returns 2.0.
|
||||
*/
|
||||
GEODE_DLL float getDisplayFactor();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <Geode/modify/Field.hpp>
|
||||
#include <Geode/modify/CCNode.hpp>
|
||||
#include <cocos2d.h>
|
||||
#include <queue>
|
||||
|
||||
using namespace geode::prelude;
|
||||
using namespace geode::modifier;
|
||||
|
@ -143,6 +144,162 @@ CCNode* CCNode::getChildByIDRecursive(std::string const& id) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
class BFSNodeTreeCrawler final {
|
||||
private:
|
||||
std::queue<CCNode*> m_queue;
|
||||
std::unordered_set<CCNode*> m_explored;
|
||||
|
||||
public:
|
||||
BFSNodeTreeCrawler(CCNode* target) {
|
||||
if (auto first = getChild(target, 0)) {
|
||||
m_explored.insert(first);
|
||||
m_queue.push(first);
|
||||
}
|
||||
}
|
||||
|
||||
CCNode* next() {
|
||||
if (m_queue.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
auto node = m_queue.front();
|
||||
m_queue.pop();
|
||||
for (auto sibling : CCArrayExt<CCNode*>(node->getParent()->getChildren())) {
|
||||
if (!m_explored.contains(sibling)) {
|
||||
m_explored.insert(sibling);
|
||||
m_queue.push(sibling);
|
||||
}
|
||||
}
|
||||
for (auto child : CCArrayExt<CCNode*>(node->getChildren())) {
|
||||
if (!m_explored.contains(child)) {
|
||||
m_explored.insert(child);
|
||||
m_queue.push(child);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
};
|
||||
|
||||
class NodeQuery final {
|
||||
private:
|
||||
enum class Op {
|
||||
ImmediateChild,
|
||||
DescendantChild,
|
||||
};
|
||||
|
||||
std::string m_targetID;
|
||||
Op m_nextOp;
|
||||
std::unique_ptr<NodeQuery> m_next = nullptr;
|
||||
|
||||
public:
|
||||
static Result<std::unique_ptr<NodeQuery>> parse(std::string const& query) {
|
||||
if (query.empty()) {
|
||||
return Err("Query may not be empty");
|
||||
}
|
||||
|
||||
auto result = std::make_unique<NodeQuery>();
|
||||
NodeQuery* current = result.get();
|
||||
|
||||
size_t i = 0;
|
||||
std::string collectedID;
|
||||
std::optional<Op> nextOp = Op::DescendantChild;
|
||||
while (i < query.size()) {
|
||||
auto c = query.at(i);
|
||||
if (c == ' ') {
|
||||
if (!nextOp) {
|
||||
nextOp.emplace(Op::DescendantChild);
|
||||
}
|
||||
}
|
||||
else if (c == '>') {
|
||||
if (!nextOp || *nextOp == Op::DescendantChild) {
|
||||
nextOp.emplace(Op::ImmediateChild);
|
||||
}
|
||||
// Double >> is syntax error
|
||||
else {
|
||||
return Err("Can't have multiple child operators at once (index {})", i);
|
||||
}
|
||||
}
|
||||
// ID-valid characters
|
||||
else if (std::isalnum(c) || c == '-' || c == '_' || c == '/' || c == '.') {
|
||||
if (nextOp) {
|
||||
current->m_next = std::make_unique<NodeQuery>();
|
||||
current->m_nextOp = *nextOp;
|
||||
current->m_targetID = collectedID;
|
||||
current = current->m_next.get();
|
||||
|
||||
collectedID = "";
|
||||
nextOp = std::nullopt;
|
||||
}
|
||||
collectedID.push_back(c);
|
||||
}
|
||||
// Any other character is syntax error due to needing to reserve
|
||||
// stuff for possible future features
|
||||
else {
|
||||
return Err("Unexpected character '{}' at index {}", c, i);
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
if (nextOp || collectedID.empty()) {
|
||||
return Err("Expected node ID but got end of query");
|
||||
}
|
||||
current->m_targetID = collectedID;
|
||||
|
||||
return Ok(std::move(result));
|
||||
}
|
||||
|
||||
CCNode* match(CCNode* node) const {
|
||||
// Make sure this matches the ID being looked for
|
||||
if (!m_targetID.empty() && node->getID() != m_targetID) {
|
||||
return nullptr;
|
||||
}
|
||||
// If this is the last thing to match, return the result
|
||||
if (!m_next) {
|
||||
return node;
|
||||
}
|
||||
switch (m_nextOp) {
|
||||
case Op::ImmediateChild: {
|
||||
for (auto c : CCArrayExt<CCNode*>(node->getChildren())) {
|
||||
if (auto r = m_next->match(c)) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case Op::DescendantChild: {
|
||||
auto crawler = BFSNodeTreeCrawler(node);
|
||||
while (auto c = crawler.next()) {
|
||||
if (auto r = m_next->match(c)) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string toString() const {
|
||||
auto str = m_targetID.empty() ? "&" : m_targetID;
|
||||
if (m_next) {
|
||||
switch (m_nextOp) {
|
||||
case Op::ImmediateChild: str += " > "; break;
|
||||
case Op::DescendantChild: str += " "; break;
|
||||
}
|
||||
str += m_next->toString();
|
||||
}
|
||||
return str;
|
||||
}
|
||||
};
|
||||
|
||||
CCNode* CCNode::querySelector(std::string const& queryStr) {
|
||||
auto res = NodeQuery::parse(queryStr);
|
||||
if (!res) {
|
||||
log::error("Invalid CCNode::querySelector query '{}': {}", queryStr, res.unwrapErr());
|
||||
return nullptr;
|
||||
}
|
||||
auto query = std::move(res.unwrap());
|
||||
log::info("parsed query: {}", query->toString());
|
||||
return query->match(this);
|
||||
}
|
||||
|
||||
void CCNode::removeChildByID(std::string const& id) {
|
||||
if (auto child = this->getChildByID(id)) {
|
||||
this->removeChild(child);
|
||||
|
|
|
@ -9,6 +9,10 @@ using namespace geode::prelude;
|
|||
#include <objc/runtime.h>
|
||||
#include <Geode/utils/web.hpp>
|
||||
|
||||
#define CommentType CommentTypeDummy
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#undef CommentType
|
||||
|
||||
bool utils::clipboard::write(std::string const& data) {
|
||||
[[NSPasteboard generalPasteboard] clearContents];
|
||||
[[NSPasteboard generalPasteboard] setString:[NSString stringWithUTF8String:data.c_str()]
|
||||
|
@ -332,3 +336,16 @@ std::string geode::utils::thread::getDefaultName() {
|
|||
void geode::utils::thread::platformSetName(std::string const& name) {
|
||||
pthread_setname_np(name.c_str());
|
||||
}
|
||||
|
||||
float geode::utils::getDisplayFactor() {
|
||||
float displayScale = 1.f;
|
||||
if ([[NSScreen mainScreen] respondsToSelector:@selector(backingScaleFactor)]) {
|
||||
NSArray* screens = [NSScreen screens];
|
||||
for (int i = 0; i < screens.count; i++) {
|
||||
float s = [screens[i] backingScaleFactor];
|
||||
if (s > displayScale)
|
||||
displayScale = s;
|
||||
}
|
||||
}
|
||||
return displayScale;
|
||||
}
|
|
@ -18,28 +18,40 @@ CCSprite* geode::createLayerBG() {
|
|||
return bg;
|
||||
}
|
||||
|
||||
void geode::addSideArt(CCNode* to, SideArt sides, bool useAnchorLayout) {
|
||||
void geode::addSideArt(CCNode* to, SideArt sides, SideArtStyle style, bool useAnchorLayout) {
|
||||
const char* sprite;
|
||||
float offset;
|
||||
switch (style) {
|
||||
default:
|
||||
case SideArtStyle::Layer: sprite = "GJ_sideArt_001.png"; offset = 35; break;
|
||||
case SideArtStyle::LayerGray: sprite = "gauntletCorner_001.png"; offset = 35; break;
|
||||
case SideArtStyle::PopupBlue: sprite = "rewardCorner_001.png"; offset = 24.75f; break;
|
||||
case SideArtStyle::PopupGold: sprite = "dailyLevelCorner_001.png"; offset = 24.75f; break;
|
||||
}
|
||||
if (sides & SideArt::BottomLeft) {
|
||||
auto spr = CCSprite::createWithSpriteFrameName("GJ_sideArt_001.png");
|
||||
to->addChildAtPosition(spr, Anchor::BottomLeft, ccp(35, 35), useAnchorLayout);
|
||||
auto spr = CCSprite::createWithSpriteFrameName(sprite);
|
||||
to->addChildAtPosition(spr, Anchor::BottomLeft, ccp(offset, offset), useAnchorLayout);
|
||||
}
|
||||
if (sides & SideArt::BottomRight) {
|
||||
auto spr = CCSprite::createWithSpriteFrameName("GJ_sideArt_001.png");
|
||||
auto spr = CCSprite::createWithSpriteFrameName(sprite);
|
||||
spr->setFlipX(true);
|
||||
to->addChildAtPosition(spr, Anchor::BottomRight, ccp(-35, 35), useAnchorLayout);
|
||||
to->addChildAtPosition(spr, Anchor::BottomRight, ccp(-offset, offset), useAnchorLayout);
|
||||
}
|
||||
if (sides & SideArt::TopLeft) {
|
||||
auto spr = CCSprite::createWithSpriteFrameName("GJ_sideArt_001.png");
|
||||
auto spr = CCSprite::createWithSpriteFrameName(sprite);
|
||||
spr->setFlipY(true);
|
||||
to->addChildAtPosition(spr, Anchor::TopLeft, ccp(35, -35), useAnchorLayout);
|
||||
to->addChildAtPosition(spr, Anchor::TopLeft, ccp(offset, -offset), useAnchorLayout);
|
||||
}
|
||||
if (sides & SideArt::TopRight) {
|
||||
auto spr = CCSprite::createWithSpriteFrameName("GJ_sideArt_001.png");
|
||||
auto spr = CCSprite::createWithSpriteFrameName(sprite);
|
||||
spr->setFlipX(true);
|
||||
spr->setFlipY(true);
|
||||
to->addChildAtPosition(spr, Anchor::TopRight, ccp(-35, -35), useAnchorLayout);
|
||||
to->addChildAtPosition(spr, Anchor::TopRight, ccp(-offset, -offset), useAnchorLayout);
|
||||
}
|
||||
}
|
||||
void geode::addSideArt(CCNode* to, SideArt sides, bool useAnchorLayout) {
|
||||
return addSideArt(to, sides, SideArtStyle::Layer, useAnchorLayout);
|
||||
}
|
||||
|
||||
void geode::addListBorders(CCNode* to, CCPoint const& center, CCSize const& size) {
|
||||
// if the size is 346.f, the top aligns perfectly by default :3
|
||||
|
|
8
loader/src/utils/general.cpp
Normal file
8
loader/src/utils/general.cpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <Geode/utils/general.hpp>
|
||||
|
||||
#ifndef GEODE_IS_MACOS
|
||||
// feel free to properly implement this for other platforms
|
||||
float geode::utils::getDisplayFactor() {
|
||||
return 1.0f;
|
||||
}
|
||||
#endif
|
Loading…
Add table
Reference in a new issue