Merge branch 'master' into vulkan

This commit is contained in:
Lynix 2018-04-26 22:48:49 +02:00
commit 43bb487801
191 changed files with 5200 additions and 3554 deletions

View File

@ -15,6 +15,7 @@ Miscellaneous:
- Fix compilation with some MinGW distributions - Fix compilation with some MinGW distributions
- 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
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.
@ -66,6 +67,33 @@ Nazara Engine:
- Add PhysWorld2D::[Get|Set]IterationCount to control how many iterations chipmunk will perform per step. - Add PhysWorld2D::[Get|Set]IterationCount to control how many iterations chipmunk will perform per step.
- Add PhysWorld2D::UseSpatialHash to use spatial hashing instead of bounding box trees, which may speedup simulation in some cases. - Add PhysWorld2D::UseSpatialHash to use spatial hashing instead of bounding box trees, which may speedup simulation in some cases.
- Add PhysWorld[2D|3D] max step count per Step call (default: 50), to avoid spirals of death when the physics engine simulation time is over step size. - Add PhysWorld[2D|3D] max step count per Step call (default: 50), to avoid spirals of death when the physics engine simulation time is over step size.
- Fix Window triggering KeyPressed event after triggering a resize/movement event on Windows
- (WIP) Add support for materials and callbacks to Physics3D module.
- PhysWorld3D class is now movable
- ⚠️ Removed array/pointer constructor from Vector classes
- Fixed Platform module not being classified as client-only
- ⚠️ Renamed Bitset::Read to Bitset::Write
- Fixed ENetCompressor class destructor not being virtual
- ⚠️ Added a type tag parameter to Serialize and Unserialize functions, to prevent implicit conversions with overloads
- Added Collider3D::ForEachPolygon method, allowing construction of a debug mesh based on the physics collider
- Fixed ConvexCollider3D::GetType returning Compound instead of ConvexHull.
- Dual-stack sockets are now supported (by using NetProtocol_Any at creation/opening)
- Fixed IPv6 addresses not being correctly encoded/decoded from the socket API.
- Fix copy and move semantic on HandledObject and ObjectHandle
- Add support for emissive and normal maps in .mtl loader using custom keywords ([map_]emissive and [map_]normal)
- Music, Sound and SoundEmitter are now movable
- Fixed Sound copy which was not copying looping state
- Fixed Billboard bounding volume
- Fixed Directory::GetResultSize and Directory::IsResultDirectory on Posix systems
- 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
Nazara Development Kit: Nazara Development Kit:
- Added ImageWidget (#139) - Added ImageWidget (#139)
@ -101,6 +129,19 @@ Nazara Development Kit:
- ⚠️ Renamed World::Update() to World::Refresh() for more clarity and to differentiate it from World::Update(elapsedTime) - ⚠️ Renamed World::Update() to World::Refresh() for more clarity and to differentiate it from World::Update(elapsedTime)
- World entity ids are now reused from lowest to highest (they were previously reused in reverse order of death) - World entity ids are now reused from lowest to highest (they were previously reused in reverse order of death)
- World now has an internal profiler, allowing to measure the refresh and system update time - World now has an internal profiler, allowing to measure the refresh and system update time
- CollisionComponent[2D|3D] and PhysicsComponent[2D|3D] now configures their internal RigidBody userdata to the entity ID they belong to (useful for callbacks).
- Fixed EntityList copy/movement assignment operator which was not properly unregistering contained entities.
- ListenerSystem now handles velocity in a generic way (no longer require a VelocityComponent and is compatible with physics)
- World now has const getters for systems
- Add World::ForEachSystem method, allowing iteration on every active system on a specific world
- 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
- ⚠️ 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
# 0.4: # 0.4:

View File

@ -83,9 +83,10 @@ namespace Ndk
}; };
protected: protected:
const EntityHandle& CreateEntity(); const EntityHandle& CreateEntity(bool isContentEntity);
void DestroyEntity(Entity* entity); void DestroyEntity(Entity* entity);
virtual void Layout(); virtual void Layout();
void InvalidateNode() override; void InvalidateNode() override;
virtual bool IsFocusable() const; virtual bool IsFocusable() const;
@ -111,11 +112,18 @@ namespace Ndk
void RegisterToCanvas(); void RegisterToCanvas();
inline void UpdateCanvasIndex(std::size_t index); inline void UpdateCanvasIndex(std::size_t index);
void UnregisterFromCanvas(); void UnregisterFromCanvas();
void UpdatePositionAndSize();
struct WidgetEntity
{
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();
std::size_t m_canvasIndex; std::size_t m_canvasIndex;
std::vector<EntityOwner> m_entities; std::vector<WidgetEntity> m_entities;
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;

View File

@ -62,7 +62,7 @@ namespace Ndk
WidgetEntry& entry = m_widgetEntries[index]; WidgetEntry& entry = m_widgetEntries[index];
Nz::Vector3f pos = entry.widget->GetPosition(); Nz::Vector3f pos = entry.widget->GetPosition();
Nz::Vector2f size = entry.widget->GetContentSize(); Nz::Vector2f size = entry.widget->GetSize();
entry.box.Set(pos.x, pos.y, pos.z, size.x, size.y, 1.f); entry.box.Set(pos.x, pos.y, pos.z, size.x, size.y, 1.f);
} }

View File

@ -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

View File

@ -0,0 +1,80 @@
// 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 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

View File

@ -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;
}
}

View File

@ -28,7 +28,7 @@ namespace Ndk
public: public:
using RenderableList = std::vector<Nz::InstancedRenderableRef>; using RenderableList = std::vector<Nz::InstancedRenderableRef>;
GraphicsComponent() = default; GraphicsComponent();
inline GraphicsComponent(const GraphicsComponent& graphicsComponent); inline GraphicsComponent(const GraphicsComponent& graphicsComponent);
~GraphicsComponent() = default; ~GraphicsComponent() = default;
@ -54,6 +54,8 @@ namespace Ndk
inline void RemoveFromCullingList(GraphicsComponentCullingList* cullingList) const; inline void RemoveFromCullingList(GraphicsComponentCullingList* cullingList) const;
inline void SetScissorRect(const Nz::Recti& scissorRect);
inline void UpdateLocalMatrix(const Nz::InstancedRenderable* instancedRenderable, const Nz::Matrix4f& localMatrix); inline void UpdateLocalMatrix(const Nz::InstancedRenderable* instancedRenderable, const Nz::Matrix4f& localMatrix);
inline void UpdateRenderOrder(const Nz::InstancedRenderable* instancedRenderable, int renderOrder); inline void UpdateRenderOrder(const Nz::InstancedRenderable* instancedRenderable, int renderOrder);
@ -144,6 +146,7 @@ namespace Ndk
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::BoundingVolumef m_boundingVolume;
mutable Nz::Matrix4f m_transformMatrix; mutable Nz::Matrix4f m_transformMatrix;
Nz::Recti m_scissorRect;
Nz::TextureRef m_reflectionMap; Nz::TextureRef m_reflectionMap;
mutable bool m_boundingVolumeUpdated; mutable bool m_boundingVolumeUpdated;
mutable bool m_transformMatrixUpdated; mutable bool m_transformMatrixUpdated;

View File

@ -9,12 +9,16 @@
namespace Ndk namespace Ndk
{ {
inline GraphicsComponent::GraphicsComponent() :
m_scissorRect(-1, -1)
{
}
/*! /*!
* \brief Constructs a GraphicsComponent object by copy semantic * \brief Constructs a GraphicsComponent object by copy semantic
* *
* \param graphicsComponent GraphicsComponent to copy * \param graphicsComponent GraphicsComponent to copy
*/ */
inline GraphicsComponent::GraphicsComponent(const GraphicsComponent& graphicsComponent) : inline GraphicsComponent::GraphicsComponent(const GraphicsComponent& graphicsComponent) :
Component(graphicsComponent), Component(graphicsComponent),
HandledObject(graphicsComponent), HandledObject(graphicsComponent),
@ -177,6 +181,14 @@ namespace Ndk
} }
} }
inline void GraphicsComponent::SetScissorRect(const Nz::Recti& scissorRect)
{
m_scissorRect = scissorRect;
for (VolumeCullingEntry& entry : m_volumeCullingEntries)
entry.listEntry.ForceInvalidation(); //< Invalidate render queues
}
inline void GraphicsComponent::UpdateLocalMatrix(const Nz::InstancedRenderable* instancedRenderable, const Nz::Matrix4f& localMatrix) inline void GraphicsComponent::UpdateLocalMatrix(const Nz::InstancedRenderable* instancedRenderable, const Nz::Matrix4f& localMatrix)
{ {
for (auto& renderable : m_renderables) for (auto& renderable : m_renderables)

View File

@ -9,6 +9,7 @@
#include <Nazara/Core/Bitset.hpp> #include <Nazara/Core/Bitset.hpp>
#include <Nazara/Core/HandledObject.hpp> #include <Nazara/Core/HandledObject.hpp>
#include <Nazara/Core/MovablePtr.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);
@ -96,8 +97,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;
}; };

View File

@ -169,6 +169,9 @@ namespace Ndk
inline EntityList& EntityList::operator=(const EntityList& entityList) inline EntityList& EntityList::operator=(const EntityList& entityList)
{ {
for (const Ndk::EntityHandle& entity : *this)
entity->UnregisterEntityList(this);
m_entityBits = entityList.m_entityBits; m_entityBits = entityList.m_entityBits;
m_world = entityList.m_world; m_world = entityList.m_world;
@ -180,6 +183,12 @@ namespace Ndk
inline EntityList& EntityList::operator=(EntityList&& entityList) noexcept inline EntityList& EntityList::operator=(EntityList&& entityList) noexcept
{ {
if (this == &entityList)
return *this;
for (const Ndk::EntityHandle& entity : *this)
entity->UnregisterEntityList(this);
m_entityBits = std::move(entityList.m_entityBits); m_entityBits = std::move(entityList.m_entityBits);
m_world = entityList.m_world; m_world = entityList.m_world;

View File

@ -25,7 +25,7 @@ namespace Ndk
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;
}; };
} }

View File

@ -31,7 +31,6 @@ namespace Ndk
* *
* \see Reset * \see Reset
*/ */
inline EntityOwner::~EntityOwner() inline EntityOwner::~EntityOwner()
{ {
Reset(nullptr); Reset(nullptr);
@ -68,13 +67,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

View File

@ -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>

View File

@ -0,0 +1,51 @@
// 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 GetAABBMaterial();
Nz::MaterialRef GetCollisionMaterial();
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_aabbMaterial;
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

View File

@ -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>

View File

@ -28,7 +28,7 @@ namespace Ndk
//virtual LabelWidget* Clone() const = 0; //virtual LabelWidget* Clone() const = 0;
void ResizeToContent(); void ResizeToContent() override;
inline void UpdateText(const Nz::AbstractTextDrawer& drawer); inline void UpdateText(const Nz::AbstractTextDrawer& drawer);
@ -36,6 +36,8 @@ namespace Ndk
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;
}; };

View File

@ -11,6 +11,7 @@
#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 <vector>
namespace Ndk namespace Ndk
{ {
@ -30,15 +31,20 @@ namespace Ndk
inline void EnableMultiline(bool enable = true); inline void EnableMultiline(bool enable = true);
void EraseSelection();
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 Nz::Vector2ui& cursorPosition); inline std::size_t GetGlyphIndex(const Nz::Vector2ui& cursorPosition);
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;
@ -53,6 +59,7 @@ namespace Ndk
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);
@ -64,6 +71,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*/);
@ -79,6 +88,9 @@ 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();
@ -88,10 +100,13 @@ namespace Ndk
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;
}; };

View File

@ -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);
@ -29,7 +30,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
@ -63,7 +87,12 @@ 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;
} }
@ -75,7 +104,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
@ -104,7 +133,7 @@ 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);
@ -120,22 +149,8 @@ namespace Ndk
{ {
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();
} }
@ -146,7 +161,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)
@ -155,6 +170,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);
@ -175,6 +192,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;

View File

@ -50,11 +50,16 @@ namespace Ndk
inline void DisableProfiler(); inline void DisableProfiler();
inline void EnableProfiler(bool enable = true); inline void EnableProfiler(bool enable = true);
template<typename F> void ForEachSystem(const F& iterationFunc);
template<typename F> void ForEachSystem(const F& iterationFunc) const;
inline const EntityHandle& GetEntity(EntityId id); inline const EntityHandle& GetEntity(EntityId id);
inline const EntityList& GetEntities() const; inline const EntityList& GetEntities() const;
inline const ProfilerData& GetProfilerData() const; inline const ProfilerData& GetProfilerData() const;
inline BaseSystem& GetSystem(SystemIndex index); inline BaseSystem& GetSystem(SystemIndex index);
inline const BaseSystem& GetSystem(SystemIndex index) const;
template<typename SystemType> SystemType& GetSystem(); template<typename SystemType> SystemType& GetSystem();
template<typename SystemType> const SystemType& GetSystem() const;
inline bool HasSystem(SystemIndex index) const; inline bool HasSystem(SystemIndex index) const;
template<typename SystemType> bool HasSystem() const; template<typename SystemType> bool HasSystem() const;

View File

@ -133,6 +133,40 @@ namespace Ndk
} }
} }
/*!
* \brief Executes a function on every present system
*
* Calls iterationFunc on every previously added system, in the same order as their indexes
*
* \param iterationFunc Function to be called
*/
template<typename F>
void World::ForEachSystem(const F& iterationFunc)
{
for (const auto& systemPtr : m_systems)
{
if (systemPtr)
iterationFunc(*systemPtr);
}
}
/*!
* \brief Executes a function on every present system
*
* Calls iterationFunc on every previously added system, in the same order as their indexes
*
* \param iterationFunc Function to be called
*/
template<typename F>
void World::ForEachSystem(const F& iterationFunc) const
{
for (const auto& systemPtr : m_systems)
{
if (systemPtr)
iterationFunc(static_cast<const Ndk::BaseSystem&>(*systemPtr)); //< Force const reference
}
}
/*! /*!
* \brief Gets an entity * \brief Gets an entity
* \return A constant reference to a handle of the entity * \return A constant reference to a handle of the entity
@ -177,9 +211,8 @@ namespace Ndk
* *
* \param index Index of the system * \param index Index of the system
* *
* \remark Produces a NazaraAssert if system is not available in this world * \remark The world must have the system before calling this function
*/ */
inline BaseSystem& World::GetSystem(SystemIndex index) inline BaseSystem& World::GetSystem(SystemIndex index)
{ {
NazaraAssert(HasSystem(index), "This system is not part of the world"); NazaraAssert(HasSystem(index), "This system is not part of the world");
@ -190,13 +223,30 @@ namespace Ndk
return *system; return *system;
} }
/*!
* \brief Gets a system in the world by index
* \return A const reference to the system
*
* \param index Index of the system
*
* \remark The world must have the system before calling this function
*/
inline const BaseSystem& World::GetSystem(SystemIndex index) const
{
NazaraAssert(HasSystem(index), "This system is not part of the world");
const BaseSystem* system = m_systems[index].get();
NazaraAssert(system, "Invalid system pointer");
return *system;
}
/*! /*!
* \brief Gets a system in the world by type * \brief Gets a system in the world by type
* \return A reference to the system * \return A reference to the system
* *
* \remark Produces a NazaraAssert if system is not available in this world * \remark Produces a NazaraAssert if system is not available in this world
*/ */
template<typename SystemType> template<typename SystemType>
SystemType& World::GetSystem() SystemType& World::GetSystem()
{ {
@ -206,6 +256,21 @@ namespace Ndk
return static_cast<SystemType&>(GetSystem(index)); return static_cast<SystemType&>(GetSystem(index));
} }
/*!
* \brief Gets a system in the world by type
* \return A const reference to the system
*
* \remark Produces a NazaraAssert if system is not available in this world
*/
template<typename SystemType>
const SystemType& World::GetSystem() const
{
static_assert(std::is_base_of<BaseSystem, SystemType>::value, "SystemType is not a system");
SystemIndex index = GetSystemIndex<SystemType>();
return static_cast<const SystemType&>(GetSystem(index));
}
/*! /*!
* \brief Checks whether or not a system is present in the world by index * \brief Checks whether or not a system is present in the world by index
* \return true If it is the case * \return true If it is the case
@ -361,7 +426,7 @@ namespace Ndk
m_orderedSystems = std::move(world.m_orderedSystems); m_orderedSystems = std::move(world.m_orderedSystems);
m_orderedSystemsUpdated = world.m_orderedSystemsUpdated; m_orderedSystemsUpdated = world.m_orderedSystemsUpdated;
m_profilerData = std::move(world.m_profilerData); m_profilerData = std::move(world.m_profilerData);
m_isProfilerEnabled = m_isProfilerEnabled; m_isProfilerEnabled = world.m_isProfilerEnabled;
m_entities = std::move(world.m_entities); m_entities = std::move(world.m_entities);
for (EntityBlock& block : m_entities) for (EntityBlock& block : m_entities)

View File

@ -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(); m_backgroundEntity = CreateEntity(false);
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);
@ -147,26 +147,30 @@ namespace Ndk
else else
UnregisterFromCanvas(); UnregisterFromCanvas();
for (const EntityHandle& entity : m_entities) for (WidgetEntity& entity : m_entities)
entity->Enable(show); entity.handle->Enable(show);
for (const auto& widgetPtr : m_children) for (const auto& widgetPtr : m_children)
widgetPtr->Show(show); widgetPtr->Show(show);
} }
} }
const Ndk::EntityHandle& BaseWidget::CreateEntity() const Ndk::EntityHandle& BaseWidget::CreateEntity(bool isContentEntity)
{ {
const EntityHandle& newEntity = m_world->CreateEntity(); const EntityHandle& newEntity = m_world->CreateEntity();
newEntity->Enable(m_visible); newEntity->Enable(m_visible);
m_entities.emplace_back(newEntity); m_entities.emplace_back();
WidgetEntity& widgetEntity = m_entities.back();
widgetEntity.handle = newEntity;
widgetEntity.isContent = isContentEntity;
return newEntity; return newEntity;
} }
void BaseWidget::DestroyEntity(Entity* entity) void BaseWidget::DestroyEntity(Entity* entity)
{ {
auto it = std::find(m_entities.begin(), m_entities.end(), entity); auto it = std::find_if(m_entities.begin(), m_entities.end(), [&](const WidgetEntity& widgetEntity) { return widgetEntity.handle == entity; });
NazaraAssert(it != m_entities.end(), "Entity does not belong to this widget"); NazaraAssert(it != m_entities.end(), "Entity does not belong to this widget");
m_entities.erase(it); m_entities.erase(it);
@ -174,19 +178,17 @@ namespace Ndk
void BaseWidget::Layout() void BaseWidget::Layout()
{ {
if (IsRegisteredToCanvas())
m_canvas->NotifyWidgetBoxUpdate(m_canvasIndex);
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_contentSize.x + m_padding.left + m_padding.right, m_contentSize.y + m_padding.top + m_padding.bottom);
UpdatePositionAndSize();
} }
void BaseWidget::InvalidateNode() void BaseWidget::InvalidateNode()
{ {
Node::InvalidateNode(); Node::InvalidateNode();
if (IsRegisteredToCanvas()) UpdatePositionAndSize();
m_canvas->NotifyWidgetBoxUpdate(m_canvasIndex);
} }
bool BaseWidget::IsFocusable() const bool BaseWidget::IsFocusable() const
@ -271,4 +273,25 @@ namespace Ndk
m_canvasIndex = InvalidCanvasIndex; m_canvasIndex = InvalidCanvasIndex;
} }
} }
void BaseWidget::UpdatePositionAndSize()
{
if (IsRegisteredToCanvas())
m_canvas->NotifyWidgetBoxUpdate(m_canvasIndex);
Nz::Vector2f widgetPos = Nz::Vector2f(GetPosition());
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 contentBounds(Nz::Rectf(contentPos.x, contentPos.y, contentSize.x, contentSize.y));
for (WidgetEntity& widgetEntity : m_entities)
{
const Ndk::EntityHandle& entity = widgetEntity.handle;
if (entity->HasComponent<GraphicsComponent>())
entity->GetComponent<GraphicsComponent>().SetScissorRect((widgetEntity.isContent) ? contentBounds : fullBounds);
}
}
} }

View File

@ -59,6 +59,7 @@ namespace Ndk
Nz::PhysWorld2D& physWorld = entityWorld->GetSystem<PhysicsSystem2D>().GetWorld(); Nz::PhysWorld2D& physWorld = entityWorld->GetSystem<PhysicsSystem2D>().GetWorld();
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())));
Nz::Matrix4f matrix; Nz::Matrix4f matrix;
if (m_entity->HasComponent<NodeComponent>()) if (m_entity->HasComponent<NodeComponent>())

View File

@ -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;
}

View File

@ -35,7 +35,7 @@ namespace Ndk
object.dataUpdated = true; object.dataUpdated = true;
} }
object.renderable->AddToRenderQueue(renderQueue, object.data); object.renderable->AddToRenderQueue(renderQueue, object.data, m_scissorRect);
} }
} }
@ -277,12 +277,13 @@ namespace Ndk
{ {
Nz::Boxf localBox = boundingVolume.obb.localBox; Nz::Boxf localBox = boundingVolume.obb.localBox;
Nz::Vector3f newPos = r.data.localMatrix * localBox.GetPosition(); Nz::Vector3f newPos = r.data.localMatrix * localBox.GetPosition();
Nz::Vector3f newLengths = r.data.localMatrix * localBox.GetLengths(); Nz::Vector3f newCorner = r.data.localMatrix * (localBox.GetPosition() + localBox.GetLengths());
Nz::Vector3f newLengths = newCorner - newPos;
boundingVolume.Set(Nz::Boxf(newPos.x, newPos.y, newPos.z, newLengths.x, newLengths.y, newLengths.z)); boundingVolume.Set(Nz::Boxf(newPos.x, newPos.y, newPos.z, newLengths.x, newLengths.y, newLengths.z));
} }
m_boundingVolume.ExtendTo(r.renderable->GetBoundingVolume()); m_boundingVolume.ExtendTo(boundingVolume);
} }
RenderSystem& renderSystem = m_entity->GetWorld()->GetSystem<RenderSystem>(); RenderSystem& renderSystem = m_entity->GetWorld()->GetSystem<RenderSystem>();

View File

@ -8,6 +8,7 @@
#include <NDK/Components/CollisionComponent2D.hpp> #include <NDK/Components/CollisionComponent2D.hpp>
#include <NDK/Components/NodeComponent.hpp> #include <NDK/Components/NodeComponent.hpp>
#include <NDK/Systems/PhysicsSystem2D.hpp> #include <NDK/Systems/PhysicsSystem2D.hpp>
#include <memory>
namespace Ndk namespace Ndk
{ {
@ -40,8 +41,9 @@ namespace Ndk
else else
matrix.MakeIdentity(); matrix.MakeIdentity();
m_object.reset(new Nz::RigidBody2D(&world, 1.f, geom)); m_object = std::make_unique<Nz::RigidBody2D>(&world, 1.f, geom);
m_object->SetPosition(Nz::Vector2f(matrix.GetTranslation())); m_object->SetPosition(Nz::Vector2f(matrix.GetTranslation()));
m_object->SetUserdata(reinterpret_cast<void*>(static_cast<std::ptrdiff_t>(m_entity->GetId())));
} }
/*! /*!

View File

@ -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)

View File

@ -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>();

View File

@ -0,0 +1,366 @@
// 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::MaterialRef mat, Nz::IndexBufferRef indexBuffer, Nz::VertexBufferRef vertexBuffer) :
m_entityOwner(owner),
m_material(std::move(mat)),
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
{
m_boundingVolume.MakeNull();
}
protected:
Ndk::EntityHandle m_entityOwner;
Nz::IndexBufferRef m_indexBuffer;
Nz::MaterialRef m_material;
Nz::MeshData m_meshData;
Nz::VertexBufferRef m_vertexBuffer;
};
class AABBDebugRenderable : public DebugRenderable
{
public:
using DebugRenderable::DebugRenderable;
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>();
Nz::Matrix4f transformMatrix = Nz::Matrix4f::Identity();
transformMatrix.SetScale(entityGfx.GetBoundingVolume().aabb.GetLengths());
transformMatrix.SetTranslation(entityGfx.GetBoundingVolume().aabb.GetCenter());
renderQueue->AddMesh(0, m_material, m_meshData, Nz::Boxf::Zero(), transformMatrix, scissorRect);
}
};
class OBBDebugRenderable : public DebugRenderable
{
public:
using DebugRenderable::DebugRenderable;
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>();
Nz::Matrix4f transformMatrix = instanceData.transformMatrix;
transformMatrix.ApplyScale(entityGfx.GetBoundingVolume().obb.localBox.GetLengths());
renderQueue->AddMesh(0, m_material, m_meshData, Nz::Boxf::Zero(), transformMatrix, scissorRect);
}
};
}
/*!
* \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>();
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>();
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.GetBoundingVolume().obb.localBox;
Nz::InstancedRenderableRef renderable = GenerateCollision3DMesh(entity);
if (renderable)
{
renderable->SetPersistent(false);
entityGfx.Attach(renderable, Nz::Matrix4f::Translate(obb.GetCenter()), DebugDrawOrder);
}
entityDebug.UpdateDebugRenderable(option, std::move(renderable));
break;
}
case DebugDraw::GraphicsAABB:
{
auto indexVertexBuffers = GetBoxMesh();
Nz::InstancedRenderableRef renderable = new AABBDebugRenderable(entity, GetAABBMaterial(), 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(mesh);
subMesh->Create(vertexBuffer);
subMesh->SetIndexBuffer(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::GetAABBMaterial()
{
if (!m_aabbMaterial)
{
m_aabbMaterial = Nz::Material::New();
m_aabbMaterial->EnableFaceCulling(false);
m_aabbMaterial->EnableDepthBuffer(true);
m_aabbMaterial->SetDiffuseColor(Nz::Color::Red);
m_aabbMaterial->SetFaceFilling(Nz::FaceFilling_Line);
}
return m_aabbMaterial;
}
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);
}
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);
}
return m_obbMaterial;
}
SystemIndex DebugSystem::systemIndex;
}

View File

@ -6,7 +6,6 @@
#include <Nazara/Audio/Audio.hpp> #include <Nazara/Audio/Audio.hpp>
#include <NDK/Components/ListenerComponent.hpp> #include <NDK/Components/ListenerComponent.hpp>
#include <NDK/Components/NodeComponent.hpp> #include <NDK/Components/NodeComponent.hpp>
#include <NDK/Components/VelocityComponent.hpp>
namespace Ndk namespace Ndk
{ {
@ -34,7 +33,7 @@ namespace Ndk
* \param elapsedTime Delta time used for the update * \param elapsedTime Delta time used for the update
*/ */
void ListenerSystem::OnUpdate(float /*elapsedTime*/) void ListenerSystem::OnUpdate(float elapsedTime)
{ {
std::size_t activeListenerCount = 0; std::size_t activeListenerCount = 0;
@ -45,18 +44,18 @@ namespace Ndk
if (!listener.IsActive()) if (!listener.IsActive())
continue; continue;
Nz::Vector3f oldPos = Nz::Audio::GetListenerPosition();
// We get the position and the rotation to affect these to the listener // We get the position and the rotation to affect these to the listener
const NodeComponent& node = entity->GetComponent<NodeComponent>(); const NodeComponent& node = entity->GetComponent<NodeComponent>();
Nz::Audio::SetListenerPosition(node.GetPosition(Nz::CoordSys_Global)); Nz::Vector3f newPos = node.GetPosition(Nz::CoordSys_Global);
Nz::Audio::SetListenerPosition(newPos);
Nz::Audio::SetListenerRotation(node.GetRotation(Nz::CoordSys_Global)); Nz::Audio::SetListenerRotation(node.GetRotation(Nz::CoordSys_Global));
// We verify the presence of a component of velocity // Compute listener velocity based on their old/new position
// (The listener'speed does not move it, but disturbs the sound like Doppler effect) Nz::Vector3f velocity = (newPos - oldPos) / elapsedTime;
if (entity->HasComponent<VelocityComponent>()) Nz::Audio::SetListenerVelocity(velocity);
{
const VelocityComponent& velocity = entity->GetComponent<VelocityComponent>();
Nz::Audio::SetListenerVelocity(velocity.linearVelocity);
}
activeListenerCount++; activeListenerCount++;
} }

View File

@ -206,7 +206,7 @@ namespace Ndk
std::size_t visibilityHash = m_drawableCulling.Cull(camComponent.GetFrustum(), &forceInvalidation); std::size_t visibilityHash = m_drawableCulling.Cull(camComponent.GetFrustum(), &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)

View File

@ -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(); m_gradientEntity = CreateEntity(false);
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(); m_textEntity = CreateEntity(true);
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);
@ -82,12 +82,11 @@ namespace Ndk
{ {
BaseWidget::Layout(); BaseWidget::Layout();
m_gradientSprite->SetSize(GetSize());
Nz::Vector2f origin = GetContentOrigin(); Nz::Vector2f origin = GetContentOrigin();
const Nz::Vector2f& contentSize = GetContentSize(); const Nz::Vector2f& contentSize = GetContentSize();
m_gradientEntity->GetComponent<NodeComponent>().SetPosition(origin);
m_gradientSprite->SetSize(contentSize);
Nz::Boxf textBox = m_textEntity->GetComponent<GraphicsComponent>().GetBoundingVolume().obb.localBox; 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); m_textEntity->GetComponent<NodeComponent>().SetPosition(origin.x + contentSize.x / 2 - textBox.width / 2, origin.y + contentSize.y / 2 - textBox.height / 2);
} }

View File

@ -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(); m_checkboxBorderEntity = CreateEntity(false);
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(); m_checkboxBackgroundEntity = CreateEntity(false);
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(); m_checkboxContentEntity = CreateEntity(true);
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(); m_textEntity = CreateEntity(true);
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);

View File

@ -11,7 +11,7 @@ namespace Ndk
ImageWidget::ImageWidget(BaseWidget* parent) : ImageWidget::ImageWidget(BaseWidget* parent) :
BaseWidget(parent) BaseWidget(parent)
{ {
m_entity = CreateEntity(); m_entity = CreateEntity(true);
m_entity->AddComponent<NodeComponent>(); m_entity->AddComponent<NodeComponent>();
auto& gfx = m_entity->AddComponent<GraphicsComponent>(); auto& gfx = m_entity->AddComponent<GraphicsComponent>();

View File

@ -13,13 +13,20 @@ namespace Ndk
{ {
m_textSprite = Nz::TextSprite::New(); m_textSprite = Nz::TextSprite::New();
m_textEntity = CreateEntity(); m_textEntity = CreateEntity(true);
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() void LabelWidget::ResizeToContent()
{ {
SetContentSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths())); SetContentSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths()));

View File

@ -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
@ -30,11 +30,11 @@ namespace Ndk
SetBarColor(s_barColor, s_barCornerColor); SetBarColor(s_barColor, s_barCornerColor);
m_borderEntity = CreateEntity(); m_borderEntity = CreateEntity(false);
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(); m_barEntity = CreateEntity(true);
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(); m_textEntity = CreateEntity(true);
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);

View File

@ -12,22 +12,20 @@ namespace Ndk
TextAreaWidget::TextAreaWidget(BaseWidget* parent) : TextAreaWidget::TextAreaWidget(BaseWidget* parent) :
BaseWidget(parent), BaseWidget(parent),
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_cursorSprite = Nz::Sprite::New(); m_cursorEntity = CreateEntity(true);
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();
m_cursorEntity->AddComponent<GraphicsComponent>().Attach(m_cursorSprite, 10);
m_cursorEntity->AddComponent<NodeComponent>().SetParent(this); m_cursorEntity->AddComponent<NodeComponent>().SetParent(this);
m_cursorEntity->Enable(false); m_cursorEntity->Enable(false);
m_textSprite = Nz::TextSprite::New(); m_textSprite = Nz::TextSprite::New();
m_textEntity = CreateEntity(); m_textEntity = CreateEntity(true);
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);
@ -72,7 +70,29 @@ namespace Ndk
OnTextChanged(this, m_text); OnTextChanged(this, m_text);
} }
std::size_t TextAreaWidget::GetHoveredGlyph(float x, float y) const void TextAreaWidget::EraseSelection()
{
if (!HasSelection())
return;
std::size_t cursorGlyphBegin = GetGlyphIndex(m_cursorPositionBegin);
std::size_t cursorGlyphEnd = GetGlyphIndex(m_cursorPositionEnd);
std::size_t textLength = m_text.GetLength();
if (cursorGlyphBegin > textLength)
return;
Nz::String newText;
if (cursorGlyphBegin > 0)
newText.Append(m_text.SubString(0, m_text.GetCharacterPosition(cursorGlyphBegin) - 1));
if (cursorGlyphEnd < textLength)
newText.Append(m_text.SubString(m_text.GetCharacterPosition(cursorGlyphEnd)));
SetText(newText);
}
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 +108,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,10 +117,10 @@ namespace Ndk
break; break;
} }
return i; return Nz::Vector2ui(i - firstLineGlyph, line);
} }
return 0; return Nz::Vector2ui::Zero();
} }
void TextAreaWidget::ResizeToContent() void TextAreaWidget::ResizeToContent()
@ -109,7 +130,7 @@ namespace Ndk
void TextAreaWidget::Write(const Nz::String& text) void TextAreaWidget::Write(const Nz::String& text)
{ {
std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition); std::size_t cursorGlyph = GetGlyphIndex(m_cursorPositionBegin);
if (cursorGlyph >= m_drawer.GetGlyphCount()) if (cursorGlyph >= m_drawer.GetGlyphCount())
{ {
@ -156,20 +177,27 @@ namespace Ndk
{ {
case Nz::Keyboard::Delete: case Nz::Keyboard::Delete:
{ {
std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition); if (HasSelection())
EraseSelection();
else
{
std::size_t cursorGlyphBegin = GetGlyphIndex(m_cursorPositionBegin);
std::size_t cursorGlyphEnd = GetGlyphIndex(m_cursorPositionEnd);
std::size_t textLength = m_text.GetLength(); std::size_t textLength = m_text.GetLength();
if (cursorGlyph > textLength) if (cursorGlyphBegin > textLength)
return true; return true;
Nz::String newText; Nz::String newText;
if (cursorGlyph > 0) if (cursorGlyphBegin > 0)
newText.Append(m_text.SubString(0, m_text.GetCharacterPosition(cursorGlyph) - 1)); newText.Append(m_text.SubString(0, m_text.GetCharacterPosition(cursorGlyphBegin) - 1));
if (cursorGlyph < textLength) if (cursorGlyphEnd < textLength)
newText.Append(m_text.SubString(m_text.GetCharacterPosition(cursorGlyph + 1))); newText.Append(m_text.SubString(m_text.GetCharacterPosition(cursorGlyphEnd + 1)));
SetText(newText);
}
SetText(newText);
return true; return true;
} }
@ -181,10 +209,38 @@ 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;
const auto& lineInfo = m_drawer.GetLine(m_cursorPositionEnd.y);
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, m_cursorPositionEnd.y });
return true;
}
case Nz::Keyboard::Left: case Nz::Keyboard::Left:
{ {
bool ignoreDefaultAction = false; bool ignoreDefaultAction = false;
@ -193,7 +249,11 @@ namespace Ndk
if (ignoreDefaultAction) if (ignoreDefaultAction)
return true; return true;
MoveCursor(-1); if (HasSelection())
SetCursorPosition(m_cursorPositionBegin);
else
MoveCursor(-1);
return true; return true;
} }
@ -205,7 +265,11 @@ namespace Ndk
if (ignoreDefaultAction) if (ignoreDefaultAction)
return true; return true;
MoveCursor(1); if (HasSelection())
SetCursorPosition(m_cursorPositionEnd);
else
MoveCursor(1);
return true; return true;
} }
@ -217,6 +281,9 @@ 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;
} }
@ -236,7 +303,40 @@ namespace Ndk
{ {
SetFocus(); SetFocus();
SetCursorPosition(GetHoveredGlyph(float(x), float(y))); const Padding& padding = GetPadding();
Nz::Vector2ui hoveredGlyph = 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)
{
const Padding& padding = GetPadding();
SetSelection(m_selectionCursor, GetHoveredGlyph(float(x - padding.left), float(y - padding.top)));
} }
} }
@ -252,20 +352,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;
} }
@ -287,6 +397,9 @@ namespace Ndk
if (Nz::Unicode::GetCategory(character) == Nz::Unicode::Category_Other_Control) if (Nz::Unicode::GetCategory(character) == Nz::Unicode::Category_Other_Control)
break; break;
if (HasSelection())
EraseSelection();
Write(Nz::String::Unicode(character)); Write(Nz::String::Unicode(character));
break; break;
} }
@ -298,24 +411,68 @@ namespace Ndk
if (m_readOnly) if (m_readOnly)
return; return;
const auto& lineInfo = m_drawer.GetLine(m_cursorPosition.y); m_cursorEntity->GetComponent<NodeComponent>().SetPosition(GetContentOrigin());
std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition);
std::size_t glyphCount = m_drawer.GetGlyphCount(); std::size_t selectionLineCount = m_cursorPositionEnd.y - m_cursorPositionBegin.y + 1;
float position; std::size_t oldSpriteCount = m_cursorSprites.size();
if (glyphCount > 0 && lineInfo.glyphIndex < cursorGlyph) if (m_cursorSprites.size() != selectionLineCount)
{ {
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()
@ -334,6 +491,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)
} }
} }

View File

@ -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>();

View File

@ -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"

View File

@ -1,7 +1,7 @@
NazaraBuild = {} NazaraBuild = {}
-- I wish Premake had a way to know the compiler in advance -- I wish Premake had a way to know the compiler in advance
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) table.insert(self.ExecutableDir, path)
@ -13,16 +13,16 @@ function NazaraBuild:AddInstallPath(path)
end end
function NazaraBuild:FilterLibDirectory(prefix, func) function NazaraBuild:FilterLibDirectory(prefix, func)
filter({"action:codeblocks or codelite or gmake", "architecture:x86", "system:Windows"}) filter({"action:codeblocks or codelite or gmake*", "architecture:x86", "system:Windows"})
func(prefix .. "mingw/x86") func(prefix .. "mingw/x86")
filter({"action:codeblocks or codelite or gmake", "architecture:x86_64", "system:Windows"}) filter({"action:codeblocks or codelite or gmake*", "architecture:x86_64", "system:Windows"})
func(prefix .. "mingw/x64") func(prefix .. "mingw/x64")
filter({"action:codeblocks or codelite or gmake", "architecture:x86", "system:not Windows"}) filter({"action:codeblocks or codelite or gmake*", "architecture:x86", "system:not Windows"})
func(prefix .. "gmake/x86") func(prefix .. "gmake/x86")
filter({"action:codeblocks or codelite or gmake", "architecture:x86_64", "system:not Windows"}) filter({"action:codeblocks or codelite or gmake*", "architecture:x86_64", "system:not Windows"})
func(prefix .. "gmake/x64") func(prefix .. "gmake/x64")
filter({"action:vs*", "architecture:x86"}) filter({"action:vs*", "architecture:x86"})

View File

@ -1,5 +1,7 @@
MODULE.Name = "Platform" MODULE.Name = "Platform"
MODULE.ClientOnly = true
MODULE.Libraries = { MODULE.Libraries = {
"NazaraCore", "NazaraCore",
"NazaraUtility" "NazaraUtility"

View File

@ -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.*",

View File

@ -324,12 +324,11 @@ int main()
// Début de la boucle de rendu du programme (s'occupant par exemple de mettre à jour le monde) // Début de la boucle de rendu du programme (s'occupant par exemple de mettre à jour le monde)
while (application.Run()) while (application.Run())
{ {
Nz::UInt64 elapsedUs = updateClock.Restart();
Nz::UInt64 elapsedUS = updateClock.Restart() / 1'000'000;
// Mise à jour (Caméra) // Mise à jour (Caméra)
const Nz::UInt64 updateRate = 1000000 / 60; // 60 fois par seconde const Nz::UInt64 updateRate = 1000000 / 60; // 60 fois par seconde
updateAccumulator += elapsedUS; updateAccumulator += elapsedUs;
if (updateAccumulator >= updateRate) if (updateAccumulator >= updateRate)
{ {

View File

@ -113,7 +113,7 @@ class SpriteRenderer : public Nz::ParticleRenderer
Nz::SparsePtr<const Nz::Vector2f> sizePtr(&size, 0); Nz::SparsePtr<const Nz::Vector2f> sizePtr(&size, 0);
Nz::SparsePtr<const Nz::Vector2f> sinCosPtr(nullptr, 0); Nz::SparsePtr<const Nz::Vector2f> sinCosPtr(nullptr, 0);
renderQueue->AddBillboards(0, m_material, endId - startId + 1, mapper.GetComponentPtr<const Nz::Vector3f>(Nz::ParticleComponent_Position), sizePtr, sinCosPtr, mapper.GetComponentPtr<const Nz::Color>(Nz::ParticleComponent_Color)); renderQueue->AddBillboards(0, m_material, endId - startId + 1, Nz::Recti(-1, -1), mapper.GetComponentPtr<const Nz::Vector3f>(Nz::ParticleComponent_Position), sizePtr, sinCosPtr, mapper.GetComponentPtr<const Nz::Color>(Nz::ParticleComponent_Color));
} }
private: private:

View File

@ -267,6 +267,8 @@ ParticleDemo("Space battle", sharedData)
if (!m_spacestationModel.LoadFromFile("resources/SpaceStation/space_station.obj", parameters)) if (!m_spacestationModel.LoadFromFile("resources/SpaceStation/space_station.obj", parameters))
NazaraWarning("Failed to load space_station.obj"); NazaraWarning("Failed to load space_station.obj");
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));
@ -343,7 +345,7 @@ void SpacebattleExample::Enter(Ndk::StateMachine& fsm)
CreateSpaceShip(); CreateSpaceShip();
CreateTurret(); CreateTurret();
Ndk::EntityHandle light = m_shared.world3D->CreateEntity(); const Ndk::EntityHandle& light = m_shared.world3D->CreateEntity();
Ndk::NodeComponent& lightNode = light->AddComponent<Ndk::NodeComponent>(); Ndk::NodeComponent& lightNode = light->AddComponent<Ndk::NodeComponent>();
Ndk::LightComponent& lightComp = light->AddComponent<Ndk::LightComponent>(Nz::LightType_Directional); Ndk::LightComponent& lightComp = light->AddComponent<Ndk::LightComponent>(Nz::LightType_Directional);
lightNode.SetRotation(Nz::EulerAnglesf(-30.f, 0.f, 0.f)); lightNode.SetRotation(Nz::EulerAnglesf(-30.f, 0.f, 0.f));
@ -360,7 +362,7 @@ void SpacebattleExample::Enter(Ndk::StateMachine& fsm)
m_turretCannonBaseRotation = 0.f; m_turretCannonBaseRotation = 0.f;
m_turretShootTimer = 0.f; m_turretShootTimer = 0.f;
Ndk::EntityHandle torpedoGroupEntity = m_shared.world3D->CreateEntity(); const Ndk::EntityHandle& torpedoGroupEntity = m_shared.world3D->CreateEntity();
m_torpedoGroup = torpedoGroupEntity->AddComponent<Ndk::ParticleGroupComponent>(200, m_torpedoDeclaration).CreateHandle(); m_torpedoGroup = torpedoGroupEntity->AddComponent<Ndk::ParticleGroupComponent>(200, m_torpedoDeclaration).CreateHandle();
RegisterParticleGroup(torpedoGroupEntity); RegisterParticleGroup(torpedoGroupEntity);
@ -471,7 +473,7 @@ void SpacebattleExample::Enter(Ndk::StateMachine& fsm)
auto rotationPtr = mapper.GetComponentPtr<const float>(Nz::ParticleComponent_Rotation); auto rotationPtr = mapper.GetComponentPtr<const float>(Nz::ParticleComponent_Rotation);
auto sizePtr = mapper.GetComponentPtr<const Nz::Vector2f>(Nz::ParticleComponent_Size); auto sizePtr = mapper.GetComponentPtr<const Nz::Vector2f>(Nz::ParticleComponent_Size);
renderQueue->AddBillboards(0, sparkleMat1, endId - startId + 1, positionPtr, sizePtr, rotationPtr); renderQueue->AddBillboards(0, sparkleMat1, endId - startId + 1, Nz::Recti(-1, -1), positionPtr, sizePtr, rotationPtr);
for (unsigned int i = startId; i <= endId; ++i) for (unsigned int i = startId; i <= endId; ++i)
{ {
Nz::AbstractRenderQueue::PointLight pointLight; Nz::AbstractRenderQueue::PointLight pointLight;
@ -607,6 +609,7 @@ void SpacebattleExample::Enter(Ndk::StateMachine& fsm)
fireMat->EnableFaceCulling(true); fireMat->EnableFaceCulling(true);
fireMat->SetDiffuseMap("resources/fire_particle.png"); fireMat->SetDiffuseMap("resources/fire_particle.png");
// Additive blending for fire // Additive blending for fire
fireMat->EnableDepthSorting(false); //< No need for depth sort
fireMat->SetDstBlend(Nz::BlendFunc_One); fireMat->SetDstBlend(Nz::BlendFunc_One);
fireMat->SetSrcBlend(Nz::BlendFunc_SrcAlpha); fireMat->SetSrcBlend(Nz::BlendFunc_SrcAlpha);
@ -622,7 +625,7 @@ void SpacebattleExample::Enter(Ndk::StateMachine& fsm)
auto rotPtr = mapper.GetComponentPtr<const float>(Nz::ParticleComponent_Rotation); auto rotPtr = mapper.GetComponentPtr<const float>(Nz::ParticleComponent_Rotation);
auto sizePtr = mapper.GetComponentPtr<const Nz::Vector2f>(Nz::ParticleComponent_Size); auto sizePtr = mapper.GetComponentPtr<const Nz::Vector2f>(Nz::ParticleComponent_Size);
renderQueue->AddBillboards(0, fireMat, endId - startId + 1, posPtr, sizePtr, rotPtr, colorPtr); renderQueue->AddBillboards(0, fireMat, endId - startId + 1, Nz::Recti(-1, -1), posPtr, sizePtr, rotPtr, colorPtr);
})); }));
m_smokeGroup->SetRenderer(Nz::ParticleFunctionRenderer::New([smokeMat] (const Nz::ParticleGroup& /*group*/, const Nz::ParticleMapper& mapper, unsigned int startId, unsigned int endId, Nz::AbstractRenderQueue* renderQueue) m_smokeGroup->SetRenderer(Nz::ParticleFunctionRenderer::New([smokeMat] (const Nz::ParticleGroup& /*group*/, const Nz::ParticleMapper& mapper, unsigned int startId, unsigned int endId, Nz::AbstractRenderQueue* renderQueue)
@ -632,7 +635,7 @@ void SpacebattleExample::Enter(Ndk::StateMachine& fsm)
auto rotPtr = mapper.GetComponentPtr<const float>(Nz::ParticleComponent_Rotation); auto rotPtr = mapper.GetComponentPtr<const float>(Nz::ParticleComponent_Rotation);
auto sizePtr = mapper.GetComponentPtr<const Nz::Vector2f>(Nz::ParticleComponent_Size); auto sizePtr = mapper.GetComponentPtr<const Nz::Vector2f>(Nz::ParticleComponent_Size);
renderQueue->AddBillboards(0, smokeMat, endId - startId + 1, posPtr, sizePtr, rotPtr, colorPtr); renderQueue->AddBillboards(0, smokeMat, endId - startId + 1, Nz::Recti(-1, -1), posPtr, sizePtr, rotPtr, colorPtr);
})); }));
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -647,6 +650,7 @@ void SpacebattleExample::Enter(Ndk::StateMachine& fsm)
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
Nz::TextSpriteRef introText = Nz::TextSprite::New(); Nz::TextSpriteRef introText = Nz::TextSprite::New();
introText->SetMaterial(Nz::Material::New("Translucent3D"));
introText->Update(Nz::SimpleTextDrawer::Draw("--Tourelle de défense du secteur A407M2--\nLes contrôles ont été adaptés à vos contrôleurs:\nLa souris contrôle l'orientation de la tourelle, cliquez pour tirer.\n", 72)); introText->Update(Nz::SimpleTextDrawer::Draw("--Tourelle de défense du secteur A407M2--\nLes contrôles ont été adaptés à vos contrôleurs:\nLa souris contrôle l'orientation de la tourelle, cliquez pour tirer.\n", 72));
introText->SetScale(0.5f); introText->SetScale(0.5f);

View File

@ -59,7 +59,7 @@ int main()
shared.particleCount->Update(Nz::SimpleTextDrawer::Draw("XXXXX particles", 36)); shared.particleCount->Update(Nz::SimpleTextDrawer::Draw("XXXXX particles", 36));
world2D.GetSystem<Ndk::RenderSystem>().SetGlobalUp(Nz::Vector3f::Down()); world2D.GetSystem<Ndk::RenderSystem>().SetGlobalUp(Nz::Vector3f::Down());
//world3D.GetSystem<Ndk::RenderSystem>().ChangeRenderTechnique<Nz::DeferredRenderTechnique>(); world3D.GetSystem<Ndk::RenderSystem>().ChangeRenderTechnique<Nz::DeferredRenderTechnique>();
Ndk::EntityHandle viewEntity = world2D.CreateEntity(); Ndk::EntityHandle viewEntity = world2D.CreateEntity();

View File

@ -22,8 +22,8 @@ namespace Nz
void MixToMono(T* input, T* output, UInt32 channelCount, UInt64 frameCount) void MixToMono(T* input, T* output, UInt32 channelCount, UInt64 frameCount)
{ {
// To avoid overflow, we use, as an accumulator, a type which is large enough: (u)int 64 bits for integers, double for floatings // To avoid overflow, we use, as an accumulator, a type which is large enough: (u)int 64 bits for integers, double for floatings
typedef typename std::conditional<std::is_unsigned<T>::value, UInt64, Int64>::type BiggestInt; using BiggestInt = typename std::conditional<std::is_unsigned<T>::value, UInt64, Int64>::type;
typedef typename std::conditional<std::is_integral<T>::value, BiggestInt, double>::type Biggest; using Biggest = typename std::conditional<std::is_integral<T>::value, BiggestInt, double>::type;
for (UInt64 i = 0; i < frameCount; ++i) for (UInt64 i = 0; i < frameCount; ++i)
{ {

View File

@ -38,7 +38,7 @@ namespace Nz
public: public:
Music() = default; Music() = default;
Music(const Music&) = delete; Music(const Music&) = delete;
Music(Music&&) = delete; Music(Music&&) noexcept = default;
~Music(); ~Music();
bool Create(SoundStream* soundStream); bool Create(SoundStream* soundStream);
@ -67,10 +67,10 @@ namespace Nz
void Stop() override; void Stop() override;
Music& operator=(const Music&) = delete; Music& operator=(const Music&) = delete;
Music& operator=(Music&&) = delete; Music& operator=(Music&&) noexcept = default;
private: private:
MovablePtr<MusicImpl> m_impl = nullptr; MovablePtr<MusicImpl> m_impl;
bool FillAndQueueBuffer(unsigned int buffer); bool FillAndQueueBuffer(unsigned int buffer);
void MusicThread(); void MusicThread();

View File

@ -20,7 +20,7 @@ namespace Nz
Sound() = default; Sound() = default;
Sound(const SoundBuffer* soundBuffer); Sound(const SoundBuffer* soundBuffer);
Sound(const Sound& sound); Sound(const Sound& sound);
Sound(Sound&&) = default; Sound(Sound&&) noexcept = default;
~Sound(); ~Sound();
void EnableLooping(bool loop) override; void EnableLooping(bool loop) override;
@ -47,7 +47,7 @@ namespace Nz
void Stop() override; void Stop() override;
Sound& operator=(const Sound&) = delete; ///TODO? Sound& operator=(const Sound&) = delete; ///TODO?
Sound& operator=(Sound&&) = default; Sound& operator=(Sound&&) noexcept = default;
private: private:
SoundBufferConstRef m_buffer; SoundBufferConstRef m_buffer;

View File

@ -11,6 +11,7 @@
#include <Nazara/Audio/Config.hpp> #include <Nazara/Audio/Config.hpp>
#include <Nazara/Audio/Enums.hpp> #include <Nazara/Audio/Enums.hpp>
#include <Nazara/Math/Vector3.hpp> #include <Nazara/Math/Vector3.hpp>
#include <limits>
///TODO: Inherit SoundEmitter from Node ///TODO: Inherit SoundEmitter from Node
@ -19,6 +20,7 @@ namespace Nz
class NAZARA_AUDIO_API SoundEmitter class NAZARA_AUDIO_API SoundEmitter
{ {
public: public:
SoundEmitter(SoundEmitter&& emitter) noexcept;
virtual ~SoundEmitter(); virtual ~SoundEmitter();
virtual void EnableLooping(bool loop) = 0; virtual void EnableLooping(bool loop) = 0;
@ -51,16 +53,17 @@ namespace Nz
virtual void Stop() = 0; virtual void Stop() = 0;
SoundEmitter& operator=(const SoundEmitter&) = delete; ///TODO SoundEmitter& operator=(const SoundEmitter&) = delete;
SoundEmitter& operator=(SoundEmitter&&) = delete; SoundEmitter& operator=(SoundEmitter&&) noexcept;
protected: protected:
SoundEmitter(); SoundEmitter();
SoundEmitter(const SoundEmitter& emitter); SoundEmitter(const SoundEmitter& emitter);
SoundEmitter(SoundEmitter&&) = delete;
SoundStatus GetInternalStatus() const; SoundStatus GetInternalStatus() const;
static constexpr unsigned int InvalidSource = std::numeric_limits<unsigned int>::max();
unsigned int m_source; unsigned int m_source;
}; };
} }

View File

@ -88,6 +88,7 @@
#include <Nazara/Core/StringStream.hpp> #include <Nazara/Core/StringStream.hpp>
#include <Nazara/Core/TaskScheduler.hpp> #include <Nazara/Core/TaskScheduler.hpp>
#include <Nazara/Core/Thread.hpp> #include <Nazara/Core/Thread.hpp>
#include <Nazara/Core/TypeTag.hpp>
#include <Nazara/Core/Unicode.hpp> #include <Nazara/Core/Unicode.hpp>
#include <Nazara/Core/Updatable.hpp> #include <Nazara/Core/Updatable.hpp>

View File

@ -10,6 +10,7 @@
#include <Nazara/Prerequisites.hpp> #include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/Enums.hpp> #include <Nazara/Core/Enums.hpp>
#include <Nazara/Core/SerializationContext.hpp> #include <Nazara/Core/SerializationContext.hpp>
#include <Nazara/Core/TypeTag.hpp>
#include <functional> #include <functional>
#include <string> #include <string>
#include <tuple> #include <tuple>
@ -37,19 +38,22 @@ namespace Nz
}; };
template<typename T> template<typename T>
struct TypeTag {}; bool Serialize(SerializationContext& context, T&& value);
inline bool Serialize(SerializationContext& context, bool value); inline bool Serialize(SerializationContext& context, bool value, TypeTag<bool>);
inline bool Serialize(SerializationContext& context, const std::string& value); inline bool Serialize(SerializationContext& context, const std::string& value, TypeTag<std::string>);
template<typename T> template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, bool> Serialize(SerializationContext& context, T value); std::enable_if_t<std::is_arithmetic<T>::value, bool> Serialize(SerializationContext& context, T value, TypeTag<T>);
inline bool Unserialize(SerializationContext& context, bool* value);
inline bool Unserialize(SerializationContext& context, std::string* value);
template<typename T> template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, bool> Unserialize(SerializationContext& context, T* value); bool Unserialize(SerializationContext& context, T* value);
inline bool Unserialize(SerializationContext& context, bool* value, TypeTag<bool>);
inline bool Unserialize(SerializationContext& context, std::string* value, TypeTag<std::string>);
template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, bool> Unserialize(SerializationContext& context, T* value, TypeTag<T>);
} }
#include <Nazara/Core/Algorithm.inl> #include <Nazara/Core/Algorithm.inl>

View File

@ -12,6 +12,7 @@
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Stream.hpp> #include <Nazara/Core/Stream.hpp>
#include <climits> #include <climits>
#include <utility>
#include <Nazara/Core/Debug.hpp> #include <Nazara/Core/Debug.hpp>
namespace Nz namespace Nz
@ -194,10 +195,17 @@ namespace Nz
return reversed; return reversed;
} }
template<typename T> struct PointedType<T*> {typedef T type;}; template<typename T> struct PointedType<T*> { using type = T; };
template<typename T> struct PointedType<T* const> {typedef T type;}; template<typename T> struct PointedType<T* const> { using type = T; };
template<typename T> struct PointedType<T* volatile> {typedef T type;}; template<typename T> struct PointedType<T* volatile> { using type = T; };
template<typename T> struct PointedType<T* const volatile> {typedef T type;}; template<typename T> struct PointedType<T* const volatile> { using type = T; };
template<typename T>
bool Serialize(SerializationContext& context, T&& value)
{
return Serialize(context, std::forward<T>(value), TypeTag<std::decay_t<T>>());
}
/*! /*!
* \ingroup core * \ingroup core
@ -209,7 +217,7 @@ namespace Nz
* *
* \see Serialize, Unserialize * \see Serialize, Unserialize
*/ */
inline bool Serialize(SerializationContext& context, bool value) inline bool Serialize(SerializationContext& context, bool value, TypeTag<bool>)
{ {
if (context.currentBitPos == 8) if (context.currentBitPos == 8)
{ {
@ -221,7 +229,7 @@ namespace Nz
context.currentByte |= 1 << context.currentBitPos; context.currentByte |= 1 << context.currentBitPos;
if (++context.currentBitPos >= 8) if (++context.currentBitPos >= 8)
return Serialize<UInt8>(context, context.currentByte); return Serialize(context, context.currentByte, TypeTag<UInt8>());
else else
return true; return true;
} }
@ -234,9 +242,9 @@ namespace Nz
* \param context Context for the serialization * \param context Context for the serialization
* \param value String to serialize * \param value String to serialize
*/ */
bool Serialize(SerializationContext& context, const std::string& value) bool Serialize(SerializationContext& context, const std::string& value, TypeTag<std::string>)
{ {
if (!Serialize(context, UInt32(value.size()))) if (!Serialize(context, UInt32(value.size()), TypeTag<UInt32>()))
return false; return false;
return context.stream->Write(value.data(), value.size()) == value.size(); return context.stream->Write(value.data(), value.size()) == value.size();
@ -253,7 +261,7 @@ namespace Nz
* \see Serialize, Unserialize * \see Serialize, Unserialize
*/ */
template<typename T> template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, bool> Serialize(SerializationContext& context, T value) std::enable_if_t<std::is_arithmetic<T>::value, bool> Serialize(SerializationContext& context, T value, TypeTag<T>)
{ {
// Flush bits in case a writing is in progress // Flush bits in case a writing is in progress
context.FlushBits(); context.FlushBits();
@ -264,6 +272,13 @@ namespace Nz
return context.stream->Write(&value, sizeof(T)) == sizeof(T); return context.stream->Write(&value, sizeof(T)) == sizeof(T);
} }
template<typename T>
bool Unserialize(SerializationContext& context, T* value)
{
return Unserialize(context, value, TypeTag<T>());
}
/*! /*!
* \ingroup core * \ingroup core
* \brief Unserializes a boolean * \brief Unserializes a boolean
@ -274,11 +289,11 @@ namespace Nz
* *
* \see Serialize, Unserialize * \see Serialize, Unserialize
*/ */
inline bool Unserialize(SerializationContext& context, bool* value) inline bool Unserialize(SerializationContext& context, bool* value, TypeTag<bool>)
{ {
if (context.currentBitPos == 8) if (context.currentBitPos == 8)
{ {
if (!Unserialize(context, &context.currentByte)) if (!Unserialize(context, &context.currentByte, TypeTag<UInt8>()))
return false; return false;
context.currentBitPos = 0; context.currentBitPos = 0;
@ -299,10 +314,10 @@ namespace Nz
* \param context Context of unserialization * \param context Context of unserialization
* \param string std::string to unserialize * \param string std::string to unserialize
*/ */
bool Unserialize(SerializationContext& context, std::string* string) bool Unserialize(SerializationContext& context, std::string* string, TypeTag<std::string>)
{ {
UInt32 size; UInt32 size;
if (!Unserialize(context, &size)) if (!Unserialize(context, &size, TypeTag<UInt32>()))
return false; return false;
string->resize(size); string->resize(size);
@ -322,7 +337,7 @@ namespace Nz
* \see Serialize, Unserialize * \see Serialize, Unserialize
*/ */
template<typename T> template<typename T>
std::enable_if_t<std::is_arithmetic<T>::value, bool> Unserialize(SerializationContext& context, T* value) std::enable_if_t<std::is_arithmetic<T>::value, bool> Unserialize(SerializationContext& context, T* value, TypeTag<T>)
{ {
NazaraAssert(value, "Invalid data pointer"); NazaraAssert(value, "Invalid data pointer");

View File

@ -51,9 +51,6 @@ namespace Nz
std::size_t GetCapacity() const; std::size_t GetCapacity() const;
std::size_t GetSize() const; std::size_t GetSize() const;
PointerSequence Read(const void* ptr, std::size_t bitCount);
PointerSequence Read(const PointerSequence& sequence, std::size_t bitCount);
void PerformsAND(const Bitset& a, const Bitset& b); void PerformsAND(const Bitset& a, const Bitset& b);
void PerformsNOT(const Bitset& a); void PerformsNOT(const Bitset& a);
void PerformsOR(const Bitset& a, const Bitset& b); void PerformsOR(const Bitset& a, const Bitset& b);
@ -90,6 +87,9 @@ namespace Nz
void UnboundedSet(std::size_t bit, bool val = true); void UnboundedSet(std::size_t bit, bool val = true);
bool UnboundedTest(std::size_t bit) const; bool UnboundedTest(std::size_t bit) const;
PointerSequence Write(const void* ptr, std::size_t bitCount);
PointerSequence Write(const PointerSequence& sequence, std::size_t bitCount);
Bit operator[](std::size_t index); Bit operator[](std::size_t index);
bool operator[](std::size_t index) const; bool operator[](std::size_t index) const;

View File

@ -328,9 +328,9 @@ namespace Nz
} }
/*! /*!
* \brief Read a byte sequence into a bitset * \brief Writes a byte sequence into a bitset
* *
* This function extends the bitset with bits read from a byte sequence * This function extends the bitset with bits read from a byte sequence.
* *
* \param ptr A pointer to the start of the byte sequence * \param ptr A pointer to the start of the byte sequence
* \param bitCount Number of bits to read from the byte sequence * \param bitCount Number of bits to read from the byte sequence
@ -341,17 +341,18 @@ namespace Nz
* *
* \see AppendBits * \see AppendBits
* \see Read * \see Read
* \see Write
*/ */
template<typename Block, class Allocator> template<typename Block, class Allocator>
typename Bitset<Block, Allocator>::PointerSequence Bitset<Block, Allocator>::Read(const void* ptr, std::size_t bitCount) typename Bitset<Block, Allocator>::PointerSequence Bitset<Block, Allocator>::Write(const void* ptr, std::size_t bitCount)
{ {
return Read(PointerSequence(ptr, 0U), bitCount); return Write(PointerSequence(ptr, 0U), bitCount);
} }
/*! /*!
* \brief Read a byte sequence into a bitset * \brief Writes a byte sequence into a bitset
* *
* This function extends the bitset with bits read from a pointer sequence (made of a pointer and a bit index) * This function extends the bitset with bits read from a pointer sequence (made of a pointer and a bit index).
* *
* \param sequence A pointer sequence to the start of the byte sequence * \param sequence A pointer sequence to the start of the byte sequence
* \param bitCount Number of bits to read from the byte sequence * \param bitCount Number of bits to read from the byte sequence
@ -362,9 +363,10 @@ namespace Nz
* *
* \see AppendBits * \see AppendBits
* \see Read * \see Read
* \see Write
*/ */
template<typename Block, class Allocator> template<typename Block, class Allocator>
typename Bitset<Block, Allocator>::PointerSequence Bitset<Block, Allocator>::Read(const PointerSequence& sequence, std::size_t bitCount) typename Bitset<Block, Allocator>::PointerSequence Bitset<Block, Allocator>::Write(const PointerSequence& sequence, std::size_t bitCount)
{ {
NazaraAssert(sequence.first, "Invalid pointer sequence"); NazaraAssert(sequence.first, "Invalid pointer sequence");
NazaraAssert(sequence.second < 8, "Invalid next bit index (must be < 8)"); NazaraAssert(sequence.second < 8, "Invalid next bit index (must be < 8)");
@ -1161,9 +1163,9 @@ namespace Nz
Bitset bitset; Bitset bitset;
if (sequence) if (sequence)
*sequence = bitset.Read(ptr, bitCount); *sequence = bitset.Write(ptr, bitCount);
else else
bitset.Read(ptr, bitCount); bitset.Write(ptr, bitCount);
return bitset; return bitset;
} }

View File

@ -90,7 +90,7 @@ namespace Nz
{ {
m_context.currentBitPos = 8; //< To prevent Serialize to flush bits itself m_context.currentBitPos = 8; //< To prevent Serialize to flush bits itself
if (!Serialize<UInt8>(m_context, m_context.currentByte)) if (!Serialize(m_context, m_context.currentByte))
return false; return false;
} }

View File

@ -71,8 +71,8 @@ namespace Nz
static float Hue2RGB(float v1, float v2, float vH); static float Hue2RGB(float v1, float v2, float vH);
}; };
inline bool Serialize(SerializationContext& context, const Color& color); inline bool Serialize(SerializationContext& context, const Color& color, TypeTag<Color>);
inline bool Unserialize(SerializationContext& context, Color* color); inline bool Unserialize(SerializationContext& context, Color* color, TypeTag<Color>);
} }
std::ostream& operator<<(std::ostream& out, const Nz::Color& color); std::ostream& operator<<(std::ostream& out, const Nz::Color& color);

View File

@ -617,7 +617,7 @@ namespace Nz
* \param context Serialization context * \param context Serialization context
* \param color Input color * \param color Input color
*/ */
inline bool Serialize(SerializationContext& context, const Color& color) inline bool Serialize(SerializationContext& context, const Color& color, TypeTag<Color>)
{ {
if (!Serialize(context, color.r)) if (!Serialize(context, color.r))
return false; return false;
@ -641,7 +641,7 @@ namespace Nz
* \param context Serialization context * \param context Serialization context
* \param color Output color * \param color Output color
*/ */
inline bool Unserialize(SerializationContext& context, Color* color) inline bool Unserialize(SerializationContext& context, Color* color, TypeTag<Color>)
{ {
if (!Unserialize(context, &color->r)) if (!Unserialize(context, &color->r))
return false; return false;

View File

@ -23,16 +23,16 @@ namespace Nz
public: public:
HandledObject() = default; HandledObject() = default;
HandledObject(const HandledObject& object); HandledObject(const HandledObject& object);
HandledObject(HandledObject&& object); HandledObject(HandledObject&& object) noexcept;
~HandledObject(); ~HandledObject();
ObjectHandle<T> CreateHandle(); ObjectHandle<T> CreateHandle();
HandledObject& operator=(const HandledObject& object); HandledObject& operator=(const HandledObject& object);
HandledObject& operator=(HandledObject&& object); HandledObject& operator=(HandledObject&& object) noexcept;
protected: protected:
void UnregisterAllHandles(); void UnregisterAllHandles() noexcept;
private: private:
void RegisterHandle(ObjectHandle<T>* handle); void RegisterHandle(ObjectHandle<T>* handle);

View File

@ -34,7 +34,7 @@ namespace Nz
* \param object HandledObject to move into this * \param object HandledObject to move into this
*/ */
template<typename T> template<typename T>
HandledObject<T>::HandledObject(HandledObject&& object) : HandledObject<T>::HandledObject(HandledObject&& object) noexcept :
m_handles(std::move(object.m_handles)) m_handles(std::move(object.m_handles))
{ {
for (ObjectHandle<T>* handle : m_handles) for (ObjectHandle<T>* handle : m_handles)
@ -84,8 +84,10 @@ namespace Nz
* \param object HandledObject to move in this * \param object HandledObject to move in this
*/ */
template<typename T> template<typename T>
HandledObject<T>& HandledObject<T>::operator=(HandledObject&& object) HandledObject<T>& HandledObject<T>::operator=(HandledObject&& object) noexcept
{ {
UnregisterAllHandles();
m_handles = std::move(object.m_handles); m_handles = std::move(object.m_handles);
for (ObjectHandle<T>* handle : m_handles) for (ObjectHandle<T>* handle : m_handles)
handle->OnObjectMoved(static_cast<T*>(this)); handle->OnObjectMoved(static_cast<T*>(this));
@ -110,7 +112,7 @@ namespace Nz
* \brief Unregisters all handles * \brief Unregisters all handles
*/ */
template<typename T> template<typename T>
void HandledObject<T>::UnregisterAllHandles() void HandledObject<T>::UnregisterAllHandles() noexcept
{ {
// Tell every handle we got destroyed, to null them // Tell every handle we got destroyed, to null them
for (ObjectHandle<T>* handle : m_handles) for (ObjectHandle<T>* handle : m_handles)

View File

@ -49,8 +49,8 @@ namespace Nz
static const ObjectHandle InvalidHandle; static const ObjectHandle InvalidHandle;
protected: protected:
void OnObjectDestroyed(); void OnObjectDestroyed() noexcept;
void OnObjectMoved(T* newObject); void OnObjectMoved(T* newObject) noexcept;
T* m_object; T* m_object;
}; };
@ -81,8 +81,8 @@ namespace Nz
template<typename T> bool operator>=(const T& lhs, const ObjectHandle<T>& rhs); template<typename T> bool operator>=(const T& lhs, const ObjectHandle<T>& rhs);
template<typename T> bool operator>=(const ObjectHandle<T>& lhs, const T& rhs); template<typename T> bool operator>=(const ObjectHandle<T>& lhs, const T& rhs);
template<typename T> struct PointedType<ObjectHandle<T>> { typedef T type; }; template<typename T> struct PointedType<ObjectHandle<T>> { using type = T; };
template<typename T> struct PointedType<const ObjectHandle<T>> { typedef T type; }; template<typename T> struct PointedType<const ObjectHandle<T>> { using type = T; };
} }
namespace std namespace std

View File

@ -268,7 +268,7 @@ namespace Nz
* \brief Action to do on object destruction * \brief Action to do on object destruction
*/ */
template<typename T> template<typename T>
void ObjectHandle<T>::OnObjectDestroyed() void ObjectHandle<T>::OnObjectDestroyed() noexcept
{ {
// Shortcut // Shortcut
m_object = nullptr; m_object = nullptr;
@ -278,7 +278,7 @@ namespace Nz
* \brief Action to do on object move * \brief Action to do on object move
*/ */
template<typename T> template<typename T>
void ObjectHandle<T>::OnObjectMoved(T* newObject) void ObjectHandle<T>::OnObjectMoved(T* newObject) noexcept
{ {
// The object has been moved, update our pointer // The object has been moved, update our pointer
m_object = newObject; m_object = newObject;

View File

@ -69,8 +69,8 @@ namespace Nz
template<typename T> bool operator>=(const ObjectRef<T>& lhs, const T& rhs); template<typename T> bool operator>=(const ObjectRef<T>& lhs, const T& rhs);
template<typename T> struct PointedType<ObjectRef<T>> { typedef T type; }; template<typename T> struct PointedType<ObjectRef<T>> { using type = T; };
template<typename T> struct PointedType<ObjectRef<T> const> { typedef T type; }; template<typename T> struct PointedType<ObjectRef<T> const> { using type = T; };
} }
#include <Nazara/Core/ObjectRef.inl> #include <Nazara/Core/ObjectRef.inl>

View File

@ -10,6 +10,7 @@
#include <Nazara/Prerequisites.hpp> #include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/Config.hpp> #include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Endianness.hpp> #include <Nazara/Core/Endianness.hpp>
#include <Nazara/Core/TypeTag.hpp>
namespace Nz namespace Nz
{ {

View File

@ -9,6 +9,7 @@
#include <Nazara/Prerequisites.hpp> #include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/Endianness.hpp> #include <Nazara/Core/Endianness.hpp>
#include <Nazara/Core/TypeTag.hpp>
#include <cstdarg> #include <cstdarg>
#include <iosfwd> #include <iosfwd>
#include <memory> #include <memory>
@ -188,10 +189,10 @@ namespace Nz
//char* rend(); //char* rend();
//const char* rend() const; //const char* rend() const;
typedef const char& const_reference; using const_reference = const char&;
typedef char* iterator; using iterator = char*;
//typedef char* reverse_iterator; //using reverse_iterator = char*;
typedef char value_type; using value_type = char;
// Méthodes STD // Méthodes STD
char& operator[](std::size_t pos); char& operator[](std::size_t pos);
@ -328,8 +329,8 @@ namespace Nz
class AbstractHash; class AbstractHash;
inline bool HashAppend(AbstractHash* hash, const String& string); inline bool HashAppend(AbstractHash* hash, const String& string);
NAZARA_CORE_API bool Serialize(SerializationContext& context, const String& string); NAZARA_CORE_API bool Serialize(SerializationContext& context, const String& string, TypeTag<String>);
NAZARA_CORE_API bool Unserialize(SerializationContext& context, String* string); NAZARA_CORE_API bool Unserialize(SerializationContext& context, String* string, TypeTag<String>);
} }
namespace std namespace std

View File

@ -0,0 +1,16 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_TYPETAG_HPP
#define NAZARA_TYPETAG_HPP
namespace Nz
{
template<typename T>
struct TypeTag {};
}
#endif // NAZARA_TYPETAG_HPP

View File

@ -33,6 +33,7 @@
#include <Nazara/Graphics/AbstractRenderQueue.hpp> #include <Nazara/Graphics/AbstractRenderQueue.hpp>
#include <Nazara/Graphics/AbstractRenderTechnique.hpp> #include <Nazara/Graphics/AbstractRenderTechnique.hpp>
#include <Nazara/Graphics/AbstractViewer.hpp> #include <Nazara/Graphics/AbstractViewer.hpp>
#include <Nazara/Graphics/BasicRenderQueue.hpp>
#include <Nazara/Graphics/Billboard.hpp> #include <Nazara/Graphics/Billboard.hpp>
#include <Nazara/Graphics/ColorBackground.hpp> #include <Nazara/Graphics/ColorBackground.hpp>
#include <Nazara/Graphics/Config.hpp> #include <Nazara/Graphics/Config.hpp>
@ -45,14 +46,13 @@
#include <Nazara/Graphics/DeferredFXAAPass.hpp> #include <Nazara/Graphics/DeferredFXAAPass.hpp>
#include <Nazara/Graphics/DeferredGeometryPass.hpp> #include <Nazara/Graphics/DeferredGeometryPass.hpp>
#include <Nazara/Graphics/DeferredPhongLightingPass.hpp> #include <Nazara/Graphics/DeferredPhongLightingPass.hpp>
#include <Nazara/Graphics/DeferredProxyRenderQueue.hpp>
#include <Nazara/Graphics/DeferredRenderPass.hpp> #include <Nazara/Graphics/DeferredRenderPass.hpp>
#include <Nazara/Graphics/DeferredRenderQueue.hpp>
#include <Nazara/Graphics/DeferredRenderTechnique.hpp> #include <Nazara/Graphics/DeferredRenderTechnique.hpp>
#include <Nazara/Graphics/DepthRenderQueue.hpp> #include <Nazara/Graphics/DepthRenderQueue.hpp>
#include <Nazara/Graphics/DepthRenderTechnique.hpp> #include <Nazara/Graphics/DepthRenderTechnique.hpp>
#include <Nazara/Graphics/Drawable.hpp> #include <Nazara/Graphics/Drawable.hpp>
#include <Nazara/Graphics/Enums.hpp> #include <Nazara/Graphics/Enums.hpp>
#include <Nazara/Graphics/ForwardRenderQueue.hpp>
#include <Nazara/Graphics/ForwardRenderTechnique.hpp> #include <Nazara/Graphics/ForwardRenderTechnique.hpp>
#include <Nazara/Graphics/Graphics.hpp> #include <Nazara/Graphics/Graphics.hpp>
#include <Nazara/Graphics/GuillotineTextureAtlas.hpp> #include <Nazara/Graphics/GuillotineTextureAtlas.hpp>
@ -73,6 +73,7 @@
#include <Nazara/Graphics/ParticleRenderer.hpp> #include <Nazara/Graphics/ParticleRenderer.hpp>
#include <Nazara/Graphics/ParticleStruct.hpp> #include <Nazara/Graphics/ParticleStruct.hpp>
#include <Nazara/Graphics/Renderable.hpp> #include <Nazara/Graphics/Renderable.hpp>
#include <Nazara/Graphics/RenderQueue.hpp>
#include <Nazara/Graphics/RenderTechniques.hpp> #include <Nazara/Graphics/RenderTechniques.hpp>
#include <Nazara/Graphics/SceneData.hpp> #include <Nazara/Graphics/SceneData.hpp>
#include <Nazara/Graphics/SkeletalModel.hpp> #include <Nazara/Graphics/SkeletalModel.hpp>

View File

@ -37,20 +37,20 @@ namespace Nz
// Je ne suis vraiment pas fan du nombre de surcharges pour AddBillboards, // Je ne suis vraiment pas fan du nombre de surcharges pour AddBillboards,
// mais je n'ai pas d'autre solution tout aussi performante pour le moment... // mais je n'ai pas d'autre solution tout aussi performante pour le moment...
virtual void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) = 0; virtual void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) = 0;
virtual void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) = 0; virtual void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) = 0;
virtual void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) = 0; virtual void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) = 0;
virtual void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) = 0; virtual void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) = 0;
virtual void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) = 0; virtual void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) = 0;
virtual void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) = 0; virtual void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) = 0;
virtual void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) = 0; virtual void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) = 0;
virtual void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) = 0; virtual void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) = 0;
virtual void AddDrawable(int renderOrder, const Drawable* drawable) = 0; virtual void AddDrawable(int renderOrder, const Drawable* drawable) = 0;
virtual void AddDirectionalLight(const DirectionalLight& light); virtual void AddDirectionalLight(const DirectionalLight& light);
virtual void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix) = 0; virtual void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix, const Recti& scissorRect) = 0;
virtual void AddPointLight(const PointLight& light); virtual void AddPointLight(const PointLight& light);
virtual void AddSpotLight(const SpotLight& light); virtual void AddSpotLight(const SpotLight& light);
virtual void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay = nullptr) = 0; virtual void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Recti& scissorRect, const Texture* overlay = nullptr) = 0;
virtual void Clear(bool fully = false); virtual void Clear(bool fully = false);

View File

@ -0,0 +1,142 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_BASICRENDERQUEUE_HPP
#define NAZARA_BASICRENDERQUEUE_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/Color.hpp>
#include <Nazara/Core/MovablePtr.hpp>
#include <Nazara/Graphics/AbstractRenderQueue.hpp>
#include <Nazara/Graphics/Material.hpp>
#include <Nazara/Graphics/RenderQueue.hpp>
#include <Nazara/Math/Box.hpp>
#include <Nazara/Math/Matrix4.hpp>
#include <Nazara/Math/Plane.hpp>
#include <Nazara/Utility/IndexBuffer.hpp>
#include <Nazara/Utility/MeshData.hpp>
#include <Nazara/Utility/VertexBuffer.hpp>
#include <map>
#include <unordered_map>
#include <vector>
namespace Nz
{
class AbstractViewer;
class NAZARA_GRAPHICS_API BasicRenderQueue : public AbstractRenderQueue
{
friend class ForwardRenderTechnique;
public:
struct BillboardData;
BasicRenderQueue() = default;
~BasicRenderQueue() = default;
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
void AddDrawable(int renderOrder, const Drawable* drawable) override;
void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix, const Recti& scissorRect) override;
void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Recti& scissorRect, const Texture* overlay = nullptr) override;
void Clear(bool fully = false) override;
inline const BillboardData* GetBillboardData(std::size_t billboardIndex) const;
void Sort(const AbstractViewer* viewer);
struct BillboardData
{
Color color;
Vector3f center;
Vector2f size;
Vector2f sinCos;
};
struct Billboard
{
int layerIndex;
MovablePtr<const Nz::Material> material;
Nz::Recti scissorRect;
BillboardData data;
};
struct BillboardChain
{
int layerIndex;
MovablePtr<const Nz::Material> material;
Nz::Recti scissorRect;
std::size_t billboardCount;
std::size_t billboardIndex;
};
RenderQueue<BillboardChain> billboards;
RenderQueue<Billboard> depthSortedBillboards;
struct CustomDrawable
{
int layerIndex;
MovablePtr<const Drawable> drawable;
};
RenderQueue<CustomDrawable> customDrawables;
struct Model
{
int layerIndex;
MeshData meshData;
MovablePtr<const Nz::Material> material;
Nz::Matrix4f matrix;
Nz::Recti scissorRect;
Nz::Spheref obbSphere;
};
RenderQueue<Model> models;
RenderQueue<Model> depthSortedModels;
struct SpriteChain
{
int layerIndex;
std::size_t spriteCount;
MovablePtr<const Material> material;
MovablePtr<const Texture> overlay;
MovablePtr<const VertexStruct_XYZ_Color_UV> vertices;
Nz::Recti scissorRect;
};
RenderQueue<SpriteChain> basicSprites;
RenderQueue<SpriteChain> depthSortedSprites;
private:
inline Color ComputeColor(float alpha);
inline Vector2f ComputeSinCos(float angle);
inline Vector2f ComputeSize(float size);
inline void RegisterLayer(int layerIndex);
std::unordered_map<const MaterialPipeline*, std::size_t> m_pipelineCache;
std::unordered_map<const Material*, std::size_t> m_materialCache;
std::unordered_map<const Texture*, std::size_t> m_overlayCache;
std::unordered_map<const UberShader*, std::size_t> m_shaderCache;
std::unordered_map<const Texture*, std::size_t> m_textureCache;
std::unordered_map<const VertexBuffer*, std::size_t> m_vertexBufferCache;
std::unordered_map<int, std::size_t> m_layerCache;
std::vector<BillboardData> m_billboards;
std::vector<int> m_renderLayers;
};
}
#include <Nazara/Graphics/BasicRenderQueue.inl>
#endif // NAZARA_BASICRENDERQUEUE_HPP

View File

@ -0,0 +1,38 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/BasicRenderQueue.hpp>
#include <cassert>
namespace Nz
{
inline const BasicRenderQueue::BillboardData* BasicRenderQueue::GetBillboardData(std::size_t billboardIndex) const
{
assert(billboardIndex < m_billboards.size());
return &m_billboards[billboardIndex];
}
inline Color BasicRenderQueue::ComputeColor(float alpha)
{
return Color(255, 255, 255, static_cast<UInt8>(255.f * alpha));
}
inline Vector2f BasicRenderQueue::ComputeSinCos(float angle)
{
float radians = ToRadians(angle);
return { std::sin(radians), std::cos(radians) };
}
inline Vector2f BasicRenderQueue::ComputeSize(float size)
{
return Vector2f(size, size);
}
inline void BasicRenderQueue::RegisterLayer(int layerIndex)
{
auto it = std::lower_bound(m_renderLayers.begin(), m_renderLayers.end(), layerIndex);
if (it == m_renderLayers.end() || *it != layerIndex)
m_renderLayers.insert(it, layerIndex);
}
}

View File

@ -29,7 +29,7 @@ namespace Nz
Billboard(Billboard&&) = delete; Billboard(Billboard&&) = delete;
~Billboard() = default; ~Billboard() = default;
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override; void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override;
inline const Color& GetColor() const; inline const Color& GetColor() const;
inline float GetRotation() const; inline float GetRotation() const;

View File

@ -8,6 +8,7 @@
#define NAZARA_DEFERREDGEOMETRYPASS_HPP #define NAZARA_DEFERREDGEOMETRYPASS_HPP
#include <Nazara/Prerequisites.hpp> #include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/BasicRenderQueue.hpp>
#include <Nazara/Graphics/DeferredRenderPass.hpp> #include <Nazara/Graphics/DeferredRenderPass.hpp>
#include <Nazara/Renderer/RenderStates.hpp> #include <Nazara/Renderer/RenderStates.hpp>
#include <Nazara/Renderer/Shader.hpp> #include <Nazara/Renderer/Shader.hpp>
@ -17,6 +18,8 @@ namespace Nz
{ {
class NAZARA_GRAPHICS_API DeferredGeometryPass : public DeferredRenderPass class NAZARA_GRAPHICS_API DeferredGeometryPass : public DeferredRenderPass
{ {
friend class DeferredRenderTechnique;
public: public:
DeferredGeometryPass(); DeferredGeometryPass();
virtual ~DeferredGeometryPass(); virtual ~DeferredGeometryPass();
@ -27,9 +30,17 @@ namespace Nz
protected: protected:
struct ShaderUniforms; struct ShaderUniforms;
void DrawBillboards(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::Billboard>& billboards) const;
void DrawBillboards(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::BillboardChain>& billboards) const;
void DrawModels(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::Model>& models) const;
void DrawSprites(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::SpriteChain>& sprites) const;
const ShaderUniforms* GetShaderUniforms(const Shader* shader) const; const ShaderUniforms* GetShaderUniforms(const Shader* shader) const;
void OnShaderInvalidated(const Shader* shader) const; void OnShaderInvalidated(const Shader* shader) const;
static bool Initialize();
static void Uninitialize();
struct ShaderUniforms struct ShaderUniforms
{ {
NazaraSlot(Shader, OnShaderUniformInvalidated, shaderUniformInvalidatedSlot); NazaraSlot(Shader, OnShaderUniformInvalidated, shaderUniformInvalidatedSlot);
@ -41,8 +52,18 @@ namespace Nz
}; };
mutable std::unordered_map<const Shader*, ShaderUniforms> m_shaderUniforms; mutable std::unordered_map<const Shader*, ShaderUniforms> m_shaderUniforms;
mutable std::vector<std::pair<const VertexStruct_XYZ_Color_UV*, std::size_t>> m_spriteChains;
Buffer m_vertexBuffer;
RenderStates m_clearStates; RenderStates m_clearStates;
ShaderRef m_clearShader; ShaderRef m_clearShader;
TextureRef m_whiteTexture;
VertexBuffer m_billboardPointBuffer;
VertexBuffer m_spriteBuffer;
static IndexBuffer s_quadIndexBuffer;
static VertexBuffer s_quadVertexBuffer;
static VertexDeclaration s_billboardInstanceDeclaration;
static VertexDeclaration s_billboardVertexDeclaration;
}; };
} }

View File

@ -0,0 +1,58 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_DEFERREDRENDERQUEUE_HPP
#define NAZARA_DEFERREDRENDERQUEUE_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/BasicRenderQueue.hpp>
#include <Nazara/Graphics/Material.hpp>
#include <Nazara/Math/Box.hpp>
#include <Nazara/Math/Matrix4.hpp>
#include <Nazara/Utility/IndexBuffer.hpp>
#include <Nazara/Utility/MeshData.hpp>
#include <Nazara/Utility/VertexBuffer.hpp>
#include <unordered_map>
#include <vector>
namespace Nz
{
class BasicRenderQueue;
class NAZARA_GRAPHICS_API DeferredProxyRenderQueue final : public AbstractRenderQueue
{
public:
struct BillboardData;
inline DeferredProxyRenderQueue(BasicRenderQueue* deferredQueue, BasicRenderQueue* forwardQueue);
~DeferredProxyRenderQueue() = default;
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, std::size_t billboardCount, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
void AddDrawable(int renderOrder, const Drawable* drawable) override;
void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix, const Recti& scissorRect) override;
void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Recti& scissorRect, const Texture* overlay = nullptr) override;
void Clear(bool fully = false) override;
inline BasicRenderQueue* GetDeferredRenderQueue();
inline BasicRenderQueue* GetForwardRenderQueue();
private:
BasicRenderQueue * m_deferredRenderQueue;
BasicRenderQueue* m_forwardRenderQueue;
};
}
#include <Nazara/Graphics/DeferredProxyRenderQueue.inl>
#endif // NAZARA_DEFERREDRENDERQUEUE_HPP

View File

@ -0,0 +1,30 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/DeferredProxyRenderQueue.hpp>
namespace Nz
{
/*!
* \brief Constructs a DeferredProxyRenderQueue using a deferred and a forward queues
*
* \param deferredQueue Deferred queue which will be used for non-blended objects
* \param forwardQueue Forward queue which will be used for blended objects
*/
inline DeferredProxyRenderQueue::DeferredProxyRenderQueue(BasicRenderQueue* deferredQueue, BasicRenderQueue* forwardQueue) :
m_deferredRenderQueue(deferredQueue),
m_forwardRenderQueue(forwardQueue)
{
}
inline BasicRenderQueue* DeferredProxyRenderQueue::GetDeferredRenderQueue()
{
return m_deferredRenderQueue;
}
inline BasicRenderQueue* DeferredProxyRenderQueue::GetForwardRenderQueue()
{
return m_forwardRenderQueue;
}
}

View File

@ -14,10 +14,10 @@
namespace Nz namespace Nz
{ {
class DeferredRenderTechnique; class DeferredRenderTechnique;
class DeferredRenderQueue; class DeferredProxyRenderQueue;
struct SceneData;
class RenderTexture; class RenderTexture;
class Texture; class Texture;
struct SceneData;
class NAZARA_GRAPHICS_API DeferredRenderPass class NAZARA_GRAPHICS_API DeferredRenderPass
{ {
@ -42,7 +42,7 @@ namespace Nz
protected: protected:
Vector2ui m_dimensions; Vector2ui m_dimensions;
DeferredRenderTechnique* m_deferredTechnique; DeferredRenderTechnique* m_deferredTechnique;
DeferredRenderQueue* m_renderQueue; DeferredProxyRenderQueue* m_renderQueue;
RenderTexture* m_GBufferRTT; RenderTexture* m_GBufferRTT;
RenderTexture* m_workRTT; RenderTexture* m_workRTT;
Texture* m_depthStencilTexture; Texture* m_depthStencilTexture;

View File

@ -1,89 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_DEFERREDRENDERQUEUE_HPP
#define NAZARA_DEFERREDRENDERQUEUE_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/ForwardRenderQueue.hpp>
#include <Nazara/Graphics/Material.hpp>
#include <Nazara/Math/Box.hpp>
#include <Nazara/Math/Matrix4.hpp>
#include <Nazara/Utility/IndexBuffer.hpp>
#include <Nazara/Utility/MeshData.hpp>
#include <Nazara/Utility/VertexBuffer.hpp>
#include <map>
namespace Nz
{
class NAZARA_GRAPHICS_API DeferredRenderQueue : public AbstractRenderQueue
{
public:
DeferredRenderQueue(ForwardRenderQueue* forwardQueue);
~DeferredRenderQueue() = default;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
void AddDrawable(int renderOrder, const Drawable* drawable) override;
void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix) override;
void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay = nullptr) override;
void Clear(bool fully = false) override;
struct MeshInstanceEntry
{
NazaraSlot(IndexBuffer, OnIndexBufferRelease, indexBufferReleaseSlot);
NazaraSlot(VertexBuffer, OnVertexBufferRelease, vertexBufferReleaseSlot);
std::vector<Matrix4f> instances;
};
typedef std::map<MeshData, MeshInstanceEntry, ForwardRenderQueue::MeshDataComparator> MeshInstanceContainer;
struct BatchedModelEntry
{
NazaraSlot(Material, OnMaterialRelease, materialReleaseSlot);
MeshInstanceContainer meshMap;
bool enabled = false;
};
typedef std::map<const Material*, BatchedModelEntry, ForwardRenderQueue::MaterialComparator> MeshMaterialBatches;
struct BatchedMaterialEntry
{
std::size_t maxInstanceCount = 0;
MeshMaterialBatches materialMap;
};
typedef std::map<const MaterialPipeline*, BatchedMaterialEntry, ForwardRenderQueue::MaterialPipelineComparator> MeshPipelineBatches;
struct Layer
{
MeshPipelineBatches opaqueModels;
unsigned int clearCount = 0;
};
std::map<int, Layer> layers;
private:
Layer& GetLayer(unsigned int i); ///TODO: Inline
ForwardRenderQueue* m_forwardQueue;
void OnIndexBufferInvalidation(const IndexBuffer* indexBuffer);
void OnMaterialInvalidation(const Material* material);
void OnVertexBufferInvalidation(const VertexBuffer* vertexBuffer);
};
}
#endif // NAZARA_DEFERREDRENDERQUEUE_HPP

View File

@ -9,7 +9,7 @@
#include <Nazara/Prerequisites.hpp> #include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/AbstractRenderTechnique.hpp> #include <Nazara/Graphics/AbstractRenderTechnique.hpp>
#include <Nazara/Graphics/DeferredRenderQueue.hpp> #include <Nazara/Graphics/DeferredProxyRenderQueue.hpp>
#include <Nazara/Graphics/ForwardRenderTechnique.hpp> #include <Nazara/Graphics/ForwardRenderTechnique.hpp>
#include <Nazara/Math/Vector2.hpp> #include <Nazara/Math/Vector2.hpp>
#include <Nazara/Renderer/RenderTexture.hpp> #include <Nazara/Renderer/RenderTexture.hpp>
@ -64,8 +64,9 @@ namespace Nz
}; };
std::map<RenderPassType, std::map<int, std::unique_ptr<DeferredRenderPass>>, RenderPassComparator> m_passes; std::map<RenderPassType, std::map<int, std::unique_ptr<DeferredRenderPass>>, RenderPassComparator> m_passes;
ForwardRenderTechnique m_forwardTechnique; // Must be initialized before the RenderQueue BasicRenderQueue m_deferredRenderQueue; // Must be initialized before the ProxyRenderQueue
DeferredRenderQueue m_renderQueue; ForwardRenderTechnique m_forwardTechnique; // Must be initialized before the ProxyRenderQueue
DeferredProxyRenderQueue m_renderQueue;
mutable TextureRef m_depthStencilTexture; mutable TextureRef m_depthStencilTexture;
mutable RenderTexture m_GBufferRTT; mutable RenderTexture m_GBufferRTT;
mutable RenderTexture m_workRTT; mutable RenderTexture m_workRTT;

View File

@ -8,33 +8,33 @@
#define NAZARA_DEPTHRENDERQUEUE_HPP #define NAZARA_DEPTHRENDERQUEUE_HPP
#include <Nazara/Prerequisites.hpp> #include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/ForwardRenderQueue.hpp> #include <Nazara/Graphics/BasicRenderQueue.hpp>
#include <Nazara/Math/Box.hpp> #include <Nazara/Math/Box.hpp>
#include <Nazara/Math/Matrix4.hpp> #include <Nazara/Math/Matrix4.hpp>
namespace Nz namespace Nz
{ {
class NAZARA_GRAPHICS_API DepthRenderQueue : public ForwardRenderQueue class NAZARA_GRAPHICS_API DepthRenderQueue : public BasicRenderQueue
{ {
public: public:
DepthRenderQueue(); DepthRenderQueue();
~DepthRenderQueue() = default; ~DepthRenderQueue() = default;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override; void AddBillboards(int renderOrder, const Material* material, std::size_t count, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override; void AddBillboards(int renderOrder, const Material* material, std::size_t count, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override; void AddBillboards(int renderOrder, const Material* material, std::size_t count, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override; void AddBillboards(int renderOrder, const Material* material, std::size_t count, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override; void AddBillboards(int renderOrder, const Material* material, std::size_t count, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override; void AddBillboards(int renderOrder, const Material* material, std::size_t count, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override; void AddBillboards(int renderOrder, const Material* material, std::size_t count, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override; void AddBillboards(int renderOrder, const Material* material, std::size_t count, const Recti& scissorRect, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
void AddDirectionalLight(const DirectionalLight& light) override; void AddDirectionalLight(const DirectionalLight& light) override;
void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix) override; void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix, const Recti& scissorRect) override;
void AddPointLight(const PointLight& light) override; void AddPointLight(const PointLight& light) override;
void AddSpotLight(const SpotLight& light) override; void AddSpotLight(const SpotLight& light) override;
void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay = nullptr) override; void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Recti& scissorRect, const Texture* overlay = nullptr) override;
private: private:
inline bool IsMaterialSuitable(const Material* material) const; inline bool IsMaterialSuitable(const Material* material) const;
MaterialRef m_baseMaterial; MaterialRef m_baseMaterial;

View File

@ -35,9 +35,12 @@ namespace Nz
private: private:
struct ShaderUniforms; struct ShaderUniforms;
void DrawBasicSprites(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const; void DrawBillboards(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::Billboard>& billboards) const;
void DrawBillboards(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const; void DrawBillboards(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::BillboardChain>& billboards) const;
void DrawOpaqueModels(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const; void DrawCustomDrawables(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::CustomDrawable>& customDrawables) const;
void DrawModels(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::Model>& models) const;
void DrawSprites(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::SpriteChain>& sprites) const;
const ShaderUniforms* GetShaderUniforms(const Shader* shader) const; const ShaderUniforms* GetShaderUniforms(const Shader* shader) const;
void OnShaderInvalidated(const Shader* shader) const; void OnShaderInvalidated(const Shader* shader) const;
@ -59,11 +62,14 @@ namespace Nz
}; };
mutable std::unordered_map<const Shader*, ShaderUniforms> m_shaderUniforms; mutable std::unordered_map<const Shader*, ShaderUniforms> m_shaderUniforms;
mutable std::vector<std::pair<const VertexStruct_XYZ_Color_UV*, std::size_t>> m_spriteChains;
Buffer m_vertexBuffer; Buffer m_vertexBuffer;
mutable DepthRenderQueue m_renderQueue; RenderStates m_clearStates;
Texture m_whiteTexture; ShaderRef m_clearShader;
TextureRef m_whiteTexture;
VertexBuffer m_billboardPointBuffer; VertexBuffer m_billboardPointBuffer;
VertexBuffer m_spriteBuffer; VertexBuffer m_spriteBuffer;
mutable DepthRenderQueue m_renderQueue;
static IndexBuffer s_quadIndexBuffer; static IndexBuffer s_quadIndexBuffer;
static VertexBuffer s_quadVertexBuffer; static VertexBuffer s_quadVertexBuffer;

View File

@ -1,201 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_FORWARDRENDERQUEUE_HPP
#define NAZARA_FORWARDRENDERQUEUE_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/Color.hpp>
#include <Nazara/Graphics/AbstractRenderQueue.hpp>
#include <Nazara/Graphics/Material.hpp>
#include <Nazara/Math/Box.hpp>
#include <Nazara/Math/Matrix4.hpp>
#include <Nazara/Math/Plane.hpp>
#include <Nazara/Utility/IndexBuffer.hpp>
#include <Nazara/Utility/MeshData.hpp>
#include <Nazara/Utility/VertexBuffer.hpp>
#include <map>
namespace Nz
{
class AbstractViewer;
class NAZARA_GRAPHICS_API ForwardRenderQueue : public AbstractRenderQueue
{
friend class ForwardRenderTechnique;
public:
ForwardRenderQueue() = default;
~ForwardRenderQueue() = default;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const Vector2f> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr = nullptr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const Vector2f> sinCosPtr, SparsePtr<const float> alphaPtr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const Color> colorPtr = nullptr) override;
void AddBillboards(int renderOrder, const Material* material, unsigned int count, SparsePtr<const Vector3f> positionPtr, SparsePtr<const float> sizePtr, SparsePtr<const float> anglePtr, SparsePtr<const float> alphaPtr) override;
void AddDrawable(int renderOrder, const Drawable* drawable) override;
void AddMesh(int renderOrder, const Material* material, const MeshData& meshData, const Boxf& meshAABB, const Matrix4f& transformMatrix) override;
void AddSprites(int renderOrder, const Material* material, const VertexStruct_XYZ_Color_UV* vertices, std::size_t spriteCount, const Texture* overlay = nullptr) override;
void Clear(bool fully = false) override;
void Sort(const AbstractViewer* viewer);
struct MaterialComparator
{
bool operator()(const Material* mat1, const Material* mat2) const;
};
struct MaterialPipelineComparator
{
bool operator()(const MaterialPipeline* pipeline1, const MaterialPipeline* pipeline2) const;
};
/// Billboards
struct BillboardData
{
Color color;
Vector3f center;
Vector2f size;
Vector2f sinCos;
};
struct BatchedBillboardEntry
{
NazaraSlot(Material, OnMaterialRelease, materialReleaseSlot);
std::vector<BillboardData> billboards;
};
using BatchedBillboardContainer = std::map<const Material*, BatchedBillboardEntry, MaterialComparator>;
struct BatchedBillboardPipelineEntry
{
BatchedBillboardContainer materialMap;
bool enabled = false;
};
using BillboardPipelineBatches = std::map<const MaterialPipeline*, BatchedBillboardPipelineEntry, MaterialPipelineComparator>;
/// Sprites
struct SpriteChain_XYZ_Color_UV
{
const VertexStruct_XYZ_Color_UV* vertices;
std::size_t spriteCount;
};
struct BatchedSpriteEntry
{
NazaraSlot(Texture, OnTextureRelease, textureReleaseSlot);
std::vector<SpriteChain_XYZ_Color_UV> spriteChains;
};
using SpriteOverlayBatches = std::map<const Texture*, BatchedSpriteEntry>;
struct BatchedBasicSpriteEntry
{
NazaraSlot(Material, OnMaterialRelease, materialReleaseSlot);
SpriteOverlayBatches overlayMap;
bool enabled = false;
};
using SpriteMaterialBatches = std::map<const Material*, BatchedBasicSpriteEntry, MaterialComparator>;
struct BatchedSpritePipelineEntry
{
SpriteMaterialBatches materialMap;
bool enabled = false;
};
using SpritePipelineBatches = std::map<const MaterialPipeline*, BatchedSpritePipelineEntry, MaterialPipelineComparator>;
/// Meshes
struct MeshDataComparator
{
bool operator()(const MeshData& data1, const MeshData& data2) const;
};
struct MeshInstanceEntry
{
NazaraSlot(IndexBuffer, OnIndexBufferRelease, indexBufferReleaseSlot);
NazaraSlot(VertexBuffer, OnVertexBufferRelease, vertexBufferReleaseSlot);
std::vector<Matrix4f> instances;
Spheref squaredBoundingSphere;
};
using MeshInstanceContainer = std::map<MeshData, MeshInstanceEntry, MeshDataComparator>;
struct BatchedModelEntry
{
NazaraSlot(Material, OnMaterialRelease, materialReleaseSlot);
MeshInstanceContainer meshMap;
bool enabled = false;
};
using MeshMaterialBatches = std::map<const Material*, BatchedModelEntry, MaterialComparator>;
struct BatchedMaterialEntry
{
std::size_t maxInstanceCount = 0;
MeshMaterialBatches materialMap;
};
using MeshPipelineBatches = std::map<const MaterialPipeline*, BatchedMaterialEntry, MaterialPipelineComparator>;
struct UnbatchedModelData
{
Matrix4f transformMatrix;
MeshData meshData;
Spheref obbSphere;
const Material* material;
};
struct UnbatchedSpriteData
{
std::size_t spriteCount;
const Material* material;
const Texture* overlay;
const VertexStruct_XYZ_Color_UV* vertices;
};
struct Layer
{
BillboardPipelineBatches billboards;
SpritePipelineBatches opaqueSprites;
MeshPipelineBatches opaqueModels;
std::vector<std::size_t> depthSortedMeshes;
std::vector<std::size_t> depthSortedSprites;
std::vector<UnbatchedModelData> depthSortedMeshData;
std::vector<UnbatchedSpriteData> depthSortedSpriteData;
std::vector<const Drawable*> otherDrawables;
unsigned int clearCount = 0;
};
std::map<int, Layer> layers;
private:
BillboardData* GetBillboardData(int renderOrder, const Material* material, unsigned int count);
Layer& GetLayer(int i); ///TODO: Inline
void SortBillboards(Layer& layer, const Planef& nearPlane);
void SortForOrthographic(const AbstractViewer* viewer);
void SortForPerspective(const AbstractViewer* viewer);
void OnIndexBufferInvalidation(const IndexBuffer* indexBuffer);
void OnMaterialInvalidation(const Material* material);
void OnTextureInvalidation(const Texture* texture);
void OnVertexBufferInvalidation(const VertexBuffer* vertexBuffer);
};
}
#endif // NAZARA_FORWARDRENDERQUEUE_HPP

View File

@ -10,7 +10,7 @@
#include <Nazara/Prerequisites.hpp> #include <Nazara/Prerequisites.hpp>
#include <Nazara/Graphics/AbstractRenderTechnique.hpp> #include <Nazara/Graphics/AbstractRenderTechnique.hpp>
#include <Nazara/Graphics/Config.hpp> #include <Nazara/Graphics/Config.hpp>
#include <Nazara/Graphics/ForwardRenderQueue.hpp> #include <Nazara/Graphics/BasicRenderQueue.hpp>
#include <Nazara/Graphics/Light.hpp> #include <Nazara/Graphics/Light.hpp>
#include <Nazara/Renderer/Shader.hpp> #include <Nazara/Renderer/Shader.hpp>
#include <Nazara/Utility/IndexBuffer.hpp> #include <Nazara/Utility/IndexBuffer.hpp>
@ -40,11 +40,12 @@ namespace Nz
struct ShaderUniforms; struct ShaderUniforms;
void ChooseLights(const Spheref& object, bool includeDirectionalLights = true) const; void ChooseLights(const Spheref& object, bool includeDirectionalLights = true) const;
void DrawBasicSprites(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const; void DrawBillboards(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::Billboard>& billboards) const;
void DrawBillboards(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const; void DrawBillboards(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::BillboardChain>& billboards) const;
void DrawOpaqueModels(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const; void DrawCustomDrawables(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::CustomDrawable>& customDrawables) const;
void DrawOrderedSprites(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const; void DrawModels(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::Model>& models) const;
void DrawTransparentModels(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const; void DrawSprites(const SceneData& sceneData, const BasicRenderQueue& renderQueue, const RenderQueue<BasicRenderQueue::SpriteChain>& sprites) const;
const ShaderUniforms* GetShaderUniforms(const Shader* shader) const; const ShaderUniforms* GetShaderUniforms(const Shader* shader) const;
void OnShaderInvalidated(const Shader* shader) const; void OnShaderInvalidated(const Shader* shader) const;
void SendLightUniforms(const Shader* shader, const LightUniforms& uniforms, unsigned int index, unsigned int lightIndex, unsigned int uniformOffset) const; void SendLightUniforms(const Shader* shader, const LightUniforms& uniforms, unsigned int index, unsigned int lightIndex, unsigned int uniformOffset) const;
@ -84,15 +85,16 @@ namespace Nz
mutable std::unordered_map<const Shader*, ShaderUniforms> m_shaderUniforms; mutable std::unordered_map<const Shader*, ShaderUniforms> m_shaderUniforms;
mutable std::vector<LightIndex> m_lights; mutable std::vector<LightIndex> m_lights;
mutable std::vector<std::pair<const VertexStruct_XYZ_Color_UV*, std::size_t>> m_spriteChains;
Buffer m_vertexBuffer; Buffer m_vertexBuffer;
mutable ForwardRenderQueue m_renderQueue; mutable BasicRenderQueue m_renderQueue;
Texture m_whiteTexture; TextureRef m_whiteCubemap;
TextureRef m_whiteTexture;
VertexBuffer m_billboardPointBuffer; VertexBuffer m_billboardPointBuffer;
VertexBuffer m_spriteBuffer; VertexBuffer m_spriteBuffer;
unsigned int m_maxLightPassPerObject; unsigned int m_maxLightPassPerObject;
static IndexBuffer s_quadIndexBuffer; static IndexBuffer s_quadIndexBuffer;
static Texture s_dummyReflection;
static TextureSampler s_reflectionSampler; static TextureSampler s_reflectionSampler;
static TextureSampler s_shadowSampler; static TextureSampler s_shadowSampler;
static VertexBuffer s_quadVertexBuffer; static VertexBuffer s_quadVertexBuffer;

View File

@ -2,7 +2,7 @@
// This file is part of the "Nazara Engine - Graphics module" // This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/Renderer.hpp> #include <Nazara/Graphics/ForwardRenderTechnique.hpp>
namespace Nz namespace Nz
{ {

View File

@ -37,7 +37,7 @@ namespace Nz
InstancedRenderable(InstancedRenderable&& renderable) = delete; InstancedRenderable(InstancedRenderable&& renderable) = delete;
virtual ~InstancedRenderable(); virtual ~InstancedRenderable();
virtual void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const = 0; virtual void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const = 0;
virtual bool Cull(const Frustumf& frustum, const InstanceData& instanceData) const; virtual bool Cull(const Frustumf& frustum, const InstanceData& instanceData) const;

View File

@ -11,6 +11,7 @@
#include <Nazara/Core/Resource.hpp> #include <Nazara/Core/Resource.hpp>
#include <Nazara/Core/ResourceLoader.hpp> #include <Nazara/Core/ResourceLoader.hpp>
#include <Nazara/Core/ResourceParameters.hpp> #include <Nazara/Core/ResourceParameters.hpp>
#include <Nazara/Math/Rect.hpp>
#include <Nazara/Graphics/InstancedRenderable.hpp> #include <Nazara/Graphics/InstancedRenderable.hpp>
#include <Nazara/Graphics/Material.hpp> #include <Nazara/Graphics/Material.hpp>
#include <Nazara/Utility/Mesh.hpp> #include <Nazara/Utility/Mesh.hpp>
@ -44,8 +45,8 @@ namespace Nz
Model(Model&& model) = default; Model(Model&& model) = default;
virtual ~Model(); virtual ~Model();
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override; void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override;
inline void AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix, unsigned int renderOrder = 0); inline void AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix, int renderOrder = 0, const Recti& scissorRect = Recti(-1, -1, -1, -1)) const;
using InstancedRenderable::GetMaterial; using InstancedRenderable::GetMaterial;
const MaterialRef& GetMaterial(const String& subMeshName) const; const MaterialRef& GetMaterial(const String& subMeshName) const;

View File

@ -22,14 +22,15 @@ namespace Nz
* *
* \param renderQueue Queue to be added * \param renderQueue Queue to be added
* \param transformMatrix Transform matrix to be used for rendering the model * \param transformMatrix Transform matrix to be used for rendering the model
* \param renderOrder Specify the renderqueue layer to be used * \param renderOrder Specify the render queue layer to be used
* \param scissorRect The Scissor rect to uses for rendering
*/ */
inline void Model::AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix, unsigned int renderOrder) void Model::AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix, int renderOrder, const Recti& scissorRect) const
{ {
InstanceData instanceData(Nz::Matrix4f::Identity()); InstanceData instanceData(Nz::Matrix4f::Identity());
instanceData.renderOrder = renderOrder; instanceData.renderOrder = renderOrder;
instanceData.transformMatrix = transformMatrix; instanceData.transformMatrix = transformMatrix;
return AddToRenderQueue(renderQueue, instanceData); return AddToRenderQueue(renderQueue, instanceData, scissorRect);
} }
/*! /*!

View File

@ -0,0 +1,96 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_RENDERQUEUE_HPP
#define NAZARA_RENDERQUEUE_HPP
#include <Nazara/Prerequisites.hpp>
#include <memory>
#include <vector>
namespace Nz
{
class RenderQueueInternal
{
public:
using Index = Nz::UInt64;
RenderQueueInternal() = default;
~RenderQueueInternal() = default;
protected:
using RenderDataPair = std::pair<Index, std::size_t>;
void Sort();
std::vector<RenderDataPair> m_orderedRenderQueue;
};
template<typename RenderData>
class RenderQueue : public RenderQueueInternal
{
public:
class const_iterator;
friend const_iterator;
using size_type = std::size_t;
RenderQueue() = default;
RenderQueue(const RenderQueue&) = default;
RenderQueue(RenderQueue&&) = default;
~RenderQueue() = default;
void Clear();
void Insert(RenderData&& data);
template<typename IndexFunc> void Sort(IndexFunc&& func);
// STL API
inline const_iterator begin() const;
inline bool empty() const;
inline const_iterator end() const;
inline size_type size() const;
RenderQueue& operator=(const RenderQueue&) = default;
RenderQueue& operator=(RenderQueue&&) = default;
private:
const RenderData& GetData(std::size_t i) const;
std::vector<RenderData> m_data;
};
template<typename RenderData>
class RenderQueue<RenderData>::const_iterator : public std::iterator<std::forward_iterator_tag, const RenderData>
{
friend RenderQueue;
public:
const_iterator(const const_iterator& it);
const RenderData& operator*() const;
const_iterator& operator=(const const_iterator& it);
const_iterator& operator++();
const_iterator operator++(int);
bool operator==(const const_iterator& rhs) const;
bool operator!=(const const_iterator& rhs) const;
void swap(const_iterator& rhs);
private:
const_iterator(const RenderQueue* queue, std::size_t nextId);
std::size_t m_nextDataId;
const RenderQueue* m_queue;
};
}
#include <Nazara/Graphics/RenderQueue.inl>
#endif // NAZARA_RENDERQUEUE_HPP

View File

@ -0,0 +1,136 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Graphics/RenderQueue.hpp>
#include <Nazara/Core/Error.hpp>
namespace Nz
{
template<typename RenderData>
void RenderQueue<RenderData>::Clear()
{
m_orderedRenderQueue.clear();
m_data.clear();
}
template<typename RenderData>
void RenderQueue<RenderData>::Insert(RenderData&& data)
{
m_data.emplace_back(std::move(data));
}
template<typename RenderData>
template<typename IndexFunc>
void RenderQueue<RenderData>::Sort(IndexFunc&& func)
{
m_orderedRenderQueue.clear();
m_orderedRenderQueue.reserve(m_data.size());
std::size_t dataIndex = 0;
for (const RenderData& renderData : m_data)
m_orderedRenderQueue.emplace_back(func(renderData), dataIndex++);
RenderQueueInternal::Sort();
}
template<typename RenderData>
typename RenderQueue<RenderData>::const_iterator RenderQueue<RenderData>::begin() const
{
return const_iterator(this, 0);
}
template<typename RenderData>
bool RenderQueue<RenderData>::empty() const
{
return m_orderedRenderQueue.empty();
}
template<typename RenderData>
typename RenderQueue<RenderData>::const_iterator RenderQueue<RenderData>::end() const
{
return const_iterator(this, m_orderedRenderQueue.size());
}
template<typename RenderData>
typename RenderQueue<RenderData>::size_type RenderQueue<RenderData>::size() const
{
return m_orderedRenderQueue.size();
}
template<typename RenderData>
const RenderData& RenderQueue<RenderData>::GetData(std::size_t i) const
{
NazaraAssert(i < m_orderedRenderQueue.size(), "Cannot dereference post-end iterator");
return m_data[m_orderedRenderQueue[i].second];
}
template<typename RenderData>
RenderQueue<RenderData>::const_iterator::const_iterator(const RenderQueue* queue, std::size_t nextId) :
m_nextDataId(nextId),
m_queue(queue)
{
}
template<typename RenderData>
RenderQueue<RenderData>::const_iterator::const_iterator(const const_iterator& it) :
m_nextDataId(it.m_nextDataId),
m_queue(it.m_queue)
{
}
template<typename RenderData>
const RenderData& RenderQueue<RenderData>::const_iterator::operator*() const
{
return m_queue->GetData(m_nextDataId);
}
template<typename RenderData>
typename RenderQueue<RenderData>::const_iterator& RenderQueue<RenderData>::const_iterator::operator=(const const_iterator& it)
{
m_nextDataId = it.m_nextDataId;
m_queue = it.m_queue;
return *this;
}
template<typename RenderData>
typename RenderQueue<RenderData>::const_iterator& RenderQueue<RenderData>::const_iterator::operator++()
{
++m_nextDataId;
return *this;
}
template<typename RenderData>
typename RenderQueue<RenderData>::const_iterator RenderQueue<RenderData>::const_iterator::operator++(int)
{
return iterator(m_queue, m_nextDataId++);
}
template<typename RenderData>
bool RenderQueue<RenderData>::const_iterator::operator==(const typename RenderQueue<RenderData>::const_iterator& rhs) const
{
NazaraAssert(m_queue == rhs.m_queue, "Cannot compare iterator coming from different queues");
return m_nextDataId == rhs.m_nextDataId;
}
template<typename RenderData>
bool RenderQueue<RenderData>::const_iterator::operator!=(const typename RenderQueue<RenderData>::const_iterator& rhs) const
{
return !operator==(rhs);
}
template<typename RenderData>
void RenderQueue<RenderData>::const_iterator::swap(typename RenderQueue<RenderData>::const_iterator& rhs)
{
NazaraAssert(m_queue == rhs.m_queue, "Cannot swap iterator coming from different queues");
using std::swap;
swap(m_nextDataId, rhs.m_nextDataId);
}
}

View File

@ -38,7 +38,7 @@ namespace Nz
SkeletalModel(SkeletalModel&& model) = default; SkeletalModel(SkeletalModel&& model) = default;
~SkeletalModel() = default; ~SkeletalModel() = default;
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override; void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override;
void AdvanceAnimation(float elapsedTime); void AdvanceAnimation(float elapsedTime);
SkeletalModel* Clone() const; SkeletalModel* Clone() const;

View File

@ -33,7 +33,7 @@ namespace Nz
Sprite(Sprite&&) = delete; Sprite(Sprite&&) = delete;
~Sprite() = default; ~Sprite() = default;
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override; void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override;
inline const Color& GetColor() const; inline const Color& GetColor() const;
inline const Color& GetCornerColor(RectCorner corner) const; inline const Color& GetCornerColor(RectCorner corner) const;

View File

@ -172,6 +172,7 @@ namespace Nz
{ {
MaterialRef material = Material::New(); MaterialRef material = Material::New();
material->EnableFaceCulling(false); material->EnableFaceCulling(false);
material->EnableScissorTest(true);
SetMaterial(std::move(material)); SetMaterial(std::move(material));
} }

View File

@ -30,7 +30,7 @@ namespace Nz
inline TextSprite(const TextSprite& sprite); inline TextSprite(const TextSprite& sprite);
~TextSprite() = default; ~TextSprite() = default;
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override; void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override;
inline void Clear(); inline void Clear();

View File

@ -110,14 +110,7 @@ namespace Nz
inline void TextSprite::SetDefaultMaterial() inline void TextSprite::SetDefaultMaterial()
{ {
MaterialRef material = Material::New(); SetMaterial(Material::New("Translucent2D"));
material->EnableBlending(true);
material->EnableDepthWrite(false);
material->EnableFaceCulling(false);
material->SetDstBlend(BlendFunc_InvSrcAlpha);
material->SetSrcBlend(BlendFunc_SrcAlpha);
SetMaterial(material);
} }
/*! /*!

View File

@ -33,7 +33,7 @@ namespace Nz
TileMap(TileMap&&) = delete; TileMap(TileMap&&) = delete;
~TileMap() = default; ~TileMap() = default;
void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const override; void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Recti& scissorRect) const override;
inline void DisableTile(const Vector2ui& tilePos); inline void DisableTile(const Vector2ui& tilePos);
inline void DisableTiles(); inline void DisableTiles();

View File

@ -69,11 +69,11 @@ namespace Nz
OrientedBox<T> obb; OrientedBox<T> obb;
}; };
typedef BoundingVolume<double> BoundingVolumed; using BoundingVolumed = BoundingVolume<double>;
typedef BoundingVolume<float> BoundingVolumef; using BoundingVolumef = BoundingVolume<float>;
template<typename T> bool Serialize(SerializationContext& context, const BoundingVolume<T>& boundingVolume); template<typename T> bool Serialize(SerializationContext& context, const BoundingVolume<T>& boundingVolume, TypeTag<BoundingVolume<T>>);
template<typename T> bool Unserialize(SerializationContext& context, BoundingVolume<T>* boundingVolume); template<typename T> bool Unserialize(SerializationContext& context, BoundingVolume<T>* boundingVolume, TypeTag<BoundingVolume<T>>);
} }
template<typename T> template<typename T>

View File

@ -603,7 +603,7 @@ namespace Nz
* \remark Does not save OBB corners * \remark Does not save OBB corners
*/ */
template<typename T> template<typename T>
bool Serialize(SerializationContext& context, const BoundingVolume<T>& boundingVolume) bool Serialize(SerializationContext& context, const BoundingVolume<T>& boundingVolume, TypeTag<BoundingVolume<T>>)
{ {
if (!Serialize(context, static_cast<UInt8>(boundingVolume.extend))) if (!Serialize(context, static_cast<UInt8>(boundingVolume.extend)))
return false; return false;
@ -627,7 +627,7 @@ namespace Nz
* \remark The resulting oriented box corners will *not* be updated, a call to Update is required * \remark The resulting oriented box corners will *not* be updated, a call to Update is required
*/ */
template<typename T> template<typename T>
bool Unserialize(SerializationContext& context, BoundingVolume<T>* boundingVolume) bool Unserialize(SerializationContext& context, BoundingVolume<T>* boundingVolume, TypeTag<BoundingVolume<T>>)
{ {
UInt8 extend; UInt8 extend;
if (!Unserialize(context, &extend)) if (!Unserialize(context, &extend))

View File

@ -93,15 +93,15 @@ namespace Nz
T x, y, z, width, height, depth; T x, y, z, width, height, depth;
}; };
typedef Box<double> Boxd; using Boxd = Box<double>;
typedef Box<float> Boxf; using Boxf = Box<float>;
typedef Box<int> Boxi; using Boxi = Box<int>;
typedef Box<unsigned int> Boxui; using Boxui = Box<unsigned int>;
typedef Box<Int32> Boxi32; using Boxi32 = Box<Int32>;
typedef Box<UInt32> Boxui32; using Boxui32 = Box<UInt32>;
template<typename T> bool Serialize(SerializationContext& context, const Box<T>& box); template<typename T> bool Serialize(SerializationContext& context, const Box<T>& box, TypeTag<Box<T>>);
template<typename T> bool Unserialize(SerializationContext& context, Box<T>* box); template<typename T> bool Unserialize(SerializationContext& context, Box<T>* box, TypeTag<Box<T>>);
} }
template<typename T> template<typename T>

View File

@ -912,7 +912,7 @@ namespace Nz
* \param box Input Box * \param box Input Box
*/ */
template<typename T> template<typename T>
bool Serialize(SerializationContext& context, const Box<T>& box) bool Serialize(SerializationContext& context, const Box<T>& box, TypeTag<Box<T>>)
{ {
if (!Serialize(context, box.x)) if (!Serialize(context, box.x))
return false; return false;
@ -943,7 +943,7 @@ namespace Nz
* \param box Output Box * \param box Output Box
*/ */
template<typename T> template<typename T>
bool Unserialize(SerializationContext& context, Box<T>* box) bool Unserialize(SerializationContext& context, Box<T>* box, TypeTag<Box<T>>)
{ {
if (!Unserialize(context, &box->x)) if (!Unserialize(context, &box->x))
return false; return false;

View File

@ -62,11 +62,11 @@ namespace Nz
T pitch, yaw, roll; T pitch, yaw, roll;
}; };
typedef EulerAngles<double> EulerAnglesd; using EulerAnglesd = EulerAngles<double>;
typedef EulerAngles<float> EulerAnglesf; using EulerAnglesf = EulerAngles<float>;
template<typename T> bool Serialize(SerializationContext& context, const EulerAngles<T>& eulerAngles); template<typename T> bool Serialize(SerializationContext& context, const EulerAngles<T>& eulerAngles, TypeTag<EulerAngles<T>>);
template<typename T> bool Unserialize(SerializationContext& context, EulerAngles<T>* eulerAngles); template<typename T> bool Unserialize(SerializationContext& context, EulerAngles<T>* eulerAngles, TypeTag<EulerAngles<T>>);
} }
template<typename T> std::ostream& operator<<(std::ostream& out, const Nz::EulerAngles<T>& angles); template<typename T> std::ostream& operator<<(std::ostream& out, const Nz::EulerAngles<T>& angles);

View File

@ -340,7 +340,7 @@ namespace Nz
* \param angles Input euler angles * \param angles Input euler angles
*/ */
template<typename T> template<typename T>
bool Serialize(SerializationContext& context, const EulerAngles<T>& angles) bool Serialize(SerializationContext& context, const EulerAngles<T>& angles, TypeTag<EulerAngles<T>>)
{ {
if (!Serialize(context, angles.pitch)) if (!Serialize(context, angles.pitch))
return false; return false;
@ -362,7 +362,7 @@ namespace Nz
* \param angles Output euler angles * \param angles Output euler angles
*/ */
template<typename T> template<typename T>
bool Unserialize(SerializationContext& context, EulerAngles<T>* angles) bool Unserialize(SerializationContext& context, EulerAngles<T>* angles, TypeTag<EulerAngles<T>>)
{ {
if (!Unserialize(context, &angles->pitch)) if (!Unserialize(context, &angles->pitch))
return false; return false;

View File

@ -58,17 +58,18 @@ namespace Nz
String ToString() const; String ToString() const;
template<typename U> template<typename U>
friend bool Serialize(SerializationContext& context, const Frustum<U>& frustum); friend bool Serialize(SerializationContext& context, const Frustum<U>& frustum, TypeTag<Frustum<U>>);
template<typename U> template<typename U>
friend bool Unserialize(SerializationContext& context, Frustum<U>* frustum); friend bool Unserialize(SerializationContext& context, Frustum<U>* frustum, TypeTag<Frustum<U>>);
private: private:
Vector3<T> m_corners[BoxCorner_Max+1]; Vector3<T> m_corners[BoxCorner_Max+1];
Plane<T> m_planes[FrustumPlane_Max+1]; Plane<T> m_planes[FrustumPlane_Max+1];
}; };
typedef Frustum<double> Frustumd; using Frustumd = Frustum<double>;
typedef Frustum<float> Frustumf; using Frustumf = Frustum<float>;
} }
template<typename T> template<typename T>

Some files were not shown because too many files have changed in this diff Show More