Merge branch 'master' into console-widget
This commit is contained in:
commit
400e8e92aa
102
ChangeLog.md
102
ChangeLog.md
|
|
@ -16,10 +16,13 @@ Miscellaneous:
|
||||||
- Add Lua unit tests
|
- Add Lua unit tests
|
||||||
- NDEBUG is now defined in Release
|
- NDEBUG is now defined in Release
|
||||||
- Replaced typedefs keywords with modern using keywords
|
- Replaced typedefs keywords with modern using keywords
|
||||||
|
- When supported, projects are now parts of a virtual "workspace group" according to their kind
|
||||||
|
- Fixed .dll copy when building Nazara occuring on Linux when targeting Windows (MinGW)
|
||||||
|
- ⚠ Appveyor nightlies are now compiled with VS2017
|
||||||
|
|
||||||
Nazara Engine:
|
Nazara Engine:
|
||||||
- VertexMapper:GetComponentPtr no longer throw an error if component is disabled or incompatible with template type, instead a null pointer is returned.
|
- VertexMapper:GetComponentPtr no longer throw an error if component is disabled or incompatible with template type, instead a null pointer is returned.
|
||||||
- Bitset swap operation is now correctly marked as noexcept`
|
- Bitset swap operation is now correctly marked as noexcept
|
||||||
- Mesh loaders now takes MeshParams vertexDeclaration into account
|
- Mesh loaders now takes MeshParams vertexDeclaration into account
|
||||||
- ⚠️ Replaced RenderTarget::Get[Height|Width] by RenderTarget::GetSize
|
- ⚠️ Replaced RenderTarget::Get[Height|Width] by RenderTarget::GetSize
|
||||||
- ⚠️ Removed Window::Get[Height|Width] methods
|
- ⚠️ Removed Window::Get[Height|Width] methods
|
||||||
|
|
@ -86,6 +89,72 @@ Nazara Engine:
|
||||||
- Fixed Billboard bounding volume
|
- Fixed Billboard bounding volume
|
||||||
- Fixed Directory::GetResultSize and Directory::IsResultDirectory on Posix systems
|
- Fixed Directory::GetResultSize and Directory::IsResultDirectory on Posix systems
|
||||||
- Fixed Quaternion::Inverse which was not correctly normalizing quaternions
|
- Fixed Quaternion::Inverse which was not correctly normalizing quaternions
|
||||||
|
- Graphics module now register "White2D" and "WhiteCubemap" textures to the TextureLibrary (respectively a 1x1 texture 2D and a 1x1 texture cubemap)
|
||||||
|
- Added AbstractTextDrawer::GetLineGlyphCount, which returns the number of glyph part of the line
|
||||||
|
- Fixed Font handling of whitespace glyphs (which were triggering an error)
|
||||||
|
- ⚠️ Translucent2D pipeline no longer has depth sorting
|
||||||
|
- Fixed SimpleTextDrawer line bounds
|
||||||
|
- ⚠️ Stream::ReadLine will now returns empty lines if present in the file
|
||||||
|
- Fixed cubemaps seams with OpenGL
|
||||||
|
- HandledObject movement constructor/assignement operator are now marked noexcept
|
||||||
|
- ⚠️ PhysWorld2D callbacks OnPhysWorld2DPreStep and OnPhysWorld2DPostStep now takes a invStepCount depending on the number of step taken this update, fixing force application and other
|
||||||
|
- ⚠️ Refactored Mesh/SubMesh, allowing a submesh to be attached to multiple meshes, deprecating Create/Destroy methods
|
||||||
|
- SubMesh class now has a OnSubMeshInvalidateAABB signal, triggered when a new AABB is set to the submesh
|
||||||
|
- Mesh class now has a OnMeshInvalidateAABB signal, triggered when a mesh invalidates its AABB, which is also submesh updates its AABB
|
||||||
|
- Model now invalidate properly their bounding volume when their mesh AABB is updated
|
||||||
|
- Added operator&/|/^ taking an enumeration value and a Flags object using the same enumeration type.
|
||||||
|
- Added LuaState::CallWithHandler methods, allowing to setup a error handler function
|
||||||
|
- Added LuaState::Traceback method
|
||||||
|
- Added ModelLibrary, ModelManager and ModelSaver
|
||||||
|
- Added AbstractViewer::Project and AbstractViewer::Unproject methods
|
||||||
|
- Added AbstractViewer::ProjectDepth method
|
||||||
|
- Fixed SocketPoller not be able to recover from some errors (like invalid sockets and such)
|
||||||
|
- Add LuaImplQuery implementation for std::vector
|
||||||
|
- Fixed LuaState::PushGlobal & LuaState::PushField to copy the object before moving it
|
||||||
|
- ⚠️ Replaced currentBitPos and currentByte fields by [read|write][BitPos][Byte] to handle properly bit reading/writing.
|
||||||
|
- InstancedRenderable::SetMaterial methods are now public.
|
||||||
|
- Fixed Model copy constructor not copying materials
|
||||||
|
- ⚠️ Added InstancedRenderable::Clone() method
|
||||||
|
- Fixed a lot of classes not having their move constructor/assignation operator marked noexcept
|
||||||
|
- ⚠️ SocketPoller::Wait now returns the number of socket marked as ready, and takes an additional optional parameter allowing to query the last error.
|
||||||
|
- SocketPoller will now silently ignore "interrupt errors"
|
||||||
|
- Added RigidBody2D::ClosestPointQuery
|
||||||
|
- Fix Sprite copy constructor not copying corner colors
|
||||||
|
- Added ObjectLibrary::Clear method
|
||||||
|
- ⚠️ StackArray class and macro was moved from Core/MemoryHelper.hpp to Core/StackArray.hpp
|
||||||
|
- ⚠️ Renamed NazaraStackAllocation[NoInit] macro to NazaraStackArray[NoInit]
|
||||||
|
- Added StackVector class
|
||||||
|
- ⚠️ Removed Vector[2|3]::Distancef method and made Distance method templated
|
||||||
|
- Added Vector2::Distance static method
|
||||||
|
- ⚠️ Fixed compilation errors on MSVC with flag /permissive- on CullingList class
|
||||||
|
- Added LuaImplQueryArg & LuaImplReplyVal functions for Vector[2|3]<int>
|
||||||
|
- Fixed bug in ENet implementation causing legit reliable packets to be dropped on sequence number overflow
|
||||||
|
- Fixed bug where index wouldn't be used in String::FindLast and String::FindWord
|
||||||
|
- Physics 2D contact callbacks now include an arbiter allowing to query/set parameters about the collision
|
||||||
|
- Added movement with Ctrl in TextAreaWidget
|
||||||
|
- Added Unicode Data downloader/parser
|
||||||
|
- Integrated Unicode Data
|
||||||
|
- Added CullingList::FillWithAllEntries method
|
||||||
|
- Fixed ObjectHandle movement sometimes not resetting its internal pointer
|
||||||
|
- Added BoxCollider2D::GetRadius
|
||||||
|
- Added CircleCollider2D::GetOffset
|
||||||
|
- Added ConvexCollider2D::GetVertices
|
||||||
|
- Added SegmentCollider2D::GetThickness
|
||||||
|
- Fixed vertices generation/render queue submit when using multiples materials on a Tilemap
|
||||||
|
- It is now possible to prevent CompoundCollider2D to override individual colliders properties
|
||||||
|
- Fixed TcpClient::WaitForConnected possible failure (although connected) on Windows/Linux
|
||||||
|
- CullingList now handles box tests
|
||||||
|
- ⚠️ CullingList now handles full and partial visibility testing
|
||||||
|
- Added math class Angle, capable of handling both degrees and radians angles and converting them to euler angles/quaternions to improve 2D interface.
|
||||||
|
- ⚠️ AbstractSocket::OnStateChange has been replaced by OnStateChanged, which is now called after state has been changed (with oldState and newState as parameters).
|
||||||
|
- ⚠️ TcpClient::WaitForconnected now returns the new socket state.
|
||||||
|
- Added TcpClient::PollForConnected
|
||||||
|
- ⚠️ Use of the new Angle class instead of floating point angle
|
||||||
|
- It is now possible to set elasticity/friction/surface bodies of 2D colliders and change it at runtime on RigidBody2D
|
||||||
|
- ObjectHandle were remade and should be way more optimized now
|
||||||
|
- Added ENetHost and ENetPeer accessor to total packet/data received/sent/lost
|
||||||
|
- ⚠ **Changed the way resources were Loaded, almost every LoadFromX and OpenFromX methods are now static and create the object themselves.**
|
||||||
|
- ⚠ SoundStream is now responsible for loaders instead of Music, and is now threadsafe (you can now load a stream only once and play it multiple times at the same time)
|
||||||
|
|
||||||
Nazara Development Kit:
|
Nazara Development Kit:
|
||||||
- Added ImageWidget (#139)
|
- Added ImageWidget (#139)
|
||||||
|
|
@ -129,6 +198,34 @@ Nazara Development Kit:
|
||||||
- Fix GraphicsComponent bounding volume not taking local matrix in account
|
- Fix GraphicsComponent bounding volume not taking local matrix in account
|
||||||
- ⚠️ Rewrote all render queue system, which should be more efficient, take scissor box into account
|
- ⚠️ Rewrote all render queue system, which should be more efficient, take scissor box into account
|
||||||
- ⚠️ All widgets are now bound to a scissor box when rendering
|
- ⚠️ All widgets are now bound to a scissor box when rendering
|
||||||
|
- Add DebugComponent (a component able to show aabb/obb/collision mesh)
|
||||||
|
- ⚠️ TextAreaWidget now support text selection (WIP)
|
||||||
|
- ⚠️ TextAreaWidget::GetHoveredGlyph now returns a two-dimensional position instead of a single glyph position
|
||||||
|
- Fixed Entity::OnEntityDestruction signal not being properly moved and thus not being called.
|
||||||
|
- Fixed EntityOwner move assignment which was losing entity ownership
|
||||||
|
- Added GraphicsComponent:ForEachRenderable method
|
||||||
|
- Fixed GraphicsComponent reflective material count which was not initialized
|
||||||
|
- Added PhysicsComponent2D::ClosestPointQuery
|
||||||
|
- Fixed GraphicsComponent copy constructor not copying scissor rect
|
||||||
|
- Force parent parameter to be present in widgets constructor
|
||||||
|
- Added the possibility to write only specific characters with a predicate in TextAreaWidget
|
||||||
|
- Enable write of Tab character in TextAreaWidget
|
||||||
|
- It is now possible to disable object culling in the RenderSystem
|
||||||
|
- Make Nz::PhysWorld2D& Ndk::PhysicsSystem2D::GetWorld private and rename it into GetPhysWorld
|
||||||
|
- Make Ndk::PhysicsSystem2D an interface of Nz::PhysWorld2D
|
||||||
|
- ⚠️ GraphicsComponent no longer has a BoundingVolume, it instead has only an AABB with its attached InstancedRenderable getting a BoundingVolume of their own, improving culling possibilities.
|
||||||
|
- RenderSystem now does cull InstancedRenderables attached to a GraphicsComponent, improving performance.
|
||||||
|
- ⚠️ Widgets have been reworked and no longer have padding, but instead have preferred, maximum and minimum size.
|
||||||
|
- ⚠️ BaseWidget::SetSize has been renamed to BaseWidget::Resize
|
||||||
|
- Added BaseWidget::ForEachWidgetChild
|
||||||
|
- Added experimental BoxLayout class
|
||||||
|
- RenderSystem now resolve skinning before render
|
||||||
|
- EntityOwner constructor taking a Entity* is no longer explicit
|
||||||
|
- PhysicsComponent2D now allows massless bodies (zero mass)
|
||||||
|
- ⚠️ Use of the new Angle class instead of floating point angle
|
||||||
|
- Added EntityOwner::Release
|
||||||
|
- Add missing `recomputeMoment` parameter to PhysicsComponent2D::SetMass
|
||||||
|
- Added possibility of disabling synchronization between PhysicsComponent2D and NodeComponent
|
||||||
|
|
||||||
# 0.4:
|
# 0.4:
|
||||||
|
|
||||||
|
|
@ -174,7 +271,8 @@ Nazara Engine:
|
||||||
- Added VertexMapper::GetVertexCount()
|
- Added VertexMapper::GetVertexCount()
|
||||||
- Added VertexMapper::HasComponentOfType()
|
- Added VertexMapper::HasComponentOfType()
|
||||||
- Fixed SimpleTextDrawer bounds computation
|
- Fixed SimpleTextDrawer bounds computation
|
||||||
|
- Added LuaState::Load methods which allows to load (compile) lua code to function without executing it.
|
||||||
|
- Added ENetPeer::GetLastReceiveTime() which gives the last time a reliable packet was received.
|
||||||
|
|
||||||
Nazara Development Kit:
|
Nazara Development Kit:
|
||||||
- ⚠️ Components no longer need to be copyable by assignation
|
- ⚠️ Components no longer need to be copyable by assignation
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ namespace Ndk
|
||||||
using Factory = std::function<BaseComponent*()>;
|
using Factory = std::function<BaseComponent*()>;
|
||||||
|
|
||||||
BaseComponent(ComponentIndex componentIndex);
|
BaseComponent(ComponentIndex componentIndex);
|
||||||
BaseComponent(BaseComponent&&) = default;
|
BaseComponent(BaseComponent&&) noexcept = default;
|
||||||
virtual ~BaseComponent();
|
virtual ~BaseComponent();
|
||||||
|
|
||||||
virtual std::unique_ptr<BaseComponent> Clone() const = 0;
|
virtual std::unique_ptr<BaseComponent> Clone() const = 0;
|
||||||
|
|
@ -34,7 +34,7 @@ namespace Ndk
|
||||||
inline static ComponentIndex GetMaxComponentIndex();
|
inline static ComponentIndex GetMaxComponentIndex();
|
||||||
|
|
||||||
BaseComponent& operator=(const BaseComponent&) = delete;
|
BaseComponent& operator=(const BaseComponent&) = delete;
|
||||||
BaseComponent& operator=(BaseComponent&&) = default;
|
BaseComponent& operator=(BaseComponent&&) noexcept = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BaseComponent(const BaseComponent&) = default;
|
BaseComponent(const BaseComponent&) = default;
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ namespace Ndk
|
||||||
|
|
||||||
BaseWidget(BaseWidget* parent);
|
BaseWidget(BaseWidget* parent);
|
||||||
BaseWidget(const BaseWidget&) = delete;
|
BaseWidget(const BaseWidget&) = delete;
|
||||||
BaseWidget(BaseWidget&&) = default;
|
BaseWidget(BaseWidget&&) = delete;
|
||||||
virtual ~BaseWidget();
|
virtual ~BaseWidget();
|
||||||
|
|
||||||
template<typename T, typename... Args> T* Add(Args&&... args);
|
template<typename T, typename... Args> T* Add(Args&&... args);
|
||||||
|
|
@ -46,44 +46,61 @@ namespace Ndk
|
||||||
|
|
||||||
void EnableBackground(bool enable);
|
void EnableBackground(bool enable);
|
||||||
|
|
||||||
|
template<typename F> void ForEachWidgetChild(F iterator);
|
||||||
|
template<typename F> void ForEachWidgetChild(F iterator) const;
|
||||||
|
|
||||||
//virtual BaseWidget* Clone() const = 0;
|
//virtual BaseWidget* Clone() const = 0;
|
||||||
|
|
||||||
inline const Nz::Color& GetBackgroundColor() const;
|
inline const Nz::Color& GetBackgroundColor() const;
|
||||||
inline Canvas* GetCanvas();
|
inline Canvas* GetCanvas();
|
||||||
inline Nz::SystemCursor GetCursor() const;
|
inline Nz::SystemCursor GetCursor() const;
|
||||||
inline const Padding& GetPadding() const;
|
inline float GetHeight() const;
|
||||||
inline Nz::Vector2f GetContentOrigin() const;
|
|
||||||
inline const Nz::Vector2f& GetContentSize() const;
|
inline float GetMaximumHeight() const;
|
||||||
|
inline Nz::Vector2f GetMaximumSize() const;
|
||||||
|
inline float GetMaximumWidth() const;
|
||||||
|
|
||||||
|
inline float GetMinimumHeight() const;
|
||||||
|
inline Nz::Vector2f GetMinimumSize() const;
|
||||||
|
inline float GetMinimumWidth() const;
|
||||||
|
|
||||||
|
inline float GetPreferredHeight() const;
|
||||||
|
inline Nz::Vector2f GetPreferredSize() const;
|
||||||
|
inline float GetPreferredWidth() const;
|
||||||
|
|
||||||
inline Nz::Vector2f GetSize() const;
|
inline Nz::Vector2f GetSize() const;
|
||||||
|
inline float GetWidth() const;
|
||||||
|
inline std::size_t GetWidgetChildCount() const;
|
||||||
|
|
||||||
bool HasFocus() const;
|
bool HasFocus() const;
|
||||||
|
|
||||||
inline bool IsVisible() const;
|
inline bool IsVisible() const;
|
||||||
|
|
||||||
virtual void ResizeToContent() = 0;
|
void Resize(const Nz::Vector2f& size);
|
||||||
|
|
||||||
void SetBackgroundColor(const Nz::Color& color);
|
void SetBackgroundColor(const Nz::Color& color);
|
||||||
void SetCursor(Nz::SystemCursor systemCursor);
|
void SetCursor(Nz::SystemCursor systemCursor);
|
||||||
inline void SetContentSize(const Nz::Vector2f& size);
|
|
||||||
void SetFocus();
|
void SetFocus();
|
||||||
inline void SetPadding(float left, float top, float right, float bottom);
|
|
||||||
void SetSize(const Nz::Vector2f& size);
|
inline void SetFixedHeight(float fixedHeight);
|
||||||
|
inline void SetFixedSize(const Nz::Vector2f& fixedSize);
|
||||||
|
inline void SetFixedWidth(float fixedWidth);
|
||||||
|
|
||||||
|
inline void SetMaximumHeight(float maximumHeight);
|
||||||
|
inline void SetMaximumSize(const Nz::Vector2f& maximumSize);
|
||||||
|
inline void SetMaximumWidth(float maximumWidth);
|
||||||
|
|
||||||
|
inline void SetMinimumHeight(float minimumHeight);
|
||||||
|
inline void SetMinimumSize(const Nz::Vector2f& minimumSize);
|
||||||
|
inline void SetMinimumWidth(float minimumWidth);
|
||||||
|
|
||||||
void Show(bool show = true);
|
void Show(bool show = true);
|
||||||
|
|
||||||
BaseWidget& operator=(const BaseWidget&) = delete;
|
BaseWidget& operator=(const BaseWidget&) = delete;
|
||||||
BaseWidget& operator=(BaseWidget&&) = default;
|
BaseWidget& operator=(BaseWidget&&) = delete;
|
||||||
|
|
||||||
struct Padding
|
|
||||||
{
|
|
||||||
float left;
|
|
||||||
float top;
|
|
||||||
float right;
|
|
||||||
float bottom;
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const EntityHandle& CreateEntity(bool isContentEntity);
|
const EntityHandle& CreateEntity();
|
||||||
void DestroyEntity(Entity* entity);
|
void DestroyEntity(Entity* entity);
|
||||||
virtual void Layout();
|
virtual void Layout();
|
||||||
|
|
||||||
|
|
@ -102,10 +119,12 @@ namespace Ndk
|
||||||
virtual void OnParentResized(const Nz::Vector2f& newSize);
|
virtual void OnParentResized(const Nz::Vector2f& newSize);
|
||||||
virtual void OnTextEntered(char32_t character, bool repeated);
|
virtual void OnTextEntered(char32_t character, bool repeated);
|
||||||
|
|
||||||
|
inline void SetPreferredSize(const Nz::Vector2f& preferredSize);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline BaseWidget();
|
inline BaseWidget();
|
||||||
|
|
||||||
inline void DestroyChild(BaseWidget* widget);
|
void DestroyChild(BaseWidget* widget);
|
||||||
void DestroyChildren();
|
void DestroyChildren();
|
||||||
inline bool IsRegisteredToCanvas() const;
|
inline bool IsRegisteredToCanvas() const;
|
||||||
inline void NotifyParentResized(const Nz::Vector2f& newSize);
|
inline void NotifyParentResized(const Nz::Vector2f& newSize);
|
||||||
|
|
@ -117,7 +136,6 @@ namespace Ndk
|
||||||
struct WidgetEntity
|
struct WidgetEntity
|
||||||
{
|
{
|
||||||
EntityOwner handle;
|
EntityOwner handle;
|
||||||
bool isContent;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr std::size_t InvalidCanvasIndex = std::numeric_limits<std::size_t>::max();
|
static constexpr std::size_t InvalidCanvasIndex = std::numeric_limits<std::size_t>::max();
|
||||||
|
|
@ -127,12 +145,14 @@ namespace Ndk
|
||||||
std::vector<std::unique_ptr<BaseWidget>> m_children;
|
std::vector<std::unique_ptr<BaseWidget>> m_children;
|
||||||
Canvas* m_canvas;
|
Canvas* m_canvas;
|
||||||
EntityOwner m_backgroundEntity;
|
EntityOwner m_backgroundEntity;
|
||||||
Padding m_padding;
|
|
||||||
WorldHandle m_world;
|
WorldHandle m_world;
|
||||||
Nz::Color m_backgroundColor;
|
Nz::Color m_backgroundColor;
|
||||||
Nz::SpriteRef m_backgroundSprite;
|
Nz::SpriteRef m_backgroundSprite;
|
||||||
Nz::SystemCursor m_cursor;
|
Nz::SystemCursor m_cursor;
|
||||||
Nz::Vector2f m_contentSize;
|
Nz::Vector2f m_maximumSize;
|
||||||
|
Nz::Vector2f m_minimumSize;
|
||||||
|
Nz::Vector2f m_preferredSize;
|
||||||
|
Nz::Vector2f m_size;
|
||||||
BaseWidget* m_widgetParent;
|
BaseWidget* m_widgetParent;
|
||||||
bool m_visible;
|
bool m_visible;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,13 @@ namespace Ndk
|
||||||
m_canvas(nullptr),
|
m_canvas(nullptr),
|
||||||
m_backgroundColor(Nz::Color(230, 230, 230, 255)),
|
m_backgroundColor(Nz::Color(230, 230, 230, 255)),
|
||||||
m_cursor(Nz::SystemCursor_Default),
|
m_cursor(Nz::SystemCursor_Default),
|
||||||
m_contentSize(50.f, 50.f),
|
m_size(50.f, 50.f),
|
||||||
|
m_maximumSize(std::numeric_limits<float>::infinity()),
|
||||||
|
m_minimumSize(0.f),
|
||||||
|
m_preferredSize(-1),
|
||||||
m_widgetParent(nullptr),
|
m_widgetParent(nullptr),
|
||||||
m_visible(true)
|
m_visible(true)
|
||||||
{
|
{
|
||||||
SetPadding(5.f, 5.f, 5.f, 5.f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
|
|
@ -64,6 +66,20 @@ namespace Ndk
|
||||||
SetPosition(GetPosition(Nz::CoordSys_Local).x, (parentSize.y - mySize.y) / 2.f);
|
SetPosition(GetPosition(Nz::CoordSys_Local).x, (parentSize.y - mySize.y) / 2.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
inline void BaseWidget::ForEachWidgetChild(F iterator)
|
||||||
|
{
|
||||||
|
for (const auto& child : m_children)
|
||||||
|
iterator(child.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
inline void BaseWidget::ForEachWidgetChild(F iterator) const
|
||||||
|
{
|
||||||
|
for (const auto& child : m_children)
|
||||||
|
iterator(static_cast<const BaseWidget*>(child.get()));
|
||||||
|
}
|
||||||
|
|
||||||
inline const Nz::Color& BaseWidget::GetBackgroundColor() const
|
inline const Nz::Color& BaseWidget::GetBackgroundColor() const
|
||||||
{
|
{
|
||||||
return m_backgroundColor;
|
return m_backgroundColor;
|
||||||
|
|
@ -79,24 +95,69 @@ namespace Ndk
|
||||||
return m_cursor;
|
return m_cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const BaseWidget::Padding& BaseWidget::GetPadding() const
|
inline float BaseWidget::GetHeight() const
|
||||||
{
|
{
|
||||||
return m_padding;
|
return m_size.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Nz::Vector2f BaseWidget::GetContentOrigin() const
|
inline float BaseWidget::GetMaximumHeight() const
|
||||||
{
|
{
|
||||||
return { m_padding.left, m_padding.top };
|
return m_maximumSize.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const Nz::Vector2f& BaseWidget::GetContentSize() const
|
inline Nz::Vector2f BaseWidget::GetMaximumSize() const
|
||||||
{
|
{
|
||||||
return m_contentSize;
|
return m_maximumSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float BaseWidget::GetMaximumWidth() const
|
||||||
|
{
|
||||||
|
return m_maximumSize.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float BaseWidget::GetMinimumHeight() const
|
||||||
|
{
|
||||||
|
return m_minimumSize.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Nz::Vector2f BaseWidget::GetMinimumSize() const
|
||||||
|
{
|
||||||
|
return m_minimumSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float BaseWidget::GetMinimumWidth() const
|
||||||
|
{
|
||||||
|
return m_minimumSize.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float BaseWidget::GetPreferredHeight() const
|
||||||
|
{
|
||||||
|
return m_preferredSize.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Nz::Vector2f BaseWidget::GetPreferredSize() const
|
||||||
|
{
|
||||||
|
return m_preferredSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float BaseWidget::GetPreferredWidth() const
|
||||||
|
{
|
||||||
|
return m_preferredSize.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Nz::Vector2f BaseWidget::GetSize() const
|
inline Nz::Vector2f BaseWidget::GetSize() const
|
||||||
{
|
{
|
||||||
return Nz::Vector2f(m_contentSize.x + m_padding.left + m_padding.right, m_contentSize.y + m_padding.top + m_padding.bottom);
|
return Nz::Vector2f(GetWidth(), GetHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float BaseWidget::GetWidth() const
|
||||||
|
{
|
||||||
|
return m_size.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::size_t BaseWidget::GetWidgetChildCount() const
|
||||||
|
{
|
||||||
|
return m_children.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool BaseWidget::IsVisible() const
|
inline bool BaseWidget::IsVisible() const
|
||||||
|
|
@ -104,22 +165,79 @@ namespace Ndk
|
||||||
return m_visible;
|
return m_visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BaseWidget::SetContentSize(const Nz::Vector2f& size)
|
inline void BaseWidget::SetFixedHeight(float fixedHeight)
|
||||||
{
|
{
|
||||||
NotifyParentResized(size);
|
SetMaximumHeight(fixedHeight);
|
||||||
m_contentSize = size;
|
SetMinimumHeight(fixedHeight);
|
||||||
|
|
||||||
Layout();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void BaseWidget::SetPadding(float left, float top, float right, float bottom)
|
inline void BaseWidget::SetFixedSize(const Nz::Vector2f& fixedSize)
|
||||||
{
|
{
|
||||||
m_padding.left = left;
|
SetMaximumSize(fixedSize);
|
||||||
m_padding.top = top;
|
SetMinimumSize(fixedSize);
|
||||||
m_padding.bottom = bottom;
|
}
|
||||||
m_padding.right = right;
|
|
||||||
|
|
||||||
Layout();
|
inline void BaseWidget::SetFixedWidth(float fixedWidth)
|
||||||
|
{
|
||||||
|
SetMaximumWidth(fixedWidth);
|
||||||
|
SetMinimumWidth(fixedWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void BaseWidget::SetMaximumHeight(float maximumHeight)
|
||||||
|
{
|
||||||
|
Nz::Vector2f maximumSize = GetMaximumSize();
|
||||||
|
maximumSize.y = maximumHeight;
|
||||||
|
|
||||||
|
SetMaximumSize(maximumSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void BaseWidget::SetMaximumSize(const Nz::Vector2f& maximumSize)
|
||||||
|
{
|
||||||
|
m_maximumSize = maximumSize;
|
||||||
|
|
||||||
|
Nz::Vector2f size = GetSize();
|
||||||
|
if (size.x > m_maximumSize.x || size.y > m_maximumSize.y)
|
||||||
|
Resize(size); //< Will clamp automatically
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void BaseWidget::SetMaximumWidth(float maximumWidth)
|
||||||
|
{
|
||||||
|
Nz::Vector2f maximumSize = GetMaximumSize();
|
||||||
|
maximumSize.x = maximumWidth;
|
||||||
|
|
||||||
|
SetMaximumSize(maximumSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void BaseWidget::SetMinimumHeight(float minimumHeight)
|
||||||
|
{
|
||||||
|
Nz::Vector2f minimumSize = GetMinimumSize();
|
||||||
|
minimumSize.y = minimumHeight;
|
||||||
|
|
||||||
|
SetMinimumSize(minimumSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void BaseWidget::SetMinimumSize(const Nz::Vector2f& minimumSize)
|
||||||
|
{
|
||||||
|
m_minimumSize = minimumSize;
|
||||||
|
|
||||||
|
Nz::Vector2f size = GetSize();
|
||||||
|
if (size.x < m_minimumSize.x || size.y < m_minimumSize.y)
|
||||||
|
Resize(size); //< Will clamp automatically
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void BaseWidget::SetMinimumWidth(float minimumWidth)
|
||||||
|
{
|
||||||
|
Nz::Vector2f minimumSize = GetMinimumSize();
|
||||||
|
minimumSize.x = minimumWidth;
|
||||||
|
|
||||||
|
SetMinimumSize(minimumSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void BaseWidget::SetPreferredSize(const Nz::Vector2f& preferredSize)
|
||||||
|
{
|
||||||
|
m_preferredSize = preferredSize;
|
||||||
|
|
||||||
|
Resize(m_preferredSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool BaseWidget::IsRegisteredToCanvas() const
|
inline bool BaseWidget::IsRegisteredToCanvas() const
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,6 @@ namespace Ndk
|
||||||
|
|
||||||
inline const WorldHandle& GetWorld() const;
|
inline const WorldHandle& GetWorld() const;
|
||||||
|
|
||||||
void ResizeToContent() override;
|
|
||||||
|
|
||||||
Canvas& operator=(const Canvas&) = delete;
|
Canvas& operator=(const Canvas&) = delete;
|
||||||
Canvas& operator=(Canvas&&) = delete;
|
Canvas& operator=(Canvas&&) = delete;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,6 @@ namespace Ndk
|
||||||
m_mouseMovedSlot.Connect(eventHandler.OnMouseMoved, this, &Canvas::OnEventMouseMoved);
|
m_mouseMovedSlot.Connect(eventHandler.OnMouseMoved, this, &Canvas::OnEventMouseMoved);
|
||||||
m_mouseLeftSlot.Connect(eventHandler.OnMouseLeft, this, &Canvas::OnEventMouseLeft);
|
m_mouseLeftSlot.Connect(eventHandler.OnMouseLeft, this, &Canvas::OnEventMouseLeft);
|
||||||
m_textEnteredSlot.Connect(eventHandler.OnTextEntered, this, &Canvas::OnEventTextEntered);
|
m_textEnteredSlot.Connect(eventHandler.OnTextEntered, this, &Canvas::OnEventTextEntered);
|
||||||
|
|
||||||
// Disable padding by default
|
|
||||||
SetPadding(0.f, 0.f, 0.f, 0.f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Canvas::~Canvas()
|
inline Canvas::~Canvas()
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
template<typename ComponentType>
|
template<typename ComponentType>
|
||||||
class Component : public BaseComponent
|
class Component : public BaseComponent, public Nz::HandledObject<ComponentType>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Component();
|
Component();
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@
|
||||||
#include <NDK/Components/CameraComponent.hpp>
|
#include <NDK/Components/CameraComponent.hpp>
|
||||||
#include <NDK/Components/CollisionComponent2D.hpp>
|
#include <NDK/Components/CollisionComponent2D.hpp>
|
||||||
#include <NDK/Components/CollisionComponent3D.hpp>
|
#include <NDK/Components/CollisionComponent3D.hpp>
|
||||||
|
#include <NDK/Components/ConstraintComponent2D.hpp>
|
||||||
|
#include <NDK/Components/DebugComponent.hpp>
|
||||||
#include <NDK/Components/GraphicsComponent.hpp>
|
#include <NDK/Components/GraphicsComponent.hpp>
|
||||||
#include <NDK/Components/LightComponent.hpp>
|
#include <NDK/Components/LightComponent.hpp>
|
||||||
#include <NDK/Components/ListenerComponent.hpp>
|
#include <NDK/Components/ListenerComponent.hpp>
|
||||||
|
|
@ -17,6 +19,5 @@
|
||||||
#include <NDK/Components/PhysicsComponent2D.hpp>
|
#include <NDK/Components/PhysicsComponent2D.hpp>
|
||||||
#include <NDK/Components/PhysicsComponent3D.hpp>
|
#include <NDK/Components/PhysicsComponent3D.hpp>
|
||||||
#include <NDK/Components/VelocityComponent.hpp>
|
#include <NDK/Components/VelocityComponent.hpp>
|
||||||
#include <NDK/Components/ConstraintComponent2D.hpp>
|
|
||||||
|
|
||||||
#endif // NDK_COMPONENTS_GLOBAL_HPP
|
#endif // NDK_COMPONENTS_GLOBAL_HPP
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ namespace Ndk
|
||||||
|
|
||||||
using CameraComponentHandle = Nz::ObjectHandle<CameraComponent>;
|
using CameraComponentHandle = Nz::ObjectHandle<CameraComponent>;
|
||||||
|
|
||||||
class NDK_API CameraComponent : public Component<CameraComponent>, public Nz::AbstractViewer, public Nz::HandledObject<CameraComponent>
|
class NDK_API CameraComponent : public Component<CameraComponent>, public Nz::AbstractViewer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline CameraComponent();
|
inline CameraComponent();
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@ namespace Ndk
|
||||||
inline CameraComponent::CameraComponent(const CameraComponent& camera) :
|
inline CameraComponent::CameraComponent(const CameraComponent& camera) :
|
||||||
Component(camera),
|
Component(camera),
|
||||||
AbstractViewer(camera),
|
AbstractViewer(camera),
|
||||||
HandledObject(camera),
|
|
||||||
m_visibilityHash(camera.m_visibilityHash),
|
m_visibilityHash(camera.m_visibilityHash),
|
||||||
m_projectionType(camera.m_projectionType),
|
m_projectionType(camera.m_projectionType),
|
||||||
m_targetRegion(camera.m_targetRegion),
|
m_targetRegion(camera.m_targetRegion),
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,10 @@
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
|
class CollisionComponent2D;
|
||||||
|
|
||||||
|
using CollisionComponent2DHandle = Nz::ObjectHandle<CollisionComponent2D>;
|
||||||
|
|
||||||
class NDK_API CollisionComponent2D : public Component<CollisionComponent2D>
|
class NDK_API CollisionComponent2D : public Component<CollisionComponent2D>
|
||||||
{
|
{
|
||||||
friend class PhysicsSystem2D;
|
friend class PhysicsSystem2D;
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,10 @@
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
|
class CollisionComponent3D;
|
||||||
|
|
||||||
|
using CollisionComponent3DHandle = Nz::ObjectHandle<CollisionComponent3D>;
|
||||||
|
|
||||||
class NDK_API CollisionComponent3D : public Component<CollisionComponent3D>
|
class NDK_API CollisionComponent3D : public Component<CollisionComponent3D>
|
||||||
{
|
{
|
||||||
friend class PhysicsSystem3D;
|
friend class PhysicsSystem3D;
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,10 @@
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
|
class ConstraintComponent2D;
|
||||||
|
|
||||||
|
using ConstraintComponent2DHandle = Nz::ObjectHandle<ConstraintComponent2D>;
|
||||||
|
|
||||||
class NDK_API ConstraintComponent2D : public Component<ConstraintComponent2D>
|
class NDK_API ConstraintComponent2D : public Component<ConstraintComponent2D>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
// Copyright (C) 2017 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Development Kit"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NDK_SERVER
|
||||||
|
#ifndef NDK_COMPONENTS_DEBUGCOMPONENT_HPP
|
||||||
|
#define NDK_COMPONENTS_DEBUGCOMPONENT_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Core/Flags.hpp>
|
||||||
|
#include <Nazara/Graphics/InstancedRenderable.hpp>
|
||||||
|
#include <NDK/Component.hpp>
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
enum class DebugDraw
|
||||||
|
{
|
||||||
|
//TODO: Collider2D
|
||||||
|
Collider3D,
|
||||||
|
GraphicsAABB,
|
||||||
|
GraphicsOBB,
|
||||||
|
|
||||||
|
Max = GraphicsOBB
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Nz
|
||||||
|
{
|
||||||
|
template<>
|
||||||
|
struct EnumAsFlags<Ndk::DebugDraw>
|
||||||
|
{
|
||||||
|
static constexpr Ndk::DebugDraw max = Ndk::DebugDraw::GraphicsOBB;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
using DebugDrawFlags = Nz::Flags<DebugDraw>;
|
||||||
|
|
||||||
|
constexpr DebugDrawFlags DebugDraw_None = 0;
|
||||||
|
|
||||||
|
class DebugComponent;
|
||||||
|
|
||||||
|
using DebugComponentHandle = Nz::ObjectHandle<DebugComponent>;
|
||||||
|
|
||||||
|
class NDK_API DebugComponent : public Component<DebugComponent>
|
||||||
|
{
|
||||||
|
friend class DebugSystem;
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline DebugComponent(DebugDrawFlags flags = DebugDraw_None);
|
||||||
|
inline DebugComponent(const DebugComponent& debug);
|
||||||
|
~DebugComponent() = default;
|
||||||
|
|
||||||
|
inline void Disable(DebugDrawFlags flags);
|
||||||
|
inline void Enable(DebugDrawFlags flags);
|
||||||
|
|
||||||
|
inline DebugDrawFlags GetFlags() const;
|
||||||
|
|
||||||
|
inline bool IsEnabled(DebugDrawFlags flags) const;
|
||||||
|
|
||||||
|
inline DebugComponent& operator=(const DebugComponent& debug);
|
||||||
|
|
||||||
|
static ComponentIndex componentIndex;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline const Nz::InstancedRenderableRef& GetDebugRenderable(DebugDraw option) const;
|
||||||
|
inline DebugDrawFlags GetEnabledFlags() const;
|
||||||
|
inline void UpdateDebugRenderable(DebugDraw option, Nz::InstancedRenderableRef renderable);
|
||||||
|
inline void UpdateEnabledFlags(DebugDrawFlags flags);
|
||||||
|
|
||||||
|
static constexpr std::size_t DebugModeCount = static_cast<std::size_t>(DebugDraw::Max) + 1;
|
||||||
|
|
||||||
|
std::array<Nz::InstancedRenderableRef, DebugModeCount> m_debugRenderables;
|
||||||
|
DebugDrawFlags m_enabledFlags;
|
||||||
|
DebugDrawFlags m_flags;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <NDK/Components/DebugComponent.inl>
|
||||||
|
|
||||||
|
#endif // NDK_COMPONENTS_DEBUGCOMPONENT_HPP
|
||||||
|
#endif // NDK_SERVER
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
// Copyright (C) 2017 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Development Kit"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||||
|
|
||||||
|
#include <NDK/Components/DebugComponent.hpp>
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
inline DebugComponent::DebugComponent(DebugDrawFlags flags) :
|
||||||
|
m_flags(flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline DebugComponent::DebugComponent(const DebugComponent& debug) :
|
||||||
|
m_flags(debug.m_flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void DebugComponent::Disable(DebugDrawFlags flags)
|
||||||
|
{
|
||||||
|
m_flags &= ~flags;
|
||||||
|
|
||||||
|
if (m_entity)
|
||||||
|
m_entity->Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void DebugComponent::Enable(DebugDrawFlags flags)
|
||||||
|
{
|
||||||
|
m_flags |= flags;
|
||||||
|
|
||||||
|
if (m_entity)
|
||||||
|
m_entity->Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline DebugDrawFlags DebugComponent::GetFlags() const
|
||||||
|
{
|
||||||
|
return m_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool DebugComponent::IsEnabled(DebugDrawFlags flags) const
|
||||||
|
{
|
||||||
|
return (m_flags & flags) == flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline DebugComponent& DebugComponent::operator=(const DebugComponent& debug)
|
||||||
|
{
|
||||||
|
m_flags = debug.m_flags;
|
||||||
|
|
||||||
|
if (m_entity)
|
||||||
|
m_entity->Invalidate();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Nz::InstancedRenderableRef& DebugComponent::GetDebugRenderable(DebugDraw option) const
|
||||||
|
{
|
||||||
|
return m_debugRenderables[static_cast<std::size_t>(option)];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline DebugDrawFlags DebugComponent::GetEnabledFlags() const
|
||||||
|
{
|
||||||
|
return m_enabledFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void DebugComponent::UpdateDebugRenderable(DebugDraw option, Nz::InstancedRenderableRef renderable)
|
||||||
|
{
|
||||||
|
m_debugRenderables[static_cast<std::size_t>(option)] = std::move(renderable);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void DebugComponent::UpdateEnabledFlags(DebugDrawFlags flags)
|
||||||
|
{
|
||||||
|
m_enabledFlags = flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include <Nazara/Graphics/CullingList.hpp>
|
#include <Nazara/Graphics/CullingList.hpp>
|
||||||
#include <Nazara/Graphics/InstancedRenderable.hpp>
|
#include <Nazara/Graphics/InstancedRenderable.hpp>
|
||||||
|
#include <Nazara/Math/Frustum.hpp>
|
||||||
#include <Nazara/Utility/Node.hpp>
|
#include <Nazara/Utility/Node.hpp>
|
||||||
#include <NDK/Component.hpp>
|
#include <NDK/Component.hpp>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
@ -21,19 +22,20 @@ namespace Ndk
|
||||||
using GraphicsComponentCullingList = Nz::CullingList<GraphicsComponent>;
|
using GraphicsComponentCullingList = Nz::CullingList<GraphicsComponent>;
|
||||||
using GraphicsComponentHandle = Nz::ObjectHandle<GraphicsComponent>;
|
using GraphicsComponentHandle = Nz::ObjectHandle<GraphicsComponent>;
|
||||||
|
|
||||||
class NDK_API GraphicsComponent : public Component<GraphicsComponent>, public Nz::HandledObject<GraphicsComponent>
|
class NDK_API GraphicsComponent : public Component<GraphicsComponent>
|
||||||
{
|
{
|
||||||
friend class RenderSystem;
|
friend class RenderSystem;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using RenderableList = std::vector<Nz::InstancedRenderableRef>;
|
using RenderableList = std::vector<Nz::InstancedRenderableRef>;
|
||||||
|
|
||||||
GraphicsComponent();
|
inline GraphicsComponent();
|
||||||
inline GraphicsComponent(const GraphicsComponent& graphicsComponent);
|
inline GraphicsComponent(const GraphicsComponent& graphicsComponent);
|
||||||
~GraphicsComponent() = default;
|
~GraphicsComponent() = default;
|
||||||
|
|
||||||
inline void AddToCullingList(GraphicsComponentCullingList* cullingList) const;
|
inline void AddToCullingList(GraphicsComponentCullingList* cullingList) const;
|
||||||
void AddToRenderQueue(Nz::AbstractRenderQueue* renderQueue) const;
|
void AddToRenderQueue(Nz::AbstractRenderQueue* renderQueue) const;
|
||||||
|
void AddToRenderQueueByCulling(const Nz::Frustumf& frustum, Nz::AbstractRenderQueue* renderQueue) const;
|
||||||
|
|
||||||
inline void Attach(Nz::InstancedRenderableRef renderable, int renderOrder = 0);
|
inline void Attach(Nz::InstancedRenderableRef renderable, int renderOrder = 0);
|
||||||
void Attach(Nz::InstancedRenderableRef renderable, const Nz::Matrix4f& localMatrix, int renderOrder = 0);
|
void Attach(Nz::InstancedRenderableRef renderable, const Nz::Matrix4f& localMatrix, int renderOrder = 0);
|
||||||
|
|
@ -44,13 +46,19 @@ namespace Ndk
|
||||||
|
|
||||||
inline bool DoesRequireRealTimeReflections() const;
|
inline bool DoesRequireRealTimeReflections() const;
|
||||||
|
|
||||||
inline void EnsureBoundingVolumeUpdate() const;
|
inline void EnsureBoundingVolumesUpdate() const;
|
||||||
inline void EnsureTransformMatrixUpdate() const;
|
inline void EnsureTransformMatrixUpdate() const;
|
||||||
|
|
||||||
|
template<typename Func> void ForEachRenderable(const Func& func) const;
|
||||||
|
|
||||||
|
inline const Nz::Boxf& GetAABB() const;
|
||||||
|
|
||||||
inline void GetAttachedRenderables(RenderableList* renderables) const;
|
inline void GetAttachedRenderables(RenderableList* renderables) const;
|
||||||
inline std::size_t GetAttachedRenderableCount() const;
|
inline std::size_t GetAttachedRenderableCount() const;
|
||||||
|
|
||||||
inline const Nz::BoundingVolumef& GetBoundingVolume() const;
|
inline const Nz::BoundingVolumef& GetBoundingVolume(std::size_t renderableIndex) const;
|
||||||
|
inline const Nz::Matrix4f& GetLocalMatrix(std::size_t renderableIndex) const;
|
||||||
|
inline const Nz::Matrix4f& GetTransformMatrix(std::size_t renderableIndex) const;
|
||||||
|
|
||||||
inline void RemoveFromCullingList(GraphicsComponentCullingList* cullingList) const;
|
inline void RemoveFromCullingList(GraphicsComponentCullingList* cullingList) const;
|
||||||
|
|
||||||
|
|
@ -66,7 +74,8 @@ namespace Ndk
|
||||||
|
|
||||||
void ConnectInstancedRenderableSignals(Renderable& renderable);
|
void ConnectInstancedRenderableSignals(Renderable& renderable);
|
||||||
|
|
||||||
inline void InvalidateBoundingVolume() const;
|
inline void ForceCullingInvalidation();
|
||||||
|
inline void InvalidateAABB() const;
|
||||||
void InvalidateRenderableData(const Nz::InstancedRenderable* renderable, Nz::UInt32 flags, std::size_t index);
|
void InvalidateRenderableData(const Nz::InstancedRenderable* renderable, Nz::UInt32 flags, std::size_t index);
|
||||||
void InvalidateRenderableMaterial(const Nz::InstancedRenderable* renderable, std::size_t skinIndex, std::size_t matIndex, const Nz::MaterialRef& newMat);
|
void InvalidateRenderableMaterial(const Nz::InstancedRenderable* renderable, std::size_t skinIndex, std::size_t matIndex, const Nz::MaterialRef& newMat);
|
||||||
inline void InvalidateRenderables();
|
inline void InvalidateRenderables();
|
||||||
|
|
@ -87,11 +96,20 @@ namespace Ndk
|
||||||
|
|
||||||
void UnregisterMaterial(Nz::Material* material);
|
void UnregisterMaterial(Nz::Material* material);
|
||||||
|
|
||||||
void UpdateBoundingVolume() const;
|
void UpdateBoundingVolumes() const;
|
||||||
void UpdateTransformMatrix() const;
|
void UpdateTransformMatrix() const;
|
||||||
|
|
||||||
NazaraSlot(Nz::Node, OnNodeInvalidation, m_nodeInvalidationSlot);
|
NazaraSlot(Nz::Node, OnNodeInvalidation, m_nodeInvalidationSlot);
|
||||||
|
|
||||||
|
using CullingListBoxEntry = GraphicsComponentCullingList::BoxEntry;
|
||||||
|
|
||||||
|
struct CullingBoxEntry
|
||||||
|
{
|
||||||
|
CullingListBoxEntry listEntry;
|
||||||
|
|
||||||
|
NazaraSlot(GraphicsComponentCullingList, OnCullingListRelease, cullingListReleaseSlot);
|
||||||
|
};
|
||||||
|
|
||||||
struct MaterialEntry
|
struct MaterialEntry
|
||||||
{
|
{
|
||||||
NazaraSlot(Nz::Material, OnMaterialReflectionModeChange, reflectionModelChangeSlot);
|
NazaraSlot(Nz::Material, OnMaterialReflectionModeChange, reflectionModelChangeSlot);
|
||||||
|
|
@ -126,29 +144,21 @@ namespace Ndk
|
||||||
NazaraSlot(Nz::InstancedRenderable, OnInstancedRenderableResetMaterials, renderableResetMaterialsSlot);
|
NazaraSlot(Nz::InstancedRenderable, OnInstancedRenderableResetMaterials, renderableResetMaterialsSlot);
|
||||||
NazaraSlot(Nz::InstancedRenderable, OnInstancedRenderableSkinChange, renderableSkinChangeSlot);
|
NazaraSlot(Nz::InstancedRenderable, OnInstancedRenderableSkinChange, renderableSkinChangeSlot);
|
||||||
|
|
||||||
|
mutable Nz::BoundingVolumef boundingVolume;
|
||||||
mutable Nz::InstancedRenderable::InstanceData data;
|
mutable Nz::InstancedRenderable::InstanceData data;
|
||||||
Nz::InstancedRenderableRef renderable;
|
Nz::InstancedRenderableRef renderable;
|
||||||
mutable bool dataUpdated;
|
mutable bool dataUpdated;
|
||||||
};
|
};
|
||||||
|
|
||||||
using VolumeCullingListEntry = GraphicsComponentCullingList::VolumeEntry;
|
|
||||||
|
|
||||||
struct VolumeCullingEntry
|
|
||||||
{
|
|
||||||
VolumeCullingListEntry listEntry;
|
|
||||||
|
|
||||||
NazaraSlot(GraphicsComponentCullingList, OnCullingListRelease, cullingListReleaseSlot);
|
|
||||||
};
|
|
||||||
|
|
||||||
std::size_t m_reflectiveMaterialCount;
|
std::size_t m_reflectiveMaterialCount;
|
||||||
mutable std::vector<VolumeCullingEntry> m_volumeCullingEntries;
|
mutable std::vector<CullingBoxEntry> m_cullingBoxEntries;
|
||||||
std::vector<Renderable> m_renderables;
|
std::vector<Renderable> m_renderables;
|
||||||
std::unordered_map<const Nz::Material*, MaterialEntry> m_materialEntries;
|
std::unordered_map<const Nz::Material*, MaterialEntry> m_materialEntries;
|
||||||
mutable Nz::BoundingVolumef m_boundingVolume;
|
mutable Nz::Boxf m_aabb;
|
||||||
mutable Nz::Matrix4f m_transformMatrix;
|
mutable Nz::Matrix4f m_transformMatrix;
|
||||||
Nz::Recti m_scissorRect;
|
Nz::Recti m_scissorRect;
|
||||||
Nz::TextureRef m_reflectionMap;
|
Nz::TextureRef m_reflectionMap;
|
||||||
mutable bool m_boundingVolumeUpdated;
|
mutable bool m_boundingVolumesUpdated;
|
||||||
mutable bool m_transformMatrixUpdated;
|
mutable bool m_transformMatrixUpdated;
|
||||||
unsigned int m_reflectionMapSize;
|
unsigned int m_reflectionMapSize;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
inline GraphicsComponent::GraphicsComponent() :
|
inline GraphicsComponent::GraphicsComponent() :
|
||||||
|
m_reflectiveMaterialCount(0),
|
||||||
m_scissorRect(-1, -1)
|
m_scissorRect(-1, -1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -21,10 +22,11 @@ namespace Ndk
|
||||||
*/
|
*/
|
||||||
inline GraphicsComponent::GraphicsComponent(const GraphicsComponent& graphicsComponent) :
|
inline GraphicsComponent::GraphicsComponent(const GraphicsComponent& graphicsComponent) :
|
||||||
Component(graphicsComponent),
|
Component(graphicsComponent),
|
||||||
HandledObject(graphicsComponent),
|
m_reflectiveMaterialCount(0),
|
||||||
m_boundingVolume(graphicsComponent.m_boundingVolume),
|
m_aabb(graphicsComponent.m_aabb),
|
||||||
m_transformMatrix(graphicsComponent.m_transformMatrix),
|
m_transformMatrix(graphicsComponent.m_transformMatrix),
|
||||||
m_boundingVolumeUpdated(graphicsComponent.m_boundingVolumeUpdated),
|
m_scissorRect(graphicsComponent.m_scissorRect),
|
||||||
|
m_boundingVolumesUpdated(graphicsComponent.m_boundingVolumesUpdated),
|
||||||
m_transformMatrixUpdated(graphicsComponent.m_transformMatrixUpdated)
|
m_transformMatrixUpdated(graphicsComponent.m_transformMatrixUpdated)
|
||||||
{
|
{
|
||||||
m_renderables.reserve(graphicsComponent.m_renderables.size());
|
m_renderables.reserve(graphicsComponent.m_renderables.size());
|
||||||
|
|
@ -34,12 +36,12 @@ namespace Ndk
|
||||||
|
|
||||||
inline void GraphicsComponent::AddToCullingList(GraphicsComponentCullingList* cullingList) const
|
inline void GraphicsComponent::AddToCullingList(GraphicsComponentCullingList* cullingList) const
|
||||||
{
|
{
|
||||||
m_volumeCullingEntries.emplace_back(VolumeCullingEntry{});
|
m_cullingBoxEntries.emplace_back();
|
||||||
VolumeCullingEntry& entry = m_volumeCullingEntries.back();
|
CullingBoxEntry& entry = m_cullingBoxEntries.back();
|
||||||
entry.cullingListReleaseSlot.Connect(cullingList->OnCullingListRelease, this, &GraphicsComponent::RemoveFromCullingList);
|
entry.cullingListReleaseSlot.Connect(cullingList->OnCullingListRelease, this, &GraphicsComponent::RemoveFromCullingList);
|
||||||
entry.listEntry = cullingList->RegisterVolumeTest(this);
|
entry.listEntry = cullingList->RegisterBoxTest(this);
|
||||||
|
|
||||||
InvalidateBoundingVolume();
|
InvalidateAABB();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -68,7 +70,7 @@ namespace Ndk
|
||||||
InvalidateReflectionMap();
|
InvalidateReflectionMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
InvalidateBoundingVolume();
|
InvalidateAABB();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -83,13 +85,15 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
if (it->renderable == renderable)
|
if (it->renderable == renderable)
|
||||||
{
|
{
|
||||||
InvalidateBoundingVolume();
|
InvalidateAABB();
|
||||||
|
|
||||||
std::size_t materialCount = renderable->GetMaterialCount();
|
std::size_t materialCount = renderable->GetMaterialCount();
|
||||||
for (std::size_t i = 0; i < materialCount; ++i)
|
for (std::size_t i = 0; i < materialCount; ++i)
|
||||||
UnregisterMaterial(renderable->GetMaterial(i));
|
UnregisterMaterial(renderable->GetMaterial(i));
|
||||||
|
|
||||||
m_renderables.erase(it);
|
m_renderables.erase(it);
|
||||||
|
|
||||||
|
ForceCullingInvalidation();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -111,10 +115,10 @@ namespace Ndk
|
||||||
* \brief Ensures the bounding volume is up to date
|
* \brief Ensures the bounding volume is up to date
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline void GraphicsComponent::EnsureBoundingVolumeUpdate() const
|
inline void GraphicsComponent::EnsureBoundingVolumesUpdate() const
|
||||||
{
|
{
|
||||||
if (!m_boundingVolumeUpdated)
|
if (!m_boundingVolumesUpdated)
|
||||||
UpdateBoundingVolume();
|
UpdateBoundingVolumes();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -127,6 +131,17 @@ namespace Ndk
|
||||||
UpdateTransformMatrix();
|
UpdateTransformMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets the axis-aligned bounding box of the entity
|
||||||
|
* \return A constant reference to the AABB
|
||||||
|
*/
|
||||||
|
inline const Nz::Boxf& GraphicsComponent::GetAABB() const
|
||||||
|
{
|
||||||
|
EnsureBoundingVolumesUpdate();
|
||||||
|
|
||||||
|
return m_aabb;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Gets the set of renderable elements
|
* \brief Gets the set of renderable elements
|
||||||
*
|
*
|
||||||
|
|
@ -154,28 +169,50 @@ namespace Ndk
|
||||||
return m_renderables.size();
|
return m_renderables.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
inline const Nz::BoundingVolumef& GraphicsComponent::GetBoundingVolume(std::size_t renderableIndex) const
|
||||||
* \brief Gets the bouding volume of the entity
|
|
||||||
* \return A constant reference to the bounding volume
|
|
||||||
*/
|
|
||||||
|
|
||||||
inline const Nz::BoundingVolumef& GraphicsComponent::GetBoundingVolume() const
|
|
||||||
{
|
{
|
||||||
EnsureBoundingVolumeUpdate();
|
EnsureBoundingVolumesUpdate();
|
||||||
|
|
||||||
return m_boundingVolume;
|
assert(renderableIndex < m_renderables.size());
|
||||||
|
return m_renderables[renderableIndex].boundingVolume;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Nz::Matrix4f& GraphicsComponent::GetLocalMatrix(std::size_t renderableIndex) const
|
||||||
|
{
|
||||||
|
assert(renderableIndex < m_renderables.size());
|
||||||
|
return m_renderables[renderableIndex].data.localMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Nz::Matrix4f& GraphicsComponent::GetTransformMatrix(std::size_t renderableIndex) const
|
||||||
|
{
|
||||||
|
EnsureBoundingVolumesUpdate();
|
||||||
|
|
||||||
|
assert(renderableIndex < m_renderables.size());
|
||||||
|
return m_renderables[renderableIndex].data.transformMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Calls a function for every renderable attached to this component
|
||||||
|
*
|
||||||
|
* \param func Callback function which will be called with renderable data
|
||||||
|
*/
|
||||||
|
template<typename Func>
|
||||||
|
void GraphicsComponent::ForEachRenderable(const Func& func) const
|
||||||
|
{
|
||||||
|
for (const auto& renderableData : m_renderables)
|
||||||
|
func(renderableData.renderable, renderableData.data.localMatrix, renderableData.data.renderOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void GraphicsComponent::RemoveFromCullingList(GraphicsComponentCullingList* cullingList) const
|
inline void GraphicsComponent::RemoveFromCullingList(GraphicsComponentCullingList* cullingList) const
|
||||||
{
|
{
|
||||||
for (auto it = m_volumeCullingEntries.begin(); it != m_volumeCullingEntries.end(); ++it)
|
for (auto it = m_cullingBoxEntries.begin(); it != m_cullingBoxEntries.end(); ++it)
|
||||||
{
|
{
|
||||||
if (it->listEntry.GetParent() == cullingList)
|
if (it->listEntry.GetParent() == cullingList)
|
||||||
{
|
{
|
||||||
if (m_volumeCullingEntries.size() > 1)
|
if (m_cullingBoxEntries.size() > 1)
|
||||||
*it = std::move(m_volumeCullingEntries.back());
|
*it = std::move(m_cullingBoxEntries.back());
|
||||||
|
|
||||||
m_volumeCullingEntries.pop_back();
|
m_cullingBoxEntries.pop_back();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -185,7 +222,7 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
m_scissorRect = scissorRect;
|
m_scissorRect = scissorRect;
|
||||||
|
|
||||||
for (VolumeCullingEntry& entry : m_volumeCullingEntries)
|
for (CullingBoxEntry& entry : m_cullingBoxEntries)
|
||||||
entry.listEntry.ForceInvalidation(); //< Invalidate render queues
|
entry.listEntry.ForceInvalidation(); //< Invalidate render queues
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -197,7 +234,7 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
renderable.data.localMatrix = localMatrix;
|
renderable.data.localMatrix = localMatrix;
|
||||||
|
|
||||||
InvalidateBoundingVolume();
|
InvalidateAABB();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -219,9 +256,15 @@ namespace Ndk
|
||||||
* \brief Invalidates the bounding volume
|
* \brief Invalidates the bounding volume
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline void GraphicsComponent::InvalidateBoundingVolume() const
|
inline void GraphicsComponent::ForceCullingInvalidation()
|
||||||
{
|
{
|
||||||
m_boundingVolumeUpdated = false;
|
for (CullingBoxEntry& entry : m_cullingBoxEntries)
|
||||||
|
entry.listEntry.ForceInvalidation(); //< Invalidate render queues
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void GraphicsComponent::InvalidateAABB() const
|
||||||
|
{
|
||||||
|
m_boundingVolumesUpdated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -242,7 +285,7 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
m_transformMatrixUpdated = false;
|
m_transformMatrixUpdated = false;
|
||||||
|
|
||||||
InvalidateBoundingVolume();
|
InvalidateAABB();
|
||||||
InvalidateRenderables();
|
InvalidateRenderables();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (C) 2017 Jérôme Leclercq
|
// Copyright (C) 2017 Jérôme Leclercq
|
||||||
// This file is part of the "Nazara Development Kit"
|
// This file is part of the "Nazara Development Kit"
|
||||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||||
|
|
||||||
|
|
@ -13,6 +13,10 @@
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
|
class LightComponent;
|
||||||
|
|
||||||
|
using LightComponentHandle = Nz::ObjectHandle<LightComponent>;
|
||||||
|
|
||||||
class NDK_API LightComponent : public Component<LightComponent>, public Nz::Light
|
class NDK_API LightComponent : public Component<LightComponent>, public Nz::Light
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,10 @@
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
|
class ListenerComponent;
|
||||||
|
|
||||||
|
using ListenerComponentHandle = Nz::ObjectHandle<ListenerComponent>;
|
||||||
|
|
||||||
class NDK_API ListenerComponent : public Component<ListenerComponent>
|
class NDK_API ListenerComponent : public Component<ListenerComponent>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ namespace Ndk
|
||||||
|
|
||||||
using NodeComponentHandle = Nz::ObjectHandle<NodeComponent>;
|
using NodeComponentHandle = Nz::ObjectHandle<NodeComponent>;
|
||||||
|
|
||||||
class NDK_API NodeComponent : public Component<NodeComponent>, public Nz::Node, public Nz::HandledObject<NodeComponent>
|
class NDK_API NodeComponent : public Component<NodeComponent>, public Nz::Node
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NodeComponent() = default;
|
NodeComponent() = default;
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
|
class ParticleEmitterComponent;
|
||||||
|
|
||||||
|
using ParticleEmitterComponentHandle = Nz::ObjectHandle<ParticleEmitterComponent>;
|
||||||
|
|
||||||
class NDK_API ParticleEmitterComponent : public Component<ParticleEmitterComponent>, public Nz::ParticleEmitter
|
class NDK_API ParticleEmitterComponent : public Component<ParticleEmitterComponent>, public Nz::ParticleEmitter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ namespace Ndk
|
||||||
|
|
||||||
using ParticleGroupComponentHandle = Nz::ObjectHandle<ParticleGroupComponent>;
|
using ParticleGroupComponentHandle = Nz::ObjectHandle<ParticleGroupComponent>;
|
||||||
|
|
||||||
class NDK_API ParticleGroupComponent : public Component<ParticleGroupComponent>, public Nz::ParticleGroup, public Nz::HandledObject<ParticleGroupComponent>
|
class NDK_API ParticleGroupComponent : public Component<ParticleGroupComponent>, public Nz::ParticleGroup
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline ParticleGroupComponent(unsigned int maxParticleCount, Nz::ParticleLayout layout);
|
inline ParticleGroupComponent(unsigned int maxParticleCount, Nz::ParticleLayout layout);
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
|
class PhysicsComponent2D;
|
||||||
|
|
||||||
|
using PhysicsComponent2DHandle = Nz::ObjectHandle<PhysicsComponent2D>;
|
||||||
|
|
||||||
class NDK_API PhysicsComponent2D : public Component<PhysicsComponent2D>
|
class NDK_API PhysicsComponent2D : public Component<PhysicsComponent2D>
|
||||||
{
|
{
|
||||||
friend class CollisionComponent2D;
|
friend class CollisionComponent2D;
|
||||||
|
|
@ -20,32 +24,53 @@ namespace Ndk
|
||||||
friend class ConstraintComponent2D;
|
friend class ConstraintComponent2D;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PhysicsComponent2D() = default;
|
PhysicsComponent2D();
|
||||||
PhysicsComponent2D(const PhysicsComponent2D& physics);
|
PhysicsComponent2D(const PhysicsComponent2D& physics);
|
||||||
~PhysicsComponent2D() = default;
|
~PhysicsComponent2D() = default;
|
||||||
|
|
||||||
void AddForce(const Nz::Vector2f& force, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
inline void AddForce(const Nz::Vector2f& force, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||||
void AddForce(const Nz::Vector2f& force, const Nz::Vector2f& point, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
inline void AddForce(const Nz::Vector2f& force, const Nz::Vector2f& point, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||||
void AddImpulse(const Nz::Vector2f& impulse, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
inline void AddImpulse(const Nz::Vector2f& impulse, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||||
void AddImpulse(const Nz::Vector2f& impulse, const Nz::Vector2f& point, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
inline void AddImpulse(const Nz::Vector2f& impulse, const Nz::Vector2f& point, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||||
void AddTorque(float torque);
|
inline void AddTorque(const Nz::RadianAnglef& torque);
|
||||||
|
|
||||||
Nz::Rectf GetAABB() const;
|
inline bool ClosestPointQuery(const Nz::Vector2f& position, Nz::Vector2f* closestPoint, float* closestDistance) const;
|
||||||
float GetAngularVelocity() const;
|
|
||||||
Nz::Vector2f GetCenterOfGravity(Nz::CoordSys coordSys = Nz::CoordSys_Local) const;
|
|
||||||
float GetMass() const;
|
|
||||||
Nz::Vector2f GetPosition() const;
|
|
||||||
float GetRotation() const;
|
|
||||||
Nz::Vector2f GetVelocity() const;
|
|
||||||
|
|
||||||
bool IsSleeping() const;
|
inline void EnableNodeSynchronization(bool nodeSynchronization);
|
||||||
|
|
||||||
void SetAngularVelocity(float angularVelocity);
|
inline Nz::Rectf GetAABB() const;
|
||||||
void SetMass(float mass);
|
inline float GetAngularDamping() const;
|
||||||
void SetMassCenter(const Nz::Vector2f& center);
|
inline Nz::RadianAnglef GetAngularVelocity() const;
|
||||||
void SetPosition(const Nz::Vector2f& position);
|
NAZARA_DEPRECATED("Name error, please use GetMassCenter")
|
||||||
void SetRotation(float rotation);
|
inline Nz::Vector2f GetCenterOfGravity(Nz::CoordSys coordSys = Nz::CoordSys_Local) const;
|
||||||
void SetVelocity(const Nz::Vector2f& velocity);
|
inline float GetElasticity(std::size_t shapeIndex = 0) const;
|
||||||
|
inline float GetFriction(std::size_t shapeIndex = 0) const;
|
||||||
|
inline float GetMass() const;
|
||||||
|
inline Nz::Vector2f GetMassCenter(Nz::CoordSys coordSys = Nz::CoordSys_Local) const;
|
||||||
|
inline float GetMomentOfInertia() const;
|
||||||
|
inline Nz::Vector2f GetPosition() const;
|
||||||
|
inline Nz::RadianAnglef GetRotation() const;
|
||||||
|
inline Nz::Vector2f GetSurfaceVelocity(std::size_t shapeIndex = 0) const;
|
||||||
|
inline std::size_t GetShapeCount() const;
|
||||||
|
inline Nz::Vector2f GetVelocity() const;
|
||||||
|
|
||||||
|
inline bool IsNodeSynchronizationEnabled() const;
|
||||||
|
inline bool IsSleeping() const;
|
||||||
|
|
||||||
|
inline void SetAngularDamping(float angularDamping);
|
||||||
|
inline void SetAngularVelocity(const Nz::RadianAnglef& angularVelocity);
|
||||||
|
inline void SetElasticity(float elasticity);
|
||||||
|
inline void SetElasticity(std::size_t shapeIndex, float friction);
|
||||||
|
inline void SetFriction(float friction);
|
||||||
|
inline void SetFriction(std::size_t shapeIndex, float friction);
|
||||||
|
inline void SetMass(float mass, bool recomputeMoment = true);
|
||||||
|
inline void SetMassCenter(const Nz::Vector2f& center, Nz::CoordSys coordSys = Nz::CoordSys_Local);
|
||||||
|
inline void SetMomentOfInertia(float moment);
|
||||||
|
inline void SetPosition(const Nz::Vector2f& position);
|
||||||
|
inline void SetRotation(const Nz::RadianAnglef& rotation);
|
||||||
|
inline void SetSurfaceVelocity(const Nz::Vector2f& velocity);
|
||||||
|
inline void SetSurfaceVelocity(std::size_t shapeIndex, const Nz::Vector2f& velocity);
|
||||||
|
inline void SetVelocity(const Nz::Vector2f& velocity);
|
||||||
|
|
||||||
static ComponentIndex componentIndex;
|
static ComponentIndex componentIndex;
|
||||||
|
|
||||||
|
|
@ -59,6 +84,7 @@ namespace Ndk
|
||||||
void OnEntityDestruction() override;
|
void OnEntityDestruction() override;
|
||||||
|
|
||||||
std::unique_ptr<Nz::RigidBody2D> m_object;
|
std::unique_ptr<Nz::RigidBody2D> m_object;
|
||||||
|
bool m_nodeSynchronizationEnabled;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,24 @@
|
||||||
// This file is part of the "Nazara Development Kit"
|
// This file is part of the "Nazara Development Kit"
|
||||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||||
|
|
||||||
|
#include <NDK/Components/PhysicsComponent2D.hpp>
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
|
/*!
|
||||||
|
* \brief Constructs a PhysicsComponent2D object by default
|
||||||
|
*/
|
||||||
|
inline PhysicsComponent2D::PhysicsComponent2D() :
|
||||||
|
m_nodeSynchronizationEnabled(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Constructs a PhysicsComponent2D object by copy semantic
|
* \brief Constructs a PhysicsComponent2D object by copy semantic
|
||||||
*
|
*
|
||||||
* \param physics PhysicsComponent2D to copy
|
* \param physics PhysicsComponent2D to copy
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline PhysicsComponent2D::PhysicsComponent2D(const PhysicsComponent2D& physics)
|
inline PhysicsComponent2D::PhysicsComponent2D(const PhysicsComponent2D& physics)
|
||||||
{
|
{
|
||||||
// No copy of physical object (because we only create it when attached to an entity)
|
// No copy of physical object (because we only create it when attached to an entity)
|
||||||
|
|
@ -90,13 +98,46 @@ namespace Ndk
|
||||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline void PhysicsComponent2D::AddTorque(float torque)
|
inline void PhysicsComponent2D::AddTorque(const Nz::RadianAnglef& torque)
|
||||||
{
|
{
|
||||||
NazaraAssert(m_object, "Invalid physics object");
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
||||||
m_object->AddTorque(torque);
|
m_object->AddTorque(torque);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Finds the closest point on the entity relative to a position
|
||||||
|
* \return True if such a point exists (will return false if no collider exists)
|
||||||
|
*
|
||||||
|
* \param position The starting point which will be used for the query
|
||||||
|
* \param closestPoint The closest point on entity surface
|
||||||
|
* \param closestDistance The distance between the closest point and the starting point, may be negative if starting point is inside the entity
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||||
|
*/
|
||||||
|
inline bool PhysicsComponent2D::ClosestPointQuery(const Nz::Vector2f& position, Nz::Vector2f* closestPoint, float* closestDistance) const
|
||||||
|
{
|
||||||
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
||||||
|
return m_object->ClosestPointQuery(position, closestPoint, closestDistance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Enables position/rotation synchronization with the NodeComponent
|
||||||
|
*
|
||||||
|
* By default, at every update of the PhysicsSystem2D, the NodeComponent's position and rotation (if any) will be synchronized with
|
||||||
|
* the values of the PhysicsComponent2D. This function allows to enable/disable this behavior on a per-entity basis.
|
||||||
|
*
|
||||||
|
* \param nodeSynchronization Should synchronization occur between NodeComponent and PhysicsComponent2D
|
||||||
|
*/
|
||||||
|
inline void PhysicsComponent2D::EnableNodeSynchronization(bool nodeSynchronization)
|
||||||
|
{
|
||||||
|
m_nodeSynchronizationEnabled = nodeSynchronization;
|
||||||
|
|
||||||
|
if (m_entity)
|
||||||
|
m_entity->Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Gets the AABB of the physics object
|
* \brief Gets the AABB of the physics object
|
||||||
* \return AABB of the object
|
* \return AABB of the object
|
||||||
|
|
@ -110,6 +151,22 @@ namespace Ndk
|
||||||
return m_object->GetAABB();
|
return m_object->GetAABB();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets the angular damping or moment of inertia of the physics object
|
||||||
|
* \return Angular damping of the object
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||||
|
*
|
||||||
|
* \see GetMomentOfInertia
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline float PhysicsComponent2D::GetAngularDamping() const
|
||||||
|
{
|
||||||
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
||||||
|
return m_object->GetAngularDamping();
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Gets the angular velocity of the physics object
|
* \brief Gets the angular velocity of the physics object
|
||||||
* \return Angular velocity of the object
|
* \return Angular velocity of the object
|
||||||
|
|
@ -117,7 +174,7 @@ namespace Ndk
|
||||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline float PhysicsComponent2D::GetAngularVelocity() const
|
inline Nz::RadianAnglef PhysicsComponent2D::GetAngularVelocity() const
|
||||||
{
|
{
|
||||||
NazaraAssert(m_object, "Invalid physics object");
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
||||||
|
|
@ -137,7 +194,37 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
NazaraAssert(m_object, "Invalid physics object");
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
||||||
return m_object->GetCenterOfGravity(coordSys);
|
return m_object->GetMassCenter(coordSys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets the elasticity of a shape belonging to this physics object
|
||||||
|
* \return Elasticity of the shape
|
||||||
|
*
|
||||||
|
* \param shapeIndex Shape index of the collider we're interested
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||||
|
*/
|
||||||
|
inline float PhysicsComponent2D::GetElasticity(std::size_t shapeIndex) const
|
||||||
|
{
|
||||||
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
||||||
|
return m_object->GetElasticity(shapeIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets the friction of a shape belonging to this physics object
|
||||||
|
* \return Friction of the shape
|
||||||
|
*
|
||||||
|
* \param shapeIndex Shape index of the collider we're interested
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||||
|
*/
|
||||||
|
inline float PhysicsComponent2D::GetFriction(std::size_t shapeIndex) const
|
||||||
|
{
|
||||||
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
||||||
|
return m_object->GetFriction(shapeIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -146,7 +233,6 @@ namespace Ndk
|
||||||
*
|
*
|
||||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline float PhysicsComponent2D::GetMass() const
|
inline float PhysicsComponent2D::GetMass() const
|
||||||
{
|
{
|
||||||
NazaraAssert(m_object, "Invalid physics object");
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
@ -154,6 +240,38 @@ namespace Ndk
|
||||||
return m_object->GetMass();
|
return m_object->GetMass();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets the gravity center of the physics object
|
||||||
|
* \return Gravity center of the object
|
||||||
|
*
|
||||||
|
* \param coordSys System coordinates to consider
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline Nz::Vector2f PhysicsComponent2D::GetMassCenter(Nz::CoordSys coordSys) const
|
||||||
|
{
|
||||||
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
||||||
|
return m_object->GetMassCenter(coordSys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets the angular damping or moment of inertia of the physics object
|
||||||
|
* \return Moment of inertia of the object
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||||
|
*
|
||||||
|
* \see GetAngularDamping
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline float PhysicsComponent2D::GetMomentOfInertia() const
|
||||||
|
{
|
||||||
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
||||||
|
return m_object->GetMomentOfInertia();
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Gets the position of the physics object
|
* \brief Gets the position of the physics object
|
||||||
* \return Position of the object
|
* \return Position of the object
|
||||||
|
|
@ -174,14 +292,37 @@ namespace Ndk
|
||||||
*
|
*
|
||||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||||
*/
|
*/
|
||||||
|
inline Nz::RadianAnglef PhysicsComponent2D::GetRotation() const
|
||||||
inline float PhysicsComponent2D::GetRotation() const
|
|
||||||
{
|
{
|
||||||
NazaraAssert(m_object, "Invalid physics object");
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
||||||
return m_object->GetRotation();
|
return m_object->GetRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets the surface velocity of a shape belonging to this physics object
|
||||||
|
* \return Surface velocity of the shape
|
||||||
|
*
|
||||||
|
* \param shapeIndex Shape index of the collider we're interested
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||||
|
*/
|
||||||
|
inline Nz::Vector2f PhysicsComponent2D::GetSurfaceVelocity(std::size_t shapeIndex) const
|
||||||
|
{
|
||||||
|
return m_object->GetSurfaceVelocity(shapeIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Gets the rotation of the physics object
|
||||||
|
* \return Shape count of the object
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||||
|
*/
|
||||||
|
inline std::size_t PhysicsComponent2D::GetShapeCount() const
|
||||||
|
{
|
||||||
|
return m_object->GetShapeCount();
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Gets the velocity of the physics object
|
* \brief Gets the velocity of the physics object
|
||||||
* \return Velocity of the object
|
* \return Velocity of the object
|
||||||
|
|
@ -196,13 +337,23 @@ namespace Ndk
|
||||||
return m_object->GetVelocity();
|
return m_object->GetVelocity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks if position & rotation are synchronized with NodeComponent
|
||||||
|
* \return true If synchronization is enabled
|
||||||
|
*
|
||||||
|
* \see EnableNodeSynchronization
|
||||||
|
*/
|
||||||
|
inline bool PhysicsComponent2D::IsNodeSynchronizationEnabled() const
|
||||||
|
{
|
||||||
|
return m_nodeSynchronizationEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Checks whether the entity is currently sleeping
|
* \brief Checks whether the entity is currently sleeping
|
||||||
* \return true If it is the case
|
* \return true If it is the case
|
||||||
*
|
*
|
||||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline bool PhysicsComponent2D::IsSleeping() const
|
inline bool PhysicsComponent2D::IsSleeping() const
|
||||||
{
|
{
|
||||||
NazaraAssert(m_object, "Invalid physics object");
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
@ -210,6 +361,23 @@ namespace Ndk
|
||||||
return m_object->IsSleeping();
|
return m_object->IsSleeping();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sets the angular damping or moment of inertia of the physics object
|
||||||
|
*
|
||||||
|
* \param angularDamping Angular damping of the object
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||||
|
*
|
||||||
|
* \see SetMomentOfInertia
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline void PhysicsComponent2D::SetAngularDamping(float angularDamping)
|
||||||
|
{
|
||||||
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
||||||
|
m_object->SetAngularDamping(angularDamping);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Sets the angular velocity of the physics object
|
* \brief Sets the angular velocity of the physics object
|
||||||
*
|
*
|
||||||
|
|
@ -217,29 +385,93 @@ namespace Ndk
|
||||||
*
|
*
|
||||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||||
*/
|
*/
|
||||||
|
inline void PhysicsComponent2D::SetAngularVelocity(const Nz::RadianAnglef& angularVelocity)
|
||||||
inline void PhysicsComponent2D::SetAngularVelocity(float angularVelocity)
|
|
||||||
{
|
{
|
||||||
NazaraAssert(m_object, "Invalid physics object");
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
||||||
m_object->SetAngularVelocity(angularVelocity);
|
m_object->SetAngularVelocity(angularVelocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sets the elasticity of the whole physics object
|
||||||
|
*
|
||||||
|
* Overrides all shapes elasticity with a single value
|
||||||
|
*
|
||||||
|
* \param elasticity Elasticity to be applied
|
||||||
|
*
|
||||||
|
* \remark Elasticity must be positive or zero
|
||||||
|
*/
|
||||||
|
inline void PhysicsComponent2D::SetElasticity(float elasticity)
|
||||||
|
{
|
||||||
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
NazaraAssert(elasticity >= 0.f, "Friction must be positive");
|
||||||
|
|
||||||
|
m_object->SetElasticity(elasticity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sets the elasticity of a single shape of the physics object
|
||||||
|
*
|
||||||
|
* \param shapeIndex Target shape index
|
||||||
|
* \param elasticity Elasticity to be applied
|
||||||
|
*
|
||||||
|
* \remark Elasticity must be positive or zero
|
||||||
|
*/
|
||||||
|
inline void PhysicsComponent2D::SetElasticity(std::size_t shapeIndex, float elasticity)
|
||||||
|
{
|
||||||
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
NazaraAssert(elasticity >= 0.f, "Friction must be positive");
|
||||||
|
|
||||||
|
m_object->SetElasticity(shapeIndex, elasticity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sets the friction of the whole physics object
|
||||||
|
*
|
||||||
|
* Overrides all shapes friction with a single value
|
||||||
|
*
|
||||||
|
* \param friction Friction to be applied
|
||||||
|
*
|
||||||
|
* \remark Friction must be positive or zero
|
||||||
|
*/
|
||||||
|
inline void PhysicsComponent2D::SetFriction(float friction)
|
||||||
|
{
|
||||||
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
NazaraAssert(friction >= 0.f, "Friction must be positive");
|
||||||
|
|
||||||
|
m_object->SetFriction(friction);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sets the friction of a single shape of the physics object
|
||||||
|
*
|
||||||
|
* \param shapeIndex Target shape index
|
||||||
|
* \param friction Friction to be applied
|
||||||
|
*
|
||||||
|
* \remark Friction must be positive or zero
|
||||||
|
*/
|
||||||
|
inline void PhysicsComponent2D::SetFriction(std::size_t shapeIndex, float friction)
|
||||||
|
{
|
||||||
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
NazaraAssert(friction >= 0.f, "Friction must be positive");
|
||||||
|
|
||||||
|
m_object->SetFriction(shapeIndex, friction);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Sets the mass of the physics object
|
* \brief Sets the mass of the physics object
|
||||||
*
|
*
|
||||||
* \param mass Mass of the object
|
* \param mass Mass of the object
|
||||||
|
* \param recomputeMoment Should the moment of inertia be recomputed according to the new mass
|
||||||
*
|
*
|
||||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
* \remark Mass must be positive or zero
|
||||||
* \remark Produces a NazaraAssert if the mass is negative
|
|
||||||
*/
|
*/
|
||||||
|
inline void PhysicsComponent2D::SetMass(float mass, bool recomputeMoment)
|
||||||
inline void PhysicsComponent2D::SetMass(float mass)
|
|
||||||
{
|
{
|
||||||
NazaraAssert(m_object, "Invalid physics object");
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
NazaraAssert(mass > 0.f, "Mass should be positive");
|
NazaraAssert(mass >= 0.f, "Mass should be positive");
|
||||||
|
|
||||||
m_object->SetMass(mass);
|
m_object->SetMass(mass, recomputeMoment);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -249,12 +481,27 @@ namespace Ndk
|
||||||
*
|
*
|
||||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||||
*/
|
*/
|
||||||
|
inline void PhysicsComponent2D::SetMassCenter(const Nz::Vector2f& center, Nz::CoordSys coordSys)
|
||||||
inline void PhysicsComponent2D::SetMassCenter(const Nz::Vector2f& center)
|
|
||||||
{
|
{
|
||||||
NazaraAssert(m_object, "Invalid physics object");
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
||||||
m_object->SetMassCenter(center);
|
m_object->SetMassCenter(center, coordSys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sets the angular damping or moment of inertia of the physics object
|
||||||
|
*
|
||||||
|
* \param moment Moment of inertia of the object
|
||||||
|
*
|
||||||
|
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||||
|
*
|
||||||
|
* \see SetAngularDamping
|
||||||
|
*/
|
||||||
|
inline void PhysicsComponent2D::SetMomentOfInertia(float moment)
|
||||||
|
{
|
||||||
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
||||||
|
m_object->SetMomentOfInertia(moment);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -264,7 +511,6 @@ namespace Ndk
|
||||||
*
|
*
|
||||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline void PhysicsComponent2D::SetPosition(const Nz::Vector2f& position)
|
inline void PhysicsComponent2D::SetPosition(const Nz::Vector2f& position)
|
||||||
{
|
{
|
||||||
NazaraAssert(m_object, "Invalid physics object");
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
@ -279,22 +525,45 @@ namespace Ndk
|
||||||
*
|
*
|
||||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||||
*/
|
*/
|
||||||
|
inline void PhysicsComponent2D::SetRotation(const Nz::RadianAnglef& rotation)
|
||||||
inline void PhysicsComponent2D::SetRotation(float rotation)
|
|
||||||
{
|
{
|
||||||
NazaraAssert(m_object, "Invalid physics object");
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
||||||
m_object->SetRotation(rotation);
|
m_object->SetRotation(rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sets the surface velocity of the whole physics object
|
||||||
|
*
|
||||||
|
* Overrides all shapes surface velocity with a single value
|
||||||
|
*
|
||||||
|
* \param velocity Surface velocity to be applied
|
||||||
|
*/
|
||||||
|
inline void PhysicsComponent2D::SetSurfaceVelocity(const Nz::Vector2f& velocity)
|
||||||
|
{
|
||||||
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
||||||
|
m_object->SetSurfaceVelocity(velocity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Sets the surface velocity of a single shape of the physics object
|
||||||
|
*
|
||||||
|
* \param shapeIndex Target shape index
|
||||||
|
* \param velocity Surface velocity to be applied
|
||||||
|
*/
|
||||||
|
inline void PhysicsComponent2D::SetSurfaceVelocity(std::size_t shapeIndex, const Nz::Vector2f& velocity)
|
||||||
|
{
|
||||||
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
||||||
|
m_object->SetSurfaceVelocity(shapeIndex, velocity);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Sets the velocity of the physics object
|
* \brief Sets the velocity of the physics object
|
||||||
*
|
*
|
||||||
* \param velocity Velocity of the object
|
* \param velocity Velocity of the object
|
||||||
*
|
|
||||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline void PhysicsComponent2D::SetVelocity(const Nz::Vector2f& velocity)
|
inline void PhysicsComponent2D::SetVelocity(const Nz::Vector2f& velocity)
|
||||||
{
|
{
|
||||||
NazaraAssert(m_object, "Invalid physics object");
|
NazaraAssert(m_object, "Invalid physics object");
|
||||||
|
|
@ -306,7 +575,6 @@ namespace Ndk
|
||||||
* \brief Gets the underlying physics object
|
* \brief Gets the underlying physics object
|
||||||
* \return A reference to the physics object
|
* \return A reference to the physics object
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline Nz::RigidBody2D* PhysicsComponent2D::GetRigidBody()
|
inline Nz::RigidBody2D* PhysicsComponent2D::GetRigidBody()
|
||||||
{
|
{
|
||||||
return m_object.get();
|
return m_object.get();
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
|
class PhysicsComponent3D;
|
||||||
|
|
||||||
|
using PhysicsComponent3DHandle = Nz::ObjectHandle<PhysicsComponent3D>;
|
||||||
|
|
||||||
class NDK_API PhysicsComponent3D : public Component<PhysicsComponent3D>
|
class NDK_API PhysicsComponent3D : public Component<PhysicsComponent3D>
|
||||||
{
|
{
|
||||||
friend class CollisionComponent3D;
|
friend class CollisionComponent3D;
|
||||||
|
|
@ -23,49 +27,49 @@ namespace Ndk
|
||||||
PhysicsComponent3D(const PhysicsComponent3D& physics);
|
PhysicsComponent3D(const PhysicsComponent3D& physics);
|
||||||
~PhysicsComponent3D() = default;
|
~PhysicsComponent3D() = default;
|
||||||
|
|
||||||
void AddForce(const Nz::Vector3f& force, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
inline void AddForce(const Nz::Vector3f& force, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||||
void AddForce(const Nz::Vector3f& force, const Nz::Vector3f& point, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
inline void AddForce(const Nz::Vector3f& force, const Nz::Vector3f& point, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||||
void AddTorque(const Nz::Vector3f& torque, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
inline void AddTorque(const Nz::Vector3f& torque, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||||
|
|
||||||
void EnableAutoSleep(bool autoSleep);
|
inline void EnableAutoSleep(bool autoSleep);
|
||||||
void EnableNodeSynchronization(bool nodeSynchronization);
|
inline void EnableNodeSynchronization(bool nodeSynchronization);
|
||||||
|
|
||||||
Nz::Boxf GetAABB() const;
|
inline Nz::Boxf GetAABB() const;
|
||||||
Nz::Vector3f GetAngularDamping() const;
|
inline Nz::Vector3f GetAngularDamping() const;
|
||||||
Nz::Vector3f GetAngularVelocity() const;
|
inline Nz::Vector3f GetAngularVelocity() const;
|
||||||
float GetGravityFactor() const;
|
inline float GetGravityFactor() const;
|
||||||
float GetLinearDamping() const;
|
inline float GetLinearDamping() const;
|
||||||
Nz::Vector3f GetLinearVelocity() const;
|
inline Nz::Vector3f GetLinearVelocity() const;
|
||||||
float GetMass() const;
|
inline float GetMass() const;
|
||||||
Nz::Vector3f GetMassCenter(Nz::CoordSys coordSys = Nz::CoordSys_Local) const;
|
inline Nz::Vector3f GetMassCenter(Nz::CoordSys coordSys = Nz::CoordSys_Local) const;
|
||||||
const Nz::Matrix4f& GetMatrix() const;
|
inline const Nz::Matrix4f& GetMatrix() const;
|
||||||
Nz::Vector3f GetPosition() const;
|
inline Nz::Vector3f GetPosition() const;
|
||||||
Nz::Quaternionf GetRotation() const;
|
inline Nz::Quaternionf GetRotation() const;
|
||||||
|
|
||||||
bool IsAutoSleepEnabled() const;
|
inline bool IsAutoSleepEnabled() const;
|
||||||
bool IsMoveable() const;
|
inline bool IsMoveable() const;
|
||||||
bool IsNodeSynchronizationEnabled() const;
|
inline bool IsNodeSynchronizationEnabled() const;
|
||||||
bool IsSleeping() const;
|
inline bool IsSleeping() const;
|
||||||
|
|
||||||
void SetAngularDamping(const Nz::Vector3f& angularDamping);
|
inline void SetAngularDamping(const Nz::Vector3f& angularDamping);
|
||||||
void SetAngularVelocity(const Nz::Vector3f& angularVelocity);
|
inline void SetAngularVelocity(const Nz::Vector3f& angularVelocity);
|
||||||
void SetGravityFactor(float gravityFactor);
|
inline void SetGravityFactor(float gravityFactor);
|
||||||
void SetLinearDamping(float damping);
|
inline void SetLinearDamping(float damping);
|
||||||
void SetLinearVelocity(const Nz::Vector3f& velocity);
|
inline void SetLinearVelocity(const Nz::Vector3f& velocity);
|
||||||
void SetMass(float mass);
|
inline void SetMass(float mass);
|
||||||
void SetMassCenter(const Nz::Vector3f& center);
|
inline void SetMassCenter(const Nz::Vector3f& center);
|
||||||
void SetMaterial(const Nz::String& materialName);
|
inline void SetMaterial(const Nz::String& materialName);
|
||||||
void SetMaterial(int materialIndex);
|
inline void SetMaterial(int materialIndex);
|
||||||
void SetPosition(const Nz::Vector3f& position);
|
inline void SetPosition(const Nz::Vector3f& position);
|
||||||
void SetRotation(const Nz::Quaternionf& rotation);
|
inline void SetRotation(const Nz::Quaternionf& rotation);
|
||||||
|
|
||||||
static ComponentIndex componentIndex;
|
static ComponentIndex componentIndex;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ApplyPhysicsState(Nz::RigidBody3D& rigidBody) const;
|
inline void ApplyPhysicsState(Nz::RigidBody3D& rigidBody) const;
|
||||||
void CopyPhysicsState(const Nz::RigidBody3D& rigidBody);
|
inline void CopyPhysicsState(const Nz::RigidBody3D& rigidBody);
|
||||||
Nz::RigidBody3D* GetRigidBody();
|
inline Nz::RigidBody3D* GetRigidBody();
|
||||||
const Nz::RigidBody3D& GetRigidBody() const;
|
inline const Nz::RigidBody3D& GetRigidBody() const;
|
||||||
|
|
||||||
void OnAttached() override;
|
void OnAttached() override;
|
||||||
void OnComponentAttached(BaseComponent& component) override;
|
void OnComponentAttached(BaseComponent& component) override;
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ namespace Ndk
|
||||||
|
|
||||||
using VelocityComponentHandle = Nz::ObjectHandle<VelocityComponent>;
|
using VelocityComponentHandle = Nz::ObjectHandle<VelocityComponent>;
|
||||||
|
|
||||||
class NDK_API VelocityComponent : public Component<VelocityComponent>, public Nz::HandledObject<VelocityComponent>
|
class NDK_API VelocityComponent : public Component<VelocityComponent>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VelocityComponent(const Nz::Vector3f& velocity = Nz::Vector3f::Zero());
|
VelocityComponent(const Nz::Vector3f& velocity = Nz::Vector3f::Zero());
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,8 @@
|
||||||
#define NDK_ENTITY_HPP
|
#define NDK_ENTITY_HPP
|
||||||
|
|
||||||
#include <Nazara/Core/Bitset.hpp>
|
#include <Nazara/Core/Bitset.hpp>
|
||||||
#include <Nazara/Core/HandledObject.hpp>
|
#include <Nazara/Core/MovablePtr.hpp>
|
||||||
|
#include <Nazara/Core/ObjectHandle.hpp>
|
||||||
#include <Nazara/Core/Signal.hpp>
|
#include <Nazara/Core/Signal.hpp>
|
||||||
#include <NDK/Algorithm.hpp>
|
#include <NDK/Algorithm.hpp>
|
||||||
#include <NDK/Prerequisites.hpp>
|
#include <NDK/Prerequisites.hpp>
|
||||||
|
|
@ -33,7 +34,7 @@ namespace Ndk
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Entity(const Entity&) = delete;
|
Entity(const Entity&) = delete;
|
||||||
Entity(Entity&& entity);
|
Entity(Entity&& entity) noexcept;
|
||||||
~Entity();
|
~Entity();
|
||||||
|
|
||||||
BaseComponent& AddComponent(std::unique_ptr<BaseComponent>&& component);
|
BaseComponent& AddComponent(std::unique_ptr<BaseComponent>&& component);
|
||||||
|
|
@ -60,6 +61,7 @@ namespace Ndk
|
||||||
|
|
||||||
void Invalidate();
|
void Invalidate();
|
||||||
inline bool IsEnabled() const;
|
inline bool IsEnabled() const;
|
||||||
|
bool IsDying() const;
|
||||||
inline bool IsValid() const;
|
inline bool IsValid() const;
|
||||||
|
|
||||||
inline void RemoveAllComponents();
|
inline void RemoveAllComponents();
|
||||||
|
|
@ -96,8 +98,8 @@ namespace Ndk
|
||||||
Nz::Bitset<> m_componentBits;
|
Nz::Bitset<> m_componentBits;
|
||||||
Nz::Bitset<> m_removedComponentBits;
|
Nz::Bitset<> m_removedComponentBits;
|
||||||
Nz::Bitset<> m_systemBits;
|
Nz::Bitset<> m_systemBits;
|
||||||
|
Nz::MovablePtr<World> m_world;
|
||||||
EntityId m_id;
|
EntityId m_id;
|
||||||
World* m_world;
|
|
||||||
bool m_enabled;
|
bool m_enabled;
|
||||||
bool m_valid;
|
bool m_valid;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -15,17 +15,18 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EntityOwner() = default;
|
EntityOwner() = default;
|
||||||
explicit EntityOwner(Entity* entity);
|
EntityOwner(Entity* entity);
|
||||||
EntityOwner(const EntityOwner& handle) = delete;
|
EntityOwner(const EntityOwner& handle) = delete;
|
||||||
EntityOwner(EntityOwner&& handle) noexcept = default;
|
EntityOwner(EntityOwner&& handle) noexcept = default;
|
||||||
~EntityOwner();
|
~EntityOwner();
|
||||||
|
|
||||||
|
void Release();
|
||||||
void Reset(Entity* entity = nullptr);
|
void Reset(Entity* entity = nullptr);
|
||||||
void Reset(EntityOwner&& handle);
|
void Reset(EntityOwner&& handle);
|
||||||
|
|
||||||
EntityOwner& operator=(Entity* entity);
|
EntityOwner& operator=(Entity* entity);
|
||||||
EntityOwner& operator=(const EntityOwner& handle) = delete;
|
EntityOwner& operator=(const EntityOwner& handle) = delete;
|
||||||
EntityOwner& operator=(EntityOwner&& handle) noexcept = default;
|
EntityOwner& operator=(EntityOwner&& handle) noexcept;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// This file is part of the "Nazara Development Kit"
|
// This file is part of the "Nazara Development Kit"
|
||||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||||
|
|
||||||
|
#include <NDK/EntityOwner.hpp>
|
||||||
#include <Nazara/Core/StringStream.hpp>
|
#include <Nazara/Core/StringStream.hpp>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
@ -31,22 +32,28 @@ namespace Ndk
|
||||||
*
|
*
|
||||||
* \see Reset
|
* \see Reset
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline EntityOwner::~EntityOwner()
|
inline EntityOwner::~EntityOwner()
|
||||||
{
|
{
|
||||||
Reset(nullptr);
|
Reset(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Release the ownership of the entity without killing it
|
||||||
|
*/
|
||||||
|
inline void EntityOwner::Release()
|
||||||
|
{
|
||||||
|
EntityHandle::Reset(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Resets the ownership of the entity, previous is killed
|
* \brief Resets the ownership of the entity, previous is killed
|
||||||
*
|
*
|
||||||
* \param entity Entity to own
|
* \param entity Entity to own
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline void EntityOwner::Reset(Entity* entity)
|
inline void EntityOwner::Reset(Entity* entity)
|
||||||
{
|
{
|
||||||
if (m_object)
|
if (IsValid())
|
||||||
m_object->Kill();
|
GetObject()->Kill();
|
||||||
|
|
||||||
EntityHandle::Reset(entity);
|
EntityHandle::Reset(entity);
|
||||||
}
|
}
|
||||||
|
|
@ -56,11 +63,10 @@ namespace Ndk
|
||||||
*
|
*
|
||||||
* \param handle EntityOwner to move into this
|
* \param handle EntityOwner to move into this
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline void EntityOwner::Reset(EntityOwner&& handle)
|
inline void EntityOwner::Reset(EntityOwner&& handle)
|
||||||
{
|
{
|
||||||
Reset(handle.GetObject());
|
Reset(handle.GetObject());
|
||||||
handle.m_object = nullptr;
|
handle.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -68,13 +74,26 @@ namespace Ndk
|
||||||
*
|
*
|
||||||
* \param entity Entity to own
|
* \param entity Entity to own
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline EntityOwner& EntityOwner::operator=(Entity* entity)
|
inline EntityOwner& EntityOwner::operator=(Entity* entity)
|
||||||
{
|
{
|
||||||
Reset(entity);
|
Reset(entity);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Steals ownership of a EntityOwner
|
||||||
|
*
|
||||||
|
* \param handle Handle to the new entity to own, or an invalid handle
|
||||||
|
*/
|
||||||
|
inline EntityOwner& EntityOwner::operator=(EntityOwner&& handle) noexcept
|
||||||
|
{
|
||||||
|
Reset(); //< Kill previously owned entity, if any
|
||||||
|
|
||||||
|
EntityHandle::operator=(std::move(handle));
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace std
|
namespace std
|
||||||
|
|
|
||||||
|
|
@ -269,6 +269,15 @@ namespace Nz
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline unsigned int LuaImplQueryArg(const LuaState& state, int index, Vector2i* vec, TypeTag<Vector2i>)
|
||||||
|
{
|
||||||
|
Vector2d vecDouble;
|
||||||
|
unsigned int ret = LuaImplQueryArg(state, index, &vecDouble, TypeTag<Vector2d>());
|
||||||
|
|
||||||
|
vec->Set(vecDouble);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
inline unsigned int LuaImplQueryArg(const LuaState& state, int index, Vector3d* vec, TypeTag<Vector3d>)
|
inline unsigned int LuaImplQueryArg(const LuaState& state, int index, Vector3d* vec, TypeTag<Vector3d>)
|
||||||
{
|
{
|
||||||
switch (state.GetType(index))
|
switch (state.GetType(index))
|
||||||
|
|
@ -308,6 +317,15 @@ namespace Nz
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline unsigned int LuaImplQueryArg(const LuaState& state, int index, Vector3i* vec, TypeTag<Vector3i>)
|
||||||
|
{
|
||||||
|
Vector3d vecDouble;
|
||||||
|
unsigned int ret = LuaImplQueryArg(state, index, &vecDouble, TypeTag<Vector3d>());
|
||||||
|
|
||||||
|
vec->Set(vecDouble);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
inline unsigned int LuaImplQueryArg(const LuaState& state, int index, Ndk::Entity** handle, TypeTag<Ndk::Entity*>)
|
inline unsigned int LuaImplQueryArg(const LuaState& state, int index, Ndk::Entity** handle, TypeTag<Ndk::Entity*>)
|
||||||
{
|
{
|
||||||
if (!state.IsOfType(index, LuaType_Nil))
|
if (!state.IsOfType(index, LuaType_Nil))
|
||||||
|
|
@ -384,7 +402,7 @@ namespace Nz
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned int LuaImplQueryArg(const LuaState& state, int index, MusicParams* params, TypeTag<MusicParams>)
|
inline unsigned int LuaImplQueryArg(const LuaState& state, int index, SoundBufferParams* params, TypeTag<SoundBufferParams>)
|
||||||
{
|
{
|
||||||
state.CheckType(index, Nz::LuaType_Table);
|
state.CheckType(index, Nz::LuaType_Table);
|
||||||
|
|
||||||
|
|
@ -393,7 +411,7 @@ namespace Nz
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned int LuaImplQueryArg(const LuaState& state, int index, SoundBufferParams* params, TypeTag<SoundBufferParams>)
|
inline unsigned int LuaImplQueryArg(const LuaState& state, int index, SoundStreamParams* params, TypeTag<SoundStreamParams>)
|
||||||
{
|
{
|
||||||
state.CheckType(index, Nz::LuaType_Table);
|
state.CheckType(index, Nz::LuaType_Table);
|
||||||
|
|
||||||
|
|
@ -538,6 +556,12 @@ namespace Nz
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int LuaImplReplyVal(const LuaState& state, Vector2i&& val, TypeTag<Vector2i>)
|
||||||
|
{
|
||||||
|
state.PushInstance<Vector2d>("Vector2", val);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
inline int LuaImplReplyVal(const LuaState& state, Vector3d&& val, TypeTag<Vector3d>)
|
inline int LuaImplReplyVal(const LuaState& state, Vector3d&& val, TypeTag<Vector3d>)
|
||||||
{
|
{
|
||||||
state.PushInstance<Vector3d>("Vector3", val);
|
state.PushInstance<Vector3d>("Vector3", val);
|
||||||
|
|
@ -556,6 +580,12 @@ namespace Nz
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int LuaImplReplyVal(const LuaState& state, Vector3i&& val, TypeTag<Vector3i>)
|
||||||
|
{
|
||||||
|
state.PushInstance<Vector3d>("Vector3", val);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
inline int LuaImplReplyVal(const LuaState& state, Ndk::Entity* ptr, TypeTag<Ndk::Entity*>)
|
inline int LuaImplReplyVal(const LuaState& state, Ndk::Entity* ptr, TypeTag<Ndk::Entity*>)
|
||||||
{
|
{
|
||||||
state.PushInstance<Ndk::EntityHandle>("Entity", ptr);
|
state.PushInstance<Ndk::EntityHandle>("Entity", ptr);
|
||||||
|
|
@ -605,12 +635,24 @@ namespace Nz
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int LuaImplReplyVal(const LuaState& state, ModelRef&& handle, TypeTag<ModelRef>)
|
||||||
|
{
|
||||||
|
state.PushInstance<ModelRef>("Model", handle);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
inline int LuaImplReplyVal(const LuaState& state, const SoundBuffer* val, TypeTag<const SoundBuffer*>)
|
inline int LuaImplReplyVal(const LuaState& state, const SoundBuffer* val, TypeTag<const SoundBuffer*>)
|
||||||
{
|
{
|
||||||
state.PushInstance<SoundBufferConstRef>("SoundBuffer", val);
|
state.PushInstance<SoundBufferConstRef>("SoundBuffer", val);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int LuaImplReplyVal(const LuaState& state, SoundBufferRef&& handle, TypeTag<SoundBufferRef>)
|
||||||
|
{
|
||||||
|
state.PushInstance<SoundBufferRef>("SoundBuffer", handle);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
inline int LuaImplReplyVal(const LuaState& state, SpriteRef&& handle, TypeTag<SpriteRef>)
|
inline int LuaImplReplyVal(const LuaState& state, SpriteRef&& handle, TypeTag<SpriteRef>)
|
||||||
{
|
{
|
||||||
state.PushInstance<SpriteRef>("Sprite", handle);
|
state.PushInstance<SpriteRef>("Sprite", handle);
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,11 @@ namespace Ndk
|
||||||
public:
|
public:
|
||||||
System();
|
System();
|
||||||
System(const System&) = delete;
|
System(const System&) = delete;
|
||||||
System(System&&) = default;
|
System(System&&) noexcept = default;
|
||||||
virtual ~System();
|
virtual ~System();
|
||||||
|
|
||||||
System& operator=(const System&) = delete;
|
System& operator=(const System&) = delete;
|
||||||
System& operator=(System&&) = default;
|
System& operator=(System&&) noexcept = default;
|
||||||
|
|
||||||
static SystemIndex RegisterSystem();
|
static SystemIndex RegisterSystem();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#ifndef NDK_SYSTEMS_GLOBAL_HPP
|
#ifndef NDK_SYSTEMS_GLOBAL_HPP
|
||||||
#define NDK_SYSTEMS_GLOBAL_HPP
|
#define NDK_SYSTEMS_GLOBAL_HPP
|
||||||
|
|
||||||
|
#include <NDK/Systems/DebugSystem.hpp>
|
||||||
#include <NDK/Systems/ListenerSystem.hpp>
|
#include <NDK/Systems/ListenerSystem.hpp>
|
||||||
#include <NDK/Systems/ParticleSystem.hpp>
|
#include <NDK/Systems/ParticleSystem.hpp>
|
||||||
#include <NDK/Systems/PhysicsSystem2D.hpp>
|
#include <NDK/Systems/PhysicsSystem2D.hpp>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
// Copyright (C) 2017 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Development Kit"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NDK_SERVER
|
||||||
|
#ifndef NDK_SYSTEMS_DEBUGSYSTEM_HPP
|
||||||
|
#define NDK_SYSTEMS_DEBUGSYSTEM_HPP
|
||||||
|
|
||||||
|
#include <Nazara/Graphics/InstancedRenderable.hpp>
|
||||||
|
#include <Nazara/Utility/IndexBuffer.hpp>
|
||||||
|
#include <Nazara/Utility/Mesh.hpp>
|
||||||
|
#include <Nazara/Utility/VertexBuffer.hpp>
|
||||||
|
#include <NDK/System.hpp>
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
class NDK_API DebugSystem : public System<DebugSystem>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DebugSystem();
|
||||||
|
~DebugSystem() = default;
|
||||||
|
|
||||||
|
static SystemIndex systemIndex;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Nz::InstancedRenderableRef GenerateBox(Nz::Boxf box);
|
||||||
|
Nz::InstancedRenderableRef GenerateCollision3DMesh(Entity* entity);
|
||||||
|
|
||||||
|
Nz::MaterialRef GetCollisionMaterial();
|
||||||
|
Nz::MaterialRef GetGlobalAABBMaterial();
|
||||||
|
Nz::MaterialRef GetLocalAABBMaterial();
|
||||||
|
Nz::MaterialRef GetOBBMaterial();
|
||||||
|
std::pair<Nz::IndexBufferRef, Nz::VertexBufferRef> GetBoxMesh();
|
||||||
|
|
||||||
|
void OnEntityValidation(Entity* entity, bool justAdded) override;
|
||||||
|
|
||||||
|
void OnUpdate(float elapsedTime) override;
|
||||||
|
|
||||||
|
Nz::MaterialRef m_globalAabbMaterial;
|
||||||
|
Nz::MaterialRef m_localAabbMaterial;
|
||||||
|
Nz::MaterialRef m_collisionMaterial;
|
||||||
|
Nz::MaterialRef m_obbMaterial;
|
||||||
|
Nz::IndexBufferRef m_boxMeshIndexBuffer;
|
||||||
|
Nz::VertexBufferRef m_boxMeshVertexBuffer;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <NDK/Systems/DebugSystem.inl>
|
||||||
|
|
||||||
|
#endif // NDK_SYSTEMS_DEBUGSYSTEM_HPP
|
||||||
|
#endif // NDK_SERVER
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
// Copyright (C) 2017 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Development Kit"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||||
|
|
||||||
|
#include <NDK/Systems/DebugSystem.hpp>
|
||||||
|
|
||||||
|
|
@ -16,24 +16,111 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
class NDK_API PhysicsSystem2D : public System<PhysicsSystem2D>
|
class NDK_API PhysicsSystem2D : public System<PhysicsSystem2D>
|
||||||
{
|
{
|
||||||
|
friend class CollisionComponent2D;
|
||||||
|
friend class PhysicsComponent2D;
|
||||||
|
|
||||||
|
using ContactEndCallback = std::function<void(PhysicsSystem2D& world, Nz::Arbiter2D& arbiter, const EntityHandle& bodyA, const EntityHandle& bodyB, void* userdata)>;
|
||||||
|
using ContactPreSolveCallback = std::function<bool(PhysicsSystem2D& world, Nz::Arbiter2D& arbiter, const EntityHandle& bodyA, const EntityHandle& bodyB, void* userdata)>;
|
||||||
|
using ContactPostSolveCallback = std::function<void(PhysicsSystem2D& world, Nz::Arbiter2D& arbiter, const EntityHandle& bodyA, const EntityHandle& bodyB, void* userdata)>;
|
||||||
|
using ContactStartCallback = std::function<bool(PhysicsSystem2D& world, Nz::Arbiter2D& arbiter, const EntityHandle& bodyA, const EntityHandle& bodyB, void* userdata)>;
|
||||||
|
|
||||||
|
using DebugDrawCircleCallback = std::function<void(const Nz::Vector2f& origin, const Nz::RadianAnglef& rotation, float radius, Nz::Color outlineColor, Nz::Color fillColor, void* userdata)>;
|
||||||
|
using DebugDrawDotCallback = std::function<void(const Nz::Vector2f& origin, float radius, Nz::Color color, void* userdata)>;
|
||||||
|
using DebugDrawPolygonCallback = std::function<void(const Nz::Vector2f* vertices, std::size_t vertexCount, float radius, Nz::Color outlineColor, Nz::Color fillColor, void* userdata)>;
|
||||||
|
using DebugDrawSegmentCallback = std::function<void(const Nz::Vector2f& first, const Nz::Vector2f& second, Nz::Color color, void* userdata)>;
|
||||||
|
using DebugDrawTickSegmentCallback = std::function<void(const Nz::Vector2f& first, const Nz::Vector2f& second, float thickness, Nz::Color outlineColor, Nz::Color fillColor, void* userdata)>;
|
||||||
|
using DebugDrawGetColorCallback = std::function<Nz::Color(const EntityHandle& body, std::size_t shapeIndex, void* userdata)>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
struct Callback;
|
||||||
|
struct DebugDrawOptions;
|
||||||
|
struct NearestQueryResult;
|
||||||
|
struct RaycastHit;
|
||||||
|
|
||||||
PhysicsSystem2D();
|
PhysicsSystem2D();
|
||||||
PhysicsSystem2D(const PhysicsSystem2D& system);
|
|
||||||
~PhysicsSystem2D() = default;
|
~PhysicsSystem2D() = default;
|
||||||
|
|
||||||
Nz::PhysWorld2D& GetWorld();
|
void DebugDraw(const DebugDrawOptions& options, bool drawShapes = true, bool drawConstraints = true, bool drawCollisions = true);
|
||||||
const Nz::PhysWorld2D& GetWorld() const;
|
|
||||||
|
inline float GetDamping() const;
|
||||||
|
inline Nz::Vector2f GetGravity() const;
|
||||||
|
inline std::size_t GetIterationCount() const;
|
||||||
|
inline std::size_t GetMaxStepCount() const;
|
||||||
|
inline float GetStepSize() const;
|
||||||
|
|
||||||
|
bool NearestBodyQuery(const Nz::Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, EntityHandle* nearestBody = nullptr);
|
||||||
|
bool NearestBodyQuery(const Nz::Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, NearestQueryResult* result);
|
||||||
|
|
||||||
|
bool RaycastQuery(const Nz::Vector2f& from, const Nz::Vector2f& to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, std::vector<RaycastHit>* hitInfos);
|
||||||
|
bool RaycastQueryFirst(const Nz::Vector2f& from, const Nz::Vector2f& to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RaycastHit* hitInfo = nullptr);
|
||||||
|
|
||||||
|
void RegionQuery(const Nz::Rectf& boundingBox, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, std::vector<EntityHandle>* bodies);
|
||||||
|
|
||||||
|
void RegisterCallbacks(unsigned int collisionId, Callback callbacks);
|
||||||
|
void RegisterCallbacks(unsigned int collisionIdA, unsigned int collisionIdB, Callback callbacks);
|
||||||
|
|
||||||
|
inline void SetDamping(float dampingValue);
|
||||||
|
inline void SetGravity(const Nz::Vector2f& gravity);
|
||||||
|
inline void SetIterationCount(std::size_t iterationCount);
|
||||||
|
inline void SetMaxStepCount(std::size_t maxStepCount);
|
||||||
|
inline void SetStepSize(float stepSize);
|
||||||
|
|
||||||
|
inline void UseSpatialHash(float cellSize, std::size_t entityCount);
|
||||||
|
|
||||||
|
struct Callback
|
||||||
|
{
|
||||||
|
ContactEndCallback endCallback = nullptr;
|
||||||
|
ContactPreSolveCallback preSolveCallback = nullptr;
|
||||||
|
ContactPostSolveCallback postSolveCallback = nullptr;
|
||||||
|
ContactStartCallback startCallback = nullptr;
|
||||||
|
void* userdata;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DebugDrawOptions
|
||||||
|
{
|
||||||
|
Nz::Color constraintColor;
|
||||||
|
Nz::Color collisionPointColor;
|
||||||
|
Nz::Color shapeOutlineColor;
|
||||||
|
|
||||||
|
DebugDrawCircleCallback circleCallback;
|
||||||
|
DebugDrawGetColorCallback colorCallback;
|
||||||
|
DebugDrawDotCallback dotCallback;
|
||||||
|
DebugDrawPolygonCallback polygonCallback;
|
||||||
|
DebugDrawSegmentCallback segmentCallback;
|
||||||
|
DebugDrawTickSegmentCallback thickSegmentCallback;
|
||||||
|
|
||||||
|
void* userdata;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NearestQueryResult
|
||||||
|
{
|
||||||
|
EntityHandle nearestBody;
|
||||||
|
Nz::Vector2f closestPoint;
|
||||||
|
Nz::Vector2f fraction;
|
||||||
|
float distance;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RaycastHit
|
||||||
|
{
|
||||||
|
EntityHandle body;
|
||||||
|
Nz::Vector2f hitPos;
|
||||||
|
Nz::Vector2f hitNormal;
|
||||||
|
float fraction;
|
||||||
|
};
|
||||||
|
|
||||||
static SystemIndex systemIndex;
|
static SystemIndex systemIndex;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CreatePhysWorld() const;
|
void CreatePhysWorld() const;
|
||||||
|
const EntityHandle& GetEntityFromBody(const Nz::RigidBody2D& body) const;
|
||||||
|
inline Nz::PhysWorld2D& GetPhysWorld();
|
||||||
|
inline const Nz::PhysWorld2D& GetPhysWorld() const;
|
||||||
void OnEntityValidation(Entity* entity, bool justAdded) override;
|
void OnEntityValidation(Entity* entity, bool justAdded) override;
|
||||||
void OnUpdate(float elapsedTime) override;
|
void OnUpdate(float elapsedTime) override;
|
||||||
|
|
||||||
EntityList m_dynamicObjects;
|
EntityList m_dynamicObjects;
|
||||||
EntityList m_staticObjects;
|
EntityList m_staticObjects;
|
||||||
mutable std::unique_ptr<Nz::PhysWorld2D> m_world; ///TODO: std::optional (Should I make a Nz::Optional class?)
|
mutable std::unique_ptr<Nz::PhysWorld2D> m_physWorld; ///TODO: std::optional (Should I make a Nz::Optional class?)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,17 +4,72 @@
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
|
inline float PhysicsSystem2D::GetDamping() const
|
||||||
|
{
|
||||||
|
return GetPhysWorld().GetDamping();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Nz::Vector2f PhysicsSystem2D::GetGravity() const
|
||||||
|
{
|
||||||
|
return GetPhysWorld().GetGravity();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::size_t PhysicsSystem2D::GetIterationCount() const
|
||||||
|
{
|
||||||
|
return GetPhysWorld().GetIterationCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::size_t PhysicsSystem2D::GetMaxStepCount() const
|
||||||
|
{
|
||||||
|
return GetPhysWorld().GetMaxStepCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float PhysicsSystem2D::GetStepSize() const
|
||||||
|
{
|
||||||
|
return GetPhysWorld().GetStepSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PhysicsSystem2D::SetDamping(float dampingValue)
|
||||||
|
{
|
||||||
|
GetPhysWorld().SetDamping(dampingValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PhysicsSystem2D::SetGravity(const Nz::Vector2f& gravity)
|
||||||
|
{
|
||||||
|
GetPhysWorld().SetGravity(gravity);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PhysicsSystem2D::SetIterationCount(std::size_t iterationCount)
|
||||||
|
{
|
||||||
|
GetPhysWorld().SetIterationCount(iterationCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PhysicsSystem2D::SetMaxStepCount(std::size_t maxStepCount)
|
||||||
|
{
|
||||||
|
GetPhysWorld().SetMaxStepCount(maxStepCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PhysicsSystem2D::SetStepSize(float stepSize)
|
||||||
|
{
|
||||||
|
GetPhysWorld().SetStepSize(stepSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PhysicsSystem2D::UseSpatialHash(float cellSize, std::size_t entityCount)
|
||||||
|
{
|
||||||
|
GetPhysWorld().UseSpatialHash(cellSize, entityCount);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Gets the physical world
|
* \brief Gets the physical world
|
||||||
* \return A reference to the physical world
|
* \return A reference to the physical world
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline Nz::PhysWorld2D& PhysicsSystem2D::GetWorld()
|
inline Nz::PhysWorld2D& PhysicsSystem2D::GetPhysWorld()
|
||||||
{
|
{
|
||||||
if (!m_world)
|
if (!m_physWorld)
|
||||||
CreatePhysWorld();
|
CreatePhysWorld();
|
||||||
|
|
||||||
return *m_world;
|
return *m_physWorld;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -22,11 +77,11 @@ namespace Ndk
|
||||||
* \return A constant reference to the physical world
|
* \return A constant reference to the physical world
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline const Nz::PhysWorld2D& PhysicsSystem2D::GetWorld() const
|
inline const Nz::PhysWorld2D& PhysicsSystem2D::GetPhysWorld() const
|
||||||
{
|
{
|
||||||
if (!m_world)
|
if (!m_physWorld)
|
||||||
CreatePhysWorld();
|
CreatePhysWorld();
|
||||||
|
|
||||||
return *m_world;
|
return *m_physWorld;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,13 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RenderSystem();
|
RenderSystem();
|
||||||
inline RenderSystem(const RenderSystem& renderSystem);
|
|
||||||
~RenderSystem() = default;
|
~RenderSystem() = default;
|
||||||
|
|
||||||
template<typename T> T& ChangeRenderTechnique();
|
template<typename T> T& ChangeRenderTechnique();
|
||||||
inline Nz::AbstractRenderTechnique& ChangeRenderTechnique(std::unique_ptr<Nz::AbstractRenderTechnique>&& renderTechnique);
|
inline Nz::AbstractRenderTechnique& ChangeRenderTechnique(std::unique_ptr<Nz::AbstractRenderTechnique>&& renderTechnique);
|
||||||
|
|
||||||
|
inline void EnableCulling(bool enable);
|
||||||
|
|
||||||
inline const Nz::BackgroundRef& GetDefaultBackground() const;
|
inline const Nz::BackgroundRef& GetDefaultBackground() const;
|
||||||
inline const Nz::Matrix4f& GetCoordinateSystemMatrix() const;
|
inline const Nz::Matrix4f& GetCoordinateSystemMatrix() const;
|
||||||
inline Nz::Vector3f GetGlobalForward() const;
|
inline Nz::Vector3f GetGlobalForward() const;
|
||||||
|
|
@ -38,6 +39,8 @@ namespace Ndk
|
||||||
inline Nz::Vector3f GetGlobalUp() const;
|
inline Nz::Vector3f GetGlobalUp() const;
|
||||||
inline Nz::AbstractRenderTechnique& GetRenderTechnique() const;
|
inline Nz::AbstractRenderTechnique& GetRenderTechnique() const;
|
||||||
|
|
||||||
|
inline bool IsCullingEnabled() const;
|
||||||
|
|
||||||
inline void SetDefaultBackground(Nz::BackgroundRef background);
|
inline void SetDefaultBackground(Nz::BackgroundRef background);
|
||||||
inline void SetGlobalForward(const Nz::Vector3f& direction);
|
inline void SetGlobalForward(const Nz::Vector3f& direction);
|
||||||
inline void SetGlobalRight(const Nz::Vector3f& direction);
|
inline void SetGlobalRight(const Nz::Vector3f& direction);
|
||||||
|
|
@ -72,6 +75,7 @@ namespace Ndk
|
||||||
Nz::RenderTexture m_shadowRT;
|
Nz::RenderTexture m_shadowRT;
|
||||||
bool m_coordinateSystemInvalidated;
|
bool m_coordinateSystemInvalidated;
|
||||||
bool m_forceRenderQueueInvalidation;
|
bool m_forceRenderQueueInvalidation;
|
||||||
|
bool m_isCullingEnabled;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
// This file is part of the "Nazara Development Kit"
|
// This file is part of the "Nazara Development Kit"
|
||||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||||
|
|
||||||
|
#include <NDK/Systems/RenderSystem.hpp>
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -26,7 +28,24 @@ namespace Ndk
|
||||||
inline Nz::AbstractRenderTechnique& RenderSystem::ChangeRenderTechnique(std::unique_ptr<Nz::AbstractRenderTechnique>&& renderTechnique)
|
inline Nz::AbstractRenderTechnique& RenderSystem::ChangeRenderTechnique(std::unique_ptr<Nz::AbstractRenderTechnique>&& renderTechnique)
|
||||||
{
|
{
|
||||||
m_renderTechnique = std::move(renderTechnique);
|
m_renderTechnique = std::move(renderTechnique);
|
||||||
return *m_renderTechnique.get();
|
return *m_renderTechnique;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Enables/disables object culling
|
||||||
|
*
|
||||||
|
* Object culling is an algorithm used by the render system to detect invisible objects (which will not appear on screen) before they are rendered.
|
||||||
|
* This includes Frustum Culling and potentially Occlusion Culling.
|
||||||
|
*
|
||||||
|
* Disabling this is not recommended, as the system will draw every object in the world which could induce a performance loss.
|
||||||
|
*
|
||||||
|
* \param enable Whether to enable or disable culling
|
||||||
|
*
|
||||||
|
* \see IsCullingEnabled
|
||||||
|
*/
|
||||||
|
inline void RenderSystem::EnableCulling(bool enable)
|
||||||
|
{
|
||||||
|
m_isCullingEnabled = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -89,6 +108,17 @@ namespace Ndk
|
||||||
return *m_renderTechnique.get();
|
return *m_renderTechnique.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Query if culling is enabled (enabled by default)
|
||||||
|
* \return True if culling is enabled, false otherwise
|
||||||
|
*
|
||||||
|
* \see EnableCulling
|
||||||
|
*/
|
||||||
|
inline bool RenderSystem::IsCullingEnabled() const
|
||||||
|
{
|
||||||
|
return m_isCullingEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Sets the background used for rendering
|
* \brief Sets the background used for rendering
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
// Copyright (C) 2017 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Development Kit"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef NDK_WIDGETS_BOXLAYOUT_HPP
|
||||||
|
#define NDK_WIDGETS_BOXLAYOUT_HPP
|
||||||
|
|
||||||
|
#include <NDK/Prerequisites.hpp>
|
||||||
|
#include <NDK/BaseWidget.hpp>
|
||||||
|
#include <NDK/Widgets/Enums.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
class NDK_API BoxLayout : public BaseWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline BoxLayout(BaseWidget* parent, BoxLayoutOrientation orientation);
|
||||||
|
BoxLayout(const BoxLayout&) = delete;
|
||||||
|
BoxLayout(BoxLayout&&) = default;
|
||||||
|
~BoxLayout() = default;
|
||||||
|
|
||||||
|
void Layout() override;
|
||||||
|
|
||||||
|
BoxLayout& operator=(const BoxLayout&) = delete;
|
||||||
|
BoxLayout& operator=(BoxLayout&&) = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct ChildInfo
|
||||||
|
{
|
||||||
|
BaseWidget* widget;
|
||||||
|
bool isConstrained;
|
||||||
|
float maximumSize;
|
||||||
|
float minimumSize;
|
||||||
|
float size;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<ChildInfo> m_childInfos;
|
||||||
|
BoxLayoutOrientation m_orientation;
|
||||||
|
float m_spacing;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <NDK/Widgets/BoxLayout.inl>
|
||||||
|
|
||||||
|
#endif // NDK_WIDGETS_BOXLAYOUT_HPP
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright (C) 2017 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Development Kit"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||||
|
|
||||||
|
#include <NDK/Widgets/BoxLayout.hpp>
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
BoxLayout::BoxLayout(BaseWidget* parent, BoxLayoutOrientation orientation) :
|
||||||
|
BaseWidget(parent),
|
||||||
|
m_orientation(orientation),
|
||||||
|
m_spacing(5.f)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -23,15 +23,11 @@ namespace Ndk
|
||||||
class NDK_API ButtonWidget : public BaseWidget
|
class NDK_API ButtonWidget : public BaseWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ButtonWidget(BaseWidget* parent = nullptr);
|
ButtonWidget(BaseWidget* parent);
|
||||||
ButtonWidget(const ButtonWidget&) = delete;
|
ButtonWidget(const ButtonWidget&) = delete;
|
||||||
ButtonWidget(ButtonWidget&&) = default;
|
ButtonWidget(ButtonWidget&&) = default;
|
||||||
~ButtonWidget() = default;
|
~ButtonWidget() = default;
|
||||||
|
|
||||||
//virtual ButtonWidget* Clone() const = 0;
|
|
||||||
|
|
||||||
void ResizeToContent() override;
|
|
||||||
|
|
||||||
inline const Nz::Color& GetColor() const;
|
inline const Nz::Color& GetColor() const;
|
||||||
inline const Nz::Color& GetCornerColor() const;
|
inline const Nz::Color& GetCornerColor() const;
|
||||||
inline const Nz::Color& GetHoverColor() const;
|
inline const Nz::Color& GetHoverColor() const;
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,10 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
m_textSprite->Update(drawer);
|
m_textSprite->Update(drawer);
|
||||||
|
|
||||||
|
Nz::Vector2f textSize = Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths());
|
||||||
|
SetMinimumSize(textSize);
|
||||||
|
SetPreferredSize(textSize + Nz::Vector2f(20.f, 10.f));
|
||||||
|
|
||||||
Layout();
|
Layout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (C) 2017 Samy Bensaid
|
// Copyright (C) 2017 Samy Bensaid
|
||||||
// This file is part of the "Nazara Development Kit"
|
// This file is part of the "Nazara Development Kit"
|
||||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||||
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Ndk
|
||||||
friend class Sdk;
|
friend class Sdk;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CheckboxWidget(BaseWidget* parent = nullptr);
|
CheckboxWidget(BaseWidget* parent);
|
||||||
CheckboxWidget(const CheckboxWidget&) = delete;
|
CheckboxWidget(const CheckboxWidget&) = delete;
|
||||||
CheckboxWidget(CheckboxWidget&&) = default;
|
CheckboxWidget(CheckboxWidget&&) = default;
|
||||||
~CheckboxWidget() = default;
|
~CheckboxWidget() = default;
|
||||||
|
|
@ -53,7 +53,6 @@ namespace Ndk
|
||||||
void SetState(CheckboxState state);
|
void SetState(CheckboxState state);
|
||||||
inline void SetTextMargin(float margin);
|
inline void SetTextMargin(float margin);
|
||||||
|
|
||||||
void ResizeToContent() override;
|
|
||||||
inline void UpdateText(const Nz::AbstractTextDrawer& drawer);
|
inline void UpdateText(const Nz::AbstractTextDrawer& drawer);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -68,6 +67,7 @@ namespace Ndk
|
||||||
|
|
||||||
void Layout() override;
|
void Layout() override;
|
||||||
void UpdateCheckbox();
|
void UpdateCheckbox();
|
||||||
|
void UpdateSize();
|
||||||
|
|
||||||
void OnMouseButtonRelease(int x, int y, Nz::Mouse::Button button) override;
|
void OnMouseButtonRelease(int x, int y, Nz::Mouse::Button button) override;
|
||||||
inline bool ContainsCheckbox(int x, int y) const;
|
inline bool ContainsCheckbox(int x, int y) const;
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@ namespace Ndk
|
||||||
m_checkboxBackgroundSprite->SetSize(size - GetCheckboxBorderSize() * 2.f);
|
m_checkboxBackgroundSprite->SetSize(size - GetCheckboxBorderSize() * 2.f);
|
||||||
m_checkboxContentSprite->SetSize(GetCheckboxSize() - GetCheckboxBorderSize() * 2.f - Nz::Vector2f { 4.f, 4.f });
|
m_checkboxContentSprite->SetSize(GetCheckboxSize() - GetCheckboxBorderSize() * 2.f - Nz::Vector2f { 4.f, 4.f });
|
||||||
|
|
||||||
|
UpdateSize();
|
||||||
Layout();
|
Layout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,6 +78,8 @@ namespace Ndk
|
||||||
inline void CheckboxWidget::UpdateText(const Nz::AbstractTextDrawer& drawer)
|
inline void CheckboxWidget::UpdateText(const Nz::AbstractTextDrawer& drawer)
|
||||||
{
|
{
|
||||||
m_textSprite->Update(drawer);
|
m_textSprite->Update(drawer);
|
||||||
|
|
||||||
|
UpdateSize();
|
||||||
Layout();
|
Layout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,12 @@
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
|
enum BoxLayoutOrientation
|
||||||
|
{
|
||||||
|
BoxLayoutOrientation_Horizontal,
|
||||||
|
BoxLayoutOrientation_Vertical
|
||||||
|
};
|
||||||
|
|
||||||
enum CheckboxState
|
enum CheckboxState
|
||||||
{
|
{
|
||||||
CheckboxState_Checked,
|
CheckboxState_Checked,
|
||||||
|
|
|
||||||
|
|
@ -19,21 +19,19 @@ namespace Ndk
|
||||||
class NDK_API ImageWidget : public BaseWidget
|
class NDK_API ImageWidget : public BaseWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ImageWidget(BaseWidget* parent = nullptr);
|
ImageWidget(BaseWidget* parent);
|
||||||
ImageWidget(const ImageWidget&) = delete;
|
ImageWidget(const ImageWidget&) = delete;
|
||||||
ImageWidget(ImageWidget&&) = default;
|
ImageWidget(ImageWidget&&) = default;
|
||||||
~ImageWidget() = default;
|
~ImageWidget() = default;
|
||||||
|
|
||||||
//virtual ImageWidget* Clone() const = 0;
|
//virtual ImageWidget* Clone() const = 0;
|
||||||
|
|
||||||
void ResizeToContent() override;
|
|
||||||
|
|
||||||
inline const Nz::Color& GetColor() const;
|
inline const Nz::Color& GetColor() const;
|
||||||
inline const Nz::TextureRef& GetTexture() const;
|
inline const Nz::TextureRef& GetTexture() const;
|
||||||
inline const Nz::Rectf& GetTextureCoords() const;
|
inline const Nz::Rectf& GetTextureCoords() const;
|
||||||
|
|
||||||
inline void SetColor(const Nz::Color& color);
|
inline void SetColor(const Nz::Color& color);
|
||||||
inline void SetTexture(const Nz::TextureRef& texture, bool resizeToContent = true);
|
inline void SetTexture(const Nz::TextureRef& texture);
|
||||||
inline void SetTextureCoords(const Nz::Rectf& coords);
|
inline void SetTextureCoords(const Nz::Rectf& coords);
|
||||||
inline void SetTextureRect(const Nz::Rectui& rect);
|
inline void SetTextureRect(const Nz::Rectui& rect);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,12 +26,13 @@ namespace Ndk
|
||||||
m_sprite->SetColor(color);
|
m_sprite->SetColor(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void ImageWidget::SetTexture(const Nz::TextureRef& texture, bool resizeToContent)
|
inline void ImageWidget::SetTexture(const Nz::TextureRef& texture)
|
||||||
{
|
{
|
||||||
m_sprite->SetTexture(texture, false);
|
m_sprite->SetTexture(texture, false);
|
||||||
|
|
||||||
if (resizeToContent)
|
Nz::Vector2f textureSize = Nz::Vector2f(Nz::Vector2ui(m_sprite->GetMaterial()->GetDiffuseMap()->GetSize()));
|
||||||
ResizeToContent();
|
SetMinimumSize(textureSize);
|
||||||
|
SetPreferredSize(textureSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void ImageWidget::SetTextureCoords(const Nz::Rectf& coords)
|
inline void ImageWidget::SetTextureCoords(const Nz::Rectf& coords)
|
||||||
|
|
|
||||||
|
|
@ -21,23 +21,17 @@ namespace Ndk
|
||||||
class NDK_API LabelWidget : public BaseWidget
|
class NDK_API LabelWidget : public BaseWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LabelWidget(BaseWidget* parent = nullptr);
|
LabelWidget(BaseWidget* parent);
|
||||||
LabelWidget(const LabelWidget&) = delete;
|
LabelWidget(const LabelWidget&) = delete;
|
||||||
LabelWidget(LabelWidget&&) = default;
|
LabelWidget(LabelWidget&&) = default;
|
||||||
~LabelWidget() = default;
|
~LabelWidget() = default;
|
||||||
|
|
||||||
//virtual LabelWidget* Clone() const = 0;
|
|
||||||
|
|
||||||
void ResizeToContent() override;
|
|
||||||
|
|
||||||
inline void UpdateText(const Nz::AbstractTextDrawer& drawer);
|
inline void UpdateText(const Nz::AbstractTextDrawer& drawer);
|
||||||
|
|
||||||
LabelWidget& operator=(const LabelWidget&) = delete;
|
LabelWidget& operator=(const LabelWidget&) = delete;
|
||||||
LabelWidget& operator=(LabelWidget&&) = default;
|
LabelWidget& operator=(LabelWidget&&) = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Layout() override;
|
|
||||||
|
|
||||||
EntityHandle m_textEntity;
|
EntityHandle m_textEntity;
|
||||||
Nz::TextSpriteRef m_textSprite;
|
Nz::TextSpriteRef m_textSprite;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -9,5 +9,8 @@ namespace Ndk
|
||||||
inline void LabelWidget::UpdateText(const Nz::AbstractTextDrawer& drawer)
|
inline void LabelWidget::UpdateText(const Nz::AbstractTextDrawer& drawer)
|
||||||
{
|
{
|
||||||
m_textSprite->Update(drawer);
|
m_textSprite->Update(drawer);
|
||||||
|
|
||||||
|
SetMinimumSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths()));
|
||||||
|
SetPreferredSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (C) 2017 Samy Bensaid
|
// Copyright (C) 2017 Samy Bensaid
|
||||||
// This file is part of the "Nazara Development Kit"
|
// This file is part of the "Nazara Development Kit"
|
||||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||||
|
|
||||||
|
|
@ -23,7 +23,7 @@ namespace Ndk
|
||||||
friend class Sdk;
|
friend class Sdk;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ProgressBarWidget(BaseWidget* parent = nullptr);
|
ProgressBarWidget(BaseWidget* parent);
|
||||||
ProgressBarWidget(const ProgressBarWidget&) = delete;
|
ProgressBarWidget(const ProgressBarWidget&) = delete;
|
||||||
ProgressBarWidget(ProgressBarWidget&&) = default;
|
ProgressBarWidget(ProgressBarWidget&&) = default;
|
||||||
~ProgressBarWidget() = default;
|
~ProgressBarWidget() = default;
|
||||||
|
|
@ -67,8 +67,6 @@ namespace Ndk
|
||||||
inline void SetTextMargin(float margin);
|
inline void SetTextMargin(float margin);
|
||||||
inline void SetTextColor(const Nz::Color& color);
|
inline void SetTextColor(const Nz::Color& color);
|
||||||
|
|
||||||
inline void ResizeToContent() override {}
|
|
||||||
|
|
||||||
NazaraSignal(OnValueChanged, const ProgressBarWidget* /*progressBar*/);
|
NazaraSignal(OnValueChanged, const ProgressBarWidget* /*progressBar*/);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (C) 2017 Samy Bensaid
|
// Copyright (C) 2017 Samy Bensaid
|
||||||
// This file is part of the "Nazara Development Kit"
|
// This file is part of the "Nazara Development Kit"
|
||||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||||
|
|
||||||
|
|
@ -148,9 +148,8 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
if (IsTextEnabled())
|
if (IsTextEnabled())
|
||||||
{
|
{
|
||||||
Nz::Vector2f size = GetContentSize();
|
Nz::Vector2f size = GetSize();
|
||||||
m_textSprite->Update(Nz::SimpleTextDrawer::Draw(Nz::String::Number(m_value).Append('%'),
|
m_textSprite->Update(Nz::SimpleTextDrawer::Draw(Nz::String::Number(m_value).Append('%'), static_cast<unsigned int>(std::min(size.x, size.y) / 2.f), 0u, m_textColor));
|
||||||
static_cast<unsigned>(std::min(size.x, size.y) / 2.f), 0u, m_textColor));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,17 @@
|
||||||
#include <Nazara/Utility/SimpleTextDrawer.hpp>
|
#include <Nazara/Utility/SimpleTextDrawer.hpp>
|
||||||
#include <NDK/BaseWidget.hpp>
|
#include <NDK/BaseWidget.hpp>
|
||||||
#include <NDK/Widgets/Enums.hpp>
|
#include <NDK/Widgets/Enums.hpp>
|
||||||
|
#include <functional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
class NDK_API TextAreaWidget : public BaseWidget
|
class NDK_API TextAreaWidget : public BaseWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TextAreaWidget(BaseWidget* parent = nullptr);
|
using CharacterFilter = std::function<bool(char32_t)>;
|
||||||
|
|
||||||
|
TextAreaWidget(BaseWidget* parent);
|
||||||
TextAreaWidget(const TextAreaWidget&) = delete;
|
TextAreaWidget(const TextAreaWidget&) = delete;
|
||||||
TextAreaWidget(TextAreaWidget&&) = default;
|
TextAreaWidget(TextAreaWidget&&) = default;
|
||||||
~TextAreaWidget() = default;
|
~TextAreaWidget() = default;
|
||||||
|
|
@ -28,10 +32,18 @@ namespace Ndk
|
||||||
|
|
||||||
//virtual TextAreaWidget* Clone() const = 0;
|
//virtual TextAreaWidget* Clone() const = 0;
|
||||||
|
|
||||||
inline void EnableMultiline(bool enable = true);
|
|
||||||
|
|
||||||
|
inline void EnableMultiline(bool enable = true);
|
||||||
|
inline void EnableTabWriting(bool enable = true);
|
||||||
|
|
||||||
|
inline void Erase(std::size_t glyphPosition);
|
||||||
|
void Erase(std::size_t firstGlyph, std::size_t lastGlyph);
|
||||||
|
void EraseSelection();
|
||||||
|
|
||||||
|
inline const CharacterFilter& GetCharacterFilter() const;
|
||||||
inline unsigned int GetCharacterSize() const;
|
inline unsigned int GetCharacterSize() const;
|
||||||
inline const Nz::Vector2ui& GetCursorPosition() const;
|
inline const Nz::Vector2ui& GetCursorPosition() const;
|
||||||
|
inline Nz::Vector2ui GetCursorPosition(std::size_t glyphIndex) const;
|
||||||
inline const Nz::String& GetDisplayText() const;
|
inline const Nz::String& GetDisplayText() const;
|
||||||
inline EchoMode GetEchoMode() const;
|
inline EchoMode GetEchoMode() const;
|
||||||
inline std::size_t GetGlyphIndex() const;
|
inline std::size_t GetGlyphIndex() const;
|
||||||
|
|
@ -39,25 +51,30 @@ namespace Ndk
|
||||||
inline const Nz::String& GetText() const;
|
inline const Nz::String& GetText() const;
|
||||||
inline const Nz::Color& GetTextColor() const;
|
inline const Nz::Color& GetTextColor() const;
|
||||||
|
|
||||||
std::size_t GetHoveredGlyph(float x, float y) const;
|
Nz::Vector2ui GetHoveredGlyph(float x, float y) const;
|
||||||
|
|
||||||
|
inline bool HasSelection() const;
|
||||||
|
|
||||||
inline bool IsMultilineEnabled() const;
|
inline bool IsMultilineEnabled() const;
|
||||||
inline bool IsReadOnly() const;
|
inline bool IsReadOnly() const;
|
||||||
|
inline bool IsTabWritingEnabled() const;
|
||||||
|
|
||||||
inline void MoveCursor(int offset);
|
inline void MoveCursor(int offset);
|
||||||
inline void MoveCursor(const Nz::Vector2i& offset);
|
inline void MoveCursor(const Nz::Vector2i& offset);
|
||||||
|
|
||||||
void ResizeToContent() override;
|
inline void SetCharacterFilter(CharacterFilter filter);
|
||||||
|
void SetCharacterSize(unsigned int characterSize);
|
||||||
inline void SetCharacterSize(unsigned int characterSize);
|
|
||||||
inline void SetCursorPosition(std::size_t glyphIndex);
|
inline void SetCursorPosition(std::size_t glyphIndex);
|
||||||
inline void SetCursorPosition(Nz::Vector2ui cursorPosition);
|
inline void SetCursorPosition(Nz::Vector2ui cursorPosition);
|
||||||
inline void SetEchoMode(EchoMode echoMode);
|
inline void SetEchoMode(EchoMode echoMode);
|
||||||
inline void SetReadOnly(bool readOnly = true);
|
inline void SetReadOnly(bool readOnly = true);
|
||||||
|
inline void SetSelection(Nz::Vector2ui fromPosition, Nz::Vector2ui toPosition);
|
||||||
inline void SetText(const Nz::String& text);
|
inline void SetText(const Nz::String& text);
|
||||||
inline void SetTextColor(const Nz::Color& text);
|
inline void SetTextColor(const Nz::Color& text);
|
||||||
|
|
||||||
void Write(const Nz::String& text);
|
inline void Write(const Nz::String& text);
|
||||||
|
inline void Write(const Nz::String& text, const Nz::Vector2ui& glyphPosition);
|
||||||
|
void Write(const Nz::String& text, std::size_t glyphPosition);
|
||||||
|
|
||||||
TextAreaWidget& operator=(const TextAreaWidget&) = delete;
|
TextAreaWidget& operator=(const TextAreaWidget&) = delete;
|
||||||
TextAreaWidget& operator=(TextAreaWidget&&) = default;
|
TextAreaWidget& operator=(TextAreaWidget&&) = default;
|
||||||
|
|
@ -65,6 +82,8 @@ namespace Ndk
|
||||||
NazaraSignal(OnTextAreaCursorMove, const TextAreaWidget* /*textArea*/, std::size_t* /*newCursorPosition*/);
|
NazaraSignal(OnTextAreaCursorMove, const TextAreaWidget* /*textArea*/, std::size_t* /*newCursorPosition*/);
|
||||||
NazaraSignal(OnTextAreaKeyBackspace, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
NazaraSignal(OnTextAreaKeyBackspace, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||||
NazaraSignal(OnTextAreaKeyDown, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
NazaraSignal(OnTextAreaKeyDown, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||||
|
NazaraSignal(OnTextAreaKeyEnd, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||||
|
NazaraSignal(OnTextAreaKeyHome, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||||
NazaraSignal(OnTextAreaKeyLeft, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
NazaraSignal(OnTextAreaKeyLeft, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||||
NazaraSignal(OnTextAreaKeyReturn, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
NazaraSignal(OnTextAreaKeyReturn, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||||
NazaraSignal(OnTextAreaKeyRight, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
NazaraSignal(OnTextAreaKeyRight, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||||
|
|
@ -80,21 +99,29 @@ namespace Ndk
|
||||||
bool OnKeyPressed(const Nz::WindowEvent::KeyEvent& key) override;
|
bool OnKeyPressed(const Nz::WindowEvent::KeyEvent& key) override;
|
||||||
void OnKeyReleased(const Nz::WindowEvent::KeyEvent& key) override;
|
void OnKeyReleased(const Nz::WindowEvent::KeyEvent& key) override;
|
||||||
void OnMouseButtonPress(int /*x*/, int /*y*/, Nz::Mouse::Button button) override;
|
void OnMouseButtonPress(int /*x*/, int /*y*/, Nz::Mouse::Button button) override;
|
||||||
|
void OnMouseButtonRelease(int /*x*/, int /*y*/, Nz::Mouse::Button button) override;
|
||||||
|
void OnMouseEnter() override;
|
||||||
|
void OnMouseMoved(int x, int y, int deltaX, int deltaY) override;
|
||||||
void OnTextEntered(char32_t character, bool repeated) override;
|
void OnTextEntered(char32_t character, bool repeated) override;
|
||||||
|
|
||||||
void RefreshCursor();
|
void RefreshCursor();
|
||||||
void UpdateDisplayText();
|
void UpdateDisplayText();
|
||||||
|
|
||||||
|
CharacterFilter m_characterFilter;
|
||||||
EchoMode m_echoMode;
|
EchoMode m_echoMode;
|
||||||
EntityHandle m_cursorEntity;
|
EntityHandle m_cursorEntity;
|
||||||
EntityHandle m_textEntity;
|
EntityHandle m_textEntity;
|
||||||
Nz::SimpleTextDrawer m_drawer;
|
Nz::SimpleTextDrawer m_drawer;
|
||||||
Nz::SpriteRef m_cursorSprite;
|
|
||||||
Nz::String m_text;
|
Nz::String m_text;
|
||||||
Nz::TextSpriteRef m_textSprite;
|
Nz::TextSpriteRef m_textSprite;
|
||||||
Nz::Vector2ui m_cursorPosition;
|
Nz::Vector2ui m_cursorPositionBegin;
|
||||||
|
Nz::Vector2ui m_cursorPositionEnd;
|
||||||
|
Nz::Vector2ui m_selectionCursor;
|
||||||
|
std::vector<Nz::SpriteRef> m_cursorSprites;
|
||||||
|
bool m_isMouseButtonDown;
|
||||||
bool m_multiLineEnabled;
|
bool m_multiLineEnabled;
|
||||||
bool m_readOnly;
|
bool m_readOnly;
|
||||||
|
bool m_tabEnabled; // writes (Shift+)Tab character if set to true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,8 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
inline void TextAreaWidget::Clear()
|
inline void TextAreaWidget::Clear()
|
||||||
{
|
{
|
||||||
m_cursorPosition.MakeZero();
|
m_cursorPositionBegin.MakeZero();
|
||||||
|
m_cursorPositionEnd.MakeZero();
|
||||||
m_drawer.Clear();
|
m_drawer.Clear();
|
||||||
m_text.Clear();
|
m_text.Clear();
|
||||||
m_textSprite->Update(m_drawer);
|
m_textSprite->Update(m_drawer);
|
||||||
|
|
@ -22,6 +23,21 @@ namespace Ndk
|
||||||
m_multiLineEnabled = enable;
|
m_multiLineEnabled = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void TextAreaWidget::EnableTabWriting(bool enable)
|
||||||
|
{
|
||||||
|
m_tabEnabled = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void TextAreaWidget::Erase(std::size_t glyphPosition)
|
||||||
|
{
|
||||||
|
Erase(glyphPosition, glyphPosition + 1U);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const TextAreaWidget::CharacterFilter& TextAreaWidget::GetCharacterFilter() const
|
||||||
|
{
|
||||||
|
return m_characterFilter;
|
||||||
|
}
|
||||||
|
|
||||||
inline unsigned int TextAreaWidget::GetCharacterSize() const
|
inline unsigned int TextAreaWidget::GetCharacterSize() const
|
||||||
{
|
{
|
||||||
return m_drawer.GetCharacterSize();
|
return m_drawer.GetCharacterSize();
|
||||||
|
|
@ -29,7 +45,30 @@ namespace Ndk
|
||||||
|
|
||||||
inline const Nz::Vector2ui& TextAreaWidget::GetCursorPosition() const
|
inline const Nz::Vector2ui& TextAreaWidget::GetCursorPosition() const
|
||||||
{
|
{
|
||||||
return m_cursorPosition;
|
return m_cursorPositionBegin;
|
||||||
|
}
|
||||||
|
|
||||||
|
Nz::Vector2ui TextAreaWidget::GetCursorPosition(std::size_t glyphIndex) const
|
||||||
|
{
|
||||||
|
glyphIndex = std::min(glyphIndex, m_drawer.GetGlyphCount());
|
||||||
|
|
||||||
|
std::size_t lineCount = m_drawer.GetLineCount();
|
||||||
|
std::size_t line = 0U;
|
||||||
|
for (std::size_t i = line + 1; i < lineCount; ++i)
|
||||||
|
{
|
||||||
|
if (m_drawer.GetLine(i).glyphIndex > glyphIndex)
|
||||||
|
break;
|
||||||
|
|
||||||
|
line = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& lineInfo = m_drawer.GetLine(line);
|
||||||
|
|
||||||
|
Nz::Vector2ui cursorPos;
|
||||||
|
cursorPos.y = static_cast<unsigned int>(line);
|
||||||
|
cursorPos.x = static_cast<unsigned int>(glyphIndex - lineInfo.glyphIndex);
|
||||||
|
|
||||||
|
return cursorPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const Nz::String& TextAreaWidget::GetDisplayText() const
|
inline const Nz::String& TextAreaWidget::GetDisplayText() const
|
||||||
|
|
@ -68,11 +107,21 @@ namespace Ndk
|
||||||
return m_drawer.GetColor();
|
return m_drawer.GetColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool Ndk::TextAreaWidget::IsMultilineEnabled() const
|
inline bool TextAreaWidget::HasSelection() const
|
||||||
|
{
|
||||||
|
return m_cursorPositionBegin != m_cursorPositionEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool TextAreaWidget::IsMultilineEnabled() const
|
||||||
{
|
{
|
||||||
return m_multiLineEnabled;
|
return m_multiLineEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool TextAreaWidget::IsTabWritingEnabled() const
|
||||||
|
{
|
||||||
|
return m_tabEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool TextAreaWidget::IsReadOnly() const
|
inline bool TextAreaWidget::IsReadOnly() const
|
||||||
{
|
{
|
||||||
return m_readOnly;
|
return m_readOnly;
|
||||||
|
|
@ -80,7 +129,7 @@ namespace Ndk
|
||||||
|
|
||||||
inline void TextAreaWidget::MoveCursor(int offset)
|
inline void TextAreaWidget::MoveCursor(int offset)
|
||||||
{
|
{
|
||||||
std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition);
|
std::size_t cursorGlyph = GetGlyphIndex(m_cursorPositionBegin);
|
||||||
if (offset >= 0)
|
if (offset >= 0)
|
||||||
SetCursorPosition(cursorGlyph + static_cast<std::size_t>(offset));
|
SetCursorPosition(cursorGlyph + static_cast<std::size_t>(offset));
|
||||||
else
|
else
|
||||||
|
|
@ -109,40 +158,24 @@ namespace Ndk
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Nz::Vector2ui cursorPosition = m_cursorPosition;
|
Nz::Vector2ui cursorPosition = m_cursorPositionBegin;
|
||||||
cursorPosition.x = ClampOffset(static_cast<unsigned int>(cursorPosition.x), offset.x);
|
cursorPosition.x = ClampOffset(static_cast<unsigned int>(cursorPosition.x), offset.x);
|
||||||
cursorPosition.y = ClampOffset(static_cast<unsigned int>(cursorPosition.y), offset.y);
|
cursorPosition.y = ClampOffset(static_cast<unsigned int>(cursorPosition.y), offset.y);
|
||||||
|
|
||||||
SetCursorPosition(cursorPosition);
|
SetCursorPosition(cursorPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void TextAreaWidget::SetCharacterSize(unsigned int characterSize)
|
inline void TextAreaWidget::SetCharacterFilter(CharacterFilter filter)
|
||||||
{
|
{
|
||||||
m_drawer.SetCharacterSize(characterSize);
|
m_characterFilter = std::move(filter);
|
||||||
|
|
||||||
UpdateDisplayText();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void TextAreaWidget::SetCursorPosition(std::size_t glyphIndex)
|
inline void TextAreaWidget::SetCursorPosition(std::size_t glyphIndex)
|
||||||
{
|
{
|
||||||
OnTextAreaCursorMove(this, &glyphIndex);
|
OnTextAreaCursorMove(this, &glyphIndex);
|
||||||
|
|
||||||
glyphIndex = std::min(glyphIndex, m_drawer.GetGlyphCount());
|
m_cursorPositionBegin = GetCursorPosition(glyphIndex);
|
||||||
|
m_cursorPositionEnd = m_cursorPositionBegin;
|
||||||
std::size_t lineCount = m_drawer.GetLineCount();
|
|
||||||
std::size_t line = 0U;
|
|
||||||
for (std::size_t i = line + 1; i < lineCount; ++i)
|
|
||||||
{
|
|
||||||
if (m_drawer.GetLine(i).glyphIndex > glyphIndex)
|
|
||||||
break;
|
|
||||||
|
|
||||||
line = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& lineInfo = m_drawer.GetLine(line);
|
|
||||||
|
|
||||||
m_cursorPosition.y = static_cast<unsigned int>(line);
|
|
||||||
m_cursorPosition.x = static_cast<unsigned int>(glyphIndex - lineInfo.glyphIndex);
|
|
||||||
|
|
||||||
RefreshCursor();
|
RefreshCursor();
|
||||||
}
|
}
|
||||||
|
|
@ -153,7 +186,7 @@ namespace Ndk
|
||||||
if (cursorPosition.y >= lineCount)
|
if (cursorPosition.y >= lineCount)
|
||||||
cursorPosition.y = static_cast<unsigned int>(lineCount - 1);
|
cursorPosition.y = static_cast<unsigned int>(lineCount - 1);
|
||||||
|
|
||||||
m_cursorPosition = cursorPosition;
|
m_cursorPositionBegin = cursorPosition;
|
||||||
|
|
||||||
const auto& lineInfo = m_drawer.GetLine(cursorPosition.y);
|
const auto& lineInfo = m_drawer.GetLine(cursorPosition.y);
|
||||||
if (cursorPosition.y + 1 < lineCount)
|
if (cursorPosition.y + 1 < lineCount)
|
||||||
|
|
@ -162,6 +195,8 @@ namespace Ndk
|
||||||
cursorPosition.x = std::min(cursorPosition.x, static_cast<unsigned int>(nextLineInfo.glyphIndex - lineInfo.glyphIndex - 1));
|
cursorPosition.x = std::min(cursorPosition.x, static_cast<unsigned int>(nextLineInfo.glyphIndex - lineInfo.glyphIndex - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_cursorPositionEnd = m_cursorPositionBegin;
|
||||||
|
|
||||||
std::size_t glyphIndex = lineInfo.glyphIndex + cursorPosition.x;
|
std::size_t glyphIndex = lineInfo.glyphIndex + cursorPosition.x;
|
||||||
|
|
||||||
OnTextAreaCursorMove(this, &glyphIndex);
|
OnTextAreaCursorMove(this, &glyphIndex);
|
||||||
|
|
@ -182,6 +217,23 @@ namespace Ndk
|
||||||
m_cursorEntity->Enable(!m_readOnly && HasFocus());
|
m_cursorEntity->Enable(!m_readOnly && HasFocus());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void TextAreaWidget::SetSelection(Nz::Vector2ui fromPosition, Nz::Vector2ui toPosition)
|
||||||
|
{
|
||||||
|
///TODO: Check if position are valid
|
||||||
|
|
||||||
|
// Ensure begin is before end
|
||||||
|
if (toPosition.y < fromPosition.y || (toPosition.y == fromPosition.y && toPosition.x < fromPosition.x))
|
||||||
|
std::swap(fromPosition, toPosition);
|
||||||
|
|
||||||
|
if (m_cursorPositionBegin != fromPosition || m_cursorPositionEnd != toPosition)
|
||||||
|
{
|
||||||
|
m_cursorPositionBegin = fromPosition;
|
||||||
|
m_cursorPositionEnd = toPosition;
|
||||||
|
|
||||||
|
RefreshCursor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void TextAreaWidget::SetText(const Nz::String& text)
|
inline void TextAreaWidget::SetText(const Nz::String& text)
|
||||||
{
|
{
|
||||||
m_text = text;
|
m_text = text;
|
||||||
|
|
@ -196,4 +248,14 @@ namespace Ndk
|
||||||
|
|
||||||
m_textSprite->Update(m_drawer);
|
m_textSprite->Update(m_drawer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void TextAreaWidget::Write(const Nz::String& text)
|
||||||
|
{
|
||||||
|
Write(text, GetGlyphIndex(m_cursorPositionBegin));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void TextAreaWidget::Write(const Nz::String& text, const Nz::Vector2ui& glyphPosition)
|
||||||
|
{
|
||||||
|
Write(text, GetGlyphIndex(glyphPosition));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,8 @@ namespace Ndk
|
||||||
inline void KillEntity(Entity* entity);
|
inline void KillEntity(Entity* entity);
|
||||||
inline void KillEntities(const EntityVector& list);
|
inline void KillEntities(const EntityVector& list);
|
||||||
|
|
||||||
|
inline bool IsEntityDying(const Entity* entity) const;
|
||||||
|
inline bool IsEntityDying(EntityId id) const;
|
||||||
inline bool IsEntityValid(const Entity* entity) const;
|
inline bool IsEntityValid(const Entity* entity) const;
|
||||||
inline bool IsEntityIdValid(EntityId id) const;
|
inline bool IsEntityIdValid(EntityId id) const;
|
||||||
inline bool IsProfilerEnabled() const;
|
inline bool IsProfilerEnabled() const;
|
||||||
|
|
|
||||||
|
|
@ -324,13 +324,34 @@ namespace Ndk
|
||||||
KillEntity(entity);
|
KillEntity(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether or not an entity is dying (has been killed this update)
|
||||||
|
* \return true If the entity exists and is dying
|
||||||
|
*
|
||||||
|
* \param entity Pointer to the entity
|
||||||
|
*/
|
||||||
|
inline bool World::IsEntityDying(const Entity* entity) const
|
||||||
|
{
|
||||||
|
return entity && IsEntityDying(entity->GetId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks whether or not an entity is dying (has been killed this update)
|
||||||
|
* \return true If it is the case, false if the entity is alive (and hasn't been killed yet) or if the entity id is invalid
|
||||||
|
*
|
||||||
|
* \param id Identifier of the entity
|
||||||
|
*/
|
||||||
|
inline bool World::IsEntityDying(EntityId id) const
|
||||||
|
{
|
||||||
|
return m_killedEntities.UnboundedTest(id);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Checks whether or not an entity is valid
|
* \brief Checks whether or not an entity is valid
|
||||||
* \return true If it is the case
|
* \return true If it is the case
|
||||||
*
|
*
|
||||||
* \param entity Pointer to the entity
|
* \param entity Pointer to the entity
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline bool World::IsEntityValid(const Entity* entity) const
|
inline bool World::IsEntityValid(const Entity* entity) const
|
||||||
{
|
{
|
||||||
return entity && entity->GetWorld() == this && IsEntityIdValid(entity->GetId());
|
return entity && entity->GetWorld() == this && IsEntityIdValid(entity->GetId());
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ namespace Ndk
|
||||||
m_backgroundSprite->SetColor(m_backgroundColor);
|
m_backgroundSprite->SetColor(m_backgroundColor);
|
||||||
m_backgroundSprite->SetMaterial(Nz::Material::New((m_backgroundColor.IsOpaque()) ? "Basic2D" : "Translucent2D")); //< TODO: Use a shared material instead of creating one everytime
|
m_backgroundSprite->SetMaterial(Nz::Material::New((m_backgroundColor.IsOpaque()) ? "Basic2D" : "Translucent2D")); //< TODO: Use a shared material instead of creating one everytime
|
||||||
|
|
||||||
m_backgroundEntity = CreateEntity(false);
|
m_backgroundEntity = CreateEntity();
|
||||||
m_backgroundEntity->AddComponent<GraphicsComponent>().Attach(m_backgroundSprite, -1);
|
m_backgroundEntity->AddComponent<GraphicsComponent>().Attach(m_backgroundSprite, -1);
|
||||||
m_backgroundEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_backgroundEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
|
|
||||||
|
|
@ -89,14 +89,14 @@ namespace Ndk
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_backgroundEntity->Kill();
|
m_backgroundEntity.Reset();
|
||||||
m_backgroundSprite.Reset();
|
m_backgroundSprite.Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Checks if this widget has keyboard focus
|
* \brief Checks if this widget has keyboard focus
|
||||||
* \return true if widget has keyboard focus, false otherwhise
|
* \return true if widget has keyboard focus, false otherwise
|
||||||
*/
|
*/
|
||||||
bool BaseWidget::HasFocus() const
|
bool BaseWidget::HasFocus() const
|
||||||
{
|
{
|
||||||
|
|
@ -106,6 +106,19 @@ namespace Ndk
|
||||||
return m_canvas->IsKeyboardOwner(m_canvasIndex);
|
return m_canvas->IsKeyboardOwner(m_canvasIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BaseWidget::Resize(const Nz::Vector2f& size)
|
||||||
|
{
|
||||||
|
// Adjust new size
|
||||||
|
Nz::Vector2f newSize = size;
|
||||||
|
newSize.Maximize(m_minimumSize);
|
||||||
|
newSize.Minimize(m_maximumSize);
|
||||||
|
|
||||||
|
NotifyParentResized(newSize);
|
||||||
|
m_size = newSize;
|
||||||
|
|
||||||
|
Layout();
|
||||||
|
}
|
||||||
|
|
||||||
void BaseWidget::SetBackgroundColor(const Nz::Color& color)
|
void BaseWidget::SetBackgroundColor(const Nz::Color& color)
|
||||||
{
|
{
|
||||||
m_backgroundColor = color;
|
m_backgroundColor = color;
|
||||||
|
|
@ -131,11 +144,6 @@ namespace Ndk
|
||||||
m_canvas->SetKeyboardOwner(m_canvasIndex);
|
m_canvas->SetKeyboardOwner(m_canvasIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseWidget::SetSize(const Nz::Vector2f& size)
|
|
||||||
{
|
|
||||||
SetContentSize({std::max(size.x - m_padding.left - m_padding.right, 0.f), std::max(size.y - m_padding.top - m_padding.bottom, 0.f)});
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseWidget::Show(bool show)
|
void BaseWidget::Show(bool show)
|
||||||
{
|
{
|
||||||
if (m_visible != show)
|
if (m_visible != show)
|
||||||
|
|
@ -155,7 +163,7 @@ namespace Ndk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Ndk::EntityHandle& BaseWidget::CreateEntity(bool isContentEntity)
|
const Ndk::EntityHandle& BaseWidget::CreateEntity()
|
||||||
{
|
{
|
||||||
const EntityHandle& newEntity = m_world->CreateEntity();
|
const EntityHandle& newEntity = m_world->CreateEntity();
|
||||||
newEntity->Enable(m_visible);
|
newEntity->Enable(m_visible);
|
||||||
|
|
@ -163,7 +171,6 @@ namespace Ndk
|
||||||
m_entities.emplace_back();
|
m_entities.emplace_back();
|
||||||
WidgetEntity& widgetEntity = m_entities.back();
|
WidgetEntity& widgetEntity = m_entities.back();
|
||||||
widgetEntity.handle = newEntity;
|
widgetEntity.handle = newEntity;
|
||||||
widgetEntity.isContent = isContentEntity;
|
|
||||||
|
|
||||||
return newEntity;
|
return newEntity;
|
||||||
}
|
}
|
||||||
|
|
@ -179,7 +186,7 @@ namespace Ndk
|
||||||
void BaseWidget::Layout()
|
void BaseWidget::Layout()
|
||||||
{
|
{
|
||||||
if (m_backgroundEntity)
|
if (m_backgroundEntity)
|
||||||
m_backgroundSprite->SetSize(m_contentSize.x + m_padding.left + m_padding.right, m_contentSize.y + m_padding.top + m_padding.bottom);
|
m_backgroundSprite->SetSize(m_size.x, m_size.y);
|
||||||
|
|
||||||
UpdatePositionAndSize();
|
UpdatePositionAndSize();
|
||||||
}
|
}
|
||||||
|
|
@ -282,16 +289,12 @@ namespace Ndk
|
||||||
Nz::Vector2f widgetPos = Nz::Vector2f(GetPosition());
|
Nz::Vector2f widgetPos = Nz::Vector2f(GetPosition());
|
||||||
Nz::Vector2f widgetSize = GetSize();
|
Nz::Vector2f widgetSize = GetSize();
|
||||||
|
|
||||||
Nz::Vector2f contentPos = widgetPos + GetContentOrigin();
|
|
||||||
Nz::Vector2f contentSize = GetContentSize();
|
|
||||||
|
|
||||||
Nz::Recti fullBounds(Nz::Rectf(widgetPos.x, widgetPos.y, widgetSize.x, widgetSize.y));
|
Nz::Recti fullBounds(Nz::Rectf(widgetPos.x, widgetPos.y, widgetSize.x, widgetSize.y));
|
||||||
Nz::Recti contentBounds(Nz::Rectf(contentPos.x, contentPos.y, contentSize.x, contentSize.y));
|
|
||||||
for (WidgetEntity& widgetEntity : m_entities)
|
for (WidgetEntity& widgetEntity : m_entities)
|
||||||
{
|
{
|
||||||
const Ndk::EntityHandle& entity = widgetEntity.handle;
|
const Ndk::EntityHandle& entity = widgetEntity.handle;
|
||||||
if (entity->HasComponent<GraphicsComponent>())
|
if (entity->HasComponent<GraphicsComponent>())
|
||||||
entity->GetComponent<GraphicsComponent>().SetScissorRect((widgetEntity.isContent) ? contentBounds : fullBounds);
|
entity->GetComponent<GraphicsComponent>().SetScissorRect(fullBounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,6 @@
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
void Canvas::ResizeToContent()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t Canvas::RegisterWidget(BaseWidget* widget)
|
std::size_t Canvas::RegisterWidget(BaseWidget* widget)
|
||||||
{
|
{
|
||||||
WidgetEntry box;
|
WidgetEntry box;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ namespace Ndk
|
||||||
*
|
*
|
||||||
* \remark Produces a NazaraAssert if the entity has no physics component and has no static body
|
* \remark Produces a NazaraAssert if the entity has no physics component and has no static body
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void CollisionComponent2D::SetGeom(Nz::Collider2DRef geom)
|
void CollisionComponent2D::SetGeom(Nz::Collider2DRef geom)
|
||||||
{
|
{
|
||||||
m_geom = std::move(geom);
|
m_geom = std::move(geom);
|
||||||
|
|
@ -56,7 +55,7 @@ namespace Ndk
|
||||||
|
|
||||||
NazaraAssert(entityWorld, "Entity must have world");
|
NazaraAssert(entityWorld, "Entity must have world");
|
||||||
NazaraAssert(entityWorld->HasSystem<PhysicsSystem2D>(), "World must have a physics system");
|
NazaraAssert(entityWorld->HasSystem<PhysicsSystem2D>(), "World must have a physics system");
|
||||||
Nz::PhysWorld2D& physWorld = entityWorld->GetSystem<PhysicsSystem2D>().GetWorld();
|
Nz::PhysWorld2D& physWorld = entityWorld->GetSystem<PhysicsSystem2D>().GetPhysWorld();
|
||||||
|
|
||||||
m_staticBody = std::make_unique<Nz::RigidBody2D>(&physWorld, 0.f, m_geom);
|
m_staticBody = std::make_unique<Nz::RigidBody2D>(&physWorld, 0.f, m_geom);
|
||||||
m_staticBody->SetUserdata(reinterpret_cast<void*>(static_cast<std::ptrdiff_t>(m_entity->GetId())));
|
m_staticBody->SetUserdata(reinterpret_cast<void*>(static_cast<std::ptrdiff_t>(m_entity->GetId())));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
// Copyright (C) 2017 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Development Kit"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||||
|
|
||||||
|
#include <NDK/Components/DebugComponent.hpp>
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
ComponentIndex DebugComponent::componentIndex;
|
||||||
|
}
|
||||||
|
|
@ -22,6 +22,7 @@ namespace Ndk
|
||||||
*/
|
*/
|
||||||
void GraphicsComponent::AddToRenderQueue(Nz::AbstractRenderQueue* renderQueue) const
|
void GraphicsComponent::AddToRenderQueue(Nz::AbstractRenderQueue* renderQueue) const
|
||||||
{
|
{
|
||||||
|
EnsureBoundingVolumesUpdate();
|
||||||
EnsureTransformMatrixUpdate();
|
EnsureTransformMatrixUpdate();
|
||||||
|
|
||||||
RenderSystem& renderSystem = m_entity->GetWorld()->GetSystem<RenderSystem>();
|
RenderSystem& renderSystem = m_entity->GetWorld()->GetSystem<RenderSystem>();
|
||||||
|
|
@ -30,7 +31,6 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
if (!object.dataUpdated)
|
if (!object.dataUpdated)
|
||||||
{
|
{
|
||||||
object.data.transformMatrix = Nz::Matrix4f::ConcatenateAffine(renderSystem.GetCoordinateSystemMatrix(), Nz::Matrix4f::ConcatenateAffine(object.data.localMatrix, m_transformMatrix));
|
|
||||||
object.renderable->UpdateData(&object.data);
|
object.renderable->UpdateData(&object.data);
|
||||||
object.dataUpdated = true;
|
object.dataUpdated = true;
|
||||||
}
|
}
|
||||||
|
|
@ -39,6 +39,34 @@ namespace Ndk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Adds the renderable elements to the render queue if their bounding volume intersects with the frustum
|
||||||
|
*
|
||||||
|
* \param frustum Queue to be added
|
||||||
|
* \param renderQueue Queue to be added
|
||||||
|
*/
|
||||||
|
void GraphicsComponent::AddToRenderQueueByCulling(const Nz::Frustumf& frustum, Nz::AbstractRenderQueue* renderQueue) const
|
||||||
|
{
|
||||||
|
EnsureBoundingVolumesUpdate();
|
||||||
|
EnsureTransformMatrixUpdate();
|
||||||
|
|
||||||
|
RenderSystem& renderSystem = m_entity->GetWorld()->GetSystem<RenderSystem>();
|
||||||
|
|
||||||
|
for (const Renderable& object : m_renderables)
|
||||||
|
{
|
||||||
|
if (frustum.Contains(object.boundingVolume))
|
||||||
|
{
|
||||||
|
if (!object.dataUpdated)
|
||||||
|
{
|
||||||
|
object.renderable->UpdateData(&object.data);
|
||||||
|
object.dataUpdated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
object.renderable->AddToRenderQueue(renderQueue, object.data, m_scissorRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Attaches a renderable to the entity with a specific matrix
|
* \brief Attaches a renderable to the entity with a specific matrix
|
||||||
*
|
*
|
||||||
|
|
@ -60,12 +88,13 @@ namespace Ndk
|
||||||
for (std::size_t i = 0; i < materialCount; ++i)
|
for (std::size_t i = 0; i < materialCount; ++i)
|
||||||
RegisterMaterial(entry.renderable->GetMaterial(i));
|
RegisterMaterial(entry.renderable->GetMaterial(i));
|
||||||
|
|
||||||
InvalidateBoundingVolume();
|
InvalidateAABB();
|
||||||
|
ForceCullingInvalidation();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsComponent::ConnectInstancedRenderableSignals(Renderable& entry)
|
void GraphicsComponent::ConnectInstancedRenderableSignals(Renderable& entry)
|
||||||
{
|
{
|
||||||
entry.renderableBoundingVolumeInvalidationSlot.Connect(entry.renderable->OnInstancedRenderableInvalidateBoundingVolume, [this](const Nz::InstancedRenderable*) { InvalidateBoundingVolume(); });
|
entry.renderableBoundingVolumeInvalidationSlot.Connect(entry.renderable->OnInstancedRenderableInvalidateBoundingVolume, [this](const Nz::InstancedRenderable*) { InvalidateAABB(); });
|
||||||
entry.renderableDataInvalidationSlot.Connect(entry.renderable->OnInstancedRenderableInvalidateData, std::bind(&GraphicsComponent::InvalidateRenderableData, this, std::placeholders::_1, std::placeholders::_2, m_renderables.size() - 1));
|
entry.renderableDataInvalidationSlot.Connect(entry.renderable->OnInstancedRenderableInvalidateData, std::bind(&GraphicsComponent::InvalidateRenderableData, this, std::placeholders::_1, std::placeholders::_2, m_renderables.size() - 1));
|
||||||
entry.renderableMaterialInvalidationSlot.Connect(entry.renderable->OnInstancedRenderableInvalidateMaterial, this, &GraphicsComponent::InvalidateRenderableMaterial);
|
entry.renderableMaterialInvalidationSlot.Connect(entry.renderable->OnInstancedRenderableInvalidateMaterial, this, &GraphicsComponent::InvalidateRenderableMaterial);
|
||||||
entry.renderableReleaseSlot.Connect(entry.renderable->OnInstancedRenderableRelease, this, &GraphicsComponent::Detach);
|
entry.renderableReleaseSlot.Connect(entry.renderable->OnInstancedRenderableRelease, this, &GraphicsComponent::Detach);
|
||||||
|
|
@ -82,8 +111,7 @@ namespace Ndk
|
||||||
r.dataUpdated = false;
|
r.dataUpdated = false;
|
||||||
r.renderable->InvalidateData(&r.data, flags);
|
r.renderable->InvalidateData(&r.data, flags);
|
||||||
|
|
||||||
for (VolumeCullingEntry& entry : m_volumeCullingEntries)
|
ForceCullingInvalidation();
|
||||||
entry.listEntry.ForceInvalidation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsComponent::InvalidateRenderableMaterial(const Nz::InstancedRenderable* renderable, std::size_t skinIndex, std::size_t matIndex, const Nz::MaterialRef& newMat)
|
void GraphicsComponent::InvalidateRenderableMaterial(const Nz::InstancedRenderable* renderable, std::size_t skinIndex, std::size_t matIndex, const Nz::MaterialRef& newMat)
|
||||||
|
|
@ -234,11 +262,10 @@ namespace Ndk
|
||||||
NazaraUnused(node);
|
NazaraUnused(node);
|
||||||
|
|
||||||
// Our view matrix depends on NodeComponent position/rotation
|
// Our view matrix depends on NodeComponent position/rotation
|
||||||
InvalidateBoundingVolume();
|
InvalidateAABB();
|
||||||
InvalidateTransformMatrix();
|
InvalidateTransformMatrix();
|
||||||
|
|
||||||
for (VolumeCullingEntry& entry : m_volumeCullingEntries)
|
ForceCullingInvalidation(); //< Force invalidation on movement for now (FIXME)
|
||||||
entry.listEntry.ForceInvalidation(); //< Force invalidation on movement
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsComponent::UnregisterMaterial(Nz::Material* material)
|
void GraphicsComponent::UnregisterMaterial(Nz::Material* material)
|
||||||
|
|
@ -263,35 +290,32 @@ namespace Ndk
|
||||||
* \brief Updates the bounding volume
|
* \brief Updates the bounding volume
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void GraphicsComponent::UpdateBoundingVolume() const
|
void GraphicsComponent::UpdateBoundingVolumes() const
|
||||||
{
|
{
|
||||||
EnsureTransformMatrixUpdate();
|
EnsureTransformMatrixUpdate();
|
||||||
|
|
||||||
m_boundingVolume.MakeNull();
|
|
||||||
for (const Renderable& r : m_renderables)
|
|
||||||
{
|
|
||||||
Nz::BoundingVolumef boundingVolume = r.renderable->GetBoundingVolume();
|
|
||||||
|
|
||||||
// Adjust renderable bounding volume by local matrix
|
|
||||||
if (boundingVolume.IsFinite())
|
|
||||||
{
|
|
||||||
Nz::Boxf localBox = boundingVolume.obb.localBox;
|
|
||||||
Nz::Vector3f newPos = r.data.localMatrix * localBox.GetPosition();
|
|
||||||
Nz::Vector3f newLengths = r.data.localMatrix * localBox.GetLengths();
|
|
||||||
|
|
||||||
boundingVolume.Set(Nz::Boxf(newPos.x, newPos.y, newPos.z, newLengths.x, newLengths.y, newLengths.z));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_boundingVolume.ExtendTo(boundingVolume);
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderSystem& renderSystem = m_entity->GetWorld()->GetSystem<RenderSystem>();
|
RenderSystem& renderSystem = m_entity->GetWorld()->GetSystem<RenderSystem>();
|
||||||
|
|
||||||
m_boundingVolume.Update(Nz::Matrix4f::ConcatenateAffine(renderSystem.GetCoordinateSystemMatrix(), m_transformMatrix));
|
m_aabb.Set(-1.f, -1.f, -1.f);
|
||||||
m_boundingVolumeUpdated = true;
|
for (const Renderable& r : m_renderables)
|
||||||
|
{
|
||||||
|
r.boundingVolume = r.renderable->GetBoundingVolume();
|
||||||
|
r.data.transformMatrix = Nz::Matrix4f::ConcatenateAffine(renderSystem.GetCoordinateSystemMatrix(), Nz::Matrix4f::ConcatenateAffine(r.data.localMatrix, m_transformMatrix));
|
||||||
|
if (r.boundingVolume.IsFinite())
|
||||||
|
{
|
||||||
|
r.boundingVolume.Update(r.data.transformMatrix);
|
||||||
|
|
||||||
for (VolumeCullingEntry& entry : m_volumeCullingEntries)
|
if (m_aabb.IsValid())
|
||||||
entry.listEntry.UpdateVolume(m_boundingVolume);
|
m_aabb.ExtendTo(r.boundingVolume.aabb);
|
||||||
|
else
|
||||||
|
m_aabb.Set(r.boundingVolume.aabb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_boundingVolumesUpdated = true;
|
||||||
|
|
||||||
|
for (CullingBoxEntry& entry : m_cullingBoxEntries)
|
||||||
|
entry.listEntry.UpdateBox(m_aabb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ namespace Ndk
|
||||||
World* entityWorld = m_entity->GetWorld();
|
World* entityWorld = m_entity->GetWorld();
|
||||||
NazaraAssert(entityWorld->HasSystem<PhysicsSystem2D>(), "World must have a 2D physics system");
|
NazaraAssert(entityWorld->HasSystem<PhysicsSystem2D>(), "World must have a 2D physics system");
|
||||||
|
|
||||||
Nz::PhysWorld2D& world = entityWorld->GetSystem<PhysicsSystem2D>().GetWorld();
|
Nz::PhysWorld2D& world = entityWorld->GetSystem<PhysicsSystem2D>().GetPhysWorld();
|
||||||
|
|
||||||
Nz::Collider2DRef geom;
|
Nz::Collider2DRef geom;
|
||||||
if (m_entity->HasComponent<CollisionComponent2D>())
|
if (m_entity->HasComponent<CollisionComponent2D>())
|
||||||
|
|
|
||||||
|
|
@ -14,26 +14,8 @@ namespace Ndk
|
||||||
* \brief NDK class that represents an entity in a world
|
* \brief NDK class that represents an entity in a world
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
// Must exists in .cpp file because of BaseComponent unique_ptr
|
||||||
* \brief Constructs a Entity object by move semantic
|
Entity::Entity(Entity&&) noexcept = default;
|
||||||
*
|
|
||||||
* \param entity Entity to move into this
|
|
||||||
*/
|
|
||||||
|
|
||||||
Entity::Entity(Entity&& entity) :
|
|
||||||
HandledObject(std::move(entity)),
|
|
||||||
m_components(std::move(entity.m_components)),
|
|
||||||
m_containedInLists(std::move(entity.m_containedInLists)),
|
|
||||||
m_componentBits(std::move(entity.m_componentBits)),
|
|
||||||
m_removedComponentBits(std::move(entity.m_removedComponentBits)),
|
|
||||||
m_systemBits(std::move(entity.m_systemBits)),
|
|
||||||
m_id(entity.m_id),
|
|
||||||
m_world(entity.m_world),
|
|
||||||
m_enabled(entity.m_enabled),
|
|
||||||
m_valid(entity.m_valid)
|
|
||||||
{
|
|
||||||
entity.m_world = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Constructs a Entity object linked to a world and with an id
|
* \brief Constructs a Entity object linked to a world and with an id
|
||||||
|
|
@ -41,7 +23,6 @@ namespace Ndk
|
||||||
* \param world World in which the entity interact
|
* \param world World in which the entity interact
|
||||||
* \param id Identifier of the entity
|
* \param id Identifier of the entity
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Entity::Entity(World* world, EntityId id) :
|
Entity::Entity(World* world, EntityId id) :
|
||||||
m_id(id),
|
m_id(id),
|
||||||
m_world(world)
|
m_world(world)
|
||||||
|
|
@ -53,7 +34,6 @@ namespace Ndk
|
||||||
*
|
*
|
||||||
* \see Destroy
|
* \see Destroy
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Entity::~Entity()
|
Entity::~Entity()
|
||||||
{
|
{
|
||||||
if (m_world && m_valid)
|
if (m_world && m_valid)
|
||||||
|
|
@ -153,13 +133,22 @@ namespace Ndk
|
||||||
/*!
|
/*!
|
||||||
* \brief Invalidates the entity
|
* \brief Invalidates the entity
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Entity::Invalidate()
|
void Entity::Invalidate()
|
||||||
{
|
{
|
||||||
// We alert everyone that we have been updated
|
// We alert everyone that we have been updated
|
||||||
m_world->Invalidate(m_id);
|
m_world->Invalidate(m_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Checks if the entity has been killed this update
|
||||||
|
* \return True if the entity is currently dying and will be dead at next world refresh
|
||||||
|
*/
|
||||||
|
bool Entity::IsDying() const
|
||||||
|
{
|
||||||
|
return m_world->IsEntityDying(m_id);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Creates the entity
|
* \brief Creates the entity
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ namespace Ndk
|
||||||
|
|
||||||
music.BindMethod("IsLooping", &Nz::Music::IsLooping);
|
music.BindMethod("IsLooping", &Nz::Music::IsLooping);
|
||||||
|
|
||||||
music.BindMethod("OpenFromFile", &Nz::Music::OpenFromFile, Nz::MusicParams());
|
music.BindMethod("OpenFromFile", &Nz::Music::OpenFromFile, Nz::SoundStreamParams());
|
||||||
|
|
||||||
music.BindMethod("Pause", &Nz::Music::Pause);
|
music.BindMethod("Pause", &Nz::Music::Pause);
|
||||||
music.BindMethod("Play", &Nz::Music::Play);
|
music.BindMethod("Play", &Nz::Music::Play);
|
||||||
|
|
@ -138,7 +138,7 @@ namespace Ndk
|
||||||
|
|
||||||
soundBuffer.BindMethod("IsValid", &Nz::SoundBuffer::IsValid);
|
soundBuffer.BindMethod("IsValid", &Nz::SoundBuffer::IsValid);
|
||||||
|
|
||||||
soundBuffer.BindMethod("LoadFromFile", &Nz::SoundBuffer::LoadFromFile, Nz::SoundBufferParams());
|
soundBuffer.BindStaticMethod("LoadFromFile", &Nz::SoundBuffer::LoadFromFile, Nz::SoundBufferParams());
|
||||||
|
|
||||||
soundBuffer.BindStaticMethod("IsFormatSupported", &Nz::SoundBuffer::IsFormatSupported);
|
soundBuffer.BindStaticMethod("IsFormatSupported", &Nz::SoundBuffer::IsFormatSupported);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -181,8 +181,6 @@ namespace Ndk
|
||||||
material.BindMethod("IsShadowCastingEnabled", &Nz::Material::IsShadowCastingEnabled);
|
material.BindMethod("IsShadowCastingEnabled", &Nz::Material::IsShadowCastingEnabled);
|
||||||
material.BindMethod("IsShadowReceiveEnabled", &Nz::Material::IsShadowReceiveEnabled);
|
material.BindMethod("IsShadowReceiveEnabled", &Nz::Material::IsShadowReceiveEnabled);
|
||||||
|
|
||||||
material.BindMethod("LoadFromFile", &Nz::Material::LoadFromFile, Nz::MaterialParams());
|
|
||||||
|
|
||||||
material.BindMethod("Reset", &Nz::Material::Reset);
|
material.BindMethod("Reset", &Nz::Material::Reset);
|
||||||
|
|
||||||
material.BindMethod("SetAlphaThreshold", &Nz::Material::SetAlphaThreshold);
|
material.BindMethod("SetAlphaThreshold", &Nz::Material::SetAlphaThreshold);
|
||||||
|
|
@ -205,6 +203,7 @@ namespace Ndk
|
||||||
material.BindMethod("SetSrcBlend", &Nz::Material::SetSrcBlend);
|
material.BindMethod("SetSrcBlend", &Nz::Material::SetSrcBlend);
|
||||||
|
|
||||||
material.BindStaticMethod("GetDefault", &Nz::Material::GetDefault);
|
material.BindStaticMethod("GetDefault", &Nz::Material::GetDefault);
|
||||||
|
material.BindStaticMethod("LoadFromFile", &Nz::Material::LoadFromFile, Nz::MaterialParams());
|
||||||
|
|
||||||
material.BindMethod("SetAlphaMap", [] (Nz::LuaState& lua, Nz::MaterialRef& instance, std::size_t /*argumentCount*/) -> int
|
material.BindMethod("SetAlphaMap", [] (Nz::LuaState& lua, Nz::MaterialRef& instance, std::size_t /*argumentCount*/) -> int
|
||||||
{
|
{
|
||||||
|
|
@ -308,8 +307,6 @@ namespace Ndk
|
||||||
//modelClass.SetMethod("GetMesh", &Nz::Model::GetMesh);
|
//modelClass.SetMethod("GetMesh", &Nz::Model::GetMesh);
|
||||||
|
|
||||||
model.BindMethod("IsAnimated", &Nz::Model::IsAnimated);
|
model.BindMethod("IsAnimated", &Nz::Model::IsAnimated);
|
||||||
model.BindMethod("LoadFromFile", &Nz::Model::LoadFromFile, Nz::ModelParameters());
|
|
||||||
|
|
||||||
|
|
||||||
model.BindMethod("SetMaterial", [] (Nz::LuaState& lua, Nz::Model* instance, std::size_t argumentCount) -> int
|
model.BindMethod("SetMaterial", [] (Nz::LuaState& lua, Nz::Model* instance, std::size_t argumentCount) -> int
|
||||||
{
|
{
|
||||||
|
|
@ -371,6 +368,8 @@ namespace Ndk
|
||||||
|
|
||||||
//modelClass.SetMethod("SetMesh", &Nz::Model::SetMesh);
|
//modelClass.SetMethod("SetMesh", &Nz::Model::SetMesh);
|
||||||
//modelClass.SetMethod("SetSequence", &Nz::Model::SetSequence);
|
//modelClass.SetMethod("SetSequence", &Nz::Model::SetSequence);
|
||||||
|
|
||||||
|
model.BindStaticMethod("LoadFromFile", &Nz::Model::LoadFromFile, Nz::ModelParameters());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************** Nz::Sprite ***********************************/
|
/*********************************** Nz::Sprite ***********************************/
|
||||||
|
|
|
||||||
|
|
@ -266,14 +266,15 @@ namespace Ndk
|
||||||
state.SetGlobal("ResolveError");
|
state.SetGlobal("ResolveError");
|
||||||
|
|
||||||
// Nz::SocketError
|
// Nz::SocketError
|
||||||
static_assert(Nz::SocketError_Max + 1 == 15, "Nz::ResolveError has been updated but change was not reflected to Lua binding");
|
static_assert(Nz::SocketError_Max + 1 == 16, "Nz::SocketError has been updated but change was not reflected to Lua binding");
|
||||||
state.PushTable(0, 15);
|
state.PushTable(0, 16);
|
||||||
{
|
{
|
||||||
state.PushField("AddressNotAvailable", Nz::SocketError_AddressNotAvailable);
|
state.PushField("AddressNotAvailable", Nz::SocketError_AddressNotAvailable);
|
||||||
state.PushField("ConnectionClosed", Nz::SocketError_ConnectionClosed);
|
state.PushField("ConnectionClosed", Nz::SocketError_ConnectionClosed);
|
||||||
state.PushField("ConnectionRefused", Nz::SocketError_ConnectionRefused);
|
state.PushField("ConnectionRefused", Nz::SocketError_ConnectionRefused);
|
||||||
state.PushField("DatagramSize", Nz::SocketError_DatagramSize);
|
state.PushField("DatagramSize", Nz::SocketError_DatagramSize);
|
||||||
state.PushField("Internal", Nz::SocketError_Internal);
|
state.PushField("Internal", Nz::SocketError_Internal);
|
||||||
|
state.PushField("Interrupted", Nz::SocketError_Interrupted);
|
||||||
state.PushField("Packet", Nz::SocketError_Packet);
|
state.PushField("Packet", Nz::SocketError_Packet);
|
||||||
state.PushField("NetworkError", Nz::SocketError_NetworkError);
|
state.PushField("NetworkError", Nz::SocketError_NetworkError);
|
||||||
state.PushField("NoError", Nz::SocketError_NoError);
|
state.PushField("NoError", Nz::SocketError_NoError);
|
||||||
|
|
|
||||||
|
|
@ -44,21 +44,6 @@ namespace Ndk
|
||||||
texture.BindMethod("InvalidateMipmaps", &Nz::Texture::InvalidateMipmaps);
|
texture.BindMethod("InvalidateMipmaps", &Nz::Texture::InvalidateMipmaps);
|
||||||
texture.BindMethod("IsValid", &Nz::Texture::IsValid);
|
texture.BindMethod("IsValid", &Nz::Texture::IsValid);
|
||||||
|
|
||||||
texture.BindMethod("LoadFromFile", &Nz::Texture::LoadFromFile, true, Nz::ImageParams());
|
|
||||||
//bool LoadFromImage(const Image& image, bool generateMipmaps = true);
|
|
||||||
//bool LoadFromMemory(const void* data, std::size_t size, const ImageParams& params = ImageParams(), bool generateMipmaps = true);
|
|
||||||
//bool LoadFromStream(Stream& stream, const ImageParams& params = ImageParams(), bool generateMipmaps = true);
|
|
||||||
|
|
||||||
texture.BindMethod("LoadArrayFromFile", &Nz::Texture::LoadArrayFromFile, Nz::Vector2ui(2, 2), true, Nz::ImageParams());
|
|
||||||
//bool LoadArrayFromImage(const Image& image, bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2));
|
|
||||||
//bool LoadArrayFromMemory(const void* data, std::size_t size, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2));
|
|
||||||
//bool LoadArrayFromStream(Stream& stream, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2));
|
|
||||||
|
|
||||||
//bool LoadCubemapFromFile(const String& filePath, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const CubemapParams& cubemapParams = CubemapParams());
|
|
||||||
//bool LoadCubemapFromImage(const Image& image, bool generateMipmaps = true, const CubemapParams& params = CubemapParams());
|
|
||||||
//bool LoadCubemapFromMemory(const void* data, std::size_t size, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const CubemapParams& cubemapParams = CubemapParams());
|
|
||||||
//bool LoadCubemapFromStream(Stream& stream, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const CubemapParams& cubemapParams = CubemapParams());
|
|
||||||
|
|
||||||
texture.BindMethod("LoadFaceFromFile", &Nz::Texture::LoadFaceFromFile, Nz::ImageParams());
|
texture.BindMethod("LoadFaceFromFile", &Nz::Texture::LoadFaceFromFile, Nz::ImageParams());
|
||||||
//bool LoadFaceFromMemory(CubemapFace face, const void* data, std::size_t size, const ImageParams& params = ImageParams());
|
//bool LoadFaceFromMemory(CubemapFace face, const void* data, std::size_t size, const ImageParams& params = ImageParams());
|
||||||
//bool LoadFaceFromStream(CubemapFace face, Stream& stream, const ImageParams& params = ImageParams());
|
//bool LoadFaceFromStream(CubemapFace face, Stream& stream, const ImageParams& params = ImageParams());
|
||||||
|
|
@ -71,6 +56,21 @@ namespace Ndk
|
||||||
texture.BindStaticMethod("IsFormatSupported", &Nz::Texture::IsFormatSupported);
|
texture.BindStaticMethod("IsFormatSupported", &Nz::Texture::IsFormatSupported);
|
||||||
texture.BindStaticMethod("IsMipmappingSupported", &Nz::Texture::IsMipmappingSupported);
|
texture.BindStaticMethod("IsMipmappingSupported", &Nz::Texture::IsMipmappingSupported);
|
||||||
texture.BindStaticMethod("IsTypeSupported", &Nz::Texture::IsTypeSupported);
|
texture.BindStaticMethod("IsTypeSupported", &Nz::Texture::IsTypeSupported);
|
||||||
|
|
||||||
|
texture.BindStaticMethod("LoadFromFile", &Nz::Texture::LoadFromFile, true, Nz::ImageParams());
|
||||||
|
//TextureRef LoadFromImage(const Image& image, bool generateMipmaps = true);
|
||||||
|
//TextureRef LoadFromMemory(const void* data, std::size_t size, const ImageParams& params = ImageParams(), bool generateMipmaps = true);
|
||||||
|
//TextureRef LoadFromStream(Stream& stream, const ImageParams& params = ImageParams(), bool generateMipmaps = true);
|
||||||
|
|
||||||
|
texture.BindStaticMethod("LoadArrayFromFile", &Nz::Texture::LoadArrayFromFile, Nz::Vector2ui(2, 2), true, Nz::ImageParams());
|
||||||
|
//TextureRef LoadArrayFromImage(const Image& image, bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2));
|
||||||
|
//TextureRef LoadArrayFromMemory(const void* data, std::size_t size, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2));
|
||||||
|
//TextureRef LoadArrayFromStream(Stream& stream, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2));
|
||||||
|
|
||||||
|
//TextureRef LoadCubemapFromFile(const String& filePath, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const CubemapParams& cubemapParams = CubemapParams());
|
||||||
|
//TextureRef LoadCubemapFromImage(const Image& image, bool generateMipmaps = true, const CubemapParams& params = CubemapParams());
|
||||||
|
//TextureRef LoadCubemapFromMemory(const void* data, std::size_t size, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const CubemapParams& cubemapParams = CubemapParams());
|
||||||
|
//TextureRef LoadCubemapFromStream(Stream& stream, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const CubemapParams& cubemapParams = CubemapParams());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************** Nz::TextureLibrary ***********************************/
|
/*********************************** Nz::TextureLibrary ***********************************/
|
||||||
|
|
|
||||||
|
|
@ -148,8 +148,6 @@ namespace Ndk
|
||||||
|
|
||||||
font.BindMethod("Precache", (bool(Nz::Font::*)(unsigned int, Nz::UInt32, const Nz::String&) const) &Nz::Font::Precache);
|
font.BindMethod("Precache", (bool(Nz::Font::*)(unsigned int, Nz::UInt32, const Nz::String&) const) &Nz::Font::Precache);
|
||||||
|
|
||||||
font.BindMethod("OpenFromFile", &Nz::Font::OpenFromFile, Nz::FontParams());
|
|
||||||
|
|
||||||
font.BindMethod("SetGlyphBorder", &Nz::Font::SetGlyphBorder);
|
font.BindMethod("SetGlyphBorder", &Nz::Font::SetGlyphBorder);
|
||||||
font.BindMethod("SetMinimumStepSize", &Nz::Font::SetMinimumStepSize);
|
font.BindMethod("SetMinimumStepSize", &Nz::Font::SetMinimumStepSize);
|
||||||
|
|
||||||
|
|
@ -157,6 +155,8 @@ namespace Ndk
|
||||||
font.BindStaticMethod("GetDefaultGlyphBorder", &Nz::Font::GetDefaultGlyphBorder);
|
font.BindStaticMethod("GetDefaultGlyphBorder", &Nz::Font::GetDefaultGlyphBorder);
|
||||||
font.BindStaticMethod("GetDefaultMinimumStepSize", &Nz::Font::GetDefaultMinimumStepSize);
|
font.BindStaticMethod("GetDefaultMinimumStepSize", &Nz::Font::GetDefaultMinimumStepSize);
|
||||||
|
|
||||||
|
font.BindStaticMethod("OpenFromFile", &Nz::Font::OpenFromFile, Nz::FontParams());
|
||||||
|
|
||||||
font.BindStaticMethod("SetDefaultGlyphBorder", &Nz::Font::SetDefaultGlyphBorder);
|
font.BindStaticMethod("SetDefaultGlyphBorder", &Nz::Font::SetDefaultGlyphBorder);
|
||||||
font.BindStaticMethod("SetDefaultMinimumStepSize", &Nz::Font::SetDefaultMinimumStepSize);
|
font.BindStaticMethod("SetDefaultMinimumStepSize", &Nz::Font::SetDefaultMinimumStepSize);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,11 +28,13 @@
|
||||||
|
|
||||||
#ifndef NDK_SERVER
|
#ifndef NDK_SERVER
|
||||||
#include <NDK/Components/CameraComponent.hpp>
|
#include <NDK/Components/CameraComponent.hpp>
|
||||||
|
#include <NDK/Components/DebugComponent.hpp>
|
||||||
#include <NDK/Components/LightComponent.hpp>
|
#include <NDK/Components/LightComponent.hpp>
|
||||||
#include <NDK/Components/ListenerComponent.hpp>
|
#include <NDK/Components/ListenerComponent.hpp>
|
||||||
#include <NDK/Components/GraphicsComponent.hpp>
|
#include <NDK/Components/GraphicsComponent.hpp>
|
||||||
#include <NDK/Components/ParticleEmitterComponent.hpp>
|
#include <NDK/Components/ParticleEmitterComponent.hpp>
|
||||||
#include <NDK/Components/ParticleGroupComponent.hpp>
|
#include <NDK/Components/ParticleGroupComponent.hpp>
|
||||||
|
#include <NDK/Systems/DebugSystem.hpp>
|
||||||
#include <NDK/Systems/ParticleSystem.hpp>
|
#include <NDK/Systems/ParticleSystem.hpp>
|
||||||
#include <NDK/Systems/ListenerSystem.hpp>
|
#include <NDK/Systems/ListenerSystem.hpp>
|
||||||
#include <NDK/Systems/RenderSystem.hpp>
|
#include <NDK/Systems/RenderSystem.hpp>
|
||||||
|
|
@ -95,6 +97,7 @@ namespace Ndk
|
||||||
#ifndef NDK_SERVER
|
#ifndef NDK_SERVER
|
||||||
// Client components
|
// Client components
|
||||||
InitializeComponent<CameraComponent>("NdkCam");
|
InitializeComponent<CameraComponent>("NdkCam");
|
||||||
|
InitializeComponent<DebugComponent>("NdkDebug");
|
||||||
InitializeComponent<LightComponent>("NdkLight");
|
InitializeComponent<LightComponent>("NdkLight");
|
||||||
InitializeComponent<ListenerComponent>("NdkList");
|
InitializeComponent<ListenerComponent>("NdkList");
|
||||||
InitializeComponent<GraphicsComponent>("NdkGfx");
|
InitializeComponent<GraphicsComponent>("NdkGfx");
|
||||||
|
|
@ -113,6 +116,7 @@ namespace Ndk
|
||||||
|
|
||||||
#ifndef NDK_SERVER
|
#ifndef NDK_SERVER
|
||||||
// Client systems
|
// Client systems
|
||||||
|
InitializeSystem<DebugSystem>();
|
||||||
InitializeSystem<ListenerSystem>();
|
InitializeSystem<ListenerSystem>();
|
||||||
InitializeSystem<ParticleSystem>();
|
InitializeSystem<ParticleSystem>();
|
||||||
InitializeSystem<RenderSystem>();
|
InitializeSystem<RenderSystem>();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,433 @@
|
||||||
|
// Copyright (C) 2017 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Development Kit"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||||
|
|
||||||
|
#include <NDK/Systems/DebugSystem.hpp>
|
||||||
|
#include <Nazara/Core/Primitive.hpp>
|
||||||
|
#include <Nazara/Graphics/Model.hpp>
|
||||||
|
#include <Nazara/Utility/IndexIterator.hpp>
|
||||||
|
#include <Nazara/Utility/Mesh.hpp>
|
||||||
|
#include <Nazara/Utility/StaticMesh.hpp>
|
||||||
|
#include <NDK/Components/CollisionComponent3D.hpp>
|
||||||
|
#include <NDK/Components/DebugComponent.hpp>
|
||||||
|
#include <NDK/Components/GraphicsComponent.hpp>
|
||||||
|
#include <NDK/Components/NodeComponent.hpp>
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class DebugRenderable : public Nz::InstancedRenderable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DebugRenderable(Ndk::Entity* owner, Nz::IndexBufferRef indexBuffer, Nz::VertexBufferRef vertexBuffer) :
|
||||||
|
m_entityOwner(owner),
|
||||||
|
m_indexBuffer(std::move(indexBuffer)),
|
||||||
|
m_vertexBuffer(std::move(vertexBuffer))
|
||||||
|
{
|
||||||
|
ResetMaterials(1);
|
||||||
|
|
||||||
|
m_meshData.indexBuffer = m_indexBuffer;
|
||||||
|
m_meshData.primitiveMode = Nz::PrimitiveMode_LineList;
|
||||||
|
m_meshData.vertexBuffer = m_vertexBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateBoundingVolume(InstanceData* /*instanceData*/) const override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MakeBoundingVolume() const override
|
||||||
|
{
|
||||||
|
// We generate an infinite bounding volume so that we're always considered for rendering when culling does occurs
|
||||||
|
// (bounding volume culling happens only if GraphicsComponent AABB partially fail)
|
||||||
|
m_boundingVolume.MakeInfinite();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Ndk::EntityHandle m_entityOwner;
|
||||||
|
Nz::IndexBufferRef m_indexBuffer;
|
||||||
|
Nz::MeshData m_meshData;
|
||||||
|
Nz::VertexBufferRef m_vertexBuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AABBDebugRenderable : public DebugRenderable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AABBDebugRenderable(Ndk::Entity* owner, Nz::MaterialRef globalMaterial, Nz::MaterialRef localMaterial, Nz::IndexBufferRef indexBuffer, Nz::VertexBufferRef vertexBuffer) :
|
||||||
|
DebugRenderable(owner, std::move(indexBuffer), std::move(vertexBuffer)),
|
||||||
|
m_globalMaterial(std::move(globalMaterial)),
|
||||||
|
m_localMaterial(std::move(localMaterial))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddToRenderQueue(Nz::AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Nz::Recti& scissorRect) const override
|
||||||
|
{
|
||||||
|
NazaraAssert(m_entityOwner, "DebugRenderable has no owner");
|
||||||
|
|
||||||
|
const DebugComponent& entityDebug = m_entityOwner->GetComponent<DebugComponent>();
|
||||||
|
const GraphicsComponent& entityGfx = m_entityOwner->GetComponent<GraphicsComponent>();
|
||||||
|
|
||||||
|
auto DrawBox = [&](const Nz::Boxf& box, const Nz::MaterialRef& mat)
|
||||||
|
{
|
||||||
|
Nz::Matrix4f transformMatrix = Nz::Matrix4f::Identity();
|
||||||
|
transformMatrix.SetScale(box.GetLengths());
|
||||||
|
transformMatrix.SetTranslation(box.GetCenter());
|
||||||
|
|
||||||
|
renderQueue->AddMesh(0, mat, m_meshData, Nz::Boxf::Zero(), transformMatrix, scissorRect);
|
||||||
|
};
|
||||||
|
|
||||||
|
DrawBox(entityGfx.GetAABB(), m_globalMaterial);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < entityGfx.GetAttachedRenderableCount(); ++i)
|
||||||
|
{
|
||||||
|
const Nz::BoundingVolumef& boundingVolume = entityGfx.GetBoundingVolume(i);
|
||||||
|
if (boundingVolume.IsFinite())
|
||||||
|
DrawBox(boundingVolume.aabb, m_localMaterial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<InstancedRenderable> Clone() const override
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Nz::MaterialRef m_globalMaterial;
|
||||||
|
Nz::MaterialRef m_localMaterial;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OBBDebugRenderable : public DebugRenderable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OBBDebugRenderable(Ndk::Entity* owner, Nz::MaterialRef material, Nz::IndexBufferRef indexBuffer, Nz::VertexBufferRef vertexBuffer) :
|
||||||
|
DebugRenderable(owner, std::move(indexBuffer), std::move(vertexBuffer)),
|
||||||
|
m_material(std::move(material))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddToRenderQueue(Nz::AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Nz::Recti& scissorRect) const override
|
||||||
|
{
|
||||||
|
NazaraAssert(m_entityOwner, "DebugRenderable has no owner");
|
||||||
|
|
||||||
|
const DebugComponent& entityDebug = m_entityOwner->GetComponent<DebugComponent>();
|
||||||
|
const GraphicsComponent& entityGfx = m_entityOwner->GetComponent<GraphicsComponent>();
|
||||||
|
|
||||||
|
auto DrawBox = [&](const Nz::Boxf& box, const Nz::Matrix4f& transformMatrix)
|
||||||
|
{
|
||||||
|
Nz::Matrix4f boxMatrix = Nz::Matrix4f::Identity();
|
||||||
|
boxMatrix.SetScale(box.GetLengths());
|
||||||
|
boxMatrix.SetTranslation(box.GetCenter());
|
||||||
|
boxMatrix.ConcatenateAffine(transformMatrix);
|
||||||
|
|
||||||
|
renderQueue->AddMesh(0, m_material, m_meshData, Nz::Boxf::Zero(), boxMatrix, scissorRect);
|
||||||
|
};
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < entityGfx.GetAttachedRenderableCount(); ++i)
|
||||||
|
{
|
||||||
|
const Nz::BoundingVolumef& boundingVolume = entityGfx.GetBoundingVolume(i);
|
||||||
|
if (boundingVolume.IsFinite())
|
||||||
|
DrawBox(boundingVolume.obb.localBox, entityGfx.GetTransformMatrix(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<InstancedRenderable> Clone() const override
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Nz::MaterialRef m_material;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \ingroup NDK
|
||||||
|
* \class Ndk::DebugSystem
|
||||||
|
* \brief NDK class that represents the debug system
|
||||||
|
*
|
||||||
|
* \remark This system is enabled if the entity owns the trait: DebugComponent and GraphicsComponent
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \brief Constructs an DebugSystem object by default
|
||||||
|
*/
|
||||||
|
DebugSystem::DebugSystem()
|
||||||
|
{
|
||||||
|
Requires<DebugComponent, GraphicsComponent, NodeComponent>();
|
||||||
|
SetUpdateOrder(1000); //< Update last
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<Nz::IndexBufferRef, Nz::VertexBufferRef> DebugSystem::GetBoxMesh()
|
||||||
|
{
|
||||||
|
if (!m_boxMeshIndexBuffer)
|
||||||
|
{
|
||||||
|
std::array<Nz::UInt16, 24> indices = {
|
||||||
|
{
|
||||||
|
0, 1,
|
||||||
|
1, 2,
|
||||||
|
2, 3,
|
||||||
|
3, 0,
|
||||||
|
|
||||||
|
4, 5,
|
||||||
|
5, 6,
|
||||||
|
6, 7,
|
||||||
|
7, 4,
|
||||||
|
|
||||||
|
0, 4,
|
||||||
|
1, 5,
|
||||||
|
2, 6,
|
||||||
|
3, 7
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
m_boxMeshIndexBuffer = Nz::IndexBuffer::New(false, Nz::UInt32(indices.size()), Nz::DataStorage_Hardware, 0);
|
||||||
|
m_boxMeshIndexBuffer->Fill(indices.data(), 0, Nz::UInt32(indices.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_boxMeshVertexBuffer)
|
||||||
|
{
|
||||||
|
Nz::Boxf box(-0.5f, -0.5f, -0.5f, 1.f, 1.f, 1.f);
|
||||||
|
|
||||||
|
std::array<Nz::Vector3f, 8> positions = {
|
||||||
|
{
|
||||||
|
box.GetCorner(Nz::BoxCorner_FarLeftBottom),
|
||||||
|
box.GetCorner(Nz::BoxCorner_NearLeftBottom),
|
||||||
|
box.GetCorner(Nz::BoxCorner_NearRightBottom),
|
||||||
|
box.GetCorner(Nz::BoxCorner_FarRightBottom),
|
||||||
|
box.GetCorner(Nz::BoxCorner_FarLeftTop),
|
||||||
|
box.GetCorner(Nz::BoxCorner_NearLeftTop),
|
||||||
|
box.GetCorner(Nz::BoxCorner_NearRightTop),
|
||||||
|
box.GetCorner(Nz::BoxCorner_FarRightTop)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
m_boxMeshVertexBuffer = Nz::VertexBuffer::New(Nz::VertexDeclaration::Get(Nz::VertexLayout_XYZ), Nz::UInt32(positions.size()), Nz::DataStorage_Hardware, 0);
|
||||||
|
m_boxMeshVertexBuffer->Fill(positions.data(), 0, Nz::UInt32(positions.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return { m_boxMeshIndexBuffer, m_boxMeshVertexBuffer };
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugSystem::OnEntityValidation(Entity* entity, bool /*justAdded*/)
|
||||||
|
{
|
||||||
|
static constexpr int DebugDrawOrder = 1'000;
|
||||||
|
|
||||||
|
DebugComponent& entityDebug = entity->GetComponent<DebugComponent>();
|
||||||
|
GraphicsComponent& entityGfx = entity->GetComponent<GraphicsComponent>();
|
||||||
|
NodeComponent& entityNode = entity->GetComponent<NodeComponent>();
|
||||||
|
|
||||||
|
DebugDrawFlags enabledFlags = entityDebug.GetEnabledFlags();
|
||||||
|
DebugDrawFlags flags = entityDebug.GetFlags();
|
||||||
|
|
||||||
|
DebugDrawFlags flagsToEnable = flags & ~enabledFlags;
|
||||||
|
for (std::size_t i = 0; i <= static_cast<std::size_t>(DebugDraw::Max); ++i)
|
||||||
|
{
|
||||||
|
DebugDraw option = static_cast<DebugDraw>(i);
|
||||||
|
if (flagsToEnable & option)
|
||||||
|
{
|
||||||
|
switch (option)
|
||||||
|
{
|
||||||
|
case DebugDraw::Collider3D:
|
||||||
|
{
|
||||||
|
const Nz::Boxf& obb = entityGfx.GetAABB();
|
||||||
|
|
||||||
|
Nz::InstancedRenderableRef renderable = GenerateCollision3DMesh(entity);
|
||||||
|
if (renderable)
|
||||||
|
{
|
||||||
|
renderable->SetPersistent(false);
|
||||||
|
|
||||||
|
entityGfx.Attach(renderable, Nz::Matrix4f::Translate(obb.GetCenter() - entityNode.GetPosition()), DebugDrawOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
entityDebug.UpdateDebugRenderable(option, std::move(renderable));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case DebugDraw::GraphicsAABB:
|
||||||
|
{
|
||||||
|
auto indexVertexBuffers = GetBoxMesh();
|
||||||
|
|
||||||
|
Nz::InstancedRenderableRef renderable = new AABBDebugRenderable(entity, GetGlobalAABBMaterial(), GetLocalAABBMaterial(), indexVertexBuffers.first, indexVertexBuffers.second);
|
||||||
|
renderable->SetPersistent(false);
|
||||||
|
|
||||||
|
entityGfx.Attach(renderable, Nz::Matrix4f::Identity(), DebugDrawOrder);
|
||||||
|
|
||||||
|
entityDebug.UpdateDebugRenderable(option, std::move(renderable));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case DebugDraw::GraphicsOBB:
|
||||||
|
{
|
||||||
|
auto indexVertexBuffers = GetBoxMesh();
|
||||||
|
|
||||||
|
Nz::InstancedRenderableRef renderable = new OBBDebugRenderable(entity, GetOBBMaterial(), indexVertexBuffers.first, indexVertexBuffers.second);
|
||||||
|
renderable->SetPersistent(false);
|
||||||
|
|
||||||
|
entityGfx.Attach(renderable, Nz::Matrix4f::Identity(), DebugDrawOrder);
|
||||||
|
|
||||||
|
entityDebug.UpdateDebugRenderable(option, std::move(renderable));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugDrawFlags flagsToDisable = enabledFlags & ~flags;
|
||||||
|
for (std::size_t i = 0; i <= static_cast<std::size_t>(DebugDraw::Max); ++i)
|
||||||
|
{
|
||||||
|
DebugDraw option = static_cast<DebugDraw>(i);
|
||||||
|
if (flagsToDisable & option)
|
||||||
|
entityGfx.Detach(entityDebug.GetDebugRenderable(option));
|
||||||
|
}
|
||||||
|
|
||||||
|
entityDebug.UpdateEnabledFlags(flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugSystem::OnUpdate(float elapsedTime)
|
||||||
|
{
|
||||||
|
// Nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
Nz::InstancedRenderableRef DebugSystem::GenerateBox(Nz::Boxf box)
|
||||||
|
{
|
||||||
|
Nz::MeshRef mesh = Nz::Mesh::New();
|
||||||
|
mesh->CreateStatic();
|
||||||
|
|
||||||
|
mesh->BuildSubMesh(Nz::Primitive::Box(box.GetLengths()));
|
||||||
|
mesh->SetMaterialCount(1);
|
||||||
|
|
||||||
|
Nz::ModelRef model = Nz::Model::New();
|
||||||
|
model->SetMesh(mesh);
|
||||||
|
model->SetMaterial(0, GetOBBMaterial());
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
Nz::InstancedRenderableRef DebugSystem::GenerateCollision3DMesh(Entity* entity)
|
||||||
|
{
|
||||||
|
if (entity->HasComponent<CollisionComponent3D>())
|
||||||
|
{
|
||||||
|
CollisionComponent3D& entityCollision = entity->GetComponent<CollisionComponent3D>();
|
||||||
|
const Nz::Collider3DRef& geom = entityCollision.GetGeom();
|
||||||
|
|
||||||
|
std::vector<Nz::Vector3f> vertices;
|
||||||
|
std::vector<std::size_t> indices;
|
||||||
|
|
||||||
|
geom->ForEachPolygon([&](const float* polygonVertices, std::size_t vertexCount)
|
||||||
|
{
|
||||||
|
std::size_t firstIndex = vertices.size();
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < vertexCount; ++i)
|
||||||
|
{
|
||||||
|
const float* vertexData = &polygonVertices[i * 3];
|
||||||
|
vertices.emplace_back(vertexData[0], vertexData[1], vertexData[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < vertexCount - 1; ++i)
|
||||||
|
{
|
||||||
|
indices.push_back(firstIndex + i);
|
||||||
|
indices.push_back(firstIndex + i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
indices.push_back(firstIndex + vertexCount - 1);
|
||||||
|
indices.push_back(firstIndex);
|
||||||
|
});
|
||||||
|
|
||||||
|
Nz::IndexBufferRef indexBuffer = Nz::IndexBuffer::New(vertices.size() > 0xFFFF, Nz::UInt32(indices.size()), Nz::DataStorage_Hardware, 0);
|
||||||
|
Nz::IndexMapper indexMapper(indexBuffer, Nz::BufferAccess_WriteOnly);
|
||||||
|
|
||||||
|
Nz::IndexIterator indexPtr = indexMapper.begin();
|
||||||
|
for (std::size_t index : indices)
|
||||||
|
*indexPtr++ = static_cast<Nz::UInt32>(index);
|
||||||
|
|
||||||
|
indexMapper.Unmap();
|
||||||
|
|
||||||
|
Nz::VertexBufferRef vertexBuffer = Nz::VertexBuffer::New(Nz::VertexDeclaration::Get(Nz::VertexLayout_XYZ), Nz::UInt32(vertices.size()), Nz::DataStorage_Hardware, 0);
|
||||||
|
vertexBuffer->Fill(vertices.data(), 0, Nz::UInt32(vertices.size()));
|
||||||
|
|
||||||
|
Nz::MeshRef mesh = Nz::Mesh::New();
|
||||||
|
mesh->CreateStatic();
|
||||||
|
|
||||||
|
Nz::StaticMeshRef subMesh = Nz::StaticMesh::New(vertexBuffer, indexBuffer);
|
||||||
|
subMesh->SetPrimitiveMode(Nz::PrimitiveMode_LineList);
|
||||||
|
subMesh->SetMaterialIndex(0);
|
||||||
|
subMesh->GenerateAABB();
|
||||||
|
|
||||||
|
mesh->SetMaterialCount(1);
|
||||||
|
mesh->AddSubMesh(subMesh);
|
||||||
|
|
||||||
|
Nz::ModelRef model = Nz::Model::New();
|
||||||
|
model->SetMesh(mesh);
|
||||||
|
model->SetMaterial(0, GetCollisionMaterial());
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Nz::MaterialRef DebugSystem::GetGlobalAABBMaterial()
|
||||||
|
{
|
||||||
|
if (!m_globalAabbMaterial)
|
||||||
|
{
|
||||||
|
m_globalAabbMaterial = Nz::Material::New();
|
||||||
|
m_globalAabbMaterial->EnableFaceCulling(false);
|
||||||
|
m_globalAabbMaterial->EnableDepthBuffer(true);
|
||||||
|
m_globalAabbMaterial->SetDiffuseColor(Nz::Color::Orange);
|
||||||
|
m_globalAabbMaterial->SetFaceFilling(Nz::FaceFilling_Line);
|
||||||
|
m_globalAabbMaterial->SetLineWidth(2.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_globalAabbMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
|
Nz::MaterialRef DebugSystem::GetLocalAABBMaterial()
|
||||||
|
{
|
||||||
|
if (!m_localAabbMaterial)
|
||||||
|
{
|
||||||
|
m_localAabbMaterial = Nz::Material::New();
|
||||||
|
m_localAabbMaterial->EnableFaceCulling(false);
|
||||||
|
m_localAabbMaterial->EnableDepthBuffer(true);
|
||||||
|
m_localAabbMaterial->SetDiffuseColor(Nz::Color::Red);
|
||||||
|
m_localAabbMaterial->SetFaceFilling(Nz::FaceFilling_Line);
|
||||||
|
m_localAabbMaterial->SetLineWidth(2.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_localAabbMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
|
Nz::MaterialRef DebugSystem::GetCollisionMaterial()
|
||||||
|
{
|
||||||
|
if (!m_collisionMaterial)
|
||||||
|
{
|
||||||
|
m_collisionMaterial = Nz::Material::New();
|
||||||
|
m_collisionMaterial->EnableFaceCulling(false);
|
||||||
|
m_collisionMaterial->EnableDepthBuffer(true);
|
||||||
|
m_collisionMaterial->SetDiffuseColor(Nz::Color::Blue);
|
||||||
|
m_collisionMaterial->SetFaceFilling(Nz::FaceFilling_Line);
|
||||||
|
m_collisionMaterial->SetLineWidth(2.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_collisionMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
|
Nz::MaterialRef DebugSystem::GetOBBMaterial()
|
||||||
|
{
|
||||||
|
if (!m_obbMaterial)
|
||||||
|
{
|
||||||
|
m_obbMaterial = Nz::Material::New();
|
||||||
|
m_obbMaterial->EnableFaceCulling(false);
|
||||||
|
m_obbMaterial->EnableDepthBuffer(true);
|
||||||
|
m_obbMaterial->SetDiffuseColor(Nz::Color::Green);
|
||||||
|
m_obbMaterial->SetFaceFilling(Nz::FaceFilling_Line);
|
||||||
|
m_obbMaterial->SetLineWidth(2.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_obbMaterial;
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemIndex DebugSystem::systemIndex;
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <NDK/Systems/PhysicsSystem2D.hpp>
|
#include <NDK/Systems/PhysicsSystem2D.hpp>
|
||||||
#include <Nazara/Physics2D/RigidBody2D.hpp>
|
#include <Nazara/Physics2D/RigidBody2D.hpp>
|
||||||
|
#include <NDK/World.hpp>
|
||||||
#include <NDK/Components/CollisionComponent2D.hpp>
|
#include <NDK/Components/CollisionComponent2D.hpp>
|
||||||
#include <NDK/Components/NodeComponent.hpp>
|
#include <NDK/Components/NodeComponent.hpp>
|
||||||
#include <NDK/Components/PhysicsComponent2D.hpp>
|
#include <NDK/Components/PhysicsComponent2D.hpp>
|
||||||
|
|
@ -33,9 +34,108 @@ namespace Ndk
|
||||||
|
|
||||||
void PhysicsSystem2D::CreatePhysWorld() const
|
void PhysicsSystem2D::CreatePhysWorld() const
|
||||||
{
|
{
|
||||||
NazaraAssert(!m_world, "Physics world should not be created twice");
|
NazaraAssert(!m_physWorld, "Physics world should not be created twice");
|
||||||
|
|
||||||
m_world = std::make_unique<Nz::PhysWorld2D>();
|
m_physWorld = std::make_unique<Nz::PhysWorld2D>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicsSystem2D::DebugDraw(const DebugDrawOptions& options, bool drawShapes, bool drawConstraints, bool drawCollisions)
|
||||||
|
{
|
||||||
|
Nz::PhysWorld2D::DebugDrawOptions worldOptions{ options.constraintColor, options.collisionPointColor, options.shapeOutlineColor };
|
||||||
|
|
||||||
|
if (options.colorCallback)
|
||||||
|
{
|
||||||
|
worldOptions.colorCallback = [&options, this](Nz::RigidBody2D& body, std::size_t shapeIndex, void* userdata)
|
||||||
|
{
|
||||||
|
return options.colorCallback(GetEntityFromBody(body), shapeIndex, userdata);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
worldOptions.circleCallback = options.circleCallback;
|
||||||
|
worldOptions.dotCallback = options.dotCallback;
|
||||||
|
worldOptions.polygonCallback = options.polygonCallback;
|
||||||
|
worldOptions.segmentCallback = options.segmentCallback;
|
||||||
|
worldOptions.thickSegmentCallback = options.thickSegmentCallback;
|
||||||
|
|
||||||
|
worldOptions.userdata = options.userdata;
|
||||||
|
|
||||||
|
GetPhysWorld().DebugDraw(worldOptions, drawShapes, drawConstraints, drawCollisions);
|
||||||
|
}
|
||||||
|
|
||||||
|
const EntityHandle& PhysicsSystem2D::GetEntityFromBody(const Nz::RigidBody2D& body) const
|
||||||
|
{
|
||||||
|
auto entityId = static_cast<EntityId>(reinterpret_cast<std::uintptr_t>(body.GetUserdata()));
|
||||||
|
|
||||||
|
auto& world = GetWorld();
|
||||||
|
|
||||||
|
NazaraAssert(world.IsEntityIdValid(entityId), "All Bodies of this world must be part of the physics world by using PhysicsComponent");
|
||||||
|
|
||||||
|
return world.GetEntity(entityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PhysicsSystem2D::NearestBodyQuery(const Nz::Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, EntityHandle* nearestBody)
|
||||||
|
{
|
||||||
|
Nz::RigidBody2D* body;
|
||||||
|
bool res = GetPhysWorld().NearestBodyQuery(from, maxDistance, collisionGroup, categoryMask, collisionMask, &body);
|
||||||
|
|
||||||
|
(*nearestBody) = GetEntityFromBody(*body);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PhysicsSystem2D::NearestBodyQuery(const Nz::Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, NearestQueryResult* result)
|
||||||
|
{
|
||||||
|
Nz::PhysWorld2D::NearestQueryResult queryResult;
|
||||||
|
bool res = GetPhysWorld().NearestBodyQuery(from, maxDistance, collisionGroup, categoryMask, collisionMask, &queryResult);
|
||||||
|
|
||||||
|
result->nearestBody = GetEntityFromBody(*queryResult.nearestBody);
|
||||||
|
result->closestPoint = std::move(queryResult.closestPoint);
|
||||||
|
result->fraction = std::move(queryResult.fraction);
|
||||||
|
result->distance = queryResult.distance;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PhysicsSystem2D::RaycastQuery(const Nz::Vector2f& from, const Nz::Vector2f& to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, std::vector<RaycastHit>* hitInfos)
|
||||||
|
{
|
||||||
|
std::vector<Nz::PhysWorld2D::RaycastHit> queryResult;
|
||||||
|
bool res = GetPhysWorld().RaycastQuery(from, to, radius, collisionGroup, categoryMask, collisionMask, &queryResult);
|
||||||
|
|
||||||
|
for (auto& hitResult : queryResult)
|
||||||
|
{
|
||||||
|
hitInfos->push_back({
|
||||||
|
GetEntityFromBody(*hitResult.nearestBody),
|
||||||
|
std::move(hitResult.hitPos),
|
||||||
|
std::move(hitResult.hitNormal),
|
||||||
|
hitResult.fraction
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PhysicsSystem2D::RaycastQueryFirst(const Nz::Vector2f& from, const Nz::Vector2f& to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RaycastHit* hitInfo)
|
||||||
|
{
|
||||||
|
Nz::PhysWorld2D::RaycastHit queryResult;
|
||||||
|
bool res = GetPhysWorld().RaycastQueryFirst(from, to, radius, collisionGroup, categoryMask, collisionMask, &queryResult);
|
||||||
|
|
||||||
|
hitInfo->body = GetEntityFromBody(*queryResult.nearestBody);
|
||||||
|
hitInfo->hitPos = std::move(queryResult.hitPos);
|
||||||
|
hitInfo->hitNormal = std::move(queryResult.hitNormal);
|
||||||
|
hitInfo->fraction = queryResult.fraction;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicsSystem2D::RegionQuery(const Nz::Rectf& boundingBox, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, std::vector<EntityHandle>* bodies)
|
||||||
|
{
|
||||||
|
std::vector<Nz::RigidBody2D*> queryResult;
|
||||||
|
GetPhysWorld().RegionQuery(boundingBox, collisionGroup, categoryMask, collisionMask, &queryResult);
|
||||||
|
|
||||||
|
for (auto& body : queryResult)
|
||||||
|
{
|
||||||
|
bodies->emplace_back(GetEntityFromBody(*body));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
@ -47,18 +147,34 @@ namespace Ndk
|
||||||
|
|
||||||
void PhysicsSystem2D::OnEntityValidation(Entity* entity, bool justAdded)
|
void PhysicsSystem2D::OnEntityValidation(Entity* entity, bool justAdded)
|
||||||
{
|
{
|
||||||
// It's possible our entity got revalidated because of the addition/removal of a PhysicsComponent3D
|
if (entity->HasComponent<PhysicsComponent2D>())
|
||||||
if (!justAdded)
|
|
||||||
{
|
{
|
||||||
// We take the opposite array from which the entity should belong to
|
if (entity->GetComponent<PhysicsComponent2D>().IsNodeSynchronizationEnabled())
|
||||||
auto& entities = (entity->HasComponent<PhysicsComponent2D>()) ? m_staticObjects : m_dynamicObjects;
|
m_dynamicObjects.Insert(entity);
|
||||||
entities.Remove(entity);
|
else
|
||||||
|
m_dynamicObjects.Remove(entity);
|
||||||
|
|
||||||
|
m_staticObjects.Remove(entity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_dynamicObjects.Remove(entity);
|
||||||
|
m_staticObjects.Insert(entity);
|
||||||
|
|
||||||
|
// If entities just got added to the system, teleport them to their NodeComponent position/rotation
|
||||||
|
// This will prevent the physics engine to mess with the scene while correcting position/rotation
|
||||||
|
if (justAdded)
|
||||||
|
{
|
||||||
|
auto& collision = entity->GetComponent<CollisionComponent2D>();
|
||||||
|
auto& node = entity->GetComponent<NodeComponent>();
|
||||||
|
|
||||||
|
Nz::RigidBody2D* physObj = collision.GetStaticBody();
|
||||||
|
physObj->SetPosition(Nz::Vector2f(node.GetPosition()));
|
||||||
|
//physObj->SetRotation(node.GetRotation());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& entities = (entity->HasComponent<PhysicsComponent2D>()) ? m_dynamicObjects : m_staticObjects;
|
if (!m_physWorld)
|
||||||
entities.Insert(entity);
|
|
||||||
|
|
||||||
if (!m_world)
|
|
||||||
CreatePhysWorld();
|
CreatePhysWorld();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,10 +186,10 @@ namespace Ndk
|
||||||
|
|
||||||
void PhysicsSystem2D::OnUpdate(float elapsedTime)
|
void PhysicsSystem2D::OnUpdate(float elapsedTime)
|
||||||
{
|
{
|
||||||
if (!m_world)
|
if (!m_physWorld)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_world->Step(elapsedTime);
|
m_physWorld->Step(elapsedTime);
|
||||||
|
|
||||||
for (const Ndk::EntityHandle& entity : m_dynamicObjects)
|
for (const Ndk::EntityHandle& entity : m_dynamicObjects)
|
||||||
{
|
{
|
||||||
|
|
@ -81,7 +197,7 @@ namespace Ndk
|
||||||
PhysicsComponent2D& phys = entity->GetComponent<PhysicsComponent2D>();
|
PhysicsComponent2D& phys = entity->GetComponent<PhysicsComponent2D>();
|
||||||
|
|
||||||
Nz::RigidBody2D* body = phys.GetRigidBody();
|
Nz::RigidBody2D* body = phys.GetRigidBody();
|
||||||
node.SetRotation(Nz::EulerAnglesf(0.f, 0.f, body->GetRotation()), Nz::CoordSys_Global);
|
node.SetRotation(body->GetRotation(), Nz::CoordSys_Global);
|
||||||
node.SetPosition(Nz::Vector3f(body->GetPosition(), node.GetPosition(Nz::CoordSys_Global).z), Nz::CoordSys_Global);
|
node.SetPosition(Nz::Vector3f(body->GetPosition(), node.GetPosition(Nz::CoordSys_Global).z), Nz::CoordSys_Global);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -124,5 +240,87 @@ namespace Ndk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PhysicsSystem2D::RegisterCallbacks(unsigned int collisionId, Callback callbacks)
|
||||||
|
{
|
||||||
|
Nz::PhysWorld2D::Callback worldCallbacks;
|
||||||
|
|
||||||
|
if (callbacks.endCallback)
|
||||||
|
{
|
||||||
|
worldCallbacks.endCallback = [this, cb = std::move(callbacks.endCallback)](Nz::PhysWorld2D& world, Nz::Arbiter2D& arbiter, Nz::RigidBody2D& bodyA, Nz::RigidBody2D& bodyB, void* userdata)
|
||||||
|
{
|
||||||
|
cb(*this, arbiter, GetEntityFromBody(bodyA), GetEntityFromBody(bodyB), userdata);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callbacks.preSolveCallback)
|
||||||
|
{
|
||||||
|
worldCallbacks.preSolveCallback = [this, cb = std::move(callbacks.preSolveCallback)](Nz::PhysWorld2D& world, Nz::Arbiter2D& arbiter, Nz::RigidBody2D& bodyA, Nz::RigidBody2D& bodyB, void* userdata)
|
||||||
|
{
|
||||||
|
return cb(*this, arbiter, GetEntityFromBody(bodyA), GetEntityFromBody(bodyB), userdata);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callbacks.postSolveCallback)
|
||||||
|
{
|
||||||
|
worldCallbacks.postSolveCallback = [this, cb = std::move(callbacks.postSolveCallback)](Nz::PhysWorld2D& world, Nz::Arbiter2D& arbiter, Nz::RigidBody2D& bodyA, Nz::RigidBody2D& bodyB, void* userdata)
|
||||||
|
{
|
||||||
|
cb(*this, arbiter, GetEntityFromBody(bodyA), GetEntityFromBody(bodyB), userdata);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callbacks.startCallback)
|
||||||
|
{
|
||||||
|
worldCallbacks.startCallback = [this, cb = std::move(callbacks.startCallback)](Nz::PhysWorld2D& world, Nz::Arbiter2D& arbiter, Nz::RigidBody2D& bodyA, Nz::RigidBody2D& bodyB, void* userdata)
|
||||||
|
{
|
||||||
|
return cb(*this, arbiter, GetEntityFromBody(bodyA), GetEntityFromBody(bodyB), userdata);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
worldCallbacks.userdata = callbacks.userdata;
|
||||||
|
|
||||||
|
m_physWorld->RegisterCallbacks(collisionId, worldCallbacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicsSystem2D::RegisterCallbacks(unsigned int collisionIdA, unsigned int collisionIdB, Callback callbacks)
|
||||||
|
{
|
||||||
|
Nz::PhysWorld2D::Callback worldCallbacks{};
|
||||||
|
|
||||||
|
if (callbacks.endCallback)
|
||||||
|
{
|
||||||
|
worldCallbacks.endCallback = [this, cb = std::move(callbacks.endCallback)](Nz::PhysWorld2D& world, Nz::Arbiter2D& arbiter, Nz::RigidBody2D& bodyA, Nz::RigidBody2D& bodyB, void* userdata)
|
||||||
|
{
|
||||||
|
cb(*this, arbiter, GetEntityFromBody(bodyA), GetEntityFromBody(bodyB), userdata);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callbacks.preSolveCallback)
|
||||||
|
{
|
||||||
|
worldCallbacks.preSolveCallback = [this, cb = std::move(callbacks.preSolveCallback)](Nz::PhysWorld2D& world, Nz::Arbiter2D& arbiter, Nz::RigidBody2D& bodyA, Nz::RigidBody2D& bodyB, void* userdata)
|
||||||
|
{
|
||||||
|
return cb(*this, arbiter, GetEntityFromBody(bodyA), GetEntityFromBody(bodyB), userdata);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callbacks.postSolveCallback)
|
||||||
|
{
|
||||||
|
worldCallbacks.postSolveCallback = [this, cb = std::move(callbacks.postSolveCallback)](Nz::PhysWorld2D& world, Nz::Arbiter2D& arbiter, Nz::RigidBody2D& bodyA, Nz::RigidBody2D& bodyB, void* userdata)
|
||||||
|
{
|
||||||
|
cb(*this, arbiter, GetEntityFromBody(bodyA), GetEntityFromBody(bodyB), userdata);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callbacks.startCallback)
|
||||||
|
{
|
||||||
|
worldCallbacks.startCallback = [this, cb = std::move(callbacks.startCallback)](Nz::PhysWorld2D& world, Nz::Arbiter2D& arbiter, Nz::RigidBody2D& bodyA, Nz::RigidBody2D& bodyB, void* userdata)
|
||||||
|
{
|
||||||
|
return cb(*this, arbiter, GetEntityFromBody(bodyA), GetEntityFromBody(bodyB), userdata);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
worldCallbacks.userdata = callbacks.userdata;
|
||||||
|
|
||||||
|
m_physWorld->RegisterCallbacks(collisionIdA, collisionIdB, worldCallbacks);
|
||||||
|
}
|
||||||
|
|
||||||
SystemIndex PhysicsSystem2D::systemIndex;
|
SystemIndex PhysicsSystem2D::systemIndex;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include <Nazara/Graphics/ColorBackground.hpp>
|
#include <Nazara/Graphics/ColorBackground.hpp>
|
||||||
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
|
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
|
||||||
#include <Nazara/Graphics/SceneData.hpp>
|
#include <Nazara/Graphics/SceneData.hpp>
|
||||||
|
#include <Nazara/Graphics/SkinningManager.hpp>
|
||||||
#include <Nazara/Graphics/SkyboxBackground.hpp>
|
#include <Nazara/Graphics/SkyboxBackground.hpp>
|
||||||
#include <Nazara/Math/Rect.hpp>
|
#include <Nazara/Math/Rect.hpp>
|
||||||
#include <Nazara/Renderer/Renderer.hpp>
|
#include <Nazara/Renderer/Renderer.hpp>
|
||||||
|
|
@ -34,7 +35,8 @@ namespace Ndk
|
||||||
RenderSystem::RenderSystem() :
|
RenderSystem::RenderSystem() :
|
||||||
m_coordinateSystemMatrix(Nz::Matrix4f::Identity()),
|
m_coordinateSystemMatrix(Nz::Matrix4f::Identity()),
|
||||||
m_coordinateSystemInvalidated(true),
|
m_coordinateSystemInvalidated(true),
|
||||||
m_forceRenderQueueInvalidation(false)
|
m_forceRenderQueueInvalidation(false),
|
||||||
|
m_isCullingEnabled(true)
|
||||||
{
|
{
|
||||||
ChangeRenderTechnique<Nz::ForwardRenderTechnique>();
|
ChangeRenderTechnique<Nz::ForwardRenderTechnique>();
|
||||||
SetDefaultBackground(Nz::ColorBackground::New());
|
SetDefaultBackground(Nz::ColorBackground::New());
|
||||||
|
|
@ -183,6 +185,8 @@ namespace Ndk
|
||||||
m_coordinateSystemInvalidated = false;
|
m_coordinateSystemInvalidated = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Nz::SkinningManager::Skin();
|
||||||
|
|
||||||
UpdateDynamicReflections();
|
UpdateDynamicReflections();
|
||||||
UpdatePointSpotShadowMaps();
|
UpdatePointSpotShadowMaps();
|
||||||
|
|
||||||
|
|
@ -194,27 +198,36 @@ namespace Ndk
|
||||||
|
|
||||||
Nz::AbstractRenderQueue* renderQueue = m_renderTechnique->GetRenderQueue();
|
Nz::AbstractRenderQueue* renderQueue = m_renderTechnique->GetRenderQueue();
|
||||||
|
|
||||||
// To make sure the bounding volume used by the culling list is updated
|
// To make sure the bounding volumes used by the culling list is updated
|
||||||
for (const Ndk::EntityHandle& drawable : m_drawables)
|
for (const Ndk::EntityHandle& drawable : m_drawables)
|
||||||
{
|
{
|
||||||
GraphicsComponent& graphicsComponent = drawable->GetComponent<GraphicsComponent>();
|
GraphicsComponent& graphicsComponent = drawable->GetComponent<GraphicsComponent>();
|
||||||
graphicsComponent.EnsureBoundingVolumeUpdate();
|
graphicsComponent.EnsureBoundingVolumesUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool forceInvalidation = false;
|
bool forceInvalidation = false;
|
||||||
|
|
||||||
std::size_t visibilityHash = m_drawableCulling.Cull(camComponent.GetFrustum(), &forceInvalidation);
|
const Nz::Frustumf& frustum = camComponent.GetFrustum();
|
||||||
|
|
||||||
|
std::size_t visibilityHash;
|
||||||
|
if (m_isCullingEnabled)
|
||||||
|
visibilityHash = m_drawableCulling.Cull(frustum, &forceInvalidation);
|
||||||
|
else
|
||||||
|
visibilityHash = m_drawableCulling.FillWithAllEntries(&forceInvalidation);
|
||||||
|
|
||||||
// Always regenerate renderqueue if particle groups are present for now (FIXME)
|
// Always regenerate renderqueue if particle groups are present for now (FIXME)
|
||||||
if (!m_particleGroups.empty())
|
if (!m_lights.empty() || !m_particleGroups.empty())
|
||||||
forceInvalidation = true;
|
forceInvalidation = true;
|
||||||
|
|
||||||
if (camComponent.UpdateVisibility(visibilityHash) || m_forceRenderQueueInvalidation || forceInvalidation)
|
if (camComponent.UpdateVisibility(visibilityHash) || m_forceRenderQueueInvalidation || forceInvalidation)
|
||||||
{
|
{
|
||||||
renderQueue->Clear();
|
renderQueue->Clear();
|
||||||
for (const GraphicsComponent* gfxComponent : m_drawableCulling)
|
for (const GraphicsComponent* gfxComponent : m_drawableCulling.GetFullyVisibleResults())
|
||||||
gfxComponent->AddToRenderQueue(renderQueue);
|
gfxComponent->AddToRenderQueue(renderQueue);
|
||||||
|
|
||||||
|
for (const GraphicsComponent* gfxComponent : m_drawableCulling.GetPartiallyVisibleResults())
|
||||||
|
gfxComponent->AddToRenderQueueByCulling(frustum, renderQueue);
|
||||||
|
|
||||||
for (const Ndk::EntityHandle& light : m_lights)
|
for (const Ndk::EntityHandle& light : m_lights)
|
||||||
{
|
{
|
||||||
LightComponent& lightComponent = light->GetComponent<LightComponent>();
|
LightComponent& lightComponent = light->GetComponent<LightComponent>();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
// Copyright (C) 2017 Jérôme Leclercq
|
||||||
|
// This file is part of the "Nazara Development Kit"
|
||||||
|
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||||
|
|
||||||
|
#include <NDK/Widgets/BoxLayout.hpp>
|
||||||
|
#include <Nazara/Core/Log.hpp>
|
||||||
|
#include <Nazara/Core/MemoryHelper.hpp>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace Ndk
|
||||||
|
{
|
||||||
|
void BoxLayout::Layout()
|
||||||
|
{
|
||||||
|
std::size_t axis1, axis2;
|
||||||
|
|
||||||
|
switch (m_orientation)
|
||||||
|
{
|
||||||
|
case BoxLayoutOrientation_Horizontal:
|
||||||
|
axis1 = 0; //< x
|
||||||
|
axis2 = 1; //< y
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BoxLayoutOrientation_Vertical:
|
||||||
|
axis1 = 1; //< y
|
||||||
|
axis2 = 0; //< x
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_childInfos.clear();
|
||||||
|
|
||||||
|
// Handle size
|
||||||
|
ForEachWidgetChild([&](BaseWidget* child)
|
||||||
|
{
|
||||||
|
if (!child->IsVisible())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_childInfos.emplace_back();
|
||||||
|
auto& info = m_childInfos.back();
|
||||||
|
info.isConstrained = false;
|
||||||
|
info.maximumSize = child->GetMaximumSize()[axis1];
|
||||||
|
info.minimumSize = child->GetMinimumSize()[axis1];
|
||||||
|
info.size = info.minimumSize;
|
||||||
|
info.widget = child;
|
||||||
|
});
|
||||||
|
|
||||||
|
Nz::Vector2f layoutSize = GetSize();
|
||||||
|
|
||||||
|
float availableSpace = layoutSize[axis1] - m_spacing * (m_childInfos.size() - 1);
|
||||||
|
float remainingSize = availableSpace;
|
||||||
|
for (auto& info : m_childInfos)
|
||||||
|
remainingSize -= info.minimumSize;
|
||||||
|
|
||||||
|
// Okay this algorithm is FAR from perfect but I couldn't figure a way other than this one
|
||||||
|
std::size_t unconstrainedChildCount = m_childInfos.size();
|
||||||
|
|
||||||
|
bool hasUnconstrainedChilds = false;
|
||||||
|
for (std::size_t i = 0; i < m_childInfos.size(); ++i)
|
||||||
|
{
|
||||||
|
if (remainingSize <= 0.0001f)
|
||||||
|
break;
|
||||||
|
|
||||||
|
float evenSize = remainingSize / unconstrainedChildCount;
|
||||||
|
|
||||||
|
for (auto& info : m_childInfos)
|
||||||
|
{
|
||||||
|
if (info.isConstrained)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
float previousSize = info.size;
|
||||||
|
|
||||||
|
info.size += evenSize;
|
||||||
|
if (info.size > info.maximumSize)
|
||||||
|
{
|
||||||
|
unconstrainedChildCount--;
|
||||||
|
|
||||||
|
evenSize += (info.size - info.maximumSize) / unconstrainedChildCount;
|
||||||
|
info.isConstrained = true;
|
||||||
|
info.size = info.maximumSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
hasUnconstrainedChilds = true;
|
||||||
|
|
||||||
|
remainingSize -= info.size - previousSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasUnconstrainedChilds)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
float spacing = m_spacing + remainingSize / (m_childInfos.size() - 1);
|
||||||
|
|
||||||
|
for (auto& info : m_childInfos)
|
||||||
|
{
|
||||||
|
Nz::Vector2f newSize = info.widget->GetSize();
|
||||||
|
newSize[axis1] = info.size;
|
||||||
|
|
||||||
|
info.widget->Resize(newSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle position
|
||||||
|
float cursor = 0.f;
|
||||||
|
bool first = true;
|
||||||
|
for (auto& info : m_childInfos)
|
||||||
|
{
|
||||||
|
if (first)
|
||||||
|
first = false;
|
||||||
|
else
|
||||||
|
cursor += spacing;
|
||||||
|
|
||||||
|
Nz::Vector2f position = Nz::Vector2f(0.f, 0.f);
|
||||||
|
position[axis1] = cursor;
|
||||||
|
|
||||||
|
info.widget->SetPosition(position);
|
||||||
|
|
||||||
|
cursor += info.size;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -30,13 +30,13 @@ namespace Ndk
|
||||||
m_gradientSprite->SetCornerColor(Nz::RectCorner_RightBottom, m_cornerColor);
|
m_gradientSprite->SetCornerColor(Nz::RectCorner_RightBottom, m_cornerColor);
|
||||||
m_gradientSprite->SetMaterial(Nz::Material::New("Basic2D"));
|
m_gradientSprite->SetMaterial(Nz::Material::New("Basic2D"));
|
||||||
|
|
||||||
m_gradientEntity = CreateEntity(false);
|
m_gradientEntity = CreateEntity();
|
||||||
m_gradientEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_gradientEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
m_gradientEntity->AddComponent<GraphicsComponent>().Attach(m_gradientSprite);
|
m_gradientEntity->AddComponent<GraphicsComponent>().Attach(m_gradientSprite);
|
||||||
|
|
||||||
m_textSprite = Nz::TextSprite::New();
|
m_textSprite = Nz::TextSprite::New();
|
||||||
|
|
||||||
m_textEntity = CreateEntity(true);
|
m_textEntity = CreateEntity();
|
||||||
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite, 1);
|
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite, 1);
|
||||||
|
|
||||||
|
|
@ -73,22 +73,15 @@ namespace Ndk
|
||||||
return s_pressCornerColor;
|
return s_pressCornerColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ButtonWidget::ResizeToContent()
|
|
||||||
{
|
|
||||||
SetContentSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ButtonWidget::Layout()
|
void ButtonWidget::Layout()
|
||||||
{
|
{
|
||||||
BaseWidget::Layout();
|
BaseWidget::Layout();
|
||||||
|
|
||||||
m_gradientSprite->SetSize(GetSize());
|
Nz::Vector2f size = GetSize();
|
||||||
|
m_gradientSprite->SetSize(size);
|
||||||
|
|
||||||
Nz::Vector2f origin = GetContentOrigin();
|
Nz::Boxf textBox = m_textEntity->GetComponent<GraphicsComponent>().GetAABB();
|
||||||
const Nz::Vector2f& contentSize = GetContentSize();
|
m_textEntity->GetComponent<NodeComponent>().SetPosition(size.x / 2.f - textBox.width / 2.f, size.y / 2.f - textBox.height / 2.f);
|
||||||
|
|
||||||
Nz::Boxf textBox = m_textEntity->GetComponent<GraphicsComponent>().GetBoundingVolume().obb.localBox;
|
|
||||||
m_textEntity->GetComponent<NodeComponent>().SetPosition(origin.x + contentSize.x / 2 - textBox.width / 2, origin.y + contentSize.y / 2 - textBox.height / 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ButtonWidget::OnMouseButtonPress(int /*x*/, int /*y*/, Nz::Mouse::Button button)
|
void ButtonWidget::OnMouseButtonPress(int /*x*/, int /*y*/, Nz::Mouse::Button button)
|
||||||
|
|
|
||||||
|
|
@ -28,19 +28,19 @@ namespace Ndk
|
||||||
m_checkboxContentSprite = Nz::Sprite::New(Nz::Material::New("Translucent2D"));
|
m_checkboxContentSprite = Nz::Sprite::New(Nz::Material::New("Translucent2D"));
|
||||||
m_textSprite = Nz::TextSprite::New();
|
m_textSprite = Nz::TextSprite::New();
|
||||||
|
|
||||||
m_checkboxBorderEntity = CreateEntity(false);
|
m_checkboxBorderEntity = CreateEntity();
|
||||||
m_checkboxBorderEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_checkboxBorderEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
m_checkboxBorderEntity->AddComponent<GraphicsComponent>().Attach(m_checkboxBorderSprite);
|
m_checkboxBorderEntity->AddComponent<GraphicsComponent>().Attach(m_checkboxBorderSprite);
|
||||||
|
|
||||||
m_checkboxBackgroundEntity = CreateEntity(false);
|
m_checkboxBackgroundEntity = CreateEntity();
|
||||||
m_checkboxBackgroundEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_checkboxBackgroundEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
m_checkboxBackgroundEntity->AddComponent<GraphicsComponent>().Attach(m_checkboxBackgroundSprite, 1);
|
m_checkboxBackgroundEntity->AddComponent<GraphicsComponent>().Attach(m_checkboxBackgroundSprite, 1);
|
||||||
|
|
||||||
m_checkboxContentEntity = CreateEntity(true);
|
m_checkboxContentEntity = CreateEntity();
|
||||||
m_checkboxContentEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_checkboxContentEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
m_checkboxContentEntity->AddComponent<GraphicsComponent>().Attach(m_checkboxContentSprite, 2);
|
m_checkboxContentEntity->AddComponent<GraphicsComponent>().Attach(m_checkboxContentSprite, 2);
|
||||||
|
|
||||||
m_textEntity = CreateEntity(true);
|
m_textEntity = CreateEntity();
|
||||||
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
|
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
|
||||||
|
|
||||||
|
|
@ -57,14 +57,14 @@ namespace Ndk
|
||||||
#include <NDK/Resources/checkmark.png.h>
|
#include <NDK/Resources/checkmark.png.h>
|
||||||
};
|
};
|
||||||
|
|
||||||
Nz::TextureRef checkmarkTexture = Nz::Texture::New();
|
Nz::TextureRef checkmarkTexture = Nz::Texture::LoadFromMemory(r_checkmark, sizeof(r_checkmark) / sizeof(r_checkmark[0]));
|
||||||
if (!checkmarkTexture->LoadFromMemory(r_checkmark, sizeof(r_checkmark) / sizeof(r_checkmark[0])))
|
if (!checkmarkTexture)
|
||||||
{
|
{
|
||||||
NazaraError("Failed to load embedded checkmark");
|
NazaraError("Failed to load embedded checkmark");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Nz::TextureLibrary::Register("Ndk::CheckboxWidget::checkmark", checkmarkTexture);
|
Nz::TextureLibrary::Register("Ndk::CheckboxWidget::checkmark", std::move(checkmarkTexture));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,33 +108,20 @@ namespace Ndk
|
||||||
return m_state;
|
return m_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckboxWidget::ResizeToContent()
|
|
||||||
{
|
|
||||||
Nz::Vector3f textSize = m_textSprite->GetBoundingVolume().obb.localBox.GetLengths();
|
|
||||||
Nz::Vector2f checkboxSize = GetCheckboxSize();
|
|
||||||
|
|
||||||
Nz::Vector2f finalSize { checkboxSize.x + (m_adaptativeMargin ? checkboxSize.x / 2.f : m_textMargin) + textSize.x, std::max(textSize.y, checkboxSize.y) };
|
|
||||||
SetContentSize(finalSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CheckboxWidget::Layout()
|
void CheckboxWidget::Layout()
|
||||||
{
|
{
|
||||||
BaseWidget::Layout();
|
BaseWidget::Layout();
|
||||||
|
|
||||||
Nz::Vector2f origin = GetContentOrigin();
|
|
||||||
Nz::Vector2f checkboxSize = GetCheckboxSize();
|
Nz::Vector2f checkboxSize = GetCheckboxSize();
|
||||||
Nz::Vector2f borderSize = GetCheckboxBorderSize();
|
Nz::Vector2f borderSize = GetCheckboxBorderSize();
|
||||||
|
|
||||||
m_checkboxBorderEntity->GetComponent<NodeComponent>().SetPosition(origin);
|
m_checkboxBackgroundEntity->GetComponent<NodeComponent>().SetPosition(borderSize);
|
||||||
m_checkboxBackgroundEntity->GetComponent<NodeComponent>().SetPosition(origin + borderSize);
|
|
||||||
|
|
||||||
Nz::Vector3f checkboxBox = m_checkboxContentSprite->GetBoundingVolume().obb.localBox.GetLengths();
|
Nz::Vector3f checkboxBox = m_checkboxContentSprite->GetBoundingVolume().obb.localBox.GetLengths();
|
||||||
m_checkboxContentEntity->GetComponent<NodeComponent>().SetPosition(origin.x + checkboxSize.x / 2.f - checkboxBox.x / 2.f,
|
m_checkboxContentEntity->GetComponent<NodeComponent>().SetPosition(checkboxSize.x / 2.f - checkboxBox.x / 2.f, checkboxSize.y / 2.f - checkboxBox.y / 2.f);
|
||||||
origin.y + checkboxSize.y / 2.f - checkboxBox.y / 2.f);
|
|
||||||
|
|
||||||
Nz::Vector3f textBox = m_textSprite->GetBoundingVolume().obb.localBox.GetLengths();
|
Nz::Vector3f textBox = m_textSprite->GetBoundingVolume().obb.localBox.GetLengths();
|
||||||
m_textEntity->GetComponent<NodeComponent>().SetPosition(origin.x + checkboxSize.x + (m_adaptativeMargin ? checkboxSize.x / 2.f : m_textMargin),
|
m_textEntity->GetComponent<NodeComponent>().SetPosition(checkboxSize.x + (m_adaptativeMargin ? checkboxSize.x / 2.f : m_textMargin), checkboxSize.y / 2.f - textBox.y / 2.f);
|
||||||
origin.y + checkboxSize.y / 2.f - textBox.y / 2.f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckboxWidget::OnMouseButtonRelease(int x, int y, Nz::Mouse::Button button)
|
void CheckboxWidget::OnMouseButtonRelease(int x, int y, Nz::Mouse::Button button)
|
||||||
|
|
@ -178,4 +165,14 @@ namespace Ndk
|
||||||
m_checkboxContentSprite->SetTexture(Nz::TextureRef {});
|
m_checkboxContentSprite->SetTexture(Nz::TextureRef {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheckboxWidget::UpdateSize()
|
||||||
|
{
|
||||||
|
Nz::Vector3f textSize = m_textSprite->GetBoundingVolume().obb.localBox.GetLengths();
|
||||||
|
Nz::Vector2f checkboxSize = GetCheckboxSize();
|
||||||
|
|
||||||
|
Nz::Vector2f finalSize { checkboxSize.x + (m_adaptativeMargin ? checkboxSize.x / 2.f : m_textMargin) + textSize.x, std::max(textSize.y, checkboxSize.y) };
|
||||||
|
SetMinimumSize(finalSize);
|
||||||
|
SetPreferredSize(finalSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ namespace Ndk
|
||||||
ImageWidget::ImageWidget(BaseWidget* parent) :
|
ImageWidget::ImageWidget(BaseWidget* parent) :
|
||||||
BaseWidget(parent)
|
BaseWidget(parent)
|
||||||
{
|
{
|
||||||
m_entity = CreateEntity(true);
|
m_entity = CreateEntity();
|
||||||
m_entity->AddComponent<NodeComponent>();
|
m_entity->AddComponent<NodeComponent>();
|
||||||
auto& gfx = m_entity->AddComponent<GraphicsComponent>();
|
auto& gfx = m_entity->AddComponent<GraphicsComponent>();
|
||||||
|
|
||||||
|
|
@ -19,19 +19,10 @@ namespace Ndk
|
||||||
gfx.Attach(m_sprite);
|
gfx.Attach(m_sprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageWidget::ResizeToContent()
|
|
||||||
{
|
|
||||||
Nz::Vector3ui textureSize = m_sprite->GetMaterial()->GetDiffuseMap()->GetSize();
|
|
||||||
SetSize({ static_cast<float>(textureSize.x), static_cast<float>(textureSize.y) });
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImageWidget::Layout()
|
void ImageWidget::Layout()
|
||||||
{
|
{
|
||||||
BaseWidget::Layout();
|
BaseWidget::Layout();
|
||||||
Nz::Vector2f origin = GetContentOrigin();
|
|
||||||
Nz::Vector2f contentSize = GetContentSize();
|
|
||||||
|
|
||||||
m_entity->GetComponent<NodeComponent>().SetPosition(origin);
|
m_sprite->SetSize(GetSize());
|
||||||
m_sprite->SetSize(contentSize);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,22 +13,10 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
m_textSprite = Nz::TextSprite::New();
|
m_textSprite = Nz::TextSprite::New();
|
||||||
|
|
||||||
m_textEntity = CreateEntity(true);
|
m_textEntity = CreateEntity();
|
||||||
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
|
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
|
||||||
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
|
|
||||||
Layout();
|
Layout();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LabelWidget::Layout()
|
|
||||||
{
|
|
||||||
BaseWidget::Layout();
|
|
||||||
|
|
||||||
m_textEntity->GetComponent<NodeComponent>().SetPosition(GetContentOrigin());
|
|
||||||
}
|
|
||||||
|
|
||||||
void LabelWidget::ResizeToContent()
|
|
||||||
{
|
|
||||||
SetContentSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,11 +30,11 @@ namespace Ndk
|
||||||
SetBarColor(s_barColor, s_barCornerColor);
|
SetBarColor(s_barColor, s_barCornerColor);
|
||||||
|
|
||||||
|
|
||||||
m_borderEntity = CreateEntity(false);
|
m_borderEntity = CreateEntity();
|
||||||
m_borderEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_borderEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
m_borderEntity->AddComponent<GraphicsComponent>().Attach(m_borderSprite);
|
m_borderEntity->AddComponent<GraphicsComponent>().Attach(m_borderSprite);
|
||||||
|
|
||||||
m_barEntity = CreateEntity(true);
|
m_barEntity = CreateEntity();
|
||||||
m_barEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_barEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
GraphicsComponent& graphics = m_barEntity->AddComponent<GraphicsComponent>();
|
GraphicsComponent& graphics = m_barEntity->AddComponent<GraphicsComponent>();
|
||||||
|
|
||||||
|
|
@ -43,7 +43,7 @@ namespace Ndk
|
||||||
|
|
||||||
|
|
||||||
m_textSprite = Nz::TextSprite::New();
|
m_textSprite = Nz::TextSprite::New();
|
||||||
m_textEntity = CreateEntity(true);
|
m_textEntity = CreateEntity();
|
||||||
|
|
||||||
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
|
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
|
||||||
|
|
@ -76,8 +76,7 @@ namespace Ndk
|
||||||
|
|
||||||
void ProgressBarWidget::Layout()
|
void ProgressBarWidget::Layout()
|
||||||
{
|
{
|
||||||
Nz::Vector2f origin = GetContentOrigin();
|
Nz::Vector2f size = GetSize();
|
||||||
Nz::Vector2f size = GetContentSize();
|
|
||||||
Nz::Vector2f progressBarSize = size;
|
Nz::Vector2f progressBarSize = size;
|
||||||
|
|
||||||
if (IsTextEnabled())
|
if (IsTextEnabled())
|
||||||
|
|
@ -85,7 +84,7 @@ namespace Ndk
|
||||||
UpdateText();
|
UpdateText();
|
||||||
|
|
||||||
Nz::Vector3f textSize = m_textSprite->GetBoundingVolume().obb.localBox.GetLengths();
|
Nz::Vector3f textSize = m_textSprite->GetBoundingVolume().obb.localBox.GetLengths();
|
||||||
m_textEntity->GetComponent<NodeComponent>().SetPosition(origin.x + size.x - textSize.x, origin.y + size.y / 2.f - textSize.y);
|
m_textEntity->GetComponent<NodeComponent>().SetPosition(size.x - textSize.x, size.y / 2.f - textSize.y);
|
||||||
|
|
||||||
progressBarSize -= { textSize.x + m_textMargin, 0.f };
|
progressBarSize -= { textSize.x + m_textMargin, 0.f };
|
||||||
}
|
}
|
||||||
|
|
@ -96,7 +95,6 @@ namespace Ndk
|
||||||
m_barBackgroundSprite->SetSize(progressBarSize - (borderSize * 2.f));
|
m_barBackgroundSprite->SetSize(progressBarSize - (borderSize * 2.f));
|
||||||
m_barSprite->SetSize((progressBarSize.x - (borderSize.x * 2.f)) / 100.f * static_cast<float>(m_value), progressBarSize.y - (borderSize.y * 2.f));
|
m_barSprite->SetSize((progressBarSize.x - (borderSize.x * 2.f)) / 100.f * static_cast<float>(m_value), progressBarSize.y - (borderSize.y * 2.f));
|
||||||
|
|
||||||
m_borderEntity->GetComponent<NodeComponent>().SetPosition(origin.x, origin.y);
|
m_barEntity->GetComponent<NodeComponent>().SetPosition(borderSize.x, borderSize.y);
|
||||||
m_barEntity->GetComponent<NodeComponent>().SetPosition(origin.x + borderSize.x, origin.y + borderSize.y);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <NDK/Widgets/TextAreaWidget.hpp>
|
#include <NDK/Widgets/TextAreaWidget.hpp>
|
||||||
#include <Nazara/Core/Unicode.hpp>
|
#include <Nazara/Core/Unicode.hpp>
|
||||||
|
#include <Nazara/Utility/Font.hpp>
|
||||||
#include <NDK/Components/GraphicsComponent.hpp>
|
#include <NDK/Components/GraphicsComponent.hpp>
|
||||||
#include <NDK/Components/NodeComponent.hpp>
|
#include <NDK/Components/NodeComponent.hpp>
|
||||||
|
|
||||||
|
|
@ -11,28 +12,32 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
TextAreaWidget::TextAreaWidget(BaseWidget* parent) :
|
TextAreaWidget::TextAreaWidget(BaseWidget* parent) :
|
||||||
BaseWidget(parent),
|
BaseWidget(parent),
|
||||||
|
m_characterFilter(),
|
||||||
m_echoMode(EchoMode_Normal),
|
m_echoMode(EchoMode_Normal),
|
||||||
m_cursorPosition(0U, 0U),
|
m_cursorPositionBegin(0U, 0U),
|
||||||
|
m_cursorPositionEnd(0U, 0U),
|
||||||
|
m_isMouseButtonDown(false),
|
||||||
m_multiLineEnabled(false),
|
m_multiLineEnabled(false),
|
||||||
m_readOnly(false)
|
m_readOnly(false),
|
||||||
|
m_tabEnabled(false)
|
||||||
{
|
{
|
||||||
m_cursorSprite = Nz::Sprite::New();
|
m_cursorEntity = CreateEntity();
|
||||||
m_cursorSprite->SetColor(Nz::Color::Black);
|
m_cursorEntity->AddComponent<GraphicsComponent>();
|
||||||
m_cursorSprite->SetSize(1.f, float(m_drawer.GetFont()->GetSizeInfo(m_drawer.GetCharacterSize()).lineHeight));
|
|
||||||
|
|
||||||
m_cursorEntity = CreateEntity(true);
|
|
||||||
m_cursorEntity->AddComponent<GraphicsComponent>().Attach(m_cursorSprite, 10);
|
|
||||||
m_cursorEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_cursorEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
|
m_cursorEntity->GetComponent<NodeComponent>().SetPosition(5.f, 3.f);
|
||||||
m_cursorEntity->Enable(false);
|
m_cursorEntity->Enable(false);
|
||||||
|
|
||||||
m_textSprite = Nz::TextSprite::New();
|
m_textSprite = Nz::TextSprite::New();
|
||||||
|
|
||||||
m_textEntity = CreateEntity(true);
|
m_textEntity = CreateEntity();
|
||||||
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
|
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
|
||||||
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||||
|
m_textEntity->GetComponent<NodeComponent>().SetPosition(5.f, 3.f);
|
||||||
|
|
||||||
SetCursor(Nz::SystemCursor_Text);
|
SetCursor(Nz::SystemCursor_Text);
|
||||||
|
SetCharacterSize(GetCharacterSize()); //< Actualize minimum / preferred size
|
||||||
|
|
||||||
|
EnableBackground(true);
|
||||||
Layout();
|
Layout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -72,7 +77,44 @@ namespace Ndk
|
||||||
OnTextChanged(this, m_text);
|
OnTextChanged(this, m_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t TextAreaWidget::GetHoveredGlyph(float x, float y) const
|
void TextAreaWidget::Erase(std::size_t firstGlyph, std::size_t lastGlyph)
|
||||||
|
{
|
||||||
|
if (firstGlyph > lastGlyph)
|
||||||
|
std::swap(firstGlyph, lastGlyph);
|
||||||
|
|
||||||
|
std::size_t textLength = m_text.GetLength();
|
||||||
|
if (firstGlyph > textLength)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Nz::String newText;
|
||||||
|
if (firstGlyph > 0)
|
||||||
|
{
|
||||||
|
std::size_t characterPosition = m_text.GetCharacterPosition(firstGlyph - 1);
|
||||||
|
NazaraAssert(characterPosition != Nz::String::npos, "Invalid character position");
|
||||||
|
|
||||||
|
newText.Append(m_text.SubString(0, characterPosition));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastGlyph < textLength)
|
||||||
|
{
|
||||||
|
std::size_t characterPosition = m_text.GetCharacterPosition(lastGlyph);
|
||||||
|
NazaraAssert(characterPosition != Nz::String::npos, "Invalid character position");
|
||||||
|
|
||||||
|
newText.Append(m_text.SubString(characterPosition));
|
||||||
|
}
|
||||||
|
|
||||||
|
SetText(newText);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextAreaWidget::EraseSelection()
|
||||||
|
{
|
||||||
|
if (!HasSelection())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Erase(GetGlyphIndex(m_cursorPositionBegin), GetGlyphIndex(m_cursorPositionEnd));
|
||||||
|
}
|
||||||
|
|
||||||
|
Nz::Vector2ui TextAreaWidget::GetHoveredGlyph(float x, float y) const
|
||||||
{
|
{
|
||||||
std::size_t glyphCount = m_drawer.GetGlyphCount();
|
std::size_t glyphCount = m_drawer.GetGlyphCount();
|
||||||
if (glyphCount > 0)
|
if (glyphCount > 0)
|
||||||
|
|
@ -88,7 +130,8 @@ namespace Ndk
|
||||||
|
|
||||||
std::size_t upperLimit = (line != lineCount - 1) ? m_drawer.GetLine(line + 1).glyphIndex : glyphCount + 1;
|
std::size_t upperLimit = (line != lineCount - 1) ? m_drawer.GetLine(line + 1).glyphIndex : glyphCount + 1;
|
||||||
|
|
||||||
std::size_t i = m_drawer.GetLine(line).glyphIndex;
|
std::size_t firstLineGlyph = m_drawer.GetLine(line).glyphIndex;
|
||||||
|
std::size_t i = firstLineGlyph;
|
||||||
for (; i < upperLimit - 1; ++i)
|
for (; i < upperLimit - 1; ++i)
|
||||||
{
|
{
|
||||||
Nz::Rectf bounds = m_drawer.GetGlyph(i).bounds;
|
Nz::Rectf bounds = m_drawer.GetGlyph(i).bounds;
|
||||||
|
|
@ -96,32 +139,46 @@ namespace Ndk
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return Nz::Vector2ui(i - firstLineGlyph, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return Nz::Vector2ui::Zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextAreaWidget::ResizeToContent()
|
void TextAreaWidget::SetCharacterSize(unsigned int characterSize)
|
||||||
{
|
{
|
||||||
SetContentSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths()));
|
m_drawer.SetCharacterSize(characterSize);
|
||||||
|
|
||||||
|
std::size_t fontCount = m_drawer.GetFontCount();
|
||||||
|
unsigned int lineHeight = 0;
|
||||||
|
int spaceAdvance = 0;
|
||||||
|
for (std::size_t i = 0; i < fontCount; ++i)
|
||||||
|
{
|
||||||
|
Nz::Font* font = m_drawer.GetFont(i);
|
||||||
|
|
||||||
|
const Nz::Font::SizeInfo& sizeInfo = font->GetSizeInfo(characterSize);
|
||||||
|
lineHeight = std::max(lineHeight, sizeInfo.lineHeight);
|
||||||
|
spaceAdvance = std::max(spaceAdvance, sizeInfo.spaceAdvance);
|
||||||
|
}
|
||||||
|
|
||||||
|
Nz::Vector2f size = { float(spaceAdvance), float(lineHeight) + 5.f };
|
||||||
|
SetMinimumSize(size);
|
||||||
|
SetPreferredSize({ size.x * 6.f, size.y });
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextAreaWidget::Write(const Nz::String& text)
|
void TextAreaWidget::Write(const Nz::String& text, std::size_t glyphPosition)
|
||||||
{
|
{
|
||||||
std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition);
|
if (glyphPosition >= m_drawer.GetGlyphCount())
|
||||||
|
|
||||||
if (cursorGlyph >= m_drawer.GetGlyphCount())
|
|
||||||
{
|
{
|
||||||
AppendText(text);
|
AppendText(text);
|
||||||
SetCursorPosition(m_drawer.GetGlyphCount());
|
SetCursorPosition(m_drawer.GetGlyphCount());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_text.Insert(m_text.GetCharacterPosition(cursorGlyph), text);
|
m_text.Insert(m_text.GetCharacterPosition(glyphPosition), text);
|
||||||
SetText(m_text);
|
SetText(m_text);
|
||||||
|
|
||||||
SetCursorPosition(cursorGlyph + text.GetLength());
|
SetCursorPosition(glyphPosition + text.GetLength());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,8 +186,6 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
BaseWidget::Layout();
|
BaseWidget::Layout();
|
||||||
|
|
||||||
m_textEntity->GetComponent<NodeComponent>().SetPosition(GetContentOrigin());
|
|
||||||
|
|
||||||
RefreshCursor();
|
RefreshCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -156,20 +211,11 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
case Nz::Keyboard::Delete:
|
case Nz::Keyboard::Delete:
|
||||||
{
|
{
|
||||||
std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition);
|
if (HasSelection())
|
||||||
|
EraseSelection();
|
||||||
|
else
|
||||||
|
Erase(GetGlyphIndex(m_cursorPositionBegin));
|
||||||
|
|
||||||
std::size_t textLength = m_text.GetLength();
|
|
||||||
if (cursorGlyph > textLength)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
Nz::String newText;
|
|
||||||
if (cursorGlyph > 0)
|
|
||||||
newText.Append(m_text.SubString(0, m_text.GetCharacterPosition(cursorGlyph) - 1));
|
|
||||||
|
|
||||||
if (cursorGlyph < textLength)
|
|
||||||
newText.Append(m_text.SubString(m_text.GetCharacterPosition(cursorGlyph + 1)));
|
|
||||||
|
|
||||||
SetText(newText);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -181,10 +227,42 @@ namespace Ndk
|
||||||
if (ignoreDefaultAction)
|
if (ignoreDefaultAction)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (HasSelection())
|
||||||
|
SetCursorPosition(m_cursorPositionEnd);
|
||||||
|
|
||||||
MoveCursor({0, 1});
|
MoveCursor({0, 1});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Nz::Keyboard::End:
|
||||||
|
{
|
||||||
|
bool ignoreDefaultAction = false;
|
||||||
|
OnTextAreaKeyEnd(this, &ignoreDefaultAction);
|
||||||
|
|
||||||
|
if (ignoreDefaultAction)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
std::size_t lineCount = m_drawer.GetLineCount();
|
||||||
|
if (key.control && lineCount > 0)
|
||||||
|
SetCursorPosition({ static_cast<unsigned int>(m_drawer.GetLineGlyphCount(lineCount - 1)), static_cast<unsigned int>(lineCount - 1) });
|
||||||
|
else
|
||||||
|
SetCursorPosition({ static_cast<unsigned int>(m_drawer.GetLineGlyphCount(m_cursorPositionEnd.y)), m_cursorPositionEnd.y });
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Nz::Keyboard::Home:
|
||||||
|
{
|
||||||
|
bool ignoreDefaultAction = false;
|
||||||
|
OnTextAreaKeyHome(this, &ignoreDefaultAction);
|
||||||
|
|
||||||
|
if (ignoreDefaultAction)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
SetCursorPosition({ 0U, key.control ? 0U : m_cursorPositionEnd.y });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
case Nz::Keyboard::Left:
|
case Nz::Keyboard::Left:
|
||||||
{
|
{
|
||||||
bool ignoreDefaultAction = false;
|
bool ignoreDefaultAction = false;
|
||||||
|
|
@ -193,7 +271,33 @@ namespace Ndk
|
||||||
if (ignoreDefaultAction)
|
if (ignoreDefaultAction)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
MoveCursor(-1);
|
if (HasSelection())
|
||||||
|
SetCursorPosition(m_cursorPositionBegin);
|
||||||
|
else if (key.control)
|
||||||
|
{
|
||||||
|
std::size_t index = GetGlyphIndex(m_cursorPositionBegin);
|
||||||
|
|
||||||
|
if (index == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
std::size_t spaceIndex = m_text.FindLast(' ', index - 2);
|
||||||
|
std::size_t endlIndex = m_text.FindLast('\n', index - 1);
|
||||||
|
|
||||||
|
if ((spaceIndex > endlIndex || endlIndex == Nz::String::npos) && spaceIndex != Nz::String::npos)
|
||||||
|
SetCursorPosition(spaceIndex + 1);
|
||||||
|
else if (endlIndex != Nz::String::npos)
|
||||||
|
{
|
||||||
|
if (index == endlIndex + 1)
|
||||||
|
SetCursorPosition(endlIndex);
|
||||||
|
else
|
||||||
|
SetCursorPosition(endlIndex + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SetCursorPosition({ 0U, m_cursorPositionBegin.y });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
MoveCursor(-1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,7 +309,34 @@ namespace Ndk
|
||||||
if (ignoreDefaultAction)
|
if (ignoreDefaultAction)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
MoveCursor(1);
|
if (HasSelection())
|
||||||
|
SetCursorPosition(m_cursorPositionEnd);
|
||||||
|
else if (key.control)
|
||||||
|
{
|
||||||
|
std::size_t index = GetGlyphIndex(m_cursorPositionEnd);
|
||||||
|
std::size_t spaceIndex = m_text.Find(' ', index);
|
||||||
|
std::size_t endlIndex = m_text.Find('\n', index);
|
||||||
|
|
||||||
|
if (spaceIndex < endlIndex && spaceIndex != Nz::String::npos)
|
||||||
|
{
|
||||||
|
if (m_text.GetSize() > spaceIndex)
|
||||||
|
SetCursorPosition(spaceIndex + 1);
|
||||||
|
else
|
||||||
|
SetCursorPosition({ static_cast<unsigned int>(m_drawer.GetLineGlyphCount(m_cursorPositionEnd.y)), m_cursorPositionEnd.y });
|
||||||
|
}
|
||||||
|
else if (endlIndex != Nz::String::npos)
|
||||||
|
{
|
||||||
|
if (index == endlIndex)
|
||||||
|
SetCursorPosition(endlIndex + 1);
|
||||||
|
else
|
||||||
|
SetCursorPosition(endlIndex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SetCursorPosition({ static_cast<unsigned int>(m_drawer.GetLineGlyphCount(m_cursorPositionEnd.y)), m_cursorPositionEnd.y });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
MoveCursor(1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -217,10 +348,65 @@ namespace Ndk
|
||||||
if (ignoreDefaultAction)
|
if (ignoreDefaultAction)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (HasSelection())
|
||||||
|
SetCursorPosition(m_cursorPositionBegin);
|
||||||
|
|
||||||
MoveCursor({0, -1});
|
MoveCursor({0, -1});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Nz::Keyboard::Tab:
|
||||||
|
{
|
||||||
|
if (!m_tabEnabled)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (HasSelection())
|
||||||
|
{
|
||||||
|
for(unsigned line = m_cursorPositionBegin.y; line <= m_cursorPositionEnd.y; ++line)
|
||||||
|
{
|
||||||
|
const Nz::Vector2ui cursorPositionBegin = m_cursorPositionBegin;
|
||||||
|
const Nz::Vector2ui cursorPositionEnd = m_cursorPositionEnd;
|
||||||
|
|
||||||
|
if (key.shift)
|
||||||
|
{
|
||||||
|
if (m_drawer.GetLineGlyphCount(line) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::size_t firstGlyph = GetGlyphIndex({ 0U, line });
|
||||||
|
|
||||||
|
if (m_text[m_text.GetCharacterPosition(firstGlyph)] == '\t')
|
||||||
|
{
|
||||||
|
Erase(firstGlyph);
|
||||||
|
SetSelection(cursorPositionBegin - (cursorPositionBegin.y == line && cursorPositionBegin.x != 0U ? Nz::Vector2ui { 1U, 0U } : Nz::Vector2ui {}),
|
||||||
|
cursorPositionEnd - (cursorPositionEnd.y == line && cursorPositionEnd.x != 0U ? Nz::Vector2ui { 1U, 0U } : Nz::Vector2ui {}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Write(Nz::String('\t'), { 0U, line });
|
||||||
|
SetSelection(cursorPositionBegin + (cursorPositionBegin.y == line && cursorPositionBegin.x != 0U ? Nz::Vector2ui { 1U, 0U } : Nz::Vector2ui {}),
|
||||||
|
cursorPositionEnd + (cursorPositionEnd.y == line ? Nz::Vector2ui { 1U, 0U } : Nz::Vector2ui {}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (key.shift)
|
||||||
|
{
|
||||||
|
std::size_t currentGlyph = GetGlyphIndex(m_cursorPositionBegin);
|
||||||
|
|
||||||
|
if (currentGlyph > 0 && m_text[m_text.GetCharacterPosition(currentGlyph - 1U)] == '\t') // Check if previous glyph is a tab
|
||||||
|
{
|
||||||
|
Erase(currentGlyph - 1U);
|
||||||
|
|
||||||
|
if (m_cursorPositionBegin.x < static_cast<unsigned int>(m_drawer.GetLineGlyphCount(m_cursorPositionBegin.y)))
|
||||||
|
MoveCursor(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Write(Nz::String('\t'));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -236,11 +422,39 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
SetFocus();
|
SetFocus();
|
||||||
|
|
||||||
const Padding& padding = GetPadding();
|
Nz::Vector2ui hoveredGlyph = GetHoveredGlyph(float(x) - 5.f, float(y) - 5.f);
|
||||||
SetCursorPosition(GetHoveredGlyph(float(x - padding.left), float(y - padding.top)));
|
|
||||||
|
// Shift extends selection
|
||||||
|
if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::LShift) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::RShift))
|
||||||
|
SetSelection(hoveredGlyph, m_selectionCursor);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetCursorPosition(hoveredGlyph);
|
||||||
|
m_selectionCursor = m_cursorPositionBegin;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_isMouseButtonDown = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextAreaWidget::OnMouseButtonRelease(int, int, Nz::Mouse::Button button)
|
||||||
|
{
|
||||||
|
if (button == Nz::Mouse::Left)
|
||||||
|
m_isMouseButtonDown = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextAreaWidget::OnMouseEnter()
|
||||||
|
{
|
||||||
|
if (!Nz::Mouse::IsButtonPressed(Nz::Mouse::Left))
|
||||||
|
m_isMouseButtonDown = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextAreaWidget::OnMouseMoved(int x, int y, int deltaX, int deltaY)
|
||||||
|
{
|
||||||
|
if (m_isMouseButtonDown)
|
||||||
|
SetSelection(m_selectionCursor, GetHoveredGlyph(float(x) - 5.f, float(y) - 3.f));
|
||||||
|
}
|
||||||
|
|
||||||
void TextAreaWidget::OnTextEntered(char32_t character, bool /*repeated*/)
|
void TextAreaWidget::OnTextEntered(char32_t character, bool /*repeated*/)
|
||||||
{
|
{
|
||||||
if (m_readOnly)
|
if (m_readOnly)
|
||||||
|
|
@ -253,20 +467,30 @@ namespace Ndk
|
||||||
bool ignoreDefaultAction = false;
|
bool ignoreDefaultAction = false;
|
||||||
OnTextAreaKeyBackspace(this, &ignoreDefaultAction);
|
OnTextAreaKeyBackspace(this, &ignoreDefaultAction);
|
||||||
|
|
||||||
std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition);
|
std::size_t cursorGlyphBegin = GetGlyphIndex(m_cursorPositionBegin);
|
||||||
if (ignoreDefaultAction || cursorGlyph == 0)
|
std::size_t cursorGlyphEnd = GetGlyphIndex(m_cursorPositionEnd);
|
||||||
|
|
||||||
|
if (ignoreDefaultAction || cursorGlyphEnd == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
Nz::String newText;
|
// When a text is selected, delete key does the same as delete and leave the character behind it
|
||||||
|
if (HasSelection())
|
||||||
|
EraseSelection();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Nz::String newText;
|
||||||
|
|
||||||
if (cursorGlyph > 1)
|
if (cursorGlyphBegin > 1)
|
||||||
newText.Append(m_text.SubString(0, m_text.GetCharacterPosition(cursorGlyph - 1) - 1));
|
newText.Append(m_text.SubString(0, m_text.GetCharacterPosition(cursorGlyphBegin - 1) - 1));
|
||||||
|
|
||||||
if (cursorGlyph < m_text.GetLength())
|
if (cursorGlyphEnd < m_text.GetLength())
|
||||||
newText.Append(m_text.SubString(m_text.GetCharacterPosition(cursorGlyph)));
|
newText.Append(m_text.SubString(m_text.GetCharacterPosition(cursorGlyphEnd)));
|
||||||
|
|
||||||
MoveCursor(-1);
|
// Move cursor before setting text (to prevent SetText to move our cursor)
|
||||||
SetText(newText);
|
MoveCursor(-1);
|
||||||
|
|
||||||
|
SetText(newText);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -279,15 +503,21 @@ namespace Ndk
|
||||||
if (ignoreDefaultAction || !m_multiLineEnabled)
|
if (ignoreDefaultAction || !m_multiLineEnabled)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (HasSelection())
|
||||||
|
EraseSelection();
|
||||||
|
|
||||||
Write(Nz::String('\n'));
|
Write(Nz::String('\n'));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
if (Nz::Unicode::GetCategory(character) == Nz::Unicode::Category_Other_Control)
|
if (Nz::Unicode::GetCategory(character) == Nz::Unicode::Category_Other_Control || (m_characterFilter && !m_characterFilter(character)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (HasSelection())
|
||||||
|
EraseSelection();
|
||||||
|
|
||||||
Write(Nz::String::Unicode(character));
|
Write(Nz::String::Unicode(character));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -299,24 +529,66 @@ namespace Ndk
|
||||||
if (m_readOnly)
|
if (m_readOnly)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto& lineInfo = m_drawer.GetLine(m_cursorPosition.y);
|
std::size_t selectionLineCount = m_cursorPositionEnd.y - m_cursorPositionBegin.y + 1;
|
||||||
std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition);
|
std::size_t oldSpriteCount = m_cursorSprites.size();
|
||||||
|
if (m_cursorSprites.size() != selectionLineCount)
|
||||||
std::size_t glyphCount = m_drawer.GetGlyphCount();
|
|
||||||
float position;
|
|
||||||
if (glyphCount > 0 && lineInfo.glyphIndex < cursorGlyph)
|
|
||||||
{
|
{
|
||||||
const auto& glyph = m_drawer.GetGlyph(std::min(cursorGlyph, glyphCount - 1));
|
m_cursorSprites.resize(m_cursorPositionEnd.y - m_cursorPositionBegin.y + 1);
|
||||||
position = glyph.bounds.x;
|
for (std::size_t i = oldSpriteCount; i < m_cursorSprites.size(); ++i)
|
||||||
if (cursorGlyph >= glyphCount)
|
{
|
||||||
position += glyph.bounds.width;
|
m_cursorSprites[i] = Nz::Sprite::New();
|
||||||
|
m_cursorSprites[i]->SetMaterial(Nz::Material::New("Translucent2D"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
position = 0.f;
|
|
||||||
|
|
||||||
Nz::Vector2f contentOrigin = GetContentOrigin();
|
float lineHeight = float(m_drawer.GetFont()->GetSizeInfo(m_drawer.GetCharacterSize()).lineHeight);
|
||||||
|
|
||||||
m_cursorEntity->GetComponent<NodeComponent>().SetPosition(contentOrigin.x + position, contentOrigin.y + lineInfo.bounds.y);
|
GraphicsComponent& gfxComponent = m_cursorEntity->GetComponent<GraphicsComponent>();
|
||||||
|
gfxComponent.Clear();
|
||||||
|
|
||||||
|
for (unsigned int i = m_cursorPositionBegin.y; i <= m_cursorPositionEnd.y; ++i)
|
||||||
|
{
|
||||||
|
const auto& lineInfo = m_drawer.GetLine(i);
|
||||||
|
|
||||||
|
Nz::SpriteRef& cursorSprite = m_cursorSprites[i - m_cursorPositionBegin.y];
|
||||||
|
if (i == m_cursorPositionBegin.y || i == m_cursorPositionEnd.y)
|
||||||
|
{
|
||||||
|
auto GetGlyphPos = [&](unsigned int localGlyphPos)
|
||||||
|
{
|
||||||
|
std::size_t cursorGlyph = GetGlyphIndex({ localGlyphPos, i });
|
||||||
|
|
||||||
|
std::size_t glyphCount = m_drawer.GetGlyphCount();
|
||||||
|
float position;
|
||||||
|
if (glyphCount > 0 && lineInfo.glyphIndex < cursorGlyph)
|
||||||
|
{
|
||||||
|
const auto& glyph = m_drawer.GetGlyph(std::min(cursorGlyph, glyphCount - 1));
|
||||||
|
position = glyph.bounds.x;
|
||||||
|
if (cursorGlyph >= glyphCount)
|
||||||
|
position += glyph.bounds.width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
position = 0.f;
|
||||||
|
|
||||||
|
return position;
|
||||||
|
};
|
||||||
|
|
||||||
|
float beginX = (i == m_cursorPositionBegin.y) ? GetGlyphPos(m_cursorPositionBegin.x) : 0.f;
|
||||||
|
float endX = (i == m_cursorPositionEnd.y) ? GetGlyphPos(m_cursorPositionEnd.x) : lineInfo.bounds.width;
|
||||||
|
float spriteSize = std::max(endX - beginX, 1.f);
|
||||||
|
|
||||||
|
cursorSprite->SetColor((m_cursorPositionBegin == m_cursorPositionEnd) ? Nz::Color::Black : Nz::Color(0, 0, 0, 50));
|
||||||
|
cursorSprite->SetSize(spriteSize, float(m_drawer.GetFont()->GetSizeInfo(m_drawer.GetCharacterSize()).lineHeight));
|
||||||
|
|
||||||
|
gfxComponent.Attach(cursorSprite, Nz::Matrix4f::Translate({ beginX, lineInfo.bounds.y, 0.f }));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cursorSprite->SetColor(Nz::Color(0, 0, 0, 50));
|
||||||
|
cursorSprite->SetSize(lineInfo.bounds.width, float(m_drawer.GetFont()->GetSizeInfo(m_drawer.GetCharacterSize()).lineHeight));
|
||||||
|
|
||||||
|
gfxComponent.Attach(cursorSprite, Nz::Matrix4f::Translate({ 0.f, lineInfo.bounds.y, 0.f }));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextAreaWidget::UpdateDisplayText()
|
void TextAreaWidget::UpdateDisplayText()
|
||||||
|
|
@ -335,6 +607,6 @@ namespace Ndk
|
||||||
|
|
||||||
m_textSprite->Update(m_drawer);
|
m_textSprite->Update(m_drawer);
|
||||||
|
|
||||||
SetCursorPosition(m_cursorPosition); //< Refresh cursor position (prevent it from being outside of the text)
|
SetCursorPosition(m_cursorPositionBegin); //< Refresh cursor position (prevent it from being outside of the text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include <NDK/Systems/VelocitySystem.hpp>
|
#include <NDK/Systems/VelocitySystem.hpp>
|
||||||
|
|
||||||
#ifndef NDK_SERVER
|
#ifndef NDK_SERVER
|
||||||
|
#include <NDK/Systems/DebugSystem.hpp>
|
||||||
#include <NDK/Systems/ListenerSystem.hpp>
|
#include <NDK/Systems/ListenerSystem.hpp>
|
||||||
#include <NDK/Systems/ParticleSystem.hpp>
|
#include <NDK/Systems/ParticleSystem.hpp>
|
||||||
#include <NDK/Systems/RenderSystem.hpp>
|
#include <NDK/Systems/RenderSystem.hpp>
|
||||||
|
|
@ -47,6 +48,7 @@ namespace Ndk
|
||||||
AddSystem<VelocitySystem>();
|
AddSystem<VelocitySystem>();
|
||||||
|
|
||||||
#ifndef NDK_SERVER
|
#ifndef NDK_SERVER
|
||||||
|
AddSystem<DebugSystem>();
|
||||||
AddSystem<ListenerSystem>();
|
AddSystem<ListenerSystem>();
|
||||||
AddSystem<ParticleSystem>();
|
AddSystem<ParticleSystem>();
|
||||||
AddSystem<RenderSystem>();
|
AddSystem<RenderSystem>();
|
||||||
|
|
|
||||||
10
appveyor.yml
10
appveyor.yml
|
|
@ -17,11 +17,11 @@ skip_commits:
|
||||||
- NazaraModuleTemplate/*
|
- NazaraModuleTemplate/*
|
||||||
|
|
||||||
os:
|
os:
|
||||||
- Visual Studio 2015
|
- Visual Studio 2017
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- TOOLSET: vs2015
|
- TOOLSET: vs2017
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- cd build && "./premake5.exe" %TOOLSET% && cd ..
|
- cd build && "./premake5.exe" %TOOLSET% && cd ..
|
||||||
|
|
@ -41,9 +41,9 @@ after_build:
|
||||||
- cd build && "./premake5.exe" package && cd ../package
|
- cd build && "./premake5.exe" package && cd ../package
|
||||||
- 7z a NazaraEngine.7z * && cd ..
|
- 7z a NazaraEngine.7z * && cd ..
|
||||||
|
|
||||||
#artifacts:
|
artifacts:
|
||||||
# - path: package/NazaraEngine.7z
|
- path: package/NazaraEngine.7z
|
||||||
# name: 'NazaraEngine-$(CONFIGURATION)-$(PLATFORM)-$(APPVEYOR_REPO_COMMIT)'
|
name: 'NazaraEngine-$(CONFIGURATION)-$(PLATFORM)-$(APPVEYOR_REPO_COMMIT)'
|
||||||
|
|
||||||
on_success:
|
on_success:
|
||||||
- cd tests && "./NazaraUnitTestsServer.exe"
|
- cd tests && "./NazaraUnitTestsServer.exe"
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
premake5 codeblocks
|
.\premake5.exe codeblocks
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
premake5 codelite
|
.\premake5.exe codelite
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
premake5 vs2015
|
.\premake5.exe vs2015
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
premake5 vs2017
|
.\premake5.exe vs2017
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
premake5 encoderesources
|
.\premake5.exe encoderesources
|
||||||
pause
|
pause
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
premake5 generateheaders
|
.\premake5.exe generateheaders
|
||||||
pause
|
pause
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
premake5 parseunicode
|
.\premake5.exe parseunicode
|
||||||
pause
|
pause
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
premake5 package
|
.\premake5.exe package
|
||||||
pause
|
pause
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
premake5 --pack-libdir=msvc package
|
.\premake5.exe --pack-libdir=msvc package
|
||||||
pause
|
pause
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
premake5 --pack-libdir=mingw package
|
.\premake5.exe --pack-libdir=mingw package
|
||||||
pause
|
pause
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
newoption({
|
newoption({
|
||||||
trigger = "pack-libdir",
|
trigger = "pack-libdir",
|
||||||
description = "Specifiy the subdirectory in lib/ to be used when packaging the project"
|
description = "Specifies the subdirectory in lib/ to be used when packaging the project"
|
||||||
})
|
})
|
||||||
|
|
||||||
ACTION.Name = "Package"
|
ACTION.Name = "Package"
|
||||||
|
|
|
||||||
|
|
@ -48,15 +48,19 @@ local DirectionToString = {}
|
||||||
DirectionToString["EN"] = "Direction_European_Number"
|
DirectionToString["EN"] = "Direction_European_Number"
|
||||||
DirectionToString["ES"] = "Direction_European_Separator"
|
DirectionToString["ES"] = "Direction_European_Separator"
|
||||||
DirectionToString["ET"] = "Direction_European_Terminator"
|
DirectionToString["ET"] = "Direction_European_Terminator"
|
||||||
|
DirectionToString["FSI"] = "Direction_First_Strong_Isolate"
|
||||||
DirectionToString["L"] = "Direction_Left_To_Right"
|
DirectionToString["L"] = "Direction_Left_To_Right"
|
||||||
DirectionToString["LRE"] = "Direction_Left_To_Right_Embedding"
|
DirectionToString["LRE"] = "Direction_Left_To_Right_Embedding"
|
||||||
|
DirectionToString["LRI"] = "Direction_Left_To_Right_Isolate"
|
||||||
DirectionToString["LRO"] = "Direction_Left_To_Right_Override"
|
DirectionToString["LRO"] = "Direction_Left_To_Right_Override"
|
||||||
DirectionToString["NSM"] = "Direction_Nonspacing_Mark"
|
DirectionToString["NSM"] = "Direction_Nonspacing_Mark"
|
||||||
DirectionToString["ON"] = "Direction_Other_Neutral"
|
DirectionToString["ON"] = "Direction_Other_Neutral"
|
||||||
DirectionToString["B"] = "Direction_Paragraph_Separator"
|
DirectionToString["B"] = "Direction_Paragraph_Separator"
|
||||||
DirectionToString["PDF"] = "Direction_Pop_Directional_Format"
|
DirectionToString["PDF"] = "Direction_Pop_Directional_Formatting"
|
||||||
|
DirectionToString["PDI"] = "Direction_Pop_Directional_Isolate"
|
||||||
DirectionToString["R"] = "Direction_Right_To_Left"
|
DirectionToString["R"] = "Direction_Right_To_Left"
|
||||||
DirectionToString["RLE"] = "Direction_Right_To_Left_Embedding"
|
DirectionToString["RLE"] = "Direction_Right_To_Left_Embedding"
|
||||||
|
DirectionToString["RLI"] = "Direction_Right_To_Left_Isolate"
|
||||||
DirectionToString["RLO"] = "Direction_Right_To_Left_Override"
|
DirectionToString["RLO"] = "Direction_Right_To_Left_Override"
|
||||||
DirectionToString["S"] = "Direction_Segment_Separator"
|
DirectionToString["S"] = "Direction_Segment_Separator"
|
||||||
DirectionToString["WS"] = "Direction_White_Space"
|
DirectionToString["WS"] = "Direction_White_Space"
|
||||||
|
|
@ -83,112 +87,179 @@ end
|
||||||
|
|
||||||
ACTION.Function = function ()
|
ACTION.Function = function ()
|
||||||
local unicodeSet = {}
|
local unicodeSet = {}
|
||||||
|
if (not os.isdir("scripts/data") and not os.mkdir("scripts/data")) then
|
||||||
|
print("Failed to create scripts/data folder")
|
||||||
|
end
|
||||||
|
|
||||||
file = io.open ("scripts/data/UnicodeData.txt", "r")
|
local filepath = "scripts/data/UnicodeData.txt"
|
||||||
|
|
||||||
|
print("Downloading UnicodeData.txt...")
|
||||||
|
|
||||||
|
local t1 = os.clock()
|
||||||
|
|
||||||
|
local result_str, response_code = http.download("https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt", filepath, {
|
||||||
|
headers = { "From: Premake", "Referer: Premake" }
|
||||||
|
})
|
||||||
|
|
||||||
|
if (response_code ~= 200) then
|
||||||
|
error("Failed to download UnicodeData.txt")
|
||||||
|
end
|
||||||
|
|
||||||
|
local fileInfo = os.stat(filepath)
|
||||||
|
|
||||||
|
local t2 = os.clock()
|
||||||
|
|
||||||
|
print(string.format("Download succeeded (%.3f MiB) in %fs (%d KiB/s)", fileInfo.size / (1024 * 1024), t2 - t1, math.floor((fileInfo.size / (t2 - t1)) / 1024)))
|
||||||
|
|
||||||
|
file = io.open (filepath, "r")
|
||||||
if (not file) then
|
if (not file) then
|
||||||
error("Unable to open Unicode Data file")
|
error("Unable to open Unicode Data file")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local t1 = os.clock()
|
local characters = {}
|
||||||
|
local characterSets = {}
|
||||||
|
local lowercaseCharacters = {}
|
||||||
|
local titlecaseCharacters = {}
|
||||||
|
local uppercaseCharacters = {}
|
||||||
|
local currentBlock
|
||||||
|
local currentBlockStartCodepoint
|
||||||
|
local lineIndex = 1
|
||||||
|
|
||||||
|
t1 = os.clock()
|
||||||
|
|
||||||
print("Parsing UnicodeData.txt...")
|
print("Parsing UnicodeData.txt...")
|
||||||
local first = 0
|
|
||||||
local last = 0
|
|
||||||
unicodeSet[0] = {}
|
|
||||||
unicodeSet[0].First = 0
|
|
||||||
unicodeSet[0].Characters = {}
|
|
||||||
local currentSet = 0
|
|
||||||
local inblock = false
|
|
||||||
local blockData = nil
|
|
||||||
local unusedIndex = 0
|
|
||||||
local c = 0
|
|
||||||
for line in file:lines() do
|
for line in file:lines() do
|
||||||
local old = 0
|
local parts = line:explode(";")
|
||||||
local start = string.find(line, ';', old)
|
|
||||||
local tab = {}
|
|
||||||
while (start) do
|
|
||||||
tab[#tab+1] = string.sub(line, old, start-1, old)
|
|
||||||
old = start+1
|
|
||||||
start = string.find(line, ';', old)
|
|
||||||
end
|
|
||||||
tab[#tab+1] = string.sub(line, old)
|
|
||||||
|
|
||||||
local index = tonumber(tab[1], 16)
|
local codepoint = tonumber(parts[1], 16)
|
||||||
if (index > 0 and not inblock) then
|
local characterName = parts[2]
|
||||||
if (index-last > 1000) then
|
local category = parts[3]
|
||||||
unicodeSet[currentSet].Last = last
|
local direction = parts[5]
|
||||||
currentSet = currentSet + 1
|
local uppercaseMapping = tonumber(parts[13], 16)
|
||||||
unicodeSet[currentSet] = {}
|
local lowercaseMapping = tonumber(parts[14], 16)
|
||||||
unicodeSet[currentSet].First = index
|
local titlecaseMapping = tonumber(parts[15], 16)
|
||||||
unicodeSet[currentSet].Characters = {}
|
|
||||||
print("Set detected (Begin at " .. first .. ", end at " .. last .. ")")
|
local blockName, blockId = string.match(characterName, "<(.+), (%w+)>")
|
||||||
first = index
|
if (currentBlock) then
|
||||||
|
if (blockId ~= "Last") then
|
||||||
|
error("Parsing error: expected last block at line " .. lineIndex)
|
||||||
|
end
|
||||||
|
|
||||||
|
print("Detected set " .. blockName .. " from codepoint " .. currentBlockStartCodepoint .. " to " .. codepoint)
|
||||||
|
|
||||||
|
table.insert(characterSets, {
|
||||||
|
startCodepoint = currentBlockStartCodepoint,
|
||||||
|
endCodepoint = codepoint,
|
||||||
|
name = "<" .. blockName .. ">",
|
||||||
|
category = category,
|
||||||
|
direction = direction
|
||||||
|
})
|
||||||
|
|
||||||
|
currentBlock = nil
|
||||||
|
else
|
||||||
|
if (blockName) then
|
||||||
|
if (blockId ~= "First") then
|
||||||
|
error("Parsing error: expected first block at line " .. lineIndex)
|
||||||
|
end
|
||||||
|
|
||||||
|
currentBlock = blockName
|
||||||
|
currentBlockStartCodepoint = codepoint
|
||||||
else
|
else
|
||||||
unusedIndex = unusedIndex + index-last-1
|
table.insert(characters, {
|
||||||
end
|
codepoint = codepoint,
|
||||||
end
|
name = characterName,
|
||||||
|
category = category,
|
||||||
|
direction = direction,
|
||||||
|
upper = uppercaseMapping,
|
||||||
|
lower = lowercaseMapping,
|
||||||
|
title = titlecaseMapping
|
||||||
|
})
|
||||||
|
|
||||||
local blockName, blockId = string.match(tab[2], "<(.+), (%w+)>")
|
if (lowercaseMapping) then
|
||||||
if (blockName ~= nil and blockId ~= nil) then
|
table.insert(lowercaseCharacters, {codepoint = codepoint, lower = lowercaseMapping})
|
||||||
if (blockId == "First") then
|
|
||||||
if (inblock) then
|
|
||||||
error("Already in block (" .. tab[1] .. ")")
|
|
||||||
end
|
end
|
||||||
inblock = true
|
|
||||||
blockCharacter = getCharacter(tab, first)
|
if (titlecaseMapping) then
|
||||||
elseif (blockId == "Last") then
|
table.insert(titlecaseCharacters, {codepoint = codepoint, title = titlecaseMapping})
|
||||||
if (not inblock) then
|
|
||||||
error("Not in block (" .. tab[1] .. ")")
|
|
||||||
end
|
end
|
||||||
inblock = false
|
|
||||||
for i=first, index do
|
if (uppercaseMapping) then
|
||||||
unicodeSet[currentSet].Characters[i] = getCharacter(tab, first, i)
|
table.insert(uppercaseCharacters, {codepoint = codepoint, upper = uppercaseMapping})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
unicodeSet[currentSet].Characters[index - first] = getCharacter(tab, first, index)
|
lineIndex = lineIndex + 1
|
||||||
if (unicodeSet[currentSet].Characters[index - first].LowerCase ~= (index - first) or
|
|
||||||
unicodeSet[currentSet].Characters[index - first].UpperCase ~= (index - first) or
|
|
||||||
unicodeSet[currentSet].Characters[index - first].TitleCase ~= (index - first)) then
|
|
||||||
c = c + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
last = index
|
|
||||||
end
|
end
|
||||||
unicodeSet[currentSet].Last = last
|
|
||||||
print("Set detected (Begin at " .. first .. ", end at " .. last .. ")")
|
|
||||||
file:close()
|
|
||||||
|
|
||||||
print("Parsed " .. last+1 .. " characters in " .. #unicodeSet .. " sets, " .. unusedIndex .. " unused indices (took " .. os.difftime(os.clock(), t1) .. " sec)")
|
t2 = os.clock()
|
||||||
|
|
||||||
file = io.open("../src/Nazara/Core/UnicodeData.hpp", "w+")
|
print("Parsed " .. #characters .. " characters in " .. (t2 - t1) .. " seconds")
|
||||||
if (not file) then
|
|
||||||
error("Unable to create Unicode Data header")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
print("Writting Unicode Data to header...")
|
print("Writting Unicode Data to header...")
|
||||||
|
|
||||||
t1 = os.clock()
|
file = io.open("../src/Nazara/Core/UnicodeData.hpp", "w+")
|
||||||
for i=0, #unicodeSet do
|
if (not file) then
|
||||||
local maxn = table.maxn(unicodeSet[i].Characters)
|
error("Failed to open Unicode Data header")
|
||||||
file:write(string.format("Character unicodeSet%d[%d] = {\n", i, maxn+1))
|
return
|
||||||
|
end
|
||||||
|
|
||||||
for j=0, maxn do
|
t1 = os.clock()
|
||||||
local v = unicodeSet[i].Characters[j]
|
|
||||||
if (v) then
|
file:write(string.format("UnicodeCharacter unicodeCharacters[%d] = {\n", #characters))
|
||||||
file:write(string.format("\t{%s,%s,%d,%d,%d},\n", v.Category, v.Direction, v.LowerCase, v.TitleCase, v.UpperCase))
|
|
||||||
else
|
for _, data in pairs(characters) do
|
||||||
file:write(string.format("\t{Category_NoCategory,Direction_Boundary_Neutral,%d,%d,%d},\n", j, j, j))
|
local category = CategoryToString[data.category]
|
||||||
end
|
if (not category) then
|
||||||
|
error("Unknown category " .. data.category .. " for character " .. data.codepoint)
|
||||||
end
|
end
|
||||||
|
|
||||||
file:write("};\n\n")
|
local direction = DirectionToString[data.direction]
|
||||||
|
if (not direction) then
|
||||||
|
error("Unknown direction " .. data.direction .. " for character " .. data.codepoint)
|
||||||
|
end
|
||||||
|
|
||||||
|
file:write(string.format("\t{%d, Unicode::%s, Unicode::%s},\n", data.codepoint, category, direction))
|
||||||
end
|
end
|
||||||
|
file:write("};\n\n")
|
||||||
|
|
||||||
|
file:write(string.format("UnicodeSet unicodeSets[%d] = {\n", #characterSets))
|
||||||
|
|
||||||
|
for _, data in pairs(characterSets) do
|
||||||
|
local category = CategoryToString[data.category]
|
||||||
|
if (not category) then
|
||||||
|
error("Unknown category " .. data.category .. " for character " .. data.codepoint)
|
||||||
|
end
|
||||||
|
|
||||||
|
local direction = DirectionToString[data.direction]
|
||||||
|
if (not direction) then
|
||||||
|
error("Unknown direction " .. data.direction .. " for character " .. data.codepoint)
|
||||||
|
end
|
||||||
|
|
||||||
|
file:write(string.format("\t{%d, %d, {%d, Unicode::%s, Unicode::%s}},\n", data.startCodepoint, data.endCodepoint, data.startCodepoint, category, direction))
|
||||||
|
end
|
||||||
|
file:write("};\n\n")
|
||||||
|
|
||||||
|
file:write(string.format("UnicodeCharacterSimpleMapping unicodeLower[%d] = {\n", #lowercaseCharacters))
|
||||||
|
for _, data in pairs(lowercaseCharacters) do
|
||||||
|
file:write(string.format("\t{%d, %d},\n", data.codepoint, data.lower))
|
||||||
|
end
|
||||||
|
file:write("};\n\n")
|
||||||
|
|
||||||
|
file:write(string.format("UnicodeCharacterSimpleMapping unicodeTitle[%d] = {\n", #titlecaseCharacters))
|
||||||
|
for _, data in pairs(titlecaseCharacters) do
|
||||||
|
file:write(string.format("\t{%d, %d},\n", data.codepoint, data.title))
|
||||||
|
end
|
||||||
|
file:write("};\n\n")
|
||||||
|
|
||||||
|
file:write(string.format("UnicodeCharacterSimpleMapping unicodeUpper[%d] = {\n", #uppercaseCharacters))
|
||||||
|
for _, data in pairs(uppercaseCharacters) do
|
||||||
|
file:write(string.format("\t{%d, %d},\n", data.codepoint, data.upper))
|
||||||
|
end
|
||||||
|
file:write("};\n\n")
|
||||||
|
|
||||||
file:close()
|
file:close()
|
||||||
|
|
||||||
print("Took " .. os.difftime(os.clock(), t1) .. "sec.")
|
print("Succeeded in " .. (os.clock() - t1) .. "sec.")
|
||||||
end
|
end
|
||||||
--print(string.match("<Plane 15 Private Use, First>", "<.+, (%w+)>"))
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,13 @@ NazaraBuild = {}
|
||||||
local clangGccActions = "action:" .. table.concat({"codeblocks", "codelite", "gmake*", "xcode3", "xcode4"}, " or ")
|
local clangGccActions = "action:" .. table.concat({"codeblocks", "codelite", "gmake*", "xcode3", "xcode4"}, " or ")
|
||||||
|
|
||||||
function NazaraBuild:AddExecutablePath(path)
|
function NazaraBuild:AddExecutablePath(path)
|
||||||
table.insert(self.ExecutableDir, path)
|
self.ExecutableDir[path] = true
|
||||||
|
|
||||||
self:AddInstallPath(path)
|
self:AddInstallPath(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
function NazaraBuild:AddInstallPath(path)
|
function NazaraBuild:AddInstallPath(path)
|
||||||
table.insert(self.InstallDir, path)
|
self.InstallDir[path] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
function NazaraBuild:FilterLibDirectory(prefix, func)
|
function NazaraBuild:FilterLibDirectory(prefix, func)
|
||||||
|
|
@ -71,9 +72,18 @@ function NazaraBuild:Execute()
|
||||||
configurations(configs)
|
configurations(configs)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if (self.Config["PremakeProject"] and os.ishost("windows")) then
|
||||||
|
group("_Premake")
|
||||||
|
|
||||||
|
local commandLine = "premake5.exe " .. table.concat(_ARGV, ' ')
|
||||||
|
project("Regenerate premake")
|
||||||
|
kind("Utility")
|
||||||
|
prebuildcommands("cd .. && " .. commandLine)
|
||||||
|
end
|
||||||
|
|
||||||
-- Extern libraries
|
-- Extern libraries
|
||||||
if (self.Config["BuildDependencies"]) then
|
if (self.Config["BuildDependencies"]) then
|
||||||
self:FilterLibDirectory("../thirdparty/genlib/", targetdir) -- For generated libraries
|
group("Thirdparties")
|
||||||
|
|
||||||
for k, libTable in ipairs(self.OrderedExtLibs) do
|
for k, libTable in ipairs(self.OrderedExtLibs) do
|
||||||
project(libTable.Name)
|
project(libTable.Name)
|
||||||
|
|
@ -94,6 +104,8 @@ function NazaraBuild:Execute()
|
||||||
links(libTable.Libraries)
|
links(libTable.Libraries)
|
||||||
libdirs("../thirdparty/lib/common")
|
libdirs("../thirdparty/lib/common")
|
||||||
|
|
||||||
|
self:FilterLibDirectory("../thirdparty/genlib/", targetdir) -- For generated libraries
|
||||||
|
|
||||||
filter(clangGccActions)
|
filter(clangGccActions)
|
||||||
buildoptions("-U__STRICT_ANSI__")
|
buildoptions("-U__STRICT_ANSI__")
|
||||||
|
|
||||||
|
|
@ -112,14 +124,9 @@ function NazaraBuild:Execute()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (self.Config["PremakeProject"] and os.ishost("windows")) then
|
|
||||||
local commandLine = "premake5.exe " .. table.concat(_ARGV, ' ')
|
|
||||||
project("_PremakeProject")
|
|
||||||
kind("Utility")
|
|
||||||
prebuildcommands("cd .. && " .. commandLine)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Modules
|
-- Modules
|
||||||
|
group("Engine Modules")
|
||||||
|
|
||||||
if (_OPTIONS["united"]) then
|
if (_OPTIONS["united"]) then
|
||||||
project("NazaraEngine")
|
project("NazaraEngine")
|
||||||
|
|
||||||
|
|
@ -175,6 +182,8 @@ function NazaraBuild:Execute()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Tools
|
-- Tools
|
||||||
|
group("Engine SDK - Tools")
|
||||||
|
|
||||||
for k, toolTable in ipairs(self.OrderedTools) do
|
for k, toolTable in ipairs(self.OrderedTools) do
|
||||||
local prefix = "Nazara"
|
local prefix = "Nazara"
|
||||||
if (toolTable.Kind == "plugin") then
|
if (toolTable.Kind == "plugin") then
|
||||||
|
|
@ -243,6 +252,8 @@ function NazaraBuild:Execute()
|
||||||
filter({})
|
filter({})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
group("Examples")
|
||||||
|
|
||||||
for k, exampleTable in ipairs(self.OrderedExamples) do
|
for k, exampleTable in ipairs(self.OrderedExamples) do
|
||||||
local destPath = "../examples/bin"
|
local destPath = "../examples/bin"
|
||||||
|
|
||||||
|
|
@ -597,15 +608,21 @@ function NazaraBuild:LoadConfig()
|
||||||
end
|
end
|
||||||
|
|
||||||
function NazaraBuild:MakeInstallCommands(infoTable)
|
function NazaraBuild:MakeInstallCommands(infoTable)
|
||||||
if (os.istarget("windows")) then
|
if (os.ishost("windows")) then
|
||||||
filter("kind:SharedLib")
|
filter("kind:SharedLib")
|
||||||
|
|
||||||
postbuildmessage("Copying " .. infoTable.Name .. " library and its dependencies to install/executable directories...")
|
postbuildmessage("Copying " .. infoTable.Name .. " library and its dependencies to install/executable directories...")
|
||||||
|
|
||||||
-- Copy built file to install directory
|
-- Copy built file to install directory
|
||||||
for k,installPath in pairs(self.InstallDir) do
|
local installCommands = {}
|
||||||
|
for installPath,_ in pairs(self.InstallDir) do
|
||||||
local destPath = path.translate(path.isabsolute(installPath) and installPath or "../../" .. installPath)
|
local destPath = path.translate(path.isabsolute(installPath) and installPath or "../../" .. installPath)
|
||||||
postbuildcommands({[[xcopy "%{path.translate(cfg.buildtarget.relpath)}" "]] .. destPath .. [[\" /E /Y]]})
|
table.insert(installCommands, [[xcopy "%{path.translate(cfg.buildtarget.relpath)}" "]] .. destPath .. [[\" /E /Y]])
|
||||||
|
end
|
||||||
|
table.sort(installCommands)
|
||||||
|
|
||||||
|
for k,command in pairs(installCommands) do
|
||||||
|
postbuildcommands({command})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Copy additional dependencies to executable directories too
|
-- Copy additional dependencies to executable directories too
|
||||||
|
|
@ -631,10 +648,17 @@ function NazaraBuild:MakeInstallCommands(infoTable)
|
||||||
|
|
||||||
filter("architecture:" .. arch)
|
filter("architecture:" .. arch)
|
||||||
|
|
||||||
for k,execPath in pairs(self.ExecutableDir) do
|
local executableCommands = {}
|
||||||
|
for execPath,_ in pairs(self.ExecutableDir) do
|
||||||
local srcPath = path.isabsolute(srcPath) and path.translate(srcPath) or [[%{path.translate(cfg.linktarget.relpath:sub(1, -#cfg.linktarget.name - 1) .. "../../]] .. srcPath .. [[")}]]
|
local srcPath = path.isabsolute(srcPath) and path.translate(srcPath) or [[%{path.translate(cfg.linktarget.relpath:sub(1, -#cfg.linktarget.name - 1) .. "../../]] .. srcPath .. [[")}]]
|
||||||
local destPath = path.translate(path.isabsolute(execPath) and execPath or "../../" .. execPath)
|
local destPath = path.translate(path.isabsolute(execPath) and execPath or "../../" .. execPath)
|
||||||
postbuildcommands({[[xcopy "]] .. srcPath .. [[" "]] .. destPath .. [[\" /E /Y]]})
|
table.insert(executableCommands, [[xcopy "]] .. srcPath .. [[" "]] .. destPath .. [[\" /E /Y]])
|
||||||
|
end
|
||||||
|
|
||||||
|
table.sort(executableCommands)
|
||||||
|
|
||||||
|
for k,command in pairs(executableCommands) do
|
||||||
|
postbuildcommands({command})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -19,5 +19,6 @@ MODULE.OsFiles.Posix = {
|
||||||
|
|
||||||
MODULE.OsLibraries.Posix = {
|
MODULE.OsLibraries.Posix = {
|
||||||
"dl",
|
"dl",
|
||||||
|
"m", -- Math library (for sincos())
|
||||||
"pthread"
|
"pthread"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ TOOL.FilesExcluded = {
|
||||||
"../SDK/**/CameraComponent.*",
|
"../SDK/**/CameraComponent.*",
|
||||||
"../SDK/**/Canvas.*",
|
"../SDK/**/Canvas.*",
|
||||||
"../SDK/**/Console.*",
|
"../SDK/**/Console.*",
|
||||||
|
"../SDK/**/DebugComponent.*",
|
||||||
|
"../SDK/**/DebugSystem.*",
|
||||||
"../SDK/**/GraphicsComponent.*",
|
"../SDK/**/GraphicsComponent.*",
|
||||||
"../SDK/**/LightComponent.*",
|
"../SDK/**/LightComponent.*",
|
||||||
"../SDK/**/ListenerComponent.*",
|
"../SDK/**/ListenerComponent.*",
|
||||||
|
|
@ -34,6 +36,7 @@ TOOL.FilesExcluded = {
|
||||||
"../SDK/**/Particle*Component.*",
|
"../SDK/**/Particle*Component.*",
|
||||||
"../SDK/**/ParticleSystem.*",
|
"../SDK/**/ParticleSystem.*",
|
||||||
"../SDK/**/RenderSystem.*",
|
"../SDK/**/RenderSystem.*",
|
||||||
|
"../SDK/**/*Layout*.*",
|
||||||
"../SDK/**/*Widget*.*",
|
"../SDK/**/*Widget*.*",
|
||||||
"../SDK/**/LuaBinding_Audio.*",
|
"../SDK/**/LuaBinding_Audio.*",
|
||||||
"../SDK/**/LuaBinding_Graphics.*",
|
"../SDK/**/LuaBinding_Graphics.*",
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,8 @@ int main()
|
||||||
// En réalité les textures "cubemap" regroupent six faces en une, pour faciliter leur utilisation.
|
// En réalité les textures "cubemap" regroupent six faces en une, pour faciliter leur utilisation.
|
||||||
|
|
||||||
// Nous créons une nouvelle texture et prenons une référence sur celle-ci (à la manière des pointeurs intelligents)
|
// Nous créons une nouvelle texture et prenons une référence sur celle-ci (à la manière des pointeurs intelligents)
|
||||||
Nz::TextureRef texture = Nz::Texture::New();
|
Nz::TextureRef texture = Nz::Texture::LoadCubemapFromFile("resources/skybox-space.png");
|
||||||
if (texture->LoadCubemapFromFile("resources/skybox-space.png"))
|
if (texture)
|
||||||
{
|
{
|
||||||
// Si la création du cubemap a fonctionné
|
// Si la création du cubemap a fonctionné
|
||||||
|
|
||||||
|
|
@ -83,9 +83,6 @@ int main()
|
||||||
// Les modèles représentent, globalement, tout ce qui est visible en trois dimensions.
|
// Les modèles représentent, globalement, tout ce qui est visible en trois dimensions.
|
||||||
// Nous choisirons ici un vaisseau spatial (Quoi de mieux pour une scène spatiale ?)
|
// Nous choisirons ici un vaisseau spatial (Quoi de mieux pour une scène spatiale ?)
|
||||||
|
|
||||||
// Encore une fois, nous récupérons une référence plutôt que l'objet lui-même (cela va être très utile par la suite)
|
|
||||||
Nz::ModelRef spaceshipModel = Nz::Model::New();
|
|
||||||
|
|
||||||
// Nous allons charger notre modèle depuis un fichier, mais nous pouvons ajuster le modèle lors du chargement via
|
// Nous allons charger notre modèle depuis un fichier, mais nous pouvons ajuster le modèle lors du chargement via
|
||||||
// une structure permettant de paramétrer le chargement des modèles
|
// une structure permettant de paramétrer le chargement des modèles
|
||||||
Nz::ModelParameters params;
|
Nz::ModelParameters params;
|
||||||
|
|
@ -104,7 +101,8 @@ int main()
|
||||||
|
|
||||||
// On charge ensuite le modèle depuis son fichier
|
// On charge ensuite le modèle depuis son fichier
|
||||||
// Le moteur va charger le fichier et essayer de retrouver les fichiers associés (comme les matériaux, textures, ...)
|
// Le moteur va charger le fichier et essayer de retrouver les fichiers associés (comme les matériaux, textures, ...)
|
||||||
if (!spaceshipModel->LoadFromFile("resources/Spaceship/spaceship.obj", params))
|
Nz::ModelRef spaceshipModel = Nz::Model::LoadFromFile("resources/Spaceship/spaceship.obj", params);
|
||||||
|
if (!spaceshipModel)
|
||||||
{
|
{
|
||||||
// Si le chargement a échoué (fichier inexistant/invalide), il ne sert à rien de continuer
|
// Si le chargement a échoué (fichier inexistant/invalide), il ne sert à rien de continuer
|
||||||
std::cout << "Failed to load spaceship" << std::endl;
|
std::cout << "Failed to load spaceship" << std::endl;
|
||||||
|
|
|
||||||
|
|
@ -71,15 +71,15 @@ int main()
|
||||||
if (iChoice == 0)
|
if (iChoice == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
Nz::Mesh mesh;
|
Nz::MeshRef mesh = Nz::Mesh::LoadFromFile(resourceDirectory.GetPath() + '/' + models[iChoice-1]);
|
||||||
if (!mesh.LoadFromFile(resourceDirectory.GetPath() + '/' + models[iChoice-1]))
|
if (!mesh)
|
||||||
{
|
{
|
||||||
std::cout << "Failed to load mesh" << std::endl;
|
std::cout << "Failed to load mesh" << std::endl;
|
||||||
std::getchar();
|
std::getchar();
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (mesh.GetAnimationType())
|
switch (mesh->GetAnimationType())
|
||||||
{
|
{
|
||||||
case Nz::AnimationType_Skeletal:
|
case Nz::AnimationType_Skeletal:
|
||||||
std::cout << "This is a skeletal-animated mesh" << std::endl;
|
std::cout << "This is a skeletal-animated mesh" << std::endl;
|
||||||
|
|
@ -92,13 +92,13 @@ int main()
|
||||||
// Inutile de faire un case default (GetAnimationType renverra toujours une valeur correcte)
|
// Inutile de faire un case default (GetAnimationType renverra toujours une valeur correcte)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "It has a total of " << mesh.GetVertexCount() << " vertices for " << mesh.GetSubMeshCount() << " submesh(es)." << std::endl;
|
std::cout << "It has a total of " << mesh->GetVertexCount() << " vertices for " << mesh->GetSubMeshCount() << " submesh(es)." << std::endl;
|
||||||
|
|
||||||
if (mesh.IsAnimable())
|
if (mesh->IsAnimable())
|
||||||
{
|
{
|
||||||
if (mesh.GetAnimationType() == Nz::AnimationType_Skeletal)
|
if (mesh->GetAnimationType() == Nz::AnimationType_Skeletal)
|
||||||
{
|
{
|
||||||
const Nz::Skeleton* skeleton = mesh.GetSkeleton();
|
const Nz::Skeleton* skeleton = mesh->GetSkeleton();
|
||||||
unsigned int jointCount = skeleton->GetJointCount();
|
unsigned int jointCount = skeleton->GetJointCount();
|
||||||
std::cout << "It has a skeleton made of " << skeleton->GetJointCount() << " joint(s)." << std::endl;
|
std::cout << "It has a skeleton made of " << skeleton->GetJointCount() << " joint(s)." << std::endl;
|
||||||
std::cout << "Print joints ? (Y/N) ";
|
std::cout << "Print joints ? (Y/N) ";
|
||||||
|
|
@ -123,14 +123,14 @@ int main()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Nz::String animationPath = mesh.GetAnimation();
|
Nz::String animationPath = mesh->GetAnimation();
|
||||||
if (!animationPath.IsEmpty())
|
if (!animationPath.IsEmpty())
|
||||||
{
|
{
|
||||||
Nz::Animation animation;
|
Nz::AnimationRef animation = Nz::Animation::LoadFromFile(animationPath);
|
||||||
if (animation.LoadFromFile(animationPath))
|
if (animation)
|
||||||
{
|
{
|
||||||
unsigned int sequenceCount = animation.GetSequenceCount();
|
unsigned int sequenceCount = animation->GetSequenceCount();
|
||||||
std::cout << "It has an animation made of " << animation.GetFrameCount() << " frame(s) for " << sequenceCount << " sequence(s)." << std::endl;
|
std::cout << "It has an animation made of " << animation->GetFrameCount() << " frame(s) for " << sequenceCount << " sequence(s)." << std::endl;
|
||||||
std::cout << "Print sequences ? (Y/N) ";
|
std::cout << "Print sequences ? (Y/N) ";
|
||||||
|
|
||||||
char cChoice;
|
char cChoice;
|
||||||
|
|
@ -141,7 +141,7 @@ int main()
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < sequenceCount; ++i)
|
for (unsigned int i = 0; i < sequenceCount; ++i)
|
||||||
{
|
{
|
||||||
const Nz::Sequence* sequence = animation.GetSequence(i);
|
const Nz::Sequence* sequence = animation->GetSequence(i);
|
||||||
std::cout << "\t" << (i+1) << ": " << sequence->name << std::endl;
|
std::cout << "\t" << (i+1) << ": " << sequence->name << std::endl;
|
||||||
std::cout << "\t\tStart frame: " << sequence->firstFrame << std::endl;
|
std::cout << "\t\tStart frame: " << sequence->firstFrame << std::endl;
|
||||||
std::cout << "\t\tFrame count: " << sequence->frameCount << std::endl;
|
std::cout << "\t\tFrame count: " << sequence->frameCount << std::endl;
|
||||||
|
|
@ -157,10 +157,10 @@ int main()
|
||||||
std::cout << "It's animable but has no animation information" << std::endl;
|
std::cout << "It's animable but has no animation information" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
Nz::Boxf cube = mesh.GetAABB();
|
Nz::Boxf cube = mesh->GetAABB();
|
||||||
std::cout << "Mesh is " << cube.width << " units wide, " << cube.height << " units height and " << cube.depth << " units depth" << std::endl;
|
std::cout << "Mesh is " << cube.width << " units wide, " << cube.height << " units height and " << cube.depth << " units depth" << std::endl;
|
||||||
|
|
||||||
unsigned int materialCount = mesh.GetMaterialCount();
|
unsigned int materialCount = mesh->GetMaterialCount();
|
||||||
std::cout << "It has " << materialCount << " materials registred" << std::endl;
|
std::cout << "It has " << materialCount << " materials registred" << std::endl;
|
||||||
std::cout << "Print materials ? (Y/N) ";
|
std::cout << "Print materials ? (Y/N) ";
|
||||||
|
|
||||||
|
|
@ -172,7 +172,7 @@ int main()
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i < materialCount; ++i)
|
for (unsigned int i = 0; i < materialCount; ++i)
|
||||||
{
|
{
|
||||||
const Nz::ParameterList& matData = mesh.GetMaterialData(i);
|
const Nz::ParameterList& matData = mesh->GetMaterialData(i);
|
||||||
|
|
||||||
Nz::String data;
|
Nz::String data;
|
||||||
if (!matData.GetStringParameter(Nz::MaterialData::FilePath, &data))
|
if (!matData.GetStringParameter(Nz::MaterialData::FilePath, &data))
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ class SpriteRenderer : public Nz::ParticleRenderer
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Render(const Nz::ParticleGroup& system, const Nz::ParticleMapper& mapper, unsigned int startId, unsigned int endId, Nz::AbstractRenderQueue* renderQueue)
|
void Render(const Nz::ParticleGroup& system, const Nz::ParticleMapper& mapper, unsigned int startId, unsigned int endId, Nz::AbstractRenderQueue* renderQueue) override
|
||||||
{
|
{
|
||||||
Nz::Vector2f size(1.f, 1.f);
|
Nz::Vector2f size(1.f, 1.f);
|
||||||
Nz::SparsePtr<const Nz::Vector2f> sizePtr(&size, 0);
|
Nz::SparsePtr<const Nz::Vector2f> sizePtr(&size, 0);
|
||||||
|
|
@ -126,18 +126,19 @@ ParticleDemo("Logo", sharedData)
|
||||||
Nz::ImageParams params;
|
Nz::ImageParams params;
|
||||||
params.loadFormat = Nz::PixelFormatType_RGBA8;
|
params.loadFormat = Nz::PixelFormatType_RGBA8;
|
||||||
|
|
||||||
if (!m_logo.LoadFromFile("resources/Logo.png", params))
|
m_logo = Nz::Image::LoadFromFile("resources/Logo.png", params);
|
||||||
|
if (!m_logo)
|
||||||
NazaraError("Failed to load logo!");
|
NazaraError("Failed to load logo!");
|
||||||
|
|
||||||
unsigned int width = m_logo.GetWidth();
|
unsigned int width = m_logo->GetWidth();
|
||||||
unsigned int height = m_logo.GetHeight();
|
unsigned int height = m_logo->GetHeight();
|
||||||
m_pixels.reserve(width * height);
|
m_pixels.reserve(width * height);
|
||||||
|
|
||||||
for (unsigned int x = 0; x < width; ++x)
|
for (unsigned int x = 0; x < width; ++x)
|
||||||
{
|
{
|
||||||
for (unsigned int y = 0; y < height; ++y)
|
for (unsigned int y = 0; y < height; ++y)
|
||||||
{
|
{
|
||||||
Nz::Color color = m_logo.GetPixelColor(x, y);
|
Nz::Color color = m_logo->GetPixelColor(x, y);
|
||||||
if (color.a == 0)
|
if (color.a == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -173,8 +174,8 @@ void LogoExample::Enter(Ndk::StateMachine& fsm)
|
||||||
|
|
||||||
m_shared.world3D->GetSystem<Ndk::RenderSystem>().SetDefaultBackground(nullptr);
|
m_shared.world3D->GetSystem<Ndk::RenderSystem>().SetDefaultBackground(nullptr);
|
||||||
|
|
||||||
Nz::TextureRef backgroundTexture = Nz::Texture::New();
|
Nz::TextureRef backgroundTexture = Nz::Texture::LoadFromFile("resources/stars-background.jpg");
|
||||||
if (backgroundTexture->LoadFromFile("resources/stars-background.jpg"))
|
if (backgroundTexture)
|
||||||
m_shared.world2D->GetSystem<Ndk::RenderSystem>().SetDefaultBackground(Nz::TextureBackground::New(std::move(backgroundTexture)));
|
m_shared.world2D->GetSystem<Ndk::RenderSystem>().SetDefaultBackground(Nz::TextureBackground::New(std::move(backgroundTexture)));
|
||||||
|
|
||||||
Ndk::EntityHandle particleGroupEntity = m_shared.world2D->CreateEntity();
|
Ndk::EntityHandle particleGroupEntity = m_shared.world2D->CreateEntity();
|
||||||
|
|
@ -254,7 +255,7 @@ void LogoExample::ResetParticles(float elapsed)
|
||||||
Nz::Vector2ui size = m_shared.target->GetSize();
|
Nz::Vector2ui size = m_shared.target->GetSize();
|
||||||
|
|
||||||
Nz::Vector2f center = {size.x / 2.f, size.y / 2.f};
|
Nz::Vector2f center = {size.x / 2.f, size.y / 2.f};
|
||||||
Nz::Vector2f offset = center - Nz::Vector2f(Nz::Vector2ui(m_logo.GetSize()) / 2);
|
Nz::Vector2f offset = center - Nz::Vector2f(Nz::Vector2ui(m_logo->GetSize()) / 2);
|
||||||
|
|
||||||
std::uniform_real_distribution<float> disX(0.f, float(size.x));
|
std::uniform_real_distribution<float> disX(0.f, float(size.x));
|
||||||
std::uniform_real_distribution<float> disY(-float(size.y) * 0.5f, float(size.y) * 1.5f);
|
std::uniform_real_distribution<float> disY(-float(size.y) * 0.5f, float(size.y) * 1.5f);
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ class LogoExample : public ParticleDemo
|
||||||
Nz::BackgroundRef m_oldBackground;
|
Nz::BackgroundRef m_oldBackground;
|
||||||
void* m_particles;
|
void* m_particles;
|
||||||
Nz::Clock m_mouseClock;
|
Nz::Clock m_mouseClock;
|
||||||
Nz::Image m_logo;
|
Nz::ImageRef m_logo;
|
||||||
Nz::ParticleControllerRef m_controller;
|
Nz::ParticleControllerRef m_controller;
|
||||||
Nz::ParticleDeclarationRef m_declaration;
|
Nz::ParticleDeclarationRef m_declaration;
|
||||||
Nz::ParticleRendererRef m_renderer;
|
Nz::ParticleRendererRef m_renderer;
|
||||||
|
|
|
||||||
|
|
@ -234,52 +234,59 @@ ParticleDemo("Space battle", sharedData)
|
||||||
|
|
||||||
Nz::Color grey(100, 100, 100);
|
Nz::Color grey(100, 100, 100);
|
||||||
|
|
||||||
if (!m_turret.baseModel.LoadFromFile("resources/Turret/base.obj", parameters))
|
m_turret.baseModel = Nz::Model::LoadFromFile("resources/Turret/base.obj", parameters);
|
||||||
|
if (!m_turret.baseModel)
|
||||||
NazaraWarning("Failed to load base.obj");
|
NazaraWarning("Failed to load base.obj");
|
||||||
|
|
||||||
for (unsigned int i = 0; i < m_turret.baseModel.GetMaterialCount(); ++i)
|
for (unsigned int i = 0; i < m_turret.baseModel->GetMaterialCount(); ++i)
|
||||||
m_turret.baseModel.GetMaterial(i)->SetDiffuseColor(grey);
|
m_turret.baseModel->GetMaterial(i)->SetDiffuseColor(grey);
|
||||||
|
|
||||||
if (!m_turret.rotatingBaseModel.LoadFromFile("resources/Turret/rotating_base.obj", parameters))
|
m_turret.rotatingBaseModel = Nz::Model::LoadFromFile("resources/Turret/rotating_base.obj", parameters);
|
||||||
|
if (!m_turret.rotatingBaseModel)
|
||||||
NazaraWarning("Failed to load rotating_base.obj");
|
NazaraWarning("Failed to load rotating_base.obj");
|
||||||
|
|
||||||
for (unsigned int i = 0; i < m_turret.rotatingBaseModel.GetMaterialCount(); ++i)
|
for (unsigned int i = 0; i < m_turret.rotatingBaseModel->GetMaterialCount(); ++i)
|
||||||
m_turret.rotatingBaseModel.GetMaterial(i)->SetDiffuseColor(grey);
|
m_turret.rotatingBaseModel->GetMaterial(i)->SetDiffuseColor(grey);
|
||||||
|
|
||||||
if (!m_turret.cannonBaseModel.LoadFromFile("resources/Turret/cannon_base.obj", parameters))
|
m_turret.cannonBaseModel = Nz::Model::LoadFromFile("resources/Turret/cannon_base.obj", parameters);
|
||||||
|
if (!m_turret.cannonBaseModel)
|
||||||
NazaraWarning("Failed to load cannon_base.obj");
|
NazaraWarning("Failed to load cannon_base.obj");
|
||||||
|
|
||||||
for (unsigned int i = 0; i < m_turret.cannonBaseModel.GetMaterialCount(); ++i)
|
for (unsigned int i = 0; i < m_turret.cannonBaseModel->GetMaterialCount(); ++i)
|
||||||
m_turret.cannonBaseModel.GetMaterial(i)->SetDiffuseColor(grey);
|
m_turret.cannonBaseModel->GetMaterial(i)->SetDiffuseColor(grey);
|
||||||
|
|
||||||
parameters.mesh.texCoordScale.Set(40.f, 40.f);
|
parameters.mesh.texCoordScale.Set(40.f, 40.f);
|
||||||
parameters.mesh.matrix = Nz::Matrix4f::Rotate(Nz::EulerAnglesf(0.f, 180.f, 0.f));
|
parameters.mesh.matrix = Nz::Matrix4f::Rotate(Nz::EulerAnglesf(0.f, 180.f, 0.f));
|
||||||
if (!m_turret.cannonModel.LoadFromFile("resources/Turret/cannon.obj", parameters))
|
|
||||||
|
m_turret.cannonModel = Nz::Model::LoadFromFile("resources/Turret/cannon.obj", parameters);
|
||||||
|
if (!m_turret.cannonModel)
|
||||||
NazaraWarning("Failed to load cannon.obj");
|
NazaraWarning("Failed to load cannon.obj");
|
||||||
|
|
||||||
// Since OBJ don't support normal maps..
|
// Since OBJ doesn't support normal maps..
|
||||||
m_turret.cannonModel.GetMaterial(0)->SetNormalMap("resources/Turret/198_norm.jpg");
|
m_turret.cannonModel->GetMaterial(0)->SetNormalMap("resources/Turret/198_norm.jpg");
|
||||||
|
|
||||||
parameters.mesh.matrix.MakeIdentity();
|
parameters.mesh.matrix.MakeIdentity();
|
||||||
parameters.mesh.texCoordScale.Set(1.f, 1.f);
|
parameters.mesh.texCoordScale.Set(1.f, 1.f);
|
||||||
|
|
||||||
parameters.mesh.center = true;
|
parameters.mesh.center = true;
|
||||||
if (!m_spacestationModel.LoadFromFile("resources/SpaceStation/space_station.obj", parameters))
|
m_spacestationModel = Nz::Model::LoadFromFile("resources/SpaceStation/space_station.obj", parameters);
|
||||||
|
if (!m_spacestationModel)
|
||||||
NazaraWarning("Failed to load space_station.obj");
|
NazaraWarning("Failed to load space_station.obj");
|
||||||
|
|
||||||
m_spacestationModel.GetMesh()->GenerateNormalsAndTangents();
|
m_spacestationModel->GetMesh()->GenerateNormalsAndTangents();
|
||||||
|
|
||||||
parameters.mesh.texCoordScale.Set(1.f, -1.f);
|
parameters.mesh.texCoordScale.Set(1.f, -1.f);
|
||||||
parameters.mesh.matrix.MakeRotation(Nz::EulerAnglesf(0.f, -90.f, 0.f));
|
parameters.mesh.matrix.MakeRotation(Nz::EulerAnglesf(0.f, -90.f, 0.f));
|
||||||
|
|
||||||
if (!m_spaceshipModel.LoadFromFile("resources/space_frigate_6/space_frigate_6.obj", parameters))
|
m_spaceshipModel = Nz::Model::LoadFromFile("resources/space_frigate_6/space_frigate_6.obj", parameters);
|
||||||
|
if (!m_spaceshipModel)
|
||||||
NazaraWarning("Failed to load space_frigate_6.obj");
|
NazaraWarning("Failed to load space_frigate_6.obj");
|
||||||
|
|
||||||
// Since OBJ don't support normal maps..
|
// Since OBJ doesn't support normal maps..
|
||||||
for (unsigned int i = 0; i < m_spaceshipModel.GetMaterialCount(); ++i)
|
for (unsigned int i = 0; i < m_spaceshipModel->GetMaterialCount(); ++i)
|
||||||
{
|
{
|
||||||
m_spaceshipModel.GetMaterial(i)->SetEmissiveMap("resources/space_frigate_6/space_frigate_6_illumination.jpg");
|
m_spaceshipModel->GetMaterial(i)->SetEmissiveMap("resources/space_frigate_6/space_frigate_6_illumination.jpg");
|
||||||
m_spaceshipModel.GetMaterial(i)->SetNormalMap("resources/space_frigate_6/space_frigate_6_normal.png");
|
m_spaceshipModel->GetMaterial(i)->SetNormalMap("resources/space_frigate_6/space_frigate_6_normal.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
Nz::TextureRef skyboxCubemap = Nz::Texture::New();
|
Nz::TextureRef skyboxCubemap = Nz::Texture::New();
|
||||||
|
|
@ -324,7 +331,7 @@ ParticleDemo("Space battle", sharedData)
|
||||||
m_spaceshipTemplate->AddComponent<Ndk::VelocityComponent>();
|
m_spaceshipTemplate->AddComponent<Ndk::VelocityComponent>();
|
||||||
m_spaceshipTemplate->AddComponent<SpaceshipComponent>();
|
m_spaceshipTemplate->AddComponent<SpaceshipComponent>();
|
||||||
auto& gfxComponent = m_spaceshipTemplate->AddComponent<Ndk::GraphicsComponent>();
|
auto& gfxComponent = m_spaceshipTemplate->AddComponent<Ndk::GraphicsComponent>();
|
||||||
gfxComponent.Attach(&m_spaceshipModel);
|
gfxComponent.Attach(m_spaceshipModel);
|
||||||
|
|
||||||
m_ambientMusic.OpenFromFile("resources/ambience.ogg");
|
m_ambientMusic.OpenFromFile("resources/ambience.ogg");
|
||||||
m_ambientMusic.SetVolume(60.f);
|
m_ambientMusic.SetVolume(60.f);
|
||||||
|
|
@ -662,13 +669,15 @@ void SpacebattleExample::Enter(Ndk::StateMachine& fsm)
|
||||||
|
|
||||||
Ndk::NodeComponent& cannonNode = m_turret.cannonEntity->GetComponent<Ndk::NodeComponent>();
|
Ndk::NodeComponent& cannonNode = m_turret.cannonEntity->GetComponent<Ndk::NodeComponent>();
|
||||||
|
|
||||||
Nz::Boxf introAABB = introGfx.GetBoundingVolume().aabb;
|
Nz::Boxf introAABB = introGfx.GetAABB();
|
||||||
introNode.SetPosition(cannonNode.GetForward() * 500.f + introNode.GetLeft() * introAABB.width / 2.f + introNode.GetUp() * introAABB.height / 2.f);
|
introNode.SetPosition(cannonNode.GetForward() * 500.f + introNode.GetLeft() * introAABB.width / 2.f + introNode.GetUp() * introAABB.height / 2.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpacebattleExample::Leave(Ndk::StateMachine& fsm)
|
void SpacebattleExample::Leave(Ndk::StateMachine& fsm)
|
||||||
{
|
{
|
||||||
m_ambientMusic.Stop();
|
m_ambientMusic.Stop();
|
||||||
|
m_onMouseMoved.Disconnect();
|
||||||
|
m_shared.target->SetCursor(Nz::SystemCursor_Default);
|
||||||
m_shared.world3D->RemoveSystem<LaserBeamSystem>();
|
m_shared.world3D->RemoveSystem<LaserBeamSystem>();
|
||||||
m_shared.world3D->RemoveSystem<SpaceshipSystem>();
|
m_shared.world3D->RemoveSystem<SpaceshipSystem>();
|
||||||
m_turretFireSound.Stop();
|
m_turretFireSound.Stop();
|
||||||
|
|
@ -760,7 +769,7 @@ void SpacebattleExample::CreateSpaceShip()
|
||||||
spacestationNode.SetScale(0.1f);
|
spacestationNode.SetScale(0.1f);
|
||||||
|
|
||||||
Ndk::GraphicsComponent& spacestationGfx = m_spacestationEntity->AddComponent<Ndk::GraphicsComponent>();
|
Ndk::GraphicsComponent& spacestationGfx = m_spacestationEntity->AddComponent<Ndk::GraphicsComponent>();
|
||||||
spacestationGfx.Attach(&m_spacestationModel);
|
spacestationGfx.Attach(m_spacestationModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpacebattleExample::CreateTurret()
|
void SpacebattleExample::CreateTurret()
|
||||||
|
|
@ -774,7 +783,7 @@ void SpacebattleExample::CreateTurret()
|
||||||
baseNode.SetRotation(Nz::EulerAnglesf(0.f, 180.f, 0.f));
|
baseNode.SetRotation(Nz::EulerAnglesf(0.f, 180.f, 0.f));
|
||||||
|
|
||||||
Ndk::GraphicsComponent& baseGfx = m_turret.baseEntity->AddComponent<Ndk::GraphicsComponent>();
|
Ndk::GraphicsComponent& baseGfx = m_turret.baseEntity->AddComponent<Ndk::GraphicsComponent>();
|
||||||
baseGfx.Attach(&m_turret.baseModel);
|
baseGfx.Attach(m_turret.baseModel);
|
||||||
|
|
||||||
// Rotating base
|
// Rotating base
|
||||||
m_turret.rotatingBaseEntity = m_shared.world3D->CreateEntity();
|
m_turret.rotatingBaseEntity = m_shared.world3D->CreateEntity();
|
||||||
|
|
@ -784,7 +793,7 @@ void SpacebattleExample::CreateTurret()
|
||||||
rotatingBaseNode.SetParent(m_turret.baseEntity);
|
rotatingBaseNode.SetParent(m_turret.baseEntity);
|
||||||
|
|
||||||
Ndk::GraphicsComponent& rotatingBaseGfx = m_turret.rotatingBaseEntity->AddComponent<Ndk::GraphicsComponent>();
|
Ndk::GraphicsComponent& rotatingBaseGfx = m_turret.rotatingBaseEntity->AddComponent<Ndk::GraphicsComponent>();
|
||||||
rotatingBaseGfx.Attach(&m_turret.rotatingBaseModel);
|
rotatingBaseGfx.Attach(m_turret.rotatingBaseModel);
|
||||||
|
|
||||||
// Cannon base
|
// Cannon base
|
||||||
m_turret.cannonBaseEntity = m_shared.world3D->CreateEntity();
|
m_turret.cannonBaseEntity = m_shared.world3D->CreateEntity();
|
||||||
|
|
@ -795,7 +804,7 @@ void SpacebattleExample::CreateTurret()
|
||||||
cannonBaseNode.SetParent(m_turret.rotatingBaseEntity);
|
cannonBaseNode.SetParent(m_turret.rotatingBaseEntity);
|
||||||
|
|
||||||
Ndk::GraphicsComponent& cannonBaseGfx = m_turret.cannonBaseEntity->AddComponent<Ndk::GraphicsComponent>();
|
Ndk::GraphicsComponent& cannonBaseGfx = m_turret.cannonBaseEntity->AddComponent<Ndk::GraphicsComponent>();
|
||||||
cannonBaseGfx.Attach(&m_turret.cannonBaseModel);
|
cannonBaseGfx.Attach(m_turret.cannonBaseModel);
|
||||||
|
|
||||||
// Cannon anchor
|
// Cannon anchor
|
||||||
m_turret.cannonAnchorEntity = m_shared.world3D->CreateEntity();
|
m_turret.cannonAnchorEntity = m_shared.world3D->CreateEntity();
|
||||||
|
|
@ -814,7 +823,7 @@ void SpacebattleExample::CreateTurret()
|
||||||
cannonNode.SetRotation(Nz::EulerAnglesf(0.f, 180.f, 0.f));
|
cannonNode.SetRotation(Nz::EulerAnglesf(0.f, 180.f, 0.f));
|
||||||
|
|
||||||
Ndk::GraphicsComponent& cannonGfx = m_turret.cannonEntity->AddComponent<Ndk::GraphicsComponent>();
|
Ndk::GraphicsComponent& cannonGfx = m_turret.cannonEntity->AddComponent<Ndk::GraphicsComponent>();
|
||||||
cannonGfx.Attach(&m_turret.cannonModel);
|
cannonGfx.Attach(m_turret.cannonModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpacebattleExample::OnMouseMoved(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseMoveEvent& event)
|
void SpacebattleExample::OnMouseMoved(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseMoveEvent& event)
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue