mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-27 01:45:35 -05:00
add SpacerNode & bring back Dispatch
This commit is contained in:
parent
c1d4a89f8b
commit
b44b5d3cd3
5 changed files with 176 additions and 35 deletions
|
@ -23,7 +23,7 @@ class CCNode;
|
||||||
*/
|
*/
|
||||||
class GEODE_DLL Layout : public CCObject {
|
class GEODE_DLL Layout : public CCObject {
|
||||||
protected:
|
protected:
|
||||||
CCArray* getNodesToPosition(CCNode* forNode);
|
CCArray* getNodesToPosition(CCNode* forNode) const;
|
||||||
|
|
||||||
bool m_ignoreInvisibleChildren = false;
|
bool m_ignoreInvisibleChildren = false;
|
||||||
|
|
||||||
|
@ -37,6 +37,11 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void apply(CCNode* on) = 0;
|
virtual void apply(CCNode* on) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get how much space this layout would like to take up for a given target
|
||||||
|
*/
|
||||||
|
virtual CCSize getSizeHint(CCNode* on) const = 0;
|
||||||
|
|
||||||
void ignoreInvisibleChildren(bool ignore);
|
void ignoreInvisibleChildren(bool ignore);
|
||||||
bool isIgnoreInvisibleChildren() const;
|
bool isIgnoreInvisibleChildren() const;
|
||||||
|
|
||||||
|
@ -262,6 +267,7 @@ public:
|
||||||
static AxisLayout* create(Axis axis = Axis::Row);
|
static AxisLayout* create(Axis axis = Axis::Row);
|
||||||
|
|
||||||
void apply(CCNode* on) override;
|
void apply(CCNode* on) override;
|
||||||
|
CCSize getSizeHint(CCNode* on) const override;
|
||||||
|
|
||||||
Axis getAxis() const;
|
Axis getAxis() const;
|
||||||
AxisAlignment getAxisAlignment() const;
|
AxisAlignment getAxisAlignment() const;
|
||||||
|
|
59
loader/include/Geode/cocos/base_nodes/SpacerNode.hpp
vendored
Normal file
59
loader/include/Geode/cocos/base_nodes/SpacerNode.hpp
vendored
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CCNode.h"
|
||||||
|
|
||||||
|
NS_CC_BEGIN
|
||||||
|
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable: 4275)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A node for controlling spacing in Layouts. When a Layout is applied, if
|
||||||
|
* space is left over, the remaining space is divided among all SpacerNodes in
|
||||||
|
* the Layout. The space each node gets is the proprotion between its growth
|
||||||
|
* factor and the sum of all the SpacerNodes' growth factors in the Layout
|
||||||
|
* @example
|
||||||
|
* node->addChild(SpacerNode::create(1));
|
||||||
|
* node->addChild(SpacerNode::create(2));
|
||||||
|
* node->addChild(SpacerNode::create(1));
|
||||||
|
* node->updateLayout();
|
||||||
|
* // Total SpacerNode growth sum is 1 + 2 + 1 = 4
|
||||||
|
* // So s1 and s3 get 1/4 of the remaining space and s2 gets 2/4
|
||||||
|
* @note If you want to specify a minimum width for a SpacerNode, add
|
||||||
|
* AxisLayoutOptions for it and use setLength
|
||||||
|
*/
|
||||||
|
class GEODE_DLL SpacerNode : public CCNode {
|
||||||
|
protected:
|
||||||
|
size_t m_grow;
|
||||||
|
|
||||||
|
bool init(size_t grow);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Create a new spacer node. When the layout is applied,
|
||||||
|
* if there is space left over the remaining space is distributed among
|
||||||
|
* all spacer nodes in proportion to the sum of all the spacers' grow
|
||||||
|
* factors (akin to CSS flew grow)
|
||||||
|
* @param grow The grow factor for this node. Default is 1
|
||||||
|
*/
|
||||||
|
static SpacerNode* create(size_t grow = 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the grow factor for this spacer node. When the layout is applied,
|
||||||
|
* if there is space left over the remaining space is distributed among
|
||||||
|
* all spacer nodes in proportion to the sum of all the spacers' grow
|
||||||
|
* factors (akin to CSS flew grow)
|
||||||
|
* @param grow The new grow factor for this node. Default is 1
|
||||||
|
* @note Make sure to call updateLayout on the spacer's parent afterwards
|
||||||
|
*/
|
||||||
|
void setGrow(size_t grow);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the grow factor for this spacer node
|
||||||
|
*/
|
||||||
|
size_t getGrow() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma warning(pop)
|
||||||
|
|
||||||
|
NS_CC_END
|
1
loader/include/Geode/cocos/include/cocos2d.h
vendored
1
loader/include/Geode/cocos/include/cocos2d.h
vendored
|
@ -59,6 +59,7 @@ THE SOFTWARE.
|
||||||
// base_nodes
|
// base_nodes
|
||||||
#include "../base_nodes/CCNode.h"
|
#include "../base_nodes/CCNode.h"
|
||||||
#include "../base_nodes/CCAtlasNode.h"
|
#include "../base_nodes/CCAtlasNode.h"
|
||||||
|
#include "../base_nodes/SpacerNode.hpp"
|
||||||
|
|
||||||
// cocoa
|
// cocoa
|
||||||
#include "../cocoa/CCAffineTransform.h"
|
#include "../cocoa/CCAffineTransform.h"
|
||||||
|
|
|
@ -9,42 +9,41 @@
|
||||||
namespace geode {
|
namespace geode {
|
||||||
// Mod interoperability
|
// Mod interoperability
|
||||||
|
|
||||||
// todo: update to new event system
|
template <class... Args>
|
||||||
|
class DispatchEvent : public Event {
|
||||||
|
protected:
|
||||||
|
std::string m_id;
|
||||||
|
std::tuple<Args...> m_args;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DispatchEvent(std::string const& id, Args&&... args)
|
||||||
|
: m_id(id), m_args(std::make_tuple(args...)) {}
|
||||||
|
|
||||||
|
std::tuple<Args...> getArgs() const {
|
||||||
|
return m_args;
|
||||||
|
}
|
||||||
|
|
||||||
// template <typename... Args>
|
std::string getID() const {
|
||||||
// class DispatchEvent : public Event {
|
return m_id;
|
||||||
// std::string m_selector;
|
}
|
||||||
// std::tuple<Args...> m_args;
|
};
|
||||||
|
|
||||||
// public:
|
template <class... Args>
|
||||||
// DispatchEvent(std::string const& name, Args... args) :
|
class DispatchFilter : public EventFilter<DispatchEvent<Args...>> {
|
||||||
// m_selector(name), m_args(std::make_tuple(args...)) {}
|
protected:
|
||||||
|
std::string m_id;
|
||||||
|
|
||||||
// std::string const& selector() {
|
public:
|
||||||
// return m_selector;
|
using Ev = DispatchEvent<Args...>;
|
||||||
// }
|
using Callback = ListenerResult(Args...);
|
||||||
// };
|
|
||||||
|
|
||||||
// template <typename... Args>
|
ListenerResult handle(utils::MiniFunction<Callback> fn, Ev* event) {
|
||||||
// class DispatchHandler : public EventHandler<DispatchEvent<Args...>> {
|
if (event->getID() == m_id) {
|
||||||
// std::string m_selector;
|
return std::apply(fn, event->getArgs());
|
||||||
// utils::MiniFunction<void(Args...)> m_callback;
|
}
|
||||||
|
return ListenerResult::Propagate;
|
||||||
|
}
|
||||||
|
|
||||||
// DispatchHandler(std::string const& name, utils::MiniFunction<void(Args...)> callback) :
|
DispatchFilter(std::string const& id) : m_id(id) {}
|
||||||
// m_selector(name), m_callback(callback) {}
|
};
|
||||||
|
|
||||||
// public:
|
|
||||||
// bool handle(DispatchEvent<Args...>* ev) {
|
|
||||||
// if (ev->name() == m_selector) {
|
|
||||||
// std::apply(m_callback, ev->m_args);
|
|
||||||
// }
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// static DispatchHandler* create(
|
|
||||||
// std::string const& name, utils::MiniFunction<void(Args...)> callback
|
|
||||||
// ) {
|
|
||||||
// return new DispatchHandler(name, callback);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
}
|
}
|
|
@ -50,7 +50,7 @@ bool CCNode::hasAncestor(CCNode* ancestor) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CCArray* Layout::getNodesToPosition(CCNode* on) {
|
CCArray* Layout::getNodesToPosition(CCNode* on) const {
|
||||||
auto arr = CCArray::create();
|
auto arr = CCArray::create();
|
||||||
for (auto child : CCArrayExt<CCNode>(on->getChildren())) {
|
for (auto child : CCArrayExt<CCNode>(on->getChildren())) {
|
||||||
if (!m_ignoreInvisibleChildren || child->isVisible()) {
|
if (!m_ignoreInvisibleChildren || child->isVisible()) {
|
||||||
|
@ -176,6 +176,32 @@ struct AxisLayout::Row : public CCObject {
|
||||||
{
|
{
|
||||||
this->autorelease();
|
this->autorelease();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void accountSpacers(Axis axis, float availableLength) {
|
||||||
|
std::vector<SpacerNode*> spacers;
|
||||||
|
for (auto& node : CCArrayExt<CCNode>(nodes)) {
|
||||||
|
if (auto spacer = typeinfo_cast<SpacerNode*>(node)) {
|
||||||
|
spacers.push_back(spacer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (spacers.size()) {
|
||||||
|
auto unusedSpace = availableLength - this->axisLength;
|
||||||
|
size_t sum = 0;
|
||||||
|
for (auto& spacer : spacers) {
|
||||||
|
sum += spacer->getGrow();
|
||||||
|
}
|
||||||
|
for (auto& spacer : spacers) {
|
||||||
|
auto size = unusedSpace * spacer->getGrow() / static_cast<float>(sum);
|
||||||
|
if (axis == Axis::Row) {
|
||||||
|
spacer->setContentSize({ size, this->crossLength });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
spacer->setContentSize({ this->crossLength, size });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->axisLength = availableLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AxisPosition {
|
struct AxisPosition {
|
||||||
|
@ -195,6 +221,9 @@ static AxisPosition nodeAxis(CCNode* node, Axis axis, float scale) {
|
||||||
if (auto toggle = typeinfo_cast<CCMenuItemToggler*>(node)) {
|
if (auto toggle = typeinfo_cast<CCMenuItemToggler*>(node)) {
|
||||||
scaledSize = toggle->m_offButton->getScaledContentSize();
|
scaledSize = toggle->m_offButton->getScaledContentSize();
|
||||||
}
|
}
|
||||||
|
if (auto spacer = typeinfo_cast<SpacerNode*>(node)) {
|
||||||
|
scaledSize = CCSizeZero;
|
||||||
|
}
|
||||||
auto anchor = node->getAnchorPoint();
|
auto anchor = node->getAnchorPoint();
|
||||||
if (axis == Axis::Row) {
|
if (axis == Axis::Row) {
|
||||||
return AxisPosition {
|
return AxisPosition {
|
||||||
|
@ -611,6 +640,8 @@ void AxisLayout::tryFitLayout(
|
||||||
float rowEvenSpace = available.crossLength / rows->count();
|
float rowEvenSpace = available.crossLength / rows->count();
|
||||||
|
|
||||||
for (auto row : CCArrayExt<Row*>(rows)) {
|
for (auto row : CCArrayExt<Row*>(rows)) {
|
||||||
|
row->accountSpacers(m_axis, available.axisLength);
|
||||||
|
|
||||||
if (m_crossAlignment == AxisAlignment::Even) {
|
if (m_crossAlignment == AxisAlignment::Even) {
|
||||||
rowCrossPos -= rowEvenSpace / 2 + row->crossLength / 2;
|
rowCrossPos -= rowEvenSpace / 2 + row->crossLength / 2;
|
||||||
}
|
}
|
||||||
|
@ -756,6 +787,24 @@ void AxisLayout::apply(CCNode* on) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CCSize AxisLayout::getSizeHint(CCNode* on) const {
|
||||||
|
// Ideal is single row / column with no scaling
|
||||||
|
auto nodes = getNodesToPosition(on);
|
||||||
|
float length = 0.f;
|
||||||
|
float cross = 0.f;
|
||||||
|
for (auto& node : CCArrayExt<CCNode*>(nodes)) {
|
||||||
|
auto axis = nodeAxis(node, m_axis, 1.f);
|
||||||
|
length += axis.axisLength;
|
||||||
|
cross += axis.crossLength;
|
||||||
|
}
|
||||||
|
if (m_axis == Axis::Row) {
|
||||||
|
return { length, cross };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return { cross, length };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AxisLayout::AxisLayout(Axis axis) : m_axis(axis) {}
|
AxisLayout::AxisLayout(Axis axis) : m_axis(axis) {}
|
||||||
|
|
||||||
Axis AxisLayout::getAxis() const {
|
Axis AxisLayout::getAxis() const {
|
||||||
|
@ -969,3 +1018,30 @@ AxisLayoutOptions* AxisLayoutOptions::setScalePriority(int priority) {
|
||||||
m_scalePriority = priority;
|
m_scalePriority = priority;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SpacerNode::init(size_t grow) {
|
||||||
|
if (!CCNode::init())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_grow = grow;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpacerNode* SpacerNode::create(size_t grow) {
|
||||||
|
auto ret = new SpacerNode;
|
||||||
|
if (ret && ret->init(grow)) {
|
||||||
|
ret->autorelease();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
CC_SAFE_DELETE(ret);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpacerNode::setGrow(size_t grow) {
|
||||||
|
m_grow = grow;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t SpacerNode::getGrow() const {
|
||||||
|
return m_grow;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue