From 9b03af603430383a6a0f0da0d7c607ab0b2d9a15 Mon Sep 17 00:00:00 2001 From: Alphalaneous <38200084+Alphalaneous@users.noreply.github.com> Date: Fri, 9 May 2025 11:50:51 -0400 Subject: [PATCH 1/3] Fix a crash when removing layouts and layout opts --- src/pages/Attributes.cpp | 1307 +++++++++++++++++++------------------- 1 file changed, 657 insertions(+), 650 deletions(-) diff --git a/src/pages/Attributes.cpp b/src/pages/Attributes.cpp index 9e87287..c5b5b92 100644 --- a/src/pages/Attributes.cpp +++ b/src/pages/Attributes.cpp @@ -311,774 +311,781 @@ void DevTools::drawNodeAttributes(CCNode* node) { ImGui::Separator(); ImGui::NewLine(); } + auto layoutOptsFn = [node] { + if (auto rawOpts = node->getLayoutOptions()) { + ImGui::Text("Layout options: %s", typeid(*rawOpts).name()); - if (auto rawOpts = node->getLayoutOptions()) { - ImGui::Text("Layout options: %s", typeid(*rawOpts).name()); - - if (ImGui::Button(U8STR(FEATHER_REFRESH_CW " Update Parent Layout"))) { - if (auto parent = node->getParent()) { - parent->updateLayout(); + if (ImGui::Button(U8STR(FEATHER_REFRESH_CW " Update Parent Layout"))) { + if (auto parent = node->getParent()) { + parent->updateLayout(); + } } - } - ImGui::SameLine(); - if (ImGui::Button(U8STR(FEATHER_TRASH_2 " Remove Layout Options"))) { - node->setLayoutOptions(nullptr); - } - if (auto opts = typeinfo_cast(rawOpts)) { - bool updateLayout = false; - auto minRelativeScaleOpt = opts->getMinRelativeScale(); - float minRelativeScale = minRelativeScaleOpt.value_or(0); - bool hasMinRelativeScale = minRelativeScaleOpt.has_value(); - - if (ImGui::Checkbox("Has Min Relative Scale##simplescale0", &hasMinRelativeScale)) { - if (hasMinRelativeScale) { - opts->setMinRelativeScale(0); + ImGui::SameLine(); + if (ImGui::Button(U8STR(FEATHER_TRASH_2 " Remove Layout Options"))) { + node->setLayoutOptions(nullptr); + return; + } + if (auto opts = typeinfo_cast(rawOpts)) { + bool updateLayout = false; + auto minRelativeScaleOpt = opts->getMinRelativeScale(); + float minRelativeScale = minRelativeScaleOpt.value_or(0); + bool hasMinRelativeScale = minRelativeScaleOpt.has_value(); + + if (ImGui::Checkbox("Has Min Relative Scale##simplescale0", &hasMinRelativeScale)) { + if (hasMinRelativeScale) { + opts->setMinRelativeScale(0); + } + else { + opts->setMinRelativeScale(std::nullopt); + } + updateLayout = true; } - else { - opts->setMinRelativeScale(std::nullopt); + if (hasMinRelativeScale) { + if (ImGui::DragFloat("Min Relative Scale##simplescale1", &minRelativeScale)) { + + opts->setMinRelativeScale(minRelativeScale); + updateLayout = true; + } } - updateLayout = true; - } - if (hasMinRelativeScale) { - if (ImGui::DragFloat("Min Relative Scale##simplescale1", &minRelativeScale)) { - - opts->setMinRelativeScale(minRelativeScale); + + auto maxRelativeScaleOpt = opts->getMaxRelativeScale(); + float maxRelativeScale = maxRelativeScaleOpt.value_or(0); + bool hasMaxRelativeScale = maxRelativeScaleOpt.has_value(); + if (ImGui::Checkbox("Has Max Relative Scale##simplescale2", &hasMaxRelativeScale)) { + if (hasMaxRelativeScale) { + opts->setMaxRelativeScale(0); + } + else { + opts->setMaxRelativeScale(std::nullopt); + } updateLayout = true; } - } - auto maxRelativeScaleOpt = opts->getMaxRelativeScale(); - float maxRelativeScale = maxRelativeScaleOpt.value_or(0); - bool hasMaxRelativeScale = maxRelativeScaleOpt.has_value(); - if (ImGui::Checkbox("Has Max Relative Scale##simplescale2", &hasMaxRelativeScale)) { if (hasMaxRelativeScale) { - opts->setMaxRelativeScale(0); - } - else { - opts->setMaxRelativeScale(std::nullopt); + if (ImGui::DragFloat("Max Relative Scale##simplescale3", &maxRelativeScale)) { + opts->setMaxRelativeScale(maxRelativeScale); + updateLayout = true; + } } - updateLayout = true; - } - if (hasMaxRelativeScale) { - if (ImGui::DragFloat("Max Relative Scale##simplescale3", &maxRelativeScale)) { - opts->setMaxRelativeScale(maxRelativeScale); + int scalingPriority = static_cast(opts->getScalingPriority()); + + ImGui::Text("Scaling Priority"); + bool updateScalePrio = false; + updateScalePrio |= ImGui::RadioButton( + "First##scalepriooption1", &scalingPriority, static_cast(ScalingPriority::First) + ); + ImGui::SameLine(); + updateScalePrio |= ImGui::RadioButton( + "Early##scalepriooption2", &scalingPriority, static_cast(ScalingPriority::Early) + ); + ImGui::SameLine(); + updateScalePrio |= ImGui::RadioButton( + "Normal##scalepriooption3", &scalingPriority, static_cast(ScalingPriority::Normal) + ); + ImGui::SameLine(); + updateScalePrio |= ImGui::RadioButton( + "Late##scalepriooption4", &scalingPriority, static_cast(ScalingPriority::Late) + ); + ImGui::SameLine(); + updateScalePrio |= ImGui::RadioButton( + "Last##scalepriooption4", &scalingPriority, static_cast(ScalingPriority::Last) + ); + ImGui::SameLine(); + updateScalePrio |= ImGui::RadioButton( + "Never##alignmentoption0", &scalingPriority, static_cast(ScalingPriority::Never) + ); + if (updateScalePrio) { + opts->setScalingPriority(static_cast(scalingPriority)); updateLayout = true; } - } - - int scalingPriority = static_cast(opts->getScalingPriority()); - ImGui::Text("Scaling Priority"); - bool updateScalePrio = false; - updateScalePrio |= ImGui::RadioButton( - "First##scalepriooption1", &scalingPriority, static_cast(ScalingPriority::First) - ); - ImGui::SameLine(); - updateScalePrio |= ImGui::RadioButton( - "Early##scalepriooption2", &scalingPriority, static_cast(ScalingPriority::Early) - ); - ImGui::SameLine(); - updateScalePrio |= ImGui::RadioButton( - "Normal##scalepriooption3", &scalingPriority, static_cast(ScalingPriority::Normal) - ); - ImGui::SameLine(); - updateScalePrio |= ImGui::RadioButton( - "Late##scalepriooption4", &scalingPriority, static_cast(ScalingPriority::Late) - ); - ImGui::SameLine(); - updateScalePrio |= ImGui::RadioButton( - "Last##scalepriooption4", &scalingPriority, static_cast(ScalingPriority::Last) - ); - ImGui::SameLine(); - updateScalePrio |= ImGui::RadioButton( - "Never##alignmentoption0", &scalingPriority, static_cast(ScalingPriority::Never) - ); - if (updateScalePrio) { - opts->setScalingPriority(static_cast(scalingPriority)); - updateLayout = true; - } - - if (updateLayout && node->getParent()) { - node->getParent()->updateLayout(); + if (updateLayout && node->getParent()) { + node->getParent()->updateLayout(); + } } - } - if (auto opts = typeinfo_cast(rawOpts)) { - bool updateLayout = false; + if (auto opts = typeinfo_cast(rawOpts)) { + bool updateLayout = false; - ImGui::Text("Auto Scale"); - auto updateAxis = false; - int autoScale = opts->getAutoScale().has_value() ? opts->getAutoScale().value() : -1; - updateAxis |= ImGui::RadioButton("Default##autoscale0", &autoScale, -1); - ImGui::SameLine(); - updateAxis |= ImGui::RadioButton("Enable##autoscale1", &autoScale, 1); - ImGui::SameLine(); - updateAxis |= ImGui::RadioButton("Disable##autoscale2", &autoScale, 0); - if (updateAxis) { - switch (autoScale) { - case -1: opts->setAutoScale(std::nullopt); break; - case 0: opts->setAutoScale(false); break; - case 1: opts->setAutoScale(true); break; + ImGui::Text("Auto Scale"); + auto updateAxis = false; + int autoScale = opts->getAutoScale().has_value() ? opts->getAutoScale().value() : -1; + updateAxis |= ImGui::RadioButton("Default##autoscale0", &autoScale, -1); + ImGui::SameLine(); + updateAxis |= ImGui::RadioButton("Enable##autoscale1", &autoScale, 1); + ImGui::SameLine(); + updateAxis |= ImGui::RadioButton("Disable##autoscale2", &autoScale, 0); + if (updateAxis) { + switch (autoScale) { + case -1: opts->setAutoScale(std::nullopt); break; + case 0: opts->setAutoScale(false); break; + case 1: opts->setAutoScale(true); break; + } + updateLayout = true; } - updateLayout = true; - } - auto minScale = opts->getMinScale(); - bool hasMinScale = opts->hasExplicitMinScale(); - auto maxScale = opts->getMaxScale(); - bool hasMaxScale = opts->hasExplicitMaxScale(); + auto minScale = opts->getMinScale(); + bool hasMinScale = opts->hasExplicitMinScale(); + auto maxScale = opts->getMaxScale(); + bool hasMaxScale = opts->hasExplicitMaxScale(); - if (ImGui::Checkbox("Has Min Scale", &hasMinScale)) { - if (hasMinScale) { - opts->setScaleLimits(minScale, hasMaxScale ? std::optional(maxScale) : std::nullopt); + if (ImGui::Checkbox("Has Min Scale", &hasMinScale)) { + if (hasMinScale) { + opts->setScaleLimits(minScale, hasMaxScale ? std::optional(maxScale) : std::nullopt); + } + else { + opts->setScaleLimits(std::nullopt, hasMaxScale ? std::optional(maxScale) : std::nullopt); + } + updateLayout = true; } - else { - opts->setScaleLimits(std::nullopt, hasMaxScale ? std::optional(maxScale) : std::nullopt); + if (hasMinScale) { + if (ImGui::DragFloat("Min Scale", &minScale)) { + opts->setScaleLimits(minScale, maxScale); + updateLayout = true; + } } - updateLayout = true; - } - if (hasMinScale) { - if (ImGui::DragFloat("Min Scale", &minScale)) { - opts->setScaleLimits(minScale, maxScale); + + if (ImGui::Checkbox("Has Max Scale", &hasMaxScale)) { + if (hasMaxScale) { + opts->setScaleLimits(hasMinScale ? std::optional(minScale) : std::nullopt, maxScale); + } + else { + opts->setScaleLimits(hasMinScale ? std::optional(minScale) : std::nullopt, std::nullopt); + } updateLayout = true; } - } - if (ImGui::Checkbox("Has Max Scale", &hasMaxScale)) { if (hasMaxScale) { - opts->setScaleLimits(hasMinScale ? std::optional(minScale) : std::nullopt, maxScale); - } - else { - opts->setScaleLimits(hasMinScale ? std::optional(minScale) : std::nullopt, std::nullopt); + if (ImGui::DragFloat("Max Scale", &maxScale)) { + opts->setScaleLimits(minScale, maxScale); + updateLayout = true; + } } - updateLayout = true; - } - if (hasMaxScale) { - if (ImGui::DragFloat("Max Scale", &maxScale)) { - opts->setScaleLimits(minScale, maxScale); + auto lengthOpt = opts->getLength(); + float length = lengthOpt.value_or(0); + bool hasLength = lengthOpt.has_value(); + + if (ImGui::Checkbox("Has Length", &hasLength)) { + if (hasLength) { + opts->setLength(0); + } + else { + opts->setLength(std::nullopt); + } updateLayout = true; } - } - - auto lengthOpt = opts->getLength(); - float length = lengthOpt.value_or(0); - bool hasLength = lengthOpt.has_value(); - - if (ImGui::Checkbox("Has Length", &hasLength)) { if (hasLength) { - opts->setLength(0); - } - else { - opts->setLength(std::nullopt); - } - updateLayout = true; - } - if (hasLength) { - if (ImGui::DragFloat("Length", &length)) { - opts->setLength(length); - updateLayout = true; + if (ImGui::DragFloat("Length", &length)) { + opts->setLength(length); + updateLayout = true; + } } - } - auto prevGapOpt = opts->getPrevGap(); - float prevGap = prevGapOpt.value_or(0); - bool hasPrevGap = prevGapOpt.has_value(); + auto prevGapOpt = opts->getPrevGap(); + float prevGap = prevGapOpt.value_or(0); + bool hasPrevGap = prevGapOpt.has_value(); - if (ImGui::Checkbox("Has Prev Gap", &hasPrevGap)) { - if (hasPrevGap) { - opts->setPrevGap(0); - } - else { - opts->setPrevGap(std::nullopt); - } - updateLayout = true; - } - if (hasPrevGap) { - if (ImGui::DragFloat("Prev Gap", &prevGap)) { - opts->setPrevGap(prevGap); + if (ImGui::Checkbox("Has Prev Gap", &hasPrevGap)) { + if (hasPrevGap) { + opts->setPrevGap(0); + } + else { + opts->setPrevGap(std::nullopt); + } updateLayout = true; } - } + if (hasPrevGap) { + if (ImGui::DragFloat("Prev Gap", &prevGap)) { + opts->setPrevGap(prevGap); + updateLayout = true; + } + } - auto nextGapOpt = opts->getNextGap(); - float nextGap = nextGapOpt.value_or(0); - bool hasNextGap = nextGapOpt.has_value(); + auto nextGapOpt = opts->getNextGap(); + float nextGap = nextGapOpt.value_or(0); + bool hasNextGap = nextGapOpt.has_value(); - if (ImGui::Checkbox("Has Next Gap", &hasNextGap)) { + if (ImGui::Checkbox("Has Next Gap", &hasNextGap)) { + if (hasNextGap) { + opts->setNextGap(0); + } + else { + opts->setNextGap(std::nullopt); + } + updateLayout = true; + } if (hasNextGap) { - opts->setNextGap(0); + if (ImGui::DragFloat("Next Gap", &nextGap)) { + opts->setNextGap(nextGap); + updateLayout = true; + } } - else { - opts->setNextGap(std::nullopt); + + if (checkbox("Break Line", opts, AXIS_GET(BreakLine))) { + updateLayout = true; } - updateLayout = true; - } - if (hasNextGap) { - if (ImGui::DragFloat("Next Gap", &nextGap)) { - opts->setNextGap(nextGap); + if (checkbox("Same Line", opts, AXIS_GET(SameLine))) { updateLayout = true; } - } - - if (checkbox("Break Line", opts, AXIS_GET(BreakLine))) { - updateLayout = true; - } - if (checkbox("Same Line", opts, AXIS_GET(SameLine))) { - updateLayout = true; - } - auto relativeScale = opts->getRelativeScale(); - if (ImGui::DragFloat("Relative Scale", &relativeScale)) { - opts->setRelativeScale(relativeScale); - updateLayout = true; - } + auto relativeScale = opts->getRelativeScale(); + if (ImGui::DragFloat("Relative Scale", &relativeScale)) { + opts->setRelativeScale(relativeScale); + updateLayout = true; + } - auto prio = opts->getScalePriority(); - if (ImGui::DragInt("Scale Priority", &prio, .03f)) { - opts->setScalePriority(prio); - updateLayout = true; - } + auto prio = opts->getScalePriority(); + if (ImGui::DragInt("Scale Priority", &prio, .03f)) { + opts->setScalePriority(prio); + updateLayout = true; + } - auto crossAxisAlignmentOpt = opts->getCrossAxisAlignment(); - int crossAxisAlignment = static_cast(crossAxisAlignmentOpt.value_or(AxisAlignment::Start)); - bool hasCrossAxisAlignment = crossAxisAlignmentOpt.has_value(); + auto crossAxisAlignmentOpt = opts->getCrossAxisAlignment(); + int crossAxisAlignment = static_cast(crossAxisAlignmentOpt.value_or(AxisAlignment::Start)); + bool hasCrossAxisAlignment = crossAxisAlignmentOpt.has_value(); - if (ImGui::Checkbox("Has Cross Axis Alignment", &hasCrossAxisAlignment)) { + if (ImGui::Checkbox("Has Cross Axis Alignment", &hasCrossAxisAlignment)) { + if (hasCrossAxisAlignment) { + opts->setCrossAxisAlignment(AxisAlignment::Start); + } + else { + opts->setCrossAxisAlignment(std::nullopt); + } + updateLayout = true; + } if (hasCrossAxisAlignment) { - opts->setCrossAxisAlignment(AxisAlignment::Start); + + ImGui::Text("Cross Axis Alignment"); + bool updateAlignment = false; + updateAlignment |= ImGui::RadioButton( + "Start##alignmentoption0", &crossAxisAlignment, static_cast(AxisAlignment::Start) + ); + ImGui::SameLine(); + updateAlignment |= ImGui::RadioButton( + "Center##alignmentoption1", &crossAxisAlignment, static_cast(AxisAlignment::Center) + ); + ImGui::SameLine(); + updateAlignment |= ImGui::RadioButton( + "End##alignmentoption2", &crossAxisAlignment, static_cast(AxisAlignment::End) + ); + ImGui::SameLine(); + updateAlignment |= ImGui::RadioButton( + "Even##alignmentoption3", &crossAxisAlignment, static_cast(AxisAlignment::Even) + ); + ImGui::SameLine(); + updateAlignment |= ImGui::RadioButton( + "Between##alignmentoption4", &crossAxisAlignment, static_cast(AxisAlignment::Between) + ); + if (updateAlignment) { + opts->setCrossAxisAlignment(static_cast(crossAxisAlignment)); + updateLayout = true; + } } - else { - opts->setCrossAxisAlignment(std::nullopt); + + if (updateLayout && node->getParent()) { + node->getParent()->updateLayout(); } - updateLayout = true; } - if (hasCrossAxisAlignment) { - - ImGui::Text("Cross Axis Alignment"); - bool updateAlignment = false; - updateAlignment |= ImGui::RadioButton( - "Start##alignmentoption0", &crossAxisAlignment, static_cast(AxisAlignment::Start) - ); - ImGui::SameLine(); - updateAlignment |= ImGui::RadioButton( - "Center##alignmentoption1", &crossAxisAlignment, static_cast(AxisAlignment::Center) - ); - ImGui::SameLine(); - updateAlignment |= ImGui::RadioButton( - "End##alignmentoption2", &crossAxisAlignment, static_cast(AxisAlignment::End) - ); - ImGui::SameLine(); - updateAlignment |= ImGui::RadioButton( - "Even##alignmentoption3", &crossAxisAlignment, static_cast(AxisAlignment::Even) - ); - ImGui::SameLine(); - updateAlignment |= ImGui::RadioButton( - "Between##alignmentoption4", &crossAxisAlignment, static_cast(AxisAlignment::Between) - ); - if (updateAlignment) { - opts->setCrossAxisAlignment(static_cast(crossAxisAlignment)); + else if (auto opts = typeinfo_cast(rawOpts)) { + bool updateLayout = false; + + auto offset = opts->getOffset(); + ImGui::DragFloat2("Offset", &offset.x); + if (opts->getOffset() != offset) { + opts->setOffset(offset); updateLayout = true; } - } - if (updateLayout && node->getParent()) { - node->getParent()->updateLayout(); + auto anchor = static_cast(opts->getAnchor()); + auto updateAnchor = false; + ImGui::BeginTable("anchor-table", 3); + ImGui::TableNextColumn(); + updateAnchor |= ImGui::RadioButton("Top Left", &anchor, static_cast(Anchor::TopLeft)); + updateAnchor |= ImGui::RadioButton("Left", &anchor, static_cast(Anchor::Left)); + updateAnchor |= ImGui::RadioButton("Bottom Left", &anchor, static_cast(Anchor::BottomLeft)); + ImGui::TableNextColumn(); + updateAnchor |= ImGui::RadioButton("Top", &anchor, static_cast(Anchor::Top)); + updateAnchor |= ImGui::RadioButton("Center", &anchor, static_cast(Anchor::Center)); + updateAnchor |= ImGui::RadioButton("Bottom", &anchor, static_cast(Anchor::Bottom)); + ImGui::TableNextColumn(); + updateAnchor |= ImGui::RadioButton("Top Right", &anchor, static_cast(Anchor::TopRight)); + updateAnchor |= ImGui::RadioButton("Right", &anchor, static_cast(Anchor::Right)); + updateAnchor |= ImGui::RadioButton("Bottom Right", &anchor, static_cast(Anchor::BottomRight)); + ImGui::EndTable(); + + if (updateAnchor) { + if (opts->getAnchor() != static_cast(anchor)) { + opts->setAnchor(static_cast(anchor)); + updateLayout = true; + } + } + + if (updateLayout && node->getParent()) { + node->getParent()->updateLayout(); + } } } - else if (auto opts = typeinfo_cast(rawOpts)) { - bool updateLayout = false; - - auto offset = opts->getOffset(); - ImGui::DragFloat2("Offset", &offset.x); - if (opts->getOffset() != offset) { - opts->setOffset(offset); - updateLayout = true; + else { + if (ImGui::Button(U8STR(FEATHER_PLUS " Add SimpleAxisLayoutOptions"))) { + node->setLayoutOptions(SimpleAxisLayoutOptions::create()); } - - auto anchor = static_cast(opts->getAnchor()); - auto updateAnchor = false; - ImGui::BeginTable("anchor-table", 3); - ImGui::TableNextColumn(); - updateAnchor |= ImGui::RadioButton("Top Left", &anchor, static_cast(Anchor::TopLeft)); - updateAnchor |= ImGui::RadioButton("Left", &anchor, static_cast(Anchor::Left)); - updateAnchor |= ImGui::RadioButton("Bottom Left", &anchor, static_cast(Anchor::BottomLeft)); - ImGui::TableNextColumn(); - updateAnchor |= ImGui::RadioButton("Top", &anchor, static_cast(Anchor::Top)); - updateAnchor |= ImGui::RadioButton("Center", &anchor, static_cast(Anchor::Center)); - updateAnchor |= ImGui::RadioButton("Bottom", &anchor, static_cast(Anchor::Bottom)); - ImGui::TableNextColumn(); - updateAnchor |= ImGui::RadioButton("Top Right", &anchor, static_cast(Anchor::TopRight)); - updateAnchor |= ImGui::RadioButton("Right", &anchor, static_cast(Anchor::Right)); - updateAnchor |= ImGui::RadioButton("Bottom Right", &anchor, static_cast(Anchor::BottomRight)); - ImGui::EndTable(); - - if (updateAnchor) { - if (opts->getAnchor() != static_cast(anchor)) { - opts->setAnchor(static_cast(anchor)); - updateLayout = true; - } + if (ImGui::Button(U8STR(FEATHER_PLUS " Add AxisLayoutOptions"))) { + node->setLayoutOptions(AxisLayoutOptions::create()); } - - if (updateLayout && node->getParent()) { - node->getParent()->updateLayout(); + if (ImGui::Button(U8STR(FEATHER_PLUS " Add AnchorLayoutOptions"))) { + node->setLayoutOptions(AnchorLayoutOptions::create()); } } - } - else { - if (ImGui::Button(U8STR(FEATHER_PLUS " Add SimpleAxisLayoutOptions"))) { - node->setLayoutOptions(SimpleAxisLayoutOptions::create()); - } - if (ImGui::Button(U8STR(FEATHER_PLUS " Add AxisLayoutOptions"))) { - node->setLayoutOptions(AxisLayoutOptions::create()); - } - if (ImGui::Button(U8STR(FEATHER_PLUS " Add AnchorLayoutOptions"))) { - node->setLayoutOptions(AnchorLayoutOptions::create()); - } - } + }; + layoutOptsFn(); ImGui::NewLine(); ImGui::Separator(); ImGui::NewLine(); - if (auto rawLayout = node->getLayout()) { - ImGui::Text("Layout: %s", typeid(*rawLayout).name()); - - if (ImGui::Button(U8STR(FEATHER_REFRESH_CW " Update Layout"))) { - node->updateLayout(); - } - ImGui::SameLine(); - if (ImGui::Button(U8STR(FEATHER_TRASH_2 " Remove Layout"))) { - node->setLayout(nullptr); - } - ImGui::SameLine(); - if (ImGui::Button(U8STR(FEATHER_PLUS " Add Test Child"))) { - auto spr = CCSprite::create("GJ_button_01.png"); - auto btn = CCMenuItemSpriteExtra::create(spr, node, nullptr); - node->addChild(btn); - node->updateLayout(); - } - if (auto layout = typeinfo_cast(rawLayout)) { - ImGui::SameLine(); - if (ImGui::Button(U8STR(FEATHER_PLUS " Add AxisGap"))) { - node->addChild(AxisGap::create(5)); + auto layoutFn = [node] { + if (auto rawLayout = node->getLayout()) { + ImGui::Text("Layout: %s", typeid(*rawLayout).name()); + + if (ImGui::Button(U8STR(FEATHER_REFRESH_CW " Update Layout"))) { node->updateLayout(); } - bool updateLayout = false; - auto axis = static_cast(layout->getAxis()); - ImGui::Text("Axis"); - auto updateAxis = false; - updateAxis |= ImGui::RadioButton("Row", &axis, static_cast(Axis::Row)); ImGui::SameLine(); - updateAxis |= ImGui::RadioButton("Column", &axis, static_cast(Axis::Column)); - if (updateAxis) { - if (layout->getAxis() != static_cast(axis)) { - node->setContentSize({ - node->getContentSize().height, - node->getContentSize().width - }); - } - layout->setAxis(static_cast(axis)); - updateLayout = true; + if (ImGui::Button(U8STR(FEATHER_TRASH_2 " Remove Layout"))) { + node->setLayout(nullptr); + return; } - { - auto axisScaling = static_cast(layout->getMainAxisScaling()); - ImGui::Text("Main Axis Scaling"); - bool updateScaling = false; - updateScaling |= ImGui::RadioButton( - "None##mainscale0", &axisScaling, static_cast(AxisScaling::None) - ); - ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Scale Down##mainscale1", &axisScaling, static_cast(AxisScaling::ScaleDown) - ); - ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Scale##mainscale2", &axisScaling, static_cast(AxisScaling::Scale) - ); - ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Grow##mainscale3", &axisScaling, static_cast(AxisScaling::Grow) - ); - ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Fit##mainscale4", &axisScaling, static_cast(AxisScaling::Fit) - ); - ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Scale Down Gaps##mainscale5", &axisScaling, static_cast(AxisScaling::ScaleDownGaps) - ); - if (updateScaling) { - layout->setMainAxisScaling(static_cast(axisScaling)); - updateLayout = true; - } + ImGui::SameLine(); + if (ImGui::Button(U8STR(FEATHER_PLUS " Add Test Child"))) { + auto spr = CCSprite::create("GJ_button_01.png"); + auto btn = CCMenuItemSpriteExtra::create(spr, node, nullptr); + node->addChild(btn); + node->updateLayout(); } - { - auto axisScaling = static_cast(layout->getCrossAxisScaling()); - ImGui::Text("Cross Axis Scaling"); - bool updateScaling = false; - updateScaling |= ImGui::RadioButton( - "None##crossscale0", &axisScaling, static_cast(AxisScaling::None) - ); - ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Scale Down##crossscale1", &axisScaling, static_cast(AxisScaling::ScaleDown) - ); + if (auto layout = typeinfo_cast(rawLayout)) { ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Scale##crossscale2", &axisScaling, static_cast(AxisScaling::Scale) - ); - ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Grow##crossscale3", &axisScaling, static_cast(AxisScaling::Grow) - ); - ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Fit##crossscale4", &axisScaling, static_cast(AxisScaling::Fit) - ); - ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Scale Down Gaps##crossscale5", &axisScaling, static_cast(AxisScaling::ScaleDownGaps) - ); - if (updateScaling) { - layout->setCrossAxisScaling(static_cast(axisScaling)); - updateLayout = true; + if (ImGui::Button(U8STR(FEATHER_PLUS " Add AxisGap"))) { + node->addChild(AxisGap::create(5)); + node->updateLayout(); } - } - { - auto align = static_cast(layout->getMainAxisAlignment()); - ImGui::Text("Main Axis Alignment"); - bool updateAlign = false; - updateAlign |= ImGui::RadioButton( - "Start##mainalign0", &align, static_cast(MainAxisAlignment::Start) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Center##mainalign1", &align, static_cast(MainAxisAlignment::Center) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "End##mainalign2", &align, static_cast(MainAxisAlignment::End) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Even##mainalign3", &align, static_cast(MainAxisAlignment::Even) - ); + bool updateLayout = false; + auto axis = static_cast(layout->getAxis()); + ImGui::Text("Axis"); + auto updateAxis = false; + updateAxis |= ImGui::RadioButton("Row", &axis, static_cast(Axis::Row)); ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Between##mainalign4", &align, static_cast(MainAxisAlignment::Between) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Around##mainalign5", &align, static_cast(MainAxisAlignment::Around) - ); - if (updateAlign) { - layout->setMainAxisAlignment(static_cast(align)); + updateAxis |= ImGui::RadioButton("Column", &axis, static_cast(Axis::Column)); + if (updateAxis) { + if (layout->getAxis() != static_cast(axis)) { + node->setContentSize({ + node->getContentSize().height, + node->getContentSize().width + }); + } + layout->setAxis(static_cast(axis)); updateLayout = true; } - } - { - auto align = static_cast(layout->getCrossAxisAlignment()); - ImGui::Text("Cross Axis Alignment"); - bool updateAlign = false; - updateAlign |= ImGui::RadioButton( - "Start##crossalign0", &align, static_cast(CrossAxisAlignment::Start) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Center##crossalign1", &align, static_cast(CrossAxisAlignment::Center) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "End##crossalign2", &align, static_cast(CrossAxisAlignment::End) - ); - if (updateAlign) { - layout->setCrossAxisAlignment(static_cast(align)); - updateLayout = true; + { + auto axisScaling = static_cast(layout->getMainAxisScaling()); + ImGui::Text("Main Axis Scaling"); + bool updateScaling = false; + updateScaling |= ImGui::RadioButton( + "None##mainscale0", &axisScaling, static_cast(AxisScaling::None) + ); + ImGui::SameLine(); + updateScaling |= ImGui::RadioButton( + "Scale Down##mainscale1", &axisScaling, static_cast(AxisScaling::ScaleDown) + ); + ImGui::SameLine(); + updateScaling |= ImGui::RadioButton( + "Scale##mainscale2", &axisScaling, static_cast(AxisScaling::Scale) + ); + ImGui::SameLine(); + updateScaling |= ImGui::RadioButton( + "Grow##mainscale3", &axisScaling, static_cast(AxisScaling::Grow) + ); + ImGui::SameLine(); + updateScaling |= ImGui::RadioButton( + "Fit##mainscale4", &axisScaling, static_cast(AxisScaling::Fit) + ); + ImGui::SameLine(); + updateScaling |= ImGui::RadioButton( + "Scale Down Gaps##mainscale5", &axisScaling, static_cast(AxisScaling::ScaleDownGaps) + ); + if (updateScaling) { + layout->setMainAxisScaling(static_cast(axisScaling)); + updateLayout = true; + } + } + { + auto axisScaling = static_cast(layout->getCrossAxisScaling()); + ImGui::Text("Cross Axis Scaling"); + bool updateScaling = false; + updateScaling |= ImGui::RadioButton( + "None##crossscale0", &axisScaling, static_cast(AxisScaling::None) + ); + ImGui::SameLine(); + updateScaling |= ImGui::RadioButton( + "Scale Down##crossscale1", &axisScaling, static_cast(AxisScaling::ScaleDown) + ); + ImGui::SameLine(); + updateScaling |= ImGui::RadioButton( + "Scale##crossscale2", &axisScaling, static_cast(AxisScaling::Scale) + ); + ImGui::SameLine(); + updateScaling |= ImGui::RadioButton( + "Grow##crossscale3", &axisScaling, static_cast(AxisScaling::Grow) + ); + ImGui::SameLine(); + updateScaling |= ImGui::RadioButton( + "Fit##crossscale4", &axisScaling, static_cast(AxisScaling::Fit) + ); + ImGui::SameLine(); + updateScaling |= ImGui::RadioButton( + "Scale Down Gaps##crossscale5", &axisScaling, static_cast(AxisScaling::ScaleDownGaps) + ); + if (updateScaling) { + layout->setCrossAxisScaling(static_cast(axisScaling)); + updateLayout = true; + } + } + { + auto align = static_cast(layout->getMainAxisAlignment()); + ImGui::Text("Main Axis Alignment"); + bool updateAlign = false; + updateAlign |= ImGui::RadioButton( + "Start##mainalign0", &align, static_cast(MainAxisAlignment::Start) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Center##mainalign1", &align, static_cast(MainAxisAlignment::Center) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "End##mainalign2", &align, static_cast(MainAxisAlignment::End) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Even##mainalign3", &align, static_cast(MainAxisAlignment::Even) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Between##mainalign4", &align, static_cast(MainAxisAlignment::Between) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Around##mainalign5", &align, static_cast(MainAxisAlignment::Around) + ); + if (updateAlign) { + layout->setMainAxisAlignment(static_cast(align)); + updateLayout = true; + } + } + { + auto align = static_cast(layout->getCrossAxisAlignment()); + ImGui::Text("Cross Axis Alignment"); + bool updateAlign = false; + updateAlign |= ImGui::RadioButton( + "Start##crossalign0", &align, static_cast(CrossAxisAlignment::Start) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Center##crossalign1", &align, static_cast(CrossAxisAlignment::Center) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "End##crossalign2", &align, static_cast(CrossAxisAlignment::End) + ); + if (updateAlign) { + layout->setCrossAxisAlignment(static_cast(align)); + updateLayout = true; + } } - } - std::string axisDirection = axis ? "Bottom to Top" : "Left to Right"; - std::string secondAxisDirection = axis ? "Top to Bottom" : "Right to Left"; + std::string axisDirection = axis ? "Bottom to Top" : "Left to Right"; + std::string secondAxisDirection = axis ? "Top to Bottom" : "Right to Left"; - std::string crossAxisDirection = !axis ? "Bottom to Top" : "Left to Right"; - std::string secondcrossAxisDirection = !axis ? "Top to Bottom" : "Right to Left"; - { - auto direction = static_cast(layout->getMainAxisDirection()); - ImGui::Text("Main Axis Direction"); - bool updateDirection = false; - - updateDirection |= ImGui::RadioButton( - axisDirection.c_str(), &direction, static_cast(AxisDirection::FrontToBack) - ); - ImGui::SameLine(); - updateDirection |= ImGui::RadioButton( - secondAxisDirection.c_str(), &direction, static_cast(AxisDirection::BackToFront) - ); - if (updateDirection) { - layout->setMainAxisDirection(static_cast(direction)); + std::string crossAxisDirection = !axis ? "Bottom to Top" : "Left to Right"; + std::string secondcrossAxisDirection = !axis ? "Top to Bottom" : "Right to Left"; + { + auto direction = static_cast(layout->getMainAxisDirection()); + ImGui::Text("Main Axis Direction"); + bool updateDirection = false; + + updateDirection |= ImGui::RadioButton( + axisDirection.c_str(), &direction, static_cast(AxisDirection::FrontToBack) + ); + ImGui::SameLine(); + updateDirection |= ImGui::RadioButton( + secondAxisDirection.c_str(), &direction, static_cast(AxisDirection::BackToFront) + ); + if (updateDirection) { + layout->setMainAxisDirection(static_cast(direction)); + updateLayout = true; + } + } + { + auto direction = static_cast(layout->getCrossAxisDirection()); + ImGui::Text("Cross Axis Direction"); + bool updateDirection = false; + updateDirection |= ImGui::RadioButton( + crossAxisDirection.c_str(), &direction, static_cast(AxisDirection::FrontToBack) + ); + ImGui::SameLine(); + updateDirection |= ImGui::RadioButton( + secondcrossAxisDirection.c_str(), &direction, static_cast(AxisDirection::BackToFront) + ); + if (updateDirection) { + layout->setCrossAxisDirection(static_cast(direction)); + updateLayout = true; + } + } + + auto gap = layout->getGap(); + if (ImGui::DragFloat("Gap", &gap)) { + layout->setGap(gap); updateLayout = true; } - } - { - auto direction = static_cast(layout->getCrossAxisDirection()); - ImGui::Text("Cross Axis Direction"); - bool updateDirection = false; - updateDirection |= ImGui::RadioButton( - crossAxisDirection.c_str(), &direction, static_cast(AxisDirection::FrontToBack) - ); - ImGui::SameLine(); - updateDirection |= ImGui::RadioButton( - secondcrossAxisDirection.c_str(), &direction, static_cast(AxisDirection::BackToFront) - ); - if (updateDirection) { - layout->setCrossAxisDirection(static_cast(direction)); + + auto ignoreInvisibleChildren = layout->isIgnoreInvisibleChildren(); + if (ImGui::Checkbox("Ignore Invisible Children", &ignoreInvisibleChildren)) { + layout->ignoreInvisibleChildren(ignoreInvisibleChildren); updateLayout = true; } - } - auto gap = layout->getGap(); - if (ImGui::DragFloat("Gap", &gap)) { - layout->setGap(gap); - updateLayout = true; - } - - auto ignoreInvisibleChildren = layout->isIgnoreInvisibleChildren(); - if (ImGui::Checkbox("Ignore Invisible Children", &ignoreInvisibleChildren)) { - layout->ignoreInvisibleChildren(ignoreInvisibleChildren); - updateLayout = true; - } + auto minRelativeScaleOpt = layout->getMinRelativeScale(); + float minRelativeScale = minRelativeScaleOpt.value_or(0); + bool hasMinRelativeScale = minRelativeScaleOpt.has_value(); - auto minRelativeScaleOpt = layout->getMinRelativeScale(); - float minRelativeScale = minRelativeScaleOpt.value_or(0); - bool hasMinRelativeScale = minRelativeScaleOpt.has_value(); - - if (ImGui::Checkbox("Has Min Relative Scale", &hasMinRelativeScale)) { - if (hasMinRelativeScale) { - layout->setMinRelativeScale(0); + if (ImGui::Checkbox("Has Min Relative Scale", &hasMinRelativeScale)) { + if (hasMinRelativeScale) { + layout->setMinRelativeScale(0); + } + else { + layout->setMinRelativeScale(std::nullopt); + } + updateLayout = true; } - else { - layout->setMinRelativeScale(std::nullopt); + if (hasMinRelativeScale) { + if (ImGui::DragFloat("Min Relative Scale", &minRelativeScale)) { + + layout->setMinRelativeScale(minRelativeScale); + updateLayout = true; + + } } - updateLayout = true; - } - if (hasMinRelativeScale) { - if (ImGui::DragFloat("Min Relative Scale", &minRelativeScale)) { - - layout->setMinRelativeScale(minRelativeScale); + + auto maxRelativeScaleOpt = layout->getMaxRelativeScale(); + float maxRelativeScale = maxRelativeScaleOpt.value_or(0); + bool hasMaxRelativeScale = maxRelativeScaleOpt.has_value(); + if (ImGui::Checkbox("Has Max Relative Scale", &hasMaxRelativeScale)) { + if (hasMaxRelativeScale) { + layout->setMaxRelativeScale(0); + } + else { + layout->setMaxRelativeScale(std::nullopt); + } updateLayout = true; - } - } - auto maxRelativeScaleOpt = layout->getMaxRelativeScale(); - float maxRelativeScale = maxRelativeScaleOpt.value_or(0); - bool hasMaxRelativeScale = maxRelativeScaleOpt.has_value(); - if (ImGui::Checkbox("Has Max Relative Scale", &hasMaxRelativeScale)) { if (hasMaxRelativeScale) { - layout->setMaxRelativeScale(0); + if (ImGui::DragFloat("Max Relative Scale", &maxRelativeScale)) { + layout->setMaxRelativeScale(maxRelativeScale); + updateLayout = true; + } } - else { - layout->setMaxRelativeScale(std::nullopt); + + if (updateLayout) { + node->updateLayout(); } - updateLayout = true; } + if (auto layout = typeinfo_cast(rawLayout)) { + bool updateLayout = false; - if (hasMaxRelativeScale) { - if (ImGui::DragFloat("Max Relative Scale", &maxRelativeScale)) { - layout->setMaxRelativeScale(maxRelativeScale); + auto axis = static_cast(layout->getAxis()); + ImGui::Text("Axis"); + auto updateAxis = false; + updateAxis |= ImGui::RadioButton("Row", &axis, static_cast(Axis::Row)); + ImGui::SameLine(); + updateAxis |= ImGui::RadioButton("Column", &axis, static_cast(Axis::Column)); + if (updateAxis) { + if (layout->getAxis() != static_cast(axis)) { + node->setContentSize({ + node->getContentSize().height, + node->getContentSize().width + }); + } + layout->setAxis(static_cast(axis)); updateLayout = true; } - } - if (updateLayout) { - node->updateLayout(); - } - } - if (auto layout = typeinfo_cast(rawLayout)) { - bool updateLayout = false; + auto axisReverse = layout->getAxisReverse(); + if (ImGui::Checkbox("Flip Axis Direction", &axisReverse)) { + layout->setAxisReverse(axisReverse); + updateLayout = true; + } + axisReverse = layout->getCrossAxisReverse(); + if (ImGui::Checkbox("Flip Cross Axis Direction", &axisReverse)) { + layout->setCrossAxisReverse(axisReverse); + updateLayout = true; + } - auto axis = static_cast(layout->getAxis()); - ImGui::Text("Axis"); - auto updateAxis = false; - updateAxis |= ImGui::RadioButton("Row", &axis, static_cast(Axis::Row)); - ImGui::SameLine(); - updateAxis |= ImGui::RadioButton("Column", &axis, static_cast(Axis::Column)); - if (updateAxis) { - if (layout->getAxis() != static_cast(axis)) { - node->setContentSize({ - node->getContentSize().height, - node->getContentSize().width - }); + { + auto align = static_cast(layout->getAxisAlignment()); + ImGui::Text("Axis Alignment"); + bool updateAlign = false; + updateAlign |= ImGui::RadioButton( + "Start##axisalign0", &align, static_cast(AxisAlignment::Start) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Center##axisalign1", &align, static_cast(AxisAlignment::Center) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "End##axisalign2", &align, static_cast(AxisAlignment::End) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Even##axisalign3", &align, static_cast(AxisAlignment::Even) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Between##axisalign4", &align, static_cast(AxisAlignment::Between) + ); + if (updateAlign) { + layout->setAxisAlignment(static_cast(align)); + updateLayout = true; + } } - layout->setAxis(static_cast(axis)); - updateLayout = true; - } - auto axisReverse = layout->getAxisReverse(); - if (ImGui::Checkbox("Flip Axis Direction", &axisReverse)) { - layout->setAxisReverse(axisReverse); - updateLayout = true; - } - axisReverse = layout->getCrossAxisReverse(); - if (ImGui::Checkbox("Flip Cross Axis Direction", &axisReverse)) { - layout->setCrossAxisReverse(axisReverse); - updateLayout = true; - } + { + auto align = static_cast(layout->getCrossAxisAlignment()); + ImGui::Text("Cross Axis Alignment"); + bool updateAlign = false; + updateAlign |= ImGui::RadioButton( + "Start##cross0", &align, static_cast(AxisAlignment::Start) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Center##cross1", &align, static_cast(AxisAlignment::Center) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "End##cross2", &align, static_cast(AxisAlignment::End) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Even##cross3", &align, static_cast(AxisAlignment::Even) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Between##cross4", &align, static_cast(AxisAlignment::Between) + ); + if (updateAlign) { + layout->setCrossAxisAlignment(static_cast(align)); + updateLayout = true; + } + } - { - auto align = static_cast(layout->getAxisAlignment()); - ImGui::Text("Axis Alignment"); - bool updateAlign = false; - updateAlign |= ImGui::RadioButton( - "Start##axisalign0", &align, static_cast(AxisAlignment::Start) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Center##axisalign1", &align, static_cast(AxisAlignment::Center) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "End##axisalign2", &align, static_cast(AxisAlignment::End) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Even##axisalign3", &align, static_cast(AxisAlignment::Even) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Between##axisalign4", &align, static_cast(AxisAlignment::Between) - ); - if (updateAlign) { - layout->setAxisAlignment(static_cast(align)); - updateLayout = true; + { + auto align = static_cast(layout->getCrossAxisLineAlignment()); + ImGui::Text("Cross Axis Line Alignment"); + bool updateAlign = false; + updateAlign |= ImGui::RadioButton( + "Start##crossline0", &align, static_cast(AxisAlignment::Start) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Center##crossline1", &align, static_cast(AxisAlignment::Center) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "End##crossline2", &align, static_cast(AxisAlignment::End) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Even##crossline3", &align, static_cast(AxisAlignment::Even) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Between##crossline4", &align, static_cast(AxisAlignment::Between) + ); + if (updateAlign) { + layout->setCrossAxisLineAlignment(static_cast(align)); + updateLayout = true; + } } - } - { - auto align = static_cast(layout->getCrossAxisAlignment()); - ImGui::Text("Cross Axis Alignment"); - bool updateAlign = false; - updateAlign |= ImGui::RadioButton( - "Start##cross0", &align, static_cast(AxisAlignment::Start) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Center##cross1", &align, static_cast(AxisAlignment::Center) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "End##cross2", &align, static_cast(AxisAlignment::End) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Even##cross3", &align, static_cast(AxisAlignment::Even) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Between##cross4", &align, static_cast(AxisAlignment::Between) - ); - if (updateAlign) { - layout->setCrossAxisAlignment(static_cast(align)); + auto gap = layout->getGap(); + if (ImGui::DragFloat("Gap", &gap)) { + layout->setGap(gap); updateLayout = true; } - } - { - auto align = static_cast(layout->getCrossAxisLineAlignment()); - ImGui::Text("Cross Axis Line Alignment"); - bool updateAlign = false; - updateAlign |= ImGui::RadioButton( - "Start##crossline0", &align, static_cast(AxisAlignment::Start) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Center##crossline1", &align, static_cast(AxisAlignment::Center) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "End##crossline2", &align, static_cast(AxisAlignment::End) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Even##crossline3", &align, static_cast(AxisAlignment::Even) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Between##crossline4", &align, static_cast(AxisAlignment::Between) - ); - if (updateAlign) { - layout->setCrossAxisLineAlignment(static_cast(align)); + auto ignoreInvisibleChildren = layout->isIgnoreInvisibleChildren(); + if (ImGui::Checkbox("Ignore Invisible Children", &ignoreInvisibleChildren)) { + layout->ignoreInvisibleChildren(ignoreInvisibleChildren); updateLayout = true; } - } - - auto gap = layout->getGap(); - if (ImGui::DragFloat("Gap", &gap)) { - layout->setGap(gap); - updateLayout = true; - } - auto ignoreInvisibleChildren = layout->isIgnoreInvisibleChildren(); - if (ImGui::Checkbox("Ignore Invisible Children", &ignoreInvisibleChildren)) { - layout->ignoreInvisibleChildren(ignoreInvisibleChildren); - updateLayout = true; - } + auto autoScale = layout->getAutoScale(); + if (ImGui::Checkbox("Auto Scale", &autoScale)) { + layout->setAutoScale(autoScale); + updateLayout = true; + } - auto autoScale = layout->getAutoScale(); - if (ImGui::Checkbox("Auto Scale", &autoScale)) { - layout->setAutoScale(autoScale); - updateLayout = true; - } + auto grow = layout->getGrowCrossAxis(); + if (ImGui::Checkbox("Grow Cross Axis", &grow)) { + layout->setGrowCrossAxis(grow); + updateLayout = true; + } - auto grow = layout->getGrowCrossAxis(); - if (ImGui::Checkbox("Grow Cross Axis", &grow)) { - layout->setGrowCrossAxis(grow); - updateLayout = true; - } + auto overflow = layout->getCrossAxisOverflow(); + if (ImGui::Checkbox("Allow Cross Axis Overflow", &overflow)) { + layout->setCrossAxisOverflow(overflow); + updateLayout = true; + } - auto overflow = layout->getCrossAxisOverflow(); - if (ImGui::Checkbox("Allow Cross Axis Overflow", &overflow)) { - layout->setCrossAxisOverflow(overflow); - updateLayout = true; - } + auto maxAutoGrowAxisOpt = layout->getAutoGrowAxis(); + float autoGrowAxis = maxAutoGrowAxisOpt.value_or(0); + bool hasAutoGrowAxis = maxAutoGrowAxisOpt.has_value(); + if (ImGui::Checkbox("Has Auto Grow Axis", &hasAutoGrowAxis)) { + if (hasAutoGrowAxis) { + layout->setAutoGrowAxis(0); + } + else { + layout->setAutoGrowAxis(std::nullopt); + } + updateLayout = true; + } - auto maxAutoGrowAxisOpt = layout->getAutoGrowAxis(); - float autoGrowAxis = maxAutoGrowAxisOpt.value_or(0); - bool hasAutoGrowAxis = maxAutoGrowAxisOpt.has_value(); - if (ImGui::Checkbox("Has Auto Grow Axis", &hasAutoGrowAxis)) { if (hasAutoGrowAxis) { - layout->setAutoGrowAxis(0); - } - else { - layout->setAutoGrowAxis(std::nullopt); + if (ImGui::DragFloat("Auto Grow Axis", &autoGrowAxis)) { + layout->setAutoGrowAxis(autoGrowAxis); + updateLayout = true; + } } - updateLayout = true; - } - if (hasAutoGrowAxis) { - if (ImGui::DragFloat("Auto Grow Axis", &autoGrowAxis)) { - layout->setAutoGrowAxis(autoGrowAxis); - updateLayout = true; + if (updateLayout) { + node->updateLayout(); } } - - if (updateLayout) { - node->updateLayout(); - } - } - } - else { - if (ImGui::Button(U8STR(FEATHER_PLUS " Add SimpleAxisLayout"))) { - node->setLayout(SimpleAxisLayout::create(Axis::Row)); - } - if (ImGui::Button(U8STR(FEATHER_PLUS " Add AxisLayout"))) { - node->setLayout(AxisLayout::create()); } - if (ImGui::Button(U8STR(FEATHER_PLUS " Add AnchorLayout"))) { - node->setLayout(AnchorLayout::create()); + else { + if (ImGui::Button(U8STR(FEATHER_PLUS " Add SimpleAxisLayout"))) { + node->setLayout(SimpleAxisLayout::create(Axis::Row)); + } + if (ImGui::Button(U8STR(FEATHER_PLUS " Add AxisLayout"))) { + node->setLayout(AxisLayout::create()); + } + if (ImGui::Button(U8STR(FEATHER_PLUS " Add AnchorLayout"))) { + node->setLayout(AnchorLayout::create()); + } } - } + }; + layoutFn(); } void DevTools::drawAttributes() { From b89073cf8eac996a6d31232d60065ae5a96832c3 Mon Sep 17 00:00:00 2001 From: Alphalaneous <38200084+Alphalaneous@users.noreply.github.com> Date: Fri, 9 May 2025 12:07:34 -0400 Subject: [PATCH 2/3] Clean up code --- src/pages/Attributes.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/pages/Attributes.cpp b/src/pages/Attributes.cpp index c5b5b92..26d5b9e 100644 --- a/src/pages/Attributes.cpp +++ b/src/pages/Attributes.cpp @@ -311,7 +311,7 @@ void DevTools::drawNodeAttributes(CCNode* node) { ImGui::Separator(); ImGui::NewLine(); } - auto layoutOptsFn = [node] { + [&] { if (auto rawOpts = node->getLayoutOptions()) { ImGui::Text("Layout options: %s", typeid(*rawOpts).name()); @@ -637,14 +637,13 @@ void DevTools::drawNodeAttributes(CCNode* node) { node->setLayoutOptions(AnchorLayoutOptions::create()); } } - }; - layoutOptsFn(); + }(); ImGui::NewLine(); ImGui::Separator(); ImGui::NewLine(); - auto layoutFn = [node] { + [&] { if (auto rawLayout = node->getLayout()) { ImGui::Text("Layout: %s", typeid(*rawLayout).name()); @@ -1084,8 +1083,7 @@ void DevTools::drawNodeAttributes(CCNode* node) { node->setLayout(AnchorLayout::create()); } } - }; - layoutFn(); + }(); } void DevTools::drawAttributes() { From b53b9ba419338603b4b5bd0ce8c19d1eaf689287 Mon Sep 17 00:00:00 2001 From: Alphalaneous <38200084+Alphalaneous@users.noreply.github.com> Date: Fri, 9 May 2025 14:56:27 -0400 Subject: [PATCH 3/3] Move everything into methods --- src/DevTools.hpp | 8 + src/pages/Attributes.cpp | 1357 +++++++++++++++++++------------------- 2 files changed, 699 insertions(+), 666 deletions(-) diff --git a/src/DevTools.hpp b/src/DevTools.hpp index e9da380..4859192 100644 --- a/src/DevTools.hpp +++ b/src/DevTools.hpp @@ -58,6 +58,14 @@ class DevTools { void drawAdvancedSettings(); void drawNodeAttributes(CCNode* node); void drawAttributes(); + void drawBasicAttributes(CCNode* node); + void drawColorAttributes(CCNode* node); + void drawLabelAttributes(CCNode* node); + void drawAxisGapAttribute(CCNode* node); + void drawTextureAttributes(CCNode* node); + void drawMenuItemAttributes(CCNode* node); + void drawLayoutOptionsAttributes(CCNode* node); + void drawLayoutAttributes(CCNode* node); void drawPreview(); void drawNodePreview(CCNode* node); void drawHighlight(CCNode* node, HighlightMode mode); diff --git a/src/pages/Attributes.cpp b/src/pages/Attributes.cpp index 26d5b9e..5e983d4 100644 --- a/src/pages/Attributes.cpp +++ b/src/pages/Attributes.cpp @@ -35,6 +35,28 @@ bool checkbox(const char* text, T* ptr, bool(T::* get)() const, R(T::* set)(bool } void DevTools::drawNodeAttributes(CCNode* node) { + drawBasicAttributes(node); + drawColorAttributes(node); + drawLabelAttributes(node); + drawAxisGapAttribute(node); + + ImGui::NewLine(); + ImGui::Separator(); + ImGui::NewLine(); + + drawTextureAttributes(node); + drawMenuItemAttributes(node); + + drawLayoutOptionsAttributes(node); + + ImGui::NewLine(); + ImGui::Separator(); + ImGui::NewLine(); + + drawLayoutAttributes(node); +} + +void DevTools::drawBasicAttributes(CCNode* node) { if (ImGui::Button("Deselect")) { return this->selectNode(nullptr); } @@ -138,7 +160,9 @@ void DevTools::drawNodeAttributes(CCNode* node) { &CCNode::isIgnoreAnchorPointForPosition, &CCNode::ignoreAnchorPointForPosition ); - +} + +void DevTools::drawColorAttributes(CCNode* node) { if (auto rgbaNode = typeinfo_cast(node)) { if (auto gradient = typeinfo_cast(node)) { @@ -194,14 +218,18 @@ void DevTools::drawNodeAttributes(CCNode* node) { ImGui::SameLine(); checkbox("Cascade Opacity", rgbaNode, &CCRGBAProtocol::isCascadeOpacityEnabled, &CCRGBAProtocol::setCascadeOpacityEnabled); } +} +void DevTools::drawLabelAttributes(CCNode* node) { if (auto labelNode = typeinfo_cast(node)) { std::string str = labelNode->getString(); if (ImGui::InputText("Text", &str, 256)) { labelNode->setString(str.c_str()); } } - +} + +void DevTools::drawAxisGapAttribute(CCNode* node) { if (auto gap = typeinfo_cast(node)){ float axisGap = gap->getGap(); if (ImGui::DragFloat("Axis Gap", &axisGap)) { @@ -211,11 +239,9 @@ void DevTools::drawNodeAttributes(CCNode* node) { } } } +} - ImGui::NewLine(); - ImGui::Separator(); - ImGui::NewLine(); - +void DevTools::drawTextureAttributes(CCNode* node) { if (auto textureProtocol = typeinfo_cast(node)) { if (auto texture = textureProtocol->getTexture()) { if (auto spriteNode = typeinfo_cast(node)) { @@ -268,7 +294,9 @@ void DevTools::drawNodeAttributes(CCNode* node) { ImGui::Separator(); ImGui::NewLine(); } - +} + +void DevTools::drawMenuItemAttributes(CCNode* node) { if (auto menuItemNode = typeinfo_cast(node)) { const auto selector = menuItemNode->m_pfnSelector; if (!selector) { @@ -311,779 +339,776 @@ void DevTools::drawNodeAttributes(CCNode* node) { ImGui::Separator(); ImGui::NewLine(); } - [&] { - if (auto rawOpts = node->getLayoutOptions()) { - ImGui::Text("Layout options: %s", typeid(*rawOpts).name()); +} - if (ImGui::Button(U8STR(FEATHER_REFRESH_CW " Update Parent Layout"))) { - if (auto parent = node->getParent()) { - parent->updateLayout(); - } +void DevTools::drawLayoutOptionsAttributes(CCNode* node) { + if (auto rawOpts = node->getLayoutOptions()) { + ImGui::Text("Layout options: %s", typeid(*rawOpts).name()); + + if (ImGui::Button(U8STR(FEATHER_REFRESH_CW " Update Parent Layout"))) { + if (auto parent = node->getParent()) { + parent->updateLayout(); } - ImGui::SameLine(); - if (ImGui::Button(U8STR(FEATHER_TRASH_2 " Remove Layout Options"))) { - node->setLayoutOptions(nullptr); - return; - } - if (auto opts = typeinfo_cast(rawOpts)) { - bool updateLayout = false; - auto minRelativeScaleOpt = opts->getMinRelativeScale(); - float minRelativeScale = minRelativeScaleOpt.value_or(0); - bool hasMinRelativeScale = minRelativeScaleOpt.has_value(); - - if (ImGui::Checkbox("Has Min Relative Scale##simplescale0", &hasMinRelativeScale)) { - if (hasMinRelativeScale) { - opts->setMinRelativeScale(0); - } - else { - opts->setMinRelativeScale(std::nullopt); - } - updateLayout = true; - } + } + ImGui::SameLine(); + if (ImGui::Button(U8STR(FEATHER_TRASH_2 " Remove Layout Options"))) { + node->setLayoutOptions(nullptr); + return; + } + if (auto opts = typeinfo_cast(rawOpts)) { + bool updateLayout = false; + auto minRelativeScaleOpt = opts->getMinRelativeScale(); + float minRelativeScale = minRelativeScaleOpt.value_or(0); + bool hasMinRelativeScale = minRelativeScaleOpt.has_value(); + + if (ImGui::Checkbox("Has Min Relative Scale##simplescale0", &hasMinRelativeScale)) { if (hasMinRelativeScale) { - if (ImGui::DragFloat("Min Relative Scale##simplescale1", &minRelativeScale)) { - - opts->setMinRelativeScale(minRelativeScale); - updateLayout = true; - } + opts->setMinRelativeScale(0); } - - auto maxRelativeScaleOpt = opts->getMaxRelativeScale(); - float maxRelativeScale = maxRelativeScaleOpt.value_or(0); - bool hasMaxRelativeScale = maxRelativeScaleOpt.has_value(); - if (ImGui::Checkbox("Has Max Relative Scale##simplescale2", &hasMaxRelativeScale)) { - if (hasMaxRelativeScale) { - opts->setMaxRelativeScale(0); - } - else { - opts->setMaxRelativeScale(std::nullopt); - } + else { + opts->setMinRelativeScale(std::nullopt); + } + updateLayout = true; + } + if (hasMinRelativeScale) { + if (ImGui::DragFloat("Min Relative Scale##simplescale1", &minRelativeScale)) { + + opts->setMinRelativeScale(minRelativeScale); updateLayout = true; } + } + auto maxRelativeScaleOpt = opts->getMaxRelativeScale(); + float maxRelativeScale = maxRelativeScaleOpt.value_or(0); + bool hasMaxRelativeScale = maxRelativeScaleOpt.has_value(); + if (ImGui::Checkbox("Has Max Relative Scale##simplescale2", &hasMaxRelativeScale)) { if (hasMaxRelativeScale) { - if (ImGui::DragFloat("Max Relative Scale##simplescale3", &maxRelativeScale)) { - opts->setMaxRelativeScale(maxRelativeScale); - updateLayout = true; - } + opts->setMaxRelativeScale(0); } + else { + opts->setMaxRelativeScale(std::nullopt); + } + updateLayout = true; + } - int scalingPriority = static_cast(opts->getScalingPriority()); - - ImGui::Text("Scaling Priority"); - bool updateScalePrio = false; - updateScalePrio |= ImGui::RadioButton( - "First##scalepriooption1", &scalingPriority, static_cast(ScalingPriority::First) - ); - ImGui::SameLine(); - updateScalePrio |= ImGui::RadioButton( - "Early##scalepriooption2", &scalingPriority, static_cast(ScalingPriority::Early) - ); - ImGui::SameLine(); - updateScalePrio |= ImGui::RadioButton( - "Normal##scalepriooption3", &scalingPriority, static_cast(ScalingPriority::Normal) - ); - ImGui::SameLine(); - updateScalePrio |= ImGui::RadioButton( - "Late##scalepriooption4", &scalingPriority, static_cast(ScalingPriority::Late) - ); - ImGui::SameLine(); - updateScalePrio |= ImGui::RadioButton( - "Last##scalepriooption4", &scalingPriority, static_cast(ScalingPriority::Last) - ); - ImGui::SameLine(); - updateScalePrio |= ImGui::RadioButton( - "Never##alignmentoption0", &scalingPriority, static_cast(ScalingPriority::Never) - ); - if (updateScalePrio) { - opts->setScalingPriority(static_cast(scalingPriority)); + if (hasMaxRelativeScale) { + if (ImGui::DragFloat("Max Relative Scale##simplescale3", &maxRelativeScale)) { + opts->setMaxRelativeScale(maxRelativeScale); updateLayout = true; } + } - if (updateLayout && node->getParent()) { - node->getParent()->updateLayout(); - } + int scalingPriority = static_cast(opts->getScalingPriority()); + + ImGui::Text("Scaling Priority"); + bool updateScalePrio = false; + updateScalePrio |= ImGui::RadioButton( + "First##scalepriooption1", &scalingPriority, static_cast(ScalingPriority::First) + ); + ImGui::SameLine(); + updateScalePrio |= ImGui::RadioButton( + "Early##scalepriooption2", &scalingPriority, static_cast(ScalingPriority::Early) + ); + ImGui::SameLine(); + updateScalePrio |= ImGui::RadioButton( + "Normal##scalepriooption3", &scalingPriority, static_cast(ScalingPriority::Normal) + ); + ImGui::SameLine(); + updateScalePrio |= ImGui::RadioButton( + "Late##scalepriooption4", &scalingPriority, static_cast(ScalingPriority::Late) + ); + ImGui::SameLine(); + updateScalePrio |= ImGui::RadioButton( + "Last##scalepriooption4", &scalingPriority, static_cast(ScalingPriority::Last) + ); + ImGui::SameLine(); + updateScalePrio |= ImGui::RadioButton( + "Never##alignmentoption0", &scalingPriority, static_cast(ScalingPriority::Never) + ); + if (updateScalePrio) { + opts->setScalingPriority(static_cast(scalingPriority)); + updateLayout = true; } - if (auto opts = typeinfo_cast(rawOpts)) { - bool updateLayout = false; - ImGui::Text("Auto Scale"); - auto updateAxis = false; - int autoScale = opts->getAutoScale().has_value() ? opts->getAutoScale().value() : -1; - updateAxis |= ImGui::RadioButton("Default##autoscale0", &autoScale, -1); - ImGui::SameLine(); - updateAxis |= ImGui::RadioButton("Enable##autoscale1", &autoScale, 1); - ImGui::SameLine(); - updateAxis |= ImGui::RadioButton("Disable##autoscale2", &autoScale, 0); - if (updateAxis) { - switch (autoScale) { - case -1: opts->setAutoScale(std::nullopt); break; - case 0: opts->setAutoScale(false); break; - case 1: opts->setAutoScale(true); break; - } - updateLayout = true; + if (updateLayout && node->getParent()) { + node->getParent()->updateLayout(); + } + } + if (auto opts = typeinfo_cast(rawOpts)) { + bool updateLayout = false; + + ImGui::Text("Auto Scale"); + auto updateAxis = false; + int autoScale = opts->getAutoScale().has_value() ? opts->getAutoScale().value() : -1; + updateAxis |= ImGui::RadioButton("Default##autoscale0", &autoScale, -1); + ImGui::SameLine(); + updateAxis |= ImGui::RadioButton("Enable##autoscale1", &autoScale, 1); + ImGui::SameLine(); + updateAxis |= ImGui::RadioButton("Disable##autoscale2", &autoScale, 0); + if (updateAxis) { + switch (autoScale) { + case -1: opts->setAutoScale(std::nullopt); break; + case 0: opts->setAutoScale(false); break; + case 1: opts->setAutoScale(true); break; } + updateLayout = true; + } - auto minScale = opts->getMinScale(); - bool hasMinScale = opts->hasExplicitMinScale(); - auto maxScale = opts->getMaxScale(); - bool hasMaxScale = opts->hasExplicitMaxScale(); + auto minScale = opts->getMinScale(); + bool hasMinScale = opts->hasExplicitMinScale(); + auto maxScale = opts->getMaxScale(); + bool hasMaxScale = opts->hasExplicitMaxScale(); - if (ImGui::Checkbox("Has Min Scale", &hasMinScale)) { - if (hasMinScale) { - opts->setScaleLimits(minScale, hasMaxScale ? std::optional(maxScale) : std::nullopt); - } - else { - opts->setScaleLimits(std::nullopt, hasMaxScale ? std::optional(maxScale) : std::nullopt); - } - updateLayout = true; - } + if (ImGui::Checkbox("Has Min Scale", &hasMinScale)) { if (hasMinScale) { - if (ImGui::DragFloat("Min Scale", &minScale)) { - opts->setScaleLimits(minScale, maxScale); - updateLayout = true; - } + opts->setScaleLimits(minScale, hasMaxScale ? std::optional(maxScale) : std::nullopt); } - - if (ImGui::Checkbox("Has Max Scale", &hasMaxScale)) { - if (hasMaxScale) { - opts->setScaleLimits(hasMinScale ? std::optional(minScale) : std::nullopt, maxScale); - } - else { - opts->setScaleLimits(hasMinScale ? std::optional(minScale) : std::nullopt, std::nullopt); - } + else { + opts->setScaleLimits(std::nullopt, hasMaxScale ? std::optional(maxScale) : std::nullopt); + } + updateLayout = true; + } + if (hasMinScale) { + if (ImGui::DragFloat("Min Scale", &minScale)) { + opts->setScaleLimits(minScale, maxScale); updateLayout = true; } + } + if (ImGui::Checkbox("Has Max Scale", &hasMaxScale)) { if (hasMaxScale) { - if (ImGui::DragFloat("Max Scale", &maxScale)) { - opts->setScaleLimits(minScale, maxScale); - updateLayout = true; - } + opts->setScaleLimits(hasMinScale ? std::optional(minScale) : std::nullopt, maxScale); } + else { + opts->setScaleLimits(hasMinScale ? std::optional(minScale) : std::nullopt, std::nullopt); + } + updateLayout = true; + } - auto lengthOpt = opts->getLength(); - float length = lengthOpt.value_or(0); - bool hasLength = lengthOpt.has_value(); - - if (ImGui::Checkbox("Has Length", &hasLength)) { - if (hasLength) { - opts->setLength(0); - } - else { - opts->setLength(std::nullopt); - } + if (hasMaxScale) { + if (ImGui::DragFloat("Max Scale", &maxScale)) { + opts->setScaleLimits(minScale, maxScale); updateLayout = true; } - if (hasLength) { - if (ImGui::DragFloat("Length", &length)) { - opts->setLength(length); - updateLayout = true; - } - } + } - auto prevGapOpt = opts->getPrevGap(); - float prevGap = prevGapOpt.value_or(0); - bool hasPrevGap = prevGapOpt.has_value(); + auto lengthOpt = opts->getLength(); + float length = lengthOpt.value_or(0); + bool hasLength = lengthOpt.has_value(); - if (ImGui::Checkbox("Has Prev Gap", &hasPrevGap)) { - if (hasPrevGap) { - opts->setPrevGap(0); - } - else { - opts->setPrevGap(std::nullopt); - } - updateLayout = true; + if (ImGui::Checkbox("Has Length", &hasLength)) { + if (hasLength) { + opts->setLength(0); } - if (hasPrevGap) { - if (ImGui::DragFloat("Prev Gap", &prevGap)) { - opts->setPrevGap(prevGap); - updateLayout = true; - } + else { + opts->setLength(std::nullopt); + } + updateLayout = true; + } + if (hasLength) { + if (ImGui::DragFloat("Length", &length)) { + opts->setLength(length); + updateLayout = true; } + } - auto nextGapOpt = opts->getNextGap(); - float nextGap = nextGapOpt.value_or(0); - bool hasNextGap = nextGapOpt.has_value(); + auto prevGapOpt = opts->getPrevGap(); + float prevGap = prevGapOpt.value_or(0); + bool hasPrevGap = prevGapOpt.has_value(); - if (ImGui::Checkbox("Has Next Gap", &hasNextGap)) { - if (hasNextGap) { - opts->setNextGap(0); - } - else { - opts->setNextGap(std::nullopt); - } + if (ImGui::Checkbox("Has Prev Gap", &hasPrevGap)) { + if (hasPrevGap) { + opts->setPrevGap(0); + } + else { + opts->setPrevGap(std::nullopt); + } + updateLayout = true; + } + if (hasPrevGap) { + if (ImGui::DragFloat("Prev Gap", &prevGap)) { + opts->setPrevGap(prevGap); updateLayout = true; } + } + + auto nextGapOpt = opts->getNextGap(); + float nextGap = nextGapOpt.value_or(0); + bool hasNextGap = nextGapOpt.has_value(); + + if (ImGui::Checkbox("Has Next Gap", &hasNextGap)) { if (hasNextGap) { - if (ImGui::DragFloat("Next Gap", &nextGap)) { - opts->setNextGap(nextGap); - updateLayout = true; - } + opts->setNextGap(0); } - - if (checkbox("Break Line", opts, AXIS_GET(BreakLine))) { - updateLayout = true; + else { + opts->setNextGap(std::nullopt); } - if (checkbox("Same Line", opts, AXIS_GET(SameLine))) { + updateLayout = true; + } + if (hasNextGap) { + if (ImGui::DragFloat("Next Gap", &nextGap)) { + opts->setNextGap(nextGap); updateLayout = true; } + } - auto relativeScale = opts->getRelativeScale(); - if (ImGui::DragFloat("Relative Scale", &relativeScale)) { - opts->setRelativeScale(relativeScale); - updateLayout = true; - } + if (checkbox("Break Line", opts, AXIS_GET(BreakLine))) { + updateLayout = true; + } + if (checkbox("Same Line", opts, AXIS_GET(SameLine))) { + updateLayout = true; + } - auto prio = opts->getScalePriority(); - if (ImGui::DragInt("Scale Priority", &prio, .03f)) { - opts->setScalePriority(prio); - updateLayout = true; - } + auto relativeScale = opts->getRelativeScale(); + if (ImGui::DragFloat("Relative Scale", &relativeScale)) { + opts->setRelativeScale(relativeScale); + updateLayout = true; + } - auto crossAxisAlignmentOpt = opts->getCrossAxisAlignment(); - int crossAxisAlignment = static_cast(crossAxisAlignmentOpt.value_or(AxisAlignment::Start)); - bool hasCrossAxisAlignment = crossAxisAlignmentOpt.has_value(); + auto prio = opts->getScalePriority(); + if (ImGui::DragInt("Scale Priority", &prio, .03f)) { + opts->setScalePriority(prio); + updateLayout = true; + } - if (ImGui::Checkbox("Has Cross Axis Alignment", &hasCrossAxisAlignment)) { - if (hasCrossAxisAlignment) { - opts->setCrossAxisAlignment(AxisAlignment::Start); - } - else { - opts->setCrossAxisAlignment(std::nullopt); - } - updateLayout = true; - } + auto crossAxisAlignmentOpt = opts->getCrossAxisAlignment(); + int crossAxisAlignment = static_cast(crossAxisAlignmentOpt.value_or(AxisAlignment::Start)); + bool hasCrossAxisAlignment = crossAxisAlignmentOpt.has_value(); + + if (ImGui::Checkbox("Has Cross Axis Alignment", &hasCrossAxisAlignment)) { if (hasCrossAxisAlignment) { - - ImGui::Text("Cross Axis Alignment"); - bool updateAlignment = false; - updateAlignment |= ImGui::RadioButton( - "Start##alignmentoption0", &crossAxisAlignment, static_cast(AxisAlignment::Start) - ); - ImGui::SameLine(); - updateAlignment |= ImGui::RadioButton( - "Center##alignmentoption1", &crossAxisAlignment, static_cast(AxisAlignment::Center) - ); - ImGui::SameLine(); - updateAlignment |= ImGui::RadioButton( - "End##alignmentoption2", &crossAxisAlignment, static_cast(AxisAlignment::End) - ); - ImGui::SameLine(); - updateAlignment |= ImGui::RadioButton( - "Even##alignmentoption3", &crossAxisAlignment, static_cast(AxisAlignment::Even) - ); - ImGui::SameLine(); - updateAlignment |= ImGui::RadioButton( - "Between##alignmentoption4", &crossAxisAlignment, static_cast(AxisAlignment::Between) - ); - if (updateAlignment) { - opts->setCrossAxisAlignment(static_cast(crossAxisAlignment)); - updateLayout = true; - } + opts->setCrossAxisAlignment(AxisAlignment::Start); } - - if (updateLayout && node->getParent()) { - node->getParent()->updateLayout(); + else { + opts->setCrossAxisAlignment(std::nullopt); } + updateLayout = true; } - else if (auto opts = typeinfo_cast(rawOpts)) { - bool updateLayout = false; - - auto offset = opts->getOffset(); - ImGui::DragFloat2("Offset", &offset.x); - if (opts->getOffset() != offset) { - opts->setOffset(offset); + if (hasCrossAxisAlignment) { + + ImGui::Text("Cross Axis Alignment"); + bool updateAlignment = false; + updateAlignment |= ImGui::RadioButton( + "Start##alignmentoption0", &crossAxisAlignment, static_cast(AxisAlignment::Start) + ); + ImGui::SameLine(); + updateAlignment |= ImGui::RadioButton( + "Center##alignmentoption1", &crossAxisAlignment, static_cast(AxisAlignment::Center) + ); + ImGui::SameLine(); + updateAlignment |= ImGui::RadioButton( + "End##alignmentoption2", &crossAxisAlignment, static_cast(AxisAlignment::End) + ); + ImGui::SameLine(); + updateAlignment |= ImGui::RadioButton( + "Even##alignmentoption3", &crossAxisAlignment, static_cast(AxisAlignment::Even) + ); + ImGui::SameLine(); + updateAlignment |= ImGui::RadioButton( + "Between##alignmentoption4", &crossAxisAlignment, static_cast(AxisAlignment::Between) + ); + if (updateAlignment) { + opts->setCrossAxisAlignment(static_cast(crossAxisAlignment)); updateLayout = true; } + } - auto anchor = static_cast(opts->getAnchor()); - auto updateAnchor = false; - ImGui::BeginTable("anchor-table", 3); - ImGui::TableNextColumn(); - updateAnchor |= ImGui::RadioButton("Top Left", &anchor, static_cast(Anchor::TopLeft)); - updateAnchor |= ImGui::RadioButton("Left", &anchor, static_cast(Anchor::Left)); - updateAnchor |= ImGui::RadioButton("Bottom Left", &anchor, static_cast(Anchor::BottomLeft)); - ImGui::TableNextColumn(); - updateAnchor |= ImGui::RadioButton("Top", &anchor, static_cast(Anchor::Top)); - updateAnchor |= ImGui::RadioButton("Center", &anchor, static_cast(Anchor::Center)); - updateAnchor |= ImGui::RadioButton("Bottom", &anchor, static_cast(Anchor::Bottom)); - ImGui::TableNextColumn(); - updateAnchor |= ImGui::RadioButton("Top Right", &anchor, static_cast(Anchor::TopRight)); - updateAnchor |= ImGui::RadioButton("Right", &anchor, static_cast(Anchor::Right)); - updateAnchor |= ImGui::RadioButton("Bottom Right", &anchor, static_cast(Anchor::BottomRight)); - ImGui::EndTable(); - - if (updateAnchor) { - if (opts->getAnchor() != static_cast(anchor)) { - opts->setAnchor(static_cast(anchor)); - updateLayout = true; - } - } - - if (updateLayout && node->getParent()) { - node->getParent()->updateLayout(); - } + if (updateLayout && node->getParent()) { + node->getParent()->updateLayout(); } } - else { - if (ImGui::Button(U8STR(FEATHER_PLUS " Add SimpleAxisLayoutOptions"))) { - node->setLayoutOptions(SimpleAxisLayoutOptions::create()); + else if (auto opts = typeinfo_cast(rawOpts)) { + bool updateLayout = false; + + auto offset = opts->getOffset(); + ImGui::DragFloat2("Offset", &offset.x); + if (opts->getOffset() != offset) { + opts->setOffset(offset); + updateLayout = true; } - if (ImGui::Button(U8STR(FEATHER_PLUS " Add AxisLayoutOptions"))) { - node->setLayoutOptions(AxisLayoutOptions::create()); + + auto anchor = static_cast(opts->getAnchor()); + auto updateAnchor = false; + ImGui::BeginTable("anchor-table", 3); + ImGui::TableNextColumn(); + updateAnchor |= ImGui::RadioButton("Top Left", &anchor, static_cast(Anchor::TopLeft)); + updateAnchor |= ImGui::RadioButton("Left", &anchor, static_cast(Anchor::Left)); + updateAnchor |= ImGui::RadioButton("Bottom Left", &anchor, static_cast(Anchor::BottomLeft)); + ImGui::TableNextColumn(); + updateAnchor |= ImGui::RadioButton("Top", &anchor, static_cast(Anchor::Top)); + updateAnchor |= ImGui::RadioButton("Center", &anchor, static_cast(Anchor::Center)); + updateAnchor |= ImGui::RadioButton("Bottom", &anchor, static_cast(Anchor::Bottom)); + ImGui::TableNextColumn(); + updateAnchor |= ImGui::RadioButton("Top Right", &anchor, static_cast(Anchor::TopRight)); + updateAnchor |= ImGui::RadioButton("Right", &anchor, static_cast(Anchor::Right)); + updateAnchor |= ImGui::RadioButton("Bottom Right", &anchor, static_cast(Anchor::BottomRight)); + ImGui::EndTable(); + + if (updateAnchor) { + if (opts->getAnchor() != static_cast(anchor)) { + opts->setAnchor(static_cast(anchor)); + updateLayout = true; + } } - if (ImGui::Button(U8STR(FEATHER_PLUS " Add AnchorLayoutOptions"))) { - node->setLayoutOptions(AnchorLayoutOptions::create()); + + if (updateLayout && node->getParent()) { + node->getParent()->updateLayout(); } } - }(); - - ImGui::NewLine(); - ImGui::Separator(); - ImGui::NewLine(); + } + else { + if (ImGui::Button(U8STR(FEATHER_PLUS " Add SimpleAxisLayoutOptions"))) { + node->setLayoutOptions(SimpleAxisLayoutOptions::create()); + } + if (ImGui::Button(U8STR(FEATHER_PLUS " Add AxisLayoutOptions"))) { + node->setLayoutOptions(AxisLayoutOptions::create()); + } + if (ImGui::Button(U8STR(FEATHER_PLUS " Add AnchorLayoutOptions"))) { + node->setLayoutOptions(AnchorLayoutOptions::create()); + } + } +} - [&] { - if (auto rawLayout = node->getLayout()) { - ImGui::Text("Layout: %s", typeid(*rawLayout).name()); - - if (ImGui::Button(U8STR(FEATHER_REFRESH_CW " Update Layout"))) { - node->updateLayout(); - } +void DevTools::drawLayoutAttributes(CCNode* node){ + if (auto rawLayout = node->getLayout()) { + ImGui::Text("Layout: %s", typeid(*rawLayout).name()); + + if (ImGui::Button(U8STR(FEATHER_REFRESH_CW " Update Layout"))) { + node->updateLayout(); + } + ImGui::SameLine(); + if (ImGui::Button(U8STR(FEATHER_TRASH_2 " Remove Layout"))) { + node->setLayout(nullptr); + return; + } + ImGui::SameLine(); + if (ImGui::Button(U8STR(FEATHER_PLUS " Add Test Child"))) { + auto spr = CCSprite::create("GJ_button_01.png"); + auto btn = CCMenuItemSpriteExtra::create(spr, node, nullptr); + node->addChild(btn); + node->updateLayout(); + } + if (auto layout = typeinfo_cast(rawLayout)) { ImGui::SameLine(); - if (ImGui::Button(U8STR(FEATHER_TRASH_2 " Remove Layout"))) { - node->setLayout(nullptr); - return; + if (ImGui::Button(U8STR(FEATHER_PLUS " Add AxisGap"))) { + node->addChild(AxisGap::create(5)); + node->updateLayout(); } + bool updateLayout = false; + auto axis = static_cast(layout->getAxis()); + ImGui::Text("Axis"); + auto updateAxis = false; + updateAxis |= ImGui::RadioButton("Row", &axis, static_cast(Axis::Row)); ImGui::SameLine(); - if (ImGui::Button(U8STR(FEATHER_PLUS " Add Test Child"))) { - auto spr = CCSprite::create("GJ_button_01.png"); - auto btn = CCMenuItemSpriteExtra::create(spr, node, nullptr); - node->addChild(btn); - node->updateLayout(); + updateAxis |= ImGui::RadioButton("Column", &axis, static_cast(Axis::Column)); + if (updateAxis) { + if (layout->getAxis() != static_cast(axis)) { + node->setContentSize({ + node->getContentSize().height, + node->getContentSize().width + }); + } + layout->setAxis(static_cast(axis)); + updateLayout = true; } - if (auto layout = typeinfo_cast(rawLayout)) { + { + auto axisScaling = static_cast(layout->getMainAxisScaling()); + ImGui::Text("Main Axis Scaling"); + bool updateScaling = false; + updateScaling |= ImGui::RadioButton( + "None##mainscale0", &axisScaling, static_cast(AxisScaling::None) + ); ImGui::SameLine(); - if (ImGui::Button(U8STR(FEATHER_PLUS " Add AxisGap"))) { - node->addChild(AxisGap::create(5)); - node->updateLayout(); - } - bool updateLayout = false; - auto axis = static_cast(layout->getAxis()); - ImGui::Text("Axis"); - auto updateAxis = false; - updateAxis |= ImGui::RadioButton("Row", &axis, static_cast(Axis::Row)); + updateScaling |= ImGui::RadioButton( + "Scale Down##mainscale1", &axisScaling, static_cast(AxisScaling::ScaleDown) + ); ImGui::SameLine(); - updateAxis |= ImGui::RadioButton("Column", &axis, static_cast(Axis::Column)); - if (updateAxis) { - if (layout->getAxis() != static_cast(axis)) { - node->setContentSize({ - node->getContentSize().height, - node->getContentSize().width - }); - } - layout->setAxis(static_cast(axis)); + updateScaling |= ImGui::RadioButton( + "Scale##mainscale2", &axisScaling, static_cast(AxisScaling::Scale) + ); + ImGui::SameLine(); + updateScaling |= ImGui::RadioButton( + "Grow##mainscale3", &axisScaling, static_cast(AxisScaling::Grow) + ); + ImGui::SameLine(); + updateScaling |= ImGui::RadioButton( + "Fit##mainscale4", &axisScaling, static_cast(AxisScaling::Fit) + ); + ImGui::SameLine(); + updateScaling |= ImGui::RadioButton( + "Scale Down Gaps##mainscale5", &axisScaling, static_cast(AxisScaling::ScaleDownGaps) + ); + if (updateScaling) { + layout->setMainAxisScaling(static_cast(axisScaling)); updateLayout = true; } - { - auto axisScaling = static_cast(layout->getMainAxisScaling()); - ImGui::Text("Main Axis Scaling"); - bool updateScaling = false; - updateScaling |= ImGui::RadioButton( - "None##mainscale0", &axisScaling, static_cast(AxisScaling::None) - ); - ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Scale Down##mainscale1", &axisScaling, static_cast(AxisScaling::ScaleDown) - ); - ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Scale##mainscale2", &axisScaling, static_cast(AxisScaling::Scale) - ); - ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Grow##mainscale3", &axisScaling, static_cast(AxisScaling::Grow) - ); - ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Fit##mainscale4", &axisScaling, static_cast(AxisScaling::Fit) - ); - ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Scale Down Gaps##mainscale5", &axisScaling, static_cast(AxisScaling::ScaleDownGaps) - ); - if (updateScaling) { - layout->setMainAxisScaling(static_cast(axisScaling)); - updateLayout = true; - } - } - { - auto axisScaling = static_cast(layout->getCrossAxisScaling()); - ImGui::Text("Cross Axis Scaling"); - bool updateScaling = false; - updateScaling |= ImGui::RadioButton( - "None##crossscale0", &axisScaling, static_cast(AxisScaling::None) - ); - ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Scale Down##crossscale1", &axisScaling, static_cast(AxisScaling::ScaleDown) - ); - ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Scale##crossscale2", &axisScaling, static_cast(AxisScaling::Scale) - ); - ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Grow##crossscale3", &axisScaling, static_cast(AxisScaling::Grow) - ); - ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Fit##crossscale4", &axisScaling, static_cast(AxisScaling::Fit) - ); - ImGui::SameLine(); - updateScaling |= ImGui::RadioButton( - "Scale Down Gaps##crossscale5", &axisScaling, static_cast(AxisScaling::ScaleDownGaps) - ); - if (updateScaling) { - layout->setCrossAxisScaling(static_cast(axisScaling)); - updateLayout = true; - } + } + { + auto axisScaling = static_cast(layout->getCrossAxisScaling()); + ImGui::Text("Cross Axis Scaling"); + bool updateScaling = false; + updateScaling |= ImGui::RadioButton( + "None##crossscale0", &axisScaling, static_cast(AxisScaling::None) + ); + ImGui::SameLine(); + updateScaling |= ImGui::RadioButton( + "Scale Down##crossscale1", &axisScaling, static_cast(AxisScaling::ScaleDown) + ); + ImGui::SameLine(); + updateScaling |= ImGui::RadioButton( + "Scale##crossscale2", &axisScaling, static_cast(AxisScaling::Scale) + ); + ImGui::SameLine(); + updateScaling |= ImGui::RadioButton( + "Grow##crossscale3", &axisScaling, static_cast(AxisScaling::Grow) + ); + ImGui::SameLine(); + updateScaling |= ImGui::RadioButton( + "Fit##crossscale4", &axisScaling, static_cast(AxisScaling::Fit) + ); + ImGui::SameLine(); + updateScaling |= ImGui::RadioButton( + "Scale Down Gaps##crossscale5", &axisScaling, static_cast(AxisScaling::ScaleDownGaps) + ); + if (updateScaling) { + layout->setCrossAxisScaling(static_cast(axisScaling)); + updateLayout = true; } - { - auto align = static_cast(layout->getMainAxisAlignment()); - ImGui::Text("Main Axis Alignment"); - bool updateAlign = false; - updateAlign |= ImGui::RadioButton( - "Start##mainalign0", &align, static_cast(MainAxisAlignment::Start) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Center##mainalign1", &align, static_cast(MainAxisAlignment::Center) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "End##mainalign2", &align, static_cast(MainAxisAlignment::End) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Even##mainalign3", &align, static_cast(MainAxisAlignment::Even) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Between##mainalign4", &align, static_cast(MainAxisAlignment::Between) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Around##mainalign5", &align, static_cast(MainAxisAlignment::Around) - ); - if (updateAlign) { - layout->setMainAxisAlignment(static_cast(align)); - updateLayout = true; - } + } + { + auto align = static_cast(layout->getMainAxisAlignment()); + ImGui::Text("Main Axis Alignment"); + bool updateAlign = false; + updateAlign |= ImGui::RadioButton( + "Start##mainalign0", &align, static_cast(MainAxisAlignment::Start) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Center##mainalign1", &align, static_cast(MainAxisAlignment::Center) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "End##mainalign2", &align, static_cast(MainAxisAlignment::End) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Even##mainalign3", &align, static_cast(MainAxisAlignment::Even) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Between##mainalign4", &align, static_cast(MainAxisAlignment::Between) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Around##mainalign5", &align, static_cast(MainAxisAlignment::Around) + ); + if (updateAlign) { + layout->setMainAxisAlignment(static_cast(align)); + updateLayout = true; } - { - auto align = static_cast(layout->getCrossAxisAlignment()); - ImGui::Text("Cross Axis Alignment"); - bool updateAlign = false; - updateAlign |= ImGui::RadioButton( - "Start##crossalign0", &align, static_cast(CrossAxisAlignment::Start) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Center##crossalign1", &align, static_cast(CrossAxisAlignment::Center) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "End##crossalign2", &align, static_cast(CrossAxisAlignment::End) - ); - if (updateAlign) { - layout->setCrossAxisAlignment(static_cast(align)); - updateLayout = true; - } + } + { + auto align = static_cast(layout->getCrossAxisAlignment()); + ImGui::Text("Cross Axis Alignment"); + bool updateAlign = false; + updateAlign |= ImGui::RadioButton( + "Start##crossalign0", &align, static_cast(CrossAxisAlignment::Start) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Center##crossalign1", &align, static_cast(CrossAxisAlignment::Center) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "End##crossalign2", &align, static_cast(CrossAxisAlignment::End) + ); + if (updateAlign) { + layout->setCrossAxisAlignment(static_cast(align)); + updateLayout = true; } + } - std::string axisDirection = axis ? "Bottom to Top" : "Left to Right"; - std::string secondAxisDirection = axis ? "Top to Bottom" : "Right to Left"; + std::string axisDirection = axis ? "Bottom to Top" : "Left to Right"; + std::string secondAxisDirection = axis ? "Top to Bottom" : "Right to Left"; - std::string crossAxisDirection = !axis ? "Bottom to Top" : "Left to Right"; - std::string secondcrossAxisDirection = !axis ? "Top to Bottom" : "Right to Left"; - { - auto direction = static_cast(layout->getMainAxisDirection()); - ImGui::Text("Main Axis Direction"); - bool updateDirection = false; - - updateDirection |= ImGui::RadioButton( - axisDirection.c_str(), &direction, static_cast(AxisDirection::FrontToBack) - ); - ImGui::SameLine(); - updateDirection |= ImGui::RadioButton( - secondAxisDirection.c_str(), &direction, static_cast(AxisDirection::BackToFront) - ); - if (updateDirection) { - layout->setMainAxisDirection(static_cast(direction)); - updateLayout = true; - } - } - { - auto direction = static_cast(layout->getCrossAxisDirection()); - ImGui::Text("Cross Axis Direction"); - bool updateDirection = false; - updateDirection |= ImGui::RadioButton( - crossAxisDirection.c_str(), &direction, static_cast(AxisDirection::FrontToBack) - ); - ImGui::SameLine(); - updateDirection |= ImGui::RadioButton( - secondcrossAxisDirection.c_str(), &direction, static_cast(AxisDirection::BackToFront) - ); - if (updateDirection) { - layout->setCrossAxisDirection(static_cast(direction)); - updateLayout = true; - } - } - - auto gap = layout->getGap(); - if (ImGui::DragFloat("Gap", &gap)) { - layout->setGap(gap); + std::string crossAxisDirection = !axis ? "Bottom to Top" : "Left to Right"; + std::string secondcrossAxisDirection = !axis ? "Top to Bottom" : "Right to Left"; + { + auto direction = static_cast(layout->getMainAxisDirection()); + ImGui::Text("Main Axis Direction"); + bool updateDirection = false; + + updateDirection |= ImGui::RadioButton( + axisDirection.c_str(), &direction, static_cast(AxisDirection::FrontToBack) + ); + ImGui::SameLine(); + updateDirection |= ImGui::RadioButton( + secondAxisDirection.c_str(), &direction, static_cast(AxisDirection::BackToFront) + ); + if (updateDirection) { + layout->setMainAxisDirection(static_cast(direction)); updateLayout = true; } - - auto ignoreInvisibleChildren = layout->isIgnoreInvisibleChildren(); - if (ImGui::Checkbox("Ignore Invisible Children", &ignoreInvisibleChildren)) { - layout->ignoreInvisibleChildren(ignoreInvisibleChildren); + } + { + auto direction = static_cast(layout->getCrossAxisDirection()); + ImGui::Text("Cross Axis Direction"); + bool updateDirection = false; + updateDirection |= ImGui::RadioButton( + crossAxisDirection.c_str(), &direction, static_cast(AxisDirection::FrontToBack) + ); + ImGui::SameLine(); + updateDirection |= ImGui::RadioButton( + secondcrossAxisDirection.c_str(), &direction, static_cast(AxisDirection::BackToFront) + ); + if (updateDirection) { + layout->setCrossAxisDirection(static_cast(direction)); updateLayout = true; } + } - auto minRelativeScaleOpt = layout->getMinRelativeScale(); - float minRelativeScale = minRelativeScaleOpt.value_or(0); - bool hasMinRelativeScale = minRelativeScaleOpt.has_value(); + auto gap = layout->getGap(); + if (ImGui::DragFloat("Gap", &gap)) { + layout->setGap(gap); + updateLayout = true; + } + + auto ignoreInvisibleChildren = layout->isIgnoreInvisibleChildren(); + if (ImGui::Checkbox("Ignore Invisible Children", &ignoreInvisibleChildren)) { + layout->ignoreInvisibleChildren(ignoreInvisibleChildren); + updateLayout = true; + } - if (ImGui::Checkbox("Has Min Relative Scale", &hasMinRelativeScale)) { - if (hasMinRelativeScale) { - layout->setMinRelativeScale(0); - } - else { - layout->setMinRelativeScale(std::nullopt); - } - updateLayout = true; - } + auto minRelativeScaleOpt = layout->getMinRelativeScale(); + float minRelativeScale = minRelativeScaleOpt.value_or(0); + bool hasMinRelativeScale = minRelativeScaleOpt.has_value(); + + if (ImGui::Checkbox("Has Min Relative Scale", &hasMinRelativeScale)) { if (hasMinRelativeScale) { - if (ImGui::DragFloat("Min Relative Scale", &minRelativeScale)) { - - layout->setMinRelativeScale(minRelativeScale); - updateLayout = true; - - } + layout->setMinRelativeScale(0); } - - auto maxRelativeScaleOpt = layout->getMaxRelativeScale(); - float maxRelativeScale = maxRelativeScaleOpt.value_or(0); - bool hasMaxRelativeScale = maxRelativeScaleOpt.has_value(); - if (ImGui::Checkbox("Has Max Relative Scale", &hasMaxRelativeScale)) { - if (hasMaxRelativeScale) { - layout->setMaxRelativeScale(0); - } - else { - layout->setMaxRelativeScale(std::nullopt); - } + else { + layout->setMinRelativeScale(std::nullopt); + } + updateLayout = true; + } + if (hasMinRelativeScale) { + if (ImGui::DragFloat("Min Relative Scale", &minRelativeScale)) { + + layout->setMinRelativeScale(minRelativeScale); updateLayout = true; + } + } + auto maxRelativeScaleOpt = layout->getMaxRelativeScale(); + float maxRelativeScale = maxRelativeScaleOpt.value_or(0); + bool hasMaxRelativeScale = maxRelativeScaleOpt.has_value(); + if (ImGui::Checkbox("Has Max Relative Scale", &hasMaxRelativeScale)) { if (hasMaxRelativeScale) { - if (ImGui::DragFloat("Max Relative Scale", &maxRelativeScale)) { - layout->setMaxRelativeScale(maxRelativeScale); - updateLayout = true; - } + layout->setMaxRelativeScale(0); } - - if (updateLayout) { - node->updateLayout(); + else { + layout->setMaxRelativeScale(std::nullopt); } + updateLayout = true; } - if (auto layout = typeinfo_cast(rawLayout)) { - bool updateLayout = false; - - auto axis = static_cast(layout->getAxis()); - ImGui::Text("Axis"); - auto updateAxis = false; - updateAxis |= ImGui::RadioButton("Row", &axis, static_cast(Axis::Row)); - ImGui::SameLine(); - updateAxis |= ImGui::RadioButton("Column", &axis, static_cast(Axis::Column)); - if (updateAxis) { - if (layout->getAxis() != static_cast(axis)) { - node->setContentSize({ - node->getContentSize().height, - node->getContentSize().width - }); - } - layout->setAxis(static_cast(axis)); - updateLayout = true; - } - auto axisReverse = layout->getAxisReverse(); - if (ImGui::Checkbox("Flip Axis Direction", &axisReverse)) { - layout->setAxisReverse(axisReverse); - updateLayout = true; - } - axisReverse = layout->getCrossAxisReverse(); - if (ImGui::Checkbox("Flip Cross Axis Direction", &axisReverse)) { - layout->setCrossAxisReverse(axisReverse); + if (hasMaxRelativeScale) { + if (ImGui::DragFloat("Max Relative Scale", &maxRelativeScale)) { + layout->setMaxRelativeScale(maxRelativeScale); updateLayout = true; } + } - { - auto align = static_cast(layout->getAxisAlignment()); - ImGui::Text("Axis Alignment"); - bool updateAlign = false; - updateAlign |= ImGui::RadioButton( - "Start##axisalign0", &align, static_cast(AxisAlignment::Start) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Center##axisalign1", &align, static_cast(AxisAlignment::Center) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "End##axisalign2", &align, static_cast(AxisAlignment::End) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Even##axisalign3", &align, static_cast(AxisAlignment::Even) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Between##axisalign4", &align, static_cast(AxisAlignment::Between) - ); - if (updateAlign) { - layout->setAxisAlignment(static_cast(align)); - updateLayout = true; - } - } + if (updateLayout) { + node->updateLayout(); + } + } + if (auto layout = typeinfo_cast(rawLayout)) { + bool updateLayout = false; - { - auto align = static_cast(layout->getCrossAxisAlignment()); - ImGui::Text("Cross Axis Alignment"); - bool updateAlign = false; - updateAlign |= ImGui::RadioButton( - "Start##cross0", &align, static_cast(AxisAlignment::Start) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Center##cross1", &align, static_cast(AxisAlignment::Center) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "End##cross2", &align, static_cast(AxisAlignment::End) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Even##cross3", &align, static_cast(AxisAlignment::Even) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Between##cross4", &align, static_cast(AxisAlignment::Between) - ); - if (updateAlign) { - layout->setCrossAxisAlignment(static_cast(align)); - updateLayout = true; - } + auto axis = static_cast(layout->getAxis()); + ImGui::Text("Axis"); + auto updateAxis = false; + updateAxis |= ImGui::RadioButton("Row", &axis, static_cast(Axis::Row)); + ImGui::SameLine(); + updateAxis |= ImGui::RadioButton("Column", &axis, static_cast(Axis::Column)); + if (updateAxis) { + if (layout->getAxis() != static_cast(axis)) { + node->setContentSize({ + node->getContentSize().height, + node->getContentSize().width + }); } + layout->setAxis(static_cast(axis)); + updateLayout = true; + } - { - auto align = static_cast(layout->getCrossAxisLineAlignment()); - ImGui::Text("Cross Axis Line Alignment"); - bool updateAlign = false; - updateAlign |= ImGui::RadioButton( - "Start##crossline0", &align, static_cast(AxisAlignment::Start) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Center##crossline1", &align, static_cast(AxisAlignment::Center) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "End##crossline2", &align, static_cast(AxisAlignment::End) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Even##crossline3", &align, static_cast(AxisAlignment::Even) - ); - ImGui::SameLine(); - updateAlign |= ImGui::RadioButton( - "Between##crossline4", &align, static_cast(AxisAlignment::Between) - ); - if (updateAlign) { - layout->setCrossAxisLineAlignment(static_cast(align)); - updateLayout = true; - } - } + auto axisReverse = layout->getAxisReverse(); + if (ImGui::Checkbox("Flip Axis Direction", &axisReverse)) { + layout->setAxisReverse(axisReverse); + updateLayout = true; + } + axisReverse = layout->getCrossAxisReverse(); + if (ImGui::Checkbox("Flip Cross Axis Direction", &axisReverse)) { + layout->setCrossAxisReverse(axisReverse); + updateLayout = true; + } - auto gap = layout->getGap(); - if (ImGui::DragFloat("Gap", &gap)) { - layout->setGap(gap); + { + auto align = static_cast(layout->getAxisAlignment()); + ImGui::Text("Axis Alignment"); + bool updateAlign = false; + updateAlign |= ImGui::RadioButton( + "Start##axisalign0", &align, static_cast(AxisAlignment::Start) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Center##axisalign1", &align, static_cast(AxisAlignment::Center) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "End##axisalign2", &align, static_cast(AxisAlignment::End) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Even##axisalign3", &align, static_cast(AxisAlignment::Even) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Between##axisalign4", &align, static_cast(AxisAlignment::Between) + ); + if (updateAlign) { + layout->setAxisAlignment(static_cast(align)); updateLayout = true; } + } - auto ignoreInvisibleChildren = layout->isIgnoreInvisibleChildren(); - if (ImGui::Checkbox("Ignore Invisible Children", &ignoreInvisibleChildren)) { - layout->ignoreInvisibleChildren(ignoreInvisibleChildren); + { + auto align = static_cast(layout->getCrossAxisAlignment()); + ImGui::Text("Cross Axis Alignment"); + bool updateAlign = false; + updateAlign |= ImGui::RadioButton( + "Start##cross0", &align, static_cast(AxisAlignment::Start) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Center##cross1", &align, static_cast(AxisAlignment::Center) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "End##cross2", &align, static_cast(AxisAlignment::End) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Even##cross3", &align, static_cast(AxisAlignment::Even) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Between##cross4", &align, static_cast(AxisAlignment::Between) + ); + if (updateAlign) { + layout->setCrossAxisAlignment(static_cast(align)); updateLayout = true; } + } - auto autoScale = layout->getAutoScale(); - if (ImGui::Checkbox("Auto Scale", &autoScale)) { - layout->setAutoScale(autoScale); + { + auto align = static_cast(layout->getCrossAxisLineAlignment()); + ImGui::Text("Cross Axis Line Alignment"); + bool updateAlign = false; + updateAlign |= ImGui::RadioButton( + "Start##crossline0", &align, static_cast(AxisAlignment::Start) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Center##crossline1", &align, static_cast(AxisAlignment::Center) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "End##crossline2", &align, static_cast(AxisAlignment::End) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Even##crossline3", &align, static_cast(AxisAlignment::Even) + ); + ImGui::SameLine(); + updateAlign |= ImGui::RadioButton( + "Between##crossline4", &align, static_cast(AxisAlignment::Between) + ); + if (updateAlign) { + layout->setCrossAxisLineAlignment(static_cast(align)); updateLayout = true; } + } - auto grow = layout->getGrowCrossAxis(); - if (ImGui::Checkbox("Grow Cross Axis", &grow)) { - layout->setGrowCrossAxis(grow); - updateLayout = true; - } + auto gap = layout->getGap(); + if (ImGui::DragFloat("Gap", &gap)) { + layout->setGap(gap); + updateLayout = true; + } - auto overflow = layout->getCrossAxisOverflow(); - if (ImGui::Checkbox("Allow Cross Axis Overflow", &overflow)) { - layout->setCrossAxisOverflow(overflow); - updateLayout = true; - } + auto ignoreInvisibleChildren = layout->isIgnoreInvisibleChildren(); + if (ImGui::Checkbox("Ignore Invisible Children", &ignoreInvisibleChildren)) { + layout->ignoreInvisibleChildren(ignoreInvisibleChildren); + updateLayout = true; + } - auto maxAutoGrowAxisOpt = layout->getAutoGrowAxis(); - float autoGrowAxis = maxAutoGrowAxisOpt.value_or(0); - bool hasAutoGrowAxis = maxAutoGrowAxisOpt.has_value(); - if (ImGui::Checkbox("Has Auto Grow Axis", &hasAutoGrowAxis)) { - if (hasAutoGrowAxis) { - layout->setAutoGrowAxis(0); - } - else { - layout->setAutoGrowAxis(std::nullopt); - } - updateLayout = true; - } + auto autoScale = layout->getAutoScale(); + if (ImGui::Checkbox("Auto Scale", &autoScale)) { + layout->setAutoScale(autoScale); + updateLayout = true; + } + + auto grow = layout->getGrowCrossAxis(); + if (ImGui::Checkbox("Grow Cross Axis", &grow)) { + layout->setGrowCrossAxis(grow); + updateLayout = true; + } + + auto overflow = layout->getCrossAxisOverflow(); + if (ImGui::Checkbox("Allow Cross Axis Overflow", &overflow)) { + layout->setCrossAxisOverflow(overflow); + updateLayout = true; + } + auto maxAutoGrowAxisOpt = layout->getAutoGrowAxis(); + float autoGrowAxis = maxAutoGrowAxisOpt.value_or(0); + bool hasAutoGrowAxis = maxAutoGrowAxisOpt.has_value(); + if (ImGui::Checkbox("Has Auto Grow Axis", &hasAutoGrowAxis)) { if (hasAutoGrowAxis) { - if (ImGui::DragFloat("Auto Grow Axis", &autoGrowAxis)) { - layout->setAutoGrowAxis(autoGrowAxis); - updateLayout = true; - } + layout->setAutoGrowAxis(0); } - - if (updateLayout) { - node->updateLayout(); + else { + layout->setAutoGrowAxis(std::nullopt); } + updateLayout = true; } - } - else { - if (ImGui::Button(U8STR(FEATHER_PLUS " Add SimpleAxisLayout"))) { - node->setLayout(SimpleAxisLayout::create(Axis::Row)); - } - if (ImGui::Button(U8STR(FEATHER_PLUS " Add AxisLayout"))) { - node->setLayout(AxisLayout::create()); + + if (hasAutoGrowAxis) { + if (ImGui::DragFloat("Auto Grow Axis", &autoGrowAxis)) { + layout->setAutoGrowAxis(autoGrowAxis); + updateLayout = true; + } } - if (ImGui::Button(U8STR(FEATHER_PLUS " Add AnchorLayout"))) { - node->setLayout(AnchorLayout::create()); + + if (updateLayout) { + node->updateLayout(); } } - }(); + } + else { + if (ImGui::Button(U8STR(FEATHER_PLUS " Add SimpleAxisLayout"))) { + node->setLayout(SimpleAxisLayout::create(Axis::Row)); + } + if (ImGui::Button(U8STR(FEATHER_PLUS " Add AxisLayout"))) { + node->setLayout(AxisLayout::create()); + } + if (ImGui::Button(U8STR(FEATHER_PLUS " Add AnchorLayout"))) { + node->setLayout(AnchorLayout::create()); + } + } } void DevTools::drawAttributes() {