Merge branch '1.4.0-dev' into android

This commit is contained in:
altalk23 2023-10-15 16:07:42 +03:00
commit 335cc445c3
11 changed files with 272 additions and 104 deletions

View file

@ -2,17 +2,16 @@ name: Crash Report
description: Report a Geode bug (not mods themselves) that crashes the game or prevents startup caused by Geode Loader (not mods created by others).
labels: [ "unverified", "crash" ]
body:
- type: input
id: geode-confirmation
- type: checkboxes
attributes:
label: Geode Issue
description: |
The Geode repository is for issues of *Geode Loader*, not individual mods created by other developers.
When submitting a crash report, please make sure that the crash is *actually* related to ***Geode Loader itself*** and not to a mod or mod combination, after you do that type in "confirm" in the input field above.
When submitting a crash report, please make sure that the crash is *actually* related to ***Geode Loader itself*** and not to a mod or mod combination.
Failing to do this will get your issue *closed without explanation*.
placeholder: "Please, read the text below."
validations:
required: true
options:
- label: I confirm that this crash is NOT related to a mod but directly to Geode Loader itself.
required: true
- type: dropdown
id: platform
attributes:

View file

@ -89,6 +89,16 @@ class cocos2d::CCCallFuncO {
static auto create(cocos2d::CCObject*, cocos2d::SEL_CallFuncO, cocos2d::CCObject*) = mac 0x455940;
}
[[link(win, android)]]
class cocos2d::CCCallFuncND {
static auto create(cocos2d::CCObject*, cocos2d::SEL_CallFuncND, void*) = mac 0x455470;
}
[[link(win, android)]]
class cocos2d::CCCallFuncND {
static auto create(cocos2d::CCObject*, cocos2d::SEL_CallFuncND, void*) = mac 0x455470;
}
[[link(win, android)]]
class cocos2d::CCClippingNode {
CCClippingNode() {

View file

@ -1069,16 +1069,44 @@ class CustomSongLayer : FLAlertLayer, FLAlertLayerProtocol, TextInputDelegate, G
[[link(android)]]
class CustomSongWidget : cocos2d::CCNode, MusicDownloadDelegate, FLAlertLayerProtocol {
bool init(SongInfoObject*, LevelSettingsObject*, bool, bool, bool, bool, bool hideBackground) = mac 0x37be20, win 0x685b0;
bool init(SongInfoObject*, LevelSettingsObject*, bool, bool, bool, bool, bool) = mac 0x37be20, win 0x685b0;
void FLAlert_Clicked(FLAlertLayer*, bool) {}
void loadSongInfoFinished(SongInfoObject*) {}
void startDownload() = win 0x69610;
void startMonitorDownload() = win 0x696b0;
void updatePlaybackBtn() = win 0x69970;
void updateSongInfo() = win 0x69bf0;
void updateSongObject(SongInfoObject* song) = win 0x69280, mac 0x37d690;
void onCancelDownload(CCObject*) = win 0x693b0;
void onDownload(CCObject*) = win 0x69540;
void onGetSongInfo(CCObject*) = win 0x69490;
void onMore(CCObject*) = win 0x68e20;
void onPlayback(CCObject*) = win 0x697b0;
void onSelect(CCObject*) = win 0x69760;
SongInfoObject* m_songInfo;
PAD = win 0x1C;
cocos2d::CCMenu* m_buttonMenu;
cocos2d::CCLabelBMFont* m_songLabel;
cocos2d::CCLabelBMFont* m_artistLabel;
cocos2d::CCLabelBMFont* m_songIDLabel;
cocos2d::CCLabelBMFont* m_errorLabel;
CCMenuItemSpriteExtra* m_downloadBtn;
PAD = win 0x30;
CCMenuItemSpriteExtra* m_cancelDownloadBtn;
CCMenuItemSpriteExtra* m_selectSongBtn;
CCMenuItemSpriteExtra* m_getSongInfoBtn;
CCMenuItemSpriteExtra* m_playMusicBtn;
CCMenuItemSpriteExtra* m_moreBtn;
cocos2d::CCSprite* m_sliderGroove;
cocos2d::CCSprite* m_sliderBar;
LevelSettingsObject* m_levelSettings;
bool m_showSelectSongBtn;
bool m_showPlayMusicBtn;
bool m_showDownloadButtons;
bool m_isNotDownloading;
bool m_hasDefaultSong;
int m_customSongID;
bool m_unkBool;
}
[[link(android)]]
@ -1205,9 +1233,9 @@ class DrawGridLayer : cocos2d::CCLayer {
return editorLayer->m_drawGridLayer;
}
bool init(cocos2d::CCNode* grid, LevelEditorLayer* editor) = win 0x16c4d0;
bool init(cocos2d::CCNode* grid, LevelEditorLayer* editor) = win 0x16c4d0, mac 0x2729a0;
virtual void draw() = win 0x16ce90, mac 0xa3c40;
virtual void update(float) = win 0x16cd80;
virtual void update(float) = win 0x16cd80, mac 0xa3b30;
void clearPlayerPoints() {
m_playerNodePoints->removeAllObjects();
m_player2NodePoints->removeAllObjects();
@ -1479,6 +1507,7 @@ class EditorUI : cocos2d::CCLayer, FLAlertLayerProtocol, ColorSelectDelegate, GJ
void onSettings(cocos2d::CCObject* sender) = win 0x77fe0;
void activateRotationControl(cocos2d::CCObject* sender) = win 0x8fe70, mac 0x24480;
void activateScaleControl(cocos2d::CCObject* sender) = mac 0x24c80, win 0x889b0;
void deactivateScaleControl() = win 0x88bf0, mac 0xb290;
void dynamicGroupUpdate(bool idk) = win 0x8ad10;
void createRockOutline() = win 0x89c10;
void createRockEdges() = win 0x88ec0;
@ -1499,6 +1528,7 @@ class EditorUI : cocos2d::CCLayer, FLAlertLayerProtocol, ColorSelectDelegate, GJ
void repositionObjectsToCenter(cocos2d::CCArray* objs, cocos2d::CCPoint center, bool ignoreGroupParent) = mac 0x1fcd0, win 0x88410;
virtual void draw() = win 0x8fbe0;
float valueFromXPos(float val) = win 0x78e30, mac 0x1c810;
void processSelectObjects(cocos2d::CCArray*) = win 0x86f70, mac 0x24110;
bool m_isPlayingMusic;
EditButtonBar* m_buttonBar;
@ -1804,15 +1834,17 @@ class FLAlertLayerProtocol {
[[link(android)]]
class FMODAudioEngine : cocos2d::CCNode {
static FMODAudioEngine* sharedEngine() = mac 0x20ef80, win 0x239f0;
void setupAudioEngine() = win 0x23a70;
void preloadEffect(gd::string filename) = win 0x24240;
bool isBackgroundMusicPlaying() = win 0x24050;
bool isBackgroundMusicPlaying(gd::string path) = win 0x24080;
void playBackgroundMusic(gd::string path, bool fade, bool paused) = win 0x23d80;
void setBackgroundMusicTime(float time) = win 0x23fb0;
virtual void update(float) = win 0x23b20;
cocos2d::CCDictionary* m_dictionary;
std::string m_filePath;
gd::string m_filePath;
float m_backgroundMusicVolume;
float m_effectsVolume;
float m_pulse1;
@ -2533,10 +2565,14 @@ class GJGarageLayer : cocos2d::CCLayer, TextInputDelegate, FLAlertLayerProtocol,
void onDartIcon(cocos2d::CCObject* sender) = win 0x128420;
void onRobotIcon(cocos2d::CCObject* sender) = win 0x1286d0;
void onSpiderIcon(cocos2d::CCObject* sender) = win 0x128890;
void onPlayerDeathEffect(cocos2d::CCObject* sender) = win 0x128a50;
void onPlayerTrail(cocos2d::CCObject* sender) = win 0x128af0;
void onShards(cocos2d::CCObject* sender) = win 0x12ad70;
void onBack(cocos2d::CCObject* sender) = win 0x12adf0;
void onShop(cocos2d::CCObject* sender) = win 0x12ad90;
void setupColorSelect() = mac 0x1b7500;
void showCircleWave() = win 0x12aad0;
void showBlackCircleWave() = win 0x12a9d0;
PAD = mac 0x10, win 0x8;
CCTextInputNode* m_nameInput;
SimplePlayer* m_playerPreview;
@ -2660,6 +2696,7 @@ class GJRobotSprite : CCAnimatedSprite {
virtual void hideSecondary() = mac 0x34c3b0, win 0x146c90;
static GJRobotSprite* create() = mac 0x34ac00, win 0x1457a0;
void updateColor02(cocos2d::_ccColor3B) = mac 0x34bbd0, win 0x1461c0;
void updateGlowColor(cocos2d::_ccColor3B, bool) = win 0x1460C0;
void updateFrame(int) = mac 0x34bdd0, win 0x146700;
void hideGlow() = mac 0x34b860;
@ -2793,7 +2830,7 @@ class GJSpiderSprite : GJRobotSprite {
class GJSpriteColor : cocos2d::CCNode {
int m_colorID;
int m_defaultColorID;
float m_unk_0F4;
float m_opacity;
cocos2d::ccHSVValue m_hsv;
bool m_usesHSV;
float unk_10C;
@ -3401,15 +3438,16 @@ class GameObject : CCSpritePlus {
void addToTempOffset(float, float) = mac 0x335700;
void calculateOrientedBox() = mac 0x342b20, win 0xef1a0;
void canChangeCustomColor() = mac 0x342db0;
cocos2d::_ccColor3B& colorForMode(int, bool) = mac 0x343460, win 0xef8d0;
float groupOpacityMod() = win 0xebda0;
cocos2d::_ccColor3B& colorForMode(int colorMode, bool isMain) = mac 0x343460, win 0xef8d0;
cocos2d::_ccColor3B& groupColor(cocos2d::_ccColor3B const&, bool) = win 0xef9e0;
cocos2d::_ccColor3B& getActiveColorForMode(int, bool) = mac 0x343860, win 0xefb10;
void commonSetup() = mac 0x2f5570, win 0xcfac0;
void copyGroups(GameObject*) = mac 0x33ae30, win 0xeb9d0;
static GameObject* createWithFrame(const char*) = mac 0x2f5490, win 0xcf8f0;
static GameObject* createWithKey(int) = mac 0x2f4ce0, win 0xcf4f0;
void destroyObject() = mac 0x336a00;
void determineSlopeDirection() = mac 0x33a9e0, win 0xeb670;
cocos2d::_ccColor3B& getActiveColorForMode(int, bool) = mac 0x343860, win 0xefb10;
void getBallFrame(int) = mac 0x341bf0;
cocos2d::CCPoint getBoxOffset() = mac 0x3353d0, win 0xef350;
const cocos2d::_ccColor3B& getColorIndex() = mac 0x343b90;
@ -3429,7 +3467,7 @@ class GameObject : CCSpritePlus {
void groupWasDisabled() = mac 0x33b110;
void groupWasEnabled() = mac 0x33b0f0;
void hasBeenActivated() = mac 0x342a80;
void hasBeenActivatedByPlayer(GameObject*) = mac 0x342a50;
bool hasBeenActivatedByPlayer(GameObject*) = mac 0x342a50, win 0xEF110;
void hasSecondaryColor() = mac 0x342f80;
void ignoreEnter() = mac 0x3352a0;
void ignoreFade() = mac 0x335290;
@ -3440,7 +3478,15 @@ class GameObject : CCSpritePlus {
void loadGroupsFromString(gd::string str) = mac 0x33b380, win 0xebcb0;
static GameObject* objectFromString(gd::string, bool) = mac 0x33b720, win 0xebe50;
void playShineEffect() = mac 0x2fa9d0, win 0xeab20;
void quickUpdatePosition() = mac 0x335790;
//void quickUpdatePosition() = mac 0x335790;
// inlined on windows
void quickUpdatePosition() {
cocos2d::CCPoint newPos = getRealPosition();
this->setPosition(newPos);
if (m_detailSprite && !m_hasDetailColor) {
m_detailSprite->setPosition(newPos);
}
}
void removeGlow() = mac 0x2f7f70;
void resetGroupDisabled() = mac 0x2fa7e0;
void saveActiveColors() = mac 0x33d250, win 0xee3e0;
@ -3469,8 +3515,7 @@ class GameObject : CCSpritePlus {
bool canAllowMultiActivate() = mac 0x343ca0, win 0xf06b0;
void createGroupContainer(int size) = mac 0x33aca0, win 0xeb870;
bool m_unk3;
bool m_isBlueMaybe;
cocos2d::_ccColor3B m_color;
float m_unk2;
float m_unk;
float m_unk3f;
@ -3573,7 +3618,7 @@ class GameObject : CCSpritePlus {
int m_objectID;
bool m_unk364;
bool m_unk365;
bool m_unk366;
bool m_ignoreEnter;
bool m_ignoreFade;
bool m_unk368;
bool m_unk369;
@ -3627,8 +3672,8 @@ class GameObject : CCSpritePlus {
int m_unk414;
PAD = mac 0xc, win 0xc, android 0xc;
cocos2d::CCPoint m_firstPosition;
bool m_unk42C;
bool m_unk42D;
bool m_queuedForPositionUpdate;
bool m_shouldUpdateFirstPosition;
PAD = mac 0x6, win 0x6, android 0x6;
bool m_isAnimated;
PAD = mac 0x7, win 0x7, android 0x7;
@ -3645,7 +3690,7 @@ class GameObject : CCSpritePlus {
GJEffectManager* m_effectManager;
bool m_unk458;
bool m_unk459;
bool m_unk45A;
bool m_inOptimizedGroup;
bool m_wasForcedRotatedPositionUpdateIdk;
PAD = mac 0x8, win 0x8, android 0x8;
bool m_orbMultiActivate;
@ -3997,7 +4042,7 @@ class LevelEditorLayer : GJBaseGameLayer, LevelSettingsDelegate {
virtual void calculateColorValues(EffectGameObject*, EffectGameObject*, int, float, ColorActionSprite*, GJEffectManager*) = mac 0x9c590, win 0x166f90;
virtual void addToGroup(GameObject*, int, bool) = mac 0x9dab0, win 0x167310;
virtual void removeFromGroup(GameObject*, int) = mac 0x9db60, win 0x1673a0;
virtual void timeForXPos(float) = mac 0x9c7d0, win 0x167210;
virtual float timeForXPos(float) = mac 0x9c7d0, win 0x167210;
virtual void xPosForTime(float) = mac 0x9c800, win 0x167250;
virtual void levelSettingsUpdated() = mac 0x93f30, win 0x1606c0;
static LevelEditorLayer* create(GJGameLevel* level) = mac 0x90fb0, win 0x15ed60, ios 0x261628;
@ -4016,7 +4061,7 @@ class LevelEditorLayer : GJBaseGameLayer, LevelSettingsDelegate {
cocos2d::CCArray* createObjectsFromString(gd::string, bool) = mac 0x94730, win 0x160980;
void getLastObjectX() = mac 0x9c860, win 0x167290;
gd::string getLevelString() = mac 0x97790, win 0x162480;
void getNextColorChannel() = mac 0x9a610;
int getNextColorChannel() = mac 0x9a610, win 0x164e10;
void getNextFreeBlockID(cocos2d::CCArray*) = mac 0x9a4e0;
int getNextFreeGroupID(cocos2d::CCArray*) = mac 0x9a1b0, win 0x164ae0;
void getNextFreeItemID(cocos2d::CCArray*) = mac 0x9a390;
@ -4190,8 +4235,13 @@ class LevelInfoLayer : cocos2d::CCLayer, LevelDownloadDelegate, LevelUpdateDeleg
void setupLevelInfo() = mac 0x161C80, win 0x178680;
void downloadLevel() = win 0x177d90, mac 0x161b90;
void onPlay(cocos2d::CCObject* sender) = mac 0x161840, win 0x179730;
void onBack(cocos2d::CCObject* sender) = mac 0x163810, win 0x17C110;
void onDelete(cocos2d::CCObject* sender) = mac 0x162f30, win 0x17A2B0;
virtual void levelDownloadFinished(GJGameLevel*) = mac 0x164C00, win 0x1790C0;
virtual void levelUpdateFinished(GJGameLevel*, UpdateResponse) = mac 0x164E60, win 0x1792B0;
virtual void keyBackClicked() = win 0x17C1D0;
void showUpdateAlert(UpdateResponse) = mac 0x164ED0, win 0x179300;
void updateLabelValues() = mac 0x164090, win 0x17b170;
@ -4257,6 +4307,7 @@ class LevelSearchLayer : cocos2d::CCLayer {
[[link(android)]]
class LevelSelectLayer : cocos2d::CCLayer {
static LevelSelectLayer* create(int lvl) = win 0x185500;
bool init(int lvl) = win 0x1855a0, mac 0x2384e0;
PAD = win 0x10;
BoomScrollLayer* m_scrollLayer;
@ -4394,6 +4445,7 @@ class LikeItemLayer : FLAlertLayer {
[[link(android)]]
class ListButtonBar : cocos2d::CCNode {
BoomScrollLayer* m_scrollLayer;
void switchedPage(int page) = win 0x29c50;
}
[[link(android)]]
@ -4518,7 +4570,7 @@ class MessageListDelegate {}
[[link(android)]]
class MoreSearchLayer : FLAlertLayer {
static MoreSearchLayer* create() = mac 0x38ab40, win 0x182520;
static MoreSearchLayer* create() = mac 0x388180, win 0x182520;
virtual bool init() = mac 0x3896b0, win 0x1825c0;
void onClose(cocos2d::CCObject*) = mac 0x38aa40, win 0x1848f0;
}
@ -4863,8 +4915,9 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, CurrencyRewardDelegate,
void switchToRobotMode(PlayerObject*, GameObject*, bool) = mac 0x7bc80;
void switchToRollMode(PlayerObject*, GameObject*, bool) = mac 0x7bbe0;
void switchToSpiderMode(PlayerObject*, GameObject*, bool) = mac 0x7bd20;
void timeForXPos(float) = mac 0x7d120, win 0x2087d0;
void timeForXPos2(float, bool) = mac 0x293eb0, win 0x1fd3d0;
callback float timeForXPos(float) = mac 0x7d120, win 0x2087d0;
float timeForXPos2(float, bool) = mac 0x293eb0, win 0x208800;
callback float xPosForTime(float) = mac 0x7d140, win 0x208840;
void toggleBGEffectVisibility(bool) = mac 0x7fe80;
void toggleDualMode(GameObject*, bool, PlayerObject*, bool) = mac 0x7bf90, win 0x208880;
void toggleFlipped(bool, bool) = mac 0x7bdc0, win 0x20ab20;
@ -4893,7 +4946,6 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, CurrencyRewardDelegate,
virtual void visit() = mac 0x75ef0, win 0x200020;
void visitWithColorFlash() = mac 0x761f0, win 0x200190;
void willSwitchToMode(int, PlayerObject*) = mac 0x7b9e0;
void xPosForTime(float) = mac 0x7d140, win 0x208840;
~PlayLayer() = mac 0x6b090, win 0x1fafc0;
// there is 0x10 more for android between this and ccdrawnode
@ -4929,7 +4981,7 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, CurrencyRewardDelegate,
EndPortalObject* m_endPortal;
cocos2d::CCArray* m_checkpoints;
cocos2d::CCArray* m_speedObjects;
cocos2d::CCArray* unk340;
cocos2d::CCArray* m_allSpeedObjects;
cocos2d::CCArray* unk344;
cocos2d::CCSprite* unk348;
float m_backgroundRepeat;
@ -5105,7 +5157,7 @@ class PlayerObject : GameObject, AnimatedSpriteDelegate {
void boostPlayer(float) = mac 0x21d6b0, win 0x1f8f30;
void bumpPlayer(float, int) = mac 0x22d890;
void buttonDown(PlayerButton) = mac 0x22b7e0;
void checkSnapJumpToObject(GameObject*) = mac 0x2217f0;
void checkSnapJumpToObject(GameObject*) = mac 0x2217f0, win 0x1ece70;
bool collidedWithObject(float fl, GameObject* obj) {
auto rect = obj->getObjectRect();
return collidedWithObject(fl, obj, rect);
@ -5250,7 +5302,7 @@ class PlayerObject : GameObject, AnimatedSpriteDelegate {
PAD = mac 0x14, win 0x14, android 0x14;
bool m_unk4D4;
cocos2d::CCArray* m_particleSystems;
bool m_unk4DC;
bool m_hasGlow;
bool m_isHidden;
int m_hasGhostTrail;
GhostTrailEffect* m_ghostTrail;
@ -5643,6 +5695,12 @@ class SetupPulsePopup : FLAlertLayer, cocos2d::extension::ColorPickerDelegate, T
int m_pulseMode; // 0x38c on mac
}
[[link(android)]]
class SetupRotatePopup : FLAlertLayer {
void onClose(cocos2d::CCObject*) = win 0x244150;
virtual void keyBackClicked() = win 0x2441a0;
}
[[link(android)]]
class SetupShakePopup : FLAlertLayer {
static SetupShakePopup* create(EffectGameObject*, cocos2d::CCArray*) = mac 0x3adc00;
@ -5816,12 +5874,11 @@ class SpawnTriggerAction : cocos2d::CCNode {
[[link(android)]]
class SpeedObject : cocos2d::CCNode {
float m_unknown;
float m_somethingToCompare;
float m_idk3;
float m_idk4;
Speed m_speed;
float m_xPos;
GameObject* m_object;
static SpeedObject* create(GameObject*, int, float) = win 0x20DE70;
static SpeedObject* create(GameObject* object, Speed speed, float x) = win 0x20de70;
}
[[link(android)]]

View file

@ -1,7 +1,7 @@
set(GEODE_CLI_MINIMUM_VERSION 1.0.5)
# Find Geode CLI
if (NOT DEFINED GEODE_CLI)
if (NOT DEFINED GEODE_CLI OR GEODE_CLI STREQUAL "GEODE_CLI-NOTFOUND")
find_program(GEODE_CLI NAMES geode.exe geode-cli.exe geode geode-cli PATHS ${CLI_PATH})
endif()
@ -59,7 +59,7 @@ function(setup_geode_mod proname)
if(GEODE_CLI STREQUAL "GEODE_CLI-NOTFOUND")
message(FATAL_ERROR
"setup_geode_mod called, but Geode CLI was not found - "
"Please install CLI: https://docs.geode-sdk.org/info/installcli/"
"Please install CLI: https://docs.geode-sdk.org/"
)
return()
endif()

View file

@ -405,8 +405,11 @@ namespace gd {
}
~vector() {
for (auto i = m_start; i != m_finish; ++i) {
delete i;
if (m_start) {
for (auto& x : *this) {
x.~T();
}
delete m_start;
}
}

View file

@ -13,6 +13,7 @@ namespace geode {
class GEODE_DLL SceneManager {
protected:
cocos2d::CCArray* m_persistedNodes;
cocos2d::CCScene* m_lastScene = nullptr;
bool setup();

View file

@ -4,36 +4,47 @@
#include <cocos2d.h>
namespace geode {
enum WrappingMode {
NO_WRAP,
WORD_WRAP,
CUTOFF_WRAP
};
/**
* A class which provides a textarea with proper alignment and some extra features like:
*
* - Max lines
* - Changing all aspects after creation
* - Custom text alignment
* - Automatic line wrapping and cutoff
* - Configurable and automatic word wrapping
* - Line padding
*
* Contact me on Discord (\@smjs) if you have any questions, suggestions or bugs.
*/
class GEODE_DLL SimpleTextArea : public cocos2d::CCNode {
static SimpleTextArea* create(const std::string& text, const std::string& font = "chatFont.fnt", const float scale = 1);
static SimpleTextArea* create(const std::string& text, const std::string& font, const float scale, const float width);
cocos2d::CCMenu* m_container;
std::string m_font;
std::string m_text;
std::vector<cocos2d::CCLabelBMFont*> m_lines;
cocos2d::ccColor4B m_color;
cocos2d::CCTextAlignment m_alignment;
WrappingMode m_wrappingMode;
size_t m_maxLines;
float m_scale;
float m_lineHeight;
float m_linePadding;
bool m_artificialWidth;
public:
static SimpleTextArea* create(const std::string& font, const std::string& text, const float scale);
static SimpleTextArea* create(const std::string& font, const std::string& text, const float scale, const float width);
void setFont(const std::string& font);
std::string getFont();
void setColor(const cocos2d::ccColor4B& color);
cocos2d::ccColor4B getColor();
void setAlignment(const cocos2d::CCTextAlignment alignment);
cocos2d::CCTextAlignment getAlignment();
void setWrappingMode(const WrappingMode mode);
WrappingMode getWrappingMode();
void setText(const std::string& text);
std::string getText();
void setMaxLines(const size_t maxLines);
@ -50,11 +61,17 @@ namespace geode {
private:
static SimpleTextArea* create(const std::string& font, const std::string& text, const float scale, const float width, const bool artificialWidth);
bool m_shouldUpdate;
bool m_artificialWidth;
SimpleTextArea(const std::string& font, const std::string& text, const float scale, const float width, const bool artificialWidth);
cocos2d::CCLabelBMFont* createLabel(const std::string& text, const float top);
cocos2d::CCLabelBMFont* moveOverflow(cocos2d::CCLabelBMFont* line, const char c, const float top);
float calculateOffset(cocos2d::CCLabelBMFont* label);
void updateLines();
void updateContents();
void charIteration(const std::function<cocos2d::CCLabelBMFont*(cocos2d::CCLabelBMFont* line, const char c, const float top)>& overflowHandling);
void updateLinesNoWrap();
void updateLinesWordWrap();
void updateLinesCutoffWrap();
void updateContainer();
virtual void draw() override;
};
}

View file

@ -252,7 +252,7 @@ private:
friend class Index;
void cleanupItems();
void downloadIndex();
void downloadIndex(std::string commitHash = "");
void checkForUpdates();
void updateFromLocalTree();
void installNext(size_t index, IndexInstallList const& list);
@ -296,7 +296,7 @@ bool Index::hasTriedToUpdate() const {
return m_impl->m_triedToUpdate;
}
void Index::Impl::downloadIndex() {
void Index::Impl::downloadIndex(std::string commitHash) {
log::debug("Downloading index");
IndexUpdateEvent(UpdateProgress(0, "Beginning download")).post();
@ -307,7 +307,7 @@ void Index::Impl::downloadIndex() {
.join("index-download")
.fetch("https://github.com/geode-sdk/mods/zipball/main")
.into(targetFile)
.then([this, targetFile](auto) {
.then([this, targetFile, commitHash](auto) {
auto targetDir = dirs::getIndexDir() / "v0";
// delete old unzipped index
try {
@ -333,6 +333,10 @@ void Index::Impl::downloadIndex() {
// remove the directory github adds to the root of the zip
(void)flattenGithubRepo(targetDir);
if (!commitHash.empty()) {
auto const checksumPath = dirs::getIndexDir() / ".checksum";
(void)file::writeString(checksumPath, commitHash);
}
Loader::get()->queueInMainThread([this] {
// update index
@ -387,8 +391,7 @@ void Index::Impl::checkForUpdates() {
}
// otherwise save hash and download source
else {
(void)file::writeString(checksum, newSHA);
this->downloadIndex();
this->downloadIndex(newSHA);
}
})
.expect([](std::string const& err) {
@ -591,7 +594,7 @@ bool Index::isUpdateAvailable(IndexItemHandle item) const {
bool Index::areUpdatesAvailable() const {
for (auto& mod : Loader::get()->getAllMods()) {
auto item = this->getMajorItem(mod->getID());
if (item && item->getMetadata().getVersion() > mod->getVersion()) {
if (item && item->getMetadata().getVersion() > mod->getVersion() && mod->isEnabled()) {
return true;
}
}

View file

@ -173,7 +173,6 @@ void Notification::show() {
auto winSize = CCDirector::get()->getWinSize();
this->setPosition(winSize.width / 2, winSize.height / 4);
this->setZOrder(CCScene::get()->getHighestChildZ() + 100);
CCScene::get()->addChild(this);
}
SceneManager::get()->keepAcrossScenes(this);
m_showing = true;

View file

@ -23,6 +23,10 @@ SceneManager::~SceneManager() {
}
void SceneManager::keepAcrossScenes(CCNode* node) {
if (m_lastScene) {
node->removeFromParentAndCleanup(false);
m_lastScene->addChild(node);
}
m_persistedNodes->addObject(node);
}
@ -36,4 +40,5 @@ void SceneManager::willSwitchToScene(CCScene* scene) {
node->removeFromParentAndCleanup(false);
scene->addChild(node);
}
m_lastScene = scene;
}

View file

@ -2,11 +2,11 @@
using namespace geode::prelude;
SimpleTextArea* SimpleTextArea::create(const std::string& font, const std::string& text, const float scale = 1) {
return SimpleTextArea::create(font, text, scale, 500, false);
SimpleTextArea* SimpleTextArea::create(const std::string& text, const std::string& font, const float scale) {
return SimpleTextArea::create(font, text, scale, CCDirector::sharedDirector()->getWinSize().width / 2, false);
}
SimpleTextArea* SimpleTextArea::create(const std::string& font, const std::string& text, const float scale, const float width) {
SimpleTextArea* SimpleTextArea::create(const std::string& text, const std::string& font, const float scale, const float width) {
return SimpleTextArea::create(font, text, scale, width, true);
}
@ -30,9 +30,12 @@ SimpleTextArea::SimpleTextArea(const std::string& font, const std::string& text,
m_maxLines = 0;
m_scale = scale;
m_linePadding = 0;
m_color = { 0xFF, 0xFF, 0xFF, 0xFF };
m_alignment = kCCTextAlignmentLeft;
m_wrappingMode = WORD_WRAP;
m_artificialWidth = artificialWidth;
m_container = CCMenu::create();
m_shouldUpdate = true;
this->setAnchorPoint({ 0.5f, 0.5f });
m_container->setPosition({ 0, 0 });
@ -40,33 +43,47 @@ SimpleTextArea::SimpleTextArea(const std::string& font, const std::string& text,
m_container->setContentSize({ width, 0 });
this->addChild(m_container);
this->updateContents();
}
void SimpleTextArea::setFont(const std::string& font) {
m_font = font;
this->updateContents();
m_shouldUpdate = true;
}
std::string SimpleTextArea::getFont() {
return m_font;
}
void SimpleTextArea::setColor(const ccColor4B& color) {
m_color = color;
m_shouldUpdate = true;
}
ccColor4B SimpleTextArea::getColor() {
return m_color;
}
void SimpleTextArea::setAlignment(const CCTextAlignment alignment) {
m_alignment = alignment;
this->updateContents();
m_shouldUpdate = true;
}
CCTextAlignment SimpleTextArea::getAlignment() {
return m_alignment;
}
void SimpleTextArea::setWrappingMode(const WrappingMode mode) {
m_wrappingMode = mode;
m_shouldUpdate = true;
}
WrappingMode SimpleTextArea::getWrappingMode() {
return m_wrappingMode;
}
void SimpleTextArea::setText(const std::string& text) {
m_text = text;
this->updateContents();
m_shouldUpdate = true;
}
std::string SimpleTextArea::getText() {
@ -75,8 +92,7 @@ std::string SimpleTextArea::getText() {
void SimpleTextArea::setMaxLines(const size_t maxLines) {
m_maxLines = maxLines;
this->updateContents();
m_shouldUpdate = true;
}
size_t SimpleTextArea::getMaxLines() {
@ -85,6 +101,7 @@ size_t SimpleTextArea::getMaxLines() {
void SimpleTextArea::setWidth(const float width) {
m_artificialWidth = true;
m_shouldUpdate = true;
this->setContentSize({ width, this->getContentSize().height });
m_container->setContentSize(this->getContentSize());
@ -96,8 +113,7 @@ float SimpleTextArea::getWidth() {
void SimpleTextArea::setScale(const float scale) {
m_scale = scale;
this->updateContents();
m_shouldUpdate = true;
}
float SimpleTextArea::getScale() {
@ -106,8 +122,7 @@ float SimpleTextArea::getScale() {
void SimpleTextArea::setLinePadding(const float padding) {
m_linePadding = padding;
this->updateContents();
m_shouldUpdate = true;
}
float SimpleTextArea::getLinePadding() {
@ -131,34 +146,17 @@ CCLabelBMFont* SimpleTextArea::createLabel(const std::string& text, const float
label->setScale(m_scale);
label->setPosition({ 0, top });
label->setColor({ m_color.r, m_color.g, m_color.b });
label->setOpacity(m_color.a);
return label;
}
CCLabelBMFont* SimpleTextArea::moveOverflow(CCLabelBMFont* line, const char c, const float top) {
const std::string text = line->getString();
const char back = text.back();
const bool lastIsSpace = back == ' ';
CCLabelBMFont* newLine = this->createLabel(std::string(!lastIsSpace, back).append(std::string(c != ' ', c)), top);
if (!lastIsSpace) {
if (text[text.size() - 2] == ' ') {
line->setString(text.substr(0, text.size() - 1).c_str());
} else {
line->setString((text.substr(0, text.size() - 1) + '-').c_str());
}
}
m_lines.push_back(newLine);
return newLine;
}
float SimpleTextArea::calculateOffset(CCLabelBMFont* label) {
return m_linePadding + label->getContentSize().height * m_scale;
}
void SimpleTextArea::updateLines() {
void SimpleTextArea::charIteration(const std::function<CCLabelBMFont*(CCLabelBMFont* line, const char c, const float top)>& overflowHandling) {
float top = 0;
CCLabelBMFont* line = this->createLabel("", top);
m_lines = { line };
@ -173,21 +171,87 @@ void SimpleTextArea::updateLines() {
break;
} else if (c == '\n') {
line = this->createLabel("", top -= this->calculateOffset(line));
m_lines.push_back(line);
} else if (m_artificialWidth && line->getContentSize().width >= this->getWidth()) {
line = this->moveOverflow(line, c, top -= this->calculateOffset(line));
m_lines.push_back(line = this->createLabel("", top -= this->calculateOffset(line)));
} else if (m_artificialWidth && line->getContentSize().width * m_scale >= this->getWidth()) {
m_lines.push_back(line = overflowHandling(line, c, top -= this->calculateOffset(line)));
} else {
const std::string text = line->getString();
line->setString((text + c).c_str());
line->setString((std::string(line->getString()) + c).c_str());
}
}
}
void SimpleTextArea::updateContents() {
this->updateLines();
void SimpleTextArea::updateLinesNoWrap() {
std::stringstream stream(m_text);
std::string part;
float top = 0;
while (std::getline(stream, part)) {
if (m_maxLines && m_lines.size() >= m_maxLines) {
CCLabelBMFont* last = m_lines.at(m_maxLines - 1);
const std::string text = last->getString();
last->setString(text.substr(0, text.size() - 3).append("...").c_str());
break;
} else {
CCLabelBMFont* line = this->createLabel(part, 0);
top -= this->calculateOffset(line);
m_lines.push_back(line);
}
}
}
void SimpleTextArea::updateLinesWordWrap() {
this->charIteration([this](CCLabelBMFont* line, const char c, const float top) {
static std::string delimiters(" `~!@#$%^&*()-_=+[{}];:'\",<.>/?\\|");
if (delimiters.find(c) == std::string_view::npos) {
const std::string text = line->getString();
const size_t position = text.find_last_of(delimiters) + 1;
line->setString(text.substr(0, position).c_str());
return this->createLabel(text.substr(position) + c, top);
} else {
return this->createLabel(std::string(c, c != ' '), top);
}
});
}
void SimpleTextArea::updateLinesCutoffWrap() {
this->charIteration([this](CCLabelBMFont* line, const char c, const float top) {
const std::string text = line->getString();
const char back = text.back();
const bool lastIsSpace = back == ' ';
CCLabelBMFont* newLine = this->createLabel(std::string(!lastIsSpace, back).append(std::string(c != ' ', c)), top);
if (!lastIsSpace) {
if (text[text.size() - 2] == ' ') {
line->setString(text.substr(0, text.size() - 1).c_str());
} else {
line->setString((text.substr(0, text.size() - 1) + '-').c_str());
}
}
return newLine;
});
}
void SimpleTextArea::updateContainer() {
switch (m_wrappingMode) {
case NO_WRAP: {
this->updateLinesNoWrap();
} break;
case WORD_WRAP: {
this->updateLinesWordWrap();
} break;
case CUTOFF_WRAP: {
this->updateLinesCutoffWrap();
} break;
}
const size_t lineCount = m_lines.size();
const float width = this->getWidth();
@ -212,7 +276,7 @@ void SimpleTextArea::updateContents() {
line->setPosition({ 0, y });
} break;
case kCCTextAlignmentCenter: {
line->setAnchorPoint({ 0.5f, 1 });
line->setAnchorPoint({ 0, 1 });
line->setPosition({ width / 2, y });
} break;
case kCCTextAlignmentRight: {
@ -224,3 +288,13 @@ void SimpleTextArea::updateContents() {
m_container->addChild(line);
}
}
void SimpleTextArea::draw() {
CCNode::draw();
if (m_shouldUpdate) {
this->updateContainer();
m_shouldUpdate = false;
}
}