diff --git a/project/Easy2D/Easy2D.vcxproj b/project/Easy2D/Easy2D.vcxproj index 1c9388ff..50697a0b 100644 --- a/project/Easy2D/Easy2D.vcxproj +++ b/project/Easy2D/Easy2D.vcxproj @@ -7,6 +7,7 @@ + diff --git a/project/Easy2D/Easy2D.vcxproj.filters b/project/Easy2D/Easy2D.vcxproj.filters index 0453e1d6..31e88199 100644 --- a/project/Easy2D/Easy2D.vcxproj.filters +++ b/project/Easy2D/Easy2D.vcxproj.filters @@ -217,6 +217,9 @@ math + + core + diff --git a/src/core/ActionGroup.cpp b/src/core/ActionGroup.cpp index e9dbd3b8..44fd0ee8 100644 --- a/src/core/ActionGroup.cpp +++ b/src/core/ActionGroup.cpp @@ -182,9 +182,13 @@ namespace easy2d void Sequence::Add(Array const& actions) { - for (const auto &action : actions) + if (actions_.empty()) + actions_ = actions; + else { - this->Add(action); + actions_.reserve(actions_.size() + actions.size()); + for (const auto& action : actions) + Add(action); } } @@ -253,7 +257,7 @@ namespace easy2d { Action::Update(target, dt); - size_t done_num = 0; + int done_num = 0; for (const auto& action : actions_) { if (action->IsDone()) @@ -291,9 +295,13 @@ namespace easy2d void Spawn::Add(Array const& actions) { - for (const auto &action : actions) + if (actions_.empty()) + actions_ = actions; + else { - this->Add(action); + actions_.reserve(actions_.size() + actions.size()); + for (const auto& action : actions) + Add(action); } } diff --git a/src/core/Animation.cpp b/src/core/Animation.cpp index 678959e3..cb052fca 100644 --- a/src/core/Animation.cpp +++ b/src/core/Animation.cpp @@ -76,8 +76,8 @@ namespace easy2d E2D_ASSERT(dynamic_cast(target) && "Animation only supports Sprites"); const auto& frames = frames_->GetFrames(); - size_t size = frames.size(); - size_t index = std::min(static_cast(math::Floor(size * step)), size - 1); + int size = frames.size(); + int index = std::min(static_cast(math::Floor(size * step)), size - 1); static_cast(target)->Load(frames[index]); } diff --git a/src/core/Array.h b/src/core/Array.h new file mode 100644 index 00000000..988df825 --- /dev/null +++ b/src/core/Array.h @@ -0,0 +1,102 @@ +// Copyright (c) 2016-2018 Easy2D - Nomango +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#pragma once +#include "macros.h" + +namespace easy2d +{ + // + // Array + // Lightweight std::vector<>-like class + // + template> + class Array : _Alloc + { + public: + using value_type = _Ty; + using allocator_type = _Alloc; + using iterator = value_type*; + using const_iterator = const value_type*; + using reference = value_type &; + using const_reference = const value_type &; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + inline Array() { size_ = capacity_ = 0; data_ = nullptr; } + inline Array(std::initializer_list<_Ty> const& list) { size_ = capacity_ = 0; data_ = nullptr; operator=(list); } + inline Array(const Array<_Ty>& src) { size_ = capacity_ = 0; data_ = nullptr; operator=(src); } + inline Array(Array<_Ty>&& src) { size_ = capacity_ = 0; data_ = nullptr; operator=(src); } + inline ~Array() { if (data_) _destroy_all(); } + + inline Array<_Ty>& operator=(const Array<_Ty>& src) { if (&src == this) { return *this; } clear(); reserve(src.size_); std::uninitialized_copy(src.begin(), src.end(), begin()); size_ = src.size_; return *this; } + inline Array<_Ty>& operator=(Array<_Ty>&& src) { clear(); size_ = src.size_; capacity_ = src.capacity_; data_ = src.data_; src.data_ = src.size_ = src.capacity_ = 0; return *this; } + inline Array<_Ty>& operator=(std::initializer_list<_Ty> const& list) { clear(); reserve((int)list.size()); std::uninitialized_copy(list.begin(), list.end(), begin()); size_ = (int)list.size(); return *this; } + + inline bool empty() const { return size_ == 0; } + inline int size() const { return size_; } + inline int size_in_bytes() const { return size_ * ((int)sizeof(_Ty)); } + inline int capacity() const { return capacity_; } + inline reference operator[](int i) { if (i < 0 || i >= size_) throw std::out_of_range("vector subscript out of range"); return data_[i]; } + inline const_reference operator[](int i) const { if (i < 0 || i >= size_) throw std::out_of_range("vector subscript out of range"); return data_[i]; } + + inline void clear() { if (data_) { _destroy_all(); } } + inline iterator begin() { return iterator(data_); } + inline const_iterator begin() const { return const_iterator(data_); } + inline const_iterator cbegin() const { return begin(); } + inline iterator end() { return iterator(data_ + size_); } + inline const_iterator end() const { return const_iterator(data_ + size_); } + inline const_iterator cend() const { return end(); } + inline reverse_iterator rbegin() { return reverse_iterator(end()); } + inline const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + inline const_reverse_iterator crbegin() const { return rbegin(); } + inline reverse_iterator rend() { return reverse_iterator(begin()); } + inline const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + inline const_reverse_iterator crend() const { return rend(); } + inline reference front() { if (empty()) throw std::out_of_range("front() called on empty array"); return data_[0]; } + inline const_reference front() const { if (empty()) throw std::out_of_range("front() called on empty array"); return data_[0]; } + inline reference back() { if (empty()) throw std::out_of_range("back() called on empty array"); return data_[size_ - 1]; } + inline const_reference back() const { if (empty()) throw std::out_of_range("back() called on empty array"); return data_[size_ - 1]; } + inline void swap(Array<_Ty>& rhs) { int rhs_size = rhs.size_; rhs.size_ = size_; size_ = rhs_size; int rhs_cap = rhs.capacity_; rhs.capacity_ = capacity_; capacity_ = rhs_cap; _Ty* rhs_data = rhs.data_; rhs.data_ = data_; data_ = rhs_data; } + + inline void resize(int new_size) { if (new_size > capacity_) { reserve(_grow_capacity(new_size)); } _Ty tmp; std::uninitialized_fill_n(data_ + size_, new_size - size_, tmp); size_ = new_size; } + inline void resize(int new_size, const _Ty& v) { if (new_size > capacity_) reserve(_grow_capacity(new_size)); if (new_size > size_) std::uninitialized_fill_n(data_ + size_, new_size - size_, v); size_ = new_size; } + inline void reserve(int new_capacity) { if (new_capacity <= capacity_) return; _Ty* new_data = _Alloc::allocate(new_capacity); if (data_) { ::memcpy(new_data, data_, (size_t)size_ * sizeof(_Ty)); _Alloc::deallocate(data_, capacity_); } data_ = new_data; capacity_ = new_capacity; } + + inline void push_back(const _Ty& v) { if (size_ == capacity_) reserve(_grow_capacity(size_ + 1)); _Alloc::construct(data_ + size_, v); size_++; } + inline void pop_back() { if (empty()) throw std::out_of_range("vector empty before pop"); size_--; } + inline void push_front(const _Ty& v) { if (size_ == 0) push_back(v); else insert(data_, v); } + inline iterator erase(const_iterator it) { E2D_ASSERT(it >= data_ && it < data_ + size_); _Alloc::destroy(it); const ptrdiff_t off = it - data_; ::memmove(data_ + off, data_ + off + 1, ((size_t)size_ - (size_t)off - 1) * sizeof(_Ty)); size_--; return data_ + off; } + inline iterator erase(const_iterator it, const_iterator it_last) { E2D_ASSERT(it >= data_ && it < data_ + size_ && it_last > it && it_last <= data_ + size_); _destroy(it, it_last); const ptrdiff_t count = it_last - it; const ptrdiff_t off = it - data_; ::memmove(data_ + off, data_ + off + count, ((size_t)size_ - (size_t)off - count) * sizeof(_Ty)); size_ -= (int)count; return data_ + off; } + inline iterator insert(const_iterator it, const _Ty& v) { E2D_ASSERT(it >= data_ && it <= data_ + size_); const ptrdiff_t off = it - data_; if (size_ == capacity_) reserve(_grow_capacity(size_ + 1)); if (off < (int)size_) ::memmove(data_ + off + 1, data_ + off, ((size_t)size_ - (size_t)off) * sizeof(_Ty)); _Alloc::construct(data_ + off, v); size_++; return data_ + off; } + inline bool contains(const _Ty& v) const { const _Ty* data = data_; const _Ty* data_end = data_ + size_; while (data < data_end) if (*data++ == v) return true; return false; } + inline int index_of(const_iterator it) const { E2D_ASSERT(it >= data_ && it <= data_ + size_); const ptrdiff_t off = it - data_; return (int)off; } + + private: + inline int _grow_capacity(int sz) const { int new_capacity = capacity_ ? (capacity_ + capacity_ / 2) : 8; return new_capacity > sz ? new_capacity : sz; } + inline void _destroy(iterator it, iterator it_last) { E2D_ASSERT(it >= data_ && it < data_ + size_ && it_last > it && it_last <= data_ + size_); for (; it != it_last; ++it) _Alloc::destroy(it); } + inline void _destroy_all() { E2D_ASSERT((data_ && capacity_) || (!data_ && !capacity_)); if (size_) _destroy(begin(), end()); if (data_ && capacity_) _Alloc::deallocate(data_, capacity_); size_ = capacity_ = 0; data_ = nullptr; } + + private: + int size_; + int capacity_; + _Ty* data_; + }; +} diff --git a/src/core/Canvas.cpp b/src/core/Canvas.cpp index c1dfad40..68e25302 100644 --- a/src/core/Canvas.cpp +++ b/src/core/Canvas.cpp @@ -422,12 +422,9 @@ namespace easy2d { if (current_sink_ && !points.empty()) { - auto d2d_points = reinterpret_cast const&>(points); - auto size = d2d_points.size(); - current_sink_->AddLines( - &d2d_points[0], - static_cast(size) + reinterpret_cast(&points[0]), + static_cast(points.size()) ); } } diff --git a/src/core/Frames.cpp b/src/core/Frames.cpp index c700c445..f90e71bb 100644 --- a/src/core/Frames.cpp +++ b/src/core/Frames.cpp @@ -49,9 +49,13 @@ namespace easy2d void Frames::Add(Array const& frames) { - for (const auto &image : frames) + if (frames_.empty()) + frames_ = frames; + else { - this->Add(image); + frames_.reserve(frames_.size() + frames.size()); + for (const auto& image : frames) + Add(image); } } diff --git a/src/core/Geometry.cpp b/src/core/Geometry.cpp index 76387963..4a8d839c 100644 --- a/src/core/Geometry.cpp +++ b/src/core/Geometry.cpp @@ -328,12 +328,9 @@ namespace easy2d { if (current_sink_ && !points.empty()) { - auto d2d_points = reinterpret_cast const&>(points); - auto size = d2d_points.size(); - current_sink_->AddLines( - &d2d_points[0], - static_cast(size) + reinterpret_cast(&points[0]), + static_cast(points.size()) ); } } diff --git a/src/core/Object.cpp b/src/core/Object.cpp index e9a41c6d..2a956d51 100644 --- a/src/core/Object.cpp +++ b/src/core/Object.cpp @@ -30,6 +30,7 @@ namespace easy2d Object::Object() : tracing_leak_(false) + , user_data_(nullptr) { #ifdef E2D_DEBUG diff --git a/src/core/helper.hpp b/src/core/helper.hpp index 6fc580aa..f8828b12 100644 --- a/src/core/helper.hpp +++ b/src/core/helper.hpp @@ -21,6 +21,7 @@ #pragma once #include "RefCounter.hpp" #include "IntrusivePtr.hpp" +#include "Array.h" #include "closure.hpp" #include "../math/vector.hpp" #include "../math/Rect.hpp" @@ -53,9 +54,6 @@ namespace easy2d template using Pair = std::pair; - template - using Array = std::vector; - template using List = std::list; diff --git a/src/ui/Menu.cpp b/src/ui/Menu.cpp index 78e11b5e..181de680 100644 --- a/src/ui/Menu.cpp +++ b/src/ui/Menu.cpp @@ -43,7 +43,7 @@ namespace easy2d return enabled_; } - size_t Menu::GetButtonCount() const + int Menu::GetButtonCount() const { return buttons_.size(); } diff --git a/src/ui/Menu.h b/src/ui/Menu.h index fefd7828..56fc562a 100644 --- a/src/ui/Menu.h +++ b/src/ui/Menu.h @@ -40,7 +40,7 @@ namespace easy2d bool IsEnable() const; // 获取菜单中的按钮数量 - size_t GetButtonCount() const; + int GetButtonCount() const; // 设置菜单启用或禁用 void SetEnabled( diff --git a/src/utils/ResLoader.cpp b/src/utils/ResLoader.cpp index 014f6fc5..16e661a3 100644 --- a/src/utils/ResLoader.cpp +++ b/src/utils/ResLoader.cpp @@ -79,33 +79,40 @@ namespace easy2d return 0; int total = 0; - FramesPtr frames = new (std::nothrow) Frames; - if (frames) - { - for (const auto& image : images) - { - ImagePtr ptr = new (std::nothrow) Image; - if (ptr) - { - if (image.IsFile()) - { - String path = Search(image.GetFileName(), search_paths_); - ptr->Load(path.c_str()); - } - else - ptr->Load(image); + Array image_arr; - if (ptr->IsValid()) - { - frames->Add(ptr); - ++total; - } + image_arr.reserve(images.size()); + for (const auto& image : images) + { + ImagePtr ptr = new (std::nothrow) Image; + if (ptr) + { + if (image.IsFile()) + { + String path = Search(image.GetFileName(), search_paths_); + ptr->Load(path.c_str()); + } + else + ptr->Load(image); + + if (ptr->IsValid()) + { + image_arr.push_back(ptr); + ++total; } } } + if (total) - res_.insert(std::make_pair(id, frames)); - return total; + { + FramesPtr frames = new (std::nothrow) Frames(image_arr); + if (frames) + { + res_.insert(std::make_pair(id, frames)); + return total; + } + } + return 0; } int ResLoader::AddFrames(String const& id, Array const& images) @@ -113,22 +120,13 @@ namespace easy2d if (images.empty()) return 0; - int total = 0; - FramesPtr frames = new (std::nothrow) Frames; + FramesPtr frames = new (std::nothrow) Frames(images); if (frames) { - for (const auto& image : images) - { - if (image) - { - frames->Add(image); - total++; - } - } - } - if (total) res_.insert(std::make_pair(id, frames)); - return total; + return frames->GetFrames().size(); + } + return 0; } int ResLoader::AddFrames(String const & id, Resource const & image, int cols, int rows)