mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-27 01:45:35 -05:00
working on a layout rewrite
This commit is contained in:
parent
ab0030136a
commit
ecbfd5ad0f
7 changed files with 250 additions and 80 deletions
|
@ -921,9 +921,14 @@ public:
|
||||||
* has been added, call updateLayout
|
* has been added, call updateLayout
|
||||||
* @param layout Layout to set to this node
|
* @param layout Layout to set to this node
|
||||||
* @param apply Whether to call updateLayout now or not
|
* @param apply Whether to call updateLayout now or not
|
||||||
|
* @param respectAnchor If true, if the target node is
|
||||||
|
* isIgnoreAnchorPointForPosition, then it is set to false and the children
|
||||||
|
* are automatically moved to match where they should be positioned.
|
||||||
|
* Visually, this should result in no difference; however, when dealing with
|
||||||
|
* CCLayers / CCMenus, this will change where the children are located
|
||||||
* @note Geode addition
|
* @note Geode addition
|
||||||
*/
|
*/
|
||||||
GEODE_DLL void setLayout(Layout* layout, bool apply = true);
|
GEODE_DLL void setLayout(Layout* layout, bool apply = true, bool respectAnchor = true);
|
||||||
/**
|
/**
|
||||||
* Get the Layout for this node
|
* Get the Layout for this node
|
||||||
* @returns The current layout, or nullptr if no layout is set
|
* @returns The current layout, or nullptr if no layout is set
|
||||||
|
|
131
loader/include/Geode/cocos/base_nodes/Layout.hpp
vendored
131
loader/include/Geode/cocos/base_nodes/Layout.hpp
vendored
|
@ -18,15 +18,20 @@ class CCNode;
|
||||||
* RowLayout, ColumnLayout, and GridLayout, but if you need a different kind
|
* RowLayout, ColumnLayout, and GridLayout, but if you need a different kind
|
||||||
* of layout you can inherit from the Layout class.
|
* of layout you can inherit from the Layout class.
|
||||||
*/
|
*/
|
||||||
class Layout {
|
class GEODE_DLL Layout {
|
||||||
|
protected:
|
||||||
|
static CCArray* getNodesToPosition(CCNode* forNode);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Automatically apply the layout's positioning on a set of nodes
|
* Automatically apply the layout's positioning on a set of nodes
|
||||||
* @param nodes Nodes to position
|
* @param on Node to apply the layout on. Position's the node's children
|
||||||
* @param availableSize Give hints to the layout about how much space is
|
* according to the layout. The content size of the node should be
|
||||||
* available. Note that the layout may still overflow
|
* respected as a boundary the layout shouldn't overflow. The node may be
|
||||||
|
* rescaled to better fit its contents. Layouts should respect nodes that
|
||||||
|
* have their PositionHint marked as absolute
|
||||||
*/
|
*/
|
||||||
virtual void apply(CCArray* nodes, CCSize const& availableSize) = 0;
|
virtual void apply(CCNode* on) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,30 +61,62 @@ enum class Alignment {
|
||||||
*/
|
*/
|
||||||
class GEODE_DLL RowLayout : public Layout {
|
class GEODE_DLL RowLayout : public Layout {
|
||||||
protected:
|
protected:
|
||||||
Alignment m_alignment = Alignment::Center;
|
std::optional<Alignment> m_vAlignment = Alignment::Center;
|
||||||
std::optional<float> m_alignVertically;
|
|
||||||
float m_gap;
|
float m_gap;
|
||||||
|
std::optional<float> m_maxAutoScale = std::nullopt;
|
||||||
|
bool m_reverse = false;
|
||||||
|
bool m_fitInside = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void apply(CCArray* nodes, CCSize const& availableSize) override;
|
void apply(CCNode* on) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new RowLayout. Note that this class is not automatically
|
* Create a new RowLayout. Note that this class is not automatically
|
||||||
* managed by default, so you must assign it to a CCNode or manually
|
* managed by default, so you must assign it to a CCNode or manually
|
||||||
* manage the memory yourself.
|
* manage the memory yourself. See the chainable setters on RowLayout for
|
||||||
* @param gap Space between nodes
|
* what options you can customize for the layout
|
||||||
* @param alignVertically Whether to align the nodes vertically, and if so,
|
|
||||||
* what Y position to align them at
|
|
||||||
* @returns Created RowLayout
|
* @returns Created RowLayout
|
||||||
*/
|
*/
|
||||||
static RowLayout* create(
|
static RowLayout* create();
|
||||||
float gap = 5.f,
|
|
||||||
std::optional<float> alignVertically = std::nullopt
|
|
||||||
);
|
|
||||||
|
|
||||||
RowLayout* setAlignment(Alignment align);
|
/**
|
||||||
|
* Sets where to align nodes on the Y-axis. If nullopt, the
|
||||||
|
* nodes' Y-position will not be affected, and the height of the node this
|
||||||
|
* layout applies to isn't altered. If an alignment is given, the height
|
||||||
|
* of the node this layout applies to is shrunk to fit the height of the
|
||||||
|
* nodes and no more. Any nodes that don't fit inside this space are
|
||||||
|
* aligned based on the value
|
||||||
|
* @param align Value
|
||||||
|
* @returns The same RowLayout this was applied on
|
||||||
|
*/
|
||||||
|
RowLayout* setVAlignment(std::optional<Alignment> align);
|
||||||
|
/**
|
||||||
|
* The spacing between the children of the node this layout applies to.
|
||||||
|
* Measured as the space between their edges, not centres
|
||||||
|
*/
|
||||||
RowLayout* setGap(float gap);
|
RowLayout* setGap(float gap);
|
||||||
RowLayout* setAlignVertically(std::optional<float> align);
|
/**
|
||||||
|
* Whether to reverse the direction of the children in this layout or not
|
||||||
|
*/
|
||||||
|
RowLayout* setReverse(bool reverse);
|
||||||
|
/**
|
||||||
|
* If a value is provided, then the node this layout applies to may be
|
||||||
|
* automatically rescaled to fit its contents better. By default the value
|
||||||
|
* is nullopt, which means that the layout doesn't affect the node's scale
|
||||||
|
* in any way, and any nodes that might overflow will be squished using
|
||||||
|
* other methods. If the value is set, the layout assumes that the scaled
|
||||||
|
* content size of the target node is what the content should be fit
|
||||||
|
* inside of, and scales to fit that space. If the value is nullopt, the
|
||||||
|
* unscaled content size is used instead
|
||||||
|
*/
|
||||||
|
RowLayout* setMaxAutoScale(std::optional<float> scale);
|
||||||
|
/**
|
||||||
|
* If true, the children of the node this layout is applied to will be
|
||||||
|
* contained entirely within the bounds of the node's content size. If
|
||||||
|
* false, the children's positions will be within the bounds, but they may
|
||||||
|
* visually overflow depending on their anchor point
|
||||||
|
*/
|
||||||
|
RowLayout* setFitInside(bool fit);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -87,21 +124,59 @@ public:
|
||||||
*/
|
*/
|
||||||
class GEODE_DLL ColumnLayout : public Layout {
|
class GEODE_DLL ColumnLayout : public Layout {
|
||||||
protected:
|
protected:
|
||||||
Alignment m_alignment = Alignment::Center;
|
std::optional<Alignment> m_hAlignment = Alignment::Center;
|
||||||
std::optional<float> m_alignHorizontally;
|
|
||||||
float m_gap;
|
float m_gap;
|
||||||
|
std::optional<float> m_maxAutoScale = std::nullopt;
|
||||||
|
bool m_reverse = false;
|
||||||
|
bool m_fitInside = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void apply(CCArray* nodes, CCSize const& availableSize) override;
|
void apply(CCNode* on) override;
|
||||||
|
|
||||||
static ColumnLayout* create(
|
/**
|
||||||
float gap = 5.f,
|
* Create a new ColumnLayout. Note that this class is not automatically
|
||||||
std::optional<float> alignHorizontally = std::nullopt
|
* managed by default, so you must assign it to a CCNode or manually
|
||||||
);
|
* manage the memory yourself. See the chainable setters on RowLayout for
|
||||||
|
* what options you can customize for the layout
|
||||||
|
* @returns Created ColumnLayout
|
||||||
|
*/
|
||||||
|
static ColumnLayout* create();
|
||||||
|
|
||||||
ColumnLayout* setAlignment(Alignment align);
|
/**
|
||||||
|
* Sets where to align nodes on the X-axis. If nullopt, the
|
||||||
|
* nodes' X-position will not be affected, and the width of the node this
|
||||||
|
* layout applies to isn't altered. If an alignment is given, the width
|
||||||
|
* of the node this layout applies to is shrunk to fit the width of the
|
||||||
|
* nodes and no more. Any nodes that don't fit inside this space are
|
||||||
|
* aligned based on the value
|
||||||
|
* @param align Value
|
||||||
|
* @returns The same RowLayout this was applied on
|
||||||
|
*/
|
||||||
|
ColumnLayout* setHAlignment(std::optional<Alignment> align);
|
||||||
|
/**
|
||||||
|
* The spacing between the children of the node this layout applies to.
|
||||||
|
* Measured as the space between their edges, not centres
|
||||||
|
*/
|
||||||
ColumnLayout* setGap(float gap);
|
ColumnLayout* setGap(float gap);
|
||||||
ColumnLayout* setAlignHorizontally(std::optional<float> align);
|
/**
|
||||||
|
* Whether to reverse the direction of the children in this layout or not
|
||||||
|
*/
|
||||||
|
ColumnLayout* setReverse(bool reverse);
|
||||||
|
/**
|
||||||
|
* If a value is provided, then the node this layout applies to may be
|
||||||
|
* automatically rescaled to fit its contents better. By default the value
|
||||||
|
* is nullopt, which means that the layout doesn't affect the node's scale
|
||||||
|
* in any way, and any nodes that might overflow will be squished using
|
||||||
|
* other methods
|
||||||
|
*/
|
||||||
|
ColumnLayout* setMaxAutoScale(std::optional<float> scale);
|
||||||
|
/**
|
||||||
|
* If true, the children of the node this layout is applied to will be
|
||||||
|
* contained entirely within the bounds of the node's content size. If
|
||||||
|
* false, the children's positions will be within the bounds, but they may
|
||||||
|
* visually overflow depending on their anchor point
|
||||||
|
*/
|
||||||
|
ColumnLayout* setFitInside(bool fit);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -137,7 +212,7 @@ protected:
|
||||||
std::optional<size_t> m_rowSize;
|
std::optional<size_t> m_rowSize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void apply(CCArray* nodes, CCSize const& availableSize) override;
|
void apply(CCNode* on) override;
|
||||||
|
|
||||||
static GridLayout* create(
|
static GridLayout* create(
|
||||||
std::optional<size_t> rowSize,
|
std::optional<size_t> rowSize,
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include <cocos2d.h>
|
#include <cocos2d.h>
|
||||||
#include <Geode/utils/cocos.hpp>
|
#include <Geode/utils/cocos.hpp>
|
||||||
|
#include <Geode/utils/ranges.hpp>
|
||||||
|
#include <Geode/loader/Log.hpp>
|
||||||
|
|
||||||
USE_GEODE_NAMESPACE();
|
USE_GEODE_NAMESPACE();
|
||||||
|
|
||||||
|
@ -9,17 +11,58 @@ void CCNode::swapChildIndices(CCNode* first, CCNode* second) {
|
||||||
m_pChildren->exchangeObject(first, second);
|
m_pChildren->exchangeObject(first, second);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RowLayout::apply(CCArray* nodes, CCSize const& availableSize) {
|
CCArray* Layout::getNodesToPosition(CCNode* on) {
|
||||||
float totalWidth = .0f;
|
auto filtered = CCArray::create();
|
||||||
|
for (auto& child : CCArrayExt<CCNode>(on->getChildren())) {
|
||||||
|
if (child->getPositionHint() != PositionHint::Absolute) {
|
||||||
|
filtered->addObject(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RowLayout::apply(CCNode* on) {
|
||||||
|
|
||||||
|
auto nodes = getNodesToPosition(on);
|
||||||
|
if (m_reverse) {
|
||||||
|
nodes->reverseObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto availableWidth = m_maxAutoScale.has_value() ?
|
||||||
|
on->getScaledContentSize().width :
|
||||||
|
on->getContentSize().width;
|
||||||
|
|
||||||
size_t ix = 0;
|
size_t ix = 0;
|
||||||
|
float totalWidth = .0f;
|
||||||
for (auto& node : CCArrayExt<CCNode*>(nodes)) {
|
for (auto& node : CCArrayExt<CCNode*>(nodes)) {
|
||||||
totalWidth += node->getScaledContentSize().width;
|
// if no need to fit fully inside, figure out what part may overflow
|
||||||
|
// for first item
|
||||||
|
if (ix == 0 && !m_fitInside) {
|
||||||
|
totalWidth += node->getScaledContentSize().width
|
||||||
|
* (1.f - node->getAnchorPoint().x);
|
||||||
|
}
|
||||||
|
// if no need to fit fully inside, figure out what part may overflow
|
||||||
|
// for last item
|
||||||
|
else if (ix == nodes->count() - 1 && !m_fitInside) {
|
||||||
|
totalWidth += node->getScaledContentSize().width
|
||||||
|
* node->getAnchorPoint().x;
|
||||||
|
}
|
||||||
|
// otherwise either we need to fit fully inside or this node is not
|
||||||
|
// at the start or end
|
||||||
|
else {
|
||||||
|
totalWidth += node->getScaledContentSize().width;
|
||||||
|
}
|
||||||
if (ix) {
|
if (ix) {
|
||||||
totalWidth += m_gap;
|
totalWidth += m_gap;
|
||||||
}
|
}
|
||||||
ix++;
|
ix++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto squeeze = availableSize.width / totalWidth;
|
||||||
|
if (squeeze > 1.f) {
|
||||||
|
squeeze = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
float pos;
|
float pos;
|
||||||
switch (m_alignment) {
|
switch (m_alignment) {
|
||||||
default:
|
default:
|
||||||
|
@ -40,22 +83,16 @@ void RowLayout::apply(CCArray* nodes, CCSize const& availableSize) {
|
||||||
if (m_alignVertically) {
|
if (m_alignVertically) {
|
||||||
node->setPositionY(m_alignVertically.value());
|
node->setPositionY(m_alignVertically.value());
|
||||||
}
|
}
|
||||||
pos += sw + m_gap;
|
pos += (sw + m_gap) * squeeze;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout* RowLayout::create(
|
RowLayout* RowLayout::create() {
|
||||||
float gap,
|
return new RowLayout();
|
||||||
std::optional<float> alignVertically
|
|
||||||
) {
|
|
||||||
auto ret = new RowLayout;
|
|
||||||
ret->m_gap = gap;
|
|
||||||
ret->m_alignVertically = alignVertically;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout* RowLayout::setAlignment(Alignment align) {
|
RowLayout* RowLayout::setVAlignment(std::optional<Alignment> align) {
|
||||||
m_alignment = align;
|
m_vAlignment = align;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,14 +101,26 @@ RowLayout* RowLayout::setGap(float gap) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout* RowLayout::setAlignVertically(std::optional<float> align) {
|
RowLayout* RowLayout::setReverse(bool reverse) {
|
||||||
m_alignVertically = align;
|
m_reverse = reverse;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColumnLayout::apply(CCArray* nodes, CCSize const& availableSize) {
|
RowLayout* RowLayout::setMaxAutoScale(std::optional<float> scale) {
|
||||||
|
m_maxAutoScale = scale;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout* RowLayout::setFitInside(bool fit) {
|
||||||
|
m_fitInside = fit;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColumnLayout::apply(CCNode* on) {
|
||||||
float totalHeight = .0f;
|
float totalHeight = .0f;
|
||||||
size_t ix = 0;
|
size_t ix = 0;
|
||||||
|
auto nodes = getNodesToPosition(on);
|
||||||
|
auto availableSize = on->getScaledContentSize();
|
||||||
for (auto& node : CCArrayExt<CCNode*>(nodes)) {
|
for (auto& node : CCArrayExt<CCNode*>(nodes)) {
|
||||||
totalHeight += node->getScaledContentSize().height;
|
totalHeight += node->getScaledContentSize().height;
|
||||||
if (ix) {
|
if (ix) {
|
||||||
|
@ -79,6 +128,14 @@ void ColumnLayout::apply(CCArray* nodes, CCSize const& availableSize) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto squeeze = availableSize.height / totalHeight;
|
||||||
|
if (squeeze > 1.f) {
|
||||||
|
squeeze = 1.f;
|
||||||
|
}
|
||||||
|
if (totalHeight > availableSize.height) {
|
||||||
|
totalHeight = availableSize.height;
|
||||||
|
}
|
||||||
|
|
||||||
float pos;
|
float pos;
|
||||||
switch (m_alignment) {
|
switch (m_alignment) {
|
||||||
default:
|
default:
|
||||||
|
@ -86,35 +143,37 @@ void ColumnLayout::apply(CCArray* nodes, CCSize const& availableSize) {
|
||||||
case Alignment::Begin: pos = -totalHeight; break;
|
case Alignment::Begin: pos = -totalHeight; break;
|
||||||
case Alignment::End: pos = 0.f; break;
|
case Alignment::End: pos = 0.f; break;
|
||||||
}
|
}
|
||||||
|
if (m_reverse) {
|
||||||
|
nodes->reverseObjects();
|
||||||
|
}
|
||||||
|
log::debug("start pos: {}", pos);
|
||||||
|
log::debug("squeeze: {}", squeeze);
|
||||||
for (auto& node : CCArrayExt<CCNode*>(nodes)) {
|
for (auto& node : CCArrayExt<CCNode*>(nodes)) {
|
||||||
auto sh = node->getScaledContentSize().height;
|
auto sh = node->getScaledContentSize().height;
|
||||||
float disp;
|
float disp;
|
||||||
switch (m_alignment) {
|
switch (m_alignment) {
|
||||||
default:
|
default:
|
||||||
case Alignment::Center: disp = sh * node->getAnchorPoint().y; break;
|
case Alignment::Center: disp = sh * node->getAnchorPoint().y; break;
|
||||||
case Alignment::Begin: disp = sh; break;
|
case Alignment::Begin: disp = (m_reverse ? 0.f : sh); break;
|
||||||
case Alignment::End: disp = 0.f; break;
|
case Alignment::End: disp = (m_reverse ? sh : 0.f); break;
|
||||||
}
|
}
|
||||||
|
log::debug("positioning at: {}", pos + disp);
|
||||||
node->setPositionY(pos + disp);
|
node->setPositionY(pos + disp);
|
||||||
if (m_alignHorizontally) {
|
if (m_alignHorizontally) {
|
||||||
node->setPositionX(m_alignHorizontally.value());
|
node->setPositionX(m_alignHorizontally.value());
|
||||||
}
|
}
|
||||||
pos += sh + m_gap;
|
auto opos = pos;
|
||||||
|
pos += (sh + m_gap) * squeeze;
|
||||||
|
log::debug("pos: {} -> {}", opos, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout* ColumnLayout::create(
|
ColumnLayout* ColumnLayout::create() {
|
||||||
float gap,
|
return new ColumnLayout();
|
||||||
std::optional<float> alignHorizontally
|
|
||||||
) {
|
|
||||||
auto ret = new ColumnLayout;
|
|
||||||
ret->m_gap = gap;
|
|
||||||
ret->m_alignHorizontally = alignHorizontally;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout* ColumnLayout::setAlignment(Alignment align) {
|
ColumnLayout* ColumnLayout::setHAlignment(std::optional<Alignment> align) {
|
||||||
m_alignment = align;
|
m_hAlignment = align;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,12 +182,22 @@ ColumnLayout* ColumnLayout::setGap(float gap) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout* ColumnLayout::setAlignHorizontally(std::optional<float> align) {
|
ColumnLayout* ColumnLayout::setReverse(bool reverse) {
|
||||||
m_alignHorizontally = align;
|
m_reverse = reverse;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GridLayout::apply(CCArray* nodes, CCSize const& availableSize) {
|
ColumnLayout* ColumnLayout::setMaxAutoScale(std::optional<float> scale) {
|
||||||
|
m_maxAutoScale = scale;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout* ColumnLayout::setFitInside(bool fit) {
|
||||||
|
m_fitInside = fit;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GridLayout::apply(CCNode* on) {
|
||||||
// todo
|
// todo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,13 @@ CCNode* CCNode::getChildByIDRecursive(std::string const& id) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCNode::setLayout(Layout* layout, bool apply) {
|
void CCNode::setLayout(Layout* layout, bool apply, bool respectAnchor) {
|
||||||
|
if (respectAnchor && this->isIgnoreAnchorPointForPosition()) {
|
||||||
|
for (auto child : CCArrayExt<CCNode>(m_pChildren)) {
|
||||||
|
child->setPosition(child->getPosition() + this->getScaledContentSize());
|
||||||
|
}
|
||||||
|
this->ignoreAnchorPointForPosition(false);
|
||||||
|
}
|
||||||
GeodeNodeMetadata::set(this)->m_layout.reset(layout);
|
GeodeNodeMetadata::set(this)->m_layout.reset(layout);
|
||||||
if (apply) {
|
if (apply) {
|
||||||
this->updateLayout();
|
this->updateLayout();
|
||||||
|
@ -131,15 +137,7 @@ Layout* CCNode::getLayout() {
|
||||||
|
|
||||||
void CCNode::updateLayout() {
|
void CCNode::updateLayout() {
|
||||||
if (auto layout = GeodeNodeMetadata::set(this)->m_layout.get()) {
|
if (auto layout = GeodeNodeMetadata::set(this)->m_layout.get()) {
|
||||||
// nodes with absolute position should never be rearranged
|
layout->apply(this);
|
||||||
auto filtered = CCArray::create();
|
|
||||||
for (auto& child : CCArrayExt<CCNode>(m_pChildren)) {
|
|
||||||
if (child->getPositionHint() != PositionHint::Absolute) {
|
|
||||||
filtered->addObject(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
layout->apply(filtered, m_obContentSize);
|
|
||||||
filtered->release();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,9 +29,9 @@ $register_ids(CreatorLayer) {
|
||||||
detachAndCreateMenu(
|
detachAndCreateMenu(
|
||||||
this,
|
this,
|
||||||
"top-right-menu",
|
"top-right-menu",
|
||||||
ColumnLayout::create(5.f, 0.f)->setAlignment(Alignment::Begin),
|
ColumnLayout::create(),
|
||||||
lockBtn
|
lockBtn
|
||||||
);
|
)->setAnchorPoint({ 0.f, 0.f });
|
||||||
}
|
}
|
||||||
|
|
||||||
// move treasure room button to its own menu
|
// move treasure room button to its own menu
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <Geode/Bindings.hpp>
|
#include <Geode/Bindings.hpp>
|
||||||
#include <Geode/modify/EditLevelLayer.hpp>
|
#include <Geode/modify/EditLevelLayer.hpp>
|
||||||
#include <Geode/utils/cocos.hpp>
|
#include <Geode/utils/cocos.hpp>
|
||||||
|
#include <Geode/ui/BasedButtonSprite.hpp>
|
||||||
|
|
||||||
USE_GEODE_NAMESPACE();
|
USE_GEODE_NAMESPACE();
|
||||||
|
|
||||||
|
@ -45,8 +46,30 @@ $register_ids(EditLevelLayer) {
|
||||||
);
|
);
|
||||||
|
|
||||||
detachAndCreateMenu(
|
detachAndCreateMenu(
|
||||||
menu, "folder-menu", ColumnLayout::create(), menu->getChildByID("folder-button")
|
this, "folder-menu", ColumnLayout::create(), menu->getChildByID("folder-button")
|
||||||
);
|
);
|
||||||
|
menu->setPosition(
|
||||||
|
menu->getPositionX() + static_cast<CCNode*>(
|
||||||
|
menu->getChildren()->firstObject()
|
||||||
|
)->getPositionX(),
|
||||||
|
285.f
|
||||||
|
);
|
||||||
|
menu->setLayout(
|
||||||
|
ColumnLayout::create()
|
||||||
|
->setGap(7.f)
|
||||||
|
->setReverse(true)
|
||||||
|
->setAlignment(Alignment::Begin)
|
||||||
|
->setAlignHorizontally(0.f)
|
||||||
|
);
|
||||||
|
menu->setZOrder(1);
|
||||||
|
|
||||||
|
for (int i = 0; i < rand() % 4; i++) {
|
||||||
|
auto btn = CircleButtonSprite::create(
|
||||||
|
CCLabelBMFont::create(std::to_string(i).c_str(), "bigFont.fnt")
|
||||||
|
);
|
||||||
|
menu->addChild(btn);
|
||||||
|
}
|
||||||
|
menu->updateLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto menu = this->getChildByID("back-button-menu")) setIDSafe(menu, 0, "back-button");
|
if (auto menu = this->getChildByID("back-button-menu")) setIDSafe(menu, 0, "back-button");
|
||||||
|
|
|
@ -44,7 +44,7 @@ $register_ids(MenuLayer) {
|
||||||
pfp->setPositionHint(PositionHint::Absolute);
|
pfp->setPositionHint(PositionHint::Absolute);
|
||||||
}
|
}
|
||||||
|
|
||||||
menu->setLayout(RowLayout::create(18.f, 0.f));
|
menu->setLayout(RowLayout::create()->setGap(18.f));
|
||||||
}
|
}
|
||||||
// bottom menu
|
// bottom menu
|
||||||
if (auto menu = getChildOfType<CCMenu>(this, 1)) {
|
if (auto menu = getChildOfType<CCMenu>(this, 1)) {
|
||||||
|
@ -57,10 +57,10 @@ $register_ids(MenuLayer) {
|
||||||
// move daily chest to its own menu
|
// move daily chest to its own menu
|
||||||
|
|
||||||
if (auto dailyChest = setIDSafe(menu, -1, "daily-chest-button")) {
|
if (auto dailyChest = setIDSafe(menu, -1, "daily-chest-button")) {
|
||||||
detachAndCreateMenu(this, "right-side-menu", ColumnLayout::create(0.f, 0.f), dailyChest);
|
detachAndCreateMenu(this, "right-side-menu", ColumnLayout::create(), dailyChest);
|
||||||
}
|
}
|
||||||
|
|
||||||
menu->setLayout(RowLayout::create(5.f, ach->getPositionY()));
|
menu->setLayout(RowLayout::create());
|
||||||
}
|
}
|
||||||
// social media menu
|
// social media menu
|
||||||
if (auto menu = getChildOfType<CCMenu>(this, 2)) {
|
if (auto menu = getChildOfType<CCMenu>(this, 2)) {
|
||||||
|
@ -79,8 +79,8 @@ $register_ids(MenuLayer) {
|
||||||
|
|
||||||
if (auto closeBtn = setIDSafe(menu, 1, "close-button")) {
|
if (auto closeBtn = setIDSafe(menu, 1, "close-button")) {
|
||||||
detachAndCreateMenu(
|
detachAndCreateMenu(
|
||||||
this, "close-menu", RowLayout::create(5.f, 0.f)->setAlignment(Alignment::Begin), closeBtn
|
this, "close-menu", RowLayout::create(), closeBtn
|
||||||
);
|
)->setAnchorPoint({ 0.f, .5f });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue