From 19f17fa0595dc613c6ca10dcb533f1780cd0718d Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 13 Apr 2018 00:00:36 +0200 Subject: [PATCH 01/12] Graphics: Add 2D & cubemap white textures --- ChangeLog.md | 1 + .../Nazara/Graphics/DeferredGeometryPass.hpp | 2 +- .../Nazara/Graphics/DepthRenderTechnique.hpp | 2 +- .../Graphics/ForwardRenderTechnique.hpp | 4 ++-- src/Nazara/Graphics/DeferredGeometryPass.cpp | 6 ++---- src/Nazara/Graphics/DepthRenderTechnique.cpp | 6 ++---- .../Graphics/ForwardRenderTechnique.cpp | 15 ++++----------- src/Nazara/Graphics/Graphics.cpp | 19 +++++++++++++++++++ 8 files changed, 32 insertions(+), 23 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 03a51ba76..7fec5792d 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -85,6 +85,7 @@ Nazara Engine: - Fixed Sound copy which was not copying looping state - Fixed Billboard bounding volume - Fixed Directory::GetResultSize and Directory::IsResultDirectory on Posix systems +- Graphics module now register "White2D" and "WhiteCubemap" textures to the TextureLibrary (respectively a 1x1 texture 2D and a 1x1 texture cubemap) Nazara Development Kit: - Added ImageWidget (#139) diff --git a/include/Nazara/Graphics/DeferredGeometryPass.hpp b/include/Nazara/Graphics/DeferredGeometryPass.hpp index cb38508b8..3c7890bfe 100644 --- a/include/Nazara/Graphics/DeferredGeometryPass.hpp +++ b/include/Nazara/Graphics/DeferredGeometryPass.hpp @@ -56,7 +56,7 @@ namespace Nz Buffer m_vertexBuffer; RenderStates m_clearStates; ShaderRef m_clearShader; - Texture m_whiteTexture; + TextureRef m_whiteTexture; VertexBuffer m_billboardPointBuffer; VertexBuffer m_spriteBuffer; diff --git a/include/Nazara/Graphics/DepthRenderTechnique.hpp b/include/Nazara/Graphics/DepthRenderTechnique.hpp index 44ef1fa77..f8f7bc4e3 100644 --- a/include/Nazara/Graphics/DepthRenderTechnique.hpp +++ b/include/Nazara/Graphics/DepthRenderTechnique.hpp @@ -66,7 +66,7 @@ namespace Nz Buffer m_vertexBuffer; RenderStates m_clearStates; ShaderRef m_clearShader; - Texture m_whiteTexture; + TextureRef m_whiteTexture; VertexBuffer m_billboardPointBuffer; VertexBuffer m_spriteBuffer; mutable DepthRenderQueue m_renderQueue; diff --git a/include/Nazara/Graphics/ForwardRenderTechnique.hpp b/include/Nazara/Graphics/ForwardRenderTechnique.hpp index 8fc75fd13..640986e62 100644 --- a/include/Nazara/Graphics/ForwardRenderTechnique.hpp +++ b/include/Nazara/Graphics/ForwardRenderTechnique.hpp @@ -88,13 +88,13 @@ namespace Nz mutable std::vector> m_spriteChains; Buffer m_vertexBuffer; mutable BasicRenderQueue m_renderQueue; - Texture m_whiteTexture; + TextureRef m_whiteCubemap; + TextureRef m_whiteTexture; VertexBuffer m_billboardPointBuffer; VertexBuffer m_spriteBuffer; unsigned int m_maxLightPassPerObject; static IndexBuffer s_quadIndexBuffer; - static Texture s_dummyReflection; static TextureSampler s_reflectionSampler; static TextureSampler s_shadowSampler; static VertexBuffer s_quadVertexBuffer; diff --git a/src/Nazara/Graphics/DeferredGeometryPass.cpp b/src/Nazara/Graphics/DeferredGeometryPass.cpp index 01072bf20..ef7586259 100644 --- a/src/Nazara/Graphics/DeferredGeometryPass.cpp +++ b/src/Nazara/Graphics/DeferredGeometryPass.cpp @@ -48,9 +48,7 @@ namespace Nz { ErrorFlags flags(ErrorFlag_ThrowException, true); - std::array whitePixel = { { 255, 255, 255, 255 } }; - m_whiteTexture.Create(ImageType_2D, PixelFormatType_RGBA8, 1, 1); - m_whiteTexture.Update(whitePixel.data()); + m_whiteTexture = Nz::TextureLibrary::Get("White2D"); m_vertexBuffer.Create(s_vertexBufferSize, DataStorage_Hardware, BufferUsage_Dynamic); @@ -576,7 +574,7 @@ namespace Nz lastMaterial = basicSprites.material; } - const Nz::Texture* overlayTexture = (basicSprites.overlay) ? basicSprites.overlay.Get() : &m_whiteTexture; + const Nz::Texture* overlayTexture = (basicSprites.overlay) ? basicSprites.overlay.Get() : m_whiteTexture.Get(); if (overlayTexture != lastOverlay) { Renderer::SetTexture(overlayTextureUnit, overlayTexture); diff --git a/src/Nazara/Graphics/DepthRenderTechnique.cpp b/src/Nazara/Graphics/DepthRenderTechnique.cpp index c536c4c83..6c858f51c 100644 --- a/src/Nazara/Graphics/DepthRenderTechnique.cpp +++ b/src/Nazara/Graphics/DepthRenderTechnique.cpp @@ -49,9 +49,7 @@ namespace Nz { ErrorFlags flags(ErrorFlag_ThrowException, true); - std::array whitePixel = { {255, 255, 255, 255} }; - m_whiteTexture.Create(ImageType_2D, PixelFormatType_RGBA8, 1, 1); - m_whiteTexture.Update(whitePixel.data()); + m_whiteTexture = Nz::TextureLibrary::Get("White2D"); m_vertexBuffer.Create(s_vertexBufferSize, DataStorage_Hardware, BufferUsage_Dynamic); @@ -587,7 +585,7 @@ namespace Nz lastMaterial = basicSprites.material; } - const Nz::Texture* overlayTexture = (basicSprites.overlay) ? basicSprites.overlay.Get() : &m_whiteTexture; + const Nz::Texture* overlayTexture = (basicSprites.overlay) ? basicSprites.overlay.Get() : m_whiteTexture.Get(); if (overlayTexture != lastOverlay) { Renderer::SetTexture(overlayTextureUnit, overlayTexture); diff --git a/src/Nazara/Graphics/ForwardRenderTechnique.cpp b/src/Nazara/Graphics/ForwardRenderTechnique.cpp index 904d87dfd..142e559eb 100644 --- a/src/Nazara/Graphics/ForwardRenderTechnique.cpp +++ b/src/Nazara/Graphics/ForwardRenderTechnique.cpp @@ -52,9 +52,8 @@ namespace Nz { ErrorFlags flags(ErrorFlag_ThrowException, true); - std::array whitePixel = { {255, 255, 255, 255} }; - m_whiteTexture.Create(ImageType_2D, PixelFormatType_RGBA8, 1, 1); - m_whiteTexture.Update(whitePixel.data()); + m_whiteCubemap = Nz::TextureLibrary::Get("WhiteCubemap"); + m_whiteTexture = Nz::TextureLibrary::Get("White2D"); m_vertexBuffer.Create(s_vertexBufferSize, DataStorage_Hardware, BufferUsage_Dynamic); @@ -219,10 +218,6 @@ namespace Nz s_shadowSampler.SetFilterMode(SamplerFilter_Bilinear); s_shadowSampler.SetWrapMode(SamplerWrap_Clamp); - - std::array whitePixels = { { 255, 255, 255, 255, 255, 255 } }; - s_dummyReflection.Create(ImageType_Cubemap, PixelFormatType_L8, 1, 1); - s_dummyReflection.Update(whitePixels.data()); } catch (const std::exception& e) { @@ -239,7 +234,6 @@ namespace Nz void ForwardRenderTechnique::Uninitialize() { - s_dummyReflection.Destroy(); s_quadIndexBuffer.Reset(); s_quadVertexBuffer.Reset(); } @@ -247,7 +241,7 @@ namespace Nz /*! * \brief Chooses the nearest lights for one object * - * \param object Sphere symbolising the object + * \param object Sphere symbolizing the object * \param includeDirectionalLights Should directional lights be included in the computation */ @@ -726,7 +720,7 @@ namespace Nz lastMaterial = basicSprites.material; } - const Nz::Texture* overlayTexture = (basicSprites.overlay) ? basicSprites.overlay.Get() : &m_whiteTexture; + const Nz::Texture* overlayTexture = (basicSprites.overlay) ? basicSprites.overlay.Get() : m_whiteTexture.Get(); if (overlayTexture != lastOverlay) { Renderer::SetTexture(overlayTextureUnit, overlayTexture); @@ -897,7 +891,6 @@ namespace Nz } IndexBuffer ForwardRenderTechnique::s_quadIndexBuffer; - Texture ForwardRenderTechnique::s_dummyReflection; TextureSampler ForwardRenderTechnique::s_reflectionSampler; TextureSampler ForwardRenderTechnique::s_shadowSampler; VertexBuffer ForwardRenderTechnique::s_quadVertexBuffer; diff --git a/src/Nazara/Graphics/Graphics.cpp b/src/Nazara/Graphics/Graphics.cpp index 5ae1d8554..b8538a163 100644 --- a/src/Nazara/Graphics/Graphics.cpp +++ b/src/Nazara/Graphics/Graphics.cpp @@ -156,6 +156,21 @@ namespace Nz Font::SetDefaultAtlas(std::make_shared()); + // Textures + std::array whitePixels = { { 255, 255, 255, 255, 255, 255 } }; + + Nz::TextureRef whiteTexture = Nz::Texture::New(); + whiteTexture->Create(ImageType_2D, PixelFormatType_L8, 1, 1); + whiteTexture->Update(whitePixels.data()); + + TextureLibrary::Register("White2D", std::move(whiteTexture)); + + Nz::TextureRef whiteCubemap = Nz::Texture::New(); + whiteCubemap->Create(ImageType_Cubemap, PixelFormatType_L8, 1, 1); + whiteCubemap->Update(whitePixels.data()); + + TextureLibrary::Register("WhiteCubemap", std::move(whiteCubemap)); + onExit.Reset(); NazaraNotice("Initialized: Graphics module"); @@ -217,6 +232,10 @@ namespace Nz defaultAtlas.reset(); + // Textures + TextureLibrary::Unregister("White2D"); + TextureLibrary::Unregister("WhiteCubemap"); + // Loaders Loaders::UnregisterMesh(); Loaders::UnregisterTexture(); From 251b8af03af701cc6eb0fa48a61e24d4675663ea Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 13 Apr 2018 22:09:19 +0200 Subject: [PATCH 02/12] SDK: Add DebugComponent @gawaboumga @gawaboumga @gawaboumga @gawaboumga @gawaboumga @gawaboumga @gawaboumga @gawaboumga @gawaboumga @gawaboumga --- ChangeLog.md | 1 + SDK/include/NDK/Components.hpp | 3 +- SDK/include/NDK/Components/DebugComponent.hpp | 80 ++++ SDK/include/NDK/Components/DebugComponent.inl | 74 ++++ SDK/include/NDK/Systems.hpp | 1 + SDK/include/NDK/Systems/DebugSystem.hpp | 51 +++ SDK/include/NDK/Systems/DebugSystem.inl | 6 + SDK/src/NDK/Components/DebugComponent.cpp | 10 + SDK/src/NDK/Sdk.cpp | 4 + SDK/src/NDK/Systems/DebugSystem.cpp | 363 ++++++++++++++++++ SDK/src/NDK/World.cpp | 2 + include/Nazara/Core.hpp | 1 + 12 files changed, 595 insertions(+), 1 deletion(-) create mode 100644 SDK/include/NDK/Components/DebugComponent.hpp create mode 100644 SDK/include/NDK/Components/DebugComponent.inl create mode 100644 SDK/include/NDK/Systems/DebugSystem.hpp create mode 100644 SDK/include/NDK/Systems/DebugSystem.inl create mode 100644 SDK/src/NDK/Components/DebugComponent.cpp create mode 100644 SDK/src/NDK/Systems/DebugSystem.cpp diff --git a/ChangeLog.md b/ChangeLog.md index 7fec5792d..c724b0117 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -129,6 +129,7 @@ Nazara Development Kit: - 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) # 0.4: diff --git a/SDK/include/NDK/Components.hpp b/SDK/include/NDK/Components.hpp index e099b641b..97c15fc7c 100644 --- a/SDK/include/NDK/Components.hpp +++ b/SDK/include/NDK/Components.hpp @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include @@ -17,6 +19,5 @@ #include #include #include -#include #endif // NDK_COMPONENTS_GLOBAL_HPP diff --git a/SDK/include/NDK/Components/DebugComponent.hpp b/SDK/include/NDK/Components/DebugComponent.hpp new file mode 100644 index 000000000..85e868b5a --- /dev/null +++ b/SDK/include/NDK/Components/DebugComponent.hpp @@ -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 +#include +#include + +namespace Ndk +{ + enum class DebugDraw + { + //TODO: Collider2D + Collider3D, + GraphicsAABB, + GraphicsOBB, + + Max = GraphicsOBB + }; +} + +namespace Nz +{ + template<> + struct EnumAsFlags + { + static constexpr Ndk::DebugDraw max = Ndk::DebugDraw::GraphicsOBB; + }; +} + +namespace Ndk +{ + using DebugDrawFlags = Nz::Flags; + + constexpr DebugDrawFlags DebugDraw_None = 0; + + class NDK_API DebugComponent : public Component + { + 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(DebugDraw::Max) + 1; + + std::array m_debugRenderables; + DebugDrawFlags m_enabledFlags; + DebugDrawFlags m_flags; + }; +} + +#include + +#endif // NDK_COMPONENTS_DEBUGCOMPONENT_HPP +#endif // NDK_SERVER diff --git a/SDK/include/NDK/Components/DebugComponent.inl b/SDK/include/NDK/Components/DebugComponent.inl new file mode 100644 index 000000000..e0f42a560 --- /dev/null +++ b/SDK/include/NDK/Components/DebugComponent.inl @@ -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 + +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(option)]; + } + + inline DebugDrawFlags DebugComponent::GetEnabledFlags() const + { + return m_enabledFlags; + } + + inline void DebugComponent::UpdateDebugRenderable(DebugDraw option, Nz::InstancedRenderableRef renderable) + { + m_debugRenderables[static_cast(option)] = std::move(renderable); + } + + inline void DebugComponent::UpdateEnabledFlags(DebugDrawFlags flags) + { + m_enabledFlags = flags; + } +} diff --git a/SDK/include/NDK/Systems.hpp b/SDK/include/NDK/Systems.hpp index a0ee23e77..80571ef45 100644 --- a/SDK/include/NDK/Systems.hpp +++ b/SDK/include/NDK/Systems.hpp @@ -5,6 +5,7 @@ #ifndef NDK_SYSTEMS_GLOBAL_HPP #define NDK_SYSTEMS_GLOBAL_HPP +#include #include #include #include diff --git a/SDK/include/NDK/Systems/DebugSystem.hpp b/SDK/include/NDK/Systems/DebugSystem.hpp new file mode 100644 index 000000000..940feb782 --- /dev/null +++ b/SDK/include/NDK/Systems/DebugSystem.hpp @@ -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 +#include +#include +#include +#include + +namespace Ndk +{ + class NDK_API DebugSystem : public System + { + 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 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 + +#endif // NDK_SYSTEMS_DEBUGSYSTEM_HPP +#endif // NDK_SERVER diff --git a/SDK/include/NDK/Systems/DebugSystem.inl b/SDK/include/NDK/Systems/DebugSystem.inl new file mode 100644 index 000000000..b7439fc12 --- /dev/null +++ b/SDK/include/NDK/Systems/DebugSystem.inl @@ -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 + diff --git a/SDK/src/NDK/Components/DebugComponent.cpp b/SDK/src/NDK/Components/DebugComponent.cpp new file mode 100644 index 000000000..6c8ab9f1c --- /dev/null +++ b/SDK/src/NDK/Components/DebugComponent.cpp @@ -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 + +namespace Ndk +{ + ComponentIndex DebugComponent::componentIndex; +} diff --git a/SDK/src/NDK/Sdk.cpp b/SDK/src/NDK/Sdk.cpp index e4a7008b7..90d07c738 100644 --- a/SDK/src/NDK/Sdk.cpp +++ b/SDK/src/NDK/Sdk.cpp @@ -28,11 +28,13 @@ #ifndef NDK_SERVER #include +#include #include #include #include #include #include +#include #include #include #include @@ -95,6 +97,7 @@ namespace Ndk #ifndef NDK_SERVER // Client components InitializeComponent("NdkCam"); + InitializeComponent("NdkDebug"); InitializeComponent("NdkLight"); InitializeComponent("NdkList"); InitializeComponent("NdkGfx"); @@ -113,6 +116,7 @@ namespace Ndk #ifndef NDK_SERVER // Client systems + InitializeSystem(); InitializeSystem(); InitializeSystem(); InitializeSystem(); diff --git a/SDK/src/NDK/Systems/DebugSystem.cpp b/SDK/src/NDK/Systems/DebugSystem.cpp new file mode 100644 index 000000000..61dcae0a8 --- /dev/null +++ b/SDK/src/NDK/Systems/DebugSystem.cpp @@ -0,0 +1,363 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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(); + const GraphicsComponent& entityGfx = m_entityOwner->GetComponent(); + + 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(); + const GraphicsComponent& entityGfx = m_entityOwner->GetComponent(); + + 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(); + SetUpdateOrder(1000); //< Update last + } + + std::pair DebugSystem::GetBoxMesh() + { + if (!m_boxMeshIndexBuffer) + { + std::array 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, indices.size(), Nz::DataStorage_Hardware, 0); + m_boxMeshIndexBuffer->Fill(indices.data(), 0, indices.size()); + } + + if (!m_boxMeshVertexBuffer) + { + Nz::Boxf box(-0.5f, -0.5f, -0.5f, 1.f, 1.f, 1.f); + + std::array 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), positions.size(), Nz::DataStorage_Hardware, 0); + m_boxMeshVertexBuffer->Fill(positions.data(), 0, positions.size()); + } + + return { m_boxMeshIndexBuffer, m_boxMeshVertexBuffer }; + } + + void DebugSystem::OnEntityValidation(Entity* entity, bool /*justAdded*/) + { + static constexpr int DebugDrawOrder = 1'000; + + DebugComponent& entityDebug = entity->GetComponent(); + GraphicsComponent& entityGfx = entity->GetComponent(); + + DebugDrawFlags enabledFlags = entityDebug.GetEnabledFlags(); + DebugDrawFlags flags = entityDebug.GetFlags(); + + DebugDrawFlags flagsToEnable = flags & ~enabledFlags; + for (std::size_t i = 0; i <= static_cast(DebugDraw::Max); ++i) + { + DebugDraw option = static_cast(i); + if (flagsToEnable & option) + { + switch (option) + { + case DebugDraw::Collider3D: + { + const Nz::Boxf& obb = entityGfx.GetBoundingVolume().obb.localBox; + + Nz::InstancedRenderableRef renderable = GenerateCollision3DMesh(entity); + 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(DebugDraw::Max); ++i) + { + DebugDraw option = static_cast(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& entityCollision = entity->GetComponent(); + const Nz::Collider3DRef& geom = entityCollision.GetGeom(); + + std::vector vertices; + std::vector 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, 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(index); + + indexMapper.Unmap(); + + Nz::VertexBufferRef vertexBuffer = Nz::VertexBuffer::New(Nz::VertexDeclaration::Get(Nz::VertexLayout_XYZ), vertices.size(), Nz::DataStorage_Hardware, 0); + vertexBuffer->Fill(vertices.data(), 0, 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; +} diff --git a/SDK/src/NDK/World.cpp b/SDK/src/NDK/World.cpp index 7582461b9..bfbe0140c 100644 --- a/SDK/src/NDK/World.cpp +++ b/SDK/src/NDK/World.cpp @@ -11,6 +11,7 @@ #include #ifndef NDK_SERVER +#include #include #include #include @@ -47,6 +48,7 @@ namespace Ndk AddSystem(); #ifndef NDK_SERVER + AddSystem(); AddSystem(); AddSystem(); AddSystem(); diff --git a/include/Nazara/Core.hpp b/include/Nazara/Core.hpp index b4481b1a6..515d8c545 100644 --- a/include/Nazara/Core.hpp +++ b/include/Nazara/Core.hpp @@ -88,6 +88,7 @@ #include #include #include +#include #include #include From a48dc11063e8c6d88b808945396bd2f80c6f5fba Mon Sep 17 00:00:00 2001 From: Lynix Date: Sat, 14 Apr 2018 00:08:50 +0200 Subject: [PATCH 03/12] Fix compilation in server mode --- build/scripts/tools/ndk_server.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/scripts/tools/ndk_server.lua b/build/scripts/tools/ndk_server.lua index cea295f7e..e235b1343 100644 --- a/build/scripts/tools/ndk_server.lua +++ b/build/scripts/tools/ndk_server.lua @@ -27,6 +27,8 @@ TOOL.FilesExcluded = { "../SDK/**/CameraComponent.*", "../SDK/**/Canvas.*", "../SDK/**/Console.*", + "../SDK/**/DebugComponent.*", + "../SDK/**/DebugSystem.*", "../SDK/**/GraphicsComponent.*", "../SDK/**/LightComponent.*", "../SDK/**/ListenerComponent.*", From 3362a4f1600450662d0fbde5b92cc2154de67cf9 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sat, 14 Apr 2018 00:09:07 +0200 Subject: [PATCH 04/12] Sdk/DebugSystem: Fix some warnings --- SDK/src/NDK/Systems/DebugSystem.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/SDK/src/NDK/Systems/DebugSystem.cpp b/SDK/src/NDK/Systems/DebugSystem.cpp index 61dcae0a8..11d286064 100644 --- a/SDK/src/NDK/Systems/DebugSystem.cpp +++ b/SDK/src/NDK/Systems/DebugSystem.cpp @@ -130,8 +130,8 @@ namespace Ndk } }; - m_boxMeshIndexBuffer = Nz::IndexBuffer::New(false, indices.size(), Nz::DataStorage_Hardware, 0); - m_boxMeshIndexBuffer->Fill(indices.data(), 0, indices.size()); + 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) @@ -151,8 +151,8 @@ namespace Ndk } }; - m_boxMeshVertexBuffer = Nz::VertexBuffer::New(Nz::VertexDeclaration::Get(Nz::VertexLayout_XYZ), positions.size(), Nz::DataStorage_Hardware, 0); - m_boxMeshVertexBuffer->Fill(positions.data(), 0, positions.size()); + 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 }; @@ -282,7 +282,7 @@ namespace Ndk indices.push_back(firstIndex); }); - Nz::IndexBufferRef indexBuffer = Nz::IndexBuffer::New(vertices.size() > 0xFFFF, indices.size(), Nz::DataStorage_Hardware, 0); + 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(); @@ -291,8 +291,8 @@ namespace Ndk indexMapper.Unmap(); - Nz::VertexBufferRef vertexBuffer = Nz::VertexBuffer::New(Nz::VertexDeclaration::Get(Nz::VertexLayout_XYZ), vertices.size(), Nz::DataStorage_Hardware, 0); - vertexBuffer->Fill(vertices.data(), 0, vertices.size()); + 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(); From 69c61ba7463ee1f1ef72908574d9bf278b1409cb Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 15 Apr 2018 02:27:49 +0200 Subject: [PATCH 05/12] Utility/AbstractTextDrawer: Add GetLineGlyphCount --- include/Nazara/Utility/AbstractTextDrawer.hpp | 3 +++ include/Nazara/Utility/AbstractTextDrawer.inl | 23 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 include/Nazara/Utility/AbstractTextDrawer.inl diff --git a/include/Nazara/Utility/AbstractTextDrawer.hpp b/include/Nazara/Utility/AbstractTextDrawer.hpp index 2ef500aab..c52051a5c 100644 --- a/include/Nazara/Utility/AbstractTextDrawer.hpp +++ b/include/Nazara/Utility/AbstractTextDrawer.hpp @@ -34,6 +34,7 @@ namespace Nz virtual std::size_t GetGlyphCount() const = 0; virtual const Line& GetLine(std::size_t index) const = 0; virtual std::size_t GetLineCount() const = 0; + inline std::size_t GetLineGlyphCount(std::size_t index) const; struct Glyph { @@ -53,4 +54,6 @@ namespace Nz }; } +#include + #endif // NAZARA_ABSTRACTTEXTDRAWER_HPP diff --git a/include/Nazara/Utility/AbstractTextDrawer.inl b/include/Nazara/Utility/AbstractTextDrawer.inl new file mode 100644 index 000000000..a10a16892 --- /dev/null +++ b/include/Nazara/Utility/AbstractTextDrawer.inl @@ -0,0 +1,23 @@ +// Copyright (C) 2017 Jérôme Leclercq +// This file is part of the "Nazara Engine - Utility module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + inline std::size_t AbstractTextDrawer::GetLineGlyphCount(std::size_t index) const + { + std::size_t lineCount = GetLineCount(); + const auto& lineInfo = GetLine(index); + if (index == lineCount - 1) + return GetGlyphCount() - lineInfo.glyphIndex; + + const auto& nextLineInfo = GetLine(index + 1); + + return nextLineInfo.glyphIndex - lineInfo.glyphIndex; + } +} + +#include From d253ec1adc61418dcfba1f54ca17fe7c626f78b1 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 15 Apr 2018 02:30:36 +0200 Subject: [PATCH 06/12] Sdk/GraphicsComponent: Fix bounding volume when using a local matrix --- SDK/src/NDK/Components/GraphicsComponent.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SDK/src/NDK/Components/GraphicsComponent.cpp b/SDK/src/NDK/Components/GraphicsComponent.cpp index f8b4e468d..f865e749b 100644 --- a/SDK/src/NDK/Components/GraphicsComponent.cpp +++ b/SDK/src/NDK/Components/GraphicsComponent.cpp @@ -277,7 +277,8 @@ namespace Ndk { Nz::Boxf localBox = boundingVolume.obb.localBox; 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)); } From bf0b8e9c761b14f48f4fc87691ef41d8f2b1e130 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 15 Apr 2018 02:31:51 +0200 Subject: [PATCH 07/12] Graphics: Fix clear being parasited by scissor operations --- src/Nazara/Graphics/DeferredGeometryPass.cpp | 1 + src/Nazara/Graphics/DepthRenderTechnique.cpp | 12 +++++++++--- src/Nazara/Graphics/ForwardRenderTechnique.cpp | 5 +++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Nazara/Graphics/DeferredGeometryPass.cpp b/src/Nazara/Graphics/DeferredGeometryPass.cpp index ef7586259..dcea7d305 100644 --- a/src/Nazara/Graphics/DeferredGeometryPass.cpp +++ b/src/Nazara/Graphics/DeferredGeometryPass.cpp @@ -85,6 +85,7 @@ namespace Nz m_GBufferRTT->SetColorTargets({0, 1, 2}); // G-Buffer Renderer::SetTarget(m_GBufferRTT); + Renderer::SetScissorRect(Recti(0, 0, m_dimensions.x, m_dimensions.y)); Renderer::SetViewport(Recti(0, 0, m_dimensions.x, m_dimensions.y)); Renderer::SetRenderStates(m_clearStates); diff --git a/src/Nazara/Graphics/DepthRenderTechnique.cpp b/src/Nazara/Graphics/DepthRenderTechnique.cpp index 6c858f51c..5435d7497 100644 --- a/src/Nazara/Graphics/DepthRenderTechnique.cpp +++ b/src/Nazara/Graphics/DepthRenderTechnique.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -63,15 +64,20 @@ namespace Nz * \param sceneData Data of the scene */ - void DepthRenderTechnique::Clear(const SceneData& /*sceneData*/) const + void DepthRenderTechnique::Clear(const SceneData& sceneData) const { + const RenderTarget* renderTarget = sceneData.viewer->GetTarget(); + Recti fullscreenScissorRect = Recti(Vector2i(renderTarget->GetSize())); + + Renderer::SetScissorRect(fullscreenScissorRect); + Renderer::Enable(RendererParameter_DepthBuffer, true); Renderer::Enable(RendererParameter_DepthWrite, true); Renderer::Clear(RendererBuffer_Depth); // Just in case the background does render depth - //if (sceneData.background) - // sceneData.background->Draw(sceneData.viewer); + if (sceneData.background) + sceneData.background->Draw(sceneData.viewer); } /*! diff --git a/src/Nazara/Graphics/ForwardRenderTechnique.cpp b/src/Nazara/Graphics/ForwardRenderTechnique.cpp index 142e559eb..cf3611362 100644 --- a/src/Nazara/Graphics/ForwardRenderTechnique.cpp +++ b/src/Nazara/Graphics/ForwardRenderTechnique.cpp @@ -69,6 +69,11 @@ namespace Nz void ForwardRenderTechnique::Clear(const SceneData& sceneData) const { + const RenderTarget* renderTarget = sceneData.viewer->GetTarget(); + Recti fullscreenScissorRect = Recti(Vector2i(renderTarget->GetSize())); + + Renderer::SetScissorRect(fullscreenScissorRect); + Renderer::Enable(RendererParameter_DepthBuffer, true); Renderer::Enable(RendererParameter_DepthWrite, true); Renderer::Clear(RendererBuffer_Depth); From 347f8cc9865d0530b5754db7936be65cd5b3d4e6 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 15 Apr 2018 02:34:21 +0200 Subject: [PATCH 08/12] Utility/Font: Fix handling of whitespace glyphs --- ChangeLog.md | 2 ++ src/Nazara/Utility/Font.cpp | 12 ++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index c724b0117..6b1641293 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -86,6 +86,8 @@ Nazara Engine: - Fixed Billboard bounding volume - Fixed Directory::GetResultSize and Directory::IsResultDirectory on Posix systems - 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) Nazara Development Kit: - Added ImageWidget (#139) diff --git a/src/Nazara/Utility/Font.cpp b/src/Nazara/Utility/Font.cpp index 63cc28495..a0264b9ee 100644 --- a/src/Nazara/Utility/Font.cpp +++ b/src/Nazara/Utility/Font.cpp @@ -514,8 +514,16 @@ namespace Nz FontGlyph fontGlyph; if (ExtractGlyph(characterSize, character, style, &fontGlyph)) { - glyph.atlasRect.width = fontGlyph.image.GetWidth(); - glyph.atlasRect.height = fontGlyph.image.GetHeight(); + if (fontGlyph.image.IsValid()) + { + glyph.atlasRect.width = fontGlyph.image.GetWidth(); + glyph.atlasRect.height = fontGlyph.image.GetHeight(); + } + else + { + glyph.atlasRect.width = 0; + glyph.atlasRect.height = 0; + } // Insertion du rectangle dans l'un des atlas if (glyph.atlasRect.width > 0 && glyph.atlasRect.height > 0) // Si l'image contient quelque chose From 9f95a6122b7d6ebf59e1acbdbdbeebf2265f5905 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 15 Apr 2018 02:35:51 +0200 Subject: [PATCH 09/12] Graphics/MaterialPipeline: Disable depth sorting for Translucent2D pipeline --- src/Nazara/Graphics/MaterialPipeline.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Nazara/Graphics/MaterialPipeline.cpp b/src/Nazara/Graphics/MaterialPipeline.cpp index c1313b05a..6f2d5f173 100644 --- a/src/Nazara/Graphics/MaterialPipeline.cpp +++ b/src/Nazara/Graphics/MaterialPipeline.cpp @@ -199,7 +199,7 @@ namespace Nz pipelineInfo.blending = true; pipelineInfo.depthWrite = false; pipelineInfo.faceCulling = false; - pipelineInfo.depthSorting = true; + pipelineInfo.depthSorting = false; pipelineInfo.scissorTest = true; pipelineInfo.dstBlend = BlendFunc_InvSrcAlpha; pipelineInfo.srcBlend = BlendFunc_SrcAlpha; From 65c6996ccda6e462459ae187a886fc86cdefaa09 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 15 Apr 2018 02:39:19 +0200 Subject: [PATCH 10/12] SDK/TextAreaWidget: Add support for line selection --- ChangeLog.md | 3 + SDK/include/NDK/Widgets/TextAreaWidget.hpp | 21 +- SDK/include/NDK/Widgets/TextAreaWidget.inl | 78 +++++-- SDK/src/NDK/Widgets/TextAreaWidget.cpp | 250 +++++++++++++++++---- 4 files changed, 280 insertions(+), 72 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 6b1641293..51476899b 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -88,6 +88,7 @@ Nazara Engine: - 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 Nazara Development Kit: - Added ImageWidget (#139) @@ -132,6 +133,8 @@ Nazara Development Kit: - ⚠️ 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 # 0.4: diff --git a/SDK/include/NDK/Widgets/TextAreaWidget.hpp b/SDK/include/NDK/Widgets/TextAreaWidget.hpp index e0f08053e..e7cdc2f7a 100644 --- a/SDK/include/NDK/Widgets/TextAreaWidget.hpp +++ b/SDK/include/NDK/Widgets/TextAreaWidget.hpp @@ -11,6 +11,7 @@ #include #include #include +#include namespace Ndk { @@ -30,15 +31,20 @@ namespace Ndk inline void EnableMultiline(bool enable = true); + void EraseSelection(); + inline unsigned int GetCharacterSize() const; inline const Nz::Vector2ui& GetCursorPosition() const; + inline Nz::Vector2ui GetCursorPosition(std::size_t glyphIndex) const; inline const Nz::String& GetDisplayText() const; inline EchoMode GetEchoMode() const; inline std::size_t GetGlyphIndex(const Nz::Vector2ui& cursorPosition); inline const Nz::String& GetText() 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 IsReadOnly() const; @@ -53,6 +59,7 @@ namespace Ndk inline void SetCursorPosition(Nz::Vector2ui cursorPosition); inline void SetEchoMode(EchoMode echoMode); inline void SetReadOnly(bool readOnly = true); + inline void SetSelection(Nz::Vector2ui fromPosition, Nz::Vector2ui toPosition); inline void SetText(const Nz::String& text); inline void SetTextColor(const Nz::Color& text); @@ -64,6 +71,8 @@ namespace Ndk NazaraSignal(OnTextAreaCursorMove, const TextAreaWidget* /*textArea*/, std::size_t* /*newCursorPosition*/); NazaraSignal(OnTextAreaKeyBackspace, 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(OnTextAreaKeyReturn, 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; void OnKeyReleased(const Nz::WindowEvent::KeyEvent& key) 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 RefreshCursor(); @@ -88,10 +100,13 @@ namespace Ndk EntityHandle m_cursorEntity; EntityHandle m_textEntity; Nz::SimpleTextDrawer m_drawer; - Nz::SpriteRef m_cursorSprite; Nz::String m_text; Nz::TextSpriteRef m_textSprite; - Nz::Vector2ui m_cursorPosition; + Nz::Vector2ui m_cursorPositionBegin; + Nz::Vector2ui m_cursorPositionEnd; + Nz::Vector2ui m_selectionCursor; + std::vector m_cursorSprites; + bool m_isMouseButtonDown; bool m_multiLineEnabled; bool m_readOnly; }; diff --git a/SDK/include/NDK/Widgets/TextAreaWidget.inl b/SDK/include/NDK/Widgets/TextAreaWidget.inl index 07daf7896..274d46a02 100644 --- a/SDK/include/NDK/Widgets/TextAreaWidget.inl +++ b/SDK/include/NDK/Widgets/TextAreaWidget.inl @@ -8,7 +8,8 @@ namespace Ndk { inline void TextAreaWidget::Clear() { - m_cursorPosition.MakeZero(); + m_cursorPositionBegin.MakeZero(); + m_cursorPositionEnd.MakeZero(); m_drawer.Clear(); m_text.Clear(); m_textSprite->Update(m_drawer); @@ -29,7 +30,30 @@ namespace Ndk 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(line); + cursorPos.x = static_cast(glyphIndex - lineInfo.glyphIndex); + + return cursorPos; } inline const Nz::String& TextAreaWidget::GetDisplayText() const @@ -63,7 +87,12 @@ namespace Ndk 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; } @@ -75,7 +104,7 @@ namespace Ndk inline void TextAreaWidget::MoveCursor(int offset) { - std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition); + std::size_t cursorGlyph = GetGlyphIndex(m_cursorPositionBegin); if (offset >= 0) SetCursorPosition(cursorGlyph + static_cast(offset)); else @@ -104,7 +133,7 @@ namespace Ndk } }; - Nz::Vector2ui cursorPosition = m_cursorPosition; + Nz::Vector2ui cursorPosition = m_cursorPositionBegin; cursorPosition.x = ClampOffset(static_cast(cursorPosition.x), offset.x); cursorPosition.y = ClampOffset(static_cast(cursorPosition.y), offset.y); @@ -120,22 +149,8 @@ namespace Ndk { OnTextAreaCursorMove(this, &glyphIndex); - 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); - - m_cursorPosition.y = static_cast(line); - m_cursorPosition.x = static_cast(glyphIndex - lineInfo.glyphIndex); + m_cursorPositionBegin = GetCursorPosition(glyphIndex); + m_cursorPositionEnd = m_cursorPositionBegin; RefreshCursor(); } @@ -146,7 +161,7 @@ namespace Ndk if (cursorPosition.y >= lineCount) cursorPosition.y = static_cast(lineCount - 1); - m_cursorPosition = cursorPosition; + m_cursorPositionBegin = cursorPosition; const auto& lineInfo = m_drawer.GetLine(cursorPosition.y); if (cursorPosition.y + 1 < lineCount) @@ -155,6 +170,8 @@ namespace Ndk cursorPosition.x = std::min(cursorPosition.x, static_cast(nextLineInfo.glyphIndex - lineInfo.glyphIndex - 1)); } + m_cursorPositionEnd = m_cursorPositionBegin; + std::size_t glyphIndex = lineInfo.glyphIndex + cursorPosition.x; OnTextAreaCursorMove(this, &glyphIndex); @@ -175,6 +192,23 @@ namespace Ndk 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) { m_text = text; diff --git a/SDK/src/NDK/Widgets/TextAreaWidget.cpp b/SDK/src/NDK/Widgets/TextAreaWidget.cpp index b750dd2f2..764a328d8 100644 --- a/SDK/src/NDK/Widgets/TextAreaWidget.cpp +++ b/SDK/src/NDK/Widgets/TextAreaWidget.cpp @@ -12,16 +12,14 @@ namespace Ndk TextAreaWidget::TextAreaWidget(BaseWidget* parent) : BaseWidget(parent), m_echoMode(EchoMode_Normal), - m_cursorPosition(0U, 0U), + m_cursorPositionBegin(0U, 0U), + m_cursorPositionEnd(0U, 0U), + m_isMouseButtonDown(false), m_multiLineEnabled(false), m_readOnly(false) { - m_cursorSprite = Nz::Sprite::New(); - m_cursorSprite->SetColor(Nz::Color::Black); - m_cursorSprite->SetSize(1.f, float(m_drawer.GetFont()->GetSizeInfo(m_drawer.GetCharacterSize()).lineHeight)); - m_cursorEntity = CreateEntity(true); - m_cursorEntity->AddComponent().Attach(m_cursorSprite, 10); + m_cursorEntity->AddComponent(); m_cursorEntity->AddComponent().SetParent(this); m_cursorEntity->Enable(false); @@ -72,7 +70,29 @@ namespace Ndk 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(); 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 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) { Nz::Rectf bounds = m_drawer.GetGlyph(i).bounds; @@ -96,10 +117,10 @@ namespace Ndk break; } - return i; + return Nz::Vector2ui(i - firstLineGlyph, line); } - return 0; + return Nz::Vector2ui::Zero(); } void TextAreaWidget::ResizeToContent() @@ -109,7 +130,7 @@ namespace Ndk 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()) { @@ -156,20 +177,27 @@ namespace Ndk { 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(); - if (cursorGlyph > textLength) - return true; + std::size_t textLength = m_text.GetLength(); + if (cursorGlyphBegin > textLength) + return true; - Nz::String newText; - if (cursorGlyph > 0) - newText.Append(m_text.SubString(0, m_text.GetCharacterPosition(cursorGlyph) - 1)); + Nz::String newText; + if (cursorGlyphBegin > 0) + newText.Append(m_text.SubString(0, m_text.GetCharacterPosition(cursorGlyphBegin) - 1)); - if (cursorGlyph < textLength) - newText.Append(m_text.SubString(m_text.GetCharacterPosition(cursorGlyph + 1))); + if (cursorGlyphEnd < textLength) + newText.Append(m_text.SubString(m_text.GetCharacterPosition(cursorGlyphEnd + 1))); + + SetText(newText); + } - SetText(newText); return true; } @@ -181,10 +209,38 @@ namespace Ndk if (ignoreDefaultAction) return true; + if (HasSelection()) + SetCursorPosition(m_cursorPositionEnd); + MoveCursor({0, 1}); 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({ 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: { bool ignoreDefaultAction = false; @@ -193,7 +249,11 @@ namespace Ndk if (ignoreDefaultAction) return true; - MoveCursor(-1); + if (HasSelection()) + SetCursorPosition(m_cursorPositionBegin); + else + MoveCursor(-1); + return true; } @@ -205,7 +265,11 @@ namespace Ndk if (ignoreDefaultAction) return true; - MoveCursor(1); + if (HasSelection()) + SetCursorPosition(m_cursorPositionEnd); + else + MoveCursor(1); + return true; } @@ -217,6 +281,9 @@ namespace Ndk if (ignoreDefaultAction) return true; + if (HasSelection()) + SetCursorPosition(m_cursorPositionBegin); + MoveCursor({0, -1}); return true; } @@ -237,7 +304,39 @@ namespace Ndk SetFocus(); const Padding& padding = GetPadding(); - SetCursorPosition(GetHoveredGlyph(float(x - padding.left), float(y - padding.top))); + 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))); } } @@ -253,20 +352,30 @@ namespace Ndk bool ignoreDefaultAction = false; OnTextAreaKeyBackspace(this, &ignoreDefaultAction); - std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition); - if (ignoreDefaultAction || cursorGlyph == 0) + std::size_t cursorGlyphBegin = GetGlyphIndex(m_cursorPositionBegin); + std::size_t cursorGlyphEnd = GetGlyphIndex(m_cursorPositionEnd); + + if (ignoreDefaultAction || cursorGlyphEnd == 0) 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) - newText.Append(m_text.SubString(0, m_text.GetCharacterPosition(cursorGlyph - 1) - 1)); + if (cursorGlyphBegin > 1) + newText.Append(m_text.SubString(0, m_text.GetCharacterPosition(cursorGlyphBegin - 1) - 1)); - if (cursorGlyph < m_text.GetLength()) - newText.Append(m_text.SubString(m_text.GetCharacterPosition(cursorGlyph))); + if (cursorGlyphEnd < m_text.GetLength()) + newText.Append(m_text.SubString(m_text.GetCharacterPosition(cursorGlyphEnd))); - MoveCursor(-1); - SetText(newText); + // Move cursor before setting text (to prevent SetText to move our cursor) + MoveCursor(-1); + + SetText(newText); + } break; } @@ -288,6 +397,9 @@ namespace Ndk if (Nz::Unicode::GetCategory(character) == Nz::Unicode::Category_Other_Control) break; + if (HasSelection()) + EraseSelection(); + Write(Nz::String::Unicode(character)); break; } @@ -299,24 +411,68 @@ namespace Ndk if (m_readOnly) return; - const auto& lineInfo = m_drawer.GetLine(m_cursorPosition.y); - std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition); + m_cursorEntity->GetComponent().SetPosition(GetContentOrigin()); - std::size_t glyphCount = m_drawer.GetGlyphCount(); - float position; - if (glyphCount > 0 && lineInfo.glyphIndex < cursorGlyph) + std::size_t selectionLineCount = m_cursorPositionEnd.y - m_cursorPositionBegin.y + 1; + std::size_t oldSpriteCount = m_cursorSprites.size(); + if (m_cursorSprites.size() != selectionLineCount) { - const auto& glyph = m_drawer.GetGlyph(std::min(cursorGlyph, glyphCount - 1)); - position = glyph.bounds.x; - if (cursorGlyph >= glyphCount) - position += glyph.bounds.width; + m_cursorSprites.resize(m_cursorPositionEnd.y - m_cursorPositionBegin.y + 1); + for (std::size_t i = oldSpriteCount; i < m_cursorSprites.size(); ++i) + { + 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().SetPosition(contentOrigin.x + position, contentOrigin.y + lineInfo.bounds.y); + GraphicsComponent& gfxComponent = m_cursorEntity->GetComponent(); + 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 = [&](std::size_t 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() @@ -335,6 +491,6 @@ namespace Ndk 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) } } From d68346ca1722ed693c42c1b454fb6ecc8094b9d8 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 15 Apr 2018 02:42:12 +0200 Subject: [PATCH 11/12] Utility/SimpleTextDrawer: Fix line bounds --- ChangeLog.md | 1 + src/Nazara/Utility/SimpleTextDrawer.cpp | 46 +++++++++++-------------- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 51476899b..92b2acd6a 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -89,6 +89,7 @@ Nazara Engine: - 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 Nazara Development Kit: - Added ImageWidget (#139) diff --git a/src/Nazara/Utility/SimpleTextDrawer.cpp b/src/Nazara/Utility/SimpleTextDrawer.cpp index 62df4412b..89accf012 100644 --- a/src/Nazara/Utility/SimpleTextDrawer.cpp +++ b/src/Nazara/Utility/SimpleTextDrawer.cpp @@ -354,42 +354,38 @@ namespace Nz { glyph.atlas = nullptr; - glyph.bounds.Set(float(m_drawPos.x), float(0.f), float(advance), float(sizeInfo.lineHeight)); + glyph.bounds.Set(float(m_drawPos.x), m_lines.back().bounds.y, float(advance), float(sizeInfo.lineHeight)); glyph.corners[0].Set(glyph.bounds.GetCorner(RectCorner_LeftTop)); glyph.corners[1].Set(glyph.bounds.GetCorner(RectCorner_RightTop)); glyph.corners[2].Set(glyph.bounds.GetCorner(RectCorner_LeftBottom)); glyph.corners[3].Set(glyph.bounds.GetCorner(RectCorner_RightBottom)); - - switch (character) - { - case '\n': - { - // Extend the line bounding rect to the last glyph it contains, thus extending upon all glyphs of the line - if (!m_glyphs.empty()) - { - Glyph& lastGlyph = m_glyphs.back(); - m_lines.back().bounds.ExtendTo(lastGlyph.bounds); - } - - // Reset cursor - advance = 0; - m_drawPos.x = 0; - m_drawPos.y += sizeInfo.lineHeight; - - m_workingBounds.ExtendTo(m_lines.back().bounds); - m_lines.emplace_back(Line{Rectf(0.f, float(sizeInfo.lineHeight * m_lines.size()), 0.f, float(sizeInfo.lineHeight)), m_glyphs.size() + 1}); - break; - } - } } m_lines.back().bounds.ExtendTo(glyph.bounds); + + switch (character) + { + case '\n': + { + // Reset cursor + advance = 0; + m_drawPos.x = 0; + m_drawPos.y += sizeInfo.lineHeight; + + m_workingBounds.ExtendTo(m_lines.back().bounds); + m_lines.emplace_back(Line{Rectf(0.f, float(sizeInfo.lineHeight * m_lines.size()), 0.f, float(sizeInfo.lineHeight)), m_glyphs.size() + 1}); + break; + } + + default: + m_drawPos.x += advance; + break; + } - m_drawPos.x += advance; m_glyphs.push_back(glyph); } - m_lines.back().bounds.ExtendTo(m_glyphs.back().bounds); + m_workingBounds.ExtendTo(m_lines.back().bounds); m_bounds.Set(Rectf(std::floor(m_workingBounds.x), std::floor(m_workingBounds.y), std::ceil(m_workingBounds.width), std::ceil(m_workingBounds.height))); From d234d661207284464ec75bee8a796a2ef94fc6d7 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 15 Apr 2018 03:31:01 +0200 Subject: [PATCH 12/12] Fix compilation --- SDK/src/NDK/Widgets/TextAreaWidget.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SDK/src/NDK/Widgets/TextAreaWidget.cpp b/SDK/src/NDK/Widgets/TextAreaWidget.cpp index 764a328d8..f10f57953 100644 --- a/SDK/src/NDK/Widgets/TextAreaWidget.cpp +++ b/SDK/src/NDK/Widgets/TextAreaWidget.cpp @@ -225,7 +225,7 @@ namespace Ndk return true; const auto& lineInfo = m_drawer.GetLine(m_cursorPositionEnd.y); - SetCursorPosition({ m_drawer.GetLineGlyphCount(m_cursorPositionEnd.y), m_cursorPositionEnd.y }); + SetCursorPosition({ static_cast(m_drawer.GetLineGlyphCount(m_cursorPositionEnd.y)), m_cursorPositionEnd.y }); return true; } @@ -437,7 +437,7 @@ namespace Ndk Nz::SpriteRef& cursorSprite = m_cursorSprites[i - m_cursorPositionBegin.y]; if (i == m_cursorPositionBegin.y || i == m_cursorPositionEnd.y) { - auto GetGlyphPos = [&](std::size_t localGlyphPos) + auto GetGlyphPos = [&](unsigned int localGlyphPos) { std::size_t cursorGlyph = GetGlyphIndex({ localGlyphPos, i });