To use the node in your project you should have the bitrex/xod-menu-system-11 library installed. Use the “File → Add Library” menu item in XOD IDE if you don’t have it yet. See Using libraries for more info.
C++ implementation
#pragma XOD dirtiness disable
namespace menu_base = ____menu_base;
using menu_base_t = menu_base::MenuBase;
/* A derived type of BiDirectionalListView, used to concatenate two
bi-directional lists and iterate forward and backwards over both
as a single unit. This can also be instantiated recursively. See
e.g. the XOD standard library class "ConcatListView"*/
template <typename T>
class BiDirectionalConcatListView : public menu_base::BiDirectionalListView<T> {
public:
class Cursor : public menu_base::BiDirectionalCursor<T> {
public:
Cursor(const BiDirectionalConcatListView<T>* owner)
: _left(std::move(owner->_left.biterate())),
_right(std::move(owner->_right.biterate())),
_owner(owner) {}
bool isValid() const override { return _left && _right; }
bool value(T* out) const override {
return _cursor < _owner->_length_left ? _left.value(out) : _right.value(out);
}
void next() override {
const auto total = _owner->_length_left + _owner->_length_right;
if (_cursor < _owner->_length_left - 1) {
++_left;
} else if (_cursor >= _owner->_length_left - 1 && _cursor < total) {
if (_cursor != _owner->_length_left - 1) {
++_right;
}
}
++_cursor;
}
void prev() override {
const auto total = _owner->_length_left + _owner->_length_right;
if (_cursor > _owner->_length_left - 1 && _cursor != total - _owner->_length_right) {
--_right;
} else if (_cursor <= _owner->_length_left - 1) {
--_left;
}
if (_cursor) {
--_cursor;
}
}
private:
menu_base::BiDirectionalIterator<T> _left;
menu_base::BiDirectionalIterator<T> _right;
const BiDirectionalConcatListView<T>* _owner;
size_t _cursor = 0;
};
public:
BiDirectionalConcatListView() = default;
BiDirectionalConcatListView(menu_base::BiDirectionalList<T> left,
menu_base::BiDirectionalList<T> right)
: _left(left), _right(right), _length_left(length(left)), _length_right(length(right)) {}
BiDirectionalConcatListView& operator=(
const BiDirectionalConcatListView& rhs) {
_left = rhs._left;
_right = rhs._right;
_length_left = rhs._length_left;
_length_right = rhs._length_right;
return *this;
}
Iterator<T> iterate() const override {
return Iterator<T>(new Cursor(this));
}
menu_base::BiDirectionalIterator<T> biterate() const override {
return menu_base::BiDirectionalIterator<T>(new Cursor(this));
}
private:
friend class Cursor;
menu_base::BiDirectionalList<T> _left;
menu_base::BiDirectionalList<T> _right;
size_t _length_left;
size_t _length_right;
};
/* The state for this node contains a BiDirectionalConcatListView
of over the two BiDirectionalLists of menu_base_t-type pointers
it accepts as inputs. This node is employed variadically so there
will be an additional BiDirectionalConcatListView-containing state
genearted for each additional input created beyond the first two. */
struct State {
BiDirectionalConcatListView<menu_base_t*> menu_ptr_list_view;
};
{{ GENERATED_CODE }}
void evaluate(Context ctx) {
if(isSettingUp()) {
using menu_base::BiDirectionalList;
auto state = getState(ctx);
const auto in1 = getValue<input_IN1>(ctx);
const auto in2 = getValue<input_IN2>(ctx);
//create a new concat-view join the incoming lists once on startup,
//the outputs remain static after that
state->menu_ptr_list_view = BiDirectionalConcatListView<menu_base_t*>(in1, in2);
//output is a list that can be further concatenated
emitValue<output_OUT>(ctx, BiDirectionalList<menu_base_t*>(&state->menu_ptr_list_view));
}
}