Merge branch 'master' into feature/gui_controls

This commit is contained in:
BlackMATov
2020-04-25 01:47:34 +07:00
50 changed files with 1145 additions and 358 deletions

View File

@@ -13,6 +13,7 @@ namespace e2d
class named final {
public:
named() = default;
named(str value) noexcept;
named& name(str value) noexcept;
@@ -53,6 +54,9 @@ namespace e2d
namespace e2d
{
inline named::named(str value) noexcept
: name_(std::move(value)) {}
inline named& named::name(str value) noexcept {
name_ = std::move(value);
return *this;

View File

@@ -85,6 +85,10 @@ namespace e2d
bool add_child(
const node_iptr& child) noexcept;
bool add_child_at(
const node_iptr& child,
std::size_t index) noexcept;
bool add_child_to_back(
const node_iptr& child) noexcept;
@@ -108,6 +112,17 @@ namespace e2d
bool remove_child(
const node_iptr& child) noexcept;
node_iptr remove_child_at(
std::size_t index) noexcept;
bool swap_children(
const node_iptr& child_l,
const node_iptr& child_r) noexcept;
bool swap_children_at(
std::size_t child_l,
std::size_t child_r) noexcept;
bool send_backward() noexcept;
bool bring_to_back() noexcept;
@@ -125,6 +140,12 @@ namespace e2d
node_iptr next_sibling() noexcept;
const_node_iptr next_sibling() const noexcept;
node_iptr child_at(std::size_t index) noexcept;
const_node_iptr child_at(std::size_t index) const noexcept;
std::pair<std::size_t, bool> child_index(
const const_node_iptr& child) const noexcept;
protected:
node() = default;
node(gobject owner);

View File

@@ -27,22 +27,30 @@ namespace e2d
prefab& assign(prefab&& other) noexcept;
prefab& assign(const prefab& other);
prefab& set_prototype(ecs::prototype&& proto) noexcept;
prefab& set_prototype(const ecs::prototype& proto);
prefab& set_uuid(str&& uuid) noexcept;
prefab& set_uuid(const str& uuid);
prefab& set_children(vector<prefab>&& children) noexcept;
prefab& set_children(const vector<prefab>& children);
prefab& set_prototype(ecs::prototype&& prototype) noexcept;
prefab& set_prototype(const ecs::prototype& prototype);
str& uuid() noexcept;
const str& uuid() const noexcept;
vector<prefab>& children() noexcept;
const vector<prefab>& children() const noexcept;
ecs::prototype& prototype() noexcept;
const ecs::prototype& prototype() const noexcept;
const vector<prefab>& children() const noexcept;
private:
ecs::prototype prototype_;
str uuid_;
vector<prefab> children_;
ecs::prototype prototype_;
};
void swap(prefab& l, prefab& r) noexcept;
bool operator==(const prefab& l, const prefab& r) noexcept;
bool operator!=(const prefab& l, const prefab& r) noexcept;
bool operator==(const prefab& l, const prefab& r) = delete;
bool operator!=(const prefab& l, const prefab& r) = delete;
}

View File

@@ -29,17 +29,14 @@ namespace e2d
sprite& assign(sprite&& other) noexcept;
sprite& assign(const sprite& other);
sprite& set_pivot(const v2f& pivot) noexcept;
sprite& set_inner_texrect(const b2f& texrect) noexcept;
sprite& set_outer_texrect(const b2f& texrect) noexcept;
sprite& set_texture(const texture_asset::ptr& texture) noexcept;
const v2f& pivot() const noexcept;
const b2f& inner_texrect() const noexcept;
const b2f& outer_texrect() const noexcept;
const texture_asset::ptr& texture() const noexcept;
private:
v2f pivot_;
b2f inner_texrect_;
b2f outer_texrect_;
texture_asset::ptr texture_;

View File

@@ -109,6 +109,20 @@ namespace e2d
swap_next(l, r);
}
}
static void transfer_nodes(node_ptr p, node_ptr b, node_ptr e) noexcept {
if ( b != e ) {
node_ptr prev_p = p->prev_;
node_ptr prev_b = b->prev_;
node_ptr prev_e = e->prev_;
prev_e->next_ = p;
p->prev_ = prev_e;
prev_b->next_ = e;
e->prev_ = prev_b;
prev_p->next_ = b;
b->prev_ = prev_p;
}
}
private:
node_ptr prev_{nullptr};
node_ptr next_{nullptr};
@@ -252,15 +266,15 @@ namespace e2d
void swap(intrusive_list& other) noexcept;
template < typename Disposer >
void clear_and_dispose(Disposer&& disposer);
void clear_and_dispose(Disposer disposer);
void clear() noexcept;
template < typename Disposer >
void pop_back_and_dispose(Disposer&& disposer);
void pop_back_and_dispose(Disposer disposer);
void pop_back() noexcept;
template < typename Disposer >
void pop_front_and_dispose(Disposer&& disposer);
void pop_front_and_dispose(Disposer disposer);
void pop_front() noexcept;
void push_back(T& v) noexcept;
@@ -268,11 +282,24 @@ namespace e2d
iterator insert(const_iterator pos, T& v) noexcept;
template < typename Disposer >
iterator erase_and_dispose(const_iterator pos, Disposer&& disposer);
iterator erase_and_dispose(const_iterator pos, Disposer disposer);
iterator erase(const_iterator pos) noexcept;
void splice(const_iterator pos, intrusive_list& x) noexcept;
void splice(const_iterator pos, const_iterator f, const_iterator e) noexcept;
template < typename Predicate >
void merge(intrusive_list& x, Predicate predicate);
void merge(intrusive_list& x);
template < typename Predicate >
void sort(Predicate predicate);
void sort();
static iterator iterator_to(T& v) noexcept;
static const_iterator iterator_to(const T& v) noexcept;
static void iterator_swap(iterator l, iterator r) noexcept;
private:
using node_t = intrusive_list_hook<Tag>;
using node_ptr = typename node_t::node_ptr;
@@ -406,7 +433,7 @@ namespace e2d
template < typename T, typename Tag >
template < typename Disposer >
void intrusive_list<T,Tag>::clear_and_dispose(Disposer&& disposer) {
void intrusive_list<T,Tag>::clear_and_dispose(Disposer disposer) {
while ( !empty() ) {
pop_back_and_dispose(disposer);
}
@@ -419,7 +446,7 @@ namespace e2d
template < typename T, typename Tag >
template < typename Disposer >
void intrusive_list<T,Tag>::pop_back_and_dispose(Disposer&& disposer) {
void intrusive_list<T,Tag>::pop_back_and_dispose(Disposer disposer) {
E2D_ASSERT(!empty());
node_ptr node = root_.prev_;
node->unlink();
@@ -433,7 +460,7 @@ namespace e2d
template < typename T, typename Tag >
template < typename Disposer >
void intrusive_list<T,Tag>::pop_front_and_dispose(Disposer&& disposer) {
void intrusive_list<T,Tag>::pop_front_and_dispose(Disposer disposer) {
E2D_ASSERT(!empty());
node_ptr node = root_.next_;
node->unlink();
@@ -469,7 +496,7 @@ namespace e2d
template < typename T, typename Tag >
template < typename Disposer >
typename intrusive_list<T,Tag>::iterator intrusive_list<T,Tag>::erase_and_dispose(const_iterator pos, Disposer&& disposer) {
typename intrusive_list<T,Tag>::iterator intrusive_list<T,Tag>::erase_and_dispose(const_iterator pos, Disposer disposer) {
node_ptr node = pos.node();
E2D_ASSERT(node != &root_ && node->is_linked());
++pos;
@@ -483,6 +510,70 @@ namespace e2d
return erase_and_dispose(pos, null_disposer());
}
template < typename T, typename Tag >
void intrusive_list<T,Tag>::splice(const_iterator pos, intrusive_list& x) noexcept {
intrusive_list_hook<Tag>::transfer_nodes(pos.node(), x.begin().node(), x.end().node());
}
template < typename T, typename Tag >
void intrusive_list<T,Tag>::splice(const_iterator pos, const_iterator f, const_iterator e) noexcept {
intrusive_list_hook<Tag>::transfer_nodes(pos.node(), f.node(), e.node());
}
template < typename T, typename Tag >
template < typename Predicate >
void intrusive_list<T,Tag>::merge(intrusive_list& x, Predicate predicate) {
const_iterator b(cbegin()), e(cend()), ex(x.cend());
while ( !x.empty() ) {
const_iterator ix(x.cbegin());
while ( b != e && !predicate(*ix, *b) ) {
++b;
}
if ( b == e ) {
splice(e, x);
break;
} else {
do {
++ix;
} while ( ix != ex && predicate(*ix, *b) );
splice(b, x.begin(), ix);
}
}
}
template < typename T, typename Tag >
void intrusive_list<T,Tag>::merge(intrusive_list& x) {
merge(x, std::less<value_type>());
}
template < typename T, typename Tag >
template < typename Predicate >
void intrusive_list<T,Tag>::sort(Predicate predicate) {
if ( root_.next_ != &root_ && root_.next_ != root_.prev_ ) {
intrusive_list left_list;
intrusive_list right_list;
const_iterator mid(cbegin()), tail(cend());
while ( (mid != tail) && (++mid != tail) ) {
--tail;
}
left_list.splice(left_list.cbegin(), cbegin(), mid);
right_list.splice(right_list.cbegin(), *this);
left_list.sort(predicate);
right_list.sort(predicate);
splice(cbegin(), left_list);
merge(right_list, predicate);
}
}
template < typename T, typename Tag >
void intrusive_list<T,Tag>::sort() {
sort(std::less<value_type>());
}
template < typename T, typename Tag >
typename intrusive_list<T,Tag>::iterator intrusive_list<T,Tag>::iterator_to(T& v) noexcept {
node_t& node = static_cast<node_t&>(v);
@@ -496,4 +587,10 @@ namespace e2d
E2D_ASSERT(node.is_linked());
return const_iterator(&node);
}
template < typename T, typename Tag >
void intrusive_list<T,Tag>::iterator_swap(iterator l, iterator r) noexcept {
E2D_ASSERT(l.node()->is_linked() && r.node()->is_linked());
intrusive_list_hook<Tag>::swap_nodes(l.node(), r.node());
}
}

View File

@@ -5,7 +5,7 @@
}
},
"children" : [{
"prototype" : "sprite_prefab.json",
"prefab" : "sprite_prefab.json",
"components" : {
"actor" : {
"translation" : [-512,0]
@@ -15,7 +15,7 @@
}
}
},{
"prototype" : "sprite_prefab.json",
"prefab" : "sprite_prefab.json",
"components" : {
"actor" : {
"translation" : [-256,0]
@@ -25,7 +25,7 @@
}
}
},{
"prototype" : "sprite_prefab.json",
"prefab" : "sprite_prefab.json",
"components" : {
"actor" : {
"translation" : [0,0]
@@ -35,7 +35,7 @@
}
}
},{
"prototype" : "sprite_prefab.json",
"prefab" : "sprite_prefab.json",
"components" : {
"actor" : {
"translation" : [256,0]
@@ -45,7 +45,7 @@
}
}
},{
"prototype" : "sprite_prefab.json",
"prefab" : "sprite_prefab.json",
"components" : {
"actor" : {
"translation" : [-512,-256]
@@ -55,7 +55,7 @@
}
}
},{
"prototype" : "sprite_prefab.json",
"prefab" : "sprite_prefab.json",
"components" : {
"actor" : {
"translation" : [-256,-256]
@@ -65,7 +65,7 @@
}
}
},{
"prototype" : "sprite_prefab.json",
"prefab" : "sprite_prefab.json",
"components" : {
"actor" : {
"translation" : [0,-256]
@@ -75,7 +75,7 @@
}
}
},{
"prototype" : "sprite_prefab.json",
"prefab" : "sprite_prefab.json",
"components" : {
"actor" : {
"translation" : [256,-256]

View File

@@ -1,31 +1,24 @@
{
"prefab" : "sprite_prefab.json",
"components" : {
"named" : {
"name" : "button"
},
"button" : {
"style" : "../styles/button_style.json"
},
"rect_collider" : {
"size" : [50,50],
"offset" : [23.5,25.5]
},
"sprite_renderer" : {
"mode" : "sliced"
},
"touchable" : {
},
"widget" : {
"size" : [50,50]
}
},
"children" : [{
"prototype" : "sprite_prefab.json",
"components" : {
"named" : {
"name" : "button"
},
"button" : {
"style" : "../styles/button_style.json"
},
"touchable" : {
},
"rect_collider" : {
"size" : [50,50],
"offset" : [23.5,25.5]
},
"sprite_renderer" : {
"mode" : "sliced",
"sprite" : "../sprites/button_normal_sprite.json"
}
}
}]
},
"widget.dirty" : {}
}
}

View File

@@ -1,5 +1,5 @@
{
"prototype" : "spine_prefab.json",
"prefab" : "spine_prefab.json",
"components" : {
"named" : {
"name" : "coin"

View File

@@ -1,5 +1,5 @@
{
"prototype" : "spine_prefab.json",
"prefab" : "spine_prefab.json",
"components" : {
"named" : {
"name" : "dragon"

View File

@@ -1,5 +1,5 @@
{
"prototype" : "model_prefab.json",
"prefab" : "model_prefab.json",
"components" : {
"named" : {
"name" : "gnome"

View File

@@ -1,5 +1,5 @@
{
"prototype" : "widget_prefab.json",
"prefab" : "widget_prefab.json",
"components" : {
"named" : {
"name" : "layout"

View File

@@ -1,5 +1,5 @@
{
"prototype" : "sprite_prefab.json",
"prefab" : "sprite_prefab.json",
"components" : {
"named" : {
"name" : "panel"

View File

@@ -1,5 +1,5 @@
{
"prototype" : "spine_prefab.json",
"prefab" : "spine_prefab.json",
"components" : {
"named" : {
"name" : "raptor"

View File

@@ -1,11 +1,22 @@
{
"prototype" : "sprite_prefab.json",
"components" : {
"named" : {
"name" : "ship"
},
"sprite_renderer" : {
"sprite" : "../sprites/ship_sprite.json"
}
}
},
"children" : [{
"uuid" : "6A3E19C4-840C-40E9-9AB0-5D8DF77F0634",
"prefab" : "sprite_prefab.json",
"components" : {
"named" : {
"name" : "sprite"
},
"actor" : {
"translation" : [-33,-56.5]
},
"sprite_renderer" : {
"sprite" : "../sprites/ship_sprite.json"
}
}
}]
}

View File

@@ -1,31 +1,24 @@
{
"prefab" : "sprite_prefab.json",
"components" : {
"named" : {
"name" : "toggle"
},
"toggle" : {
"style" : "../styles/toggle_style.json"
},
"rect_collider" : {
"size" : [50,50],
"offset" : [23.5,25.5]
},
"sprite_renderer" : {
"mode" : "sliced"
},
"touchable" : {
},
"widget" : {
"size" : [50,50]
}
},
"children" : [{
"prototype" : "sprite_prefab.json",
"components" : {
"named" : {
"name" : "toggle"
},
"toggle" : {
"style" : "../styles/toggle_style.json"
},
"touchable" : {
},
"rect_collider" : {
"size" : [50,50],
"offset" : [23.5,25.5]
},
"sprite_renderer" : {
"mode" : "sliced",
"sprite" : "../sprites/button_normal_sprite.json"
}
}
}]
},
"widget.dirty" : {}
}
}

View File

@@ -1,7 +1,7 @@
{
"prototype" : "../prefabs/scene_prefab.json",
"prefab" : "../prefabs/scene_prefab.json",
"children" : [{
"prototype" : "../prefabs/camera_prefab.json",
"prefab" : "../prefabs/camera_prefab.json",
"components" : {
"actor" : {
"rotation" : 0.5
@@ -14,7 +14,7 @@
}
}
},{
"prototype" : "../prefabs/camera_prefab.json",
"prefab" : "../prefabs/camera_prefab.json",
"components" : {
"actor" : {
"rotation" : -0.5
@@ -27,7 +27,7 @@
}
}
},{
"prototype" : "../prefabs/camera_prefab.json",
"prefab" : "../prefabs/camera_prefab.json",
"components" : {
"actor" : {
"rotation" : 0.5
@@ -40,7 +40,7 @@
}
}
},{
"prototype" : "../prefabs/camera_prefab.json",
"prefab" : "../prefabs/camera_prefab.json",
"components" : {
"actor" : {
"rotation" : -0.5
@@ -53,45 +53,58 @@
}
}
},{
"prototype" : "../prefabs/gnome_prefab.json",
"prefab" : "../prefabs/gnome_prefab.json",
"components" : {
"actor" : {
"translation" : [0,0],
"scale" : 20
},
"named" : {
"name" : "gnome"
}
}
}, {
"prototype" : "../prefabs/ship_prefab.json",
"components" : {
"sprite_renderer" : {
"blending" : "additive"
},
"actor" : {
"translation" : [-50,-50]
},
"named" : {
"name" : "ship(1)"
"name" : "ships"
}
},
"children" : [{
"prototype" : "../prefabs/ship_prefab.json",
"prefab" : "../prefabs/ship_prefab.json",
"components" : {
"sprite_renderer" : {
"tint" : [255,0,0,255]
"named" : {
"name" : "ship(1)"
},
"actor" : {
"translation" : [100,0]
},
"translation" : [-50,-50]
}
},
"mod_children" : [{
"uuid" : "6A3E19C4-840C-40E9-9AB0-5D8DF77F0634",
"components" : {
"sprite_renderer" : {
"tint" : [255,0,0,255]
}
}
}]
}, {
"prefab" : "../prefabs/ship_prefab.json",
"components" : {
"named" : {
"name" : "ship(2)"
},
"actor" : {
"translation" : [50,-50]
}
}
},
"mod_children" : [{
"uuid" : "6A3E19C4-840C-40E9-9AB0-5D8DF77F0634",
"components" : {
"sprite_renderer" : {
"blending" : "additive"
}
}
}]
}]
}, {
"prototype" : "../prefabs/label_bm_prefab.json",
"prefab" : "../prefabs/label_bm_prefab.json",
"components" : {
"label" : {
"text" : "bm font",
@@ -108,7 +121,7 @@
}
}
}, {
"prototype" : "../prefabs/label_sdf_prefab.json",
"prefab" : "../prefabs/label_sdf_prefab.json",
"components" : {
"label" : {
"text" : "sdf font",

View File

@@ -1,9 +1,9 @@
{
"prototype" : "../prefabs/scene_prefab.json",
"prefab" : "../prefabs/scene_prefab.json",
"children" : [{
"prototype" : "../prefabs/camera_prefab.json"
"prefab" : "../prefabs/camera_prefab.json"
},{
"prototype" : "../prefabs/coin_prefab.json",
"prefab" : "../prefabs/coin_prefab.json",
"components" : {
"actor" : {
"translation" : [350,250],
@@ -14,7 +14,7 @@
}
}
}, {
"prototype" : "../prefabs/raptor_prefab.json",
"prefab" : "../prefabs/raptor_prefab.json",
"components" : {
"actor" : {
"translation" : [300,-350],
@@ -25,7 +25,7 @@
}
}
}, {
"prototype" : "../prefabs/dragon_prefab.json",
"prefab" : "../prefabs/dragon_prefab.json",
"components" : {
"actor" : {
"translation" : [-100,0],

View File

@@ -1,16 +1,16 @@
{
"prototype" : "../prefabs/scene_prefab.json",
"prefab" : "../prefabs/scene_prefab.json",
"components" : {
"behaviour" : {
"script" : "../scripts/sample_07/sample_07.lua"
}
},
"children" : [{
"prototype" : "../prefabs/camera_prefab.json"
"prefab" : "../prefabs/camera_prefab.json"
},{
"prototype" : "../prefabs/background_prefab.json"
"prefab" : "../prefabs/background_prefab.json"
},{
"prototype" : "../prefabs/gnome_prefab.json",
"prefab" : "../prefabs/gnome_prefab.json",
"components" : {
"actor" : {
"translation" : [0,0],
@@ -21,7 +21,7 @@
}
}
},{
"prototype" : "../prefabs/label_sdf_prefab.json",
"prefab" : "../prefabs/label_sdf_prefab.json",
"components" : {
"label" : {
"text" : "FPS: ",

View File

@@ -1,12 +1,12 @@
{
"prototype" : "../prefabs/scene_prefab.json",
"prefab" : "../prefabs/scene_prefab.json",
"components" : {
"behaviour" : {
"script" : "../scripts/sample_08/sample_08.lua"
}
},
"children" : [{
"prototype" : "../prefabs/camera_prefab.json",
"prefab" : "../prefabs/camera_prefab.json",
"components" : {
"actor" : {
"rotation" : 0.5
@@ -19,7 +19,7 @@
}
}
},{
"prototype" : "../prefabs/camera_prefab.json",
"prefab" : "../prefabs/camera_prefab.json",
"components" : {
"actor" : {
"rotation" : -0.5
@@ -32,7 +32,7 @@
}
}
},{
"prototype" : "../prefabs/ship_prefab.json",
"prefab" : "../prefabs/ship_prefab.json",
"components" : {
"named" : {
"name" : "ship(1)"
@@ -51,7 +51,7 @@
}
},
"children" : [{
"prototype" : "../prefabs/ship_prefab.json",
"prefab" : "../prefabs/ship_prefab.json",
"components" : {
"named" : {
"name" : "ship(11)"
@@ -69,11 +69,10 @@
"offset" : [-30,15],
"radius" : 33
}
},
"children" : []
}
}]
},{
"prototype" : "../prefabs/ship_prefab.json",
"prefab" : "../prefabs/ship_prefab.json",
"components" : {
"named" : {
"name" : "ship(2)"
@@ -113,7 +112,7 @@
}
}
},{
"prototype" : "../prefabs/label_sdf_prefab.json",
"prefab" : "../prefabs/label_sdf_prefab.json",
"components" : {
"named" : {
"name" : "label"
@@ -130,7 +129,7 @@
}
}
},{
"prototype" : "../prefabs/panel_prefab.json",
"prefab" : "../prefabs/panel_prefab.json",
"components" : {
"actor" : {
"translation" : [-70,150]
@@ -148,7 +147,7 @@
"touchable" : {}
},
"children" : [{
"prototype" : "../prefabs/label_sdf_prefab.json",
"prefab" : "../prefabs/label_sdf_prefab.json",
"components" : {
"named" : {
"name" : "label"
@@ -167,7 +166,7 @@
}
}]
},{
"prototype" : "../prefabs/panel_prefab.json",
"prefab" : "../prefabs/panel_prefab.json",
"components" : {
"actor" : {
"translation" : [20,200]
@@ -185,7 +184,7 @@
"touchable" : {}
},
"children" : [{
"prototype" : "../prefabs/label_sdf_prefab.json",
"prefab" : "../prefabs/label_sdf_prefab.json",
"components" : {
"named" : {
"name" : "label"
@@ -204,21 +203,21 @@
}
}]
},{
"prototype" : "../prefabs/button_prefab.json",
"prefab" : "../prefabs/button_prefab.json",
"components" : {
"actor" : {
"translation" : [-160,50]
}
}
},{
"prototype" : "../prefabs/toggle_prefab.json",
"prefab" : "../prefabs/toggle_prefab.json",
"components" : {
"actor" : {
"translation" : [-100,50]
}
}
},{
"prototype" : "../prefabs/panel_prefab.json",
"prefab" : "../prefabs/panel_prefab.json",
"components" : {
"actor" : {
"translation" : [-280,-250]
@@ -241,11 +240,11 @@
}
},
"children" : [{
"prototype" : "../prefabs/toggle_prefab.json"
"prefab" : "../prefabs/toggle_prefab.json"
},{
"prototype" : "../prefabs/toggle_prefab.json"
"prefab" : "../prefabs/toggle_prefab.json"
},{
"prototype" : "../prefabs/toggle_prefab.json"
"prefab" : "../prefabs/toggle_prefab.json"
}]
}]
}

View File

@@ -1,18 +1,18 @@
{
"prototype" : "../prefabs/scene_prefab.json",
"prefab" : "../prefabs/scene_prefab.json",
"children" : [{
"prototype" : "../prefabs/background_prefab.json"
"prefab" : "../prefabs/background_prefab.json"
},{
"prototype" : "../prefabs/camera_prefab.json"
"prefab" : "../prefabs/camera_prefab.json"
},{
"prototype" : "../prefabs/panel_prefab.json",
"prefab" : "../prefabs/panel_prefab.json",
"components" : {
"sprite_renderer" : {
"scale" : [4,2]
}
},
"children" : [{
"prototype" : "../prefabs/layout_prefab.json",
"prefab" : "../prefabs/layout_prefab.json",
"components" : {
"layout" : {
"justify_content" : "space_evenly"
@@ -22,14 +22,14 @@
}
},
"children" : [{
"prototype" : "../prefabs/widget_prefab.json",
"prefab" : "../prefabs/widget_prefab.json",
"components" : {
"widget" : {
"size" : [66,113]
}
},
"children" : [{
"prototype" : "../prefabs/ship_prefab.json",
"prefab" : "../prefabs/ship_prefab.json",
"components" : {
"actor" : {
"translation" : [33,56.5]
@@ -37,14 +37,14 @@
}
}]
},{
"prototype" : "../prefabs/widget_prefab.json",
"prefab" : "../prefabs/widget_prefab.json",
"components" : {
"widget" : {
"size" : [66,113]
}
},
"children" : [{
"prototype" : "../prefabs/ship_prefab.json",
"prefab" : "../prefabs/ship_prefab.json",
"components" : {
"actor" : {
"translation" : [33,56.5]
@@ -52,14 +52,14 @@
}
}]
},{
"prototype" : "../prefabs/widget_prefab.json",
"prefab" : "../prefabs/widget_prefab.json",
"components" : {
"widget" : {
"size" : [66,113]
}
},
"children" : [{
"prototype" : "../prefabs/ship_prefab.json",
"prefab" : "../prefabs/ship_prefab.json",
"components" : {
"actor" : {
"translation" : [33,56.5]

View File

@@ -87,6 +87,12 @@ function node.remove_all_children(self) end
---@return boolean
function node.add_child(self, child) end
---@param self node
---@param child node
---@param index integer
---@return boolean
function node.add_child_at(self, child, index) end
---@param self node
---@param child node
---@return boolean
@@ -124,6 +130,23 @@ function node.add_sibling_after(self, sibling) end
---@return boolean
function node.remove_child(self, child) end
---@param self node
---@param index integer
---@return node
function node.remove_child_at(self, index) end
---@param self node
---@param child_l node
---@param child_r node
---@return boolean
function node.swap_children(self, child_l, child_r) end
---@param self node
---@param child_l integer
---@param child_r integer
---@return boolean
function node.swap_children_at(self, child_l, child_r) end
---@param self node
---@return boolean
function node.send_backward(self) end
@@ -140,5 +163,15 @@ function node.send_forward(self) end
---@return boolean
function node.bring_to_front(self) end
---@param self node
---@param index integer
---@return node
function node.child_at(self, index) end
---@param self node
---@param child node
---@return integer, boolean
function node.child_index(self, child) end
---@type node
_G.node = _G.node or node

View File

@@ -1,5 +1,4 @@
{
"texture" : "background.png",
"pivot" : { "x" : 0, "y" : 0 },
"texrect" : { "x" : 0, "y" : 0, "w" : 256, "h" : 256 }
}

View File

@@ -1,6 +1,5 @@
{
"texture" : "button_normal.png",
"pivot" : { "x" : 0, "y" : 0 },
"inner_texrect" : { "x" : 10, "y" : 10, "w" : 27, "h" : 31 },
"outer_texrect" : { "x" : 0, "y" : 0, "w" : 47, "h" : 51 }
}

View File

@@ -1,6 +1,5 @@
{
"texture" : "button_pressed.png",
"pivot" : { "x" : 0, "y" : 0 },
"inner_texrect" : { "x" : 10, "y" : 10, "w" : 27, "h" : 31 },
"outer_texrect" : { "x" : 0, "y" : 0, "w" : 47, "h" : 51 }
}

View File

@@ -1,5 +1,4 @@
{
"texture" : "cube_0.png",
"pivot" : { "x" : 12, "y" : 12 },
"texrect" : { "x" : 0, "y" : 0, "w" : 24, "h" : 24 }
}

View File

@@ -1,5 +1,4 @@
{
"texture" : "cube_1.png",
"pivot" : { "x" : 12, "y" : 12 },
"texrect" : { "x" : 0, "y" : 0, "w" : 24, "h" : 24 }
}

View File

@@ -1,6 +1,5 @@
{
"texture" : "panel.png",
"pivot" : { "x" : 0, "y" : 0 },
"inner_texrect" : { "x" : 6, "y" : 6, "w" : 88, "h" : 88 },
"outer_texrect" : { "x" : 0, "y" : 0, "w" : 100, "h" : 100 }
}

View File

@@ -1,5 +1,4 @@
{
"texture" : "ships.png",
"pivot" : { "x" : 441, "y" : 340.5 },
"texrect" : { "x" : 408, "y" : 284, "w" : 66, "h" : 113 }
}

View File

@@ -2,11 +2,9 @@
"texture" : "ships.png",
"sprites" : [{
"name" : "ship (1).png",
"pivot" : { "x" : 441, "y" : 455 },
"texrect" : { "x" : 408, "y" : 399, "w" : 66, "h" : 113 }
},{
"name" : "ship (2).png",
"pivot" : { "x" : 441, "y" : 340 },
"texrect" : { "x" : 408, "y" : 284, "w" : 66, "h" : 113 }
}]
}

View File

@@ -80,6 +80,7 @@ namespace
auto scene_i = the<world>().instantiate();
scene_i.component<scene>().assign();
scene_i.component<named>().assign("scene");
{
prefab prefab;
@@ -113,14 +114,22 @@ namespace
}
{
prefab sprite_prefab;
sprite_prefab.prototype()
.component<named>(named()
.name("sprite"))
.component<actor>(actor()
.node(node::create(math::make_translation_trs2(v2f{-33.f,-56.5f}))))
.component<renderer>()
.component<sprite_renderer>(sprite_renderer(sprite_res)
.materials({{"normal", sprite_mat}}));
prefab prefab;
prefab.prototype()
.component<named>(named()
.name("ship"))
.component<node_rotator>()
.component<renderer>()
.component<sprite_renderer>(sprite_renderer(sprite_res)
.materials({{"normal", sprite_mat}}));
.component<node_rotator>();
prefab.set_children({sprite_prefab});
the<world>().instantiate(
prefab,
@@ -129,11 +138,12 @@ namespace
}
{
prefab prefab_a;
prefab_a.prototype()
prefab sprite_prefab;
sprite_prefab.prototype()
.component<named>(named()
.name("cube"))
.component<node_rotator>()
.name("sprite"))
.component<actor>(actor()
.node(node::create(math::make_translation_trs2(v2f{-12.f,-12.f}))))
.component<renderer>()
.component<sprite_renderer>(sprite_renderer()
.filtering(false)
@@ -142,28 +152,35 @@ namespace
.play("idle")
.looped(true));
prefab child_prefab;
child_prefab.prototype()
.component<named>(named()
.name("child"))
.component<actor>(actor()
.node(node::create(make_trs2(
v2f{20.f,0.f},
0.f,
v2f{0.3f,0.3f}))))
.component<node_rotator>();
child_prefab.set_children({sprite_prefab});
prefab root_prefab;
root_prefab.prototype()
.component<named>(named()
.name("root"))
.component<node_rotator>();
root_prefab.set_children({sprite_prefab, child_prefab});
for ( std::size_t i = 0; i < 2; ++i )
for ( std::size_t j = 0; j < 5; ++j ) {
t2f trans{
{-80.f + j * 40.f, -200.f + i * 40.f},
0.f,
{2.f,2.f}};
gobject inst = the<world>().instantiate(
prefab_a,
the<world>().instantiate(
root_prefab,
scene_i.component<actor>()->node(),
trans);
prefab prefab_b = prefab_a;
prefab_b.prototype()
.component<node_rotator>()
.component<actor>(node::create(make_trs2(
v2f{20.f,0.f},
0.f,
v2f{0.3f,0.3f})));
the<world>().instantiate(
prefab_b,
inst.component<actor>()->node());
}
}

View File

@@ -36,20 +36,18 @@ namespace
"sprite" : {
"anyOf" : [{
"type" : "object",
"required" : [ "name", "pivot", "texrect" ],
"required" : [ "name", "texrect" ],
"additionalProperties" : false,
"properties" : {
"name" : { "$ref": "#/common_definitions/name" },
"pivot" : { "$ref": "#/common_definitions/v2" },
"texrect" : { "$ref": "#/common_definitions/b2" }
}
},{
"type" : "object",
"required" : [ "name", "pivot", "inner_texrect", "outer_texrect" ],
"required" : [ "name", "inner_texrect", "outer_texrect" ],
"additionalProperties" : false,
"properties" : {
"name" : { "$ref": "#/common_definitions/name" },
"pivot" : { "$ref": "#/common_definitions/v2" },
"inner_texrect" : { "$ref": "#/common_definitions/b2" },
"outer_texrect" : { "$ref": "#/common_definitions/b2" }
}
@@ -78,7 +76,6 @@ namespace
struct sprite_desc {
str_hash name;
v2f pivot;
b2f inner_texrect;
b2f outer_texrect;
};
@@ -100,12 +97,6 @@ namespace
return false;
}
E2D_ASSERT(sprite_json.HasMember("pivot"));
if ( !json_utils::try_parse_value(sprite_json["pivot"], tsprite_descs[i].pivot) ) {
the<debug>().error("ATLAS: Incorrect formatting of 'pivot' property");
return false;
}
E2D_ASSERT(
sprite_json.HasMember("texrect") ||
(sprite_json.HasMember("inner_texrect") && sprite_json.HasMember("outer_texrect")));
@@ -163,7 +154,6 @@ namespace
nested_content ncontent;
for ( const sprite_desc& desc : sprite_descs ) {
sprite spr;
spr.set_pivot(desc.pivot);
spr.set_inner_texrect(desc.inner_texrect);
spr.set_outer_texrect(desc.outer_texrect);
spr.set_texture(texture);

View File

@@ -24,25 +24,42 @@ namespace
"required" : [],
"additionalProperties" : false,
"properties" : {
"prototype" : { "$ref": "#/common_definitions/address" },
"components" : { "type" : "object" },
"uuid" : { "$ref": "#/common_definitions/uuid" },
"prefab" : { "$ref": "#/common_definitions/address" },
"children" : { "$ref": "#/definitions/children" },
"mod_children" : { "$ref": "#/definitions/mod_children" },
"components" : { "type" : "object" }
},
"definitions" : {
"children" : {
"type" : "array",
"items" : { "$ref": "#/definitions/child" }
}
},
"definitions" : {
},
"child" : {
"type" : "object",
"required" : [],
"additionalProperties" : false,
"properties" : {
"prototype" : { "$ref": "#/common_definitions/address" },
"components" : { "type" : "object" },
"children" : {
"type" : "array",
"items" : { "$ref": "#/definitions/child" }
}
"uuid" : { "$ref": "#/common_definitions/uuid" },
"prefab" : { "$ref": "#/common_definitions/address" },
"children" : { "$ref": "#/definitions/children" },
"mod_children" : { "$ref": "#/definitions/mod_children" },
"components" : { "type" : "object" }
}
},
"mod_children" : {
"type" : "array",
"items" : { "$ref": "#/definitions/mod_child" }
},
"mod_child" : {
"type" : "object",
"required" : [ "uuid" ],
"additionalProperties" : false,
"properties" : {
"uuid" : { "$ref": "#/common_definitions/uuid" },
"children" : { "$ref": "#/definitions/children" },
"mod_children" : { "$ref": "#/definitions/mod_children" },
"components" : { "type" : "object" }
}
}
}
@@ -71,9 +88,23 @@ namespace
const rapidjson::Value& root,
asset_dependencies& dependencies)
{
if ( root.HasMember("prototype") ) {
if ( root.HasMember("prefab") ) {
dependencies.add_dependency<prefab_asset>(
path::combine(parent_address, root["prototype"].GetString()));
path::combine(parent_address, root["prefab"].GetString()));
}
if ( root.HasMember("children") ) {
const rapidjson::Value& children_root = root["children"];
for ( rapidjson::SizeType i = 0; i < children_root.Size(); ++i ) {
collect_dependencies(parent_address, children_root[i], dependencies);
}
}
if ( root.HasMember("mod_children") ) {
const rapidjson::Value& mod_children_root = root["mod_children"];
for ( rapidjson::SizeType i = 0; i < mod_children_root.Size(); ++i ) {
collect_dependencies(parent_address, mod_children_root[i], dependencies);
}
}
if ( root.HasMember("components") ) {
@@ -83,9 +114,10 @@ namespace
++component_root )
{
{
bool success = the<factory>().validate_json(
const bool success = the<factory>().validate_json(
component_root->name.GetString(),
component_root->value);
if ( !success ) {
throw prefab_asset_loading_exception();
}
@@ -94,23 +126,18 @@ namespace
factory_loader<>::collect_context ctx(
str(parent_address),
component_root->value);
bool success = the<factory>().collect_dependencies(
const bool success = the<factory>().collect_dependencies(
component_root->name.GetString(),
dependencies,
ctx);
if ( !success ) {
throw prefab_asset_loading_exception();
}
}
}
}
if ( root.HasMember("children") ) {
const rapidjson::Value& children_root = root["children"];
for ( rapidjson::SizeType i = 0; i < children_root.Size(); ++i ) {
collect_dependencies(parent_address, children_root[i], dependencies);
}
}
}
stdex::promise<asset_group> collect_dependencies(
@@ -123,25 +150,92 @@ namespace
return dependencies.load_async(library);
}
prefab parse_prefab(
prefab* find_prefab_child(prefab& root, str_view child_uuid) noexcept {
for ( prefab& child : root.children() ) {
if ( child.uuid() == child_uuid ) {
return &child;
}
}
for ( prefab& child : root.children() ) {
if ( prefab* sub_child = find_prefab_child(child, child_uuid) ) {
return sub_child;
}
}
return nullptr;
}
void parse_prefab_inplace(
prefab& content,
str_view parent_address,
const rapidjson::Value& root,
const asset_group& dependencies)
{
prefab content;
if ( root.HasMember("uuid") ) {
str uuid = root["uuid"].GetString();
content.set_uuid(std::move(uuid));
}
if ( root.HasMember("prototype") ) {
if ( root.HasMember("prefab") ) {
auto proto_res = dependencies.find_asset<prefab_asset>(
path::combine(parent_address, root["prototype"].GetString()));
path::combine(parent_address, root["prefab"].GetString()));
if ( !proto_res ) {
the<debug>().error("PREFAB: Dependency 'prototype' is not found:\n"
the<debug>().error("PREFAB: Dependency 'prefab' is not found:\n"
"--> Parent address: %0\n"
"--> Dependency address: %1",
parent_address,
root["prototype"].GetString());
root["prefab"].GetString());
throw prefab_asset_loading_exception();
}
content = proto_res->content();
content.set_children(proto_res->content().children());
content.set_prototype(proto_res->content().prototype());
}
if ( root.HasMember("children") ) {
const rapidjson::Value& children_root = root["children"];
for ( rapidjson::SizeType i = 0; i < children_root.Size(); ++i ) {
const rapidjson::Value& child_root = children_root[i];
prefab child;
parse_prefab_inplace(
child,
parent_address,
child_root,
dependencies);
content.children().push_back(std::move(child));
}
}
if ( root.HasMember("mod_children") ) {
const rapidjson::Value& mod_children_root = root["mod_children"];
for ( rapidjson::SizeType i = 0; i < mod_children_root.Size(); ++i ) {
const rapidjson::Value& mod_child_root = mod_children_root[i];
E2D_ASSERT(
mod_child_root.HasMember("uuid") &&
mod_child_root["uuid"].IsString());
prefab* const child_prefab = find_prefab_child(
content,
mod_child_root["uuid"].GetString());
if ( !child_prefab ) {
the<debug>().error("PREFAB: Modifiable child is not found:\n"
"--> Child UUID: %0",
mod_child_root["uuid"].GetString());
throw prefab_asset_loading_exception();
}
parse_prefab_inplace(
*child_prefab,
parent_address,
mod_child_root,
dependencies);
}
}
if ( root.HasMember("components") ) {
@@ -154,30 +248,29 @@ namespace
str(parent_address),
component_root->value,
dependencies);
bool success = the<factory>().fill_prototype(
const bool success = the<factory>().fill_prototype(
component_root->name.GetString(),
content.prototype(),
ctx);
if ( !success ) {
throw prefab_asset_loading_exception();
}
}
}
}
if ( root.HasMember("children") ) {
const rapidjson::Value& children_root = root["children"];
vector<prefab> children;
children.reserve(children_root.Size());
for ( rapidjson::SizeType i = 0; i < children_root.Size(); ++i ) {
children.emplace_back(parse_prefab(
parent_address, children_root[i], dependencies));
}
content.set_children(std::move(children));
}
prefab parse_prefab(
str_view parent_address,
const rapidjson::Value& root,
const asset_group& dependencies)
{
prefab content;
parse_prefab_inplace(
content,
parent_address,
root, dependencies);
return content;
}
}

View File

@@ -23,20 +23,18 @@ namespace
const char* sprite_asset_schema_source = R"json({
"anyOf" : [{
"type" : "object",
"required" : [ "texture", "pivot", "texrect" ],
"required" : [ "texture", "texrect" ],
"additionalProperties" : false,
"properties" : {
"texture" : { "$ref": "#/common_definitions/address" },
"pivot" : { "$ref": "#/common_definitions/v2" },
"texrect" : { "$ref": "#/common_definitions/b2" }
}
},{
"type" : "object",
"required" : [ "texture", "pivot", "inner_texrect", "outer_texrect" ],
"required" : [ "texture", "inner_texrect", "outer_texrect" ],
"additionalProperties" : false,
"properties" : {
"texture" : { "$ref": "#/common_definitions/address" },
"pivot" : { "$ref": "#/common_definitions/v2" },
"inner_texrect" : { "$ref": "#/common_definitions/b2" },
"outer_texrect" : { "$ref": "#/common_definitions/b2" }
}
@@ -70,16 +68,9 @@ namespace
auto texture_p = library.load_asset_async<texture_asset>(
path::combine(parent_address, root["texture"].GetString()));
v2f pivot;
b2f inner_texrect;
b2f outer_texrect;
E2D_ASSERT(root.HasMember("pivot"));
if ( !json_utils::try_parse_value(root["pivot"], pivot) ) {
the<debug>().error("SPRITE: Incorrect formatting of 'pivot' property");
return stdex::make_rejected_promise<sprite>(sprite_asset_loading_exception());
}
E2D_ASSERT(
root.HasMember("texrect") ||
(root.HasMember("inner_texrect") && root.HasMember("outer_texrect")));
@@ -105,12 +96,10 @@ namespace
}
return texture_p.then([
pivot,
inner_texrect,
outer_texrect
](const texture_asset::load_result& texture){
sprite content;
content.set_pivot(pivot);
content.set_inner_texrect(inner_texrect);
content.set_outer_texrect(outer_texrect);
content.set_texture(texture);

View File

@@ -87,6 +87,12 @@ namespace e2d::bindings::high
return n.add_child(c);
},
"add_child_at", [](node& n, const node_iptr& c, i32 i) -> bool {
return i >= 0
? n.add_child_at(c, math::numeric_cast<std::size_t>(i))
: false;
},
"add_child_to_back", [](node& n, const node_iptr& c) -> bool {
return n.add_child_to_back(c);
},
@@ -115,6 +121,22 @@ namespace e2d::bindings::high
return n.remove_child(c);
},
"remove_child_at", [](node& n, i32 i) -> node_iptr {
return i >= 0
? n.remove_child_at(math::numeric_cast<std::size_t>(i))
: node_iptr();
},
"swap_children", [](node& n, const node_iptr& cl, const node_iptr& cr) -> bool {
return n.swap_children(cl, cr);
},
"swap_children_at", [](node& n, i32 cl, i32 cr) -> bool {
return cl >= 0 && cr >= 0
? n.swap_children_at(math::numeric_cast<std::size_t>(cl), math::numeric_cast<std::size_t>(cr))
: false;
},
"send_backward", [](node& n) -> bool {
return n.send_backward();
},
@@ -141,7 +163,17 @@ namespace e2d::bindings::high
[](node& n) -> node_iptr { return n.prev_sibling(); }),
"next_sibling", sol::property(
[](node& n) -> node_iptr { return n.next_sibling(); })
[](node& n) -> node_iptr { return n.next_sibling(); }),
"child_at", [](node& n, i32 i) -> node_iptr {
return i >= 0
? n.child_at(math::numeric_cast<std::size_t>(i))
: node_iptr();
},
"child_index", [](node& n, const node_iptr& c) -> std::pair<std::size_t, bool> {
return n.child_index(c);
}
);
}
}

View File

@@ -245,10 +245,9 @@ namespace e2d
const b2f& outer_r = spr.outer_texrect();
const v2f size = outer_r.size * c->scale();
const v2f poff = (outer_r.position - spr.pivot()) * c->scale();
ctx.draw_wire_rect(
poff + size * 0.5f,
size * 0.5f,
size,
ctx.selected() ? color32::yellow() : color32::magenta());
}

View File

@@ -207,14 +207,25 @@ namespace e2d
return count;
}
bool node::add_child(const node_iptr& child) noexcept {
bool node::add_child(
const node_iptr& child) noexcept
{
return add_child_to_front(child);
}
bool node::add_child_at(
const node_iptr& child,
std::size_t index) noexcept
{
return index == 0u
? add_child_to_back(child)
: add_child_after(child_at(index - 1u), child);
}
bool node::add_child_to_back(
const node_iptr& child) noexcept
{
if ( !child ) {
if ( !child || child == this ) {
return false;
}
@@ -233,7 +244,7 @@ namespace e2d
bool node::add_child_to_front(
const node_iptr& child) noexcept
{
if ( !child ) {
if ( !child || child == this ) {
return false;
}
@@ -319,6 +330,41 @@ namespace e2d
return true;
}
node_iptr node::remove_child_at(std::size_t index) noexcept {
node_iptr child = child_at(index);
return remove_child(child)
? child
: node_iptr();
}
bool node::swap_children(
const node_iptr& child_l,
const node_iptr& child_r) noexcept
{
if ( !child_l || !child_r ) {
return false;
}
if ( child_l->parent_ != this || child_r->parent_ != this ) {
return false;
}
node_children::iterator_swap(
node_children::iterator_to(*child_l),
node_children::iterator_to(*child_r));
return true;
}
bool node::swap_children_at(
std::size_t child_l,
std::size_t child_r) noexcept
{
return swap_children(
child_at(child_l),
child_at(child_r));
}
bool node::send_backward() noexcept {
node_iptr prev = prev_sibling();
return prev
@@ -414,6 +460,36 @@ namespace e2d
}
return const_node_iptr(&*iter);
}
node_iptr node::child_at(std::size_t index) noexcept {
node_iptr child = first_child();
for ( std::size_t i = 0; i < index && child; ++i ) {
child = child->next_sibling();
}
return child;
}
const_node_iptr node::child_at(std::size_t index) const noexcept {
const_node_iptr child = first_child();
for ( std::size_t i = 0; i < index && child; ++i ) {
child = child->next_sibling();
}
return child;
}
std::pair<std::size_t, bool> node::child_index(
const const_node_iptr& child) const noexcept
{
if ( !child || child->parent_ != this ) {
return {std::size_t(-1), false};
}
const auto distance = std::distance(
children_.begin(),
node_children::iterator_to(*child));
return {math::numeric_cast<std::size_t>(distance), true};
}
}
namespace e2d

View File

@@ -25,14 +25,16 @@ namespace e2d
}
void prefab::clear() noexcept {
prototype_.clear();
uuid_.clear();
children_.clear();
prototype_.clear();
}
void prefab::swap(prefab& other) noexcept {
using std::swap;
swap(prototype_, other.prototype_);
swap(uuid_, other.uuid_);
swap(children_, other.children_);
swap(prototype_, other.prototype_);
}
prefab& prefab::assign(prefab&& other) noexcept {
@@ -46,20 +48,21 @@ namespace e2d
prefab& prefab::assign(const prefab& other) {
if ( this != &other ) {
prefab s;
s.prototype_ = other.prototype_;
s.uuid_ = other.uuid_;
s.children_ = other.children_;
s.prototype_ = other.prototype_;
swap(s);
}
return *this;
}
prefab& prefab::set_prototype(ecs::prototype&& proto) noexcept {
prototype_ = std::move(proto);
prefab& prefab::set_uuid(str&& uuid) noexcept {
uuid_ = std::move(uuid);
return *this;
}
prefab& prefab::set_prototype(const ecs::prototype& proto) {
prototype_ = proto;
prefab& prefab::set_uuid(const str& uuid) {
uuid_ = uuid;
return *this;
}
@@ -73,6 +76,32 @@ namespace e2d
return *this;
}
prefab& prefab::set_prototype(ecs::prototype&& prototype) noexcept {
prototype_ = std::move(prototype);
return *this;
}
prefab& prefab::set_prototype(const ecs::prototype& prototype) {
prototype_ = prototype;
return *this;
}
str& prefab::uuid() noexcept {
return uuid_;
}
const str& prefab::uuid() const noexcept {
return uuid_;
}
vector<prefab>& prefab::children() noexcept {
return children_;
}
const vector<prefab>& prefab::children() const noexcept {
return children_;
}
ecs::prototype& prefab::prototype() noexcept {
return prototype_;
}
@@ -80,10 +109,6 @@ namespace e2d
const ecs::prototype& prefab::prototype() const noexcept {
return prototype_;
}
const vector<prefab>& prefab::children() const noexcept {
return children_;
}
}
namespace e2d
@@ -91,13 +116,4 @@ namespace e2d
void swap(prefab& l, prefab& r) noexcept {
l.swap(r);
}
bool operator==(const prefab& l, const prefab& r) noexcept {
return l.prototype().empty() && l.children().empty()
&& r.prototype().empty() && r.children().empty();
}
bool operator!=(const prefab& l, const prefab& r) noexcept {
return !(l == r);
}
}

View File

@@ -25,7 +25,6 @@ namespace e2d
}
void sprite::clear() noexcept {
pivot_ = v2f::zero();
inner_texrect_ = b2f::zero();
outer_texrect_ = b2f::zero();
texture_.reset();
@@ -33,7 +32,6 @@ namespace e2d
void sprite::swap(sprite& other) noexcept {
using std::swap;
swap(pivot_, other.pivot_);
swap(inner_texrect_, other.inner_texrect_);
swap(outer_texrect_, other.outer_texrect_);
swap(texture_, other.texture_);
@@ -50,7 +48,6 @@ namespace e2d
sprite& sprite::assign(const sprite& other) {
if ( this != &other ) {
sprite s;
s.pivot_ = other.pivot_;
s.inner_texrect_ = other.inner_texrect_;
s.outer_texrect_ = other.outer_texrect_;
s.texture_ = other.texture_;
@@ -59,11 +56,6 @@ namespace e2d
return *this;
}
sprite& sprite::set_pivot(const v2f& pivot) noexcept {
pivot_ = pivot;
return *this;
}
sprite& sprite::set_inner_texrect(const b2f& texrect) noexcept {
inner_texrect_ = texrect;
return *this;
@@ -79,10 +71,6 @@ namespace e2d
return *this;
}
const v2f& sprite::pivot() const noexcept {
return pivot_;
}
const b2f& sprite::inner_texrect() const noexcept {
return inner_texrect_;
}
@@ -103,8 +91,7 @@ namespace e2d
}
bool operator==(const sprite& l, const sprite& r) noexcept {
return l.pivot() == r.pivot()
&& l.inner_texrect() == r.inner_texrect()
return l.inner_texrect() == r.inner_texrect()
&& l.outer_texrect() == r.outer_texrect()
&& l.texture() == r.texture();
}

View File

@@ -496,13 +496,12 @@ namespace e2d::render_system_impl
const b2f& outer_r = spr.outer_texrect();
const v2f size = outer_r.size * spr_r.scale();
const v2f poff = (outer_r.position - spr.pivot()) * spr_r.scale();
const v2f pos_xs = v2f{
0.f, size.x} + poff.x;
0.f, size.x};
const v2f pos_ys = v2f{
0.f, size.y} + poff.y;
0.f, size.y};
const v2f tex_xs = v2f{
outer_r.position.x,
@@ -550,7 +549,6 @@ namespace e2d::render_system_impl
const f32 top = (outer_r.size.y - inner_r.size.y) - bottom;
const v2f size = outer_r.size * spr_r.scale();
const v2f poff = (outer_r.position - spr.pivot()) * spr_r.scale();
const f32 sides_width = left + right;
const f32 sides_height = bottom + top;
@@ -569,13 +567,13 @@ namespace e2d::render_system_impl
0.f,
adj_left,
size.x - adj_right,
size.x} + poff.x;
size.x};
const v4f pos_ys = v4f{
0.f,
adj_bottom,
size.y - adj_top,
size.y} + poff.y;
size.y};
const v4f tex_xs = v4f{
outer_r.position.x,

View File

@@ -197,6 +197,12 @@ namespace
}
}]
},
"guid" : {
"type" : "string",
"minLength" : 36,
"maxLength" : 36,
"pattern" : "^[0-9a-fA-F]{8}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{12}$"
},
"name" : {
"type" : "string",
"minLength" : 1

View File

@@ -2,11 +2,9 @@
"texture" : "image.png",
"sprites" : [{
"name" : "sprite",
"pivot" : { "x" : 1, "y" : 2 },
"texrect" : { "x" : 5, "y" : 6, "w" : 7, "h" : 8 }
},{
"name" : "sprite2",
"pivot" : { "x" : 1, "y" : 2 },
"inner_texrect" : { "x" : 1, "y" : 2, "w" : 3, "h" : 4 },
"outer_texrect" : { "x" : 5, "y" : 6, "w" : 7, "h" : 8 }
}]

View File

@@ -1,20 +0,0 @@
{
"components" : {
"touchable" : {},
"rect_collider" : {
"size" : [1,2],
"offset" : [2,4]
},
"circle_collider" : {
"radius" : 5,
"offset" : [4,2]
},
"polygon_collider" : {
"points" : [[1,2],[2,3],[3,4]],
"offset" : [8,4]
}
}
}

View File

@@ -0,0 +1,64 @@
{
"prefab" : "prefab_root.json",
"components" : {
"named" : {
"name" : "child"
},
"rect_collider" : {
"size" : [1,2],
"offset" : [2,4]
},
"polygon_collider" : {
"points" : [[1,2],[2,3],[3,4]],
"offset" : [8,4]
}
},
"children" : [{
"uuid" : "C07CDC21-8D1A-45E5-9321-AC7B6FADA847",
"components" : {
"named" : {
"name" : "child(3)"
}
}
}],
"mod_children" : [{
"uuid" : "4A93547E-4635-4C2F-9C59-3546E11B1722",
"components" : {
"widget" : {
"size" : [10,10]
}
},
"children" : [{
"uuid" : "EA1F7728-8061-495E-9E8A-280C5E2979B3",
"prefab" : "prefab_root.json",
"components" : {
"named" : {
"name" : "subchild(1)"
}
}
}]
}, {
"uuid" : "58063213-9FC1-457C-B773-B826BE1BE6D7",
"components" : {
"widget" : {
"size" : [20,20]
}
},
"children" : [{
"uuid" : "4DDDD08D-F7B9-4588-8597-3E38051AC433",
"prefab" : "prefab_root.json",
"components" : {
"named" : {
"name" : "subchild(2)"
}
}
}]
}, {
"uuid" : "C07CDC21-8D1A-45E5-9321-AC7B6FADA847",
"components" : {
"widget" : {
"size" : [30,30]
}
}
}]
}

View File

@@ -0,0 +1,27 @@
{
"uuid" : "73740BC4-CE9F-4A7F-A029-4AB65027A8AE",
"components" : {
"named" : {
"name" : "root"
},
"circle_collider" : {
"radius" : 5,
"offset" : [4,2]
}
},
"children" : [{
"uuid" : "4A93547E-4635-4C2F-9C59-3546E11B1722",
"components" : {
"named" : {
"name" : "child(1)"
}
}
}, {
"uuid" : "58063213-9FC1-457C-B773-B826BE1BE6D7",
"components" : {
"named" : {
"name" : "child(2)"
}
}
}]
}

View File

@@ -1,5 +1,4 @@
{
"texture" : "image.png",
"pivot" : { "x" : 1, "y" : 2 },
"texrect" : { "x" : 5, "y" : 6, "w" : 7, "h" : 8 }
}

View File

@@ -1,6 +1,5 @@
{
"texture" : "image.png",
"pivot" : { "x" : 1, "y" : 2 },
"inner_texrect" : { "x" : 1, "y" : 2, "w" : 3, "h" : 4 },
"outer_texrect" : { "x" : 5, "y" : 6, "w" : 7, "h" : 8 }
}

View File

@@ -192,14 +192,12 @@ TEST_CASE("library"){
sprite_asset::ptr spr = atlas_res->find_nested_asset<sprite_asset>("sprite");
REQUIRE(spr);
REQUIRE(spr->content().pivot() == v2f(1.f,2.f));
REQUIRE(spr->content().inner_texrect() == b2f(5.f,6.f,7.f,8.f));
REQUIRE(spr->content().outer_texrect() == b2f(5.f,6.f,7.f,8.f));
REQUIRE(spr->content().texture()== texture_res);
sprite_asset::ptr spr2 = atlas_res->find_nested_asset<sprite_asset>("sprite2");
REQUIRE(spr2);
REQUIRE(spr2->content().pivot() == v2f(1.f,2.f));
REQUIRE(spr2->content().inner_texrect() == b2f(1.f,2.f,3.f,4.f));
REQUIRE(spr2->content().outer_texrect() == b2f(5.f,6.f,7.f,8.f));
REQUIRE(spr2->content().texture()== texture_res);
@@ -208,14 +206,12 @@ TEST_CASE("library"){
{
auto sprite_res = l.load_asset<sprite_asset>("sprite.json");
REQUIRE(sprite_res);
REQUIRE(sprite_res->content().pivot() == v2f(1.f, 2.f));
REQUIRE(sprite_res->content().inner_texrect() == b2f(5.f, 6.f, 7.f, 8.f));
REQUIRE(sprite_res->content().outer_texrect() == b2f(5.f, 6.f, 7.f, 8.f));
REQUIRE(sprite_res->content().texture() == texture_res);
auto sprite2_res = l.load_asset<sprite_asset>("sprite2.json");
REQUIRE(sprite2_res);
REQUIRE(sprite2_res->content().pivot() == v2f(1.f, 2.f));
REQUIRE(sprite2_res->content().inner_texrect() == b2f(1.f, 2.f, 3.f, 4.f));
REQUIRE(sprite2_res->content().outer_texrect() == b2f(5.f, 6.f, 7.f, 8.f));
REQUIRE(sprite2_res->content().texture() == texture_res);
@@ -259,28 +255,6 @@ TEST_CASE("library"){
REQUIRE(model_res->content().mesh()->content().indices_submesh_count() == 1);
REQUIRE_FALSE(model_res->content().mesh()->content().indices(0).empty());
}
{
auto prefab_res = l.load_asset<prefab_asset>("prefab.json");
REQUIRE(prefab_res);
ecs::registry w;
ecs::entity e = w.create_entity(prefab_res->content().prototype());
REQUIRE(e.exists_component<touchable>());
REQUIRE(e.exists_component<rect_collider>());
REQUIRE(e.get_component<rect_collider>().size() == v2f(1.f,2.f));
REQUIRE(e.get_component<rect_collider>().offset() == v2f(2.f,4.f));
REQUIRE(e.exists_component<circle_collider>());
REQUIRE(math::approximately(e.get_component<circle_collider>().radius(), 5.f));
REQUIRE(e.get_component<circle_collider>().offset() == v2f(4.f,2.f));
REQUIRE(e.exists_component<polygon_collider>());
REQUIRE(e.get_component<polygon_collider>().points() == vector<v2f>{{1,2},{2,3},{3,4}});
REQUIRE(e.get_component<polygon_collider>().offset() == v2f(8.f,4.f));
}
}
}
{

View File

@@ -9,19 +9,6 @@ using namespace e2d;
namespace
{
class safe_starter_initializer final : private noncopyable {
public:
safe_starter_initializer() {
modules::initialize<starter>(0, nullptr,
starter::parameters(
engine::parameters("world_untests", "enduro2d")));
}
~safe_starter_initializer() noexcept {
modules::shutdown<starter>();
}
};
class fake_node final : public node {
protected:
fake_node() : node() {
@@ -61,7 +48,6 @@ namespace
}
TEST_CASE("node") {
safe_starter_initializer initializer;
SECTION("empty_node") {
auto n = node::create();
REQUIRE(n);
@@ -317,6 +303,33 @@ TEST_CASE("node") {
REQUIRE_FALSE(n->bring_to_back());
}
}
SECTION("swap_children") {
auto p = node::create();
auto n1 = node::create(p);
auto n2 = node::create(p);
auto n3 = node::create(p);
auto p2 = node::create();
auto n4 = node::create(p2);
auto n5 = node::create();
REQUIRE_FALSE(p->swap_children(n1, node_iptr()));
REQUIRE_FALSE(p->swap_children(node_iptr(), n1));
REQUIRE_FALSE(p->swap_children(n1, p2));
REQUIRE_FALSE(p->swap_children(n1, n4));
REQUIRE_FALSE(p->swap_children(n1, n5));
REQUIRE(p->swap_children(n1, n1)); // n1 n2 n3
REQUIRE(p->swap_children(n1, n2)); // n2 n1 n3
REQUIRE(p->swap_children(n2, n3)); // n3 n1 n2
REQUIRE(p->swap_children(n2, n1)); // n3 n2 n1
REQUIRE(p->child_at(0u) == n3);
REQUIRE(p->child_at(1u) == n2);
REQUIRE(p->child_at(2u) == n1);
}
SECTION("send_forward/bring_to_front") {
{
auto p = node::create();
@@ -429,6 +442,142 @@ TEST_CASE("node") {
REQUIRE_FALSE(cn4->next_sibling());
}
}
SECTION("child_at") {
auto p = node::create();
auto n1 = node::create(p);
auto n2 = node::create(p);
auto n3 = node::create(p);
REQUIRE(p->child_at(0) == n1);
REQUIRE(p->child_at(1) == n2);
REQUIRE(p->child_at(2) == n3);
REQUIRE_FALSE(p->child_at(3));
{
const_node_iptr cp = p;
REQUIRE(cp->child_at(0) == n1);
REQUIRE(cp->child_at(1) == n2);
REQUIRE(cp->child_at(2) == n3);
REQUIRE_FALSE(cp->child_at(3));
}
}
SECTION("child_index") {
auto p = node::create();
auto n1 = node::create(p);
auto n2 = node::create(p);
auto n3 = node::create(p);
auto p2 = node::create();
auto n4 = node::create(p2);
auto n5 = node::create();
REQUIRE(p->child_index(n1).second);
REQUIRE(p->child_index(n2).second);
REQUIRE(p->child_index(n3).second);
REQUIRE_FALSE(p->child_index(n4).second);
REQUIRE_FALSE(p->child_index(n5).second);
REQUIRE(p->child_index(n1).first == 0u);
REQUIRE(p->child_index(n2).first == 1u);
REQUIRE(p->child_index(n3).first == 2u);
{
const_node_iptr cp = p;
const_node_iptr cn1 = n1;
const_node_iptr cn2 = n2;
const_node_iptr cn3 = n3;
const_node_iptr cn4 = n4;
const_node_iptr cn5 = n5;
REQUIRE(cp->child_index(cn1).second);
REQUIRE(cp->child_index(cn2).second);
REQUIRE(cp->child_index(cn3).second);
REQUIRE_FALSE(cp->child_index(cn4).second);
REQUIRE_FALSE(cp->child_index(cn5).second);
REQUIRE(cp->child_index(cn1).first == 0u);
REQUIRE(cp->child_index(cn2).first == 1u);
REQUIRE(cp->child_index(cn3).first == 2u);
}
}
SECTION("remove_child_at") {
auto p = node::create();
auto n1 = node::create(p);
auto n2 = node::create(p);
auto n3 = node::create(p);
REQUIRE_FALSE(n1->remove_child_at(0));
REQUIRE(p->remove_child_at(1) == n2);
REQUIRE_FALSE(n2->has_parent());
REQUIRE(p->child_count() == 2u);
REQUIRE(p->remove_child_at(0) == n1);
REQUIRE_FALSE(n1->has_parent());
REQUIRE(p->child_count() == 1u);
REQUIRE(p->remove_child_at(0) == n3);
REQUIRE_FALSE(n3->has_parent());
REQUIRE(p->child_count() == 0u);
}
SECTION("swap_children_at") {
auto p = node::create();
auto n1 = node::create(p);
auto n2 = node::create(p);
auto n3 = node::create(p);
REQUIRE_FALSE(p->swap_children_at(0u, 3u));
REQUIRE_FALSE(p->swap_children_at(3u, 0u));
REQUIRE(p->swap_children_at(0, 0)); // n1 n2 n3
REQUIRE(p->swap_children_at(0, 1)); // n2 n1 n3
REQUIRE(p->swap_children_at(0, 2)); // n3 n1 n2
REQUIRE(p->swap_children_at(2, 1)); // n3 n2 n1
REQUIRE(p->child_at(0u) == n3);
REQUIRE(p->child_at(1u) == n2);
REQUIRE(p->child_at(2u) == n1);
}
SECTION("add_child_at") {
auto p = node::create();
auto n1 = node::create();
auto n2 = node::create();
auto n3 = node::create();
auto n4 = node::create();
REQUIRE_FALSE(p->add_child_at(p, 0u));
REQUIRE_FALSE(p->add_child_at(nullptr, 0u));
REQUIRE_FALSE(p->add_child_at(n1, 1u));
REQUIRE(p->add_child_at(n1, 0u)); // n1
REQUIRE(p->add_child_at(n2, 0u)); // n2 n1
REQUIRE(p->add_child_at(n3, 2u)); // n2 n1 n3
REQUIRE(p->add_child_at(n4, 2u)); // n2 n1 n4 n3
REQUIRE(p->child_at(0u) == n2);
REQUIRE(p->child_at(1u) == n1);
REQUIRE(p->child_at(2u) == n4);
REQUIRE(p->child_at(3u) == n3);
REQUIRE_FALSE(p->add_child_at(n1, 5u));
REQUIRE(p->add_child_at(n1, 4u)); // n2 n4 n3 n1
REQUIRE(p->add_child_at(n3, 0u)); // n3 n2 n4 n1
REQUIRE(p->add_child_at(n4, 1u)); // n3 n4 n2 n1
REQUIRE(p->add_child_at(n4, p->child_index(n4).first)); // n3 n4 n2 n1
REQUIRE(p->child_at(0u) == n3);
REQUIRE(p->child_at(1u) == n4);
REQUIRE(p->child_at(2u) == n2);
REQUIRE(p->child_at(3u) == n1);
}
SECTION("add_child_to_back/add_child_to_front") {
auto p = node::create();
auto n1 = node::create();
@@ -439,6 +588,7 @@ TEST_CASE("node") {
REQUIRE(p->add_child_to_back(n1));
REQUIRE(p->add_child_to_back(n2));
REQUIRE(p->add_child_to_back(n3)); // n3 n2 n1
REQUIRE_FALSE(p->add_child_to_back(p));
REQUIRE_FALSE(p->add_child_to_back(nullptr));
REQUIRE(n1->prev_sibling() == n2);
@@ -474,6 +624,7 @@ TEST_CASE("node") {
REQUIRE(p->add_child_to_front(n1));
REQUIRE(p->add_child_to_front(n2));
REQUIRE(p->add_child_to_front(n3)); // n1 n2 n3
REQUIRE_FALSE(p->add_child_to_front(p));
REQUIRE_FALSE(p->add_child_to_front(nullptr));
REQUIRE(n1->next_sibling() == n2);

View File

@@ -0,0 +1,194 @@
/*******************************************************************************
* This file is part of the "Enduro2D"
* For conditions of distribution and use, see copyright notice in LICENSE.md
* Copyright (C) 2018-2020, by Matvey Cherevko (blackmatov@gmail.com)
******************************************************************************/
#include "_high.hpp"
using namespace e2d;
namespace
{
class safe_starter_initializer final : private noncopyable {
public:
safe_starter_initializer() {
modules::initialize<starter>(0, nullptr,
starter::parameters(
engine::parameters("prefab_untests", "enduro2d")));
}
~safe_starter_initializer() noexcept {
modules::shutdown<starter>();
}
};
}
TEST_CASE("prefab"){
safe_starter_initializer initializer;
library& l = the<library>();
{
auto prefab_root_res = l.load_asset<prefab_asset>("prefab_root.json");
REQUIRE(prefab_root_res);
const prefab& prefab_root = prefab_root_res->content();
REQUIRE(prefab_root.uuid() == "73740BC4-CE9F-4A7F-A029-4AB65027A8AE");
REQUIRE(prefab_root.children().size() == 2u);
REQUIRE(prefab_root.children()[0].uuid() == "4A93547E-4635-4C2F-9C59-3546E11B1722");
REQUIRE(prefab_root.children()[1].uuid() == "58063213-9FC1-457C-B773-B826BE1BE6D7");
auto go = the<world>().instantiate(prefab_root);
{
REQUIRE(go.component<named>());
REQUIRE(go.component<named>()->name() == "root");
REQUIRE(go.component<circle_collider>());
REQUIRE(go.component<circle_collider>()->radius() == Approx(5.f));
REQUIRE(go.component<circle_collider>()->offset() == v2f(4.f,2.f));
}
{
node_iptr go_node = go.component<actor>()
? go.component<actor>()->node()
: node_iptr();
REQUIRE(go_node);
REQUIRE(go_node->owner() == go);
REQUIRE(go_node->child_count() == 2u);
node_iptr child1 = go_node->child_at(0u);
node_iptr child2 = go_node->child_at(1u);
REQUIRE(child1);
REQUIRE(child2);
gobject child1_go = child1->owner();
gobject child2_go = child2->owner();
REQUIRE(child1_go);
REQUIRE(child2_go);
REQUIRE(child1_go.component<named>());
REQUIRE(child1_go.component<named>()->name() == "child(1)");
REQUIRE(child2_go.component<named>());
REQUIRE(child2_go.component<named>()->name() == "child(2)");
node_iptr child1_node = child1_go.component<actor>()
? child1_go.component<actor>()->node()
: node_iptr();
node_iptr child2_node = child2_go.component<actor>()
? child2_go.component<actor>()->node()
: node_iptr();
REQUIRE(child1_node);
REQUIRE(child1_node->owner() == child1_go);
REQUIRE(child1_node->child_count() == 0u);
REQUIRE(child2_node);
REQUIRE(child2_node->owner() == child2_go);
REQUIRE(child2_node->child_count() == 0u);
}
}
{
auto prefab_child_res = l.load_asset<prefab_asset>("prefab_child.json");
REQUIRE(prefab_child_res);
const prefab& prefab_child = prefab_child_res->content();
REQUIRE(prefab_child.uuid().empty());
REQUIRE(prefab_child.children().size() == 3u);
REQUIRE(prefab_child.children()[0].uuid() == "4A93547E-4635-4C2F-9C59-3546E11B1722");
REQUIRE(prefab_child.children()[1].uuid() == "58063213-9FC1-457C-B773-B826BE1BE6D7");
REQUIRE(prefab_child.children()[2].uuid() == "C07CDC21-8D1A-45E5-9321-AC7B6FADA847");
auto go = the<world>().instantiate(prefab_child);
{
REQUIRE(go.component<named>());
REQUIRE(go.component<named>()->name() == "child");
REQUIRE(go.component<rect_collider>());
REQUIRE(go.component<rect_collider>()->size() == v2f(1.f,2.f));
REQUIRE(go.component<rect_collider>()->offset() == v2f(2.f,4.f));
REQUIRE(go.component<circle_collider>());
REQUIRE(go.component<circle_collider>()->radius() == Approx(5.f));
REQUIRE(go.component<circle_collider>()->offset() == v2f(4.f,2.f));
REQUIRE(go.component<polygon_collider>());
REQUIRE(go.component<polygon_collider>()->points() == vector<v2f>{{1,2},{2,3},{3,4}});
REQUIRE(go.component<polygon_collider>()->offset() == v2f(8.f,4.f));
}
{
node_iptr go_node = go.component<actor>()
? go.component<actor>()->node()
: node_iptr();
REQUIRE(go_node);
REQUIRE(go_node->owner() == go);
REQUIRE(go_node->child_count() == 3u);
node_iptr child1 = go_node->child_at(0u);
node_iptr child2 = go_node->child_at(1u);
node_iptr child3 = go_node->child_at(2u);
REQUIRE(child1);
REQUIRE(child2);
REQUIRE(child3);
gobject child1_go = child1->owner();
gobject child2_go = child2->owner();
gobject child3_go = child3->owner();
REQUIRE(child1_go);
REQUIRE(child2_go);
REQUIRE(child3_go);
REQUIRE(child1_go.component<named>());
REQUIRE(child1_go.component<widget>());
REQUIRE(child1_go.component<named>()->name() == "child(1)");
REQUIRE(child1_go.component<widget>()->size() == v2f(10.f, 10.f));
REQUIRE(child2_go.component<named>());
REQUIRE(child2_go.component<widget>());
REQUIRE(child2_go.component<named>()->name() == "child(2)");
REQUIRE(child2_go.component<widget>()->size() == v2f(20.f, 20.f));
REQUIRE(child3_go.component<named>());
REQUIRE(child3_go.component<widget>());
REQUIRE(child3_go.component<named>()->name() == "child(3)");
REQUIRE(child3_go.component<widget>()->size() == v2f(30.f, 30.f));
node_iptr child1_node = child1_go.component<actor>()
? child1_go.component<actor>()->node()
: node_iptr();
node_iptr child2_node = child2_go.component<actor>()
? child2_go.component<actor>()->node()
: node_iptr();
node_iptr child3_node = child3_go.component<actor>()
? child3_go.component<actor>()->node()
: node_iptr();
REQUIRE(child1_node);
REQUIRE(child1_node->owner() == child1_go);
REQUIRE(child1_node->child_count() == 1u);
REQUIRE(child1_node->first_child()->child_count() == 2u);
REQUIRE(child2_node);
REQUIRE(child2_node->owner() == child2_go);
REQUIRE(child2_node->child_count() == 1u);
REQUIRE(child2_node->first_child()->child_count() == 2u);
REQUIRE(child3_node);
REQUIRE(child3_node->owner() == child3_go);
REQUIRE(child3_node->child_count() == 0u);
}
}
}

View File

@@ -7,6 +7,8 @@
#include "_utils.hpp"
using namespace e2d;
#include <random>
namespace
{
struct ilist_tag1 {};
@@ -21,6 +23,10 @@ namespace
obj_t() = default;
obj_t(int ni) : i(ni) {}
};
bool operator<(const obj_t& l, const obj_t& r) noexcept {
return l.i < r.i;
}
}
TEST_CASE("intrusive_list") {
@@ -433,4 +439,36 @@ TEST_CASE("intrusive_list") {
}
}
}
SECTION("sort") {
{
std::random_device rd;
std::mt19937 rnd(rd());
std::uniform_int_distribution<u32> uni_size(0, 1024);
std::uniform_int_distribution<i32> uni_number(-65536, 65535);
const auto pred = [](const obj_t& l, const obj_t& r) noexcept {
return l.i < r.i;
};
const auto r_pred = [](const obj_t& l, const obj_t& r) noexcept {
return l.i > r.i;
};
for ( std::size_t i = 0; i < 1024; ++i ) {
vector<std::unique_ptr<obj_t>> objs;
intrusive_list<obj_t, ilist_tag1> l;
for ( u32 b = 0, e = uni_size(rnd); b < e; ++b ) {
objs.push_back(std::make_unique<obj_t>(uni_number(rnd)));
l.push_back(*objs.back());
}
l.sort();
REQUIRE(std::is_sorted(l.cbegin(), l.cend()));
l.sort(r_pred);
REQUIRE(std::is_sorted(l.cbegin(), l.cend(), r_pred));
l.sort(pred);
REQUIRE(std::is_sorted(l.cbegin(), l.cend(), pred));
}
}
}
}