adding new big stuff to layouts, this def wont work

also removed PositionHint
This commit is contained in:
hjfod 2023-02-15 16:02:56 +02:00
parent ffd50eb0f1
commit 3827a00964
7 changed files with 428 additions and 115 deletions

View file

@ -973,22 +973,6 @@ public:
*/
GEODE_DLL LayoutOptions* getLayoutOptions();
/**
* Give a hint to the current Layout about where this node should be
* positioned in it. Allows detaching the node from the current
* layout by setting position to absolute
* @param hint The hint to set
* @note The layout definitely should, but might not respect the hint
* given
* @note Geode addition
*/
GEODE_DLL void setPositionHint(PositionHint hint);
/**
* Get the current position hint for this node
* @note Geode addition
*/
GEODE_DLL PositionHint getPositionHint();
/**
* Swap two children
* @param first One of the nodes to swap

View file

@ -28,8 +28,7 @@ public:
* @param on Node to apply the layout on. Position's the node's children
* according to the layout. The content size of the node should be
* 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
* rescaled to better fit its contents
*/
virtual void apply(CCNode* on) = 0;
@ -42,25 +41,15 @@ public:
};
/**
* Determines how a node should be positioned within its parent, if that
* parent has an automatically positioning layout
* The direction of an AxisLayout
*/
enum class PositionHint {
// The container can determine the best position
// for this node
Default,
// The container's layout should not affect the
// position of this node
Absolute,
};
enum class Axis {
Row,
Column,
};
/**
* Specifies the alignment of something
* Specifies the alignment of something in an AxisLayout
*/
enum class AxisAlignment {
// Align items to the start
@ -77,18 +66,46 @@ enum class AxisAlignment {
Even,
};
constexpr float AXISLAYOUT_DEFAULT_MIN_SCALE = 0.65f;
constexpr int AXISLAYOUT_DEFAULT_PRIORITY = 0;
/**
* Options for controlling the behaviour of individual nodes in an AxisLayout
* @example
* auto node = CCNode::create();
* // this node will have 10 units of spacing between it and the next one
* node->setLayoutOptions(
* AxisLayoutOptions::create()
* ->setNextGap(10.f)
* );
* someNodeWithALayout->addChild(node);
*/
class GEODE_DLL AxisLayoutOptions : public LayoutOptions {
protected:
std::optional<float> m_maxScale = 1.f;
std::optional<bool> m_autoScale = std::nullopt;
float m_maxScale = 1.f;
float m_minScale = AXISLAYOUT_DEFAULT_MIN_SCALE;
float m_relativeScale = 1.f;
std::optional<float> m_length = std::nullopt;
std::optional<float> m_nextGap = std::nullopt;
std::optional<float> m_prevGap = std::nullopt;
bool m_breakLine = false;
bool m_sameLine = false;
int m_scalePriority = AXISLAYOUT_DEFAULT_PRIORITY;
public:
static AxisLayoutOptions* create();
std::optional<float> getMaxScale() const;
std::optional<bool> getAutoScale() const;
float getMaxScale() const;
float getMinScale() const;
float getRelativeScale() const;
std::optional<float> getLength() const;
std::optional<float> getPrevGap() const;
std::optional<float> getNextGap() const;
bool getBreakLine() const;
bool getSameLine() const;
int getScalePriority() const;
/**
* Set the maximum scale this node can be if it's contained in an
@ -97,11 +114,22 @@ public:
AxisLayoutOptions* setMaxScale(float scale);
/**
* Disables auto-scaling for this node, even if the layout the node is
* contained in has it enabled. To enable auto-scaling, provide a max
* scale for the node in setMaxScale
* Set the minimum scale this node can be if it's contained in an
* auto-scaled layout. Default is AXISLAYOUT_DEFAULT_MIN_SCALE
*/
AxisLayoutOptions* setMinScale(float scale);
/**
* Set the relative scale of this node compared to other nodes if it's
* contained in an auto-scaled layout. Default is 1
*/
AxisLayoutOptions* setRelativeScale(float scale);
/**
* Set auto-scaling for this node, overriding the layout's auto-scale
* setting. If nullopt, the layout's auto-scale options will be used
*/
AxisLayoutOptions* disableAutoScale();
AxisLayoutOptions* setAutoScale(std::optional<bool> enabled);
/**
* Set an absolute length for this node. If nullopt, the length will be
@ -109,16 +137,67 @@ public:
*/
AxisLayoutOptions* setLength(std::optional<float> length);
/**
* Override the default gap in the layout between this node and the
* previous one. If nullopt, the default gap of the layout will be used
*/
AxisLayoutOptions* setPrevGap(std::optional<float> gap);
/**
* Override the default gap in the layout between this node and the next
* one. If nullopt, the default gap of the layout will be used
*/
AxisLayoutOptions* setNextGap(std::optional<float> gap);
/**
* If enabled, the node will always cause a growable axis layout to break
* into a new line even if the current line could've fit the next node
*/
AxisLayoutOptions* setBreakLine(bool enable);
/**
* If enabled, the node will be forced to be on the same line as the
* previous node even if doing this would overflow
*/
AxisLayoutOptions* setSameLine(bool enable);
/**
* Set the scale priority of this node. Nodes with higher priority will be
* scaled down first before nodes with lower priority when an auto-scaled
* layout attempts to fit its contents. Default is
* AXISLAYOUT_DEFAULT_PRIORITY
* @note For optimal performance, the priorities should all be close to
* each other with no gaps
*/
AxisLayoutOptions* setScalePriority(int priority);
};
/**
* Layout for arranging nodes along an axis. Used to implement row, column, and
* grid layouts
* A multi-purpose dynamic layout for arranging nodes along an axis. Can be
* used to arrange nodes in a single line, a grid, or a flex layout. The
* RowLayout and ColumnLayout classes function as simple thin wrappers over
* AxisLayout. The positioning of individual nodes in the layout can be
* further controlled using AxisLayoutOptions
* @warning Calculating layouts can get increasingly expensive for large
* amounts of child nodes being fit into a small space - while this should
* never prove a real performance concern as most layouts only have a few
* hundred children at the very most, be aware that you probably shouldn't
* call CCNode::updateLayout every frame for a menu with thousands of children
* @example
* auto menu = CCMenu::create();
* // The menu's children will be arranged horizontally, unless they overflow
* // the content size width in which case a new line will be inserted and
* // aligned to the left. The menu automatically will automatically grow in
* // height to fit all the rows
* menu->setLayout(
* RowLayout::create()
* ->setGap(10.f)
* ->setGrowCrossAxis(true)
* ->setAxisAlignment(AxisAlignment::Start)
* );
* menu->setContentSize({ 200.f, 0.f });
* menu->addChild(...);
* menu->updateLayout();
*/
class GEODE_DLL AxisLayout : public Layout {
protected:
@ -134,8 +213,27 @@ protected:
struct Row;
Row* fitInRow(CCNode* on, CCArray* nodes, float scale, float squish) const;
void tryFitLayout(CCNode* on, CCArray* nodes, float scale, float squish) const;
std::tuple<
std::pair<int, int>,
std::pair<float, float>,
bool
> findProps(CCArray* nodes) const;
bool shouldAutoScale(AxisLayoutOptions* opts) const;
float nextGap(AxisLayoutOptions* now, AxisLayoutOptions* next) const;
Row* fitInRow(
CCNode* on, CCArray* nodes,
std::pair<float, float> const& minMaxScales,
std::pair<int, int> const& minMaxPrios,
bool doAutoScale,
float scale, float squish, int prio
) const;
void tryFitLayout(
CCNode* on, CCArray* nodes,
std::pair<float, float> const& minMaxScales,
std::pair<int, int> const& minMaxPrios,
bool doAutoScale,
float scale, float squish, int prio
) const;
AxisLayout(Axis);

View file

@ -58,6 +58,17 @@ namespace geode {
return buf.str();
}
template <class T>
requires requires(T t) {
parse(t);
}
std::string parse(std::optional<T> const& thing) {
if (thing.has_value()) {
return "opt(" + parse(thing.value()) + ")";
}
return "nullopt";
}
// Log component system
struct GEODE_DLL ComponentTrait {

View file

@ -32,13 +32,10 @@ void CCNode::insertAfter(CCNode* child, CCNode* after) {
}
CCArray* Layout::getNodesToPosition(CCNode* on) {
auto filtered = CCArray::create();
for (auto& child : CCArrayExt<CCNode>(on->getChildren())) {
if (child->getPositionHint() != PositionHint::Absolute) {
filtered->addObject(child);
}
if (!on->getChildren()) {
return CCArray::create();
}
return filtered;
return on->getChildren()->shallowCopy();
}
static AxisLayoutOptions* axisOpts(CCNode* node) {
@ -46,14 +43,64 @@ static AxisLayoutOptions* axisOpts(CCNode* node) {
return typeinfo_cast<AxisLayoutOptions*>(node->getLayoutOptions());
}
static bool isOptsBreakLine(CCNode* node) {
if (auto opts = axisOpts(node)) {
static bool isOptsBreakLine(AxisLayoutOptions* opts) {
if (opts) {
return opts->getBreakLine();
}
return false;
}
static constexpr float AXIS_MIN_SCALE = 0.65f;
static bool isOptsSameLine(AxisLayoutOptions* opts) {
if (opts) {
return opts->getSameLine();
}
return false;
}
static int optsScalePrio(AxisLayoutOptions* opts) {
if (opts) {
return opts->getScalePriority();
}
return 0;
}
static float optsMinScale(AxisLayoutOptions* opts) {
if (opts) {
return opts->getMinScale();
}
return AXISLAYOUT_DEFAULT_MIN_SCALE;
}
static float optsMaxScale(AxisLayoutOptions* opts) {
if (opts) {
return opts->getMaxScale();
}
return 1.f;
}
struct AxisLayout::Row : public CCObject {
float nextOverflowScaleDownFactor;
float axisLength;
float crossLength;
float axisEndsLength;
// all layout calculations happen within a single frame so no Ref needed
CCArray* nodes;
Row(
float scaleFactor,
float axisLength,
float crossLength,
float axisEndsLength,
CCArray* nodes
) : nextOverflowScaleDownFactor(scaleFactor),
axisLength(axisLength),
crossLength(crossLength),
axisEndsLength(axisEndsLength),
nodes(nodes)
{
this->autorelease();
}
};
struct AxisPosition {
float axisLength;
@ -91,73 +138,146 @@ static AxisPosition nodeAxis(CCNode* node, Axis axis, float scale) {
}
}
struct AxisLayout::Row : public CCObject {
float nextOverflowScaleDownFactor;
float axisLength;
float crossLength;
float axisEndsLength;
Ref<CCArray> nodes;
Row(
float scaleFactor,
float axisLength,
float crossLength,
float axisEndsLength,
CCArray* nodes
) : nextOverflowScaleDownFactor(scaleFactor),
axisLength(axisLength),
crossLength(crossLength),
axisEndsLength(axisEndsLength),
nodes(nodes)
{
this->autorelease();
float AxisLayout::nextGap(AxisLayoutOptions* now, AxisLayoutOptions* next) const {
std::optional<float> gap;
if (now) {
gap = now->getNextGap();
}
};
if (next && (!gap || gap.value() < next->getPrevGap())) {
gap = next->getPrevGap();
}
return gap.value_or(m_gap);
}
AxisLayout::Row* AxisLayout::fitInRow(CCNode* on, CCArray* nodes, float scale, float squish) const {
bool AxisLayout::shouldAutoScale(AxisLayoutOptions* opts) const {
if (!opts) return m_autoScale;
return opts->getAutoScale().value_or(m_autoScale);
}
std::tuple<
std::pair<int, int>,
std::pair<float, float>,
bool
> AxisLayout::findProps(CCArray* nodes) const {
std::pair<int, int> minMaxPrio;
std::pair<float, float> minMaxScale;
bool doAutoScale = m_autoScale;
bool first = true;
for (auto node : CCArrayExt<CCNode>(nodes)) {
int prio = 0;
float max = 1.f;
float min = AXISLAYOUT_DEFAULT_MIN_SCALE;
if (auto opts = axisOpts(node)) {
prio = opts->getScalePriority();
max = opts->getMaxScale();
min = opts->getMinScale();
if (opts->getAutoScale().value_or(false)) {
doAutoScale = true;
}
}
if (first) {
minMaxPrio = { prio, prio };
minMaxScale = { min, max };
first = false;
}
else {
if (prio < minMaxPrio.first) {
minMaxPrio.first = prio;
}
if (prio > minMaxPrio.second) {
minMaxPrio.second = prio;
}
if (min < minMaxPrio.first) {
minMaxPrio.first = min;
}
if (max > minMaxPrio.second) {
minMaxPrio.second = max;
}
}
}
return { minMaxPrio, minMaxScale, doAutoScale };
}
AxisLayout::Row* AxisLayout::fitInRow(
CCNode* on, CCArray* nodes,
std::pair<float, float> const& minMaxScales,
std::pair<int, int> const& minMaxPrios,
bool doAutoScale,
float scale, float squish, int prio
) const {
float nextAxisLength = 0.f;
float axisLength = 0.f;
float crossLength = 0.f;
auto res = CCArray::create();
auto available = nodeAxis(on, m_axis, 1.f);
CCNode* prev = nullptr;
AxisLayoutOptions* prev = nullptr;
size_t ix = 0;
for (auto& node : CCArrayExt<CCNode*>(nodes)) {
if (m_autoScale) {
if (auto opts = axisOpts(node)) {
if (auto max = opts->getMaxScale()) {
node->setScale(max.value());
}
auto opts = axisOpts(node);
if (this->shouldAutoScale(opts)) {
if (opts) {
node->setScale(opts->getMaxScale() * opts->getRelativeScale());
}
else {
node->setScale(1);
}
}
auto pos = nodeAxis(node, m_axis, scale * squish);
AxisPosition pos;
// if this node's scale prio is higher than current, don't scale it
// down
if (prio > optsScalePrio(opts)) {
pos = nodeAxis(node, m_axis, squish);
}
// otherwise if it matches scale it down by the factor
else if (prio == optsScalePrio(opts)) {
auto trueScale = scale;
auto min = optsMinScale(opts);
auto max = optsMaxScale(opts);
if (trueScale < min) {
trueScale = min;
}
if (trueScale > max) {
trueScale = max;
}
pos = nodeAxis(node, m_axis, trueScale * squish);
}
// otherwise it's been scaled down to minimum
else {
pos = nodeAxis(node, m_axis, optsMinScale(opts) * squish);
}
nextAxisLength += pos.axisLength;
// if multiple rows are allowed and this row is full, time for the
// next row
// also force at least one object to be added to this row, because if
// it's too large for this row it's gonna be too large for all rows
if (
m_growCrossAxis && (
(nextAxisLength > available.axisLength || isOptsBreakLine(prev)) &&
ix != 0
)
m_growCrossAxis && ((
(nextAxisLength > available.axisLength) &&
ix != 0 &&
!isOptsSameLine(opts)
) || isOptsBreakLine(prev))
) {
break;
}
res->addObject(node);
if (ix) {
nextAxisLength += m_gap * scale * squish;
axisLength += m_gap * scale * squish;
auto gap = nextGap(prev, opts);
// if we've exhausted all priority scale options, scale gap too
if (prio == minMaxPrios.first) {
nextAxisLength += gap * scale * squish;
axisLength += gap * scale * squish;
}
else {
nextAxisLength += gap * squish;
axisLength += gap * squish;
}
}
axisLength += pos.axisLength;
if (pos.crossLength > crossLength) {
crossLength = pos.crossLength;
}
prev = node;
prev = opts;
ix++;
}
@ -191,7 +311,13 @@ AxisLayout::Row* AxisLayout::fitInRow(CCNode* on, CCArray* nodes, float scale, f
);
}
void AxisLayout::tryFitLayout(CCNode* on, CCArray* nodes, float scale, float squish) const {
void AxisLayout::tryFitLayout(
CCNode* on, CCArray* nodes,
std::pair<float, float> const& minMaxScales,
std::pair<int, int> const& minMaxPrios,
bool doAutoScale,
float scale, float squish, int prio
) const {
// where do all of these magical calculations come from?
// idk i got tired of doing the math but they work so ¯\_(ツ)_/¯
// like i genuinely have no clue fr why some of these work tho,
@ -205,7 +331,11 @@ void AxisLayout::tryFitLayout(CCNode* on, CCArray* nodes, float scale, float squ
size_t ix = 0;
auto newNodes = nodes->shallowCopy();
while (newNodes->count()) {
auto row = this->fitInRow(on, newNodes, scale, squish);
auto row = this->fitInRow(
on, newNodes,
minMaxScales, minMaxPrios, doAutoScale,
scale, squish, prio
);
rows->addObject(row);
if (
row->nextOverflowScaleDownFactor > crossScaleDownFactor &&
@ -224,10 +354,33 @@ void AxisLayout::tryFitLayout(CCNode* on, CCArray* nodes, float scale, float squ
auto available = nodeAxis(on, m_axis, 1.f);
// if cross axis overflow not allowed, try to scale down layout
if (!m_allowCrossAxisOverflow && totalRowCrossLength > available.crossLength) {
if (m_autoScale && crossScaleDownFactor > AXIS_MIN_SCALE) {
if (
!m_allowCrossAxisOverflow &&
doAutoScale &&
totalRowCrossLength > available.crossLength
) {
bool attemptRescale = false;
if (
crossScaleDownFactor < minMaxScales.first ||
// if the scale down factor is the same as before, then we've
// entered an infinite loop
crossScaleDownFactor == scale
) {
if (prio > minMaxPrios.first) {
prio -= 1;
attemptRescale = true;
}
}
else {
attemptRescale = true;
}
if (attemptRescale) {
rows->release();
return this->tryFitLayout(on, nodes, crossScaleDownFactor, squish);
return this->tryFitLayout(
on, nodes,
minMaxScales, minMaxPrios, doAutoScale,
crossScaleDownFactor, squish, prio
);
}
}
@ -237,7 +390,11 @@ void AxisLayout::tryFitLayout(CCNode* on, CCArray* nodes, float scale, float squ
// then squish rows
if (totalRowCrossLength / available.crossLength < crossScaleDownFactor) {
rows->release();
return this->tryFitLayout(on, nodes, scale, crossScaleDownFactor);
return this->tryFitLayout(
on, nodes,
minMaxScales, minMaxPrios, doAutoScale,
scale, crossScaleDownFactor, prio
);
}
}
@ -316,8 +473,8 @@ void AxisLayout::tryFitLayout(CCNode* on, CCArray* nodes, float scale, float squ
row->axisLength /= scale * squish;
if (m_autoScale) {
rowScale = available.axisLength / row->axisLength;
if (rowScale < AXIS_MIN_SCALE) {
rowScale = AXIS_MIN_SCALE;
if (rowScale < AXISLAYOUT_DEFAULT_MIN_SCALE) {
rowScale = AXISLAYOUT_DEFAULT_MIN_SCALE;
}
row->axisLength *= rowScale;
}
@ -352,19 +509,20 @@ void AxisLayout::tryFitLayout(CCNode* on, CCArray* nodes, float scale, float squ
float evenSpace = available.axisLength / row->nodes->count();
size_t ix = 0;
AxisLayoutOptions* prev = nullptr;
for (auto& node : CCArrayExt<CCNode*>(row->nodes)) {
auto scale = rowScale;
auto opts = axisOpts(node);
// rescale node if overflowing
if (m_autoScale) {
if (auto opts = typeinfo_cast<AxisLayoutOptions*>(node->getLayoutOptions())) {
if (auto max = opts->getMaxScale()) {
if (scale > max.value()) {
scale = max.value();
}
if (this->shouldAutoScale(opts)) {
if (opts) {
if (scale > opts->getMaxScale()) {
scale = opts->getMaxScale();
}
else {
scale = node->getScale();
}
scale *= opts->getRelativeScale();
}
// CCMenuItemSpriteExtra is quirky af
if (auto btn = typeinfo_cast<CCMenuItemSpriteExtra*>(node)) {
@ -380,8 +538,11 @@ void AxisLayout::tryFitLayout(CCNode* on, CCArray* nodes, float scale, float squ
row->axisEndsLength * scale * (1.f - rowSquish) * 1.f / nodes->count();
}
else {
if (ix) {
rowAxisPos += this->nextGap(prev, opts) * scale * rowSquish;
}
axisPos = rowAxisPos + pos.axisLength * pos.axisAnchor;
rowAxisPos += pos.axisLength + m_gap * scale * rowSquish -
rowAxisPos += pos.axisLength -
row->axisEndsLength * scale * (1.f - rowSquish) * 1.f / nodes->count();
}
float crossOffset;
@ -404,6 +565,7 @@ void AxisLayout::tryFitLayout(CCNode* on, CCArray* nodes, float scale, float squ
else {
node->setPosition(rowCrossPos + crossOffset, axisPos);
}
prev = opts;
ix++;
}
@ -420,7 +582,8 @@ void AxisLayout::tryFitLayout(CCNode* on, CCArray* nodes, float scale, float squ
void AxisLayout::apply(CCNode* on) {
auto nodes = getNodesToPosition(on);
this->tryFitLayout(on, nodes, 1.f, 1.f);
auto [prios, scales, doAutoScale] = findProps(nodes);
this->tryFitLayout(on, nodes, scales, prios, doAutoScale, scales.second, 1.f, prios.second);
}
AxisLayout::AxisLayout(Axis axis) : m_axis(axis) {}
@ -510,41 +673,85 @@ AxisLayout* AxisLayout::create(Axis axis) {
return new AxisLayout(axis);
}
// RowLayout
RowLayout::RowLayout() : AxisLayout(Axis::Row) {}
RowLayout* RowLayout::create() {
return new RowLayout();
}
// ColumnLayout
ColumnLayout::ColumnLayout() : AxisLayout(Axis::Column) {}
ColumnLayout* ColumnLayout::create() {
return new ColumnLayout();
}
// AxisLayoutOptions
AxisLayoutOptions* AxisLayoutOptions::create() {
return new AxisLayoutOptions();
}
std::optional<float> AxisLayoutOptions::getMaxScale() const {
std::optional<bool> AxisLayoutOptions::getAutoScale() const {
return m_autoScale;
}
float AxisLayoutOptions::getMaxScale() const {
return m_maxScale;
}
float AxisLayoutOptions::getMinScale() const {
return m_minScale;
}
float AxisLayoutOptions::getRelativeScale() const {
return m_relativeScale;
}
std::optional<float> AxisLayoutOptions::getLength() const {
return m_length;
}
std::optional<float> AxisLayoutOptions::getPrevGap() const {
return m_prevGap;
}
std::optional<float> AxisLayoutOptions::getNextGap() const {
return m_nextGap;
}
bool AxisLayoutOptions::getBreakLine() const {
return m_breakLine;
}
bool AxisLayoutOptions::getSameLine() const {
return m_sameLine;
}
int AxisLayoutOptions::getScalePriority() const {
return m_scalePriority;
}
AxisLayoutOptions* AxisLayoutOptions::setMaxScale(float scale) {
m_maxScale = scale;
return this;
}
AxisLayoutOptions* AxisLayoutOptions::disableAutoScale() {
m_maxScale = std::nullopt;
AxisLayoutOptions* AxisLayoutOptions::setMinScale(float scale) {
m_minScale = scale;
return this;
}
AxisLayoutOptions* AxisLayoutOptions::setRelativeScale(float scale) {
m_relativeScale = scale;
return this;
}
AxisLayoutOptions* AxisLayoutOptions::setAutoScale(std::optional<bool> enabled) {
m_autoScale = enabled;
return this;
}
@ -553,7 +760,27 @@ AxisLayoutOptions* AxisLayoutOptions::setLength(std::optional<float> length) {
return this;
}
AxisLayoutOptions* AxisLayoutOptions::setPrevGap(std::optional<float> gap) {
m_prevGap = gap;
return this;
}
AxisLayoutOptions* AxisLayoutOptions::setNextGap(std::optional<float> gap) {
m_nextGap = gap;
return this;
}
AxisLayoutOptions* AxisLayoutOptions::setBreakLine(bool enable) {
m_breakLine = enable;
return this;
}
AxisLayoutOptions* AxisLayoutOptions::setSameLine(bool enable) {
m_sameLine = enable;
return this;
}
AxisLayoutOptions* AxisLayoutOptions::setScalePriority(int priority) {
m_scalePriority = priority;
return this;
}

View file

@ -21,7 +21,6 @@ private:
std::string m_id = "";
std::unique_ptr<Layout> m_layout = nullptr;
std::unique_ptr<LayoutOptions> m_layoutOptions = nullptr;
PositionHint m_positionHint = PositionHint::Default;
std::unordered_map<std::string, std::any> m_attributes;
friend class ProxyCCNode;
@ -156,14 +155,6 @@ void CCNode::updateLayout(bool updateChildOrder) {
}
}
void CCNode::setPositionHint(PositionHint hint) {
GeodeNodeMetadata::set(this)->m_positionHint = hint;
}
PositionHint CCNode::getPositionHint() {
return GeodeNodeMetadata::set(this)->m_positionHint;
}
void CCNode::setAttribute(std::string const& attr, std::any value) {
GeodeNodeMetadata::set(this)->m_attributes[attr] = value;
}

View file

@ -103,7 +103,7 @@ $register_ids(EditorPauseLayer) {
auto optionsMenu = detachAndCreateMenu(
this,
"options-menu",
ColumnLayout::create()
RowLayout::create()
->setGap(-1.f)
->setAxisAlignment(AxisAlignment::Start)
->setGrowCrossAxis(true)
@ -129,6 +129,8 @@ $register_ids(EditorPauseLayer) {
label->setLayoutOptions(
AxisLayoutOptions::create()
->setBreakLine(true)
->setSameLine(true)
->setRelativeScale(.5f)
);
}
}

View file

@ -308,7 +308,7 @@ $register_ids(EditorUI) {
this->getChildByID("layer-index-label")->setLayoutOptions(
AxisLayoutOptions::create()
->disableAutoScale()
->setAutoScale(false)
->setLength(25.f)
);