mirror of
https://github.com/geode-sdk/geode.git
synced 2025-04-10 12:04:36 -04:00
UI Fixes and Revamped Developer List (#877)
* UI Fixes and Revamped Developer List * Remove toggler fix as the underlying issue is fixed in bindings
This commit is contained in:
parent
74a450e3c3
commit
2779c04394
12 changed files with 274 additions and 62 deletions
|
@ -91,11 +91,11 @@ struct CustomMenuLayer : Modify<CustomMenuLayer, MenuLayer> {
|
|||
Notification::create("There were errors - see Geode page!", NotificationIcon::Error)->show();
|
||||
}
|
||||
|
||||
auto icon = CCSprite::createWithSpriteFrameName("exclamation-red.png"_spr);
|
||||
auto icon = CCSprite::createWithSpriteFrameName("exMark_001.png");
|
||||
icon->setPosition(m_fields->m_geodeButton->getContentSize() - ccp(10, 10));
|
||||
icon->setID("errors-found");
|
||||
icon->setZOrder(99);
|
||||
icon->setScale(.8f);
|
||||
icon->setScale(.6f);
|
||||
m_fields->m_geodeButton->addChild(icon);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,10 +26,8 @@ $on_mod(Loaded) {
|
|||
ColorProvider::get()->define("mod-list-recommended-bg"_spr, ccc3(25, 255, 167));
|
||||
ColorProvider::get()->define("mod-list-recommended-by"_spr, ccc3(25, 255, 167));
|
||||
ColorProvider::get()->define("mod-list-recommended-by-2"_spr, ccc3(47, 255, 255));
|
||||
ColorProvider::get()->define(
|
||||
"mod-problems-item-bg"_spr,
|
||||
{ 255, 255, 255, 15 }
|
||||
);
|
||||
ColorProvider::get()->define("mod-problems-item-bg"_spr, { 255, 255, 255, 15 });
|
||||
ColorProvider::get()->define("mod-developer-item-bg"_spr, { 255, 255, 255, 15 });
|
||||
|
||||
// Only used when GD theme is active
|
||||
ColorProvider::get()->define("mods-layer-gd-bg"_spr, { 0, 102, 255, 255 });
|
||||
|
@ -45,6 +43,7 @@ $on_mod(Loaded) {
|
|||
ColorProvider::get()->reset("mod-list-restart-required-label"_spr);
|
||||
ColorProvider::get()->reset("mod-list-restart-required-label-bg"_spr);
|
||||
ColorProvider::get()->reset("mod-problems-item-bg"_spr);
|
||||
ColorProvider::get()->reset("mod-developer-item-bg"_spr);
|
||||
}
|
||||
else {
|
||||
ColorProvider::get()->override("mod-list-bg"_spr, { 168, 85, 44, 255 });
|
||||
|
@ -57,10 +56,8 @@ $on_mod(Loaded) {
|
|||
ColorProvider::get()->override("mod-list-restart-required-label-bg"_spr, ccc3(0, 174, 180));
|
||||
ColorProvider::get()->override("mod-list-errors-found"_spr, { 255, 0, 0, 255 });
|
||||
ColorProvider::get()->override("mod-list-errors-found-2"_spr, { 235, 35, 112, 255 });
|
||||
ColorProvider::get()->override(
|
||||
"mod-problems-item-bg"_spr,
|
||||
{ 0, 0, 0, 75 }
|
||||
);
|
||||
ColorProvider::get()->override("mod-problems-item-bg"_spr, { 0, 0, 0, 75 });
|
||||
ColorProvider::get()->override("mod-developer-item-bg"_spr, { 0, 0, 0, 75 });
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -211,6 +208,9 @@ const char* getGeodeButtonSpriteName(GeodeButtonSprite spr) {
|
|||
IconButtonSprite* createGeodeButton(CCNode* icon, std::string const& text, GeodeButtonSprite bg) {
|
||||
return IconButtonSprite::create(getGeodeButtonSpriteName(bg), icon, text.c_str(), "bigFont.fnt");
|
||||
}
|
||||
ButtonSprite* createGeodeButton(std::string const& text, int width, bool gold, bool absolute, GeodeButtonSprite bg) {
|
||||
return ButtonSprite::create(text.c_str(), width, absolute, gold ? "goldFont.fnt" : "bigFont.fnt", getGeodeButtonSpriteName(bg), 0.0f, .8f);
|
||||
}
|
||||
ButtonSprite* createGeodeButton(std::string const& text, bool gold, GeodeButtonSprite bg) {
|
||||
return ButtonSprite::create(text.c_str(), gold ? "goldFont.fnt" : "bigFont.fnt", getGeodeButtonSpriteName(bg), .8f);
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ enum class GeodeButtonSprite {
|
|||
};
|
||||
const char* getGeodeButtonSpriteName(GeodeButtonSprite spr);
|
||||
IconButtonSprite* createGeodeButton(CCNode* icon, std::string const& text, GeodeButtonSprite bg = GeodeButtonSprite::Default);
|
||||
ButtonSprite* createGeodeButton(std::string const& text, int width, bool absolute = false, bool gold = false, GeodeButtonSprite bg = GeodeButtonSprite::Default);
|
||||
ButtonSprite* createGeodeButton(std::string const& text, bool gold = false, GeodeButtonSprite bg = GeodeButtonSprite::Default);
|
||||
|
||||
CircleButtonSprite* createGeodeCircleButton(CCSprite* top, float scale = 1.f, CircleBaseSize size = CircleBaseSize::Medium, bool altColor = false);
|
||||
|
|
107
loader/src/ui/mods/list/ModDeveloperItem.cpp
Normal file
107
loader/src/ui/mods/list/ModDeveloperItem.cpp
Normal file
|
@ -0,0 +1,107 @@
|
|||
#include "ModProblemItem.hpp"
|
||||
|
||||
#include <Geode/cocos/base_nodes/CCNode.h>
|
||||
#include <Geode/cocos/base_nodes/Layout.hpp>
|
||||
#include <Geode/cocos/cocoa/CCGeometry.h>
|
||||
#include <Geode/cocos/label_nodes/CCLabelBMFont.h>
|
||||
#include <Geode/cocos/platform/CCPlatformMacros.h>
|
||||
#include <Geode/cocos/sprite_nodes/CCSprite.h>
|
||||
#include <Geode/DefaultInclude.hpp>
|
||||
#include <Geode/loader/Loader.hpp>
|
||||
#include <Geode/loader/Log.hpp>
|
||||
#include <Geode/loader/Mod.hpp>
|
||||
#include <Geode/ui/TextArea.hpp>
|
||||
#include <Geode/utils/cocos.hpp>
|
||||
#include <Geode/utils/ColorProvider.hpp>
|
||||
#include <GUI/CCControlExtension/CCScale9Sprite.h>
|
||||
#include <ccTypes.h>
|
||||
#include <fmt/core.h>
|
||||
#include <sstream>
|
||||
#include "ui/mods/list/ModDeveloperItem.hpp"
|
||||
#include "../UpdateModListState.hpp"
|
||||
|
||||
bool ModDeveloperItem::init(DevListPopup* popup, std::string developer, CCSize const& size) {
|
||||
if (!CCNode::init()) {
|
||||
return false;
|
||||
}
|
||||
m_popup = popup;
|
||||
|
||||
this->setContentSize(size);
|
||||
this->setAnchorPoint({ 0.5f, 0.5f });
|
||||
|
||||
ccColor4B bgColor = ColorProvider::get()->color("mod-developer-item-bg"_spr);
|
||||
|
||||
m_bg = CCScale9Sprite::create("square02b_001.png");
|
||||
m_bg->setColor(to3B(bgColor));
|
||||
m_bg->setOpacity(bgColor.a);
|
||||
m_bg->setScale(.3f);
|
||||
m_bg->setContentSize(CCSize {
|
||||
size.width,
|
||||
size.height
|
||||
} / m_bg->getScale());
|
||||
this->addChildAtPosition(
|
||||
m_bg,
|
||||
Anchor::Center
|
||||
);
|
||||
|
||||
auto label = CCLabelBMFont::create(
|
||||
developer.c_str(),
|
||||
"bigFont.fnt"
|
||||
);
|
||||
|
||||
// Left + Right + Space between
|
||||
constexpr float paddings = 30.0f;
|
||||
float calc = size.width - paddings;
|
||||
label->setWidth(calc);
|
||||
label->setScale(0.4f);
|
||||
label->setAnchorPoint({0.0f, 0.5f});
|
||||
|
||||
this->addChildAtPosition(
|
||||
label,
|
||||
Anchor::Left,
|
||||
{5, 0}
|
||||
);
|
||||
|
||||
auto menu = CCMenu::create();
|
||||
menu->setAnchorPoint({1.0f, 0.5f});
|
||||
|
||||
auto more = createGeodeButton("More");
|
||||
|
||||
auto btn = CCMenuItemSpriteExtra::create(
|
||||
more, this, menu_selector(ModDeveloperItem::onMoreByThisDev)
|
||||
);
|
||||
btn->setUserObject(CCString::create(developer));
|
||||
menu->addChild(btn);
|
||||
menu->setContentSize({size.width/2, size.height});
|
||||
menu->setScale(0.6f);
|
||||
|
||||
auto layout = RowLayout::create();
|
||||
layout->setDefaultScaleLimits(0.5f, 0.7f);
|
||||
layout->setAxisAlignment(AxisAlignment::End);
|
||||
layout->setAxisReverse(true);
|
||||
menu->setLayout(layout);
|
||||
|
||||
this->addChildAtPosition(
|
||||
menu,
|
||||
Anchor::Right,
|
||||
{-3, 0}
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ModDeveloperItem::onMoreByThisDev(CCObject* sender) {
|
||||
auto str = static_cast<CCString*>(static_cast<CCNode*>(sender)->getUserObject());
|
||||
UpdateModListStateEvent(UpdateWholeState(str->getCString())).post();
|
||||
m_popup->onClose(nullptr);
|
||||
}
|
||||
|
||||
ModDeveloperItem* ModDeveloperItem::create(DevListPopup* popup, std::string developer, CCSize const& size) {
|
||||
auto ret = new ModDeveloperItem();
|
||||
if (!ret || !ret->init(popup, developer, size)) {
|
||||
CC_SAFE_DELETE(ret);
|
||||
return nullptr;
|
||||
}
|
||||
ret->autorelease();
|
||||
return ret;
|
||||
}
|
21
loader/src/ui/mods/list/ModDeveloperItem.hpp
Normal file
21
loader/src/ui/mods/list/ModDeveloperItem.hpp
Normal file
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/cocos/base_nodes/CCNode.h>
|
||||
#include <Geode/cocos/cocoa/CCGeometry.h>
|
||||
#include <Geode/cocos/sprite_nodes/CCSprite.h>
|
||||
#include <Geode/loader/Loader.hpp>
|
||||
#include <GUI/CCControlExtension/CCScale9Sprite.h>
|
||||
#include "ui/mods/popups/DevPopup.hpp"
|
||||
|
||||
using namespace geode::prelude;
|
||||
|
||||
class ModDeveloperItem : public CCNode {
|
||||
protected:
|
||||
CCScale9Sprite* m_bg;
|
||||
DevListPopup* m_popup;
|
||||
public:
|
||||
static ModDeveloperItem* create(DevListPopup* popup, std::string developer, CCSize const& size);
|
||||
private:
|
||||
bool init(DevListPopup* popup, std::string developer, CCSize const& size);
|
||||
void onMoreByThisDev(CCObject* sender);
|
||||
};
|
71
loader/src/ui/mods/list/ModDeveloperList.cpp
Normal file
71
loader/src/ui/mods/list/ModDeveloperList.cpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
#include "ModDeveloperList.hpp"
|
||||
|
||||
#include <Geode/cocos/base_nodes/CCNode.h>
|
||||
#include <Geode/cocos/base_nodes/Layout.hpp>
|
||||
#include <Geode/cocos/cocoa/CCGeometry.h>
|
||||
#include <Geode/cocos/platform/CCPlatformMacros.h>
|
||||
#include <Geode/utils/cocos.hpp>
|
||||
#include <Geode/ui/ScrollLayer.hpp>
|
||||
#include <Geode/loader/Loader.hpp>
|
||||
#include <Geode/loader/Mod.hpp>
|
||||
#include <GUI/CCControlExtension/CCScale9Sprite.h>
|
||||
|
||||
#include "ui/mods/list/ModDeveloperItem.hpp"
|
||||
|
||||
bool ModDeveloperList::init(DevListPopup* popup, ModMetadata const& meta, CCSize const& size) {
|
||||
if (!CCNode::init()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_meta = meta;
|
||||
this->setContentSize(size);
|
||||
this->setAnchorPoint({ 0.5f, 0.5f });
|
||||
|
||||
CCScale9Sprite* bg = CCScale9Sprite::create("square02b_001.png");
|
||||
bg->setColor({ 0, 0, 0 });
|
||||
bg->setOpacity(75);
|
||||
bg->setScale(.3f);
|
||||
bg->setContentSize(size / bg->getScale());
|
||||
m_bg = bg;
|
||||
this->addChildAtPosition(
|
||||
m_bg,
|
||||
Anchor::Center
|
||||
);
|
||||
|
||||
// mfw fod created a scrolllayer with layouts
|
||||
m_list = ScrollLayer::create({ size.width - 10.f, size.height - 10.f });
|
||||
m_list->m_contentLayer->setLayout(
|
||||
ColumnLayout::create()
|
||||
->setAxisReverse(true)
|
||||
->setAxisAlignment(AxisAlignment::End)
|
||||
->setAutoGrowAxis(size.height)
|
||||
->setGap(5.0f)
|
||||
);
|
||||
this->addChildAtPosition(
|
||||
m_list,
|
||||
Anchor::Center,
|
||||
-m_list->getScaledContentSize() / 2
|
||||
);
|
||||
|
||||
CCSize itemSize = {
|
||||
m_list->getScaledContentWidth(),
|
||||
20.f
|
||||
};
|
||||
|
||||
for (std::string dev : m_meta.getDevelopers()) {
|
||||
m_list->m_contentLayer->addChild(ModDeveloperItem::create(popup, dev, itemSize));
|
||||
}
|
||||
m_list->m_contentLayer->updateLayout();
|
||||
m_list->scrollToTop();
|
||||
return true;
|
||||
}
|
||||
|
||||
ModDeveloperList* ModDeveloperList::create(DevListPopup* popup, ModMetadata const& meta, CCSize const& size) {
|
||||
auto ret = new ModDeveloperList();
|
||||
if (!ret || !ret->init(popup, meta, size)) {
|
||||
CC_SAFE_DELETE(ret);
|
||||
return nullptr;
|
||||
}
|
||||
ret->autorelease();
|
||||
return ret;
|
||||
}
|
30
loader/src/ui/mods/list/ModDeveloperList.hpp
Normal file
30
loader/src/ui/mods/list/ModDeveloperList.hpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/cocos/cocoa/CCGeometry.h>
|
||||
#include <Geode/cocos/base_nodes/CCNode.h>
|
||||
#include <Geode/loader/Loader.hpp>
|
||||
#include <Geode/loader/Mod.hpp>
|
||||
#include <Geode/ui/ScrollLayer.hpp>
|
||||
#include <GUI/CCControlExtension/CCScale9Sprite.h>
|
||||
#include "ui/mods/popups/DevPopup.hpp"
|
||||
|
||||
using namespace geode::prelude;
|
||||
|
||||
class ModDeveloperList : public CCNode {
|
||||
protected:
|
||||
ModMetadata m_meta;
|
||||
ScrollLayer* m_list;
|
||||
CCScale9Sprite* m_bg;
|
||||
public:
|
||||
static ModDeveloperList* create(
|
||||
DevListPopup* popup,
|
||||
ModMetadata const& meta,
|
||||
CCSize const& size
|
||||
);
|
||||
protected:
|
||||
bool init(
|
||||
DevListPopup* popup,
|
||||
ModMetadata const& meta,
|
||||
CCSize const& size
|
||||
);
|
||||
};
|
|
@ -132,9 +132,9 @@ bool ModItem::init(ModSource&& source) {
|
|||
|
||||
ButtonSprite* spr;
|
||||
if (Loader::get()->isModInstalled(m_source.getID())) {
|
||||
spr = createGeodeButton("View");
|
||||
spr = createGeodeButton("View", 50, false, true);
|
||||
} else {
|
||||
spr = createGeodeButton("Get", false, GeodeButtonSprite::Install);
|
||||
spr = createGeodeButton("Get", 50, false, true, GeodeButtonSprite::Install);
|
||||
}
|
||||
auto viewBtn = CCMenuItemSpriteExtra::create(
|
||||
spr,
|
||||
|
@ -350,6 +350,7 @@ void ModItem::updateState() {
|
|||
m_versionLabel->setString(m_source.getMetadata().getVersion().toVString().c_str());
|
||||
m_versionLabel->setColor(to3B(ColorProvider::get()->color("mod-list-version-label"_spr)));
|
||||
}
|
||||
|
||||
m_viewMenu->updateLayout();
|
||||
m_titleContainer->updateLayout();
|
||||
|
||||
|
|
|
@ -1,53 +1,32 @@
|
|||
#include <Geode/binding/ButtonSprite.hpp>
|
||||
#include "DevPopup.hpp"
|
||||
#include "../UpdateModListState.hpp"
|
||||
#include "ui/mods/list/ModDeveloperList.hpp"
|
||||
|
||||
bool DevListPopup::setup(ModMetadata const& meta) {
|
||||
|
||||
m_meta = meta;
|
||||
|
||||
this->setTitle(fmt::format("Developers for {}", meta.getName()));
|
||||
|
||||
auto container = CCNode::create();
|
||||
container->setAnchorPoint({ .5f, .5f });
|
||||
container->setContentHeight(150);
|
||||
|
||||
for (auto dev : meta.getDevelopers()) {
|
||||
auto menu = CCMenu::create();
|
||||
menu->setContentWidth(m_size.width - 30);
|
||||
|
||||
auto label = CCLabelBMFont::create(dev.c_str(), "bigFont.fnt");
|
||||
label->setLayoutOptions(AxisLayoutOptions::create()->setScalePriority(1));
|
||||
menu->addChild(label);
|
||||
|
||||
auto plus = CCSprite::createWithSpriteFrameName("GJ_plus2Btn_001.png");
|
||||
plus->setScale(1.f);
|
||||
auto btn = CCMenuItemSpriteExtra::create(
|
||||
plus, this, menu_selector(DevListPopup::onMoreByThisDev)
|
||||
);
|
||||
btn->setUserObject(CCString::create(dev));
|
||||
menu->addChild(btn);
|
||||
|
||||
menu->setLayout(
|
||||
RowLayout::create()
|
||||
->setDefaultScaleLimits(.1f, .5f)
|
||||
);
|
||||
container->addChild(menu);
|
||||
}
|
||||
|
||||
container->setLayout(
|
||||
ColumnLayout::create()
|
||||
->setDefaultScaleLimits(.1f, 1.f)
|
||||
m_title->limitLabelWidth(m_mainLayer->getContentSize().width - 50, .7f, .1f);
|
||||
CCSize contentSize = m_mainLayer->getContentSize();
|
||||
CCArray* elements = CCArray::create();
|
||||
ModDeveloperList* list = ModDeveloperList::create(this, m_meta, {210.f, 150.f});
|
||||
m_mainLayer->addChildAtPosition(
|
||||
list,
|
||||
Anchor::Center,
|
||||
{ 0.0f, -10.0f }
|
||||
);
|
||||
m_mainLayer->addChildAtPosition(container, Anchor::Center, ccp(0, 0), ccp(.5f, .5f));
|
||||
|
||||
auto okSpr = createGeodeButton("OK");
|
||||
okSpr->setScale(.7f);
|
||||
auto okBtn = CCMenuItemSpriteExtra::create(
|
||||
okSpr, this, menu_selector(DevListPopup::onClose)
|
||||
);
|
||||
m_buttonMenu->addChildAtPosition(okBtn, Anchor::Bottom, ccp(0, 20));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DevListPopup::onClose(cocos2d::CCObject*){
|
||||
this->setKeypadEnabled(false);
|
||||
this->setTouchEnabled(false);
|
||||
this->removeFromParentAndCleanup(true);
|
||||
}
|
||||
|
||||
void DevListPopup::onMoreByThisDev(CCObject* sender) {
|
||||
auto str = static_cast<CCString*>(static_cast<CCNode*>(sender)->getUserObject());
|
||||
UpdateModListStateEvent(UpdateWholeState(str->getCString())).post();
|
||||
|
@ -56,7 +35,7 @@ void DevListPopup::onMoreByThisDev(CCObject* sender) {
|
|||
|
||||
DevListPopup* DevListPopup::create(ModMetadata const& meta) {
|
||||
auto ret = new DevListPopup();
|
||||
if (ret && ret->init(220, 220, meta)) {
|
||||
if (ret && ret->init(250, 210, meta)) {
|
||||
ret->autorelease();
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -6,10 +6,12 @@
|
|||
|
||||
class DevListPopup : public GeodePopup<ModMetadata const&> {
|
||||
protected:
|
||||
bool setup(ModMetadata const& src);
|
||||
|
||||
void onMoreByThisDev(CCObject* sender);
|
||||
|
||||
ModMetadata m_meta;
|
||||
public:
|
||||
static DevListPopup* create(ModMetadata const& src);
|
||||
static DevListPopup* create(ModMetadata const&);
|
||||
void onClose(cocos2d::CCObject*);
|
||||
private:
|
||||
bool setup(ModMetadata const&);
|
||||
void createList();
|
||||
void onMoreByThisDev(CCObject* sender);
|
||||
};
|
||||
|
|
|
@ -22,7 +22,7 @@ void ModErrorPopup::createList() {
|
|||
CCSize contentSize = m_mainLayer->getContentSize();
|
||||
CCArray* elements = CCArray::create();
|
||||
std::vector<LoadProblem> problems = m_mod->getProblems();
|
||||
m_list = ModProblemList::create(m_mod, {400.f, 170.f});
|
||||
m_list = ModProblemList::create(m_mod, {400.f, 215.f});
|
||||
m_mainLayer->addChildAtPosition(
|
||||
m_list,
|
||||
Anchor::Center,
|
||||
|
@ -32,7 +32,7 @@ void ModErrorPopup::createList() {
|
|||
|
||||
ModErrorPopup* ModErrorPopup::create(Mod *mod) {
|
||||
ModErrorPopup* ret = new ModErrorPopup();
|
||||
if (!ret || !ret->init(440.f, 220.f, mod, GeodePopupStyle::Default)) {
|
||||
if (!ret || !ret->init(440.f, 280.f, mod, GeodePopupStyle::Default)) {
|
||||
CC_SAFE_DELETE(ret);
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ bool ModSettingsPopup::setup(Mod* mod) {
|
|||
|
||||
auto winSize = CCDirector::sharedDirector()->getWinSize();
|
||||
|
||||
auto const layerSize = CCSize(346, 210);
|
||||
auto const layerSize = CCSize(346, 200);
|
||||
|
||||
auto layerBG = CCLayerColor::create({ 0, 0, 0, 75 });
|
||||
layerBG->setContentSize(layerSize);
|
||||
|
@ -81,7 +81,7 @@ bool ModSettingsPopup::setup(Mod* mod) {
|
|||
|
||||
// layer borders
|
||||
|
||||
m_mainLayer->addChildAtPosition(createGeodeListBorders(layerSize), Anchor::Center);
|
||||
m_mainLayer->addChildAtPosition(createGeodeListBorders({layerSize.width, layerSize.height - 2}), Anchor::Center);
|
||||
|
||||
// buttons
|
||||
|
||||
|
@ -196,7 +196,7 @@ void ModSettingsPopup::onOpenSaveDirectory(CCObject*) {
|
|||
|
||||
ModSettingsPopup* ModSettingsPopup::create(Mod* mod) {
|
||||
auto ret = new ModSettingsPopup();
|
||||
if (ret && ret->init(440.f, 290.f, mod)) {
|
||||
if (ret && ret->init(440.f, 280.f, mod)) {
|
||||
ret->autorelease();
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue