mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-26 17:36:05 -05:00
rework layouts
This commit is contained in:
parent
d09b74eb34
commit
e36a5aea35
10 changed files with 287 additions and 218 deletions
107
loader/include/Geode/cocos/base_nodes/Layout.hpp
vendored
107
loader/include/Geode/cocos/base_nodes/Layout.hpp
vendored
|
@ -56,29 +56,28 @@ enum class Alignment {
|
|||
End,
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple layout for arranging nodes in a row (horizontal line)
|
||||
*/
|
||||
class GEODE_DLL RowLayout : public Layout {
|
||||
class GEODE_DLL AxisLayout : public Layout {
|
||||
public:
|
||||
enum Axis : bool {
|
||||
Row,
|
||||
Column,
|
||||
};
|
||||
|
||||
protected:
|
||||
std::optional<Alignment> m_vAlignment = Alignment::Center;
|
||||
float m_gap;
|
||||
std::optional<float> m_maxAutoScale = std::nullopt;
|
||||
Axis m_axis;
|
||||
Alignment m_axisAlignment = Alignment::Center;
|
||||
Alignment m_crossAlignment = Alignment::Center;
|
||||
float m_gap = 5.f;
|
||||
bool m_autoScale = true;
|
||||
bool m_shrinkCrossAxis = true;
|
||||
bool m_reverse = false;
|
||||
bool m_fitInside = false;
|
||||
|
||||
AxisLayout(Axis);
|
||||
|
||||
public:
|
||||
void apply(CCNode* on) override;
|
||||
|
||||
/**
|
||||
* Create a new RowLayout. Note that this class is not automatically
|
||||
* 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 RowLayout
|
||||
*/
|
||||
static RowLayout* create();
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -89,16 +88,17 @@ public:
|
|||
* @param align Value
|
||||
* @returns The same RowLayout this was applied on
|
||||
*/
|
||||
RowLayout* setVAlignment(std::optional<Alignment> align);
|
||||
AxisLayout* setCrossAxisAlignment(Alignment align);
|
||||
AxisLayout* setAxisAlignment(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);
|
||||
AxisLayout* setGap(float gap);
|
||||
/**
|
||||
* Whether to reverse the direction of the children in this layout or not
|
||||
*/
|
||||
RowLayout* setReverse(bool reverse);
|
||||
AxisLayout* 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
|
||||
|
@ -109,30 +109,43 @@ public:
|
|||
* 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);
|
||||
AxisLayout* setAutoScale(bool enable);
|
||||
/**
|
||||
* 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);
|
||||
AxisLayout* setFitInside(bool fit);
|
||||
AxisLayout* setShrinkCrossAxis(bool shrink);
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple layout for arranging nodes in a row (horizontal line)
|
||||
*/
|
||||
class GEODE_DLL RowLayout : public AxisLayout {
|
||||
protected:
|
||||
RowLayout();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a new RowLayout. Note that this class is not automatically
|
||||
* 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 RowLayout
|
||||
*/
|
||||
static RowLayout* create();
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple layout for arranging nodes in a column (vertical line)
|
||||
*/
|
||||
class GEODE_DLL ColumnLayout : public Layout {
|
||||
class GEODE_DLL ColumnLayout : public AxisLayout {
|
||||
protected:
|
||||
std::optional<Alignment> m_hAlignment = Alignment::Center;
|
||||
float m_gap;
|
||||
std::optional<float> m_maxAutoScale = std::nullopt;
|
||||
bool m_reverse = false;
|
||||
bool m_fitInside = false;
|
||||
ColumnLayout();
|
||||
|
||||
public:
|
||||
void apply(CCNode* on) override;
|
||||
|
||||
/**
|
||||
* Create a new ColumnLayout. Note that this class is not automatically
|
||||
* managed by default, so you must assign it to a CCNode or manually
|
||||
|
@ -141,42 +154,6 @@ public:
|
|||
* @returns Created ColumnLayout
|
||||
*/
|
||||
static ColumnLayout* create();
|
||||
|
||||
/**
|
||||
* 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);
|
||||
/**
|
||||
* 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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <Geode/utils/cocos.hpp>
|
||||
#include <Geode/utils/ranges.hpp>
|
||||
#include <Geode/loader/Log.hpp>
|
||||
#include <Geode/binding/CCMenuItemSpriteExtra.hpp>
|
||||
|
||||
USE_GEODE_NAMESPACE();
|
||||
|
||||
|
@ -21,182 +22,230 @@ CCArray* Layout::getNodesToPosition(CCNode* on) {
|
|||
return filtered;
|
||||
}
|
||||
|
||||
void RowLayout::apply(CCNode* on) {
|
||||
|
||||
void AxisLayout::apply(CCNode* on) {
|
||||
auto nodes = getNodesToPosition(on);
|
||||
if (m_reverse) {
|
||||
nodes->reverseObjects();
|
||||
}
|
||||
|
||||
auto availableWidth = m_maxAutoScale.has_value() ?
|
||||
on->getScaledContentSize().width :
|
||||
on->getContentSize().width;
|
||||
float availableAxisLength;
|
||||
float originalCrossHeight;
|
||||
|
||||
if (m_axis == Axis::Row) {
|
||||
availableAxisLength = on->getContentSize().width;
|
||||
originalCrossHeight = on->getContentSize().height;
|
||||
}
|
||||
else {
|
||||
availableAxisLength = on->getContentSize().height;
|
||||
originalCrossHeight = on->getContentSize().width;
|
||||
}
|
||||
|
||||
size_t ix = 0;
|
||||
float totalWidth = .0f;
|
||||
float totalAxisLength = .0f;
|
||||
float maxCrossLength = 0.f;
|
||||
for (auto& node : CCArrayExt<CCNode*>(nodes)) {
|
||||
float axisLength;
|
||||
float axisAnchor;
|
||||
float crossLength;
|
||||
if (m_axis == Axis::Row) {
|
||||
axisLength = node->getScaledContentSize().width;
|
||||
axisAnchor = node->getAnchorPoint().x;
|
||||
crossLength = node->getScaledContentSize().height;
|
||||
}
|
||||
else {
|
||||
axisLength = node->getScaledContentSize().height;
|
||||
axisAnchor = node->getAnchorPoint().y;
|
||||
crossLength = node->getScaledContentSize().width;
|
||||
}
|
||||
// if no need to fit fully inside and only one item exists, the total
|
||||
// width taken up is 0
|
||||
if (nodes->count() == 1 && !m_fitInside) {
|
||||
totalAxisLength = 0;
|
||||
}
|
||||
// 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);
|
||||
else if (ix == 0 && !m_fitInside) {
|
||||
totalAxisLength += axisLength * (1.f - axisAnchor);
|
||||
}
|
||||
// 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;
|
||||
totalAxisLength += axisLength * axisAnchor;
|
||||
}
|
||||
// otherwise either we need to fit fully inside or this node is not
|
||||
// at the start or end
|
||||
else {
|
||||
totalWidth += node->getScaledContentSize().width;
|
||||
totalAxisLength += axisLength;
|
||||
}
|
||||
if (ix) {
|
||||
totalWidth += m_gap;
|
||||
totalAxisLength += m_gap;
|
||||
}
|
||||
if (crossLength > maxCrossLength) {
|
||||
maxCrossLength = crossLength;
|
||||
}
|
||||
ix++;
|
||||
}
|
||||
|
||||
auto squeeze = availableSize.width / totalWidth;
|
||||
if (squeeze > 1.f) {
|
||||
squeeze = 1.f;
|
||||
const auto minScale = .65f;
|
||||
|
||||
// assume intended scale is 1x
|
||||
auto setScale = 1.f;
|
||||
auto squeeze = 1.f;
|
||||
|
||||
// check for overflow
|
||||
// first try to make the node smaller
|
||||
if (totalAxisLength > availableAxisLength && m_autoScale) {
|
||||
setScale = availableAxisLength / totalAxisLength;
|
||||
if (setScale < minScale) {
|
||||
setScale = minScale;
|
||||
}
|
||||
totalAxisLength *= setScale;
|
||||
}
|
||||
|
||||
// if we're still overflowing, squeeze nodes closer together
|
||||
if (totalAxisLength > availableAxisLength) {
|
||||
squeeze = availableAxisLength / totalAxisLength;
|
||||
totalAxisLength = availableAxisLength;
|
||||
}
|
||||
|
||||
// resize target to match settings
|
||||
if (m_shrinkCrossAxis) {
|
||||
if (m_axis == Axis::Row) {
|
||||
on->setContentSize({
|
||||
availableAxisLength,
|
||||
maxCrossLength,
|
||||
});
|
||||
}
|
||||
else {
|
||||
on->setContentSize({
|
||||
maxCrossLength,
|
||||
availableAxisLength,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
float pos;
|
||||
switch (m_alignment) {
|
||||
default:
|
||||
case Alignment::Center: pos = -totalWidth / 2; break;
|
||||
case Alignment::Begin: pos = -totalWidth; break;
|
||||
case Alignment::End: pos = 0.f; break;
|
||||
switch (m_axisAlignment) {
|
||||
case Alignment::Begin: {
|
||||
pos = 0.f;
|
||||
} break;
|
||||
|
||||
case Alignment::Center: {
|
||||
pos = availableAxisLength / 2 - totalAxisLength / 2;
|
||||
} break;
|
||||
|
||||
case Alignment::End: {
|
||||
pos = availableAxisLength - totalAxisLength;
|
||||
} break;
|
||||
}
|
||||
ix = 0;
|
||||
for (auto& node : CCArrayExt<CCNode*>(nodes)) {
|
||||
auto sw = node->getScaledContentSize().width;
|
||||
float disp;
|
||||
switch (m_alignment) {
|
||||
default:
|
||||
case Alignment::Center: disp = sw * node->getAnchorPoint().x; break;
|
||||
case Alignment::Begin: disp = sw; break;
|
||||
case Alignment::End: disp = 0.f; break;
|
||||
// rescale node if overflowing
|
||||
if (m_autoScale) {
|
||||
// CCMenuItemSpriteExtra is quirky af
|
||||
if (auto btn = typeinfo_cast<CCMenuItemSpriteExtra*>(node)) {
|
||||
btn->m_baseScale = setScale;
|
||||
}
|
||||
node->setScale(setScale);
|
||||
}
|
||||
node->setPositionX(pos + disp);
|
||||
if (m_alignVertically) {
|
||||
node->setPositionY(m_alignVertically.value());
|
||||
float axisLength;
|
||||
float axisAnchor;
|
||||
float crossLength;
|
||||
float crossAnchor;
|
||||
if (m_axis == Axis::Row) {
|
||||
axisLength = node->getScaledContentSize().width;
|
||||
axisAnchor = node->getAnchorPoint().x;
|
||||
crossLength = node->getScaledContentSize().height;
|
||||
crossAnchor = node->getAnchorPoint().y;
|
||||
}
|
||||
pos += (sw + m_gap) * squeeze;
|
||||
else {
|
||||
axisLength = node->getScaledContentSize().height;
|
||||
axisAnchor = node->getAnchorPoint().y;
|
||||
crossLength = node->getScaledContentSize().width;
|
||||
crossAnchor = node->getAnchorPoint().x;
|
||||
}
|
||||
float axisPos;
|
||||
if (ix == 0 && !m_fitInside) {
|
||||
axisPos = pos;
|
||||
pos += (axisLength * (1.f - axisAnchor) + m_gap * setScale) * squeeze;
|
||||
}
|
||||
else {
|
||||
axisPos = pos + axisLength * axisAnchor * squeeze;
|
||||
pos += (axisLength + m_gap * setScale) * squeeze;
|
||||
}
|
||||
float crossPos;
|
||||
switch (m_crossAlignment) {
|
||||
case Alignment::Begin: {
|
||||
crossPos = crossLength * crossAnchor;
|
||||
} break;
|
||||
|
||||
case Alignment::Center: {
|
||||
crossPos = maxCrossLength / 2 - crossLength * (.5f - crossAnchor);
|
||||
} break;
|
||||
|
||||
case Alignment::End: {
|
||||
crossPos = maxCrossLength - crossLength * (1.f - crossAnchor);
|
||||
} break;
|
||||
}
|
||||
if (m_axis == Axis::Row) {
|
||||
node->setPosition(axisPos, crossPos);
|
||||
}
|
||||
else {
|
||||
node->setPosition(crossPos, axisPos);
|
||||
}
|
||||
ix++;
|
||||
}
|
||||
}
|
||||
|
||||
AxisLayout::AxisLayout(Axis axis) : m_axis(axis) {}
|
||||
|
||||
AxisLayout* AxisLayout::setCrossAxisAlignment(Alignment align) {
|
||||
m_crossAlignment = align;
|
||||
return this;
|
||||
}
|
||||
|
||||
AxisLayout* AxisLayout::setAxisAlignment(Alignment align) {
|
||||
m_axisAlignment = align;
|
||||
return this;
|
||||
}
|
||||
|
||||
AxisLayout* AxisLayout::setGap(float gap) {
|
||||
m_gap = gap;
|
||||
return this;
|
||||
}
|
||||
|
||||
AxisLayout* AxisLayout::setReverse(bool reverse) {
|
||||
m_reverse = reverse;
|
||||
return this;
|
||||
}
|
||||
|
||||
AxisLayout* AxisLayout::setAutoScale(bool scale) {
|
||||
m_autoScale = scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
AxisLayout* AxisLayout::setFitInside(bool fit) {
|
||||
m_fitInside = fit;
|
||||
return this;
|
||||
}
|
||||
|
||||
AxisLayout* AxisLayout::setShrinkCrossAxis(bool shrink) {
|
||||
m_shrinkCrossAxis = shrink;
|
||||
return this;
|
||||
}
|
||||
|
||||
RowLayout::RowLayout() : AxisLayout(AxisLayout::Row) {}
|
||||
|
||||
RowLayout* RowLayout::create() {
|
||||
return new RowLayout();
|
||||
}
|
||||
|
||||
RowLayout* RowLayout::setVAlignment(std::optional<Alignment> align) {
|
||||
m_vAlignment = align;
|
||||
return this;
|
||||
}
|
||||
|
||||
RowLayout* RowLayout::setGap(float gap) {
|
||||
m_gap = gap;
|
||||
return this;
|
||||
}
|
||||
|
||||
RowLayout* RowLayout::setReverse(bool reverse) {
|
||||
m_reverse = reverse;
|
||||
return this;
|
||||
}
|
||||
|
||||
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;
|
||||
size_t ix = 0;
|
||||
auto nodes = getNodesToPosition(on);
|
||||
auto availableSize = on->getScaledContentSize();
|
||||
for (auto& node : CCArrayExt<CCNode*>(nodes)) {
|
||||
totalHeight += node->getScaledContentSize().height;
|
||||
if (ix) {
|
||||
totalHeight += m_gap;
|
||||
}
|
||||
}
|
||||
|
||||
auto squeeze = availableSize.height / totalHeight;
|
||||
if (squeeze > 1.f) {
|
||||
squeeze = 1.f;
|
||||
}
|
||||
if (totalHeight > availableSize.height) {
|
||||
totalHeight = availableSize.height;
|
||||
}
|
||||
|
||||
float pos;
|
||||
switch (m_alignment) {
|
||||
default:
|
||||
case Alignment::Center: pos = -totalHeight / 2; break;
|
||||
case Alignment::Begin: pos = -totalHeight; 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)) {
|
||||
auto sh = node->getScaledContentSize().height;
|
||||
float disp;
|
||||
switch (m_alignment) {
|
||||
default:
|
||||
case Alignment::Center: disp = sh * node->getAnchorPoint().y; break;
|
||||
case Alignment::Begin: disp = (m_reverse ? 0.f : sh); break;
|
||||
case Alignment::End: disp = (m_reverse ? sh : 0.f); break;
|
||||
}
|
||||
log::debug("positioning at: {}", pos + disp);
|
||||
node->setPositionY(pos + disp);
|
||||
if (m_alignHorizontally) {
|
||||
node->setPositionX(m_alignHorizontally.value());
|
||||
}
|
||||
auto opos = pos;
|
||||
pos += (sh + m_gap) * squeeze;
|
||||
log::debug("pos: {} -> {}", opos, pos);
|
||||
}
|
||||
}
|
||||
ColumnLayout::ColumnLayout() : AxisLayout(AxisLayout::Column) {}
|
||||
|
||||
ColumnLayout* ColumnLayout::create() {
|
||||
return new ColumnLayout();
|
||||
}
|
||||
|
||||
ColumnLayout* ColumnLayout::setHAlignment(std::optional<Alignment> align) {
|
||||
m_hAlignment = align;
|
||||
return this;
|
||||
}
|
||||
|
||||
ColumnLayout* ColumnLayout::setGap(float gap) {
|
||||
m_gap = gap;
|
||||
return this;
|
||||
}
|
||||
|
||||
ColumnLayout* ColumnLayout::setReverse(bool reverse) {
|
||||
m_reverse = reverse;
|
||||
return this;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -64,12 +64,13 @@ static CCMenu* detachAndCreateMenu(CCNode* parent, const char* menuID, Layout* l
|
|||
newMenu->setPosition(parent->convertToNodeSpace(oldMenu->convertToWorldSpace(first->getPosition())));
|
||||
newMenu->setID(menuID);
|
||||
newMenu->setZOrder(oldMenu->getZOrder());
|
||||
newMenu->setLayout(layout);
|
||||
parent->addChild(newMenu);
|
||||
|
||||
first->setPosition(0, 0);
|
||||
newMenu->addChild(first);
|
||||
first->release();
|
||||
|
||||
newMenu->setLayout(layout);
|
||||
|
||||
(switchToMenu(args, newMenu), ...);
|
||||
|
||||
|
|
|
@ -29,9 +29,11 @@ $register_ids(CreatorLayer) {
|
|||
detachAndCreateMenu(
|
||||
this,
|
||||
"top-right-menu",
|
||||
ColumnLayout::create(),
|
||||
ColumnLayout::create()
|
||||
->setFitInside(false)
|
||||
->setAxisAlignment(Alignment::Begin),
|
||||
lockBtn
|
||||
)->setAnchorPoint({ 0.f, 0.f });
|
||||
)->setAnchorPoint({ .5f, 0.f });
|
||||
}
|
||||
|
||||
// move treasure room button to its own menu
|
||||
|
@ -39,9 +41,11 @@ $register_ids(CreatorLayer) {
|
|||
detachAndCreateMenu(
|
||||
this,
|
||||
"bottom-right-menu",
|
||||
ColumnLayout::create(5.f, 0.f)->setAlignment(Alignment::End),
|
||||
ColumnLayout::create()
|
||||
->setFitInside(false)
|
||||
->setAxisAlignment(Alignment::End),
|
||||
roomBtn
|
||||
);
|
||||
)->setAnchorPoint({ .5f, 1.f });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,10 +57,11 @@ $register_ids(EditLevelLayer) {
|
|||
menu->setLayout(
|
||||
ColumnLayout::create()
|
||||
->setGap(7.f)
|
||||
->setFitInside(false)
|
||||
->setAxisAlignment(Alignment::Begin)
|
||||
->setReverse(true)
|
||||
->setAlignment(Alignment::Begin)
|
||||
->setAlignHorizontally(0.f)
|
||||
);
|
||||
menu->setAnchorPoint({ .5f, 0.f });
|
||||
menu->setZOrder(1);
|
||||
|
||||
for (int i = 0; i < rand() % 4; i++) {
|
||||
|
|
|
@ -177,10 +177,12 @@ $register_ids(EditorUI) {
|
|||
detachAndCreateMenu(
|
||||
this,
|
||||
"top-right-menu",
|
||||
RowLayout::create()->setAlignment(Alignment::End),
|
||||
RowLayout::create()
|
||||
->setFitInside(false)
|
||||
->setAxisAlignment(Alignment::End),
|
||||
menu->getChildByID("pause-button"),
|
||||
menu->getChildByID("settings-button")
|
||||
);
|
||||
)->setAnchorPoint({ 1.f, .5f });
|
||||
|
||||
detachAndCreateMenu(
|
||||
this,
|
||||
|
|
|
@ -21,12 +21,19 @@ $register_ids(LevelBrowserLayer) {
|
|||
detachAndCreateMenu(
|
||||
this,
|
||||
"my-levels-menu",
|
||||
ColumnLayout::create(5.f, 0.f)->setAlignment(Alignment::End),
|
||||
ColumnLayout::create()
|
||||
->setFitInside(false)
|
||||
->setAxisAlignment(Alignment::End),
|
||||
myLevelsBtn
|
||||
);
|
||||
)->setAnchorPoint({ .5f, 1.f });
|
||||
}
|
||||
|
||||
menu->setLayout(ColumnLayout::create(5.f, 0.f)->setAlignment(Alignment::End));
|
||||
menu->setLayout(
|
||||
ColumnLayout::create()
|
||||
->setFitInside(false)
|
||||
->setAxisAlignment(Alignment::End)
|
||||
);
|
||||
menu->setAnchorPoint({ .5f, 1.f });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,8 +44,13 @@ $register_ids(LevelInfoLayer) {
|
|||
|
||||
if (auto name = setIDSafe(menu, 0, "creator-name")) {
|
||||
detachAndCreateMenu(
|
||||
this, "creator-info-menu", ColumnLayout::create()->setAlignment(Alignment::Begin), name
|
||||
);
|
||||
this,
|
||||
"creator-info-menu",
|
||||
ColumnLayout::create()
|
||||
->setFitInside(false)
|
||||
->setAxisAlignment(Alignment::Begin),
|
||||
name
|
||||
)->setAnchorPoint({ .5f, 0.f });
|
||||
}
|
||||
|
||||
auto leftSideMenu = CCMenu::create();
|
||||
|
|
|
@ -165,9 +165,11 @@ $register_ids(LevelSettingsLayer) {
|
|||
detachAndCreateMenu(
|
||||
this,
|
||||
"font-button-menu",
|
||||
RowLayout::create()->setAlignment(Alignment::End),
|
||||
RowLayout::create()
|
||||
->setFitInside(false)
|
||||
->setAxisAlignment(Alignment::End),
|
||||
menu->getChildByID("font-button")
|
||||
);
|
||||
)->setAnchorPoint({ .5f, 1.f });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,9 +41,17 @@ $register_ids(MenuLayer) {
|
|||
setIDSafe(menu, 2, "editor-button");
|
||||
|
||||
if (auto pfp = setIDSafe(menu, 3, "profile-button")) {
|
||||
pfp->setPositionHint(PositionHint::Absolute);
|
||||
detachAndCreateMenu(
|
||||
this, "profile-menu",
|
||||
ColumnLayout::create()
|
||||
->setFitInside(false)
|
||||
->setAxisAlignment(Alignment::Begin)
|
||||
->setReverse(true),
|
||||
pfp
|
||||
)->setAnchorPoint({ .5f, .0f });
|
||||
}
|
||||
|
||||
menu->setContentSize({ 400.f, 65.f });
|
||||
menu->setLayout(RowLayout::create()->setGap(18.f));
|
||||
}
|
||||
// bottom menu
|
||||
|
@ -57,10 +65,18 @@ $register_ids(MenuLayer) {
|
|||
// move daily chest to its own menu
|
||||
|
||||
if (auto dailyChest = setIDSafe(menu, -1, "daily-chest-button")) {
|
||||
detachAndCreateMenu(this, "right-side-menu", ColumnLayout::create(), dailyChest);
|
||||
auto menu = detachAndCreateMenu(
|
||||
this,
|
||||
"right-side-menu",
|
||||
ColumnLayout::create()->setFitInside(true),
|
||||
dailyChest
|
||||
);
|
||||
menu->setContentSize({ 65.f, 180.f });
|
||||
menu->updateLayout();
|
||||
}
|
||||
|
||||
menu->setLayout(RowLayout::create());
|
||||
menu->setContentSize({ 360.f, 65.f });
|
||||
menu->setLayout(RowLayout::create()->setFitInside(true));
|
||||
}
|
||||
// social media menu
|
||||
if (auto menu = getChildOfType<CCMenu>(this, 2)) {
|
||||
|
@ -79,7 +95,12 @@ $register_ids(MenuLayer) {
|
|||
|
||||
if (auto closeBtn = setIDSafe(menu, 1, "close-button")) {
|
||||
detachAndCreateMenu(
|
||||
this, "close-menu", RowLayout::create(), closeBtn
|
||||
this,
|
||||
"close-menu",
|
||||
RowLayout::create()
|
||||
->setFitInside(false)
|
||||
->setAxisAlignment(Alignment::Begin),
|
||||
closeBtn
|
||||
)->setAnchorPoint({ 0.f, .5f });
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue