diff --git a/SDK/include/NDK/BaseWidget.hpp b/SDK/include/NDK/BaseWidget.hpp new file mode 100644 index 000000000..1e6fe7c64 --- /dev/null +++ b/SDK/include/NDK/BaseWidget.hpp @@ -0,0 +1,104 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_BASEWIDGET_HPP +#define NDK_BASEWIDGET_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Ndk +{ + class Canvas; + + class NDK_API BaseWidget : public Nz::Node + { + friend Canvas; + + public: + struct Padding; + + BaseWidget(BaseWidget* parent); + BaseWidget(const BaseWidget&) = delete; + BaseWidget(BaseWidget&&) = default; + virtual ~BaseWidget(); + + template T& Add(Args&&... args); + inline void AddChild(std::unique_ptr&& widget); + + inline void Center(); + + void EnableBackground(bool enable); + + //virtual BaseWidget* Clone() const = 0; + + inline Canvas* GetCanvas(); + inline const Padding& GetPadding() const; + inline const Nz::Vector2f& GetContentSize() const; + inline Nz::Vector2f GetSize() const; + + void GrabKeyboard(); + + virtual void ResizeToContent() = 0; + + inline void SetContentSize(const Nz::Vector2f& size); + inline void SetPadding(float left, float top, float right, float bottom); + void SetSize(const Nz::Vector2f& size); + + BaseWidget& operator=(const BaseWidget&) = delete; + BaseWidget& operator=(BaseWidget&&) = default; + + struct Padding + { + float left; + float top; + float right; + float bottom; + }; + + protected: + EntityHandle CreateEntity(); + void DestroyEntity(Entity* entity); + virtual void Layout(); + void InvalidateNode() override; + + virtual void OnKeyPressed(const Nz::WindowEvent::KeyEvent& key); + virtual void OnKeyReleased(const Nz::WindowEvent::KeyEvent& key); + virtual void OnMouseEnter(); + virtual void OnMouseMoved(int x, int y, int deltaX, int deltaY); + virtual void OnMouseButtonPress(int x, int y, Nz::Mouse::Button button); + virtual void OnMouseButtonRelease(int x, int y, Nz::Mouse::Button button); + virtual void OnMouseExit(); + virtual void OnTextEntered(char32_t character, bool repeated); + + private: + inline BaseWidget(); + + inline void UpdateCanvasIndex(std::size_t index); + + std::size_t m_canvasIndex; + std::vector m_entities; + std::vector> m_children; + Canvas* m_canvas; + EntityOwner m_backgroundEntity; + Padding m_padding; + WorldHandle m_world; + Nz::Color m_backgroundColor; + Nz::SpriteRef m_backgroundSprite; + Nz::Vector2f m_contentSize; + BaseWidget* m_widgetParent; + }; +} + +#include + +#endif // NDK_BASEWIDGET_HPP diff --git a/SDK/include/NDK/BaseWidget.inl b/SDK/include/NDK/BaseWidget.inl new file mode 100644 index 000000000..0b13ee7c7 --- /dev/null +++ b/SDK/include/NDK/BaseWidget.inl @@ -0,0 +1,85 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include +#include + +namespace Ndk +{ + inline BaseWidget::BaseWidget() : + m_backgroundColor(Nz::Color(230, 230, 230, 255)), + m_canvas(nullptr), + m_contentSize(50.f, 50.f), + m_widgetParent(nullptr) + { + SetPadding(5.f, 5.f, 5.f, 5.f); + } + + template + inline T& BaseWidget::Add(Args&&... args) + { + std::unique_ptr widget = std::make_unique(this, std::forward(args)...); + T& widgetRef = *widget; + AddChild(std::move(widget)); + + return widgetRef; + } + + inline void BaseWidget::AddChild(std::unique_ptr&& widget) + { + m_children.emplace_back(std::move(widget)); + } + + inline void BaseWidget::Center() + { + NazaraAssert(m_widgetParent, "Widget has no parent"); + + Nz::Vector2f parentSize = m_widgetParent->GetSize(); + Nz::Vector2f mySize = GetSize(); + SetPosition((parentSize.x - mySize.x) / 2.f, (parentSize.y - mySize.y) / 2.f); + } + + inline Canvas* BaseWidget::GetCanvas() + { + return m_canvas; + } + + inline const BaseWidget::Padding& BaseWidget::GetPadding() const + { + return m_padding; + } + + inline const Nz::Vector2f& BaseWidget::GetContentSize() const + { + return m_contentSize; + } + + inline Nz::Vector2f BaseWidget::GetSize() const + { + return Nz::Vector2f(m_contentSize.x + m_padding.left + m_padding.right, m_contentSize.y + m_padding.top + m_padding.bottom); + } + + inline void BaseWidget::SetContentSize(const Nz::Vector2f& size) + { + m_contentSize = size; + + Layout(); + } + + inline void BaseWidget::SetPadding(float left, float top, float right, float bottom) + { + m_padding.left = left; + m_padding.top = top; + m_padding.bottom = bottom; + m_padding.right = right; + + Layout(); + } + + inline void BaseWidget::UpdateCanvasIndex(std::size_t index) + { + m_canvasIndex = index; + } +} diff --git a/SDK/include/NDK/Canvas.hpp b/SDK/include/NDK/Canvas.hpp new file mode 100644 index 000000000..a8da5d04e --- /dev/null +++ b/SDK/include/NDK/Canvas.hpp @@ -0,0 +1,78 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_CANVAS_HPP +#define NDK_CANVAS_HPP + +#include +#include +#include + +namespace Ndk +{ + class NDK_API Canvas : public BaseWidget + { + friend BaseWidget; + + public: + struct Padding; + + inline Canvas(WorldHandle world, Nz::EventHandler& eventHandler); + Canvas(const Canvas&) = delete; + Canvas(Canvas&&) = delete; + ~Canvas() = default; + + inline const WorldHandle& GetWorld() const; + + void ResizeToContent() override; + + Canvas& operator=(const Canvas&) = delete; + Canvas& operator=(Canvas&&) = delete; + + protected: + void Layout() override; + + void NotifyWidgetUpdate(std::size_t index); + + std::size_t RegisterWidget(BaseWidget* widget); + + inline void SetKeyboardOwner(BaseWidget* widget); + + void UnregisterWidget(std::size_t index); + + private: + void OnMouseButtonPressed(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::MouseButtonEvent& event); + void OnMouseButtonRelease(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::MouseButtonEvent& event); + void OnMouseMoved(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::MouseMoveEvent& event); + void OnMouseLeft(const Nz::EventHandler* eventHandler); + void OnKeyPressed(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::KeyEvent& event); + void OnKeyReleased(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::KeyEvent& event); + void OnTextEntered(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::TextEvent& event); + + struct WidgetBox + { + BaseWidget* widget; + Nz::Boxf box; + }; + + NazaraSlot(Nz::EventHandler, OnKeyPressed, m_keyPressedSlot); + NazaraSlot(Nz::EventHandler, OnKeyReleased, m_keyReleasedSlot); + NazaraSlot(Nz::EventHandler, OnMouseButtonPressed, m_mouseButtonPressedSlot); + NazaraSlot(Nz::EventHandler, OnMouseButtonReleased, m_mouseButtonReleasedSlot); + NazaraSlot(Nz::EventHandler, OnMouseMoved, m_mouseMovedSlot); + NazaraSlot(Nz::EventHandler, OnMouseLeft, m_mouseLeftSlot); + NazaraSlot(Nz::EventHandler, OnTextEntered, m_textEnteredSlot); + + std::vector m_widgetBoxes; + const WidgetBox* m_hoveredWidget; + BaseWidget* m_keyboardOwner; + WorldHandle m_world; + }; +} + +#include + +#endif // NDK_CANVAS_HPP diff --git a/SDK/include/NDK/Canvas.inl b/SDK/include/NDK/Canvas.inl new file mode 100644 index 000000000..d0d05bf12 --- /dev/null +++ b/SDK/include/NDK/Canvas.inl @@ -0,0 +1,34 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include + +namespace Ndk +{ + inline Canvas::Canvas(WorldHandle world, Nz::EventHandler& eventHandler) : + m_hoveredWidget(nullptr), + m_keyboardOwner(nullptr), + m_world(std::move(world)) + { + m_canvas = this; + + m_keyPressedSlot.Connect(eventHandler.OnKeyPressed, this, &Canvas::OnKeyPressed); + m_keyReleasedSlot.Connect(eventHandler.OnKeyReleased, this, &Canvas::OnKeyReleased); + m_mouseButtonPressedSlot.Connect(eventHandler.OnMouseButtonPressed, this, &Canvas::OnMouseButtonPressed); + m_mouseButtonReleasedSlot.Connect(eventHandler.OnMouseButtonReleased, this, &Canvas::OnMouseButtonRelease); + m_mouseMovedSlot.Connect(eventHandler.OnMouseMoved, this, &Canvas::OnMouseMoved); + m_mouseLeftSlot.Connect(eventHandler.OnMouseLeft, this, &Canvas::OnMouseLeft); + m_textEnteredSlot.Connect(eventHandler.OnTextEntered, this, &Canvas::OnTextEntered); + } + + inline const WorldHandle& Canvas::GetWorld() const + { + return m_world; + } + + inline void Ndk::Canvas::SetKeyboardOwner(BaseWidget* widget) + { + m_keyboardOwner = widget; + } +} diff --git a/SDK/include/NDK/Components/CameraComponent.hpp b/SDK/include/NDK/Components/CameraComponent.hpp index 6bb3718c0..5a9efe742 100644 --- a/SDK/include/NDK/Components/CameraComponent.hpp +++ b/SDK/include/NDK/Components/CameraComponent.hpp @@ -64,6 +64,8 @@ namespace Ndk inline void SetZFar(float zFar); inline void SetZNear(float zNear); + inline bool UpdateVisibility(std::size_t visibilityHash); + static ComponentIndex componentIndex; private: @@ -89,6 +91,7 @@ namespace Ndk NazaraSlot(Nz::RenderTarget, OnRenderTargetRelease, m_targetReleaseSlot); NazaraSlot(Nz::RenderTarget, OnRenderTargetSizeChange, m_targetResizeSlot); + std::size_t m_visibilityHash; Nz::ProjectionType m_projectionType; mutable Nz::Frustumf m_frustum; mutable Nz::Matrix4f m_projectionMatrix; diff --git a/SDK/include/NDK/Components/CameraComponent.inl b/SDK/include/NDK/Components/CameraComponent.inl index 550cbd7b4..9aadfd509 100644 --- a/SDK/include/NDK/Components/CameraComponent.inl +++ b/SDK/include/NDK/Components/CameraComponent.inl @@ -13,6 +13,7 @@ namespace Ndk */ inline CameraComponent::CameraComponent() : + m_visibilityHash(0U), m_projectionType(Nz::ProjectionType_Perspective), m_targetRegion(0.f, 0.f, 1.f, 1.f), m_target(nullptr), @@ -38,6 +39,7 @@ namespace Ndk inline CameraComponent::CameraComponent(const CameraComponent& camera) : Component(camera), AbstractViewer(camera), + m_visibilityHash(camera.m_visibilityHash), m_projectionType(camera.m_projectionType), m_targetRegion(camera.m_targetRegion), m_target(nullptr), @@ -280,6 +282,26 @@ namespace Ndk InvalidateProjectionMatrix(); } + /*! + * \brief Update the camera component visibility hash + * + * This is used with CullingList (which produce a visibility hash) + * + * \param visibilityHash New visibility hash + * + * \return True if the visibility hash is not the same as before + */ + inline bool CameraComponent::UpdateVisibility(std::size_t visibilityHash) + { + if (m_visibilityHash != visibilityHash) + { + m_visibilityHash = visibilityHash; + return true; + } + + return false; + } + /*! * \brief Invalidates the frustum */ diff --git a/SDK/include/NDK/Components/GraphicsComponent.hpp b/SDK/include/NDK/Components/GraphicsComponent.hpp index f8cd6d957..418500a96 100644 --- a/SDK/include/NDK/Components/GraphicsComponent.hpp +++ b/SDK/include/NDK/Components/GraphicsComponent.hpp @@ -8,6 +8,7 @@ #ifndef NDK_COMPONENTS_GRAPHICSCOMPONENT_HPP #define NDK_COMPONENTS_GRAPHICSCOMPONENT_HPP +#include #include #include #include @@ -16,6 +17,7 @@ namespace Ndk { class GraphicsComponent; + using GraphicsComponentCullingList = Nz::CullingList; using GraphicsComponentHandle = Nz::ObjectHandle; class NDK_API GraphicsComponent : public Component, public Nz::HandledObject @@ -29,10 +31,11 @@ namespace Ndk inline GraphicsComponent(const GraphicsComponent& graphicsComponent); ~GraphicsComponent() = default; - inline void AddToRenderQueue(Nz::AbstractRenderQueue* renderQueue) const; + inline void AddToCullingList(GraphicsComponentCullingList* cullingList) const; + void AddToRenderQueue(Nz::AbstractRenderQueue* renderQueue) const; - inline void Attach(Nz::InstancedRenderableRef renderable, int renderOrder = 0); - inline void Attach(Nz::InstancedRenderableRef renderable, const Nz::Matrix4f& localMatrix, int renderOrder = 0); + void Attach(Nz::InstancedRenderableRef renderable, int renderOrder = 0); + void Attach(Nz::InstancedRenderableRef renderable, const Nz::Matrix4f& localMatrix, int renderOrder = 0); inline void Clear(); @@ -46,10 +49,12 @@ namespace Ndk inline const Nz::BoundingVolumef& GetBoundingVolume() const; + inline void RemoveFromCullingList(GraphicsComponentCullingList* cullingList) const; + static ComponentIndex componentIndex; private: - inline void InvalidateBoundingVolume(); + inline void InvalidateBoundingVolume() const; void InvalidateRenderableData(const Nz::InstancedRenderable* renderable, Nz::UInt32 flags, std::size_t index); inline void InvalidateRenderables(); inline void InvalidateTransformMatrix(); @@ -74,7 +79,8 @@ namespace Ndk } Renderable(Renderable&& rhs) noexcept : - renderableInvalidationSlot(std::move(rhs.renderableInvalidationSlot)), + renderableBoundingVolumeInvalidationSlot(std::move(rhs.renderableBoundingVolumeInvalidationSlot)), + renderableDataInvalidationSlot(std::move(rhs.renderableDataInvalidationSlot)), renderableReleaseSlot(std::move(rhs.renderableReleaseSlot)), data(std::move(rhs.data)), renderable(std::move(rhs.renderable)), @@ -93,13 +99,15 @@ namespace Ndk data = std::move(r.data); dataUpdated = r.dataUpdated; renderable = std::move(r.renderable); - renderableInvalidationSlot = std::move(r.renderableInvalidationSlot); + renderableBoundingVolumeInvalidationSlot = std::move(r.renderableBoundingVolumeInvalidationSlot); + renderableDataInvalidationSlot = std::move(r.renderableDataInvalidationSlot); renderableReleaseSlot = std::move(r.renderableReleaseSlot); return *this; } - NazaraSlot(Nz::InstancedRenderable, OnInstancedRenderableInvalidateData, renderableInvalidationSlot); + NazaraSlot(Nz::InstancedRenderable, OnInstancedRenderableInvalidateBoundingVolume, renderableBoundingVolumeInvalidationSlot); + NazaraSlot(Nz::InstancedRenderable, OnInstancedRenderableInvalidateData, renderableDataInvalidationSlot); NazaraSlot(Nz::InstancedRenderable, OnInstancedRenderableRelease, renderableReleaseSlot); mutable Nz::InstancedRenderable::InstanceData data; @@ -107,6 +115,16 @@ namespace Ndk mutable bool dataUpdated; }; + using VolumeCullingListEntry = GraphicsComponentCullingList::VolumeEntry; + + struct VolumeCullingEntry + { + VolumeCullingListEntry listEntry; + + NazaraSlot(GraphicsComponentCullingList, OnCullingListRelease, cullingListReleaseSlot); + }; + + mutable std::vector m_volumeCullingEntries; std::vector m_renderables; mutable Nz::BoundingVolumef m_boundingVolume; mutable Nz::Matrix4f m_transformMatrix; diff --git a/SDK/include/NDK/Components/GraphicsComponent.inl b/SDK/include/NDK/Components/GraphicsComponent.inl index bd3e6dbfb..6ca950e24 100644 --- a/SDK/include/NDK/Components/GraphicsComponent.inl +++ b/SDK/include/NDK/Components/GraphicsComponent.inl @@ -28,52 +28,12 @@ namespace Ndk Attach(r.renderable, r.data.renderOrder); } - /*! - * \brief Adds the renderable elements to the render queue - * - * \param renderQueue Queue to be added - */ - - inline void GraphicsComponent::AddToRenderQueue(Nz::AbstractRenderQueue* renderQueue) const + inline void GraphicsComponent::AddToCullingList(GraphicsComponentCullingList* cullingList) const { - EnsureTransformMatrixUpdate(); - - Ndk::RenderSystem& renderSystem = m_entity->GetWorld()->GetSystem(); - - for (const Renderable& object : m_renderables) - { - if (!object.dataUpdated) - { - object.data.transformMatrix = Nz::Matrix4f::ConcatenateAffine(renderSystem.GetCoordinateSystemMatrix(), Nz::Matrix4f::ConcatenateAffine(object.data.localMatrix, m_transformMatrix)); - object.renderable->UpdateData(&object.data); - object.dataUpdated = true; - } - - object.renderable->AddToRenderQueue(renderQueue, object.data); - } - } - - /*! - * \brief Attaches a renderable to the entity - * - * \param renderable Reference to a renderable element - * \param renderOrder Render order of the element - */ - - inline void GraphicsComponent::Attach(Nz::InstancedRenderableRef renderable, int renderOrder) - { - return Attach(renderable, Nz::Matrix4f::Identity(), renderOrder); - } - - inline void GraphicsComponent::Attach(Nz::InstancedRenderableRef renderable, const Nz::Matrix4f& localMatrix, int renderOrder) - { - m_renderables.emplace_back(m_transformMatrix); - Renderable& r = m_renderables.back(); - r.data.localMatrix = localMatrix; - r.data.renderOrder = renderOrder; - r.renderable = std::move(renderable); - r.renderableInvalidationSlot.Connect(r.renderable->OnInstancedRenderableInvalidateData, std::bind(&GraphicsComponent::InvalidateRenderableData, this, std::placeholders::_1, std::placeholders::_2, m_renderables.size() - 1)); - r.renderableReleaseSlot.Connect(r.renderable->OnInstancedRenderableRelease, this, &GraphicsComponent::Detach); + m_volumeCullingEntries.emplace_back(VolumeCullingEntry{}); + VolumeCullingEntry& entry = m_volumeCullingEntries.back(); + entry.cullingListReleaseSlot.Connect(cullingList->OnCullingListRelease, this, &GraphicsComponent::RemoveFromCullingList); + entry.listEntry = cullingList->RegisterVolumeTest(this); InvalidateBoundingVolume(); } @@ -167,11 +127,26 @@ namespace Ndk return m_boundingVolume; } + inline void GraphicsComponent::RemoveFromCullingList(GraphicsComponentCullingList* cullingList) const + { + for (auto it = m_volumeCullingEntries.begin(); it != m_volumeCullingEntries.end(); ++it) + { + if (it->listEntry.GetParent() == cullingList) + { + if (m_volumeCullingEntries.size() > 1) + *it = std::move(m_volumeCullingEntries.back()); + + m_volumeCullingEntries.pop_back(); + break; + } + } + } + /*! * \brief Invalidates the bounding volume */ - inline void GraphicsComponent::InvalidateBoundingVolume() + inline void GraphicsComponent::InvalidateBoundingVolume() const { m_boundingVolumeUpdated = false; } @@ -192,9 +167,9 @@ namespace Ndk inline void GraphicsComponent::InvalidateTransformMatrix() { - m_boundingVolumeUpdated = false; m_transformMatrixUpdated = false; + InvalidateBoundingVolume(); InvalidateRenderables(); } -} +} \ No newline at end of file diff --git a/SDK/include/NDK/Console.hpp b/SDK/include/NDK/Console.hpp index 1c007065f..59a98df0d 100644 --- a/SDK/include/NDK/Console.hpp +++ b/SDK/include/NDK/Console.hpp @@ -4,6 +4,7 @@ #pragma once +#ifndef NDK_SERVER #ifndef NDK_CONSOLE_HPP #define NDK_CONSOLE_HPP @@ -99,3 +100,4 @@ namespace Ndk #include #endif // NDK_CONSOLE_HPP +#endif // NDK_SERVER diff --git a/SDK/include/NDK/Lua/LuaBinding.hpp b/SDK/include/NDK/Lua/LuaBinding.hpp new file mode 100644 index 000000000..307345589 --- /dev/null +++ b/SDK/include/NDK/Lua/LuaBinding.hpp @@ -0,0 +1,68 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_LUABINDING_HPP +#define NDK_LUABINDING_HPP + +#include +#include +#include +#include + +namespace Ndk +{ + class NDK_API LuaBinding + { + friend class LuaBinding_SDK; + + public: + LuaBinding(); + ~LuaBinding() = default; + + template void BindComponent(const Nz::String& name); + + void RegisterClasses(Nz::LuaInstance& instance); + + std::unique_ptr core; + std::unique_ptr math; + std::unique_ptr network; + std::unique_ptr sdk; + std::unique_ptr utility; + + #ifndef NDK_SERVER + std::unique_ptr audio; + std::unique_ptr graphics; + std::unique_ptr renderer; + #endif + + private: + template + static int AddComponentOfType(Nz::LuaInstance& lua, EntityHandle& handle); + + template + static int PushComponentOfType(Nz::LuaInstance& lua, BaseComponent& component); + + using AddComponentFunc = int(*)(Nz::LuaInstance&, EntityHandle&); + using GetComponentFunc = int(*)(Nz::LuaInstance&, BaseComponent&); + + struct ComponentBinding + { + AddComponentFunc adder; + ComponentIndex index; + GetComponentFunc getter; + Nz::String name; + }; + + ComponentBinding* QueryComponentIndex(Nz::LuaInstance& lua, int argIndex = 2); + + std::vector m_componentBinding; + std::unordered_map m_componentBindingByName; + }; +} + +#include + +#endif // NDK_LUABINDING_HPP diff --git a/SDK/include/NDK/LuaBinding.inl b/SDK/include/NDK/Lua/LuaBinding.inl similarity index 66% rename from SDK/include/NDK/LuaBinding.inl rename to SDK/include/NDK/Lua/LuaBinding.inl index e4ae72254..ca77dfcf6 100644 --- a/SDK/include/NDK/LuaBinding.inl +++ b/SDK/include/NDK/Lua/LuaBinding.inl @@ -2,7 +2,7 @@ // This file is part of the "Nazara Development Kit" // For conditions of distribution and use, see copyright notice in Prerequesites.hpp -#include +#include namespace Ndk { @@ -32,18 +32,8 @@ namespace Ndk m_componentBindingByName[name] = T::componentIndex; } - /*! - * \brief Adds a component to an entity - * \return 1 in case of success - * - * \param instance Lua instance that will interact with the component - * \param handle Entity which component will be added to - * - * \remark T must be a subtype of BaseComponent - */ - template - int AddComponentOfType(Nz::LuaInstance& lua, EntityHandle& handle) + int LuaBinding::AddComponentOfType(Nz::LuaInstance& lua, EntityHandle& handle) { static_assert(std::is_base_of::value, "ComponentType must inherit BaseComponent"); @@ -52,18 +42,8 @@ namespace Ndk return 1; } - /*! - * \brief Pushes a component - * \return 1 in case of success - * - * \param instance Lua instance that will interact with the component - * \param component Component that will be pushed - * - * \remark T must be a subtype of BaseComponent - */ - template - int PushComponentOfType(Nz::LuaInstance& lua, BaseComponent& component) + int LuaBinding::PushComponentOfType(Nz::LuaInstance& lua, BaseComponent& component) { static_assert(std::is_base_of::value, "ComponentType must inherit BaseComponent"); diff --git a/SDK/include/NDK/Lua/LuaBinding_Audio.hpp b/SDK/include/NDK/Lua/LuaBinding_Audio.hpp new file mode 100644 index 000000000..510654342 --- /dev/null +++ b/SDK/include/NDK/Lua/LuaBinding_Audio.hpp @@ -0,0 +1,33 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_LUABINDING_AUDIO_HPP +#define NDK_LUABINDING_AUDIO_HPP + +#include +#include +#include +#include +#include + +namespace Ndk +{ + class NDK_API LuaBinding_Audio : public LuaBinding_Base + { + public: + LuaBinding_Audio(LuaBinding& binding); + ~LuaBinding_Audio() = default; + + void Register(Nz::LuaInstance& instance) override; + + Nz::LuaClass music; + Nz::LuaClass sound; + Nz::LuaClass soundBuffer; + Nz::LuaClass soundEmitter; + }; +} + +#endif // NDK_LUABINDING_CORE_HPP diff --git a/SDK/include/NDK/Lua/LuaBinding_Base.hpp b/SDK/include/NDK/Lua/LuaBinding_Base.hpp new file mode 100644 index 000000000..29c486835 --- /dev/null +++ b/SDK/include/NDK/Lua/LuaBinding_Base.hpp @@ -0,0 +1,53 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_LUABINDING_BASE_HPP +#define NDK_LUABINDING_BASE_HPP + +#include +#include +#include + +namespace Ndk +{ + class LuaBinding; + + class LuaBinding_Audio; + class LuaBinding_Core; + class LuaBinding_Graphics; + class LuaBinding_Math; + class LuaBinding_Network; + class LuaBinding_Renderer; + class LuaBinding_SDK; + class LuaBinding_Utility; + + class NDK_API LuaBinding_Base + { + public: + LuaBinding_Base(LuaBinding& binding); + virtual ~LuaBinding_Base(); + + virtual void Register(Nz::LuaInstance& instance) = 0; + + // Implementation lies in the respective .cpp files (still searching for a cleaner way..) + static std::unique_ptr BindCore(LuaBinding& binding); + static std::unique_ptr BindMath(LuaBinding& binding); + static std::unique_ptr BindNetwork(LuaBinding& binding); + static std::unique_ptr BindSDK(LuaBinding& binding); + static std::unique_ptr BindUtility(LuaBinding& binding); + + #ifndef NDK_SERVER + static std::unique_ptr BindAudio(LuaBinding& binding); + static std::unique_ptr BindGraphics(LuaBinding& binding); + static std::unique_ptr BindRenderer(LuaBinding& binding); + #endif + + protected: + LuaBinding& m_binding; + }; +} + +#endif // NDK_LUABINDING_BASE_HPP diff --git a/SDK/include/NDK/Lua/LuaBinding_Core.hpp b/SDK/include/NDK/Lua/LuaBinding_Core.hpp new file mode 100644 index 000000000..54400958f --- /dev/null +++ b/SDK/include/NDK/Lua/LuaBinding_Core.hpp @@ -0,0 +1,33 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_LUABINDING_CORE_HPP +#define NDK_LUABINDING_CORE_HPP + +#include +#include +#include +#include +#include + +namespace Ndk +{ + class NDK_API LuaBinding_Core : public LuaBinding_Base + { + public: + LuaBinding_Core(LuaBinding& binding); + ~LuaBinding_Core() = default; + + void Register(Nz::LuaInstance& instance) override; + + Nz::LuaClass clock; + Nz::LuaClass directory; + Nz::LuaClass file; + Nz::LuaClass stream; + }; +} + +#endif // NDK_LUABINDING_CORE_HPP diff --git a/SDK/include/NDK/Lua/LuaBinding_Graphics.hpp b/SDK/include/NDK/Lua/LuaBinding_Graphics.hpp new file mode 100644 index 000000000..75a6eff8f --- /dev/null +++ b/SDK/include/NDK/Lua/LuaBinding_Graphics.hpp @@ -0,0 +1,36 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_LUABINDING_GRAPHICS_HPP +#define NDK_LUABINDING_GRAPHICS_HPP + +#include +#include +#include +#include +#include +#include + +namespace Ndk +{ + class NDK_API LuaBinding_Graphics : public LuaBinding_Base + { + public: + LuaBinding_Graphics(LuaBinding& binding); + ~LuaBinding_Graphics() = default; + + void Register(Nz::LuaInstance& instance) override; + + Nz::LuaClass abstractViewer; + Nz::LuaClass instancedRenderable; + Nz::LuaClass material; + Nz::LuaClass model; + Nz::LuaClass sprite; + Nz::LuaClass spriteLibrary; + }; +} + +#endif // NDK_LUABINDING_GRAPHICS_HPP diff --git a/SDK/include/NDK/Lua/LuaBinding_Math.hpp b/SDK/include/NDK/Lua/LuaBinding_Math.hpp new file mode 100644 index 000000000..195d34ec2 --- /dev/null +++ b/SDK/include/NDK/Lua/LuaBinding_Math.hpp @@ -0,0 +1,37 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_LUABINDING_MATH_HPP +#define NDK_LUABINDING_MATH_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace Ndk +{ + class NDK_API LuaBinding_Math : public LuaBinding_Base + { + public: + LuaBinding_Math(LuaBinding& binding); + ~LuaBinding_Math() = default; + + void Register(Nz::LuaInstance& instance) override; + + Nz::LuaClass eulerAngles; + Nz::LuaClass matrix4d; + Nz::LuaClass quaternion; + Nz::LuaClass rect; + Nz::LuaClass vector2d; + Nz::LuaClass vector3d; + }; +} + +#endif // NDK_LUABINDING_MATH_HPP diff --git a/SDK/include/NDK/Lua/LuaBinding_Network.hpp b/SDK/include/NDK/Lua/LuaBinding_Network.hpp new file mode 100644 index 000000000..f69e038a7 --- /dev/null +++ b/SDK/include/NDK/Lua/LuaBinding_Network.hpp @@ -0,0 +1,29 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_LUABINDING_NETWORK_HPP +#define NDK_LUABINDING_NETWORK_HPP + +#include +#include +#include + +namespace Ndk +{ + class NDK_API LuaBinding_Network : public LuaBinding_Base + { + public: + LuaBinding_Network(LuaBinding& binding); + ~LuaBinding_Network() = default; + + void Register(Nz::LuaInstance& instance) override; + + Nz::LuaClass abstractSocket; + Nz::LuaClass ipAddress; + }; +} + +#endif // NDK_LUABINDING_NETWORK_HPP diff --git a/SDK/include/NDK/Lua/LuaBinding_Renderer.hpp b/SDK/include/NDK/Lua/LuaBinding_Renderer.hpp new file mode 100644 index 000000000..7655c9ac3 --- /dev/null +++ b/SDK/include/NDK/Lua/LuaBinding_Renderer.hpp @@ -0,0 +1,29 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_LUABINDING_RENDERER_HPP +#define NDK_LUABINDING_RENDERER_HPP + +#include +#include + +namespace Ndk +{ + class NDK_API LuaBinding_Renderer : public LuaBinding_Base + { + public: + LuaBinding_Renderer(LuaBinding& binding); + ~LuaBinding_Renderer() = default; + + void Register(Nz::LuaInstance& instance) override; + + Nz::LuaClass texture; + Nz::LuaClass textureLibrary; + Nz::LuaClass textureManager; + }; +} + +#endif // NDK_LUABINDING_RENDERER_HPP diff --git a/SDK/include/NDK/Lua/LuaBinding_SDK.hpp b/SDK/include/NDK/Lua/LuaBinding_SDK.hpp new file mode 100644 index 000000000..facfd5620 --- /dev/null +++ b/SDK/include/NDK/Lua/LuaBinding_SDK.hpp @@ -0,0 +1,42 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_LUABINDING_SDK_HPP +#define NDK_LUABINDING_SDK_HPP + +#include +#include +#include +#include + +namespace Ndk +{ + class Application; + + class NDK_API LuaBinding_SDK : public LuaBinding_Base + { + public: + LuaBinding_SDK(LuaBinding& binding); + ~LuaBinding_SDK() = default; + + void Register(Nz::LuaInstance& instance) override; + + Nz::LuaClass application; + Nz::LuaClass entity; + Nz::LuaClass nodeComponent; + Nz::LuaClass velocityComponent; + Nz::LuaClass world; + + #ifndef NDK_SERVER + Nz::LuaClass cameraComponent; + Nz::LuaClass console; + Nz::LuaClass graphicsComponent; + #endif + + }; +} + +#endif // NDK_LUABINDING_SDK_HPP diff --git a/SDK/include/NDK/Lua/LuaBinding_Utility.hpp b/SDK/include/NDK/Lua/LuaBinding_Utility.hpp new file mode 100644 index 000000000..80afde5bf --- /dev/null +++ b/SDK/include/NDK/Lua/LuaBinding_Utility.hpp @@ -0,0 +1,34 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_LUABINDING_UTILITY_HPP +#define NDK_LUABINDING_UTILITY_HPP + +#include +#include +#include +#include +#include + +namespace Ndk +{ + class NDK_API LuaBinding_Utility : public LuaBinding_Base + { + public: + LuaBinding_Utility(LuaBinding& binding); + ~LuaBinding_Utility() = default; + + void Register(Nz::LuaInstance& instance) override; + + // Utility + Nz::LuaClass abstractImage; + Nz::LuaClass font; + Nz::LuaClass keyboard; + Nz::LuaClass node; + }; +} + +#endif // NDK_LUABINDING_UTILITY_HPP diff --git a/SDK/include/NDK/LuaAPI.inl b/SDK/include/NDK/LuaAPI.inl index f2ddf251c..6b7573597 100644 --- a/SDK/include/NDK/LuaAPI.inl +++ b/SDK/include/NDK/LuaAPI.inl @@ -156,9 +156,10 @@ namespace Nz params->animated = instance.CheckField("Animated", params->animated); params->center = instance.CheckField("Center", params->center); - params->flipUVs = instance.CheckField("FlipUVs", params->flipUVs); params->matrix = instance.CheckField("Matrix", params->matrix); params->optimizeIndexBuffers = instance.CheckField("OptimizeIndexBuffers", params->optimizeIndexBuffers); + params->texCoordOffset = instance.CheckField("TexCoordOffset", params->texCoordOffset); + params->texCoordScale = instance.CheckField("TexCoordScale", params->texCoordScale); return 1; } @@ -403,7 +404,6 @@ namespace Nz return 1; } - #endif inline int LuaImplReplyVal(const LuaInstance& instance, Color&& val, TypeTag) diff --git a/SDK/include/NDK/LuaBinding.hpp b/SDK/include/NDK/LuaBinding.hpp deleted file mode 100644 index 559d6ac1f..000000000 --- a/SDK/include/NDK/LuaBinding.hpp +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Development Kit" -// For conditions of distribution and use, see copyright notice in Prerequesites.hpp - -#pragma once - -#ifndef NDK_LUABINDING_HPP -#define NDK_LUABINDING_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef NDK_SERVER -#include -#include -#include -#include -#endif - -namespace Ndk -{ - class NDK_API LuaBinding - { - public: - LuaBinding(); - ~LuaBinding() = default; - - template void BindComponent(const Nz::String& name); - - void RegisterClasses(Nz::LuaInstance& instance); - - // Core - Nz::LuaClass clock; - Nz::LuaClass directory; - Nz::LuaClass file; - Nz::LuaClass stream; - - // Math - Nz::LuaClass eulerAngles; - Nz::LuaClass matrix4d; - Nz::LuaClass quaternion; - Nz::LuaClass rect; - Nz::LuaClass vector2d; - Nz::LuaClass vector3d; - - // Network - Nz::LuaClass abstractSocket; - Nz::LuaClass ipAddress; - - // Utility - Nz::LuaClass abstractImage; - Nz::LuaClass font; - Nz::LuaClass keyboard; - Nz::LuaClass node; - - // SDK - Nz::LuaClass application; - Nz::LuaClass entity; - Nz::LuaClass nodeComponent; - Nz::LuaClass velocityComponent; - Nz::LuaClass world; - - #ifndef NDK_SERVER - // Audio - Nz::LuaClass music; - Nz::LuaClass sound; - Nz::LuaClass soundBuffer; - Nz::LuaClass soundEmitter; - - // Graphics - Nz::LuaClass abstractViewer; - Nz::LuaClass instancedRenderable; - Nz::LuaClass material; - Nz::LuaClass model; - Nz::LuaClass sprite; - Nz::LuaClass spriteLibrary; - Nz::LuaClass textureLibrary; - Nz::LuaClass textureManager; - - // Renderer - Nz::LuaClass texture; - - // SDK - Nz::LuaClass cameraComponent; - Nz::LuaClass console; - Nz::LuaClass graphicsComponent; - #endif - - private: - void BindCore(); - void BindMath(); - void BindNetwork(); - void BindSDK(); - void BindUtility(); - - void RegisterCore(Nz::LuaInstance& instance); - void RegisterMath(Nz::LuaInstance& instance); - void RegisterNetwork(Nz::LuaInstance& instance); - void RegisterSDK(Nz::LuaInstance& instance); - void RegisterUtility(Nz::LuaInstance& instance); - - #ifndef NDK_SERVER - void BindAudio(); - void BindGraphics(); - void BindRenderer(); - - void RegisterAudio(Nz::LuaInstance& instance); - void RegisterGraphics(Nz::LuaInstance& instance); - void RegisterRenderer(Nz::LuaInstance& instance); - #endif - - - using AddComponentFunc = int(*)(Nz::LuaInstance&, EntityHandle&); - using GetComponentFunc = int(*)(Nz::LuaInstance&, BaseComponent&); - - struct ComponentBinding - { - AddComponentFunc adder; - ComponentIndex index; - GetComponentFunc getter; - Nz::String name; - }; - - ComponentBinding* QueryComponentIndex(Nz::LuaInstance& lua, int argIndex = 2); - - std::vector m_componentBinding; - std::unordered_map m_componentBindingByName; - }; - - template - int AddComponentOfType(Nz::LuaInstance& lua, EntityHandle& handle); - - template - int PushComponentOfType(Nz::LuaInstance& lua, BaseComponent& component); -} - -#include - -#endif // NDK_LUABINDING_HPP diff --git a/SDK/include/NDK/Systems/RenderSystem.hpp b/SDK/include/NDK/Systems/RenderSystem.hpp index 488d1a7d4..61ccefe75 100644 --- a/SDK/include/NDK/Systems/RenderSystem.hpp +++ b/SDK/include/NDK/Systems/RenderSystem.hpp @@ -9,9 +9,11 @@ #define NDK_SYSTEMS_RENDERSYSTEM_HPP #include +#include #include #include #include +#include #include #include #include @@ -19,8 +21,6 @@ namespace Ndk { - class GraphicsComponent; - class NDK_API RenderSystem : public System { public: @@ -51,21 +51,25 @@ namespace Ndk void OnEntityRemoved(Entity* entity) override; void OnEntityValidation(Entity* entity, bool justAdded) override; void OnUpdate(float elapsedTime) override; + void UpdateDirectionalShadowMaps(const Nz::AbstractViewer& viewer); void UpdatePointSpotShadowMaps(); std::unique_ptr m_renderTechnique; + std::vector m_volumeEntries; EntityList m_cameras; EntityList m_drawables; EntityList m_directionalLights; EntityList m_lights; EntityList m_pointSpotLights; EntityList m_particleGroups; + GraphicsComponentCullingList m_drawableCulling; Nz::BackgroundRef m_background; Nz::DepthRenderTechnique m_shadowTechnique; Nz::Matrix4f m_coordinateSystemMatrix; Nz::RenderTexture m_shadowRT; bool m_coordinateSystemInvalidated; + bool m_forceRenderQueueInvalidation; }; } diff --git a/SDK/include/NDK/Widgets.hpp b/SDK/include/NDK/Widgets.hpp new file mode 100644 index 000000000..a019c007b --- /dev/null +++ b/SDK/include/NDK/Widgets.hpp @@ -0,0 +1,12 @@ +// This file was automatically generated + +#pragma once + +#ifndef NDK_WIDGETS_GLOBAL_HPP +#define NDK_WIDGETS_GLOBAL_HPP + +#include +#include +#include + +#endif // NDK_WIDGETS_GLOBAL_HPP diff --git a/SDK/include/NDK/Widgets/ButtonWidget.hpp b/SDK/include/NDK/Widgets/ButtonWidget.hpp new file mode 100644 index 000000000..e2173d17e --- /dev/null +++ b/SDK/include/NDK/Widgets/ButtonWidget.hpp @@ -0,0 +1,56 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_WIDGETS_BUTTONWIDGET_HPP +#define NDK_WIDGETS_BUTTONWIDGET_HPP + +#include +#include +#include +#include +#include + +namespace Ndk +{ + class World; + + class NDK_API ButtonWidget : public BaseWidget + { + public: + ButtonWidget(BaseWidget* parent = nullptr); + ButtonWidget(const ButtonWidget&) = delete; + ButtonWidget(ButtonWidget&&) = default; + ~ButtonWidget() = default; + + //virtual ButtonWidget* Clone() const = 0; + + void ResizeToContent(); + + inline void UpdateText(const Nz::AbstractTextDrawer& drawer); + + ButtonWidget& operator=(const ButtonWidget&) = delete; + ButtonWidget& operator=(ButtonWidget&&) = default; + + NazaraSignal(OnButtonTrigger, const ButtonWidget* /*button*/); + + private: + void Layout() override; + + void OnMouseEnter() override; + void OnMouseMoved(int x, int y, int deltaX, int deltaY) override; + void OnMouseButtonRelease(int x, int y, Nz::Mouse::Button button) override; + void OnMouseExit() override; + + EntityHandle m_textEntity; + EntityHandle m_gradientEntity; + Nz::SpriteRef m_gradientSprite; + Nz::TextSpriteRef m_textSprite; + }; +} + +#include + +#endif // NDK_WIDGETS_BUTTONWIDGET_HPP diff --git a/SDK/include/NDK/Widgets/ButtonWidget.inl b/SDK/include/NDK/Widgets/ButtonWidget.inl new file mode 100644 index 000000000..92d40719a --- /dev/null +++ b/SDK/include/NDK/Widgets/ButtonWidget.inl @@ -0,0 +1,13 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include + +namespace Ndk +{ + inline void ButtonWidget::UpdateText(const Nz::AbstractTextDrawer& drawer) + { + m_textSprite->Update(drawer); + } +} diff --git a/SDK/include/NDK/Widgets/LabelWidget.hpp b/SDK/include/NDK/Widgets/LabelWidget.hpp new file mode 100644 index 000000000..736cfd650 --- /dev/null +++ b/SDK/include/NDK/Widgets/LabelWidget.hpp @@ -0,0 +1,44 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_WIDGETS_LABELWIDGET_HPP +#define NDK_WIDGETS_LABELWIDGET_HPP + +#include +#include +#include +#include + +namespace Ndk +{ + class World; + + class NDK_API LabelWidget : public BaseWidget + { + public: + LabelWidget(BaseWidget* parent = nullptr); + LabelWidget(const LabelWidget&) = delete; + LabelWidget(LabelWidget&&) = default; + ~LabelWidget() = default; + + //virtual LabelWidget* Clone() const = 0; + + void ResizeToContent(); + + inline void UpdateText(const Nz::AbstractTextDrawer& drawer); + + LabelWidget& operator=(const LabelWidget&) = delete; + LabelWidget& operator=(LabelWidget&&) = default; + + private: + EntityHandle m_textEntity; + Nz::TextSpriteRef m_textSprite; + }; +} + +#include + +#endif // NDK_WIDGETS_LABELWIDGET_HPP diff --git a/SDK/include/NDK/Widgets/LabelWidget.inl b/SDK/include/NDK/Widgets/LabelWidget.inl new file mode 100644 index 000000000..4d4e100ce --- /dev/null +++ b/SDK/include/NDK/Widgets/LabelWidget.inl @@ -0,0 +1,13 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include + +namespace Ndk +{ + inline void LabelWidget::UpdateText(const Nz::AbstractTextDrawer& drawer) + { + m_textSprite->Update(drawer); + } +} diff --git a/SDK/include/NDK/Widgets/TextAreaWidget.hpp b/SDK/include/NDK/Widgets/TextAreaWidget.hpp new file mode 100644 index 000000000..8236b1689 --- /dev/null +++ b/SDK/include/NDK/Widgets/TextAreaWidget.hpp @@ -0,0 +1,81 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#pragma once + +#ifndef NDK_WIDGETS_TEXTAREAWIDGET_HPP +#define NDK_WIDGETS_TEXTAREAWIDGET_HPP + +#include +#include +#include +#include + +namespace Ndk +{ + class World; + + class NDK_API TextAreaWidget : public BaseWidget + { + public: + TextAreaWidget(BaseWidget* parent = nullptr); + TextAreaWidget(const TextAreaWidget&) = delete; + TextAreaWidget(TextAreaWidget&&) = default; + ~TextAreaWidget() = default; + + void AppendText(const Nz::String& text); + + inline void Clear(); + + //virtual TextAreaWidget* Clone() const = 0; + + inline void EnableMultiline(bool enable = true); + + inline std::size_t GetCursorPosition() const; + inline std::size_t GetLineCount() const; + inline const Nz::String& GetText() const; + + std::size_t GetHoveredGlyph(float x, float y) const; + + inline bool IsMultilineEnabled() const; + inline bool IsReadOnly() const; + + inline void MoveCursor(int offset); + + void ResizeToContent() override; + + inline void SetCursorPosition(std::size_t cursorPosition); + inline void SetReadOnly(bool readOnly = true); + void SetText(const Nz::String& text); + + void Write(const Nz::String& text); + + TextAreaWidget& operator=(const TextAreaWidget&) = delete; + TextAreaWidget& operator=(TextAreaWidget&&) = default; + + private: + void RefreshCursor(); + + void OnKeyPressed(const Nz::WindowEvent::KeyEvent& key) override; + void OnKeyReleased(const Nz::WindowEvent::KeyEvent& key) override; + void OnMouseEnter() override; + void OnMouseButtonPress(int /*x*/, int /*y*/, Nz::Mouse::Button button) override; + void OnMouseMoved(int x, int y, int deltaX, int deltaY) override; + void OnMouseExit() override; + void OnTextEntered(char32_t character, bool repeated) override; + + EntityHandle m_cursorEntity; + EntityHandle m_textEntity; + Nz::SimpleTextDrawer m_drawer; + Nz::SpriteRef m_cursorSprite; + Nz::TextSpriteRef m_textSprite; + std::size_t m_cursorPosition; + bool m_multiLineEnabled; + bool m_readOnly; + }; +} + +#include + +#endif // NDK_WIDGETS_TEXTAREAWIDGET_HPP diff --git a/SDK/include/NDK/Widgets/TextAreaWidget.inl b/SDK/include/NDK/Widgets/TextAreaWidget.inl new file mode 100644 index 000000000..d923e7223 --- /dev/null +++ b/SDK/include/NDK/Widgets/TextAreaWidget.inl @@ -0,0 +1,75 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include + +namespace Ndk +{ + inline void TextAreaWidget::Clear() + { + m_cursorPosition = 0; + m_drawer.Clear(); + m_textSprite->Update(m_drawer); + + RefreshCursor(); + } + + inline void TextAreaWidget::EnableMultiline(bool enable) + { + m_multiLineEnabled = enable; + } + + inline std::size_t TextAreaWidget::GetCursorPosition() const + { + return m_cursorPosition; + } + + inline std::size_t TextAreaWidget::GetLineCount() const + { + return m_drawer.GetLineCount(); + } + + inline const Nz::String& TextAreaWidget::GetText() const + { + return m_drawer.GetText(); + } + + inline bool Ndk::TextAreaWidget::IsMultilineEnabled() const + { + return m_multiLineEnabled; + } + + inline bool TextAreaWidget::IsReadOnly() const + { + return m_readOnly; + } + + inline void TextAreaWidget::MoveCursor(int offset) + { + if (offset >= 0) + SetCursorPosition(m_cursorPosition += static_cast(offset)); + else + { + std::size_t nOffset = static_cast(-offset); + if (nOffset >= m_cursorPosition) + SetCursorPosition(0); + else + SetCursorPosition(m_cursorPosition - nOffset); + } + } + + inline void TextAreaWidget::SetCursorPosition(std::size_t cursorPosition) + { + m_cursorPosition = std::min(cursorPosition, m_drawer.GetGlyphCount()); + + RefreshCursor(); + } + + inline void TextAreaWidget::SetReadOnly(bool readOnly) + { + m_readOnly = readOnly; + + m_cursorEntity->Enable(!m_readOnly); + } +} diff --git a/SDK/src/NDK/Application.cpp b/SDK/src/NDK/Application.cpp index f184d5b0b..4098b8a2b 100644 --- a/SDK/src/NDK/Application.cpp +++ b/SDK/src/NDK/Application.cpp @@ -152,7 +152,7 @@ namespace Ndk windowDimensions.MakeZero(); overlay->console = std::make_unique(*info.overlayWorld, Nz::Vector2f(windowDimensions), overlay->lua); - + Console& consoleRef = *overlay->console; // Redirect logs toward the console @@ -248,4 +248,4 @@ namespace Ndk #endif Application* Application::s_application = nullptr; -} \ No newline at end of file +} diff --git a/SDK/src/NDK/BaseWidget.cpp b/SDK/src/NDK/BaseWidget.cpp new file mode 100644 index 000000000..43ffbeb52 --- /dev/null +++ b/SDK/src/NDK/BaseWidget.cpp @@ -0,0 +1,132 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include +#include +#include +#include + +namespace Ndk +{ + BaseWidget::BaseWidget(BaseWidget* parent) : + BaseWidget() + { + NazaraAssert(parent, "Invalid parent"); + NazaraAssert(parent->GetCanvas(), "Parent has no canvas"); + + m_canvas = parent->GetCanvas(); + m_widgetParent = parent; + m_world = m_canvas->GetWorld(); + + m_canvasIndex = m_canvas->RegisterWidget(this); + } + + BaseWidget::~BaseWidget() + { + m_canvas->UnregisterWidget(m_canvasIndex); + } + + inline void BaseWidget::EnableBackground(bool enable) + { + if (m_backgroundEntity.IsValid() == enable) + return; + + if (enable) + { + m_backgroundSprite = Nz::Sprite::New(); + m_backgroundSprite->SetColor(m_backgroundColor); + m_backgroundSprite->SetMaterial(Nz::Material::New((m_backgroundColor.IsOpaque()) ? "Basic2D" : "Translucent2D")); + + m_backgroundEntity = m_world->CreateEntity(); + m_backgroundEntity->AddComponent().Attach(m_backgroundSprite, -1); + m_backgroundEntity->AddComponent().SetParent(this); + + BaseWidget::Layout(); // Only layout background + } + else + { + m_backgroundEntity->Kill(); + m_backgroundSprite.Reset(); + } + } + + void BaseWidget::SetSize(const Nz::Vector2f& size) + { + SetContentSize({std::max(size.x - m_padding.left - m_padding.right, 0.f), std::max(size.y - m_padding.top - m_padding.bottom, 0.f)}); + } + + EntityHandle BaseWidget::CreateEntity() + { + m_entities.emplace_back(m_world->CreateEntity()); + return m_entities.back(); + } + + void BaseWidget::DestroyEntity(Entity* entity) + { + auto it = std::find(m_entities.begin(), m_entities.end(), entity); + NazaraAssert(it != m_entities.end(), "Entity does not belong to this widget"); + + m_entities.erase(it); + } + + void BaseWidget::GrabKeyboard() + { + m_canvas->SetKeyboardOwner(this); + } + + void BaseWidget::Layout() + { + if (m_canvas) + m_canvas->NotifyWidgetUpdate(m_canvasIndex); + + if (m_backgroundEntity) + { + NodeComponent& node = m_backgroundEntity->GetComponent(); + node.SetPosition(-m_padding.left, -m_padding.top); + + m_backgroundSprite->SetSize(m_contentSize.x + m_padding.left + m_padding.right, m_contentSize.y + m_padding.top + m_padding.bottom); + } + } + + void BaseWidget::InvalidateNode() + { + Node::InvalidateNode(); + + if (m_canvas) + m_canvas->NotifyWidgetUpdate(m_canvasIndex); + } + + void BaseWidget::OnKeyPressed(const Nz::WindowEvent::KeyEvent& key) + { + } + + void BaseWidget::OnKeyReleased(const Nz::WindowEvent::KeyEvent& key) + { + } + + void BaseWidget::OnMouseEnter() + { + } + + void BaseWidget::OnMouseMoved(int x, int y, int deltaX, int deltaY) + { + } + + void BaseWidget::OnMouseButtonPress(int x, int y, Nz::Mouse::Button button) + { + } + + void BaseWidget::OnMouseButtonRelease(int x, int y, Nz::Mouse::Button button) + { + } + + void BaseWidget::OnMouseExit() + { + } + + void BaseWidget::OnTextEntered(char32_t character, bool repeated) + { + } +} diff --git a/SDK/src/NDK/Canvas.cpp b/SDK/src/NDK/Canvas.cpp new file mode 100644 index 000000000..c06d320c1 --- /dev/null +++ b/SDK/src/NDK/Canvas.cpp @@ -0,0 +1,160 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include +#include +#include +#include + +namespace Ndk +{ + void Canvas::ResizeToContent() + { + } + + void Canvas::Layout() + { + if (m_backgroundEntity) + { + NodeComponent& node = m_backgroundEntity->GetComponent(); + node.SetPosition(-m_padding.left, -m_padding.top); + + m_backgroundSprite->SetSize(m_contentSize.x + m_padding.left + m_padding.right, m_contentSize.y + m_padding.top + m_padding.bottom); + } + } + + void Canvas::NotifyWidgetUpdate(std::size_t index) + { + WidgetBox& entry = m_widgetBoxes[index]; + + Nz::Vector3f pos = entry.widget->GetPosition(); + Nz::Vector2f size = entry.widget->GetContentSize(); + + entry.box.Set(pos.x, pos.y, pos.z, size.x, size.y, 1.f); + } + + std::size_t Canvas::RegisterWidget(BaseWidget* widget) + { + WidgetBox box; + box.widget = widget; + + std::size_t index = m_widgetBoxes.size(); + m_widgetBoxes.emplace_back(box); + + NotifyWidgetUpdate(index); + return index; + } + + void Canvas::UnregisterWidget(std::size_t index) + { + if (m_widgetBoxes.size() > 1U) + { + WidgetBox& entry = m_widgetBoxes[index]; + WidgetBox& lastEntry = m_widgetBoxes.back(); + + if (m_hoveredWidget == &entry) + m_hoveredWidget = nullptr; + + if (m_keyboardOwner == entry.widget) + m_keyboardOwner = nullptr; + + entry = std::move(lastEntry); + entry.widget->UpdateCanvasIndex(index); + m_widgetBoxes.pop_back(); + } + } + + void Canvas::OnMouseButtonPressed(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseButtonEvent& event) + { + if (m_hoveredWidget) + { + int x = static_cast(std::round(event.x - m_hoveredWidget->box.x)); + int y = static_cast(std::round(event.y - m_hoveredWidget->box.y)); + + m_hoveredWidget->widget->OnMouseButtonPress(x, y, event.button); + } + } + + void Canvas::OnMouseButtonRelease(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseButtonEvent & event) + { + if (m_hoveredWidget) + { + int x = static_cast(std::round(event.x - m_hoveredWidget->box.x)); + int y = static_cast(std::round(event.y - m_hoveredWidget->box.y)); + + m_hoveredWidget->widget->OnMouseButtonRelease(x, y, event.button); + } + } + + void Canvas::OnMouseMoved(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseMoveEvent& event) + { + const WidgetBox* bestEntry = nullptr; + float bestEntryArea = std::numeric_limits::infinity(); + + for (const WidgetBox& entry : m_widgetBoxes) + { + const Nz::Boxf& box = entry.box; + + if (box.Contains(Nz::Vector3f(event.x, event.y, 0.f))) + { + float area = box.width * box.height; + if (area < bestEntryArea) + { + bestEntry = &entry; + bestEntryArea = area; + } + } + } + + if (bestEntry) + { + if (m_hoveredWidget != bestEntry) + { + if (m_hoveredWidget) + m_hoveredWidget->widget->OnMouseExit(); + + m_hoveredWidget = bestEntry; + m_hoveredWidget->widget->OnMouseEnter(); + } + + int x = static_cast(std::round(event.x - m_hoveredWidget->box.x)); + int y = static_cast(std::round(event.y - m_hoveredWidget->box.y)); + + bestEntry->widget->OnMouseMoved(x, y, event.deltaX, event.deltaY); + } + else if (m_hoveredWidget) + { + m_hoveredWidget->widget->OnMouseExit(); + m_hoveredWidget = nullptr; + } + } + + void Canvas::OnMouseLeft(const Nz::EventHandler* /*eventHandler*/) + { + if (m_hoveredWidget) + { + m_hoveredWidget->widget->OnMouseExit(); + m_hoveredWidget = nullptr; + } + } + + void Canvas::OnKeyPressed(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& event) + { + if (m_keyboardOwner) + m_keyboardOwner->OnKeyPressed(event); + } + + void Canvas::OnKeyReleased(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& event) + { + if (m_keyboardOwner) + m_keyboardOwner->OnKeyReleased(event); + } + + void Canvas::OnTextEntered(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::TextEvent& event) + { + if (m_keyboardOwner) + m_keyboardOwner->OnTextEntered(event.character, event.repeated); + } +} diff --git a/SDK/src/NDK/Components/CameraComponent.cpp b/SDK/src/NDK/Components/CameraComponent.cpp index 28f4e31d5..ae1c129c3 100644 --- a/SDK/src/NDK/Components/CameraComponent.cpp +++ b/SDK/src/NDK/Components/CameraComponent.cpp @@ -141,6 +141,7 @@ namespace Ndk { return m_zNear; } + /*! * \brief Sets the layer of the camera in case of multiples fields * diff --git a/SDK/src/NDK/Components/GraphicsComponent.cpp b/SDK/src/NDK/Components/GraphicsComponent.cpp index 954dd2de2..8a8516e16 100644 --- a/SDK/src/NDK/Components/GraphicsComponent.cpp +++ b/SDK/src/NDK/Components/GraphicsComponent.cpp @@ -15,6 +15,62 @@ namespace Ndk * \brief NDK class that represents the component for graphics */ + /*! + * \brief Adds the renderable elements to the render queue + * + * \param renderQueue Queue to be added + */ + void GraphicsComponent::AddToRenderQueue(Nz::AbstractRenderQueue* renderQueue) const + { + EnsureTransformMatrixUpdate(); + + RenderSystem& renderSystem = m_entity->GetWorld()->GetSystem(); + + for (const Renderable& object : m_renderables) + { + if (!object.dataUpdated) + { + object.data.transformMatrix = Nz::Matrix4f::ConcatenateAffine(renderSystem.GetCoordinateSystemMatrix(), Nz::Matrix4f::ConcatenateAffine(object.data.localMatrix, m_transformMatrix)); + object.renderable->UpdateData(&object.data); + object.dataUpdated = true; + } + + object.renderable->AddToRenderQueue(renderQueue, object.data); + } + } + + /*! + * \brief Attaches a renderable to the entity + * + * \param renderable Reference to a renderable element + * \param renderOrder Render order of the element + */ + void GraphicsComponent::Attach(Nz::InstancedRenderableRef renderable, int renderOrder) + { + return Attach(renderable, Nz::Matrix4f::Identity(), renderOrder); + } + + /*! + * \brief Attaches a renderable to the entity with a specific matrix + * + * \param renderable Reference to a renderable element + * \param localMatrix Local matrix that will be applied to the instanced renderable + * \param renderOrder Render order of the element + */ + void GraphicsComponent::Attach(Nz::InstancedRenderableRef renderable, const Nz::Matrix4f& localMatrix, int renderOrder) + { + m_renderables.emplace_back(m_transformMatrix); + Renderable& r = m_renderables.back(); + r.data.localMatrix = localMatrix; + r.data.renderOrder = renderOrder; + r.renderable = std::move(renderable); + r.renderableBoundingVolumeInvalidationSlot.Connect(r.renderable->OnInstancedRenderableInvalidateBoundingVolume, [this] (const Nz::InstancedRenderable*) { InvalidateBoundingVolume(); }); + r.renderableDataInvalidationSlot.Connect(r.renderable->OnInstancedRenderableInvalidateData, std::bind(&GraphicsComponent::InvalidateRenderableData, this, std::placeholders::_1, std::placeholders::_2, m_renderables.size() - 1)); + r.renderableReleaseSlot.Connect(r.renderable->OnInstancedRenderableRelease, this, &GraphicsComponent::Detach); + + InvalidateBoundingVolume(); + } + /*! * \brief Invalidates the data for renderable * @@ -33,6 +89,9 @@ namespace Ndk Renderable& r = m_renderables[index]; r.dataUpdated = false; r.renderable->InvalidateData(&r.data, flags); + + for (VolumeCullingEntry& entry : m_volumeCullingEntries) + entry.listEntry.ForceInvalidation(); } /*! @@ -102,7 +161,11 @@ namespace Ndk NazaraUnused(node); // Our view matrix depends on NodeComponent position/rotation + InvalidateBoundingVolume(); InvalidateTransformMatrix(); + + for (VolumeCullingEntry& entry : m_volumeCullingEntries) + entry.listEntry.ForceInvalidation(); //< Force invalidation on movement } /*! @@ -115,10 +178,29 @@ namespace Ndk m_boundingVolume.MakeNull(); for (const Renderable& r : m_renderables) - m_boundingVolume.ExtendTo(r.renderable->GetBoundingVolume()); + { + Nz::BoundingVolumef boundingVolume = r.renderable->GetBoundingVolume(); - m_boundingVolume.Update(m_transformMatrix); + // Adjust renderable bounding volume by local matrix + if (boundingVolume.IsFinite()) + { + Nz::Boxf localBox = boundingVolume.obb.localBox; + Nz::Vector3f newPos = r.data.localMatrix * localBox.GetPosition(); + Nz::Vector3f newLengths = r.data.localMatrix * localBox.GetLengths(); + + boundingVolume.Set(Nz::Boxf(newPos.x, newPos.y, newPos.z, newLengths.x, newLengths.y, newLengths.z)); + } + + m_boundingVolume.ExtendTo(r.renderable->GetBoundingVolume()); + } + + RenderSystem& renderSystem = m_entity->GetWorld()->GetSystem(); + + m_boundingVolume.Update(Nz::Matrix4f::ConcatenateAffine(renderSystem.GetCoordinateSystemMatrix(), m_transformMatrix)); m_boundingVolumeUpdated = true; + + for (VolumeCullingEntry& entry : m_volumeCullingEntries) + entry.listEntry.UpdateVolume(m_boundingVolume); } /*! diff --git a/SDK/src/NDK/Console.cpp b/SDK/src/NDK/Console.cpp index 122e2a125..82d3d40af 100644 --- a/SDK/src/NDK/Console.cpp +++ b/SDK/src/NDK/Console.cpp @@ -167,7 +167,6 @@ namespace Ndk * * \param event Event to be takin into consideration by the console */ - void Console::SendEvent(const Nz::WindowEvent& event) { switch (event.type) diff --git a/SDK/src/NDK/Lua/LuaBinding.cpp b/SDK/src/NDK/Lua/LuaBinding.cpp new file mode 100644 index 000000000..cb763b3b4 --- /dev/null +++ b/SDK/src/NDK/Lua/LuaBinding.cpp @@ -0,0 +1,66 @@ +// This file was automatically generated on 26 May 2014 at 01:05:31 + +#include + +namespace Ndk +{ + /*! + * \ingroup NDK + * \class Ndk::LuaBinding + * \brief NDK class that represents the binding between the engine & the SDK with the Lua scripting + */ + + /*! + * \brief Binds modules to Lua + */ + + LuaBinding::LuaBinding() + { + core = LuaBinding_Base::BindCore(*this); + math = LuaBinding_Base::BindMath(*this); + network = LuaBinding_Base::BindNetwork(*this); + utility = LuaBinding_Base::BindUtility(*this); + + #ifndef NDK_SERVER + audio = LuaBinding_Base::BindAudio(*this); + renderer = LuaBinding_Base::BindRenderer(*this); + graphics = LuaBinding_Base::BindGraphics(*this); + #endif + + sdk = LuaBinding_Base::BindSDK(*this); + } + + /*! + * \brief Registers the classes that will be used by the Lua instance + * + * \param instance Lua instance that will interact with the engine & SDK + */ + + void LuaBinding::RegisterClasses(Nz::LuaInstance& instance) + { + core->Register(instance); + math->Register(instance); + network->Register(instance); + sdk->Register(instance); + utility->Register(instance); + + #ifndef NDK_SERVER + audio->Register(instance); + graphics->Register(instance); + renderer->Register(instance); + #endif + + // ComponentType (fake enumeration to expose component indexes) + instance.PushTable(0, m_componentBinding.size()); + { + for (const ComponentBinding& entry : m_componentBinding) + { + if (entry.name.IsEmpty()) + continue; + + instance.PushField(entry.name, entry.index); + } + } + instance.SetGlobal("ComponentType"); + } +} diff --git a/SDK/src/NDK/Lua/LuaBinding_Audio.cpp b/SDK/src/NDK/Lua/LuaBinding_Audio.cpp new file mode 100644 index 000000000..619fe2850 --- /dev/null +++ b/SDK/src/NDK/Lua/LuaBinding_Audio.cpp @@ -0,0 +1,198 @@ +// This file was automatically generated on 26 May 2014 at 01:05:31 + +#include +#include +#include + +namespace Ndk +{ + std::unique_ptr LuaBinding_Base::BindAudio(LuaBinding& binding) + { + return std::make_unique(binding); + } + + LuaBinding_Audio::LuaBinding_Audio(LuaBinding& binding) : + LuaBinding_Base(binding) + { + /*********************************** Nz::SoundEmitter **********************************/ + soundEmitter.Reset("SoundEmitter"); + { + soundEmitter.BindMethod("EnableLooping", &Nz::SoundEmitter::EnableLooping); + soundEmitter.BindMethod("EnableSpatialization", &Nz::SoundEmitter::EnableSpatialization); + + soundEmitter.BindMethod("GetAttenuation", &Nz::SoundEmitter::GetAttenuation); + soundEmitter.BindMethod("GetDuration", &Nz::SoundEmitter::GetDuration); + soundEmitter.BindMethod("GetMinDistance", &Nz::SoundEmitter::GetMinDistance); + soundEmitter.BindMethod("GetPitch", &Nz::SoundEmitter::GetPitch); + soundEmitter.BindMethod("GetPlayingOffset", &Nz::SoundEmitter::GetPlayingOffset); + soundEmitter.BindMethod("GetPosition", &Nz::Sound::GetPosition); + soundEmitter.BindMethod("GetStatus", &Nz::SoundEmitter::GetStatus); + soundEmitter.BindMethod("GetVelocity", &Nz::Sound::GetVelocity); + soundEmitter.BindMethod("GetVolume", &Nz::SoundEmitter::GetVolume); + + soundEmitter.BindMethod("IsLooping", &Nz::SoundEmitter::IsLooping); + soundEmitter.BindMethod("IsSpatialized", &Nz::SoundEmitter::IsSpatialized); + + soundEmitter.BindMethod("Pause", &Nz::SoundEmitter::Pause); + soundEmitter.BindMethod("Play", &Nz::SoundEmitter::Play); + + soundEmitter.BindMethod("SetAttenuation", &Nz::SoundEmitter::SetAttenuation); + soundEmitter.BindMethod("SetMinDistance", &Nz::SoundEmitter::SetMinDistance); + soundEmitter.BindMethod("SetPitch", &Nz::SoundEmitter::SetPitch); + soundEmitter.BindMethod("SetPosition", (void(Nz::SoundEmitter::*)(const Nz::Vector3f&)) &Nz::SoundEmitter::SetPosition); + soundEmitter.BindMethod("SetVelocity", (void(Nz::SoundEmitter::*)(const Nz::Vector3f&)) &Nz::SoundEmitter::SetVelocity); + soundEmitter.BindMethod("SetVolume", &Nz::SoundEmitter::SetVolume); + + soundEmitter.BindMethod("Stop", &Nz::SoundEmitter::Stop); + } + + /*********************************** Nz::Music **********************************/ + music.Reset("Music"); + { + music.Inherit(soundEmitter); + + music.BindDefaultConstructor(); + + //musicClass.SetMethod("Create", &Nz::Music::Create); + //musicClass.SetMethod("Destroy", &Nz::Music::Destroy); + + music.BindMethod("EnableLooping", &Nz::Music::EnableLooping); + + music.BindMethod("GetDuration", &Nz::Music::GetDuration); + music.BindMethod("GetFormat", &Nz::Music::GetFormat); + music.BindMethod("GetPlayingOffset", &Nz::Music::GetPlayingOffset); + music.BindMethod("GetSampleCount", &Nz::Music::GetSampleCount); + music.BindMethod("GetSampleRate", &Nz::Music::GetSampleRate); + music.BindMethod("GetStatus", &Nz::Music::GetStatus); + + music.BindMethod("IsLooping", &Nz::Music::IsLooping); + + music.BindMethod("OpenFromFile", &Nz::Music::OpenFromFile, Nz::MusicParams()); + + music.BindMethod("Pause", &Nz::Music::Pause); + music.BindMethod("Play", &Nz::Music::Play); + + music.BindMethod("SetPlayingOffset", &Nz::Music::SetPlayingOffset); + + music.BindMethod("Stop", &Nz::Music::Stop); + + // Manual + music.BindMethod("__tostring", [] (Nz::LuaInstance& lua, Nz::Music& instance, std::size_t /*argumentCount*/) -> int + { + Nz::StringStream ss("Music("); + ss << instance.GetFilePath() << ')'; + + lua.PushString(ss); + return 1; + }); + } + + /*********************************** Nz::Sound **********************************/ + sound.Reset("Sound"); + { + sound.Inherit(soundEmitter); + + sound.BindDefaultConstructor(); + + sound.BindMethod("GetBuffer", &Nz::Sound::GetBuffer); + + sound.BindMethod("IsPlayable", &Nz::Sound::IsPlayable); + sound.BindMethod("IsPlaying", &Nz::Sound::IsPlaying); + + sound.BindMethod("LoadFromFile", &Nz::Sound::LoadFromFile, Nz::SoundBufferParams()); + + sound.BindMethod("SetPlayingOffset", &Nz::Sound::SetPlayingOffset); + + // Manual + sound.BindMethod("__tostring", [] (Nz::LuaInstance& lua, Nz::Sound& instance, std::size_t /*argumentCount*/) -> int + { + Nz::StringStream ss("Sound("); + if (const Nz::SoundBuffer* buffer = instance.GetBuffer()) + ss << buffer; + + ss << ')'; + + lua.PushString(ss); + return 1; + }); + } + + /*********************************** Nz::SoundBuffer **********************************/ + soundBuffer.Reset("SoundBuffer"); + { + soundBuffer.SetConstructor([] (Nz::LuaInstance& lua, Nz::SoundBufferRef* instance, std::size_t argumentCount) + { + NazaraUnused(lua); + NazaraUnused(argumentCount); + + Nz::PlacementNew(instance, Nz::SoundBuffer::New()); + return true; + }); + + soundBuffer.BindMethod("Destroy", &Nz::SoundBuffer::Destroy); + + soundBuffer.BindMethod("GetDuration", &Nz::SoundBuffer::GetDuration); + soundBuffer.BindMethod("GetFormat", &Nz::SoundBuffer::GetFormat); + soundBuffer.BindMethod("GetSampleCount", &Nz::SoundBuffer::GetSampleCount); + soundBuffer.BindMethod("GetSampleRate", &Nz::SoundBuffer::GetSampleRate); + + soundBuffer.BindMethod("IsValid", &Nz::SoundBuffer::IsValid); + + soundBuffer.BindMethod("LoadFromFile", &Nz::SoundBuffer::LoadFromFile, Nz::SoundBufferParams()); + + soundBuffer.BindStaticMethod("IsFormatSupported", &Nz::SoundBuffer::IsFormatSupported); + + // Manual + soundBuffer.BindMethod("Create", [] (Nz::LuaInstance& lua, Nz::SoundBufferRef& instance, std::size_t /*argumentCount*/) -> int + { + int index = 2; + Nz::AudioFormat format = lua.Check(&index); + unsigned int sampleCount = lua.Check(&index); + unsigned int sampleRate = lua.Check(&index); + + std::size_t bufferSize = 0; + const char* buffer = lua.CheckString(index, &bufferSize); + lua.ArgCheck(buffer && bufferSize >= sampleCount * sizeof(Nz::Int16), index, "Invalid buffer"); + + lua.PushBoolean(instance->Create(format, sampleCount, sampleRate, reinterpret_cast(buffer))); + return 1; + }); + + soundBuffer.BindMethod("GetSamples", [] (Nz::LuaInstance& lua, Nz::SoundBufferRef& instance, std::size_t /*argumentCount*/) -> int + { + lua.PushString(reinterpret_cast(instance->GetSamples()), instance->GetSampleCount() * sizeof(Nz::Int16)); + return 1; + }); + + soundBuffer.BindMethod("__tostring", [] (Nz::LuaInstance& lua, Nz::SoundBufferRef& instance, std::size_t /*argumentCount*/) -> int + { + Nz::StringStream ss("SoundBuffer("); + if (instance->IsValid()) + { + Nz::String filePath = instance->GetFilePath(); + if (!filePath.IsEmpty()) + ss << "File: " << filePath << ", "; + + ss << "Duration: " << instance->GetDuration() / 1000.f << "s"; + } + ss << ')'; + + lua.PushString(ss); + return 1; + }); + } + } + + /*! + * \brief Registers the classes that will be used by the Lua instance + * + * \param instance Lua instance that will interact with the Audio classes + */ + void LuaBinding_Audio::Register(Nz::LuaInstance& instance) + { + music.Register(instance); + sound.Register(instance); + soundBuffer.Register(instance); + soundEmitter.Register(instance); + } +} diff --git a/SDK/src/NDK/Lua/LuaBinding_Base.cpp b/SDK/src/NDK/Lua/LuaBinding_Base.cpp new file mode 100644 index 000000000..b9bd44c57 --- /dev/null +++ b/SDK/src/NDK/Lua/LuaBinding_Base.cpp @@ -0,0 +1,13 @@ +// This file was automatically generated on 26 May 2014 at 01:05:31 + +#include + +namespace Ndk +{ + LuaBinding_Base::LuaBinding_Base(LuaBinding& binding) : + m_binding(binding) + { + } + + LuaBinding_Base::~LuaBinding_Base() = default; +} diff --git a/SDK/src/NDK/Lua/LuaBinding_Core.cpp b/SDK/src/NDK/Lua/LuaBinding_Core.cpp new file mode 100644 index 000000000..fc53f72c3 --- /dev/null +++ b/SDK/src/NDK/Lua/LuaBinding_Core.cpp @@ -0,0 +1,354 @@ +// This file was automatically generated on 26 May 2014 at 01:05:31 + +#include +#include +#include + +namespace Ndk +{ + std::unique_ptr LuaBinding_Base::BindCore(LuaBinding& binding) + { + return std::make_unique(binding); + } + + LuaBinding_Core::LuaBinding_Core(LuaBinding& binding) : + LuaBinding_Base(binding) + { + /*********************************** Nz::Stream ***********************************/ + stream.Reset("Stream"); + { + stream.BindMethod("EnableTextMode", &Nz::Stream::EnableTextMode); + stream.BindMethod("Flush", &Nz::Stream::Flush); + stream.BindMethod("GetCursorPos", &Nz::Stream::GetCursorPos); + stream.BindMethod("GetDirectory", &Nz::Stream::GetDirectory); + stream.BindMethod("GetPath", &Nz::Stream::GetPath); + stream.BindMethod("GetOpenMode", &Nz::Stream::GetOpenMode); + stream.BindMethod("GetStreamOptions", &Nz::Stream::GetStreamOptions); + stream.BindMethod("GetSize", &Nz::Stream::GetSize); + stream.BindMethod("ReadLine", &Nz::Stream::ReadLine, 0U); + stream.BindMethod("IsReadable", &Nz::Stream::IsReadable); + stream.BindMethod("IsSequential", &Nz::Stream::IsSequential); + stream.BindMethod("IsTextModeEnabled", &Nz::Stream::IsTextModeEnabled); + stream.BindMethod("IsWritable", &Nz::Stream::IsWritable); + stream.BindMethod("SetCursorPos", &Nz::Stream::SetCursorPos); + + stream.BindMethod("Read", [] (Nz::LuaInstance& lua, Nz::Stream& instance, std::size_t /*argumentCount*/) -> int { + int argIndex = 2; + + std::size_t length = lua.Check(&argIndex); + + std::unique_ptr buffer(new char[length]); + std::size_t readLength = instance.Read(buffer.get(), length); + + lua.PushString(Nz::String(buffer.get(), readLength)); + return 1; + }); + + stream.BindMethod("Write", [] (Nz::LuaInstance& lua, Nz::Stream& instance, std::size_t /*argumentCount*/) -> int { + int argIndex = 2; + + std::size_t bufferSize = 0; + const char* buffer = lua.CheckString(argIndex, &bufferSize); + + if (instance.IsTextModeEnabled()) + lua.Push(instance.Write(Nz::String(buffer, bufferSize))); + else + lua.Push(instance.Write(buffer, bufferSize)); + return 1; + }); + } + + /*********************************** Nz::Clock **********************************/ + clock.Reset("Clock"); + { + clock.SetConstructor([] (Nz::LuaInstance& lua, Nz::Clock* instance, std::size_t argumentCount) + { + std::size_t argCount = std::min(argumentCount, 2U); + + int argIndex = 2; + switch (argCount) + { + case 0: + Nz::PlacementNew(instance); + return true; + + case 1: + { + Nz::Int64 startingValue = lua.Check(&argIndex, 0); + + Nz::PlacementNew(instance, startingValue); + return true; + } + + case 2: + { + Nz::Int64 startingValue = lua.Check(&argIndex, 0); + bool paused = lua.Check(&argIndex, false); + + Nz::PlacementNew(instance, startingValue, paused); + return true; + } + } + + lua.Error("No matching overload for Clock constructor"); + return false; + }); + + clock.BindMethod("GetMicroseconds", &Nz::Clock::GetMicroseconds); + clock.BindMethod("GetMilliseconds", &Nz::Clock::GetMilliseconds); + clock.BindMethod("GetSeconds", &Nz::Clock::GetSeconds); + clock.BindMethod("IsPaused", &Nz::Clock::IsPaused); + clock.BindMethod("Pause", &Nz::Clock::Pause); + clock.BindMethod("Restart", &Nz::Clock::Restart); + clock.BindMethod("Unpause", &Nz::Clock::Unpause); + + // Manual + clock.BindMethod("__tostring", [] (Nz::LuaInstance& lua, Nz::Clock& instance, std::size_t /*argumentCount*/) -> int { + Nz::StringStream ss("Clock(Elapsed: "); + ss << instance.GetSeconds(); + ss << "s, Paused: "; + ss << instance.IsPaused(); + ss << ')'; + + lua.PushString(ss); + return 1; + }); + } + + /********************************* Nz::Directory ********************************/ + directory.Reset("Directory"); + { + directory.SetConstructor([] (Nz::LuaInstance& lua, Nz::Directory* instance, std::size_t argumentCount) + { + std::size_t argCount = std::min(argumentCount, 1U); + + int argIndex = 2; + switch (argCount) + { + case 0: + Nz::PlacementNew(instance); + return true; + + case 1: + Nz::PlacementNew(instance, lua.Check(&argIndex)); + return true; + } + + return false; + }); + + directory.BindMethod("Close", &Nz::Directory::Close); + directory.BindMethod("Exists", &Nz::Directory::Exists); + directory.BindMethod("GetPath", &Nz::Directory::GetPath); + directory.BindMethod("GetPattern", &Nz::Directory::GetPattern); + directory.BindMethod("GetResultName", &Nz::Directory::GetResultName); + directory.BindMethod("GetResultPath", &Nz::Directory::GetResultPath); + directory.BindMethod("GetResultSize", &Nz::Directory::GetResultSize); + directory.BindMethod("IsOpen", &Nz::Directory::IsOpen); + directory.BindMethod("IsResultDirectory", &Nz::Directory::IsResultDirectory); + directory.BindMethod("NextResult", &Nz::Directory::NextResult, true); + directory.BindMethod("Open", &Nz::Directory::Open); + directory.BindMethod("SetPath", &Nz::Directory::SetPath); + directory.BindMethod("SetPattern", &Nz::Directory::SetPattern); + + directory.BindStaticMethod("Copy", Nz::Directory::Copy); + directory.BindStaticMethod("Create", Nz::Directory::Create); + directory.BindStaticMethod("Exists", Nz::Directory::Exists); + directory.BindStaticMethod("GetCurrent", Nz::Directory::GetCurrent); + directory.BindStaticMethod("Remove", Nz::Directory::Remove); + directory.BindStaticMethod("SetCurrent", Nz::Directory::SetCurrent); + + // Manual + directory.BindMethod("__tostring", [] (Nz::LuaInstance& lua, Nz::Directory& instance, std::size_t /*argumentCount*/) -> int { + Nz::StringStream ss("Directory("); + ss << instance.GetPath(); + ss << ')'; + + lua.PushString(ss); + return 1; + }); + } + + /*********************************** Nz::File ***********************************/ + file.Reset("File"); + { + file.Inherit(stream); + + file.SetConstructor([] (Nz::LuaInstance& lua, Nz::File* instance, std::size_t argumentCount) + { + std::size_t argCount = std::min(argumentCount, 1U); + + int argIndex = 2; + switch (argCount) + { + case 0: + Nz::PlacementNew(instance); + return true; + + case 1: + { + Nz::String filePath = lua.Check(&argIndex); + + Nz::PlacementNew(instance, filePath); + return true; + } + + case 2: + { + Nz::String filePath = lua.Check(&argIndex); + Nz::UInt32 openMode = lua.Check(&argIndex); + + Nz::PlacementNew(instance, filePath, openMode); + return true; + } + } + + lua.Error("No matching overload for File constructor"); + return false; + }); + + file.BindMethod("Close", &Nz::File::Close); + file.BindMethod("Copy", &Nz::File::Copy); + file.BindMethod("Delete", &Nz::File::Delete); + file.BindMethod("EndOfFile", &Nz::File::EndOfFile); + file.BindMethod("Exists", &Nz::File::Exists); + file.BindMethod("GetCreationTime", &Nz::File::GetCreationTime); + file.BindMethod("GetFileName", &Nz::File::GetFileName); + file.BindMethod("GetLastAccessTime", &Nz::File::GetLastAccessTime); + file.BindMethod("GetLastWriteTime", &Nz::File::GetLastWriteTime); + file.BindMethod("IsOpen", &Nz::File::IsOpen); + file.BindMethod("Rename", &Nz::File::GetLastWriteTime); + file.BindMethod("GetLastWriteTime", &Nz::File::GetLastWriteTime); + file.BindMethod("SetFile", &Nz::File::GetLastWriteTime); + + file.BindStaticMethod("AbsolutePath", &Nz::File::AbsolutePath); + file.BindStaticMethod("ComputeHash", (Nz::ByteArray(*)(Nz::HashType, const Nz::String&)) &Nz::File::ComputeHash); + file.BindStaticMethod("Copy", &Nz::File::Copy); + file.BindStaticMethod("Delete", &Nz::File::Delete); + file.BindStaticMethod("Exists", &Nz::File::Exists); + //fileClass.SetStaticMethod("GetCreationTime", &Nz::File::GetCreationTime); + file.BindStaticMethod("GetDirectory", &Nz::File::GetDirectory); + //fileClass.SetStaticMethod("GetLastAccessTime", &Nz::File::GetLastAccessTime); + //fileClass.SetStaticMethod("GetLastWriteTime", &Nz::File::GetLastWriteTime); + file.BindStaticMethod("GetSize", &Nz::File::GetSize); + file.BindStaticMethod("IsAbsolute", &Nz::File::IsAbsolute); + file.BindStaticMethod("NormalizePath", &Nz::File::NormalizePath); + file.BindStaticMethod("NormalizeSeparators", &Nz::File::NormalizeSeparators); + file.BindStaticMethod("Rename", &Nz::File::Rename); + + // Manual + file.BindMethod("Open", [] (Nz::LuaInstance& lua, Nz::File& instance, std::size_t argumentCount) -> int + { + std::size_t argCount = std::min(argumentCount, 2U); + + int argIndex = 2; + switch (argCount) + { + case 0: + case 1: + return lua.Push(instance.Open(lua.Check(&argIndex, Nz::OpenMode_NotOpen))); + + case 2: + { + Nz::String filePath = lua.Check(&argIndex); + Nz::UInt32 openMode = lua.Check(&argIndex, Nz::OpenMode_NotOpen); + return lua.Push(instance.Open(filePath, openMode)); + } + } + + lua.Error("No matching overload for method Open"); + return 0; + }); + + file.BindMethod("SetCursorPos", [] (Nz::LuaInstance& lua, Nz::File& instance, std::size_t argumentCount) -> int + { + std::size_t argCount = std::min(argumentCount, 2U); + + int argIndex = 2; + switch (argCount) + { + case 1: + return lua.Push(instance.SetCursorPos(lua.Check(&argIndex))); + + case 2: + { + Nz::CursorPosition curPos = lua.Check(&argIndex); + Nz::Int64 offset = lua.Check(&argIndex); + return lua.Push(instance.SetCursorPos(curPos, offset)); + } + } + + lua.Error("No matching overload for method SetCursorPos"); + return 0; + }); + + file.BindMethod("__tostring", [] (Nz::LuaInstance& lua, Nz::File& instance, std::size_t /*argumentCount*/) -> int { + Nz::StringStream ss("File("); + if (instance.IsOpen()) + ss << "Path: " << instance.GetPath(); + + ss << ')'; + + lua.PushString(ss); + return 1; + }); + } + } + + /*! + * \brief Registers the classes that will be used by the Lua instance + * + * \param instance Lua instance that will interact with the Core classes + */ + void LuaBinding_Core::Register(Nz::LuaInstance& instance) + { + // Classes + clock.Register(instance); + directory.Register(instance); + file.Register(instance); + stream.Register(instance); + + // Enums + + // Nz::CursorPosition + static_assert(Nz::CursorPosition_Max + 1 == 3, "Nz::CursorPosition has been updated but change was not reflected to Lua binding"); + instance.PushTable(0, 3); + { + instance.PushField("AtBegin", Nz::CursorPosition_AtBegin); + instance.PushField("AtCurrent", Nz::CursorPosition_AtCurrent); + instance.PushField("AtEnd", Nz::CursorPosition_AtEnd); + } + instance.SetGlobal("CursorPosition"); + + // Nz::HashType + static_assert(Nz::HashType_Max + 1 == 9, "Nz::HashType has been updated but change was not reflected to Lua binding"); + instance.PushTable(0, 9); + { + instance.PushField("CRC32", Nz::HashType_CRC32); + instance.PushField("Fletcher16", Nz::HashType_Fletcher16); + instance.PushField("MD5", Nz::HashType_MD5); + instance.PushField("SHA1", Nz::HashType_SHA1); + instance.PushField("SHA224", Nz::HashType_SHA224); + instance.PushField("SHA256", Nz::HashType_SHA256); + instance.PushField("SHA384", Nz::HashType_SHA384); + instance.PushField("SHA512", Nz::HashType_SHA512); + instance.PushField("Whirlpool", Nz::HashType_Whirlpool); + } + instance.SetGlobal("HashType"); + + // Nz::OpenMode + static_assert(Nz::OpenMode_Max + 1 == 8, "Nz::OpenModeFlags has been updated but change was not reflected to Lua binding"); + instance.PushTable(0, Nz::OpenMode_Max + 1); + { + instance.PushField("Append", Nz::OpenMode_Append); + instance.PushField("NotOpen", Nz::OpenMode_NotOpen); + instance.PushField("Lock", Nz::OpenMode_Lock); + instance.PushField("ReadOnly", Nz::OpenMode_ReadOnly); + instance.PushField("ReadWrite", Nz::OpenMode_ReadWrite); + instance.PushField("Text", Nz::OpenMode_Text); + instance.PushField("Truncate", Nz::OpenMode_Truncate); + instance.PushField("WriteOnly", Nz::OpenMode_WriteOnly); + } + instance.SetGlobal("OpenMode"); + } +} diff --git a/SDK/src/NDK/Lua/LuaBinding_Graphics.cpp b/SDK/src/NDK/Lua/LuaBinding_Graphics.cpp new file mode 100644 index 000000000..f87ac6556 --- /dev/null +++ b/SDK/src/NDK/Lua/LuaBinding_Graphics.cpp @@ -0,0 +1,370 @@ +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include + +namespace Ndk +{ + std::unique_ptr LuaBinding_Base::BindGraphics(LuaBinding& binding) + { + return std::make_unique(binding); + } + + LuaBinding_Graphics::LuaBinding_Graphics(LuaBinding& binding) : + LuaBinding_Base(binding) + { + /*********************************** Nz::AbstractViewer ***********************************/ + abstractViewer.Reset("AbstractViewer"); + { + abstractViewer.BindMethod("GetAspectRatio", &Nz::AbstractViewer::GetAspectRatio); + abstractViewer.BindMethod("GetEyePosition", &Nz::AbstractViewer::GetEyePosition); + abstractViewer.BindMethod("GetForward", &Nz::AbstractViewer::GetForward); + //abstractViewer.BindMethod("GetFrustum", &Nz::AbstractViewer::GetFrustum); + abstractViewer.BindMethod("GetProjectionMatrix", &Nz::AbstractViewer::GetProjectionMatrix); + //abstractViewer.BindMethod("GetTarget", &Nz::AbstractViewer::GetTarget); + abstractViewer.BindMethod("GetViewMatrix", &Nz::AbstractViewer::GetViewMatrix); + abstractViewer.BindMethod("GetViewport", &Nz::AbstractViewer::GetViewport); + abstractViewer.BindMethod("GetZFar", &Nz::AbstractViewer::GetZFar); + abstractViewer.BindMethod("GetZNear", &Nz::AbstractViewer::GetZNear); + } + + /*********************************** Nz::InstancedRenderable ***********************************/ + instancedRenderable.Reset("InstancedRenderable"); + { + } + + /*********************************** Nz::Material ***********************************/ + material.Reset("Material"); + { + material.SetConstructor([] (Nz::LuaInstance& lua, Nz::MaterialRef* instance, std::size_t argumentCount) + { + switch (argumentCount) + { + case 0: + Nz::PlacementNew(instance, Nz::Material::New()); + return true; + + case 1: + { + int argIndex = 1; + if (lua.IsOfType(argIndex, "MaterialPipeline")) + { + Nz::PlacementNew(instance, Nz::Material::New(*static_cast(lua.ToUserdata(argIndex)))); + return true; + } + else if (lua.IsOfType(argIndex, "Material")) + { + Nz::PlacementNew(instance, Nz::Material::New(**static_cast(lua.ToUserdata(argIndex)))); + return true; + } + else + { + Nz::PlacementNew(instance, Nz::Material::New(lua.Check(&argIndex))); + return true; + } + } + } + + lua.Error("No matching overload for constructor"); + return false; + }); + + material.BindMethod("Configure", [] (Nz::LuaInstance& lua, Nz::MaterialRef& instance, std::size_t /*argumentCount*/) -> int + { + int argIndex = 2; + if (lua.IsOfType(argIndex, "MaterialPipeline")) + { + instance->Configure(*static_cast(lua.ToUserdata(argIndex))); + return 0; + } + else + { + lua.Push(instance->Configure(lua.Check(&argIndex))); + return 1; + } + }); + + material.BindMethod("EnableAlphaTest", &Nz::Material::EnableAlphaTest); + material.BindMethod("EnableBlending", &Nz::Material::EnableBlending); + material.BindMethod("EnableColorWrite", &Nz::Material::EnableColorWrite); + material.BindMethod("EnableDepthBuffer", &Nz::Material::EnableDepthBuffer); + material.BindMethod("EnableDepthSorting", &Nz::Material::EnableDepthSorting); + material.BindMethod("EnableDepthWrite", &Nz::Material::EnableDepthWrite); + material.BindMethod("EnableFaceCulling", &Nz::Material::EnableFaceCulling); + material.BindMethod("EnableScissorTest", &Nz::Material::EnableScissorTest); + material.BindMethod("EnableShadowCasting", &Nz::Material::EnableShadowCasting); + material.BindMethod("EnableShadowReceive", &Nz::Material::EnableShadowReceive); + material.BindMethod("EnableStencilTest", &Nz::Material::EnableStencilTest); + + material.BindMethod("EnsurePipelineUpdate", &Nz::Material::EnsurePipelineUpdate); + + material.BindMethod("GetAlphaMap", &Nz::Material::GetAlphaMap); + material.BindMethod("GetAlphaThreshold", &Nz::Material::GetAlphaThreshold); + material.BindMethod("GetAmbientColor", &Nz::Material::GetAmbientColor); + material.BindMethod("GetDepthFunc", &Nz::Material::GetDepthFunc); + material.BindMethod("GetDepthMaterial", &Nz::Material::GetDepthMaterial); + material.BindMethod("GetDiffuseColor", &Nz::Material::GetDiffuseColor); + material.BindMethod("GetDiffuseMap", &Nz::Material::GetDiffuseMap); + //material.BindMethod("GetDiffuseSampler", &Nz::Material::GetDiffuseSampler); + material.BindMethod("GetDstBlend", &Nz::Material::GetDstBlend); + material.BindMethod("GetEmissiveMap", &Nz::Material::GetEmissiveMap); + material.BindMethod("GetFaceCulling", &Nz::Material::GetFaceCulling); + material.BindMethod("GetFaceFilling", &Nz::Material::GetFaceFilling); + material.BindMethod("GetHeightMap", &Nz::Material::GetHeightMap); + material.BindMethod("GetLineWidth", &Nz::Material::GetLineWidth); + material.BindMethod("GetNormalMap", &Nz::Material::GetNormalMap); + //material.BindMethod("GetPipeline", &Nz::Material::GetPipeline); + //material.BindMethod("GetPipelineInfo", &Nz::Material::GetPipelineInfo); + material.BindMethod("GetPointSize", &Nz::Material::GetPointSize); + //material.BindMethod("GetShader", &Nz::Material::GetShader); + material.BindMethod("GetShininess", &Nz::Material::GetShininess); + material.BindMethod("GetSpecularColor", &Nz::Material::GetSpecularColor); + material.BindMethod("GetSpecularMap", &Nz::Material::GetSpecularMap); + //material.BindMethod("GetSpecularSampler", &Nz::Material::GetSpecularSampler); + material.BindMethod("GetSrcBlend", &Nz::Material::GetSrcBlend); + + material.BindMethod("HasAlphaMap", &Nz::Material::HasAlphaMap); + material.BindMethod("HasDepthMaterial", &Nz::Material::HasDepthMaterial); + material.BindMethod("HasDiffuseMap", &Nz::Material::HasDiffuseMap); + material.BindMethod("HasEmissiveMap", &Nz::Material::HasEmissiveMap); + material.BindMethod("HasHeightMap", &Nz::Material::HasHeightMap); + material.BindMethod("HasNormalMap", &Nz::Material::HasNormalMap); + material.BindMethod("HasSpecularMap", &Nz::Material::HasSpecularMap); + + material.BindMethod("IsAlphaTestEnabled", &Nz::Material::IsAlphaTestEnabled); + material.BindMethod("IsBlendingEnabled", &Nz::Material::IsBlendingEnabled); + material.BindMethod("IsColorWriteEnabled", &Nz::Material::IsColorWriteEnabled); + material.BindMethod("IsDepthBufferEnabled", &Nz::Material::IsDepthBufferEnabled); + material.BindMethod("IsDepthSortingEnabled", &Nz::Material::IsDepthSortingEnabled); + material.BindMethod("IsDepthWriteEnabled", &Nz::Material::IsDepthWriteEnabled); + material.BindMethod("IsFaceCullingEnabled", &Nz::Material::IsFaceCullingEnabled); + material.BindMethod("IsScissorTestEnabled", &Nz::Material::IsScissorTestEnabled); + material.BindMethod("IsStencilTestEnabled", &Nz::Material::IsStencilTestEnabled); + material.BindMethod("IsShadowCastingEnabled", &Nz::Material::IsShadowCastingEnabled); + material.BindMethod("IsShadowReceiveEnabled", &Nz::Material::IsShadowReceiveEnabled); + + material.BindMethod("LoadFromFile", &Nz::Material::LoadFromFile, Nz::MaterialParams()); + + material.BindMethod("Reset", &Nz::Material::Reset); + + material.BindMethod("SetAlphaThreshold", &Nz::Material::SetAlphaThreshold); + material.BindMethod("SetAmbientColor", &Nz::Material::SetAmbientColor); + material.BindMethod("SetDepthFunc", &Nz::Material::SetDepthFunc); + material.BindMethod("SetDepthFunc", &Nz::Material::SetDepthFunc); + material.BindMethod("SetDepthMaterial", &Nz::Material::SetDepthMaterial); + material.BindMethod("SetDiffuseColor", &Nz::Material::SetDiffuseColor); + //material.BindMethod("SetDiffuseSampler", &Nz::Material::SetDiffuseSampler); + material.BindMethod("SetDstBlend", &Nz::Material::SetDstBlend); + material.BindMethod("SetFaceCulling", &Nz::Material::SetFaceCulling); + material.BindMethod("SetFaceFilling", &Nz::Material::SetFaceFilling); + material.BindMethod("SetLineWidth", &Nz::Material::SetLineWidth); + material.BindMethod("SetPointSize", &Nz::Material::SetPointSize); + material.BindMethod("SetShininess", &Nz::Material::SetShininess); + material.BindMethod("SetSpecularColor", &Nz::Material::SetSpecularColor); + material.BindMethod("SetSpecularColor", &Nz::Material::SetSpecularColor); + //material.BindMethod("SetSpecularSampler", &Nz::Material::SetSpecularSampler); + material.BindMethod("SetSrcBlend", &Nz::Material::SetSrcBlend); + + material.BindStaticMethod("GetDefault", &Nz::Material::GetDefault); + + material.BindMethod("SetAlphaMap", [] (Nz::LuaInstance& lua, Nz::MaterialRef& instance, std::size_t /*argumentCount*/) -> int + { + int argIndex = 2; + if (lua.IsOfType(argIndex, "Texture")) + { + instance->SetAlphaMap(*static_cast(lua.ToUserdata(argIndex))); + return 0; + } + else + return lua.Push(instance->SetAlphaMap(lua.Check(&argIndex))); + }); + + material.BindMethod("SetDiffuseMap", [] (Nz::LuaInstance& lua, Nz::MaterialRef& instance, std::size_t /*argumentCount*/) -> int + { + int argIndex = 2; + if (lua.IsOfType(argIndex, "Texture")) + { + instance->SetDiffuseMap(*static_cast(lua.ToUserdata(argIndex))); + return 0; + } + else + return lua.Push(instance->SetDiffuseMap(lua.Check(&argIndex))); + }); + + material.BindMethod("SetEmissiveMap", [] (Nz::LuaInstance& lua, Nz::MaterialRef& instance, std::size_t /*argumentCount*/) -> int + { + int argIndex = 2; + if (lua.IsOfType(argIndex, "Texture")) + { + instance->SetEmissiveMap(*static_cast(lua.ToUserdata(argIndex))); + return 0; + } + else + return lua.Push(instance->SetEmissiveMap(lua.Check(&argIndex))); + }); + + material.BindMethod("SetHeightMap", [] (Nz::LuaInstance& lua, Nz::MaterialRef& instance, std::size_t /*argumentCount*/) -> int + { + int argIndex = 2; + if (lua.IsOfType(argIndex, "Texture")) + { + instance->SetHeightMap(*static_cast(lua.ToUserdata(argIndex))); + return 0; + } + else + return lua.Push(instance->SetHeightMap(lua.Check(&argIndex))); + }); + + material.BindMethod("SetNormalMap", [] (Nz::LuaInstance& lua, Nz::MaterialRef& instance, std::size_t /*argumentCount*/) -> int + { + int argIndex = 2; + if (lua.IsOfType(argIndex, "Texture")) + { + instance->SetNormalMap(*static_cast(lua.ToUserdata(argIndex))); + return 0; + } + else + return lua.Push(instance->SetNormalMap(lua.Check(&argIndex))); + }); + + material.BindMethod("SetShader", [] (Nz::LuaInstance& lua, Nz::MaterialRef& instance, std::size_t /*argumentCount*/) -> int + { + int argIndex = 2; + if (lua.IsOfType(argIndex, "UberShader")) + { + instance->SetShader(*static_cast(lua.ToUserdata(argIndex))); + return 0; + } + else + return lua.Push(instance->SetShader(lua.Check(&argIndex))); + }); + + material.BindMethod("SetSpecularMap", [] (Nz::LuaInstance& lua, Nz::MaterialRef& instance, std::size_t /*argumentCount*/) -> int + { + int argIndex = 2; + if (lua.IsOfType(argIndex, "Texture")) + { + instance->SetSpecularMap(*static_cast(lua.ToUserdata(argIndex))); + return 0; + } + else + return lua.Push(instance->SetSpecularMap(lua.Check(&argIndex))); + }); + } + + /*********************************** Nz::Model ***********************************/ + model.Reset("Model"); + { + model.Inherit(instancedRenderable, [] (Nz::ModelRef* modelRef) -> Nz::InstancedRenderableRef* + { + return reinterpret_cast(modelRef); //TODO: Make a ObjectRefCast + }); + + model.SetConstructor([] (Nz::LuaInstance& /*lua*/, Nz::ModelRef* instance, std::size_t /*argumentCount*/) + { + Nz::PlacementNew(instance, Nz::Model::New()); + return true; + }); + + //model.BindMethod("GetMaterial", &Nz::Model::GetMaterial); + model.BindMethod("GetMaterialCount", &Nz::Model::GetMaterialCount); + //modelClass.SetMethod("GetMesh", &Nz::Model::GetMesh); + model.BindMethod("GetSkin", &Nz::Model::GetSkin); + model.BindMethod("GetSkinCount", &Nz::Model::GetSkinCount); + + model.BindMethod("IsAnimated", &Nz::Model::IsAnimated); + model.BindMethod("LoadFromFile", &Nz::Model::LoadFromFile, Nz::ModelParameters()); + + model.BindMethod("Reset", &Nz::Model::Reset); + + //model.BindMethod("SetMaterial", &Nz::Model::SetMaterial); + //modelClass.SetMethod("SetMesh", &Nz::Model::SetMesh); + //modelClass.SetMethod("SetSequence", &Nz::Model::SetSequence); + model.BindMethod("SetSkin", &Nz::Model::SetSkin); + model.BindMethod("SetSkinCount", &Nz::Model::SetSkinCount); + } + + /*********************************** Nz::Sprite ***********************************/ + sprite.Reset("Sprite"); + { + sprite.Inherit(instancedRenderable, [] (Nz::SpriteRef* spriteRef) -> Nz::InstancedRenderableRef* + { + return reinterpret_cast(spriteRef); //TODO: Make a ObjectRefCast + }); + + sprite.SetConstructor([] (Nz::LuaInstance& /*lua*/, Nz::SpriteRef* instance, std::size_t /*argumentCount*/) + { + Nz::PlacementNew(instance, Nz::Sprite::New()); + return true; + }); + + sprite.BindMethod("GetColor", &Nz::Sprite::GetColor); + sprite.BindMethod("GetCornerColor", &Nz::Sprite::GetCornerColor); + sprite.BindMethod("GetMaterial", &Nz::Sprite::GetMaterial); + sprite.BindMethod("GetOrigin", &Nz::Sprite::GetOrigin); + sprite.BindMethod("GetSize", &Nz::Sprite::GetSize); + sprite.BindMethod("GetTextureCoords", &Nz::Sprite::GetTextureCoords); + + sprite.BindMethod("SetColor", &Nz::Sprite::SetColor); + sprite.BindMethod("SetCornerColor", &Nz::Sprite::SetCornerColor); + sprite.BindMethod("SetDefaultMaterial", &Nz::Sprite::SetDefaultMaterial); + sprite.BindMethod("SetOrigin", &Nz::Sprite::SetOrigin); + sprite.BindMethod("SetSize", (void(Nz::Sprite::*)(const Nz::Vector2f&)) &Nz::Sprite::SetSize); + sprite.BindMethod("SetTextureCoords", &Nz::Sprite::SetTextureCoords); + sprite.BindMethod("SetTextureRect", &Nz::Sprite::SetTextureRect); + + sprite.BindMethod("SetMaterial", [] (Nz::LuaInstance& lua, Nz::SpriteRef& instance, std::size_t /*argumentCount*/) -> int + { + int argIndex = 2; + bool resizeSprite = lua.CheckBoolean(argIndex + 1, true); + + if (lua.IsOfType(argIndex, "Material")) + instance->SetMaterial(*static_cast(lua.ToUserdata(argIndex)), resizeSprite); + else + instance->SetMaterial(lua.Check(&argIndex), resizeSprite); + + return 0; + }); + + sprite.BindMethod("SetTexture", [] (Nz::LuaInstance& lua, Nz::SpriteRef& instance, std::size_t /*argumentCount*/) -> int + { + int argIndex = 2; + bool resizeSprite = lua.CheckBoolean(argIndex + 1, true); + + if (lua.IsOfType(argIndex, "Texture")) + instance->SetTexture(*static_cast(lua.ToUserdata(argIndex)), resizeSprite); + else + instance->SetTexture(lua.Check(&argIndex), resizeSprite); + + return 0; + }); + } + + /*********************************** Nz::SpriteLibrary ***********************************/ + spriteLibrary.Reset("SpriteLibrary"); + { + spriteLibrary.BindStaticMethod("Get", &Nz::SpriteLibrary::Get); + spriteLibrary.BindStaticMethod("Has", &Nz::SpriteLibrary::Has); + spriteLibrary.BindStaticMethod("Register", &Nz::SpriteLibrary::Register); + spriteLibrary.BindStaticMethod("Query", &Nz::SpriteLibrary::Query); + spriteLibrary.BindStaticMethod("Unregister", &Nz::SpriteLibrary::Unregister); + } + } + + /*! + * \brief Registers the classes that will be used by the Lua instance + * + * \param instance Lua instance that will interact with the Graphics classes + */ + + void LuaBinding_Graphics::Register(Nz::LuaInstance& instance) + { + abstractViewer.Register(instance); + instancedRenderable.Register(instance); + material.Register(instance); + model.Register(instance); + sprite.Register(instance); + spriteLibrary.Register(instance); + } +} diff --git a/SDK/src/NDK/Lua/LuaBinding_Math.cpp b/SDK/src/NDK/Lua/LuaBinding_Math.cpp new file mode 100644 index 000000000..6d30bb137 --- /dev/null +++ b/SDK/src/NDK/Lua/LuaBinding_Math.cpp @@ -0,0 +1,986 @@ +// This file was automatically generated on 26 May 2014 at 01:05:31 + +#include +#include +#include +#include + +namespace Ndk +{ + std::unique_ptr LuaBinding_Base::BindMath(LuaBinding& binding) + { + return std::make_unique(binding); + } + + LuaBinding_Math::LuaBinding_Math(LuaBinding& binding) : + LuaBinding_Base(binding) + { + /*********************************** Nz::EulerAngles **********************************/ + eulerAngles.Reset("EulerAngles"); + { + eulerAngles.SetConstructor([] (Nz::LuaInstance& lua, Nz::EulerAnglesd* instance, std::size_t argumentCount) + { + std::size_t argCount = std::min(argumentCount, 1U); + + switch (argCount) + { + case 0: + Nz::PlacementNew(instance, Nz::EulerAnglesd::Zero()); + return true; + + case 1: + Nz::PlacementNew(instance, *static_cast(lua.CheckUserdata(1, "EulerAngles"))); + return true; + + case 3: + Nz::PlacementNew(instance, lua.CheckNumber(1), lua.CheckNumber(2), lua.CheckNumber(3)); + return true; + } + + lua.Error("No matching overload for EulerAngles constructor"); + return false; + }); + + eulerAngles.BindMethod("Normalize", &Nz::EulerAnglesd::Normalize); + eulerAngles.BindMethod("ToQuaternion", &Nz::EulerAnglesd::ToQuaternion); + + eulerAngles.BindMethod("__tostring", &Nz::EulerAnglesd::ToString); + + eulerAngles.SetGetter([] (Nz::LuaInstance& lua, Nz::EulerAnglesd& instance) + { + std::size_t length; + const char* ypr = lua.CheckString(2, &length); + + switch (length) + { + case 1: + { + switch (ypr[0]) + { + case 'p': + lua.Push(instance.pitch); + return true; + + case 'y': + lua.Push(instance.yaw); + return true; + + case 'r': + lua.Push(instance.roll); + return true; + } + break; + } + + case 3: + { + if (std::memcmp(ypr, "yaw", 3) != 0) + break; + + lua.Push(instance.yaw); + return true; + } + + case 4: + { + if (std::memcmp(ypr, "roll", 4) != 0) + break; + + lua.Push(instance.roll); + return true; + } + + case 5: + { + if (std::memcmp(ypr, "pitch", 5) != 0) + break; + + lua.Push(instance.pitch); + return true; + } + } + + return false; + }); + + eulerAngles.SetSetter([] (Nz::LuaInstance& lua, Nz::EulerAnglesd& instance) + { + std::size_t length; + const char* ypr = lua.CheckString(2, &length); + double value = lua.CheckNumber(3); + + switch (length) + { + case 1: + { + switch (ypr[0]) + { + case 'p': + instance.pitch = value; + return true; + + case 'y': + instance.yaw = value; + return true; + + case 'r': + instance.roll = value; + return true; + } + break; + } + + case 3: + { + if (std::memcmp(ypr, "yaw", 3) != 0) + break; + + instance.yaw = value; + return true; + } + + case 4: + { + if (std::memcmp(ypr, "roll", 4) != 0) + break; + + instance.roll = value; + return true; + } + + case 5: + { + if (std::memcmp(ypr, "pitch", 5) != 0) + break; + + instance.pitch = value; + return true; + } + } + + return false; + }); + } + + /*********************************** Nz::Matrix4 **********************************/ + matrix4d.Reset("Matrix4"); + { + matrix4d.SetConstructor([] (Nz::LuaInstance& lua, Nz::Matrix4d* matrix, std::size_t argumentCount) + { + std::size_t argCount = std::min(argumentCount, 3U); + + switch (argCount) + { + case 0: + Nz::PlacementNew(matrix, Nz::Matrix4d::Zero()); + return true; + + case 1: + if (lua.IsOfType(1, "Matrix4")) + Nz::PlacementNew(matrix, *static_cast(lua.ToUserdata(1))); + break; + + case 16: + { + double values[16]; + for (int i = 0; i < 16; ++i) + values[i] = lua.CheckNumber(i); + + Nz::PlacementNew(matrix, values); + + return true; + } + } + + lua.Error("No matching overload for constructor"); + return false; + }); + + matrix4d.BindMethod("ApplyRotation", &Nz::Matrix4d::ApplyRotation); + matrix4d.BindMethod("ApplyScale", &Nz::Matrix4d::ApplyScale); + matrix4d.BindMethod("ApplyTranslation", &Nz::Matrix4d::ApplyTranslation); + + matrix4d.BindMethod("Concatenate", &Nz::Matrix4d::Concatenate); + matrix4d.BindMethod("ConcatenateAffine", &Nz::Matrix4d::ConcatenateAffine); + + //matrix4d.BindMethod("GetColumn", &Nz::Matrix4d::GetColumn); + matrix4d.BindMethod("GetDeterminant", &Nz::Matrix4d::GetDeterminant); + matrix4d.BindMethod("GetDeterminantAffine", &Nz::Matrix4d::GetDeterminantAffine); + + matrix4d.BindMethod("GetInverse", [] (Nz::LuaInstance& lua, Nz::Matrix4d& instance, std::size_t /*argumentCount*/) -> int + { + Nz::Matrix4d result; + if (instance.GetInverse(&result)) + return lua.Push(true, result); + else + return lua.Push(false); + }); + + matrix4d.BindMethod("GetInverseAffine", [] (Nz::LuaInstance& lua, Nz::Matrix4d& instance, std::size_t /*argumentCount*/) -> int + { + Nz::Matrix4d result; + if (instance.GetInverseAffine(&result)) + return lua.Push(true, result); + else + return lua.Push(false); + }); + + matrix4d.BindMethod("GetRotation", &Nz::Matrix4d::GetRotation); + + //matrix4d.BindMethod("GetRow", &Nz::Matrix4d::GetRow); + matrix4d.BindMethod("GetScale", &Nz::Matrix4d::GetScale); + matrix4d.BindMethod("GetSquaredScale", &Nz::Matrix4d::GetSquaredScale); + matrix4d.BindMethod("GetTranslation", &Nz::Matrix4d::GetTranslation); + + matrix4d.BindMethod("GetTransposed", [] (Nz::LuaInstance& lua, Nz::Matrix4d& instance, std::size_t /*argumentCount*/) -> int + { + Nz::Matrix4d result; + instance.GetTransposed(&result); + + return lua.Push(result); + }); + + matrix4d.BindMethod("HasNegativeScale", &Nz::Matrix4d::HasNegativeScale); + matrix4d.BindMethod("HasScale", &Nz::Matrix4d::HasScale); + + matrix4d.BindMethod("Inverse", [] (Nz::LuaInstance& lua, Nz::Matrix4d& instance, std::size_t /*argumentCount*/) -> int + { + bool succeeded; + instance.Inverse(&succeeded); + + return lua.Push(succeeded); + }); + + matrix4d.BindMethod("InverseAffine", [] (Nz::LuaInstance& lua, Nz::Matrix4d& instance, std::size_t /*argumentCount*/) -> int + { + bool succeeded; + instance.InverseAffine(&succeeded); + + return lua.Push(succeeded); + }); + + matrix4d.BindMethod("IsAffine", &Nz::Matrix4d::IsAffine); + matrix4d.BindMethod("IsIdentity", &Nz::Matrix4d::IsIdentity); + + matrix4d.BindMethod("MakeIdentity", &Nz::Matrix4d::MakeIdentity); + matrix4d.BindMethod("MakeLookAt", &Nz::Matrix4d::MakeLookAt, Nz::Vector3d::Up()); + matrix4d.BindMethod("MakeOrtho", &Nz::Matrix4d::MakeOrtho, -1.0, 1.0); + matrix4d.BindMethod("MakePerspective", &Nz::Matrix4d::MakePerspective); + matrix4d.BindMethod("MakeRotation", &Nz::Matrix4d::MakeRotation); + matrix4d.BindMethod("MakeScale", &Nz::Matrix4d::MakeScale); + matrix4d.BindMethod("MakeTranslation", &Nz::Matrix4d::MakeTranslation); + matrix4d.BindMethod("MakeTransform", (Nz::Matrix4d&(Nz::Matrix4d::*)(const Nz::Vector3d&, const Nz::Quaterniond&, const Nz::Vector3d&)) &Nz::Matrix4d::MakeTransform, Nz::Vector3d::Unit()); + matrix4d.BindMethod("MakeViewMatrix", &Nz::Matrix4d::MakeViewMatrix); + matrix4d.BindMethod("MakeZero", &Nz::Matrix4d::MakeZero); + + matrix4d.BindMethod("Set", [] (Nz::LuaInstance& lua, Nz::Matrix4d& instance, std::size_t argumentCount) -> int + { + std::size_t argCount = std::min(argumentCount, 3U); + + int argIndex = 2; + switch (argCount) + { + case 1: + if (lua.IsOfType(argIndex, "Matrix4")) + instance.Set(*static_cast(lua.ToUserdata(argIndex))); + break; + + case 16: + { + double values[16]; + for (std::size_t i = 0; i < 16; ++i) + values[i] = lua.CheckNumber(argIndex++); + + instance.Set(values); + + return 0; + } + } + + lua.Error("No matching overload for method Set"); + return 0; + }); + + matrix4d.BindMethod("SetRotation", &Nz::Matrix4d::SetRotation); + matrix4d.BindMethod("SetScale", &Nz::Matrix4d::SetScale); + matrix4d.BindMethod("SetTranslation", &Nz::Matrix4d::SetTranslation); + + matrix4d.BindMethod("Transform", [] (Nz::LuaInstance& lua, Nz::Matrix4d& instance, std::size_t /*argumentCount*/) -> int + { + int argIndex = 2; + if (lua.IsOfType(argIndex, "Vector2")) + { + double z(lua.CheckNumber(argIndex + 1, 0.0)); + double w(lua.CheckNumber(argIndex + 2, 1.0)); + + return lua.Push(instance.Transform(*static_cast(lua.ToUserdata(argIndex)), z, w)); + } + else if (lua.IsOfType(argIndex, "Vector3")) + { + double w(lua.CheckNumber(argIndex + 1, 1.0)); + + return lua.Push(instance.Transform(*static_cast(lua.ToUserdata(argIndex)), w)); + } + //else if (lua.IsOfType(2, "Vector4")) + // return lua.Push(instance.Transform(*static_cast(lua.ToUserdata(1)))); + + lua.Error("No matching overload for method Transform"); + return 0; + }); + + matrix4d.BindMethod("Transpose", &Nz::Matrix4d::Transpose); + + matrix4d.BindMethod("__tostring", &Nz::Matrix4d::ToString); + + matrix4d.BindStaticMethod("Concatenate", &Nz::Matrix4d::Concatenate); + matrix4d.BindStaticMethod("ConcatenateAffine", &Nz::Matrix4d::ConcatenateAffine); + matrix4d.BindStaticMethod("Identity", &Nz::Matrix4d::Identity); + matrix4d.BindStaticMethod("LookAt", &Nz::Matrix4d::LookAt, Nz::Vector3d::Up()); + matrix4d.BindStaticMethod("Ortho", &Nz::Matrix4d::Ortho, -1.0, 1.0); + matrix4d.BindStaticMethod("Perspective", &Nz::Matrix4d::Perspective); + matrix4d.BindStaticMethod("Rotate", &Nz::Matrix4d::Rotate); + matrix4d.BindStaticMethod("Scale", &Nz::Matrix4d::Scale); + matrix4d.BindStaticMethod("Translate", &Nz::Matrix4d::Translate); + matrix4d.BindStaticMethod("Transform", (Nz::Matrix4d(*)(const Nz::Vector3d&, const Nz::Quaterniond&, const Nz::Vector3d&)) &Nz::Matrix4d::Transform, Nz::Vector3d::Unit()); + matrix4d.BindStaticMethod("ViewMatrix", &Nz::Matrix4d::ViewMatrix); + matrix4d.BindStaticMethod("Zero", &Nz::Matrix4d::Zero); + + matrix4d.SetGetter([] (Nz::LuaInstance& lua, Nz::Matrix4d& instance) + { + bool succeeded = false; + std::size_t index = static_cast(lua.ToInteger(2, &succeeded)); + if (!succeeded || index < 1 || index > 16) + return false; + + lua.Push(instance[index - 1]); + return true; + }); + + matrix4d.SetSetter([] (Nz::LuaInstance& lua, Nz::Matrix4d& instance) + { + bool succeeded = false; + std::size_t index = static_cast(lua.ToInteger(2, &succeeded)); + if (!succeeded || index < 1 || index > 16) + return false; + + instance[index - 1] = lua.CheckNumber(3); + + return true; + }); + } + + /*********************************** Nz::Rect **********************************/ + rect.Reset("Rect"); + { + rect.SetConstructor([] (Nz::LuaInstance& lua, Nz::Rectd* instance, std::size_t argumentCount) + { + std::size_t argCount = std::min(argumentCount, 4U); + + switch (argCount) + { + case 0: + case 4: + PlacementNew(instance, lua.CheckNumber(1, 0.0), lua.CheckNumber(2, 0.0), lua.CheckNumber(3, 0.0), lua.CheckNumber(4, 0.0)); + return true; + + case 1: + { + if (lua.IsOfType(1, "Rect")) + PlacementNew(instance, *static_cast(lua.ToUserdata(1))); + else if (lua.IsOfType(1, Nz::LuaType_Table)) + { + // TODO => Faire sans avoir à mettre de nom dans la table et prendre les éléments un à un pour créer le Rectd + PlacementNew(instance, lua.CheckField("x", 1), + lua.CheckField("y", 1), + lua.CheckField("width", 1), + lua.CheckField("height", 1)); + } + else if (lua.IsOfType(1, "Vector2")) + PlacementNew(instance, *static_cast(lua.ToUserdata(1))); + else + break; + + return true; + } + + case 2: + { + if (lua.IsOfType(1, Nz::LuaType_Number) && lua.IsOfType(2, Nz::LuaType_Number)) + PlacementNew(instance, lua.CheckNumber(1), lua.CheckNumber(2)); + else if (lua.IsOfType(1, "Vector2") && lua.IsOfType(2, "Vector2")) + PlacementNew(instance, *static_cast(lua.ToUserdata(1)), *static_cast(lua.ToUserdata(2))); + else + break; + + return true; + } + } + + lua.Error("No matching overload for Rect constructor"); + return false; + }); + + rect.BindMethod("__tostring", &Nz::Rectd::ToString); + + rect.SetGetter([] (Nz::LuaInstance& lua, Nz::Rectd& instance) + { + switch (lua.GetType(2)) + { + case Nz::LuaType_Number: + { + auto index = lua.CheckBoundInteger(2); + if (index < 1 || index > 4) + return false; + + lua.Push(instance[index - 1]); + return true; + } + + case Nz::LuaType_String: + { + std::size_t length; + const char* xywh = lua.CheckString(2, &length); + + if (length != 1) + break; + + switch (xywh[0]) + { + case 'x': + lua.Push(instance.x); + return true; + + case 'y': + lua.Push(instance.y); + return true; + + case 'w': + lua.Push(instance.width); + return true; + + case 'h': + lua.Push(instance.height); + return true; + + default: + break; + } + break; + } + + default: + break; + } + + return false; + }); + + rect.SetSetter([] (Nz::LuaInstance& lua, Nz::Rectd& instance) + { + switch (lua.GetType(2)) + { + case Nz::LuaType_Number: + { + auto index = lua.CheckBoundInteger(2); + if (index < 1 || index > 4) + return false; + + instance[index - 1] = lua.CheckNumber(2); + return true; + } + + case Nz::LuaType_String: + { + std::size_t length; + const char* xywh = lua.CheckString(2, &length); + + if (length != 1) + break; + + double value = lua.CheckNumber(3); + + switch (xywh[0]) + { + case 'x': + instance.x = value; + return true; + + case 'y': + instance.y = value; + return true; + + case 'w': + instance.width = value; + return true; + + case 'h': + instance.height = value; + return true; + } + break; + } + + default: + break; + } + + return false; + }); + } + + /*********************************** Nz::Quaternion **********************************/ + quaternion.Reset("Quaternion"); + { + quaternion.SetConstructor([] (Nz::LuaInstance& lua, Nz::Quaterniond* instance, std::size_t argumentCount) + { + std::size_t argCount = std::min(argumentCount, 4U); + + switch (argCount) + { + case 0: + Nz::PlacementNew(instance, Nz::Quaterniond::Zero()); + return true; + + case 1: + { + if (lua.IsOfType(1, "EulerAngles")) + Nz::PlacementNew(instance, *static_cast(lua.ToUserdata(1))); + else if (lua.IsOfType(1, "Quaternion")) + Nz::PlacementNew(instance, *static_cast(lua.ToUserdata(1))); + else + break; + + return true; + } + + case 2: + Nz::PlacementNew(instance, lua.CheckNumber(1), *static_cast(lua.CheckUserdata(2, "Vector3"))); + return true; + + case 4: + Nz::PlacementNew(instance, lua.CheckNumber(1), lua.CheckNumber(2), lua.CheckNumber(3), lua.CheckNumber(4)); + return true; + + default: + break; + } + + lua.Error("No matching overload for Quaternion constructor"); + return false; + }); + + quaternion.BindMethod("ComputeW", &Nz::Quaterniond::ComputeW); + quaternion.BindMethod("Conjugate", &Nz::Quaterniond::Conjugate); + quaternion.BindMethod("DotProduct", &Nz::Quaterniond::DotProduct); + quaternion.BindMethod("GetConjugate", &Nz::Quaterniond::GetConjugate); + quaternion.BindMethod("GetInverse", &Nz::Quaterniond::GetInverse); + + quaternion.BindMethod("Inverse", &Nz::Quaterniond::Inverse); + quaternion.BindMethod("Magnitude", &Nz::Quaterniond::Magnitude); + + quaternion.BindMethod("SquaredMagnitude", &Nz::Quaterniond::SquaredMagnitude); + quaternion.BindMethod("ToEulerAngles", &Nz::Quaterniond::ToEulerAngles); + + quaternion.BindMethod("__tostring", &Nz::Quaterniond::ToString); + + quaternion.BindStaticMethod("Lerp", &Nz::Quaterniond::Lerp); + quaternion.BindStaticMethod("RotationBetween", &Nz::Quaterniond::RotationBetween); + quaternion.BindStaticMethod("Slerp", &Nz::Quaterniond::Slerp); + + quaternion.BindMethod("GetNormal", [] (Nz::LuaInstance& lua, Nz::Quaterniond& instance, std::size_t /*argumentCount*/) -> int + { + double length; + + lua.Push(instance.GetNormal(&length)); + lua.Push(length); + + return 2; + }); + + quaternion.BindMethod("Normalize", [] (Nz::LuaInstance& lua, Nz::Quaterniond& instance, std::size_t /*argumentCount*/) -> int + { + double length; + + instance.Normalize(&length); + lua.Push(1); //< instance + lua.Push(length); + + return 2; + }); + + quaternion.BindStaticMethod("Normalize", [] (Nz::LuaInstance& instance) -> int + { + int argIndex = 1; + Nz::Quaterniond quat = instance.Check(&argIndex); + + double length; + + instance.Push(Nz::Quaterniond::Normalize(quat, &length)); + instance.Push(length); + + return 2; + }); + + quaternion.SetGetter([] (Nz::LuaInstance& lua, Nz::Quaterniond& instance) + { + std::size_t length; + const char* wxyz = lua.CheckString(2, &length); + + if (length != 1) + return false; + + switch (wxyz[0]) + { + case 'w': + lua.Push(instance.w); + return true; + + case 'x': + lua.Push(instance.x); + return true; + + case 'y': + lua.Push(instance.y); + return true; + + case 'z': + lua.Push(instance.z); + return true; + } + + return false; + }); + + quaternion.SetSetter([] (Nz::LuaInstance& lua, Nz::Quaterniond& instance) + { + std::size_t length; + const char* wxyz = lua.CheckString(2, &length); + + if (length != 1) + return false; + + double value = lua.CheckNumber(3); + + switch (wxyz[0]) + { + case 'w': + instance.w = value; + return true; + + case 'x': + instance.x = value; + return true; + + case 'y': + instance.y = value; + return true; + + case 'z': + instance.z = value; + return true; + + default: + break; + } + + return false; + }); + } + + /*********************************** Nz::Vector2 **********************************/ + vector2d.Reset("Vector2"); + { + vector2d.SetConstructor([] (Nz::LuaInstance& lua, Nz::Vector2d* vector, std::size_t argumentCount) + { + std::size_t argCount = std::min(argumentCount, 2U); + + switch (argCount) + { + case 0: + case 2: + Nz::PlacementNew(vector, lua.CheckNumber(1, 0.0), lua.CheckNumber(2, 0.0)); + return true; + + case 1: + { + if (lua.IsOfType(1, Nz::LuaType_Number)) + Nz::PlacementNew(vector, lua.CheckNumber(1)); + else if (lua.IsOfType(1, "Vector2")) + Nz::PlacementNew(vector, *static_cast(lua.ToUserdata(1))); + else + break; + + return true; + } + } + + lua.Error("No matching overload for Vector2 constructor"); + return false; + }); + + vector2d.BindMethod("__tostring", &Nz::Vector2d::ToString); + + vector2d.SetGetter([] (Nz::LuaInstance& lua, Nz::Vector2d& instance) + { + switch (lua.GetType(2)) + { + case Nz::LuaType_Number: + { + long long index = lua.CheckInteger(2); + if (index < 1 || index > 2) + return false; + + lua.Push(instance[index - 1]); + return true; + } + + case Nz::LuaType_String: + { + std::size_t length; + const char* xy = lua.CheckString(2, &length); + + if (length != 1) + break; + + switch (xy[0]) + { + case 'x': + lua.Push(instance.x); + return true; + + case 'y': + lua.Push(instance.y); + return true; + + default: + break; + } + break; + } + + default: + break; + } + + return false; + }); + + vector2d.SetSetter([] (Nz::LuaInstance& lua, Nz::Vector2d& instance) + { + switch (lua.GetType(2)) + { + case Nz::LuaType_Number: + { + long long index = lua.CheckInteger(2); + if (index < 1 || index > 2) + return false; + + instance[index - 1] = lua.CheckNumber(3); + return true; + } + + case Nz::LuaType_String: + { + std::size_t length; + const char* xy = lua.CheckString(2, &length); + + if (length != 1) + break; + + double value = lua.CheckNumber(3); + + switch (xy[0]) + { + case 'x': + instance.x = value; + return true; + + case 'y': + instance.y = value; + return true; + + default: + break; + } + break; + } + + default: + break; + } + + return false; + }); + } + + /*********************************** Nz::Vector3 **********************************/ + vector3d.Reset("Vector3"); + { + vector3d.SetConstructor([] (Nz::LuaInstance& lua, Nz::Vector3d* vector, std::size_t argumentCount) + { + std::size_t argCount = std::min(argumentCount, 3U); + + switch (argCount) + { + case 0: + case 3: + Nz::PlacementNew(vector, lua.CheckNumber(1, 0.0), lua.CheckNumber(2, 0.0), lua.CheckNumber(3, 0.0)); + return true; + + case 1: + { + if (lua.IsOfType(1, Nz::LuaType_Number)) + Nz::PlacementNew(vector, lua.CheckNumber(1)); + else if (lua.IsOfType(1, "Vector2")) + Nz::PlacementNew(vector, *static_cast(lua.ToUserdata(1))); + else if (lua.IsOfType(1, "Vector3")) + Nz::PlacementNew(vector, *static_cast(lua.ToUserdata(1))); + else + break; + + return true; + } + + case 2: + { + if (lua.IsOfType(1, Nz::LuaType_Number)) + Nz::PlacementNew(vector, lua.CheckNumber(1), *static_cast(lua.CheckUserdata(2, "Vector2"))); + else if (lua.IsOfType(1, "Vector2")) + Nz::PlacementNew(vector, *static_cast(lua.ToUserdata(1)), lua.CheckNumber(2)); + else + break; + + return true; + } + } + + lua.Error("No matching overload for constructor"); + return false; + }); + + vector3d.BindMethod("__tostring", &Nz::Vector3d::ToString); + + vector3d.SetGetter([] (Nz::LuaInstance& lua, Nz::Vector3d& instance) + { + switch (lua.GetType(2)) + { + case Nz::LuaType_Number: + { + long long index = lua.CheckInteger(2); + if (index < 1 || index > 3) + return false; + + lua.Push(instance[index - 1]); + return true; + } + + case Nz::LuaType_String: + { + std::size_t length; + const char* xyz = lua.CheckString(2, &length); + + if (length != 1) + break; + + switch (xyz[0]) + { + case 'x': + lua.Push(instance.x); + return true; + + case 'y': + lua.Push(instance.y); + return true; + + case 'z': + lua.Push(instance.z); + return true; + + default: + break; + } + break; + } + + default: + break; + } + + return false; + }); + + vector3d.SetSetter([] (Nz::LuaInstance& lua, Nz::Vector3d& instance) + { + switch (lua.GetType(2)) + { + case Nz::LuaType_Number: + { + long long index = lua.CheckInteger(2); + if (index < 1 || index > 3) + return false; + + instance[index - 1] = lua.CheckNumber(3); + return true; + } + + case Nz::LuaType_String: + { + std::size_t length; + const char* xyz = lua.CheckString(2, &length); + + if (length != 1) + break; + + double value = lua.CheckNumber(3); + + switch (xyz[0]) + { + case 'x': + instance.x = value; + return true; + + case 'y': + instance.y = value; + return true; + + case 'z': + instance.z = value; + return true; + + default: + break; + } + break; + } + + default: + break; + } + + return false; + }); + } + } + + /*! + * \brief Registers the classes that will be used by the Lua instance + * + * \param instance Lua instance that will interact with the Math classes + */ + void LuaBinding_Math::Register(Nz::LuaInstance& instance) + { + eulerAngles.Register(instance); + matrix4d.Register(instance); + quaternion.Register(instance); + rect.Register(instance); + vector2d.Register(instance); + vector3d.Register(instance); + + quaternion.PushGlobalTable(instance); + { + instance.PushField("Identity", Nz::Quaterniond::Identity()); + instance.PushField("Zero", Nz::Quaterniond::Zero()); + } + instance.Pop(); + } +} diff --git a/SDK/src/NDK/LuaBinding_Network.cpp b/SDK/src/NDK/Lua/LuaBinding_Network.cpp similarity index 55% rename from SDK/src/NDK/LuaBinding_Network.cpp rename to SDK/src/NDK/Lua/LuaBinding_Network.cpp index b51906481..d6f92cb40 100644 --- a/SDK/src/NDK/LuaBinding_Network.cpp +++ b/SDK/src/NDK/Lua/LuaBinding_Network.cpp @@ -1,139 +1,147 @@ // This file was automatically generated on 26 May 2014 at 01:05:31 -#include +#include #include namespace Ndk { - /*! - * \brief Binds Network module to Lua - */ + std::unique_ptr LuaBinding_Base::BindNetwork(LuaBinding& binding) + { + return std::make_unique(binding); + } - void LuaBinding::BindNetwork() + LuaBinding_Network::LuaBinding_Network(LuaBinding& binding) : + LuaBinding_Base(binding) { /*********************************** Nz::AbstractSocket **********************************/ - abstractSocket.BindMethod("Close", &Nz::AbstractSocket::Close); - abstractSocket.BindMethod("EnableBlocking", &Nz::AbstractSocket::EnableBlocking); - abstractSocket.BindMethod("GetLastError", &Nz::AbstractSocket::GetLastError); - abstractSocket.BindMethod("GetState", &Nz::AbstractSocket::GetState); - abstractSocket.BindMethod("GetType", &Nz::AbstractSocket::GetType); - abstractSocket.BindMethod("IsBlockingEnabled", &Nz::AbstractSocket::IsBlockingEnabled); - abstractSocket.BindMethod("QueryAvailableBytes", &Nz::AbstractSocket::QueryAvailableBytes); + abstractSocket.Reset("AbstractSocket"); + { + abstractSocket.BindMethod("Close", &Nz::AbstractSocket::Close); + abstractSocket.BindMethod("EnableBlocking", &Nz::AbstractSocket::EnableBlocking); + abstractSocket.BindMethod("GetLastError", &Nz::AbstractSocket::GetLastError); + abstractSocket.BindMethod("GetState", &Nz::AbstractSocket::GetState); + abstractSocket.BindMethod("GetType", &Nz::AbstractSocket::GetType); + abstractSocket.BindMethod("IsBlockingEnabled", &Nz::AbstractSocket::IsBlockingEnabled); + abstractSocket.BindMethod("QueryAvailableBytes", &Nz::AbstractSocket::QueryAvailableBytes); + } /*********************************** Nz::IpAddress **********************************/ - ipAddress.SetConstructor([] (Nz::LuaInstance& lua, Nz::IpAddress* instance, std::size_t argumentCount) + ipAddress.Reset("IpAddress"); { - std::size_t argCount = std::min(argumentCount, 9U); - - int argIndex = 2; - switch (argCount) + ipAddress.SetConstructor([] (Nz::LuaInstance& lua, Nz::IpAddress* instance, std::size_t argumentCount) { - case 0: - Nz::PlacementNew(instance); - return true; + std::size_t argCount = std::min(argumentCount, 9U); - case 1: - Nz::PlacementNew(instance, lua.CheckString(argIndex)); - return true; - - case 4: - case 5: + int argIndex = 2; + switch (argCount) { - Nz::UInt8 a = lua.Check(&argIndex); - Nz::UInt8 b = lua.Check(&argIndex); - Nz::UInt8 c = lua.Check(&argIndex); - Nz::UInt8 d = lua.Check(&argIndex); - Nz::UInt16 port = lua.Check(&argIndex, 0); + case 0: + Nz::PlacementNew(instance); + return true; - Nz::PlacementNew(instance, a, b, c, d, port); - return true; + case 1: + Nz::PlacementNew(instance, lua.CheckString(argIndex)); + return true; + + case 4: + case 5: + { + Nz::UInt8 a = lua.Check(&argIndex); + Nz::UInt8 b = lua.Check(&argIndex); + Nz::UInt8 c = lua.Check(&argIndex); + Nz::UInt8 d = lua.Check(&argIndex); + Nz::UInt16 port = lua.Check(&argIndex, 0); + + Nz::PlacementNew(instance, a, b, c, d, port); + return true; + } + + case 8: + case 9: + { + Nz::UInt16 a = lua.Check(&argIndex); + Nz::UInt16 b = lua.Check(&argIndex); + Nz::UInt16 c = lua.Check(&argIndex); + Nz::UInt16 d = lua.Check(&argIndex); + Nz::UInt16 e = lua.Check(&argIndex); + Nz::UInt16 f = lua.Check(&argIndex); + Nz::UInt16 g = lua.Check(&argIndex); + Nz::UInt16 h = lua.Check(&argIndex); + Nz::UInt16 port = lua.Check(&argIndex, 0); + + Nz::PlacementNew(instance, a, b, c, d, e, f, g, h, port); + return true; + } } - case 8: - case 9: + lua.Error("No matching overload for constructor"); + return false; + }); + + ipAddress.BindMethod("GetPort", &Nz::IpAddress::GetPort); + ipAddress.BindMethod("GetProtocol", &Nz::IpAddress::GetProtocol); + ipAddress.BindMethod("IsLoopback", &Nz::IpAddress::IsLoopback); + ipAddress.BindMethod("IsValid", &Nz::IpAddress::IsValid); + ipAddress.BindMethod("ToUInt32", &Nz::IpAddress::ToUInt32); + ipAddress.BindMethod("__tostring", &Nz::IpAddress::ToString); + + ipAddress.BindStaticMethod("ResolveAddress", [] (Nz::LuaInstance& instance) -> int + { + Nz::String service; + Nz::ResolveError error = Nz::ResolveError_Unknown; + + int argIndex = 2; + Nz::String hostName = Nz::IpAddress::ResolveAddress(instance.Check(&argIndex), &service, &error); + + if (error == Nz::ResolveError_NoError) { - Nz::UInt16 a = lua.Check(&argIndex); - Nz::UInt16 b = lua.Check(&argIndex); - Nz::UInt16 c = lua.Check(&argIndex); - Nz::UInt16 d = lua.Check(&argIndex); - Nz::UInt16 e = lua.Check(&argIndex); - Nz::UInt16 f = lua.Check(&argIndex); - Nz::UInt16 g = lua.Check(&argIndex); - Nz::UInt16 h = lua.Check(&argIndex); - Nz::UInt16 port = lua.Check(&argIndex, 0); - - Nz::PlacementNew(instance, a, b, c, d, e, f, g, h, port); - return true; + instance.Push(hostName); + instance.Push(service); + return 2; } - } - - lua.Error("No matching overload for constructor"); - return false; - }); - - ipAddress.BindMethod("GetPort", &Nz::IpAddress::GetPort); - ipAddress.BindMethod("GetProtocol", &Nz::IpAddress::GetProtocol); - ipAddress.BindMethod("IsLoopback", &Nz::IpAddress::IsLoopback); - ipAddress.BindMethod("IsValid", &Nz::IpAddress::IsValid); - ipAddress.BindMethod("ToUInt32", &Nz::IpAddress::ToUInt32); - ipAddress.BindMethod("__tostring", &Nz::IpAddress::ToString); - - ipAddress.BindStaticMethod("ResolveAddress", [] (Nz::LuaInstance& instance) -> int - { - Nz::String service; - Nz::ResolveError error = Nz::ResolveError_Unknown; - - int argIndex = 2; - Nz::String hostName = Nz::IpAddress::ResolveAddress(instance.Check(&argIndex), &service, &error); - - if (error == Nz::ResolveError_NoError) - { - instance.Push(hostName); - instance.Push(service); - return 2; - } - else - { - instance.PushBoolean(false); - instance.Push(error); - return 2; - } - }); - - ipAddress.BindStaticMethod("ResolveHostname", [] (Nz::LuaInstance& instance) -> int - { - Nz::ResolveError error = Nz::ResolveError_Unknown; - - int argIndex = 2; - Nz::NetProtocol protocol = instance.Check(&argIndex); - Nz::String hostname = instance.Check(&argIndex); - Nz::String service = instance.Check(&argIndex, "http"); - - std::vector addresses = Nz::IpAddress::ResolveHostname(protocol, hostname, service, &error); - if (error == Nz::ResolveError_NoError) - { - int index = 1; - instance.PushTable(addresses.size()); - for (Nz::HostnameInfo& info : addresses) + else { - instance.PushInteger(index++); - instance.PushTable(0, 4); - instance.PushField("Address", std::move(info.address)); - instance.PushField("CanonicalName", std::move(info.canonicalName)); - instance.PushField("Protocol", std::move(info.protocol)); - instance.PushField("SocketType", std::move(info.socketType)); - instance.SetTable(); + instance.PushBoolean(false); + instance.Push(error); + return 2; } + }); - return 1; - } - else + ipAddress.BindStaticMethod("ResolveHostname", [] (Nz::LuaInstance& instance) -> int { - instance.PushBoolean(false); - instance.Push(error); - return 2; - } - }); + Nz::ResolveError error = Nz::ResolveError_Unknown; + + int argIndex = 2; + Nz::NetProtocol protocol = instance.Check(&argIndex); + Nz::String hostname = instance.Check(&argIndex); + Nz::String service = instance.Check(&argIndex, "http"); + + std::vector addresses = Nz::IpAddress::ResolveHostname(protocol, hostname, service, &error); + if (error == Nz::ResolveError_NoError) + { + int index = 1; + instance.PushTable(addresses.size()); + for (Nz::HostnameInfo& info : addresses) + { + instance.PushInteger(index++); + instance.PushTable(0, 4); + instance.PushField("Address", std::move(info.address)); + instance.PushField("CanonicalName", std::move(info.canonicalName)); + instance.PushField("Protocol", std::move(info.protocol)); + instance.PushField("SocketType", std::move(info.socketType)); + instance.SetTable(); + } + + return 1; + } + else + { + instance.PushBoolean(false); + instance.Push(error); + return 2; + } + }); + } } /*! @@ -141,8 +149,7 @@ namespace Ndk * * \param instance Lua instance that will interact with the Network classes */ - - void LuaBinding::RegisterNetwork(Nz::LuaInstance& instance) + void LuaBinding_Network::Register(Nz::LuaInstance& instance) { // Classes abstractSocket.Register(instance); diff --git a/SDK/src/NDK/Lua/LuaBinding_Renderer.cpp b/SDK/src/NDK/Lua/LuaBinding_Renderer.cpp new file mode 100644 index 000000000..7f881e20d --- /dev/null +++ b/SDK/src/NDK/Lua/LuaBinding_Renderer.cpp @@ -0,0 +1,110 @@ +// Copyright (C) 2016 Jérôme Leclercq, Arnaud Cadot +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include +#include +#include + +namespace Ndk +{ + std::unique_ptr LuaBinding_Base::BindRenderer(LuaBinding& binding) + { + return std::make_unique(binding); + } + + LuaBinding_Renderer::LuaBinding_Renderer(LuaBinding& binding) : + LuaBinding_Base(binding) + { + LuaBinding_Utility& utility = static_cast(*m_binding.utility); + + /*********************************** Nz::Texture ***********************************/ + texture.Reset("Texture"); + { + texture.Inherit(utility.abstractImage, [] (Nz::TextureRef* textureRef) -> Nz::AbstractImageRef* + { + return reinterpret_cast(textureRef); //TODO: Make a ObjectRefCast + }); + + texture.SetConstructor([] (Nz::LuaInstance& /*lua*/, Nz::TextureRef* instance, std::size_t /*argumentCount*/) + { + Nz::PlacementNew(instance, Nz::Texture::New()); + return true; + }); + + texture.BindMethod("Create", &Nz::Texture::Create, static_cast(1), 1U); + texture.BindMethod("Destroy", &Nz::Texture::Destroy); + + //texture.BindMethod("Download", &Nz::Texture::Download); + + texture.BindMethod("EnableMipmapping", &Nz::Texture::EnableMipmapping); + texture.BindMethod("EnsureMipmapsUpdate", &Nz::Texture::EnsureMipmapsUpdate); + texture.BindMethod("HasMipmaps", &Nz::Texture::HasMipmaps); + texture.BindMethod("InvalidateMipmaps", &Nz::Texture::InvalidateMipmaps); + texture.BindMethod("IsValid", &Nz::Texture::IsValid); + + texture.BindMethod("LoadFromFile", &Nz::Texture::LoadFromFile, true, Nz::ImageParams()); + //bool LoadFromImage(const Image& image, bool generateMipmaps = true); + //bool LoadFromMemory(const void* data, std::size_t size, const ImageParams& params = ImageParams(), bool generateMipmaps = true); + //bool LoadFromStream(Stream& stream, const ImageParams& params = ImageParams(), bool generateMipmaps = true); + + texture.BindMethod("LoadArrayFromFile", &Nz::Texture::LoadArrayFromFile, Nz::Vector2ui(2, 2), true, Nz::ImageParams()); + //bool LoadArrayFromImage(const Image& image, bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2)); + //bool LoadArrayFromMemory(const void* data, std::size_t size, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2)); + //bool LoadArrayFromStream(Stream& stream, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2)); + + //bool LoadCubemapFromFile(const String& filePath, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const CubemapParams& cubemapParams = CubemapParams()); + //bool LoadCubemapFromImage(const Image& image, bool generateMipmaps = true, const CubemapParams& params = CubemapParams()); + //bool LoadCubemapFromMemory(const void* data, std::size_t size, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const CubemapParams& cubemapParams = CubemapParams()); + //bool LoadCubemapFromStream(Stream& stream, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const CubemapParams& cubemapParams = CubemapParams()); + + texture.BindMethod("LoadFaceFromFile", &Nz::Texture::LoadFaceFromFile, Nz::ImageParams()); + //bool LoadFaceFromMemory(CubemapFace face, const void* data, std::size_t size, const ImageParams& params = ImageParams()); + //bool LoadFaceFromStream(CubemapFace face, Stream& stream, const ImageParams& params = ImageParams()); + + texture.BindMethod("SaveToFile", &Nz::Texture::SaveToFile, Nz::ImageParams()); + //bool SaveToStream(Stream& stream, const String& format, const ImageParams& params = ImageParams()); + + texture.BindMethod("SetMipmapRange", &Nz::Texture::SetMipmapRange); + + texture.BindStaticMethod("IsFormatSupported", &Nz::Texture::IsFormatSupported); + texture.BindStaticMethod("IsMipmappingSupported", &Nz::Texture::IsMipmappingSupported); + texture.BindStaticMethod("IsTypeSupported", &Nz::Texture::IsTypeSupported); + } + + /*********************************** Nz::TextureLibrary ***********************************/ + textureLibrary.Reset("TextureLibrary"); + { + textureLibrary.BindStaticMethod("Get", &Nz::TextureLibrary::Get); + textureLibrary.BindStaticMethod("Has", &Nz::TextureLibrary::Has); + textureLibrary.BindStaticMethod("Register", &Nz::TextureLibrary::Register); + textureLibrary.BindStaticMethod("Query", &Nz::TextureLibrary::Query); + textureLibrary.BindStaticMethod("Unregister", &Nz::TextureLibrary::Unregister); + } + + /*********************************** Nz::TextureManager ***********************************/ + textureManager.Reset("textureManager"); + { + textureManager.BindStaticMethod("Clear", &Nz::TextureManager::Clear); + textureManager.BindStaticMethod("Get", &Nz::TextureManager::Get); + textureManager.BindStaticMethod("GetDefaultParameters", &Nz::TextureManager::GetDefaultParameters); + textureManager.BindStaticMethod("Purge", &Nz::TextureManager::Purge); + textureManager.BindStaticMethod("Register", &Nz::TextureManager::Register); + textureManager.BindStaticMethod("SetDefaultParameters", &Nz::TextureManager::SetDefaultParameters); + textureManager.BindStaticMethod("Unregister", &Nz::TextureManager::Unregister); + } + } + + /*! + * \brief Registers the classes that will be used by the Lua instance + * + * \param instance Lua instance that will interact with the Renderer classes + */ + void LuaBinding_Renderer::Register(Nz::LuaInstance& instance) + { + texture.Register(instance); + textureLibrary.Register(instance); + textureManager.Register(instance); + } +} diff --git a/SDK/src/NDK/Lua/LuaBinding_SDK.cpp b/SDK/src/NDK/Lua/LuaBinding_SDK.cpp new file mode 100644 index 000000000..ad9bb49e9 --- /dev/null +++ b/SDK/src/NDK/Lua/LuaBinding_SDK.cpp @@ -0,0 +1,338 @@ +// Copyright (C) 2016 Jérôme Leclercq, Arnaud Cadot +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include +#include +#include + +#ifndef NDK_SERVER +#include +#endif + +namespace Ndk +{ + std::unique_ptr LuaBinding_Base::BindSDK(LuaBinding& binding) + { + return std::make_unique(binding); + } + + LuaBinding_SDK::LuaBinding_SDK(LuaBinding& binding) : + LuaBinding_Base(binding) + { + #ifndef NDK_SERVER + LuaBinding_Graphics& graphics = static_cast(*m_binding.graphics); + #endif + + LuaBinding_Utility& utility = static_cast(*m_binding.utility); + + /*********************************** Ndk::Application **********************************/ + application.Reset("Application"); + { + #ifndef NDK_SERVER + //application.SetMethod("AddWindow", &Application::AddWindow); + + application.BindMethod("EnableConsole", &Application::EnableConsole); + application.BindMethod("EnableFPSCounter", &Application::EnableFPSCounter); + + application.BindMethod("IsConsoleEnabled", &Application::IsConsoleEnabled); + application.BindMethod("IsFPSCounterEnabled", &Application::IsFPSCounterEnabled); + #endif + + application.BindMethod("AddWorld", [] (Nz::LuaInstance& lua, Application* instance, std::size_t /*argumentCount*/) -> int + { + lua.Push(instance->AddWorld().CreateHandle()); + return 1; + }); + + application.BindMethod("GetUpdateTime", &Application::GetUpdateTime); + application.BindMethod("Quit", &Application::Quit); + } + + /*********************************** Ndk::Console **********************************/ + #ifndef NDK_SERVER + console.Reset("Console"); + { + console.Inherit(utility.node, [] (ConsoleHandle* handle) -> Nz::Node* + { + return handle->GetObject(); + }); + + console.BindMethod("AddLine", &Console::AddLine, Nz::Color::White); + console.BindMethod("Clear", &Console::Clear); + console.BindMethod("GetCharacterSize", &Console::GetCharacterSize); + console.BindMethod("GetHistory", &Console::GetHistory); + console.BindMethod("GetHistoryBackground", &Console::GetHistoryBackground); + console.BindMethod("GetInput", &Console::GetInput); + console.BindMethod("GetInputBackground", &Console::GetInputBackground); + console.BindMethod("GetSize", &Console::GetSize); + console.BindMethod("GetTextFont", &Console::GetTextFont); + + console.BindMethod("IsVisible", &Console::IsVisible); + + console.BindMethod("SendCharacter", &Console::SendCharacter); + //consoleClass.SetMethod("SendEvent", &Console::SendEvent); + + console.BindMethod("SetCharacterSize", &Console::SetCharacterSize); + console.BindMethod("SetSize", &Console::SetSize); + console.BindMethod("SetTextFont", &Console::SetTextFont); + + console.BindMethod("Show", &Console::Show, true); + } + #endif + + /*********************************** Ndk::Entity **********************************/ + entity.Reset("Entity"); + { + entity.BindMethod("Enable", &Entity::Enable, true); + entity.BindMethod("GetId", &Entity::GetId); + entity.BindMethod("GetWorld", &Entity::GetWorld); + entity.BindMethod("Kill", &Entity::Kill); + entity.BindMethod("IsEnabled", &Entity::IsEnabled); + entity.BindMethod("IsValid", &Entity::IsValid); + entity.BindMethod("RemoveAllComponents", &Entity::RemoveAllComponents); + entity.BindMethod("__tostring", &EntityHandle::ToString); + + entity.BindMethod("AddComponent", [this] (Nz::LuaInstance& instance, EntityHandle& handle, std::size_t /*argumentCount*/) -> int + { + LuaBinding::ComponentBinding* binding = m_binding.QueryComponentIndex(instance); + + return binding->adder(instance, handle); + }); + + entity.BindMethod("GetComponent", [this] (Nz::LuaInstance& instance, EntityHandle& handle, std::size_t /*argumentCount*/) -> int + { + LuaBinding::ComponentBinding* binding = m_binding.QueryComponentIndex(instance); + + return binding->getter(instance, handle->GetComponent(binding->index)); + }); + + entity.BindMethod("RemoveComponent", [this] (Nz::LuaInstance& instance, EntityHandle& handle, std::size_t /*argumentCount*/) -> int + { + LuaBinding::ComponentBinding* binding = m_binding.QueryComponentIndex(instance); + + handle->RemoveComponent(binding->index); + return 0; + }); + } + + /*********************************** Ndk::NodeComponent **********************************/ + nodeComponent.Reset("NodeComponent"); + { + nodeComponent.Inherit(utility.node, [] (NodeComponentHandle* handle) -> Nz::Node* + { + return handle->GetObject(); + }); + } + + /*********************************** Ndk::VelocityComponent **********************************/ + velocityComponent.Reset("VelocityComponent"); + { + velocityComponent.SetGetter([] (Nz::LuaInstance& lua, VelocityComponentHandle& instance) + { + std::size_t length; + const char* member = lua.CheckString(2, &length); + + if (std::strcmp(member, "Linear") == 0) + { + lua.Push(instance->linearVelocity); + return true; + } + + return false; + }); + + velocityComponent.SetSetter([] (Nz::LuaInstance& lua, VelocityComponentHandle& instance) + { + std::size_t length; + const char* member = lua.CheckString(2, &length); + + int argIndex = 3; + if (std::strcmp(member, "Linear") == 0) + { + instance->linearVelocity = lua.Check(&argIndex); + return true; + } + + return false; + }); + } + + /*********************************** Ndk::World **********************************/ + world.Reset("World"); + { + world.BindMethod("CreateEntity", &World::CreateEntity); + world.BindMethod("CreateEntities", &World::CreateEntities); + world.BindMethod("Clear", &World::Clear); + } + + #ifndef NDK_SERVER + /*********************************** Ndk::CameraComponent **********************************/ + cameraComponent.Reset("CameraComponent"); + { + cameraComponent.Inherit(graphics.abstractViewer, [] (CameraComponentHandle* handle) -> Nz::AbstractViewer* + { + return handle->GetObject(); + }); + + cameraComponent.BindMethod("GetFOV", &Ndk::CameraComponent::GetFOV); + cameraComponent.BindMethod("GetLayer", &Ndk::CameraComponent::GetLayer); + + cameraComponent.BindMethod("SetFOV", &Ndk::CameraComponent::SetFOV); + cameraComponent.BindMethod("SetLayer", &Ndk::CameraComponent::SetLayer); + cameraComponent.BindMethod("SetProjectionType", &Ndk::CameraComponent::SetProjectionType); + cameraComponent.BindMethod("SetSize", (void(Ndk::CameraComponent::*)(const Nz::Vector2f&)) &Ndk::CameraComponent::SetSize); + //cameraComponent.BindMethod("SetTarget", &Ndk::CameraComponent::SetTarget); + cameraComponent.BindMethod("SetTargetRegion", &Ndk::CameraComponent::SetTargetRegion); + cameraComponent.BindMethod("SetViewport", &Ndk::CameraComponent::SetViewport); + cameraComponent.BindMethod("SetZFar", &Ndk::CameraComponent::SetZFar); + cameraComponent.BindMethod("SetZNear", &Ndk::CameraComponent::SetZNear); + } + + /*********************************** Ndk::GraphicsComponent **********************************/ + graphicsComponent.Reset("GraphicsComponent"); + { + graphicsComponent.BindMethod("Attach", [] (Nz::LuaInstance& lua, Ndk::GraphicsComponent* instance, std::size_t argumentCount) -> int + { + /* + void Attach(Nz::InstancedRenderableRef renderable, int renderOrder = 0); + void Attach(Nz::InstancedRenderableRef renderable, const Nz::Matrix4f& localMatrix, int renderOrder = 0); + */ + + std::size_t argCount = std::min(argumentCount, 3U); + + switch (argCount) + { + case 1: + { + int argIndex = 2; + instance->Attach(lua.Check(&argIndex)); + return 0; + } + + case 2: + { + int argIndex = 2; + Nz::InstancedRenderableRef renderable = lua.Check(&argIndex); + + if (lua.IsOfType(argIndex, Nz::LuaType_Number)) + { + int renderOrder = lua.Check(&argIndex); + + instance->Attach(renderable, renderOrder); + } + else if (lua.IsOfType(argIndex, "Matrix4")) + { + Nz::Matrix4f localMatrix = lua.Check(&argIndex); + + instance->Attach(renderable, localMatrix); + } + else + break; + + return 0; + } + + case 3: + { + int argIndex = 2; + Nz::InstancedRenderableRef renderable = lua.Check(&argIndex); + Nz::Matrix4f localMatrix = lua.Check(&argIndex); + int renderOrder = lua.Check(&argIndex); + + instance->Attach(renderable, localMatrix, renderOrder); + return 0; + } + } + + lua.Error("No matching overload for method GetMemoryUsage"); + return 0; + }); + } + #endif + + // Components functions + m_binding.BindComponent("Node"); + m_binding.BindComponent("Velocity"); + + #ifndef NDK_SERVER + m_binding.BindComponent("Camera"); + m_binding.BindComponent("Graphics"); + #endif + } + + /*! + * \brief Registers the classes that will be used by the Lua instance + * + * \param instance Lua instance that will interact with the SDK classes + */ + void LuaBinding_SDK::Register(Nz::LuaInstance& instance) + { + // Classes + application.Register(instance); + entity.Register(instance); + nodeComponent.Register(instance); + velocityComponent.Register(instance); + world.Register(instance); + + #ifndef NDK_SERVER + cameraComponent.Register(instance); + console.Register(instance); + graphicsComponent.Register(instance); + #endif + + // Enums + } + + /*! + * \brief Gets the index of the component + * \return A pointer to the binding linked to a component + * + * \param instance Lua instance that will interact with the component + * \param argIndex Index of the component + */ + LuaBinding::ComponentBinding* LuaBinding::QueryComponentIndex(Nz::LuaInstance& instance, int argIndex) + { + switch (instance.GetType(argIndex)) + { + case Nz::LuaType_Number: + { + ComponentIndex componentIndex = instance.Check(&argIndex); + if (componentIndex > m_componentBinding.size()) + { + instance.Error("Invalid component index"); + return nullptr; + } + + ComponentBinding& binding = m_componentBinding[componentIndex]; + if (binding.name.IsEmpty()) + { + instance.Error("Invalid component index"); + return nullptr; + } + + return &binding; + } + + case Nz::LuaType_String: + { + const char* key = instance.CheckString(argIndex); + auto it = m_componentBindingByName.find(key); + if (it == m_componentBindingByName.end()) + { + instance.Error("Invalid component name"); + return nullptr; + } + + return &m_componentBinding[it->second]; + } + + default: + break; + } + + instance.Error("Invalid component index at #" + Nz::String::Number(argIndex)); + return nullptr; + } +} diff --git a/SDK/src/NDK/Lua/LuaBinding_Utility.cpp b/SDK/src/NDK/Lua/LuaBinding_Utility.cpp new file mode 100644 index 000000000..173d6c3c5 --- /dev/null +++ b/SDK/src/NDK/Lua/LuaBinding_Utility.cpp @@ -0,0 +1,446 @@ +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include + +namespace Ndk +{ + std::unique_ptr LuaBinding_Base::BindUtility(LuaBinding& binding) + { + return std::make_unique(binding); + } + + LuaBinding_Utility::LuaBinding_Utility(LuaBinding& binding) : + LuaBinding_Base(binding) + { + /*********************************** Nz::AbstractImage **********************************/ + abstractImage.Reset("AbstractImage"); + { + abstractImage.BindMethod("GetBytesPerPixel", &Nz::AbstractImage::GetBytesPerPixel); + abstractImage.BindMethod("GetDepth", &Nz::AbstractImage::GetDepth, static_cast(0)); + abstractImage.BindMethod("GetFormat", &Nz::AbstractImage::GetFormat); + abstractImage.BindMethod("GetHeight", &Nz::AbstractImage::GetHeight, static_cast(0)); + abstractImage.BindMethod("GetLevelCount", &Nz::AbstractImage::GetLevelCount); + abstractImage.BindMethod("GetMaxLevel", &Nz::AbstractImage::GetMaxLevel); + abstractImage.BindMethod("GetSize", &Nz::AbstractImage::GetSize, static_cast(0)); + abstractImage.BindMethod("GetType", &Nz::AbstractImage::GetType); + abstractImage.BindMethod("GetWidth", &Nz::AbstractImage::GetWidth, static_cast(0)); + abstractImage.BindMethod("IsCompressed", &Nz::AbstractImage::IsCompressed); + abstractImage.BindMethod("IsCubemap", &Nz::AbstractImage::IsCubemap); + + abstractImage.BindMethod("GetMemoryUsage", [] (Nz::LuaInstance& lua, Nz::AbstractImage* instance, std::size_t argumentCount) -> int + { + std::size_t argCount = std::min(argumentCount, 1U); + switch (argCount) + { + case 0: + return lua.Push(instance->GetMemoryUsage()); + + case 1: + { + int argIndex = 2; + Nz::UInt8 level(lua.Check(&argIndex)); + + return lua.Push(instance->GetMemoryUsage(level)); + } + } + + lua.Error("No matching overload for method GetMemoryUsage"); + return 0; + }); + + abstractImage.BindMethod("Update", [] (Nz::LuaInstance& lua, Nz::AbstractImage* instance, std::size_t argumentCount) -> int + { + std::size_t argCount = std::min(argumentCount, 6U); + int argIndex = 2; + + std::size_t bufferSize = 0; + const Nz::UInt8* pixels = reinterpret_cast(lua.CheckString(argIndex++, &bufferSize)); + + if (argCount < 2 || lua.IsOfType(2, Nz::LuaType_Number)) + { + // bool Update(const UInt8* pixels, unsigned int srcWidth = 0, unsigned int srcHeight = 0, UInt8 level = 0) + unsigned int srcWidth = lua.Check(&argIndex, 0); + unsigned int srcHeight = lua.Check(&argIndex, 0); + Nz::UInt8 level = lua.Check(&argIndex, 0); + + ///TODO: Buffer checks (Nz::ByteBufferView ?) + return lua.Push(instance->Update(pixels, srcWidth, srcHeight, level)); + } + /* Disabled until Box and Rect have been ported + else if (lua.IsOfType(2, "Box")) + { + // bool Update(const UInt8* pixels, const Boxui& box, unsigned int srcWidth = 0, unsigned int srcHeight = 0, UInt8 level = 0) + Nz::Boxui box = lua.Check(&argIndex); + unsigned int srcWidth = lua.Check(&argIndex, 0); + unsigned int srcHeight = lua.Check(&argIndex, 0); + Nz::UInt8 level = lua.Check(&argIndex, 0); + + ///TODO: Buffer checks (Nz::ByteBufferView ?) + return lua.Push(abstractImage->Update(pixels, srcWidth, srcHeight, level)); + } + else if (lua.IsOfType(2, "Rect")) + { + // bool Update(const UInt8* pixels, const Rectui& rect, unsigned int z = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0, UInt8 level = 0) + Nz::Rectui box = lua.Check(&argIndex); + unsigned int srcWidth = lua.Check(&argIndex, 0); + unsigned int srcHeight = lua.Check(&argIndex, 0); + Nz::UInt8 level = lua.Check(&argIndex, 0); + + ///TODO: Buffer checks (Nz::ByteBufferView ?) + return lua.Push(abstractImage->Update(pixels, srcWidth, srcHeight, level)); + }*/ + + lua.Error("No matching overload for method Update"); + return 0; + }); + } + + /*********************************** Nz::Font **********************************/ + font.Reset("Font"); + { + font.SetConstructor([] (Nz::LuaInstance& /*lua*/, Nz::FontRef* instance, std::size_t /*argumentCount*/) + { + Nz::PlacementNew(instance, Nz::Font::New()); + return true; + }); + + font.BindMethod("ClearGlyphCache", &Nz::Font::ClearGlyphCache); + font.BindMethod("ClearKerningCache", &Nz::Font::ClearKerningCache); + font.BindMethod("ClearSizeInfoCache", &Nz::Font::ClearSizeInfoCache); + + font.BindMethod("Destroy", &Nz::Font::Destroy); + + font.BindMethod("GetCachedGlyphCount", [] (Nz::LuaInstance& lua, Nz::FontRef& instance, std::size_t argumentCount) -> int + { + std::size_t argCount = std::min(argumentCount, 2U); + + int argIndex = 2; + switch (argCount) + { + case 0: + lua.Push(instance->GetCachedGlyphCount()); + return 1; + + case 2: + { + unsigned int characterSize = lua.Check(&argIndex); + Nz::UInt32 style = lua.Check(&argIndex); + + lua.Push(instance->GetCachedGlyphCount(characterSize, style)); + return 1; + } + } + + lua.Error("No matching overload for method GetCachedGlyphCount"); + return 0; + }); + + font.BindMethod("GetFamilyName", &Nz::Font::GetFamilyName); + font.BindMethod("GetKerning", &Nz::Font::GetKerning); + font.BindMethod("GetGlyphBorder", &Nz::Font::GetGlyphBorder); + font.BindMethod("GetMinimumStepSize", &Nz::Font::GetMinimumStepSize); + font.BindMethod("GetSizeInfo", &Nz::Font::GetSizeInfo); + font.BindMethod("GetStyleName", &Nz::Font::GetStyleName); + + font.BindMethod("IsValid", &Nz::Font::IsValid); + + font.BindMethod("Precache", (bool(Nz::Font::*)(unsigned int, Nz::UInt32, const Nz::String&) const) &Nz::Font::Precache); + + font.BindMethod("OpenFromFile", &Nz::Font::OpenFromFile, Nz::FontParams()); + + font.BindMethod("SetGlyphBorder", &Nz::Font::SetGlyphBorder); + font.BindMethod("SetMinimumStepSize", &Nz::Font::SetMinimumStepSize); + + font.BindStaticMethod("GetDefault", &Nz::Font::GetDefault); + font.BindStaticMethod("GetDefaultGlyphBorder", &Nz::Font::GetDefaultGlyphBorder); + font.BindStaticMethod("GetDefaultMinimumStepSize", &Nz::Font::GetDefaultMinimumStepSize); + + font.BindStaticMethod("SetDefaultGlyphBorder", &Nz::Font::SetDefaultGlyphBorder); + font.BindStaticMethod("SetDefaultMinimumStepSize", &Nz::Font::SetDefaultMinimumStepSize); + } + + /*********************************** Nz::Keyboard **********************************/ + keyboard.Reset("Keyboard"); + { + keyboard.BindStaticMethod("GetKeyName", &Nz::Keyboard::GetKeyName); + keyboard.BindStaticMethod("IsKeyPressed", &Nz::Keyboard::IsKeyPressed); + } + + /*********************************** Nz::Node **********************************/ + node.Reset("Node"); + { + node.BindMethod("GetBackward", &Nz::Node::GetBackward); + //nodeClass.SetMethod("GetChilds", &Nz::Node::GetChilds); + node.BindMethod("GetDown", &Nz::Node::GetDown); + node.BindMethod("GetForward", &Nz::Node::GetForward); + node.BindMethod("GetInheritPosition", &Nz::Node::GetInheritPosition); + node.BindMethod("GetInheritRotation", &Nz::Node::GetInheritRotation); + node.BindMethod("GetInheritScale", &Nz::Node::GetInheritScale); + node.BindMethod("GetInitialPosition", &Nz::Node::GetInitialPosition); + //nodeClass.SetMethod("GetInitialRotation", &Nz::Node::GetInitialRotation); + node.BindMethod("GetInitialScale", &Nz::Node::GetInitialScale); + node.BindMethod("GetLeft", &Nz::Node::GetLeft); + node.BindMethod("GetNodeType", &Nz::Node::GetNodeType); + //nodeClass.SetMethod("GetParent", &Nz::Node::GetParent); + node.BindMethod("GetPosition", &Nz::Node::GetPosition, Nz::CoordSys_Global); + node.BindMethod("GetRight", &Nz::Node::GetRight); + //nodeClass.SetMethod("GetRotation", &Nz::Node::GetRotation, Nz::CoordSys_Global); + node.BindMethod("GetScale", &Nz::Node::GetScale, Nz::CoordSys_Global); + //nodeClass.SetMethod("GetTransformMatrix", &Nz::Node::GetTransformMatrix); + node.BindMethod("GetUp", &Nz::Node::GetUp); + + node.BindMethod("HasChilds", &Nz::Node::HasChilds); + + node.BindMethod("GetBackward", &Nz::Node::GetBackward); + node.BindMethod("GetDown", &Nz::Node::GetDown); + node.BindMethod("GetForward", &Nz::Node::GetForward); + node.BindMethod("GetInheritPosition", &Nz::Node::GetInheritPosition); + node.BindMethod("GetInheritRotation", &Nz::Node::GetInheritRotation); + node.BindMethod("GetInheritScale", &Nz::Node::GetInheritScale); + node.BindMethod("GetInitialPosition", &Nz::Node::GetInitialPosition); + node.BindMethod("GetInitialRotation", &Nz::Node::GetInitialRotation); + node.BindMethod("GetInitialScale", &Nz::Node::GetInitialScale); + node.BindMethod("GetLeft", &Nz::Node::GetLeft); + node.BindMethod("GetNodeType", &Nz::Node::GetNodeType); + node.BindMethod("GetPosition", &Nz::Node::GetPosition, Nz::CoordSys_Global); + node.BindMethod("GetRight", &Nz::Node::GetRight); + node.BindMethod("GetRotation", &Nz::Node::GetRotation, Nz::CoordSys_Global); + node.BindMethod("GetScale", &Nz::Node::GetScale, Nz::CoordSys_Global); + node.BindMethod("GetUp", &Nz::Node::GetUp); + + node.BindMethod("SetInitialPosition", (void(Nz::Node::*)(const Nz::Vector3f&)) &Nz::Node::SetInitialPosition); + node.BindMethod("SetInitialRotation", (void(Nz::Node::*)(const Nz::Quaternionf&)) &Nz::Node::SetInitialRotation); + + node.BindMethod("SetPosition", (void(Nz::Node::*)(const Nz::Vector3f&, Nz::CoordSys)) &Nz::Node::SetPosition, Nz::CoordSys_Local); + node.BindMethod("SetRotation", (void(Nz::Node::*)(const Nz::Quaternionf&, Nz::CoordSys)) &Nz::Node::SetRotation, Nz::CoordSys_Local); + + node.BindMethod("Move", [] (Nz::LuaInstance& lua, Nz::Node& instance, std::size_t /*argumentCount*/) -> int + { + int argIndex = 2; + + Nz::Vector3f offset = lua.Check(&argIndex); + Nz::CoordSys coordSys = lua.Check(&argIndex, Nz::CoordSys_Local); + instance.Move(offset, coordSys); + + return 0; + }); + + node.BindMethod("Rotate", [] (Nz::LuaInstance& lua, Nz::Node& instance, std::size_t /*argumentCount*/) -> int + { + int argIndex = 2; + + Nz::Quaternionf rotation = lua.Check(&argIndex); + Nz::CoordSys coordSys = lua.Check(&argIndex, Nz::CoordSys_Local); + instance.Rotate(rotation, coordSys); + + return 0; + }); + + node.BindMethod("Scale", [] (Nz::LuaInstance& lua, Nz::Node& instance, std::size_t argumentCount) -> int + { + std::size_t argCount = std::min(argumentCount, 4U); + + int argIndex = 2; + switch (argCount) + { + case 1: + { + if (lua.IsOfType(argIndex, Nz::LuaType_Number)) + instance.Scale(lua.Check(&argIndex)); + else + instance.Scale(lua.Check(&argIndex)); + + return 0; + } + + case 3: + instance.Scale(lua.Check(&argIndex)); + return 0; + } + + lua.Error("No matching overload for method Scale"); + return 0; + }); + + node.BindMethod("SetScale", [] (Nz::LuaInstance& lua, Nz::Node& instance, std::size_t argumentCount) -> int + { + std::size_t argCount = std::min(argumentCount, 4U); + + int argIndex = 2; + switch (argCount) + { + case 1: + case 2: + { + if (lua.IsOfType(argIndex, Nz::LuaType_Number)) + { + float scale = lua.Check(&argIndex); + Nz::CoordSys coordSys = lua.Check(&argIndex, Nz::CoordSys_Local); + instance.SetScale(scale, coordSys); + } + else + instance.SetScale(lua.Check(&argIndex)); + + return 0; + } + + case 3: + case 4: + { + Nz::Vector3f scale = lua.Check(&argIndex); + Nz::CoordSys coordSys = lua.Check(&argIndex, Nz::CoordSys_Local); + + instance.SetScale(scale, coordSys); + return 0; + } + } + + lua.Error("No matching overload for method SetScale"); + return 0; + }); + + node.BindMethod("SetInitialScale", [] (Nz::LuaInstance& lua, Nz::Node& instance, std::size_t argumentCount) -> int + { + std::size_t argCount = std::min(argumentCount, 4U); + + int argIndex = 2; + switch (argCount) + { + case 1: + { + if (lua.IsOfType(argIndex, Nz::LuaType_Number)) + instance.SetInitialScale(lua.Check(&argIndex)); + else + instance.SetInitialScale(lua.Check(&argIndex)); + + return 0; + } + + case 2: + case 3: + instance.SetInitialScale(lua.Check(&argIndex)); + return 0; + } + + lua.Error("No matching overload for method SetInitialScale"); + return 0; + }); + } + } + + /*! + * \brief Registers the classes that will be used by the Lua instance + * + * \param instance Lua instance that will interact with the Utility classes + */ + void LuaBinding_Utility::Register(Nz::LuaInstance& instance) + { + abstractImage.Register(instance); + font.Register(instance); + keyboard.Register(instance); + node.Register(instance); + + keyboard.PushGlobalTable(instance); + { + static_assert(Nz::Keyboard::Count == 121, "Nz::Keyboard::Key has been updated but change was not reflected to Lua binding"); + + instance.PushField("Undefined", Nz::Keyboard::Undefined); + + // A-Z + for (std::size_t i = 0; i < 26; ++i) + instance.PushField(Nz::String('A' + char(i)), Nz::Keyboard::A + i); + + // Numerical + for (std::size_t i = 0; i < 10; ++i) + { + instance.PushField("Num" + Nz::String::Number(i), Nz::Keyboard::Num0 + i); + instance.PushField("Numpad" + Nz::String::Number(i), Nz::Keyboard::Numpad0 + i); + } + + // F1-F15 + for (std::size_t i = 0; i < 15; ++i) + instance.PushField('F' + Nz::String::Number(i+1), Nz::Keyboard::F1 + i); + + // And all the others... + instance.PushField("Down", Nz::Keyboard::Down); + instance.PushField("Left", Nz::Keyboard::Left); + instance.PushField("Right", Nz::Keyboard::Right); + instance.PushField("Up", Nz::Keyboard::Up); + + instance.PushField("Add", Nz::Keyboard::Add); + instance.PushField("Decimal", Nz::Keyboard::Decimal); + instance.PushField("Divide", Nz::Keyboard::Divide); + instance.PushField("Multiply", Nz::Keyboard::Multiply); + instance.PushField("Subtract", Nz::Keyboard::Subtract); + + instance.PushField("Backslash", Nz::Keyboard::Backslash); + instance.PushField("Backspace", Nz::Keyboard::Backspace); + instance.PushField("Clear", Nz::Keyboard::Clear); + instance.PushField("Comma", Nz::Keyboard::Comma); + instance.PushField("Dash", Nz::Keyboard::Dash); + instance.PushField("Delete", Nz::Keyboard::Delete); + instance.PushField("End", Nz::Keyboard::End); + instance.PushField("Equal", Nz::Keyboard::Equal); + instance.PushField("Escape", Nz::Keyboard::Escape); + instance.PushField("Home", Nz::Keyboard::Home); + instance.PushField("Insert", Nz::Keyboard::Insert); + instance.PushField("LAlt", Nz::Keyboard::LAlt); + instance.PushField("LBracket", Nz::Keyboard::LBracket); + instance.PushField("LControl", Nz::Keyboard::LControl); + instance.PushField("LShift", Nz::Keyboard::LShift); + instance.PushField("LSystem", Nz::Keyboard::LSystem); + instance.PushField("PageDown", Nz::Keyboard::PageDown); + instance.PushField("PageUp", Nz::Keyboard::PageUp); + instance.PushField("Pause", Nz::Keyboard::Pause); + instance.PushField("Period", Nz::Keyboard::Period); + instance.PushField("Print", Nz::Keyboard::Print); + instance.PushField("PrintScreen", Nz::Keyboard::PrintScreen); + instance.PushField("Quote", Nz::Keyboard::Quote); + instance.PushField("RAlt", Nz::Keyboard::RAlt); + instance.PushField("RBracket", Nz::Keyboard::RBracket); + instance.PushField("RControl", Nz::Keyboard::RControl); + instance.PushField("Return", Nz::Keyboard::Return); + instance.PushField("RShift", Nz::Keyboard::RShift); + instance.PushField("RSystem", Nz::Keyboard::RSystem); + instance.PushField("Semicolon", Nz::Keyboard::Semicolon); + instance.PushField("Slash", Nz::Keyboard::Slash); + instance.PushField("Space", Nz::Keyboard::Space); + instance.PushField("Tab", Nz::Keyboard::Tab); + instance.PushField("Tilde", Nz::Keyboard::Tilde); + instance.PushField("Browser_Back", Nz::Keyboard::Browser_Back); + instance.PushField("Browser_Favorites", Nz::Keyboard::Browser_Favorites); + instance.PushField("Browser_Forward", Nz::Keyboard::Browser_Forward); + instance.PushField("Browser_Home", Nz::Keyboard::Browser_Home); + instance.PushField("Browser_Refresh", Nz::Keyboard::Browser_Refresh); + instance.PushField("Browser_Search", Nz::Keyboard::Browser_Search); + instance.PushField("Browser_Stop", Nz::Keyboard::Browser_Stop); + instance.PushField("Media_Next", Nz::Keyboard::Media_Next); + instance.PushField("Media_Play", Nz::Keyboard::Media_Play); + instance.PushField("Media_Previous", Nz::Keyboard::Media_Previous); + instance.PushField("Media_Stop", Nz::Keyboard::Media_Stop); + instance.PushField("Volume_Down", Nz::Keyboard::Volume_Down); + instance.PushField("Volume_Mute", Nz::Keyboard::Volume_Mute); + instance.PushField("Volume_Up", Nz::Keyboard::Volume_Up); + instance.PushField("CapsLock", Nz::Keyboard::CapsLock); + instance.PushField("NumLock", Nz::Keyboard::NumLock); + instance.PushField("ScrollLock", Nz::Keyboard::ScrollLock); + } + instance.Pop(); + + static_assert(Nz::WindowStyle_Max + 1 == 6, "Nz::WindowStyle has been updated but change was not reflected to Lua binding"); + instance.PushTable(0, Nz::WindowStyle_Max + 1); + { + instance.PushField("None", Nz::WindowStyle_None); + instance.PushField("Fullscreen", Nz::WindowStyle_Fullscreen); + instance.PushField("Closable", Nz::WindowStyle_Closable); + instance.PushField("Resizable", Nz::WindowStyle_Resizable); + instance.PushField("Titlebar", Nz::WindowStyle_Titlebar); + instance.PushField("Threaded", Nz::WindowStyle_Threaded); + } + instance.SetGlobal("WindowStyle"); + + + } +} diff --git a/SDK/src/NDK/LuaAPI.cpp b/SDK/src/NDK/LuaAPI.cpp index fba28b2b3..a28fbb05f 100644 --- a/SDK/src/NDK/LuaAPI.cpp +++ b/SDK/src/NDK/LuaAPI.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include namespace Ndk { diff --git a/SDK/src/NDK/LuaBinding_Core.cpp b/SDK/src/NDK/LuaBinding_Core.cpp deleted file mode 100644 index 3108e1a52..000000000 --- a/SDK/src/NDK/LuaBinding_Core.cpp +++ /dev/null @@ -1,341 +0,0 @@ -// This file was automatically generated on 26 May 2014 at 01:05:31 - -#include -#include -#include - -namespace Ndk -{ - /*! - * \brief Binds Core module to Lua - */ - - void LuaBinding::BindCore() - { - /*********************************** Nz::Clock **********************************/ - clock.SetConstructor([](Nz::LuaInstance& lua, Nz::Clock* instance, std::size_t argumentCount) - { - std::size_t argCount = std::min(argumentCount, 2U); - - int argIndex = 2; - switch (argCount) - { - case 0: - Nz::PlacementNew(instance); - return true; - - case 1: - { - Nz::Int64 startingValue = lua.Check(&argIndex, 0); - - Nz::PlacementNew(instance, startingValue); - return true; - } - - case 2: - { - Nz::Int64 startingValue = lua.Check(&argIndex, 0); - bool paused = lua.Check(&argIndex, false); - - Nz::PlacementNew(instance, startingValue, paused); - return true; - } - } - - lua.Error("No matching overload for Clock constructor"); - return false; - }); - - clock.BindMethod("GetMicroseconds", &Nz::Clock::GetMicroseconds); - clock.BindMethod("GetMilliseconds", &Nz::Clock::GetMilliseconds); - clock.BindMethod("GetSeconds", &Nz::Clock::GetSeconds); - clock.BindMethod("IsPaused", &Nz::Clock::IsPaused); - clock.BindMethod("Pause", &Nz::Clock::Pause); - clock.BindMethod("Restart", &Nz::Clock::Restart); - clock.BindMethod("Unpause", &Nz::Clock::Unpause); - - // Manual - clock.BindMethod("__tostring", [] (Nz::LuaInstance& lua, Nz::Clock& instance, std::size_t /*argumentCount*/) -> int { - Nz::StringStream ss("Clock(Elapsed: "); - ss << instance.GetSeconds(); - ss << "s, Paused: "; - ss << instance.IsPaused(); - ss << ')'; - - lua.PushString(ss); - return 1; - }); - - /********************************* Nz::Directory ********************************/ - directory.SetConstructor([](Nz::LuaInstance& lua, Nz::Directory* instance, std::size_t argumentCount) - { - std::size_t argCount = std::min(argumentCount, 1U); - - int argIndex = 2; - switch (argCount) - { - case 0: - Nz::PlacementNew(instance); - return true; - - case 1: - Nz::PlacementNew(instance, lua.Check(&argIndex)); - return true; - } - - return false; - }); - - directory.BindMethod("Close", &Nz::Directory::Close); - directory.BindMethod("Exists", &Nz::Directory::Exists); - directory.BindMethod("GetPath", &Nz::Directory::GetPath); - directory.BindMethod("GetPattern", &Nz::Directory::GetPattern); - directory.BindMethod("GetResultName", &Nz::Directory::GetResultName); - directory.BindMethod("GetResultPath", &Nz::Directory::GetResultPath); - directory.BindMethod("GetResultSize", &Nz::Directory::GetResultSize); - directory.BindMethod("IsOpen", &Nz::Directory::IsOpen); - directory.BindMethod("IsResultDirectory", &Nz::Directory::IsResultDirectory); - directory.BindMethod("NextResult", &Nz::Directory::NextResult, true); - directory.BindMethod("Open", &Nz::Directory::Open); - directory.BindMethod("SetPath", &Nz::Directory::SetPath); - directory.BindMethod("SetPattern", &Nz::Directory::SetPattern); - - directory.BindStaticMethod("Copy", Nz::Directory::Copy); - directory.BindStaticMethod("Create", Nz::Directory::Create); - directory.BindStaticMethod("Exists", Nz::Directory::Exists); - directory.BindStaticMethod("GetCurrent", Nz::Directory::GetCurrent); - directory.BindStaticMethod("Remove", Nz::Directory::Remove); - directory.BindStaticMethod("SetCurrent", Nz::Directory::SetCurrent); - - // Manual - directory.BindMethod("__tostring", [] (Nz::LuaInstance& lua, Nz::Directory& instance, std::size_t /*argumentCount*/) -> int { - Nz::StringStream ss("Directory("); - ss << instance.GetPath(); - ss << ')'; - - lua.PushString(ss); - return 1; - }); - - /*********************************** Nz::Stream ***********************************/ - stream.BindMethod("EnableTextMode", &Nz::Stream::EnableTextMode); - stream.BindMethod("Flush", &Nz::Stream::Flush); - stream.BindMethod("GetCursorPos", &Nz::Stream::GetCursorPos); - stream.BindMethod("GetDirectory", &Nz::Stream::GetDirectory); - stream.BindMethod("GetPath", &Nz::Stream::GetPath); - stream.BindMethod("GetOpenMode", &Nz::Stream::GetOpenMode); - stream.BindMethod("GetStreamOptions", &Nz::Stream::GetStreamOptions); - stream.BindMethod("GetSize", &Nz::Stream::GetSize); - stream.BindMethod("ReadLine", &Nz::Stream::ReadLine, 0U); - stream.BindMethod("IsReadable", &Nz::Stream::IsReadable); - stream.BindMethod("IsSequential", &Nz::Stream::IsSequential); - stream.BindMethod("IsTextModeEnabled", &Nz::Stream::IsTextModeEnabled); - stream.BindMethod("IsWritable", &Nz::Stream::IsWritable); - stream.BindMethod("SetCursorPos", &Nz::Stream::SetCursorPos); - - stream.BindMethod("Read", [] (Nz::LuaInstance& lua, Nz::Stream& instance, std::size_t /*argumentCount*/) -> int { - int argIndex = 2; - - std::size_t length = lua.Check(&argIndex); - - std::unique_ptr buffer(new char[length]); - std::size_t readLength = instance.Read(buffer.get(), length); - - lua.PushString(Nz::String(buffer.get(), readLength)); - return 1; - }); - - stream.BindMethod("Write", [] (Nz::LuaInstance& lua, Nz::Stream& instance, std::size_t /*argumentCount*/) -> int { - int argIndex = 2; - - std::size_t bufferSize = 0; - const char* buffer = lua.CheckString(argIndex, &bufferSize); - - if (instance.IsTextModeEnabled()) - lua.Push(instance.Write(Nz::String(buffer, bufferSize))); - else - lua.Push(instance.Write(buffer, bufferSize)); - return 1; - }); - - /*********************************** Nz::File ***********************************/ - file.Inherit(stream); - - file.SetConstructor([] (Nz::LuaInstance& lua, Nz::File* instance, std::size_t argumentCount) - { - std::size_t argCount = std::min(argumentCount, 1U); - - int argIndex = 2; - switch (argCount) - { - case 0: - Nz::PlacementNew(instance); - return true; - - case 1: - { - Nz::String filePath = lua.Check(&argIndex); - - Nz::PlacementNew(instance, filePath); - return true; - } - - case 2: - { - Nz::String filePath = lua.Check(&argIndex); - Nz::UInt32 openMode = lua.Check(&argIndex); - - Nz::PlacementNew(instance, filePath, openMode); - return true; - } - } - - lua.Error("No matching overload for File constructor"); - return false; - }); - - file.BindMethod("Close", &Nz::File::Close); - file.BindMethod("Copy", &Nz::File::Copy); - file.BindMethod("Delete", &Nz::File::Delete); - file.BindMethod("EndOfFile", &Nz::File::EndOfFile); - file.BindMethod("Exists", &Nz::File::Exists); - file.BindMethod("GetCreationTime", &Nz::File::GetCreationTime); - file.BindMethod("GetFileName", &Nz::File::GetFileName); - file.BindMethod("GetLastAccessTime", &Nz::File::GetLastAccessTime); - file.BindMethod("GetLastWriteTime", &Nz::File::GetLastWriteTime); - file.BindMethod("IsOpen", &Nz::File::IsOpen); - file.BindMethod("Rename", &Nz::File::GetLastWriteTime); - file.BindMethod("GetLastWriteTime", &Nz::File::GetLastWriteTime); - file.BindMethod("SetFile", &Nz::File::GetLastWriteTime); - - file.BindStaticMethod("AbsolutePath", &Nz::File::AbsolutePath); - file.BindStaticMethod("ComputeHash", (Nz::ByteArray (*)(Nz::HashType, const Nz::String&)) &Nz::File::ComputeHash); - file.BindStaticMethod("Copy", &Nz::File::Copy); - file.BindStaticMethod("Delete", &Nz::File::Delete); - file.BindStaticMethod("Exists", &Nz::File::Exists); - //fileClass.SetStaticMethod("GetCreationTime", &Nz::File::GetCreationTime); - file.BindStaticMethod("GetDirectory", &Nz::File::GetDirectory); - //fileClass.SetStaticMethod("GetLastAccessTime", &Nz::File::GetLastAccessTime); - //fileClass.SetStaticMethod("GetLastWriteTime", &Nz::File::GetLastWriteTime); - file.BindStaticMethod("GetSize", &Nz::File::GetSize); - file.BindStaticMethod("IsAbsolute", &Nz::File::IsAbsolute); - file.BindStaticMethod("NormalizePath", &Nz::File::NormalizePath); - file.BindStaticMethod("NormalizeSeparators", &Nz::File::NormalizeSeparators); - file.BindStaticMethod("Rename", &Nz::File::Rename); - - // Manual - file.BindMethod("Open", [] (Nz::LuaInstance& lua, Nz::File& instance, std::size_t argumentCount) -> int - { - std::size_t argCount = std::min(argumentCount, 2U); - - int argIndex = 2; - switch (argCount) - { - case 0: - case 1: - return lua.Push(instance.Open(lua.Check(&argIndex, Nz::OpenMode_NotOpen))); - - case 2: - { - Nz::String filePath = lua.Check(&argIndex); - Nz::UInt32 openMode = lua.Check(&argIndex, Nz::OpenMode_NotOpen); - return lua.Push(instance.Open(filePath, openMode)); - } - } - - lua.Error("No matching overload for method Open"); - return 0; - }); - - file.BindMethod("SetCursorPos", [] (Nz::LuaInstance& lua, Nz::File& instance, std::size_t argumentCount) -> int - { - std::size_t argCount = std::min(argumentCount, 2U); - - int argIndex = 2; - switch (argCount) - { - case 1: - return lua.Push(instance.SetCursorPos(lua.Check(&argIndex))); - - case 2: - { - Nz::CursorPosition curPos = lua.Check(&argIndex); - Nz::Int64 offset = lua.Check(&argIndex); - return lua.Push(instance.SetCursorPos(curPos, offset)); - } - } - - lua.Error("No matching overload for method SetCursorPos"); - return 0; - }); - - file.BindMethod("__tostring", [] (Nz::LuaInstance& lua, Nz::File& instance, std::size_t /*argumentCount*/) -> int { - Nz::StringStream ss("File("); - if (instance.IsOpen()) - ss << "Path: " << instance.GetPath(); - - ss << ')'; - - lua.PushString(ss); - return 1; - }); - } - - /*! - * \brief Registers the classes that will be used by the Lua instance - * - * \param instance Lua instance that will interact with the Core classes - */ - - void LuaBinding::RegisterCore(Nz::LuaInstance& instance) - { - // Classes - clock.Register(instance); - directory.Register(instance); - file.Register(instance); - stream.Register(instance); - - // Enums - - // Nz::CursorPosition - static_assert(Nz::CursorPosition_Max + 1 == 3, "Nz::CursorPosition has been updated but change was not reflected to Lua binding"); - instance.PushTable(0, 3); - { - instance.PushField("AtBegin", Nz::CursorPosition_AtBegin); - instance.PushField("AtCurrent", Nz::CursorPosition_AtCurrent); - instance.PushField("AtEnd", Nz::CursorPosition_AtEnd); - } - instance.SetGlobal("CursorPosition"); - - // Nz::HashType - static_assert(Nz::HashType_Max + 1 == 9, "Nz::HashType has been updated but change was not reflected to Lua binding"); - instance.PushTable(0, 9); - { - instance.PushField("CRC32", Nz::HashType_CRC32); - instance.PushField("Fletcher16", Nz::HashType_Fletcher16); - instance.PushField("MD5", Nz::HashType_MD5); - instance.PushField("SHA1", Nz::HashType_SHA1); - instance.PushField("SHA224", Nz::HashType_SHA224); - instance.PushField("SHA256", Nz::HashType_SHA256); - instance.PushField("SHA384", Nz::HashType_SHA384); - instance.PushField("SHA512", Nz::HashType_SHA512); - instance.PushField("Whirlpool", Nz::HashType_Whirlpool); - } - instance.SetGlobal("HashType"); - - // Nz::OpenMode - static_assert(Nz::OpenMode_Max + 1 == 2 * (64), "Nz::OpenModeFlags has been updated but change was not reflected to Lua binding"); - instance.PushTable(0, 8); - { - instance.PushField("Append", Nz::OpenMode_Append); - instance.PushField("NotOpen", Nz::OpenMode_NotOpen); - instance.PushField("Lock", Nz::OpenMode_Lock); - instance.PushField("ReadOnly", Nz::OpenMode_ReadOnly); - instance.PushField("ReadWrite", Nz::OpenMode_ReadWrite); - instance.PushField("Text", Nz::OpenMode_Text); - instance.PushField("Truncate", Nz::OpenMode_Truncate); - instance.PushField("WriteOnly", Nz::OpenMode_WriteOnly); - } - instance.SetGlobal("OpenMode"); - } -} diff --git a/SDK/src/NDK/LuaBinding_Graphics.cpp b/SDK/src/NDK/LuaBinding_Graphics.cpp deleted file mode 100644 index cdee66636..000000000 --- a/SDK/src/NDK/LuaBinding_Graphics.cpp +++ /dev/null @@ -1,371 +0,0 @@ -// This file is part of the "Nazara Development Kit" -// For conditions of distribution and use, see copyright notice in Prerequesites.hpp - -#include -#include - -namespace Ndk -{ - /*! - * \brief Binds Graphics module to Lua - */ - - void LuaBinding::BindGraphics() - { - /*********************************** Nz::AbstractViewer ***********************************/ - abstractViewer.BindMethod("GetAspectRatio", &Nz::AbstractViewer::GetAspectRatio); - abstractViewer.BindMethod("GetEyePosition", &Nz::AbstractViewer::GetEyePosition); - abstractViewer.BindMethod("GetForward", &Nz::AbstractViewer::GetForward); - //abstractViewer.BindMethod("GetFrustum", &Nz::AbstractViewer::GetFrustum); - abstractViewer.BindMethod("GetProjectionMatrix", &Nz::AbstractViewer::GetProjectionMatrix); - //abstractViewer.BindMethod("GetTarget", &Nz::AbstractViewer::GetTarget); - abstractViewer.BindMethod("GetViewMatrix", &Nz::AbstractViewer::GetViewMatrix); - abstractViewer.BindMethod("GetViewport", &Nz::AbstractViewer::GetViewport); - abstractViewer.BindMethod("GetZFar", &Nz::AbstractViewer::GetZFar); - abstractViewer.BindMethod("GetZNear", &Nz::AbstractViewer::GetZNear); - - /*********************************** Nz::InstancedRenderable ***********************************/ - - /*********************************** Nz::Material ***********************************/ - material.SetConstructor([] (Nz::LuaInstance& lua, Nz::MaterialRef* instance, std::size_t argumentCount) - { - switch (argumentCount) - { - case 0: - Nz::PlacementNew(instance, Nz::Material::New()); - return true; - - case 1: - { - int argIndex = 1; - if (lua.IsOfType(argIndex, "MaterialPipeline")) - { - Nz::PlacementNew(instance, Nz::Material::New(*static_cast(lua.ToUserdata(argIndex)))); - return true; - } - else if (lua.IsOfType(argIndex, "Material")) - { - Nz::PlacementNew(instance, Nz::Material::New(**static_cast(lua.ToUserdata(argIndex)))); - return true; - } - else - { - Nz::PlacementNew(instance, Nz::Material::New(lua.Check(&argIndex))); - return true; - } - } - } - - lua.Error("No matching overload for constructor"); - return false; - }); - - material.BindMethod("Configure", [] (Nz::LuaInstance& lua, Nz::MaterialRef& instance, std::size_t /*argumentCount*/) -> int - { - int argIndex = 2; - if (lua.IsOfType(argIndex, "MaterialPipeline")) - { - instance->Configure(*static_cast(lua.ToUserdata(argIndex))); - return 0; - } - else - { - lua.Push(instance->Configure(lua.Check(&argIndex))); - return 1; - } - }); - - material.BindMethod("EnableAlphaTest", &Nz::Material::EnableAlphaTest); - material.BindMethod("EnableBlending", &Nz::Material::EnableBlending); - material.BindMethod("EnableColorWrite", &Nz::Material::EnableColorWrite); - material.BindMethod("EnableDepthBuffer", &Nz::Material::EnableDepthBuffer); - material.BindMethod("EnableDepthSorting", &Nz::Material::EnableDepthSorting); - material.BindMethod("EnableDepthWrite", &Nz::Material::EnableDepthWrite); - material.BindMethod("EnableFaceCulling", &Nz::Material::EnableFaceCulling); - material.BindMethod("EnableScissorTest", &Nz::Material::EnableScissorTest); - material.BindMethod("EnableShadowCasting", &Nz::Material::EnableShadowCasting); - material.BindMethod("EnableShadowReceive", &Nz::Material::EnableShadowReceive); - material.BindMethod("EnableStencilTest", &Nz::Material::EnableStencilTest); - - material.BindMethod("EnsurePipelineUpdate", &Nz::Material::EnsurePipelineUpdate); - - material.BindMethod("GetAlphaMap", &Nz::Material::GetAlphaMap); - material.BindMethod("GetAlphaThreshold", &Nz::Material::GetAlphaThreshold); - material.BindMethod("GetAmbientColor", &Nz::Material::GetAmbientColor); - material.BindMethod("GetDepthFunc", &Nz::Material::GetDepthFunc); - material.BindMethod("GetDepthMaterial", &Nz::Material::GetDepthMaterial); - material.BindMethod("GetDiffuseColor", &Nz::Material::GetDiffuseColor); - material.BindMethod("GetDiffuseMap", &Nz::Material::GetDiffuseMap); - //material.BindMethod("GetDiffuseSampler", &Nz::Material::GetDiffuseSampler); - material.BindMethod("GetDstBlend", &Nz::Material::GetDstBlend); - material.BindMethod("GetEmissiveMap", &Nz::Material::GetEmissiveMap); - material.BindMethod("GetFaceCulling", &Nz::Material::GetFaceCulling); - material.BindMethod("GetFaceFilling", &Nz::Material::GetFaceFilling); - material.BindMethod("GetHeightMap", &Nz::Material::GetHeightMap); - material.BindMethod("GetLineWidth", &Nz::Material::GetLineWidth); - material.BindMethod("GetNormalMap", &Nz::Material::GetNormalMap); - //material.BindMethod("GetPipeline", &Nz::Material::GetPipeline); - //material.BindMethod("GetPipelineInfo", &Nz::Material::GetPipelineInfo); - material.BindMethod("GetPointSize", &Nz::Material::GetPointSize); - //material.BindMethod("GetShader", &Nz::Material::GetShader); - material.BindMethod("GetShininess", &Nz::Material::GetShininess); - material.BindMethod("GetSpecularColor", &Nz::Material::GetSpecularColor); - material.BindMethod("GetSpecularMap", &Nz::Material::GetSpecularMap); - //material.BindMethod("GetSpecularSampler", &Nz::Material::GetSpecularSampler); - material.BindMethod("GetSrcBlend", &Nz::Material::GetSrcBlend); - - material.BindMethod("HasAlphaMap", &Nz::Material::HasAlphaMap); - material.BindMethod("HasDepthMaterial", &Nz::Material::HasDepthMaterial); - material.BindMethod("HasDiffuseMap", &Nz::Material::HasDiffuseMap); - material.BindMethod("HasEmissiveMap", &Nz::Material::HasEmissiveMap); - material.BindMethod("HasHeightMap", &Nz::Material::HasHeightMap); - material.BindMethod("HasNormalMap", &Nz::Material::HasNormalMap); - material.BindMethod("HasSpecularMap", &Nz::Material::HasSpecularMap); - - material.BindMethod("IsAlphaTestEnabled", &Nz::Material::IsAlphaTestEnabled); - material.BindMethod("IsBlendingEnabled", &Nz::Material::IsBlendingEnabled); - material.BindMethod("IsColorWriteEnabled", &Nz::Material::IsColorWriteEnabled); - material.BindMethod("IsDepthBufferEnabled", &Nz::Material::IsDepthBufferEnabled); - material.BindMethod("IsDepthSortingEnabled", &Nz::Material::IsDepthSortingEnabled); - material.BindMethod("IsDepthWriteEnabled", &Nz::Material::IsDepthWriteEnabled); - material.BindMethod("IsFaceCullingEnabled", &Nz::Material::IsFaceCullingEnabled); - material.BindMethod("IsScissorTestEnabled", &Nz::Material::IsScissorTestEnabled); - material.BindMethod("IsStencilTestEnabled", &Nz::Material::IsStencilTestEnabled); - material.BindMethod("IsShadowCastingEnabled", &Nz::Material::IsShadowCastingEnabled); - material.BindMethod("IsShadowReceiveEnabled", &Nz::Material::IsShadowReceiveEnabled); - - material.BindMethod("LoadFromFile", &Nz::Material::LoadFromFile, Nz::MaterialParams()); - - material.BindMethod("Reset", &Nz::Material::Reset); - - material.BindMethod("SetAlphaThreshold", &Nz::Material::SetAlphaThreshold); - material.BindMethod("SetAmbientColor", &Nz::Material::SetAmbientColor); - material.BindMethod("SetDepthFunc", &Nz::Material::SetDepthFunc); - material.BindMethod("SetDepthFunc", &Nz::Material::SetDepthFunc); - material.BindMethod("SetDepthMaterial", &Nz::Material::SetDepthMaterial); - material.BindMethod("SetDiffuseColor", &Nz::Material::SetDiffuseColor); - //material.BindMethod("SetDiffuseSampler", &Nz::Material::SetDiffuseSampler); - material.BindMethod("SetDstBlend", &Nz::Material::SetDstBlend); - material.BindMethod("SetFaceCulling", &Nz::Material::SetFaceCulling); - material.BindMethod("SetFaceFilling", &Nz::Material::SetFaceFilling); - material.BindMethod("SetLineWidth", &Nz::Material::SetLineWidth); - material.BindMethod("SetPointSize", &Nz::Material::SetPointSize); - material.BindMethod("SetShininess", &Nz::Material::SetShininess); - material.BindMethod("SetSpecularColor", &Nz::Material::SetSpecularColor); - material.BindMethod("SetSpecularColor", &Nz::Material::SetSpecularColor); - //material.BindMethod("SetSpecularSampler", &Nz::Material::SetSpecularSampler); - material.BindMethod("SetSrcBlend", &Nz::Material::SetSrcBlend); - - material.BindStaticMethod("GetDefault", &Nz::Material::GetDefault); - - material.BindMethod("SetAlphaMap", [] (Nz::LuaInstance& lua, Nz::MaterialRef& instance, std::size_t /*argumentCount*/) -> int - { - int argIndex = 2; - if (lua.IsOfType(argIndex, "Texture")) - { - instance->SetAlphaMap(*static_cast(lua.ToUserdata(argIndex))); - return 0; - } - else - return lua.Push(instance->SetAlphaMap(lua.Check(&argIndex))); - }); - - material.BindMethod("SetDiffuseMap", [] (Nz::LuaInstance& lua, Nz::MaterialRef& instance, std::size_t /*argumentCount*/) -> int - { - int argIndex = 2; - if (lua.IsOfType(argIndex, "Texture")) - { - instance->SetDiffuseMap(*static_cast(lua.ToUserdata(argIndex))); - return 0; - } - else - return lua.Push(instance->SetDiffuseMap(lua.Check(&argIndex))); - }); - - material.BindMethod("SetEmissiveMap", [] (Nz::LuaInstance& lua, Nz::MaterialRef& instance, std::size_t /*argumentCount*/) -> int - { - int argIndex = 2; - if (lua.IsOfType(argIndex, "Texture")) - { - instance->SetEmissiveMap(*static_cast(lua.ToUserdata(argIndex))); - return 0; - } - else - return lua.Push(instance->SetEmissiveMap(lua.Check(&argIndex))); - }); - - material.BindMethod("SetHeightMap", [] (Nz::LuaInstance& lua, Nz::MaterialRef& instance, std::size_t /*argumentCount*/) -> int - { - int argIndex = 2; - if (lua.IsOfType(argIndex, "Texture")) - { - instance->SetHeightMap(*static_cast(lua.ToUserdata(argIndex))); - return 0; - } - else - return lua.Push(instance->SetHeightMap(lua.Check(&argIndex))); - }); - - material.BindMethod("SetNormalMap", [] (Nz::LuaInstance& lua, Nz::MaterialRef& instance, std::size_t /*argumentCount*/) -> int - { - int argIndex = 2; - if (lua.IsOfType(argIndex, "Texture")) - { - instance->SetNormalMap(*static_cast(lua.ToUserdata(argIndex))); - return 0; - } - else - return lua.Push(instance->SetNormalMap(lua.Check(&argIndex))); - }); - - material.BindMethod("SetShader", [] (Nz::LuaInstance& lua, Nz::MaterialRef& instance, std::size_t /*argumentCount*/) -> int - { - int argIndex = 2; - if (lua.IsOfType(argIndex, "UberShader")) - { - instance->SetShader(*static_cast(lua.ToUserdata(argIndex))); - return 0; - } - else - return lua.Push(instance->SetShader(lua.Check(&argIndex))); - }); - - material.BindMethod("SetSpecularMap", [] (Nz::LuaInstance& lua, Nz::MaterialRef& instance, std::size_t /*argumentCount*/) -> int - { - int argIndex = 2; - if (lua.IsOfType(argIndex, "Texture")) - { - instance->SetSpecularMap(*static_cast(lua.ToUserdata(argIndex))); - return 0; - } - else - return lua.Push(instance->SetSpecularMap(lua.Check(&argIndex))); - }); - - /*********************************** Nz::Model ***********************************/ - model.Inherit(instancedRenderable, [] (Nz::ModelRef* modelRef) -> Nz::InstancedRenderableRef* - { - return reinterpret_cast(modelRef); //TODO: Make a ObjectRefCast - }); - - model.SetConstructor([] (Nz::LuaInstance& /*lua*/, Nz::ModelRef* instance, std::size_t /*argumentCount*/) - { - Nz::PlacementNew(instance, Nz::Model::New()); - return true; - }); - - //model.BindMethod("GetMaterial", &Nz::Model::GetMaterial); - model.BindMethod("GetMaterialCount", &Nz::Model::GetMaterialCount); - //modelClass.SetMethod("GetMesh", &Nz::Model::GetMesh); - model.BindMethod("GetSkin", &Nz::Model::GetSkin); - model.BindMethod("GetSkinCount", &Nz::Model::GetSkinCount); - - model.BindMethod("IsAnimated", &Nz::Model::IsAnimated); - model.BindMethod("LoadFromFile", &Nz::Model::LoadFromFile, Nz::ModelParameters()); - - model.BindMethod("Reset", &Nz::Model::Reset); - - //model.BindMethod("SetMaterial", &Nz::Model::SetMaterial); - //modelClass.SetMethod("SetMesh", &Nz::Model::SetMesh); - //modelClass.SetMethod("SetSequence", &Nz::Model::SetSequence); - model.BindMethod("SetSkin", &Nz::Model::SetSkin); - model.BindMethod("SetSkinCount", &Nz::Model::SetSkinCount); - - /*********************************** Nz::Sprite ***********************************/ - sprite.Inherit(instancedRenderable, [] (Nz::SpriteRef* spriteRef) -> Nz::InstancedRenderableRef* - { - return reinterpret_cast(spriteRef); //TODO: Make a ObjectRefCast - }); - - sprite.SetConstructor([] (Nz::LuaInstance& /*lua*/, Nz::SpriteRef* instance, std::size_t /*argumentCount*/) - { - Nz::PlacementNew(instance, Nz::Sprite::New()); - return true; - }); - - sprite.BindMethod("GetColor", &Nz::Sprite::GetColor); - sprite.BindMethod("GetCornerColor", &Nz::Sprite::GetCornerColor); - sprite.BindMethod("GetMaterial", &Nz::Sprite::GetMaterial); - sprite.BindMethod("GetOrigin", &Nz::Sprite::GetOrigin); - sprite.BindMethod("GetSize", &Nz::Sprite::GetSize); - sprite.BindMethod("GetTextureCoords", &Nz::Sprite::GetTextureCoords); - - sprite.BindMethod("SetColor", &Nz::Sprite::SetColor); - sprite.BindMethod("SetCornerColor", &Nz::Sprite::SetCornerColor); - sprite.BindMethod("SetDefaultMaterial", &Nz::Sprite::SetDefaultMaterial); - sprite.BindMethod("SetOrigin", &Nz::Sprite::SetOrigin); - sprite.BindMethod("SetSize", (void(Nz::Sprite::*)(const Nz::Vector2f&)) &Nz::Sprite::SetSize); - sprite.BindMethod("SetTextureCoords", &Nz::Sprite::SetTextureCoords); - sprite.BindMethod("SetTextureRect", &Nz::Sprite::SetTextureRect); - - sprite.BindMethod("SetMaterial", [] (Nz::LuaInstance& lua, Nz::SpriteRef& instance, std::size_t /*argumentCount*/) -> int - { - int argIndex = 2; - bool resizeSprite = lua.CheckBoolean(argIndex + 1, true); - - if (lua.IsOfType(argIndex, "Material")) - instance->SetMaterial(*static_cast(lua.ToUserdata(argIndex)), resizeSprite); - else - instance->SetMaterial(lua.Check(&argIndex), resizeSprite); - - return 0; - }); - - sprite.BindMethod("SetTexture", [] (Nz::LuaInstance& lua, Nz::SpriteRef& instance, std::size_t /*argumentCount*/) -> int - { - int argIndex = 2; - bool resizeSprite = lua.CheckBoolean(argIndex + 1, true); - - if (lua.IsOfType(argIndex, "Texture")) - instance->SetTexture(*static_cast(lua.ToUserdata(argIndex)), resizeSprite); - else - instance->SetTexture(lua.Check(&argIndex), resizeSprite); - - return 0; - }); - - /*********************************** Nz::SpriteLibrary ***********************************/ - - spriteLibrary.BindStaticMethod("Get", &Nz::SpriteLibrary::Get); - spriteLibrary.BindStaticMethod("Has", &Nz::SpriteLibrary::Has); - spriteLibrary.BindStaticMethod("Register", &Nz::SpriteLibrary::Register); - spriteLibrary.BindStaticMethod("Query", &Nz::SpriteLibrary::Query); - spriteLibrary.BindStaticMethod("Unregister", &Nz::SpriteLibrary::Unregister); - - /*********************************** Nz::TextureLibrary ***********************************/ - - textureLibrary.BindStaticMethod("Get", &Nz::TextureLibrary::Get); - textureLibrary.BindStaticMethod("Has", &Nz::TextureLibrary::Has); - textureLibrary.BindStaticMethod("Register", &Nz::TextureLibrary::Register); - textureLibrary.BindStaticMethod("Query", &Nz::TextureLibrary::Query); - textureLibrary.BindStaticMethod("Unregister", &Nz::TextureLibrary::Unregister); - - /*********************************** Nz::TextureManager ***********************************/ - - textureManager.BindStaticMethod("Clear", &Nz::TextureManager::Clear); - textureManager.BindStaticMethod("Get", &Nz::TextureManager::Get); - textureManager.BindStaticMethod("GetDefaultParameters", &Nz::TextureManager::GetDefaultParameters); - textureManager.BindStaticMethod("Purge", &Nz::TextureManager::Purge); - textureManager.BindStaticMethod("Register", &Nz::TextureManager::Register); - textureManager.BindStaticMethod("SetDefaultParameters", &Nz::TextureManager::SetDefaultParameters); - textureManager.BindStaticMethod("Unregister", &Nz::TextureManager::Unregister); - } - - /*! - * \brief Registers the classes that will be used by the Lua instance - * - * \param instance Lua instance that will interact with the Graphics classes - */ - - void LuaBinding::RegisterGraphics(Nz::LuaInstance& instance) - { - abstractViewer.Register(instance); - instancedRenderable.Register(instance); - material.Register(instance); - model.Register(instance); - sprite.Register(instance); - spriteLibrary.Register(instance); - textureLibrary.Register(instance); - textureManager.Register(instance); - } -} diff --git a/SDK/src/NDK/LuaBinding_Utility.cpp b/SDK/src/NDK/LuaBinding_Utility.cpp deleted file mode 100644 index 686182410..000000000 --- a/SDK/src/NDK/LuaBinding_Utility.cpp +++ /dev/null @@ -1,417 +0,0 @@ -// This file is part of the "Nazara Development Kit" -// For conditions of distribution and use, see copyright notice in Prerequesites.hpp - -#include -#include - -namespace Ndk -{ - /*! - * \brief Binds Utility module to Lua - */ - - void LuaBinding::BindUtility() - { - /*********************************** Nz::AbstractImage **********************************/ - abstractImage.BindMethod("GetBytesPerPixel", &Nz::AbstractImage::GetBytesPerPixel); - abstractImage.BindMethod("GetDepth", &Nz::AbstractImage::GetDepth, static_cast(0)); - abstractImage.BindMethod("GetFormat", &Nz::AbstractImage::GetFormat); - abstractImage.BindMethod("GetHeight", &Nz::AbstractImage::GetHeight, static_cast(0)); - abstractImage.BindMethod("GetLevelCount", &Nz::AbstractImage::GetLevelCount); - abstractImage.BindMethod("GetMaxLevel", &Nz::AbstractImage::GetMaxLevel); - abstractImage.BindMethod("GetSize", &Nz::AbstractImage::GetSize, static_cast(0)); - abstractImage.BindMethod("GetType", &Nz::AbstractImage::GetType); - abstractImage.BindMethod("GetWidth", &Nz::AbstractImage::GetWidth, static_cast(0)); - abstractImage.BindMethod("IsCompressed", &Nz::AbstractImage::IsCompressed); - abstractImage.BindMethod("IsCubemap", &Nz::AbstractImage::IsCubemap); - - abstractImage.BindMethod("GetMemoryUsage", [] (Nz::LuaInstance& lua, Nz::AbstractImage* instance, std::size_t argumentCount) -> int - { - std::size_t argCount = std::min(argumentCount, 1U); - switch (argCount) - { - case 0: - return lua.Push(instance->GetMemoryUsage()); - - case 1: - { - int argIndex = 2; - Nz::UInt8 level(lua.Check(&argIndex)); - - return lua.Push(instance->GetMemoryUsage(level)); - } - } - - lua.Error("No matching overload for method GetMemoryUsage"); - return 0; - }); - - abstractImage.BindMethod("Update", [] (Nz::LuaInstance& lua, Nz::AbstractImage* instance, std::size_t argumentCount) -> int - { - std::size_t argCount = std::min(argumentCount, 6U); - int argIndex = 2; - - std::size_t bufferSize = 0; - const Nz::UInt8* pixels = reinterpret_cast(lua.CheckString(argIndex++, &bufferSize)); - - if (argCount < 2 || lua.IsOfType(2, Nz::LuaType_Number)) - { - // bool Update(const UInt8* pixels, unsigned int srcWidth = 0, unsigned int srcHeight = 0, UInt8 level = 0) - unsigned int srcWidth = lua.Check(&argIndex, 0); - unsigned int srcHeight = lua.Check(&argIndex, 0); - Nz::UInt8 level = lua.Check(&argIndex, 0); - - ///TODO: Buffer checks (Nz::ByteBufferView ?) - return lua.Push(instance->Update(pixels, srcWidth, srcHeight, level)); - } - /* Disabled until Box and Rect have been ported - else if (lua.IsOfType(2, "Box")) - { - // bool Update(const UInt8* pixels, const Boxui& box, unsigned int srcWidth = 0, unsigned int srcHeight = 0, UInt8 level = 0) - Nz::Boxui box = lua.Check(&argIndex); - unsigned int srcWidth = lua.Check(&argIndex, 0); - unsigned int srcHeight = lua.Check(&argIndex, 0); - Nz::UInt8 level = lua.Check(&argIndex, 0); - - ///TODO: Buffer checks (Nz::ByteBufferView ?) - return lua.Push(abstractImage->Update(pixels, srcWidth, srcHeight, level)); - } - else if (lua.IsOfType(2, "Rect")) - { - // bool Update(const UInt8* pixels, const Rectui& rect, unsigned int z = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0, UInt8 level = 0) - Nz::Rectui box = lua.Check(&argIndex); - unsigned int srcWidth = lua.Check(&argIndex, 0); - unsigned int srcHeight = lua.Check(&argIndex, 0); - Nz::UInt8 level = lua.Check(&argIndex, 0); - - ///TODO: Buffer checks (Nz::ByteBufferView ?) - return lua.Push(abstractImage->Update(pixels, srcWidth, srcHeight, level)); - }*/ - - lua.Error("No matching overload for method Update"); - return 0; - }); - - /*********************************** Nz::Font **********************************/ - font.SetConstructor([] (Nz::LuaInstance& /*lua*/, Nz::FontRef* instance, std::size_t /*argumentCount*/) - { - Nz::PlacementNew(instance, Nz::Font::New()); - return true; - }); - - font.BindMethod("ClearGlyphCache", &Nz::Font::ClearGlyphCache); - font.BindMethod("ClearKerningCache", &Nz::Font::ClearKerningCache); - font.BindMethod("ClearSizeInfoCache", &Nz::Font::ClearSizeInfoCache); - - font.BindMethod("Destroy", &Nz::Font::Destroy); - - font.BindMethod("GetCachedGlyphCount", [] (Nz::LuaInstance& lua, Nz::FontRef& instance, std::size_t argumentCount) -> int - { - std::size_t argCount = std::min(argumentCount, 2U); - - int argIndex = 2; - switch (argCount) - { - case 0: - lua.Push(instance->GetCachedGlyphCount()); - return 1; - - case 2: - { - unsigned int characterSize = lua.Check(&argIndex); - Nz::UInt32 style = lua.Check(&argIndex); - - lua.Push(instance->GetCachedGlyphCount(characterSize, style)); - return 1; - } - } - - lua.Error("No matching overload for method GetCachedGlyphCount"); - return 0; - }); - - font.BindMethod("GetFamilyName", &Nz::Font::GetFamilyName); - font.BindMethod("GetKerning", &Nz::Font::GetKerning); - font.BindMethod("GetGlyphBorder", &Nz::Font::GetGlyphBorder); - font.BindMethod("GetMinimumStepSize", &Nz::Font::GetMinimumStepSize); - font.BindMethod("GetSizeInfo", &Nz::Font::GetSizeInfo); - font.BindMethod("GetStyleName", &Nz::Font::GetStyleName); - - font.BindMethod("IsValid", &Nz::Font::IsValid); - - font.BindMethod("Precache", (bool(Nz::Font::*)(unsigned int, Nz::UInt32, const Nz::String&) const) &Nz::Font::Precache); - - font.BindMethod("OpenFromFile", &Nz::Font::OpenFromFile, Nz::FontParams()); - - font.BindMethod("SetGlyphBorder", &Nz::Font::SetGlyphBorder); - font.BindMethod("SetMinimumStepSize", &Nz::Font::SetMinimumStepSize); - - font.BindStaticMethod("GetDefault", &Nz::Font::GetDefault); - font.BindStaticMethod("GetDefaultGlyphBorder", &Nz::Font::GetDefaultGlyphBorder); - font.BindStaticMethod("GetDefaultMinimumStepSize", &Nz::Font::GetDefaultMinimumStepSize); - - font.BindStaticMethod("SetDefaultGlyphBorder", &Nz::Font::SetDefaultGlyphBorder); - font.BindStaticMethod("SetDefaultMinimumStepSize", &Nz::Font::SetDefaultMinimumStepSize); - - /*********************************** Nz::Keyboard **********************************/ - keyboard.BindStaticMethod("GetKeyName", &Nz::Keyboard::GetKeyName); - keyboard.BindStaticMethod("IsKeyPressed", &Nz::Keyboard::IsKeyPressed); - - /*********************************** Nz::Node **********************************/ - node.BindMethod("GetBackward", &Nz::Node::GetBackward); - //nodeClass.SetMethod("GetChilds", &Nz::Node::GetChilds); - node.BindMethod("GetDown", &Nz::Node::GetDown); - node.BindMethod("GetForward", &Nz::Node::GetForward); - node.BindMethod("GetInheritPosition", &Nz::Node::GetInheritPosition); - node.BindMethod("GetInheritRotation", &Nz::Node::GetInheritRotation); - node.BindMethod("GetInheritScale", &Nz::Node::GetInheritScale); - node.BindMethod("GetInitialPosition", &Nz::Node::GetInitialPosition); - //nodeClass.SetMethod("GetInitialRotation", &Nz::Node::GetInitialRotation); - node.BindMethod("GetInitialScale", &Nz::Node::GetInitialScale); - node.BindMethod("GetLeft", &Nz::Node::GetLeft); - node.BindMethod("GetNodeType", &Nz::Node::GetNodeType); - //nodeClass.SetMethod("GetParent", &Nz::Node::GetParent); - node.BindMethod("GetPosition", &Nz::Node::GetPosition, Nz::CoordSys_Global); - node.BindMethod("GetRight", &Nz::Node::GetRight); - //nodeClass.SetMethod("GetRotation", &Nz::Node::GetRotation, Nz::CoordSys_Global); - node.BindMethod("GetScale", &Nz::Node::GetScale, Nz::CoordSys_Global); - //nodeClass.SetMethod("GetTransformMatrix", &Nz::Node::GetTransformMatrix); - node.BindMethod("GetUp", &Nz::Node::GetUp); - - node.BindMethod("HasChilds", &Nz::Node::HasChilds); - - node.BindMethod("GetBackward", &Nz::Node::GetBackward); - node.BindMethod("GetDown", &Nz::Node::GetDown); - node.BindMethod("GetForward", &Nz::Node::GetForward); - node.BindMethod("GetInheritPosition", &Nz::Node::GetInheritPosition); - node.BindMethod("GetInheritRotation", &Nz::Node::GetInheritRotation); - node.BindMethod("GetInheritScale", &Nz::Node::GetInheritScale); - node.BindMethod("GetInitialPosition", &Nz::Node::GetInitialPosition); - node.BindMethod("GetInitialRotation", &Nz::Node::GetInitialRotation); - node.BindMethod("GetInitialScale", &Nz::Node::GetInitialScale); - node.BindMethod("GetLeft", &Nz::Node::GetLeft); - node.BindMethod("GetNodeType", &Nz::Node::GetNodeType); - node.BindMethod("GetPosition", &Nz::Node::GetPosition, Nz::CoordSys_Global); - node.BindMethod("GetRight", &Nz::Node::GetRight); - node.BindMethod("GetRotation", &Nz::Node::GetRotation, Nz::CoordSys_Global); - node.BindMethod("GetScale", &Nz::Node::GetScale, Nz::CoordSys_Global); - node.BindMethod("GetUp", &Nz::Node::GetUp); - - node.BindMethod("SetInitialPosition", (void(Nz::Node::*)(const Nz::Vector3f&)) &Nz::Node::SetInitialPosition); - node.BindMethod("SetInitialRotation", (void(Nz::Node::*)(const Nz::Quaternionf&)) &Nz::Node::SetInitialRotation); - - node.BindMethod("SetPosition", (void(Nz::Node::*)(const Nz::Vector3f&, Nz::CoordSys)) &Nz::Node::SetPosition, Nz::CoordSys_Local); - node.BindMethod("SetRotation", (void(Nz::Node::*)(const Nz::Quaternionf&, Nz::CoordSys)) &Nz::Node::SetRotation, Nz::CoordSys_Local); - - node.BindMethod("Move", [] (Nz::LuaInstance& lua, Nz::Node& instance, std::size_t /*argumentCount*/) -> int - { - int argIndex = 2; - - Nz::Vector3f offset = lua.Check(&argIndex); - Nz::CoordSys coordSys = lua.Check(&argIndex, Nz::CoordSys_Local); - instance.Move(offset, coordSys); - - return 0; - }); - - node.BindMethod("Rotate", [] (Nz::LuaInstance& lua, Nz::Node& instance, std::size_t /*argumentCount*/) -> int - { - int argIndex = 2; - - Nz::Quaternionf rotation = lua.Check(&argIndex); - Nz::CoordSys coordSys = lua.Check(&argIndex, Nz::CoordSys_Local); - instance.Rotate(rotation, coordSys); - - return 0; - }); - - node.BindMethod("Scale", [] (Nz::LuaInstance& lua, Nz::Node& instance, std::size_t argumentCount) -> int - { - std::size_t argCount = std::min(argumentCount, 4U); - - int argIndex = 2; - switch (argCount) - { - case 1: - { - if (lua.IsOfType(argIndex, Nz::LuaType_Number)) - instance.Scale(lua.Check(&argIndex)); - else - instance.Scale(lua.Check(&argIndex)); - - return 0; - } - - case 3: - instance.Scale(lua.Check(&argIndex)); - return 0; - } - - lua.Error("No matching overload for method Scale"); - return 0; - }); - - node.BindMethod("SetScale", [] (Nz::LuaInstance& lua, Nz::Node& instance, std::size_t argumentCount) -> int - { - std::size_t argCount = std::min(argumentCount, 4U); - - int argIndex = 2; - switch (argCount) - { - case 1: - case 2: - { - if (lua.IsOfType(argIndex, Nz::LuaType_Number)) - { - float scale = lua.Check(&argIndex); - Nz::CoordSys coordSys = lua.Check(&argIndex, Nz::CoordSys_Local); - instance.SetScale(scale, coordSys); - } - else - instance.SetScale(lua.Check(&argIndex)); - - return 0; - } - - case 3: - case 4: - { - Nz::Vector3f scale = lua.Check(&argIndex); - Nz::CoordSys coordSys = lua.Check(&argIndex, Nz::CoordSys_Local); - - instance.SetScale(scale, coordSys); - return 0; - } - } - - lua.Error("No matching overload for method SetScale"); - return 0; - }); - - node.BindMethod("SetInitialScale", [] (Nz::LuaInstance& lua, Nz::Node& instance, std::size_t argumentCount) -> int - { - std::size_t argCount = std::min(argumentCount, 4U); - - int argIndex = 2; - switch (argCount) - { - case 1: - { - if (lua.IsOfType(argIndex, Nz::LuaType_Number)) - instance.SetInitialScale(lua.Check(&argIndex)); - else - instance.SetInitialScale(lua.Check(&argIndex)); - - return 0; - } - - case 2: - case 3: - instance.SetInitialScale(lua.Check(&argIndex)); - return 0; - } - - lua.Error("No matching overload for method SetInitialScale"); - return 0; - }); - } - - /*! - * \brief Registers the classes that will be used by the Lua instance - * - * \param instance Lua instance that will interact with the Utility classes - */ - - void LuaBinding::RegisterUtility(Nz::LuaInstance& instance) - { - abstractImage.Register(instance); - font.Register(instance); - keyboard.Register(instance); - node.Register(instance); - - keyboard.PushGlobalTable(instance); - { - instance.PushField("Undefined", Nz::Keyboard::Undefined); - - // A-Z - for (std::size_t i = 0; i < 26; ++i) - instance.PushField(Nz::String('A' + char(i)), Nz::Keyboard::A + i); - - // Numerical - for (std::size_t i = 0; i < 10; ++i) - { - instance.PushField("Num" + Nz::String::Number(i), Nz::Keyboard::Num0 + i); - instance.PushField("Numpad" + Nz::String::Number(i), Nz::Keyboard::Numpad0 + i); - } - - // F1-F15 - for (std::size_t i = 0; i < 15; ++i) - instance.PushField('F' + Nz::String::Number(i+1), Nz::Keyboard::F1 + i); - - // And all the others... - instance.PushField("Down", Nz::Keyboard::Down); - instance.PushField("Left", Nz::Keyboard::Left); - instance.PushField("Right", Nz::Keyboard::Right); - instance.PushField("Up", Nz::Keyboard::Up); - - instance.PushField("Add", Nz::Keyboard::Add); - instance.PushField("Decimal", Nz::Keyboard::Decimal); - instance.PushField("Divide", Nz::Keyboard::Divide); - instance.PushField("Multiply", Nz::Keyboard::Multiply); - instance.PushField("Subtract", Nz::Keyboard::Subtract); - - instance.PushField("Backslash", Nz::Keyboard::Backslash); - instance.PushField("Backspace", Nz::Keyboard::Backspace); - instance.PushField("Clear", Nz::Keyboard::Clear); - instance.PushField("Comma", Nz::Keyboard::Comma); - instance.PushField("Dash", Nz::Keyboard::Dash); - instance.PushField("Delete", Nz::Keyboard::Delete); - instance.PushField("End", Nz::Keyboard::End); - instance.PushField("Equal", Nz::Keyboard::Equal); - instance.PushField("Escape", Nz::Keyboard::Escape); - instance.PushField("Home", Nz::Keyboard::Home); - instance.PushField("Insert", Nz::Keyboard::Insert); - instance.PushField("LAlt", Nz::Keyboard::LAlt); - instance.PushField("LBracket", Nz::Keyboard::LBracket); - instance.PushField("LControl", Nz::Keyboard::LControl); - instance.PushField("LShift", Nz::Keyboard::LShift); - instance.PushField("LSystem", Nz::Keyboard::LSystem); - instance.PushField("PageDown", Nz::Keyboard::PageDown); - instance.PushField("PageUp", Nz::Keyboard::PageUp); - instance.PushField("Pause", Nz::Keyboard::Pause); - instance.PushField("Period", Nz::Keyboard::Period); - instance.PushField("Print", Nz::Keyboard::Print); - instance.PushField("PrintScreen", Nz::Keyboard::PrintScreen); - instance.PushField("Quote", Nz::Keyboard::Quote); - instance.PushField("RAlt", Nz::Keyboard::RAlt); - instance.PushField("RBracket", Nz::Keyboard::RBracket); - instance.PushField("RControl", Nz::Keyboard::RControl); - instance.PushField("Return", Nz::Keyboard::Return); - instance.PushField("RShift", Nz::Keyboard::RShift); - instance.PushField("RSystem", Nz::Keyboard::RSystem); - instance.PushField("Semicolon", Nz::Keyboard::Semicolon); - instance.PushField("Slash", Nz::Keyboard::Slash); - instance.PushField("Space", Nz::Keyboard::Space); - instance.PushField("Tab", Nz::Keyboard::Tab); - instance.PushField("Tilde", Nz::Keyboard::Tilde); - instance.PushField("Browser_Back", Nz::Keyboard::Browser_Back); - instance.PushField("Browser_Favorites", Nz::Keyboard::Browser_Favorites); - instance.PushField("Browser_Forward", Nz::Keyboard::Browser_Forward); - instance.PushField("Browser_Home", Nz::Keyboard::Browser_Home); - instance.PushField("Browser_Refresh", Nz::Keyboard::Browser_Refresh); - instance.PushField("Browser_Search", Nz::Keyboard::Browser_Search); - instance.PushField("Browser_Stop", Nz::Keyboard::Browser_Stop); - instance.PushField("Media_Next", Nz::Keyboard::Media_Next); - instance.PushField("Media_Play", Nz::Keyboard::Media_Play); - instance.PushField("Media_Previous", Nz::Keyboard::Media_Previous); - instance.PushField("Media_Stop", Nz::Keyboard::Media_Stop); - instance.PushField("Volume_Down", Nz::Keyboard::Volume_Down); - instance.PushField("Volume_Mute", Nz::Keyboard::Volume_Mute); - instance.PushField("Volume_Up", Nz::Keyboard::Volume_Up); - instance.PushField("CapsLock", Nz::Keyboard::CapsLock); - instance.PushField("NumLock", Nz::Keyboard::NumLock); - instance.PushField("ScrollLock", Nz::Keyboard::ScrollLock); - } - instance.Pop(); - } -} diff --git a/SDK/src/NDK/Systems/RenderSystem.cpp b/SDK/src/NDK/Systems/RenderSystem.cpp index fb6709227..bdbb6cb5b 100644 --- a/SDK/src/NDK/Systems/RenderSystem.cpp +++ b/SDK/src/NDK/Systems/RenderSystem.cpp @@ -28,10 +28,10 @@ namespace Ndk /*! * \brief Constructs an RenderSystem object by default */ - RenderSystem::RenderSystem() : m_coordinateSystemMatrix(Nz::Matrix4f::Identity()), - m_coordinateSystemInvalidated(true) + m_coordinateSystemInvalidated(true), + m_forceRenderQueueInvalidation(false) { ChangeRenderTechnique(); SetDefaultBackground(Nz::ColorBackground::New()); @@ -44,15 +44,22 @@ namespace Ndk * * \param entity Pointer to the entity */ - void RenderSystem::OnEntityRemoved(Entity* entity) { + m_forceRenderQueueInvalidation = true; //< Hackfix until lights and particles are handled by culling list + m_cameras.Remove(entity); m_directionalLights.Remove(entity); m_drawables.Remove(entity); m_lights.Remove(entity); m_particleGroups.Remove(entity); m_pointSpotLights.Remove(entity); + + if (entity->HasComponent()) + { + GraphicsComponent& gfxComponent = entity->GetComponent(); + gfxComponent.RemoveFromCullingList(&m_drawableCulling); + } } /*! @@ -61,7 +68,6 @@ namespace Ndk * \param entity Pointer to the entity * \param justAdded Is the entity newly added */ - void RenderSystem::OnEntityValidation(Entity* entity, bool justAdded) { NazaraUnused(justAdded); @@ -78,12 +84,30 @@ namespace Ndk m_cameras.Remove(entity); if (entity->HasComponent() && entity->HasComponent()) + { m_drawables.Insert(entity); + + if (justAdded) + { + GraphicsComponent& gfxComponent = entity->GetComponent(); + gfxComponent.AddToCullingList(&m_drawableCulling); + } + } else + { m_drawables.Remove(entity); + if (entity->HasComponent()) + { + GraphicsComponent& gfxComponent = entity->GetComponent(); + gfxComponent.RemoveFromCullingList(&m_drawableCulling); + } + } + if (entity->HasComponent() && entity->HasComponent()) { + m_forceRenderQueueInvalidation = true; //< Hackfix until lights and particles are handled by culling list + LightComponent& lightComponent = entity->GetComponent(); if (lightComponent.GetLightType() == Nz::LightType_Directional) { @@ -100,15 +124,25 @@ namespace Ndk } else { + m_forceRenderQueueInvalidation = true; //< Hackfix until lights and particles are handled by culling list + m_directionalLights.Remove(entity); m_lights.Remove(entity); m_pointSpotLights.Remove(entity); } if (entity->HasComponent()) + { + m_forceRenderQueueInvalidation = true; //< Hackfix until lights and particles are handled by culling list + m_particleGroups.Insert(entity); + } else + { + m_forceRenderQueueInvalidation = true; //< Hackfix until lights and particles are handled by culling list + m_particleGroups.Remove(entity); + } } /*! @@ -140,30 +174,45 @@ namespace Ndk //UpdateDirectionalShadowMaps(camComponent); Nz::AbstractRenderQueue* renderQueue = m_renderTechnique->GetRenderQueue(); - renderQueue->Clear(); - //TODO: Culling + // To make sure the bounding volume used by the culling list is updated for (const Ndk::EntityHandle& drawable : m_drawables) { GraphicsComponent& graphicsComponent = drawable->GetComponent(); - - graphicsComponent.AddToRenderQueue(renderQueue); + graphicsComponent.EnsureBoundingVolumeUpdate(); } + + bool forceInvalidation = false; - for (const Ndk::EntityHandle& light : m_lights) + std::size_t visibilityHash = m_drawableCulling.Cull(camComponent.GetFrustum(), &forceInvalidation); + + // Always regenerate renderqueue if particle groups are present for now (FIXME) + if (!m_particleGroups.empty()) + forceInvalidation = true; + + if (camComponent.UpdateVisibility(visibilityHash) || m_forceRenderQueueInvalidation || forceInvalidation) { - LightComponent& lightComponent = light->GetComponent(); - NodeComponent& lightNode = light->GetComponent(); + renderQueue->Clear(); + for (const GraphicsComponent* gfxComponent : m_drawableCulling) + gfxComponent->AddToRenderQueue(renderQueue); - ///TODO: Cache somehow? - lightComponent.AddToRenderQueue(renderQueue, Nz::Matrix4f::ConcatenateAffine(m_coordinateSystemMatrix, lightNode.GetTransformMatrix())); - } + for (const Ndk::EntityHandle& light : m_lights) + { + LightComponent& lightComponent = light->GetComponent(); + NodeComponent& lightNode = light->GetComponent(); - for (const Ndk::EntityHandle& particleGroup : m_particleGroups) - { - ParticleGroupComponent& groupComponent = particleGroup->GetComponent(); + ///TODO: Cache somehow? + lightComponent.AddToRenderQueue(renderQueue, Nz::Matrix4f::ConcatenateAffine(m_coordinateSystemMatrix, lightNode.GetTransformMatrix())); + } - groupComponent.AddToRenderQueue(renderQueue, Nz::Matrix4f::Identity()); //< ParticleGroup doesn't use Matrix4f + for (const Ndk::EntityHandle& particleGroup : m_particleGroups) + { + ParticleGroupComponent& groupComponent = particleGroup->GetComponent(); + + groupComponent.AddToRenderQueue(renderQueue, Nz::Matrix4f::Identity()); //< ParticleGroup doesn't use any transform matrix (yet) + } + + m_forceRenderQueueInvalidation = false; } camComponent.ApplyView(); diff --git a/SDK/src/NDK/Systems/VelocitySystem.cpp b/SDK/src/NDK/Systems/VelocitySystem.cpp index 4bc3b3a68..02800d716 100644 --- a/SDK/src/NDK/Systems/VelocitySystem.cpp +++ b/SDK/src/NDK/Systems/VelocitySystem.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -14,17 +15,16 @@ namespace Ndk * \class Ndk::VelocitySystem * \brief NDK class that represents the velocity system * - * \remark This system is enabled if the entity owns the trait: NodeComponent and VelocityComponent - * but it's disabled with the trait: PhysicsComponent3D + * \remark This system is enabled if the entity owns the traits NodeComponent and VelocityComponent + * but it's disabled with the traits: PhysicsComponent2D, PhysicsComponent3D */ /*! * \brief Constructs an VelocitySystem object by default */ - VelocitySystem::VelocitySystem() { - Excludes(); + Excludes(); Requires(); SetUpdateOrder(10); //< Since some systems may want to stop us } diff --git a/SDK/src/NDK/Widgets/ButtonWidget.cpp b/SDK/src/NDK/Widgets/ButtonWidget.cpp new file mode 100644 index 000000000..25ac74c69 --- /dev/null +++ b/SDK/src/NDK/Widgets/ButtonWidget.cpp @@ -0,0 +1,70 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include +#include +#include + +namespace Ndk +{ + ButtonWidget::ButtonWidget(BaseWidget* parent) : + BaseWidget(parent) + { + m_gradientSprite = Nz::Sprite::New(); + m_gradientSprite->SetColor(Nz::Color(74, 74, 74)); + m_gradientSprite->SetCornerColor(Nz::RectCorner_LeftBottom, Nz::Color(180, 180, 180)); + m_gradientSprite->SetCornerColor(Nz::RectCorner_RightBottom, Nz::Color(180, 180, 180)); + m_gradientSprite->SetMaterial(Nz::Material::New("Basic2D")); + + m_gradientEntity = CreateEntity(); + m_gradientEntity->AddComponent().SetParent(this); + m_gradientEntity->AddComponent().Attach(m_gradientSprite); + + m_textSprite = Nz::TextSprite::New(); + + m_textEntity = CreateEntity(); + m_textEntity->AddComponent().SetParent(this); + m_textEntity->AddComponent().Attach(m_textSprite, 1); + + Layout(); + } + + void ButtonWidget::ResizeToContent() + { + SetContentSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths())); + } + + void ButtonWidget::Layout() + { + BaseWidget::Layout(); + + const Nz::Vector2f& contentSize = GetContentSize(); + + m_gradientSprite->SetSize(contentSize); + + Nz::Boxf textBox = m_textEntity->GetComponent().GetBoundingVolume().aabb; + m_textEntity->GetComponent().SetPosition(contentSize.x / 2 - textBox.width / 2, contentSize.y / 2 - textBox.height / 2); + } + + void ButtonWidget::OnMouseButtonRelease(int /*x*/, int /*y*/, Nz::Mouse::Button button) + { + if (button == Nz::Mouse::Left) + OnButtonTrigger(this); + } + + void ButtonWidget::OnMouseEnter() + { + m_gradientSprite->SetColor(Nz::Color(128, 128, 128)); + } + + void ButtonWidget::OnMouseMoved(int x, int y, int deltaX, int deltaY) + { + } + + void ButtonWidget::OnMouseExit() + { + m_gradientSprite->SetColor(Nz::Color(74, 74, 74)); + } +} diff --git a/SDK/src/NDK/Widgets/LabelWidget.cpp b/SDK/src/NDK/Widgets/LabelWidget.cpp new file mode 100644 index 000000000..df9c0e1c7 --- /dev/null +++ b/SDK/src/NDK/Widgets/LabelWidget.cpp @@ -0,0 +1,28 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include +#include +#include + +namespace Ndk +{ + LabelWidget::LabelWidget(BaseWidget* parent) : + BaseWidget(parent) + { + m_textSprite = Nz::TextSprite::New(); + + m_textEntity = CreateEntity(); + m_textEntity->AddComponent().Attach(m_textSprite); + m_textEntity->AddComponent().SetParent(this); + + Layout(); + } + + void LabelWidget::ResizeToContent() + { + SetContentSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths())); + } +} diff --git a/SDK/src/NDK/Widgets/TextAreaWidget.cpp b/SDK/src/NDK/Widgets/TextAreaWidget.cpp new file mode 100644 index 000000000..0e0f82f57 --- /dev/null +++ b/SDK/src/NDK/Widgets/TextAreaWidget.cpp @@ -0,0 +1,232 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Development Kit" +// For conditions of distribution and use, see copyright notice in Prerequesites.hpp + +#include +#include +#include +#include +#include +#include + +namespace Ndk +{ + TextAreaWidget::TextAreaWidget(BaseWidget* parent) : + BaseWidget(parent), + m_cursorPosition(0U), + m_multiLineEnabled(false), + m_readOnly(false) + { + m_cursorSprite = Nz::Sprite::New(); + m_cursorSprite->SetColor(Nz::Color(192, 192, 192)); + m_cursorSprite->SetSize(1.f, float(m_drawer.GetFont()->GetSizeInfo(m_drawer.GetCharacterSize()).lineHeight)); + + m_cursorEntity = CreateEntity(); + m_cursorEntity->AddComponent().Attach(m_cursorSprite, 10); + m_cursorEntity->AddComponent().SetParent(this); + m_cursorEntity->Enable(false); + + m_textSprite = Nz::TextSprite::New(); + + m_textEntity = CreateEntity(); + m_textEntity->AddComponent().Attach(m_textSprite); + m_textEntity->AddComponent().SetParent(this); + + Layout(); + } + + void TextAreaWidget::AppendText(const Nz::String& text) + { + m_drawer.AppendText(text); + + m_textSprite->Update(m_drawer); + } + + std::size_t TextAreaWidget::GetHoveredGlyph(float x, float y) const + { + std::size_t glyphCount = m_drawer.GetGlyphCount(); + if (glyphCount > 0) + { + std::size_t lineCount = m_drawer.GetLineCount(); + std::size_t line = 0U; + for (; line < lineCount - 1; ++line) + { + Nz::Rectf lineBounds = m_drawer.GetLine(line).bounds; + if (lineBounds.GetMaximum().y > y) + break; + } + + std::size_t upperLimit = (line != lineCount - 1) ? m_drawer.GetLine(line + 1).glyphIndex : glyphCount + 1; + + std::size_t i = m_drawer.GetLine(line).glyphIndex; + for (; i < upperLimit - 1; ++i) + { + Nz::Rectf bounds = m_drawer.GetGlyph(i).bounds; + if (x < bounds.x + bounds.width * 0.75f) + break; + } + + return i; + } + + return 0; + } + + void TextAreaWidget::ResizeToContent() + { + SetContentSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths())); + } + + void TextAreaWidget::SetText(const Nz::String& text) + { + m_drawer.SetText(text); + + m_textSprite->Update(m_drawer); + } + + void TextAreaWidget::Write(const Nz::String& text) + { + if (m_cursorPosition >= m_drawer.GetGlyphCount()) + { + AppendText(text); + SetCursorPosition(m_drawer.GetGlyphCount()); + } + else + { + Nz::String currentText = m_drawer.GetText(); + currentText.Insert(currentText.GetCharacterPosition(m_cursorPosition), text); + SetText(currentText); + + SetCursorPosition(m_cursorPosition + text.GetLength()); + } + } + + void TextAreaWidget::RefreshCursor() + { + 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 > m_cursorPosition) + break; + + line = i; + } + + const auto& lineInfo = m_drawer.GetLine(line); + + std::size_t glyphCount = m_drawer.GetGlyphCount(); + float position; + if (glyphCount > 0 && lineInfo.glyphIndex < m_cursorPosition) + { + const auto& glyph = m_drawer.GetGlyph(std::min(m_cursorPosition, glyphCount - 1)); + position = glyph.bounds.x; + if (m_cursorPosition >= glyphCount) + position += glyph.bounds.width; + } + else + position = 0.f; + + m_cursorEntity->GetComponent().SetPosition(position, lineInfo.bounds.y); + } + + void TextAreaWidget::OnKeyPressed(const Nz::WindowEvent::KeyEvent& key) + { + switch (key.code) + { + case Nz::Keyboard::Delete: + { + const Nz::String& text = m_drawer.GetText(); + + Nz::String newText; + if (m_cursorPosition > 0) + newText.Append(text.SubString(0, text.GetCharacterPosition(m_cursorPosition) - 1)); + + if (m_cursorPosition < m_drawer.GetGlyphCount()) + newText.Append(text.SubString(text.GetCharacterPosition(m_cursorPosition + 1))); + + m_drawer.SetText(newText); + m_textSprite->Update(m_drawer); + break; + } + + case Nz::Keyboard::Left: + MoveCursor(-1); + break; + + case Nz::Keyboard::Right: + MoveCursor(1); + break; + } + } + + void TextAreaWidget::OnKeyReleased(const Nz::WindowEvent::KeyEvent& key) + { + } + + void TextAreaWidget::OnMouseEnter() + { + m_cursorEntity->Enable(true); + } + + void TextAreaWidget::OnMouseButtonPress(int x, int y, Nz::Mouse::Button button) + { + if (button == Nz::Mouse::Left) + { + GrabKeyboard(); + + SetCursorPosition(GetHoveredGlyph(float(x), float(y))); + } + } + + void TextAreaWidget::OnMouseMoved(int x, int y, int deltaX, int deltaY) + { + } + + void TextAreaWidget::OnMouseExit() + { + m_cursorEntity->Enable(false); + } + + void TextAreaWidget::OnTextEntered(char32_t character, bool /*repeated*/) + { + if (m_readOnly) + return; + + switch (character) + { + case '\b': + { + const Nz::String& text = m_drawer.GetText(); + + Nz::String newText; + if (m_cursorPosition > 1) + newText.Append(text.SubString(0, text.GetCharacterPosition(m_cursorPosition - 1) - 1)); + + if (m_cursorPosition < m_drawer.GetGlyphCount()) + newText.Append(text.SubString(text.GetCharacterPosition(m_cursorPosition))); + + SetText(newText); + MoveCursor(-1); + break; + } + + case '\r': + case '\n': + if (!m_multiLineEnabled) + break; + + Write(Nz::String('\n')); + break; + + default: + { + if (Nz::Unicode::GetCategory(character) == Nz::Unicode::Category_Other_Control) + break; + + Write(Nz::String::Unicode(character)); + break; + } + } + } +} diff --git a/build/scripts/actions/generateheaders.lua b/build/scripts/actions/generateheaders.lua index 829d0caba..d9bbe3ea6 100644 --- a/build/scripts/actions/generateheaders.lua +++ b/build/scripts/actions/generateheaders.lua @@ -69,6 +69,15 @@ ACTION.Function = function () Target = "../SDK/include/NDK/Systems.hpp" }) + table.insert(paths, { + Excludes = {}, + HeaderGuard = "NDK_WIDGETS_GLOBAL_HPP", + Name = "NDK Widgets", + SearchDir = "../SDK/include/NDK/Widgets", + TopDir = "NDK", + Target = "../SDK/include/NDK/Widgets.hpp" + }) + for k,v in ipairs(paths) do print(v.Name) local header, err = io.open(v.Target, "w+") diff --git a/build/scripts/tools/ndk_server.lua b/build/scripts/tools/ndk_server.lua index 841aa6e4e..c439e47b1 100644 --- a/build/scripts/tools/ndk_server.lua +++ b/build/scripts/tools/ndk_server.lua @@ -25,6 +25,7 @@ TOOL.Files = { -- Excludes client-only files TOOL.FilesExcluded = { "../SDK/**/CameraComponent.*", + "../SDK/**/Canvas.*", "../SDK/**/Console.*", "../SDK/**/GraphicsComponent.*", "../SDK/**/LightComponent.*", @@ -33,6 +34,7 @@ TOOL.FilesExcluded = { "../SDK/**/Particle*Component.*", "../SDK/**/ParticleSystem.*", "../SDK/**/RenderSystem.*", + "../SDK/**/*Widget*.*", "../SDK/**/LuaBinding_Audio.*", "../SDK/**/LuaBinding_Graphics.*", "../SDK/**/LuaBinding_Renderer.*" diff --git a/examples/FirstScene/main.cpp b/examples/FirstScene/main.cpp index e7c5b2c90..863d3edea 100644 --- a/examples/FirstScene/main.cpp +++ b/examples/FirstScene/main.cpp @@ -96,7 +96,7 @@ int main() // Les UVs de ce fichier sont retournées (repère OpenGL, origine coin bas-gauche) par rapport à ce que le moteur attend (haut-gauche) // Nous devons donc indiquer au moteur de les retourner lors du chargement - params.mesh.flipUVs = true; + params.mesh.texCoordScale.Set(1.f, -1.f); // Nazara va par défaut optimiser les modèles pour un rendu plus rapide, cela peut prendre du temps et n'est pas nécessaire ici params.mesh.optimizeIndexBuffers = false; diff --git a/examples/Particles/Common.cpp b/examples/Particles/Common.cpp new file mode 100644 index 000000000..5af7225f7 --- /dev/null +++ b/examples/Particles/Common.cpp @@ -0,0 +1,70 @@ +#include "Common.hpp" +#include +#include +#include +#include + +ParticleDemo::ParticleDemo(const Nz::String& name, const ExampleShared& exampleShared) : +m_shared(exampleShared), +m_index(s_demoIndex++), +m_name(name) +{ +} + +void ParticleDemo::Enter(Ndk::StateMachine& fsm) +{ + m_shared.demoName->Update(Nz::SimpleTextDrawer::Draw(Nz::String::Number(m_index+1) + " - " + m_name, 48)); + m_fpsCounter = 0; + m_updateClock.Restart(); + + Ndk::RenderSystem& renderSystem2D = m_shared.world2D->GetSystem(); + Ndk::RenderSystem& renderSystem3D = m_shared.world3D->GetSystem(); + m_oldBackground2D = renderSystem2D.GetDefaultBackground(); + m_oldBackground3D = renderSystem3D.GetDefaultBackground(); +} + +void ParticleDemo::Leave(Ndk::StateMachine& fsm) +{ + m_shared.world2D->GetSystem().SetDefaultBackground(m_oldBackground2D); + m_shared.world3D->GetSystem().SetDefaultBackground(m_oldBackground3D); + + m_entities.clear(); + m_particleGroups.clear(); +} + +bool ParticleDemo::Update(Ndk::StateMachine& fsm, float elapsedTime) +{ + m_fpsCounter++; + if (m_updateClock.GetMilliseconds() > 1000) + { + m_updateClock.Restart(); + + m_shared.fpsCount->Update(Nz::SimpleTextDrawer::Draw(Nz::String::Number(m_fpsCounter) + " FPS", 24)); + m_fpsCounter = 0; + + unsigned int particleCount = 0; + for (const Ndk::EntityHandle& entity : m_particleGroups) + { + const Ndk::ParticleGroupComponent& group = entity->GetComponent(); + particleCount += group.GetParticleCount(); + } + + m_shared.particleCount->Update(Nz::SimpleTextDrawer::Draw(Nz::String::Number(particleCount) + " particles", 36)); + } + + return true; +} + +void ParticleDemo::RegisterEntity(const Ndk::EntityHandle& entity) +{ + m_entities.emplace_back(entity); +} + +void ParticleDemo::RegisterParticleGroup(const Ndk::EntityHandle& entity) +{ + NazaraAssert(entity->HasComponent(), "Must have particle group component"); + + m_particleGroups.emplace_back(entity); +} + +std::size_t ParticleDemo::s_demoIndex = 0; diff --git a/examples/Particles/Common.hpp b/examples/Particles/Common.hpp new file mode 100644 index 000000000..658b97419 --- /dev/null +++ b/examples/Particles/Common.hpp @@ -0,0 +1,64 @@ +#pragma once + +#ifndef NAZARA_EXAMPLES_PARTICLES_COMMON_HPP +#define NAZARA_EXAMPLES_PARTICLES_COMMON_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class ParticleDemo; + +struct ExampleShared +{ + mutable std::mt19937 randomGen; + std::vector> demos; + Nz::RenderWindow* target; + Nz::TextSpriteRef demoName; + Nz::TextSpriteRef fpsCount; + Nz::TextSpriteRef particleCount; + Ndk::EntityHandle viewer2D; + Ndk::EntityHandle viewer3D; + Ndk::WorldHandle world2D; + Ndk::WorldHandle world3D; +}; + +class ParticleDemo : public Ndk::State +{ + public: + ParticleDemo(const Nz::String& name, const ExampleShared& exampleShared); + ~ParticleDemo() = default; + + void Enter(Ndk::StateMachine& fsm) override; + void Leave(Ndk::StateMachine& fsm) override; + + bool Update(Ndk::StateMachine& fsm, float elapsedTime) override; + + protected: + const ExampleShared& m_shared; + + void RegisterEntity(const Ndk::EntityHandle& entity); + void RegisterParticleGroup(const Ndk::EntityHandle& entity); + + private: + std::size_t m_index; + std::vector m_entities; + std::vector m_particleGroups; + Nz::BackgroundRef m_oldBackground2D; + Nz::BackgroundRef m_oldBackground3D; + Nz::Clock m_updateClock; + Nz::String m_name; + unsigned int m_fpsCounter; + + static std::size_t s_demoIndex; +}; + +#endif // NAZARA_EXAMPLES_PARTICLES_COMMON_HPP diff --git a/examples/Particles/LogoDemo.cpp b/examples/Particles/LogoDemo.cpp new file mode 100644 index 000000000..cc0c2a610 --- /dev/null +++ b/examples/Particles/LogoDemo.cpp @@ -0,0 +1,170 @@ +#include "LogoDemo.hpp" +#include +#include +#include +#include +#include + +namespace +{ + const float duration = 10.f; + const float maxVel = 50.f; + const float pauseTime = 3.f; + const float startTime = 2.f; + const float speed = 3.f; +} + +struct SpriteController : public Nz::ParticleController +{ + void Apply(Nz::ParticleGroup& system, Nz::ParticleMapper& mapper, unsigned int startId, unsigned int endId, float elapsedTime) override + { + if (!enabled) + return; + + auto posPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Position); + auto velPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Velocity); + + for (unsigned int i = startId; i <= endId; ++i) + posPtr[i] += velPtr[i] * elapsedTime * factor; + } + + bool enabled = false; + float factor = 1.f; +}; + + +class SpriteRenderer : public Nz::ParticleRenderer +{ + public: + SpriteRenderer(Nz::MaterialRef mat) : + m_material(mat) + { + } + + void Render(const Nz::ParticleGroup& system, const Nz::ParticleMapper& mapper, unsigned int startId, unsigned int endId, Nz::AbstractRenderQueue* renderQueue) + { + Nz::Vector2f size(1.f, 1.f); + Nz::SparsePtr sizePtr(&size, 0); + Nz::SparsePtr sinCosPtr(nullptr, 0); + + renderQueue->AddBillboards(0, m_material, endId - startId + 1, mapper.GetComponentPtr(Nz::ParticleComponent_Position), sizePtr, sinCosPtr, mapper.GetComponentPtr(Nz::ParticleComponent_Color)); + } + + private: + Nz::MaterialRef m_material; +}; + +LogoExample::LogoExample(ExampleShared& sharedData) : +ParticleDemo("Logo", sharedData) +{ + Nz::ImageParams params; + params.loadFormat = Nz::PixelFormatType_RGBA8; + + if (!m_logo.LoadFromFile("resources/Logo.png", params)) + NazaraError("Failed to load logo!"); + + unsigned int width = m_logo.GetWidth(); + unsigned int height = m_logo.GetHeight(); + m_pixels.reserve(width * height); + + for (unsigned int y = 0; y < height; ++y) + { + for (unsigned int x = 0; x < width; ++x) + { + Nz::Color color = m_logo.GetPixelColor(x, y); + if (color.a == 0) + continue; + + PixelData data; + data.pos.Set(x, y); + data.color = color; + + m_pixels.push_back(data); + } + } + + + Nz::MaterialRef material = Nz::Material::New(); + material->EnableBlending(true); + material->EnableDepthWrite(false); + material->EnableFaceCulling(false); + material->SetDstBlend(Nz::BlendFunc_InvSrcAlpha); + material->SetSrcBlend(Nz::BlendFunc_SrcAlpha); + + m_controller = new SpriteController; + m_renderer = new SpriteRenderer(std::move(material)); +} + +void LogoExample::Enter(Ndk::StateMachine& fsm) +{ + ParticleDemo::Enter(fsm); + + m_shared.world3D->GetSystem().SetDefaultBackground(nullptr); + + Nz::TextureRef backgroundTexture = Nz::Texture::New(); + if (backgroundTexture->LoadFromFile("resources/stars-background.jpg")) + m_shared.world2D->GetSystem().SetDefaultBackground(Nz::TextureBackground::New(std::move(backgroundTexture))); + + Ndk::EntityHandle particleGroupEntity = m_shared.world2D->CreateEntity(); + Ndk::ParticleGroupComponent& particleGroup = particleGroupEntity->AddComponent(m_pixels.size(), Nz::ParticleLayout_Sprite); + RegisterParticleGroup(particleGroupEntity); + + particleGroup.AddController(m_controller); + particleGroup.SetRenderer(m_renderer); + + m_particles = static_cast(particleGroup.CreateParticles(m_pixels.size())); + ResetParticles(-duration * (speed / 2.f)); + + m_accumulator = pauseTime + duration; + m_totalAccumulator = 0.f; +} + +void LogoExample::Leave(Ndk::StateMachine & fsm) +{ + ParticleDemo::Leave(fsm); +} + +bool LogoExample::Update(Ndk::StateMachine& fsm, float elapsedTime) +{ + if (!ParticleDemo::Update(fsm, elapsedTime)) + return false; + + m_totalAccumulator += elapsedTime; + if (m_totalAccumulator <= startTime) + return true; + + m_accumulator += elapsedTime; + + SpriteController* controller = static_cast(m_controller.Get()); + if (m_accumulator > pauseTime + 2.f * duration) + { + ResetParticles(0.f); + m_accumulator = 0.f; + } + + controller->enabled = (m_accumulator > pauseTime); + controller->factor = -speed + speed * (m_accumulator - pauseTime) / (duration); + + return true; +} + +void LogoExample::ResetParticles(float elapsed) +{ + Nz::Vector2f center = {m_shared.target->GetWidth() / 2.f, m_shared.target->GetHeight() / 2.f}; + Nz::Vector2f offset = center - Nz::Vector2f(Nz::Vector2ui(m_logo.GetSize()) / 2); + + float ratio = float(m_shared.target->GetWidth()) / m_shared.target->GetHeight(); + std::uniform_real_distribution disX(-maxVel * ratio, maxVel * ratio); + std::uniform_real_distribution disY(-maxVel, maxVel); + + Nz::ParticleStruct_Sprite* sprite = m_particles; + for (PixelData& data : m_pixels) + { + sprite->color = data.color; + sprite->position = offset + Nz::Vector2f(data.pos); + sprite->rotation = 0.f; + sprite->velocity.Set(disX(m_shared.randomGen), disY(m_shared.randomGen), 0.f); + sprite->position += sprite->velocity * elapsed; + sprite++; + } +} diff --git a/examples/Particles/LogoDemo.hpp b/examples/Particles/LogoDemo.hpp new file mode 100644 index 000000000..d5c374d32 --- /dev/null +++ b/examples/Particles/LogoDemo.hpp @@ -0,0 +1,41 @@ +#pragma once + +#ifndef NAZARA_EXAMPLES_PARTICLES_LOGO_HPP +#define NAZARA_EXAMPLES_PARTICLES_LOGO_HPP + +#include +#include +#include +#include +#include "Common.hpp" + +class LogoExample : public ParticleDemo +{ + public: + LogoExample(ExampleShared& sharedData); + ~LogoExample() = default; + + void Enter(Ndk::StateMachine& fsm) override; + void Leave(Ndk::StateMachine& fsm) override; + bool Update(Ndk::StateMachine& fsm, float elapsedTime) override; + + private: + void ResetParticles(float elapsed); + + struct PixelData + { + Nz::Vector2ui pos; + Nz::Color color; + }; + + std::vector m_pixels; + Nz::BackgroundRef m_oldBackground; + Nz::ParticleStruct_Sprite* m_particles; + Nz::Image m_logo; + Nz::ParticleControllerRef m_controller; + Nz::ParticleRendererRef m_renderer; + float m_accumulator; + float m_totalAccumulator; +}; + +#endif // NAZARA_EXAMPLES_PARTICLES_LOGO_HPP diff --git a/examples/Particles/SpacebattleDemo.cpp b/examples/Particles/SpacebattleDemo.cpp new file mode 100644 index 000000000..8cc1558c6 --- /dev/null +++ b/examples/Particles/SpacebattleDemo.cpp @@ -0,0 +1,826 @@ +#include "SpacebattleDemo.hpp" +#include +#include +#include +#include +#include +#include + +namespace +{ + const float maxLaserLife = 15.f; + const float maxSmokeLife = 20.f; +} + +struct SpaceshipComponent : public Ndk::Component +{ + SpaceshipComponent() + { + engineSound.SetBuffer(Nz::SoundBufferManager::Get("resources/spaceship_loop.wav")); + engineSound.EnableSpatialization(true); + engineSound.SetMinDistance(10.f); + engineSound.SetPitch(1.5f); + + hitSound.SetBuffer(Nz::SoundBufferManager::Get("resources/explosion.wav")); + hitSound.EnableSpatialization(true); + hitSound.SetMinDistance(150.f); + + laserSound.SetBuffer(Nz::SoundBufferManager::Get("resources/laser.wav")); + laserSound.EnableSpatialization(true); + laserSound.SetMinDistance(150.f); + laserSound.SetVolume(60.f); + } + + std::array laserBeamSprites; + Nz::Sound engineSound; + Nz::Sound hitSound; + Nz::Sound laserSound; + Nz::UInt64 hitTime = 0; + Nz::Vector3f targetPos = Nz::Vector3f::Zero(); + bool attacking = true; + + static Ndk::ComponentIndex componentIndex; +}; +Ndk::ComponentIndex SpaceshipComponent::componentIndex; + +struct LaserBeamComponent : public Ndk::Component +{ + LaserBeamComponent() + { + Nz::MaterialRef laserBeamMaterial = Nz::MaterialLibrary::Get("LaserBeam"); + for (Nz::Sprite& sprite : sprites) + { + sprite.SetMaterial(laserBeamMaterial); + sprite.SetOrigin(Nz::Vector2f(0.f, 0.5f)); + sprite.SetTextureCoords(Nz::Rectf(0.f, 0.f, 50.f, 1.f)); + } + } + + void OnAttached() override + { + auto& spaceshipCom = m_entity->GetComponent(); + spaceshipCom.laserSound.Play(); + } + + std::array sprites; + Nz::Vector3f origin = Nz::Vector3f::Zero(); + float length = 1500.f; + float life = 2.f; + float width = 2.f; + + static Ndk::ComponentIndex componentIndex; +}; +Ndk::ComponentIndex LaserBeamComponent::componentIndex; + +class LaserBeamSystem : public Ndk::System +{ + public: + LaserBeamSystem(const ExampleShared& sharedData) : + m_sharedData(sharedData) + { + Requires(); + } + + void OnEntityAdded(Ndk::Entity* entity) override + { + auto& laserComponent = entity->GetComponent(); + auto& gfxComponent = entity->GetComponent(); + + for (Nz::Sprite& sprite : laserComponent.sprites) + sprite.SetSize({laserComponent.length, laserComponent.width}); + + gfxComponent.Attach(&laserComponent.sprites[0], Nz::Matrix4f::Transform(laserComponent.origin, Nz::EulerAnglesf(0.f, 90.f, 0.f))); + gfxComponent.Attach(&laserComponent.sprites[1], Nz::Matrix4f::Transform(laserComponent.origin, Nz::EulerAnglesf(90.f, 90.f, 0.f))); + } + + void OnUpdate(float elapsedTime) override + { + const float scrollSpeed = 2.f; + for (const Ndk::EntityHandle& entity : GetEntities()) + { + auto& laserComponent = entity->GetComponent(); + for (Nz::Sprite& sprite : laserComponent.sprites) + { + Nz::Rectf rect = sprite.GetTextureCoords(); + rect.x = std::fmod(rect.x - elapsedTime * scrollSpeed, rect.width); + + sprite.SetTextureCoords(rect); + } + } + } + + static Ndk::SystemIndex systemIndex; + + private: + const ExampleShared& m_sharedData; +}; +Ndk::SystemIndex LaserBeamSystem::systemIndex; + +class SpaceshipSystem : public Ndk::System +{ + public: + SpaceshipSystem(const ExampleShared& sharedData) : + m_sharedData(sharedData) + { + Requires(); + } + + void OnEntityAdded(Ndk::Entity* entity) override + { + std::uniform_real_distribution pitchDis(0.8f, 1.5f); + + auto& nodeComponent = entity->GetComponent(); + auto& spaceshipComponent = entity->GetComponent(); + + spaceshipComponent.engineSound.SetPosition(nodeComponent.GetPosition()); + spaceshipComponent.engineSound.Play(); + spaceshipComponent.engineSound.EnableLooping(true); + + spaceshipComponent.laserSound.SetPitch(pitchDis(m_sharedData.randomGen)); + } + + void OnUpdate(float elapsedTime) override + { + const float escapeMaxDist = 50.f; + const float speed = 200.f; + + Nz::UInt64 curTime = Nz::GetElapsedMilliseconds(); + std::uniform_real_distribution dis(-escapeMaxDist, escapeMaxDist); + + for (const Ndk::EntityHandle& entity : GetEntities()) + { + auto& nodeComponent = entity->GetComponent(); + auto& spaceshipComponent = entity->GetComponent(); + auto& velocityComponent = entity->GetComponent(); + + //< I agree, I need some kind of SoundEmitterComponent + spaceshipComponent.engineSound.SetPosition(nodeComponent.GetPosition()); + spaceshipComponent.engineSound.SetVelocity(velocityComponent.linearVelocity); + + spaceshipComponent.hitSound.SetPosition(nodeComponent.GetPosition()); + spaceshipComponent.hitSound.SetVelocity(velocityComponent.linearVelocity); + + spaceshipComponent.laserSound.SetPosition(nodeComponent.GetPosition()); + spaceshipComponent.laserSound.SetVelocity(velocityComponent.linearVelocity); + + Nz::Vector3f targetDir = spaceshipComponent.targetPos - nodeComponent.GetPosition(); + targetDir.Normalize(); + + Nz::Quaternionf targetRotation = Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), targetDir); + + nodeComponent.SetRotation(Nz::Quaternionf::Slerp(nodeComponent.GetRotation(), targetRotation, elapsedTime * 1.5f)); + + Nz::Vector3f actualDir = nodeComponent.GetForward(); + float sqDistance = spaceshipComponent.targetPos.SquaredDistance(nodeComponent.GetPosition()); + + if (spaceshipComponent.attacking) + { + float dotProduct = targetDir.DotProduct(actualDir); + if (dotProduct > 0.9f && sqDistance < (150.f * 150.f) && !entity->HasComponent()) + { + auto& laserBeam = entity->AddComponent(); + laserBeam.origin = Nz::Vector3f::Forward() * 12.f + Nz::Vector3f::Down() * 2.f; + } + + if (sqDistance < (100.f * 100.f)) + { + entity->RemoveComponent(); + + spaceshipComponent.targetPos -= Nz::Vector3f(dis(m_sharedData.randomGen), dis(m_sharedData.randomGen), dis(m_sharedData.randomGen)) * -actualDir * escapeMaxDist / 2.f; + spaceshipComponent.attacking = false; + } + } + else if (sqDistance < (50.f * 50.f) && spaceshipComponent.hitTime == 0) + { + spaceshipComponent.targetPos = Nz::Vector3f::Zero(); + spaceshipComponent.attacking = true; + } + + if (spaceshipComponent.hitTime == 0 || curTime - spaceshipComponent.hitTime <= 1000) + velocityComponent.linearVelocity = actualDir * speed; + else if (curTime - spaceshipComponent.hitTime > 10000) + entity->Kill(); + } + } + + static Ndk::SystemIndex systemIndex; + + private: + const ExampleShared& m_sharedData; +}; +Ndk::SystemIndex SpaceshipSystem::systemIndex; + +struct TorpedoParticle +{ + Nz::Color color; + Nz::Vector2f size; + Nz::Vector3f position; + Nz::Vector3f velocity; + float rotation; + float life; +}; + +SpacebattleExample::SpacebattleExample(ExampleShared& sharedData) : +ParticleDemo("Space battle", sharedData) +{ + Ndk::InitializeComponent("Lasrbeam"); + Ndk::InitializeComponent("Spceship"); + Ndk::InitializeSystem(); + Ndk::InitializeSystem(); + + Nz::ModelParameters parameters; + parameters.mesh.optimizeIndexBuffers = false; + + Nz::Color grey(100, 100, 100); + + if (!m_turret.baseModel.LoadFromFile("resources/Turret/base.obj", parameters)) + NazaraWarning("Failed to load base.obj"); + + for (unsigned int i = 0; i < m_turret.baseModel.GetMaterialCount(); ++i) + m_turret.baseModel.GetMaterial(i)->SetDiffuseColor(grey); + + if (!m_turret.rotatingBaseModel.LoadFromFile("resources/Turret/rotating_base.obj", parameters)) + NazaraWarning("Failed to load rotating_base.obj"); + + for (unsigned int i = 0; i < m_turret.rotatingBaseModel.GetMaterialCount(); ++i) + m_turret.rotatingBaseModel.GetMaterial(i)->SetDiffuseColor(grey); + + if (!m_turret.cannonBaseModel.LoadFromFile("resources/Turret/cannon_base.obj", parameters)) + NazaraWarning("Failed to load cannon_base.obj"); + + for (unsigned int i = 0; i < m_turret.cannonBaseModel.GetMaterialCount(); ++i) + m_turret.cannonBaseModel.GetMaterial(i)->SetDiffuseColor(grey); + + parameters.mesh.texCoordScale.Set(40.f, 40.f); + parameters.mesh.matrix = Nz::Matrix4f::Rotate(Nz::EulerAnglesf(0.f, 180.f, 0.f)); + if (!m_turret.cannonModel.LoadFromFile("resources/Turret/cannon.obj", parameters)) + NazaraWarning("Failed to load cannon.obj"); + + // Since OBJ don't support normal maps.. + m_turret.cannonModel.GetMaterial(0)->SetNormalMap("resources/Turret/198_norm.jpg"); + + parameters.mesh.matrix.MakeIdentity(); + parameters.mesh.texCoordScale.Set(1.f, 1.f); + + parameters.mesh.center = true; + if (!m_spacestationModel.LoadFromFile("resources/SpaceStation/space_station.obj", parameters)) + NazaraWarning("Failed to load space_station.obj"); + + parameters.mesh.texCoordScale.Set(1.f, -1.f); + parameters.mesh.matrix.MakeRotation(Nz::EulerAnglesf(0.f, -90.f, 0.f)); + + if (!m_spaceshipModel.LoadFromFile("resources/space_frigate_6/space_frigate_6.obj", parameters)) + NazaraWarning("Failed to load space_frigate_6.obj"); + + // Since OBJ don't support normal maps.. + for (unsigned int i = 0; i < m_spaceshipModel.GetMaterialCount(); ++i) + { + m_spaceshipModel.GetMaterial(i)->SetEmissiveMap("resources/space_frigate_6/space_frigate_6_illumination.jpg"); + m_spaceshipModel.GetMaterial(i)->SetNormalMap("resources/space_frigate_6/space_frigate_6_normal.png"); + } + + Nz::TextureRef skyboxCubemap = Nz::Texture::New(); + if (skyboxCubemap->Create(Nz::ImageType_Cubemap, Nz::PixelFormatType_RGBA8, 2048, 2048)) + { + skyboxCubemap->LoadFaceFromFile(Nz::CubemapFace_PositiveX, "resources/purple_nebula_skybox/purple_nebula_skybox_right1.png"); + skyboxCubemap->LoadFaceFromFile(Nz::CubemapFace_PositiveY, "resources/purple_nebula_skybox/purple_nebula_skybox_top3.png"); + skyboxCubemap->LoadFaceFromFile(Nz::CubemapFace_PositiveZ, "resources/purple_nebula_skybox/purple_nebula_skybox_front5.png"); + skyboxCubemap->LoadFaceFromFile(Nz::CubemapFace_NegativeX, "resources/purple_nebula_skybox/purple_nebula_skybox_left2.png"); + skyboxCubemap->LoadFaceFromFile(Nz::CubemapFace_NegativeY, "resources/purple_nebula_skybox/purple_nebula_skybox_bottom4.png"); + skyboxCubemap->LoadFaceFromFile(Nz::CubemapFace_NegativeZ, "resources/purple_nebula_skybox/purple_nebula_skybox_back6.png"); + + m_skybox.SetTexture(std::move(skyboxCubemap)); + } + + m_torpedoDeclaration = Nz::ParticleDeclaration::New(); + m_torpedoDeclaration->EnableComponent(Nz::ParticleComponent_Color, Nz::ComponentType_Color, NazaraOffsetOf(TorpedoParticle, color)); + m_torpedoDeclaration->EnableComponent(Nz::ParticleComponent_Position, Nz::ComponentType_Float3, NazaraOffsetOf(TorpedoParticle, position)); + m_torpedoDeclaration->EnableComponent(Nz::ParticleComponent_Rotation, Nz::ComponentType_Float1, NazaraOffsetOf(TorpedoParticle, rotation)); + m_torpedoDeclaration->EnableComponent(Nz::ParticleComponent_Size, Nz::ComponentType_Float2, NazaraOffsetOf(TorpedoParticle, size)); + m_torpedoDeclaration->EnableComponent(Nz::ParticleComponent_Life, Nz::ComponentType_Float1, NazaraOffsetOf(TorpedoParticle, life)); + m_torpedoDeclaration->EnableComponent(Nz::ParticleComponent_Velocity, Nz::ComponentType_Float3, NazaraOffsetOf(TorpedoParticle, velocity)); + + Nz::TextureSampler diffuseSampler; + diffuseSampler.SetWrapMode(Nz::SamplerWrap_Repeat); + + Nz::MaterialRef material = Nz::Material::New("Translucent3D"); + material->SetDiffuseMap("resources/LaserBeam.png"); + material->SetDiffuseSampler(diffuseSampler); + + Nz::MaterialLibrary::Register("LaserBeam", std::move(material)); + + Nz::MaterialRef sparkleMat1 = Nz::Material::New("Translucent3D"); + + sparkleMat1->SetDiffuseMap("resources/flare1.png"); + Nz::MaterialLibrary::Register("TorpedoFlare1", std::move(sparkleMat1)); + + m_spaceshipTemplate = m_shared.world3D->CreateEntity(); + m_spaceshipTemplate->Enable(false); + + auto& gfxComponent = m_spaceshipTemplate->AddComponent(); + auto& nodeComponent = m_spaceshipTemplate->AddComponent(); + auto& velocityComponent = m_spaceshipTemplate->AddComponent(); + auto& spaceshipComponent = m_spaceshipTemplate->AddComponent(); + gfxComponent.Attach(&m_spaceshipModel); + + m_ambientMusic.OpenFromFile("resources/ambience.ogg"); + m_ambientMusic.SetVolume(60.f); +} + +void SpacebattleExample::Enter(Ndk::StateMachine& fsm) +{ + ParticleDemo::Enter(fsm); + + m_shared.world3D->AddSystem(m_shared); + m_shared.world3D->AddSystem(m_shared); + + Ndk::RenderSystem& renderSystem2D = m_shared.world2D->GetSystem(); + Ndk::RenderSystem& renderSystem3D = m_shared.world3D->GetSystem(); + renderSystem2D.SetDefaultBackground(nullptr); + renderSystem3D.SetDefaultBackground(&m_skybox); + + CreateSpaceShip(); + CreateTurret(); + + Ndk::EntityHandle light = m_shared.world3D->CreateEntity(); + Ndk::NodeComponent& lightNode = light->AddComponent(); + Ndk::LightComponent& lightComp = light->AddComponent(Nz::LightType_Directional); + lightNode.SetRotation(Nz::EulerAnglesf(-30.f, 0.f, 0.f)); + RegisterEntity(light); + + Ndk::NodeComponent& cameraNode = m_shared.viewer3D->GetComponent(); + cameraNode.SetParent(m_turret.cannonAnchorEntity); + cameraNode.SetPosition(Nz::Vector3f::Up() * 4.f - Nz::Vector3f::Backward() * 6.f); + cameraNode.SetRotation(Nz::EulerAnglesf(0.f, 180.f, 0.f)); + + m_introTimer = 10.f; + m_spaceshipSpawnCounter = -5.f; + m_turretBaseRotation = 0.f; + m_turretCannonBaseRotation = 0.f; + m_turretShootTimer = 0.f; + + Ndk::EntityHandle torpedoGroupEntity = m_shared.world3D->CreateEntity(); + m_torpedoGroup = torpedoGroupEntity->AddComponent(200, m_torpedoDeclaration).CreateHandle(); + RegisterParticleGroup(torpedoGroupEntity); + + m_torpedoGroup->AddController(Nz::ParticleFunctionController::New([] (Nz::ParticleGroup& group, Nz::ParticleMapper& mapper, unsigned int startId, unsigned int endId, float elapsedTime) + { + auto positionPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Position); + auto lifePtr = mapper.GetComponentPtr(Nz::ParticleComponent_Life); + auto rotationPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Rotation); + auto velocityPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Velocity); + + for (unsigned int i = startId; i <= endId; ++i) + { + rotationPtr[i] += elapsedTime * 90.f; + positionPtr[i] += velocityPtr[i] * elapsedTime; + + lifePtr[i] -= elapsedTime; + if (lifePtr[i] < 0.f) + group.KillParticle(i); + } + })); + + + m_torpedoGroup->AddController(Nz::ParticleFunctionController::New([this] (Nz::ParticleGroup& group, Nz::ParticleMapper& mapper, unsigned int startId, unsigned int endId, float elapsedTime) + { + auto positionPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Position); + auto rotationPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Rotation); + auto sizePtr = mapper.GetComponentPtr(Nz::ParticleComponent_Size); + auto velocityPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Velocity); + + auto& spaceshipSystem = m_shared.world3D->GetSystem(); + + for (unsigned int i = startId; i <= endId; ++i) + { + Nz::Spheref torpedoSphere(positionPtr[i], std::max(sizePtr[i].x, sizePtr[i].y) * 0.1f); + + for (const Ndk::EntityHandle& entity : spaceshipSystem.GetEntities()) + { + auto& spaceshipNode = entity->GetComponent(); + + Nz::Spheref spaceshipSphere(spaceshipNode.GetPosition(), 10.f); + if (torpedoSphere.Intersect(spaceshipSphere)) + { + entity->RemoveComponent(); + + group.KillParticle(i); + + const float hitMaxDist = 500.f; + + std::uniform_real_distribution dis(-hitMaxDist, hitMaxDist); + + auto& spaceshipComponent = entity->GetComponent(); + spaceshipComponent.attacking = false; + spaceshipComponent.engineSound.Stop(); + spaceshipComponent.hitSound.Play(); + spaceshipComponent.hitTime = Nz::GetElapsedMilliseconds(); + spaceshipComponent.targetPos = Nz::Vector3f(dis(m_shared.randomGen), dis(m_shared.randomGen), dis(m_shared.randomGen)); + + auto& emitter = entity->AddComponent(); + emitter.SetEmissionCount(2); + emitter.SetEmissionRate(200.f); + + emitter.SetSetupFunc([this] (const Ndk::EntityHandle& entity, Nz::ParticleMapper& mapper, unsigned int count) + { + auto& gen = m_shared.randomGen; + + const float maxFireVel = 15.f; + std::uniform_real_distribution lifeDis(-0.5f, 0.5f); + std::uniform_real_distribution normalDis(-1.f, 1.f); + std::uniform_real_distribution posDis(-0.1f, 0.1f); + std::uniform_real_distribution rotDis(-180.f, 180.f); + std::uniform_real_distribution sizeDis(1.0f, 4.f); + std::uniform_real_distribution velDis(-maxFireVel, maxFireVel); + + Nz::Vector3f pos = entity->GetComponent().GetPosition(); + + Nz::ParticleStruct_Billboard* billboards = static_cast(mapper.GetPointer()); + Nz::ParticleStruct_Billboard* smokeParticles = static_cast(m_smokeGroup->CreateParticles(count)); + for (unsigned int i = 0; i < count; ++i) + { + billboards[i].color = Nz::Color::White; + billboards[i].life = 1.f + lifeDis(gen); + billboards[i].position = pos + Nz::Vector3f(posDis(gen), posDis(gen), posDis(gen)); + billboards[i].rotation = rotDis(gen); + billboards[i].size = {1.28f, 1.28f}; + billboards[i].size *= sizeDis(gen); + billboards[i].velocity.Set(normalDis(gen), normalDis(gen), normalDis(gen)); + billboards[i].velocity.Normalize(); + billboards[i].velocity *= velDis(gen); + + smokeParticles[i].color = Nz::Color(128, 128, 128, 0); + smokeParticles[i].life = maxSmokeLife; + smokeParticles[i].position = billboards[i].position; + smokeParticles[i].rotation = billboards[i].rotation; + smokeParticles[i].size = {2.56f, 2.56f}; + smokeParticles[i].size *= sizeDis(gen); + smokeParticles[i].velocity = billboards[i].velocity / 2.f; + } + }); + m_fireGroup->AddEmitter(entity); + + break; + } + } + } + })); + + m_torpedoGroup->SetRenderer(Nz::ParticleFunctionRenderer::New([sparkleMat1 = Nz::MaterialLibrary::Get("TorpedoFlare1")] (const Nz::ParticleGroup& group, const Nz::ParticleMapper& mapper, unsigned int startId, unsigned int endId, Nz::AbstractRenderQueue* renderQueue) + { + auto positionPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Position); + auto rotationPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Rotation); + auto sizePtr = mapper.GetComponentPtr(Nz::ParticleComponent_Size); + auto velocityPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Velocity); + + renderQueue->AddBillboards(0, sparkleMat1, endId - startId + 1, positionPtr, sizePtr, rotationPtr); + for (unsigned int i = startId; i <= endId; ++i) + { + Nz::AbstractRenderQueue::PointLight pointLight; + pointLight.ambientFactor = 0.f; + pointLight.attenuation = 0.9f; + pointLight.color = Nz::Color::Cyan; + pointLight.diffuseFactor = 1.f; + pointLight.position = positionPtr[i]; + pointLight.radius = std::max(sizePtr[i].x, sizePtr[i].y) * 2.f; + pointLight.invRadius = 1.f / pointLight.radius; + pointLight.shadowMap = nullptr; + + renderQueue->AddPointLight(pointLight); + } + })); + + + ////////////////////////////////////////////////////////////////////////// + + Ndk::EntityHandle fireGroupEntity = m_shared.world3D->CreateEntity(); + m_fireGroup = fireGroupEntity->AddComponent(40000, Nz::ParticleDeclaration::Get(Nz::ParticleLayout_Billboard)).CreateHandle(); + RegisterParticleGroup(fireGroupEntity); + + Ndk::EntityHandle smokeGroupEntity = m_shared.world3D->CreateEntity(); + m_smokeGroup = smokeGroupEntity->AddComponent(40000, Nz::ParticleDeclaration::Get(Nz::ParticleLayout_Billboard)).CreateHandle(); + RegisterParticleGroup(smokeGroupEntity); + + auto movementController = Nz::ParticleFunctionController::New([this] (Nz::ParticleGroup& group, Nz::ParticleMapper& mapper, unsigned int startId, unsigned int endId, float elapsedTime) + { + auto lifePtr = mapper.GetComponentPtr(Nz::ParticleComponent_Life); + auto posPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Position); + auto sizePtr = mapper.GetComponentPtr(Nz::ParticleComponent_Size); + auto velPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Velocity); + + auto& spaceshipSystem = m_shared.world3D->GetSystem(); + + const Nz::Vector2f sizeGrowth(0.5f); + + float velFactor = std::pow(0.9f, elapsedTime * 15.f); + for (unsigned int i = startId; i <= endId; ++i) + { + float& remainingLife = lifePtr[i]; + + remainingLife -= elapsedTime; + if (remainingLife <= 0.f) + { + group.KillParticle(i); + continue; + } + + Nz::Vector3f& position = posPtr[i]; + Nz::Vector2f& size = sizePtr[i]; + Nz::Vector3f& velocity = velPtr[i]; + + position += velPtr[i] * elapsedTime; + size += sizeGrowth * elapsedTime; + velocity *= (velocity.GetSquaredLength() >= 1.f) ? velFactor : 1.f; + + if (remainingLife <= 18.f) + { + for (const Ndk::EntityHandle& entity : spaceshipSystem.GetEntities()) + { + auto& spaceshipNode = entity->GetComponent(); + + Nz::Spheref spaceshipSphere(spaceshipNode.GetPosition(), 5.f); + if (spaceshipSphere.Contains(position)) + { + auto& spaceshipVel = entity->GetComponent(); + + Nz::Vector3f force = spaceshipVel.linearVelocity * 2.f + (position - spaceshipSphere.GetPosition()) * 10.f; + velocity += force * elapsedTime; + } + } + + TorpedoParticle* torpedos = static_cast(m_torpedoGroup->GetBuffer()); + std::size_t torpedoCount = m_torpedoGroup->GetParticleCount(); + for (std::size_t j = 0; j < torpedoCount; ++j) + { + Nz::Spheref tordedoSphere(torpedos[j].position, 5.f); + + if (tordedoSphere.Contains(position)) + { + Nz::Spheref tordedoCenter(torpedos[j].position, 2.f); + if (tordedoCenter.Contains(position)) + { + group.KillParticle(i); + break; + } + + Nz::Vector3f dir = (torpedos[j].position - position); + float length; + dir.Normalize(&length); + + remainingLife -= 100.f * elapsedTime / length; + size -= 100.f * sizeGrowth * elapsedTime / length; + velocity += 500.f * dir * elapsedTime / length; + velocity += torpedos[j].velocity * elapsedTime; + + break; //< There's no way a particle would be in multiple torpedo at once + } + } + } + } + }); + + m_fireGroup->AddController(movementController); + m_fireGroup->AddController(Nz::ParticleFunctionController::New([] (Nz::ParticleGroup& group, Nz::ParticleMapper& mapper, unsigned int startId, unsigned int endId, float elapsedTime) + { + auto colorPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Color); + auto lifePtr = mapper.GetComponentPtr(Nz::ParticleComponent_Life); + + float velFactor = std::pow(0.9f, elapsedTime / 0.1f); + for (unsigned int i = startId; i <= endId; ++i) + colorPtr[i].a = static_cast(Nz::Clamp(lifePtr[i] * 255.f, 0.f, 255.f)); + })); + + m_smokeGroup->AddController(movementController); + m_smokeGroup->AddController(Nz::ParticleFunctionController::New([] (Nz::ParticleGroup& group, Nz::ParticleMapper& mapper, unsigned int startId, unsigned int endId, float elapsedTime) + { + auto colorPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Color); + auto lifePtr = mapper.GetComponentPtr(Nz::ParticleComponent_Life); + + for (unsigned int i = startId; i <= endId; ++i) + { + float alpha = std::min((maxSmokeLife - lifePtr[i]) * 255.f / 5.f, 255.f); + alpha -= std::max((maxSmokeLife - lifePtr[i]) / maxSmokeLife * 255.f, 0.f); + + colorPtr[i].a = static_cast(Nz::Clamp(alpha, 0.f, 255.f)); + } + })); + + Nz::MaterialRef fireMat = Nz::Material::New("Translucent3D"); + fireMat->EnableFaceCulling(true); + fireMat->SetDiffuseMap("resources/fire_particle.png"); + // Additive blending for fire + fireMat->SetDstBlend(Nz::BlendFunc_One); + fireMat->SetSrcBlend(Nz::BlendFunc_SrcAlpha); + + Nz::MaterialRef smokeMat = Nz::Material::New("Translucent3D"); + smokeMat->EnableFaceCulling(true); + smokeMat->SetDiffuseColor(Nz::Color(128, 128, 128)); + smokeMat->SetDiffuseMap("resources/smoke.png"); + + m_fireGroup->SetRenderer(Nz::ParticleFunctionRenderer::New([fireMat] (const Nz::ParticleGroup& group, const Nz::ParticleMapper& mapper, unsigned int startId, unsigned int endId, Nz::AbstractRenderQueue* renderQueue) + { + auto colorPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Color); + auto posPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Position); + auto rotPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Rotation); + auto sizePtr = mapper.GetComponentPtr(Nz::ParticleComponent_Size); + + renderQueue->AddBillboards(0, fireMat, endId - startId + 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) + { + auto colorPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Color); + auto posPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Position); + auto rotPtr = mapper.GetComponentPtr(Nz::ParticleComponent_Rotation); + auto sizePtr = mapper.GetComponentPtr(Nz::ParticleComponent_Size); + + renderQueue->AddBillboards(0, smokeMat, endId - startId + 1, posPtr, sizePtr, rotPtr, colorPtr); + })); + + ////////////////////////////////////////////////////////////////////////// + + m_ambientMusic.Play(); + m_turretFireSound.LoadFromFile("resources/turretFire.wav"); + m_turretReloadSound.LoadFromFile("resources/turretReload.wav"); + + //m_onMouseMoved.Connect(m_shared.target->GetEventHandler().OnMouseMoved, this, &SpacebattleExample::OnMouseMoved); + //m_shared.target->SetCursor(Nz::WindowCursor_None); + + ////////////////////////////////////////////////////////////////////////// + + Nz::TextSpriteRef introText = Nz::TextSprite::New(); + introText->Update(Nz::SimpleTextDrawer::Draw("--Tourelle de défense du secteur A407M2--\nLes contrôles ont été adaptés à vos contrôleurs:\nZQSD pour orienter la tourelle, espace pour tirer.\n", 72)); + introText->SetScale(0.5f); + + m_introText = m_shared.world3D->CreateEntity(); + Ndk::NodeComponent& introNode = m_introText->AddComponent(); + Ndk::GraphicsComponent& introGfx = m_introText->AddComponent(); + introGfx.Attach(introText, 1); + RegisterEntity(m_introText); + + Ndk::NodeComponent& cannonNode = m_turret.cannonEntity->GetComponent(); + + Nz::Boxf introAABB = introGfx.GetBoundingVolume().aabb; + introNode.SetPosition(cannonNode.GetForward() * 500.f + introNode.GetLeft() * introAABB.width / 2.f + introNode.GetUp() * introAABB.height / 2.f); +} + +void SpacebattleExample::Leave(Ndk::StateMachine& fsm) +{ + m_ambientMusic.Stop(); + m_shared.world3D->RemoveSystem(); + m_shared.world3D->RemoveSystem(); + m_turretFireSound.Stop(); + m_turretReloadSound.Stop(); + + ParticleDemo::Leave(fsm); +} + +bool SpacebattleExample::Update(Ndk::StateMachine& fsm, float elapsedTime) +{ + if (!ParticleDemo::Update(fsm, elapsedTime)) + return false; + + const float speed = 100.f; + + if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::Z)) + m_turretCannonBaseRotation = std::max(m_turretCannonBaseRotation - speed * elapsedTime, -65.f); + + if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::S)) + m_turretCannonBaseRotation = std::min(m_turretCannonBaseRotation + speed * elapsedTime, 40.f); + + if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::Q)) + m_turretBaseRotation += speed * elapsedTime; + + if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::D)) + m_turretBaseRotation -= speed * elapsedTime; + + m_turret.cannonBaseEntity->GetComponent().SetRotation(Nz::EulerAnglesf(m_turretCannonBaseRotation, 0.f, 0.f)); + m_turret.rotatingBaseEntity->GetComponent().SetRotation(Nz::EulerAnglesf(0.f, m_turretBaseRotation, 0.f)); + + bool discharged = m_turretShootTimer < 1.f; + if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::Space) && !discharged) + { + m_turretFireSound.Play(); + + m_turretShootTimer = -1.f; + + Ndk::NodeComponent& cannonNode = m_turret.cannonEntity->GetComponent(); + + TorpedoParticle* particle = static_cast(m_torpedoGroup->CreateParticle()); + particle->color = Nz::Color::White; + particle->position = cannonNode.ToGlobalPosition(Nz::Vector3f::Forward() * 10.f); + particle->rotation = 0.f; + particle->life = 15.f; + particle->size.Set(13.34f, 7.41f); + particle->size *= 2.f; + particle->velocity = cannonNode.GetForward() * 100.f; + } + + m_turretShootTimer += elapsedTime * 2.f; + if (discharged && m_turretShootTimer >= 1.f) + m_turretReloadSound.Play(); + + m_turret.cannonEntity->GetComponent().SetPosition(Nz::Vector3f::Backward() * std::sin(std::min(m_turretShootTimer, 0.f) * float(M_PI)) * 3.f); + + m_spaceshipSpawnCounter += elapsedTime; + if (m_spaceshipSpawnCounter >= 10.f) + { + m_spaceshipSpawnCounter -= 10.f; + + auto& spacestationNode = m_spacestationEntity->GetComponent(); + + Ndk::EntityHandle spaceship = m_spaceshipTemplate->Clone(); + RegisterEntity(spaceship); + auto& nodeComponent = spaceship->GetComponent(); + auto& spaceshipComponent = spaceship->GetComponent(); + + spaceshipComponent.targetPos = m_shared.viewer3D->GetComponent().GetPosition(); + nodeComponent.SetPosition(spacestationNode.GetPosition()); + nodeComponent.SetRotation(Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), spacestationNode.GetRight())); + nodeComponent.Move(Nz::Vector3f::Forward() * 15.f + Nz::Vector3f::Down() * 5.f, Nz::CoordSys_Local); + } + + m_introTimer -= elapsedTime; + if (m_introTimer <= 0.f && m_introText) + m_introText->Kill(); + + return true; +} + +void SpacebattleExample::CreateSpaceShip() +{ + m_spacestationEntity = m_shared.world3D->CreateEntity(); + RegisterEntity(m_spacestationEntity); + + Ndk::NodeComponent& spacestationNode = m_spacestationEntity->AddComponent(); + spacestationNode.SetPosition(Nz::Vector3f::Forward() * 500.f + Nz::Vector3f::Up() * 200.f + Nz::Vector3f::Right() * 250.f); + spacestationNode.SetRotation(Nz::EulerAnglesf(0.f, 15.f, 0.f)); + spacestationNode.SetScale(0.1f); + + Ndk::GraphicsComponent& spacestationGfx = m_spacestationEntity->AddComponent(); + spacestationGfx.Attach(&m_spacestationModel); +} + +void SpacebattleExample::CreateTurret() +{ + // Fixed base + m_turret.baseEntity = m_shared.world3D->CreateEntity(); + RegisterEntity(m_turret.baseEntity); + + Ndk::NodeComponent& baseNode = m_turret.baseEntity->AddComponent(); + //baseNode.SetParent(m_spacestationEntity); + baseNode.SetRotation(Nz::EulerAnglesf(0.f, 180.f, 0.f)); + + Ndk::GraphicsComponent& baseGfx = m_turret.baseEntity->AddComponent(); + baseGfx.Attach(&m_turret.baseModel); + + // Rotating base + m_turret.rotatingBaseEntity = m_shared.world3D->CreateEntity(); + RegisterEntity(m_turret.rotatingBaseEntity); + + Ndk::NodeComponent& rotatingBaseNode = m_turret.rotatingBaseEntity->AddComponent(); + rotatingBaseNode.SetParent(m_turret.baseEntity); + + Ndk::GraphicsComponent& rotatingBaseGfx = m_turret.rotatingBaseEntity->AddComponent(); + rotatingBaseGfx.Attach(&m_turret.rotatingBaseModel); + + // Cannon base + m_turret.cannonBaseEntity = m_shared.world3D->CreateEntity(); + RegisterEntity(m_turret.cannonBaseEntity); + + Ndk::NodeComponent& cannonBaseNode = m_turret.cannonBaseEntity->AddComponent(); + cannonBaseNode.SetPosition({0.f, 3.39623547f, 0.f}); + cannonBaseNode.SetParent(m_turret.rotatingBaseEntity); + + Ndk::GraphicsComponent& cannonBaseGfx = m_turret.cannonBaseEntity->AddComponent(); + cannonBaseGfx.Attach(&m_turret.cannonBaseModel); + + // Cannon anchor + m_turret.cannonAnchorEntity = m_shared.world3D->CreateEntity(); + RegisterEntity(m_turret.cannonAnchorEntity); + + Ndk::NodeComponent& cannonAnchorNode = m_turret.cannonAnchorEntity->AddComponent(); + cannonAnchorNode.SetPosition({0.f, 2.96482944f, 3.20705462f}); + cannonAnchorNode.SetParent(m_turret.cannonBaseEntity); + + // Cannon + m_turret.cannonEntity = m_shared.world3D->CreateEntity(); + RegisterEntity(m_turret.cannonEntity); + + Ndk::NodeComponent& cannonNode = m_turret.cannonEntity->AddComponent(); + cannonNode.SetParent(m_turret.cannonAnchorEntity); + cannonNode.SetRotation(Nz::EulerAnglesf(0.f, 180.f, 0.f)); + + Ndk::GraphicsComponent& cannonGfx = m_turret.cannonEntity->AddComponent(); + cannonGfx.Attach(&m_turret.cannonModel); +} + +void SpacebattleExample::OnMouseMoved(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::MouseMoveEvent& event) +{ + const float speed = 0.1f; + + m_turretCannonBaseRotation = Nz::Clamp(m_turretCannonBaseRotation + speed * event.deltaY, -65.f, 40.f); + m_turretBaseRotation -= event.deltaX * speed; + + Nz::Mouse::SetPosition(m_shared.target->GetWidth() / 2, m_shared.target->GetHeight() / 2, *m_shared.target); +} diff --git a/examples/Particles/SpacebattleDemo.hpp b/examples/Particles/SpacebattleDemo.hpp new file mode 100644 index 000000000..44852a61f --- /dev/null +++ b/examples/Particles/SpacebattleDemo.hpp @@ -0,0 +1,71 @@ +#pragma once + +#ifndef NAZARA_EXAMPLES_PARTICLES_SPACEBATTLE_HPP +#define NAZARA_EXAMPLES_PARTICLES_SPACEBATTLE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Common.hpp" + +class SpacebattleExample : public ParticleDemo +{ + public: + SpacebattleExample(ExampleShared& sharedData); + ~SpacebattleExample() = default; + + void Enter(Ndk::StateMachine& fsm) override; + void Leave(Ndk::StateMachine& fsm) override; + bool Update(Ndk::StateMachine& fsm, float elapsedTime) override; + + private: + void CreateSpaceShip(); + void CreateTurret(); + void OnMouseMoved(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::MouseMoveEvent& event); + + struct Turret + { + Nz::Model baseModel; + Nz::Model cannonModel; + Nz::Model cannonBaseModel; + Nz::Model rotatingBaseModel; + Ndk::EntityHandle baseEntity; + Ndk::EntityHandle cannonAnchorEntity; + Ndk::EntityHandle cannonEntity; + Ndk::EntityHandle cannonBaseEntity; + Ndk::EntityHandle rotatingBaseEntity; + }; + + Turret m_turret; + float m_introTimer; + float m_spaceshipSpawnCounter; + float m_turretBaseRotation; + float m_turretCannonBaseRotation; + float m_turretShootTimer; + Nz::Model m_spaceshipModel; + Nz::Model m_spacestationModel; + Nz::Music m_ambientMusic; + Nz::ParticleDeclarationRef m_torpedoDeclaration; + Nz::ParticleRendererRef m_laserBeamRenderer; + Nz::Sound m_turretFireSound; + Nz::Sound m_turretReloadSound; + Nz::SkyboxBackground m_skybox; + Ndk::EntityHandle m_introText; + Ndk::EntityHandle m_spaceshipTemplate; + Ndk::EntityHandle m_spacestationEntity; + Ndk::ParticleGroupComponentHandle m_fireGroup; + Ndk::ParticleGroupComponentHandle m_smokeGroup; + Ndk::ParticleGroupComponentHandle m_torpedoGroup; + + NazaraSlot(Nz::EventHandler, OnMouseMoved, m_onMouseMoved); +}; + +#endif // NAZARA_EXAMPLES_PARTICLES_SPACEBATTLE_HPP diff --git a/examples/Particles/build.lua b/examples/Particles/build.lua new file mode 100644 index 000000000..2e1a37801 --- /dev/null +++ b/examples/Particles/build.lua @@ -0,0 +1,13 @@ +EXAMPLE.Name = "Particles" + +EXAMPLE.EnableConsole = true + +EXAMPLE.Files = { + "*.hpp", + "*.inl", + "*.cpp" +} + +EXAMPLE.Libraries = { + "NazaraSDK" +} diff --git a/examples/Particles/main.cpp b/examples/Particles/main.cpp new file mode 100644 index 000000000..67bf99754 --- /dev/null +++ b/examples/Particles/main.cpp @@ -0,0 +1,202 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "LogoDemo.hpp" +#include "SpacebattleDemo.hpp" +#include + +int main() +{ + Nz::ContextParameters::defaultCompatibilityProfile = true; + + Ndk::Application app; + + // Mix all sounds in mono (in order to give them 3D position) + Nz::SoundBufferParams soundParams; + soundParams.forceMono = true; + + Nz::SoundBufferManager::SetDefaultParameters(soundParams); + + // Pour commencer le mode vidéo, celui-ci va définir la taille de la zone de rendu et le nombre de bits par pixels + Nz::VideoMode mode = Nz::VideoMode::GetDesktopMode(); // Nous récupérons le mode vidéo du bureau + + // Nous allons prendre les trois quarts de la résolution du bureau pour notre fenêtre + mode.width = 3 * mode.width / 4; + mode.height = 3 * mode.height / 4; + + Nz::ContextParameters targetParams; + targetParams.antialiasingLevel = 0; + + Nz::RenderWindow& window = app.AddWindow(mode, "Nazara demo - Particles", Nz::WindowStyle_Closable, targetParams); + //Nz::RenderWindow& window = app.AddWindow(Nz::VideoMode(1920, 1080), "Nazara demo - Particles", Nz::WindowStyle_Fullscreen, targetParams); + + Ndk::World& world3D = app.AddWorld(); + Ndk::World& world2D = app.AddWorld(); + + std::random_device randomDevice; + + ExampleShared shared; + shared.randomGen.seed(randomDevice()); + shared.target = &window; + shared.world2D = &world2D; + shared.world3D = &world3D; + + shared.demoName = Nz::TextSprite::New(); + shared.demoName->Update(Nz::SimpleTextDrawer::Draw("XX - DemoName", 48)); + + shared.fpsCount = Nz::TextSprite::New(); + shared.fpsCount->Update(Nz::SimpleTextDrawer::Draw("XXXXX FPS", 24)); + + shared.particleCount = Nz::TextSprite::New(); + shared.particleCount->Update(Nz::SimpleTextDrawer::Draw("XXXXX particles", 36)); + + world2D.GetSystem().SetGlobalUp(Nz::Vector3f::Down()); + world3D.GetSystem().ChangeRenderTechnique(); + + + Ndk::EntityHandle viewEntity = world2D.CreateEntity(); + viewEntity->AddComponent(); + + Ndk::CameraComponent& viewer = viewEntity->AddComponent(); + viewer.SetTarget(&window); + viewer.SetProjectionType(Nz::ProjectionType_Orthogonal); + + shared.viewer2D = viewEntity; + + Ndk::EntityHandle cameraEntity = world3D.CreateEntity(); + cameraEntity->AddComponent(); + cameraEntity->AddComponent(); + + Ndk::CameraComponent& camera = cameraEntity->AddComponent(); + camera.SetTarget(&window); + camera.SetZFar(10000.f); + + shared.viewer3D = cameraEntity; + + Ndk::EntityHandle demoNameEntity = world2D.CreateEntity(); + Ndk::NodeComponent& demoNameNode = demoNameEntity->AddComponent(); + Ndk::GraphicsComponent& demoNameGfx = demoNameEntity->AddComponent(); + demoNameGfx.Attach(shared.demoName, 1); + + Ndk::EntityHandle fpsCountEntity = world2D.CreateEntity(); + Ndk::NodeComponent& fpsNode = fpsCountEntity->AddComponent(); + Ndk::GraphicsComponent& fpsGfx = fpsCountEntity->AddComponent(); + fpsGfx.Attach(shared.fpsCount, 1); + + Ndk::EntityHandle particleCountEntity = world2D.CreateEntity(); + Ndk::NodeComponent& particleCountNode = particleCountEntity->AddComponent(); + Ndk::GraphicsComponent& particleCountGfx = particleCountEntity->AddComponent(); + particleCountGfx.Attach(shared.particleCount, 1); + + + Nz::Boxf fpsCountBox = fpsGfx.GetBoundingVolume().aabb; + Nz::Boxf particleCountBox = particleCountGfx.GetBoundingVolume().aabb; + + demoNameNode.SetPosition(5.f, 5.f); + particleCountNode.SetPosition(5.f, window.GetHeight() - particleCountBox.height - 5.f); + fpsNode.SetPosition(5.f, window.GetHeight() - fpsCountBox.height - particleCountBox.height - 5.f); + + + //shared.demos.push_back(std::make_shared(shared)); + shared.demos.push_back(std::make_shared(shared)); + + std::size_t demoIndex = 0; + Ndk::StateMachine stateMachine(shared.demos[demoIndex]); + + window.EnableEventPolling(true); + + while (app.Run()) + { + Nz::WindowEvent event; + while (window.PollEvent(&event)) + { + switch (event.type) + { + case Nz::WindowEventType_KeyPressed: + { + switch (event.key.code) + { + case Nz::Keyboard::Backspace: + stateMachine.ChangeState(stateMachine.GetCurrentState()); + break; + + case Nz::Keyboard::Escape: + app.Quit(); + break; + + case Nz::Keyboard::Left: + { + if (shared.demos.size() <= 1) + break; + + if (demoIndex == 0) + demoIndex = shared.demos.size(); + + demoIndex--; + stateMachine.ChangeState(shared.demos[demoIndex]); + break; + } + + case Nz::Keyboard::Right: + { + if (shared.demos.size() <= 1) + break; + + demoIndex++; + if (demoIndex == shared.demos.size()) + demoIndex = 0; + + stateMachine.ChangeState(shared.demos[demoIndex]); + break; + } + + case Nz::Keyboard::Pause: + { + auto& velocitySystem = shared.world3D->GetSystem(); + velocitySystem.Enable(!velocitySystem.IsEnabled()); + break; + } + + case Nz::Keyboard::F5: + { + Nz::Image screenshot; + screenshot.Create(Nz::ImageType_2D, Nz::PixelFormatType_RGBA8, 1920, 1080); + window.CopyToImage(&screenshot); + + static unsigned int counter = 1; + screenshot.SaveToFile("screenshot_" + Nz::String::Number(counter++) + ".png"); + break; + } + + default: + break; + } + break; + } + + case Nz::WindowEventType_Quit: + window.Close(); + break; + + default: + break; + } + } + + stateMachine.Update(app.GetUpdateTime()); + + window.Display(); + } + + return EXIT_SUCCESS; +} diff --git a/include/Nazara/Audio/Music.hpp b/include/Nazara/Audio/Music.hpp index f31882890..29e71fab7 100644 --- a/include/Nazara/Audio/Music.hpp +++ b/include/Nazara/Audio/Music.hpp @@ -73,6 +73,7 @@ namespace Nz bool FillAndQueueBuffer(unsigned int buffer); void MusicThread(); + void StopThread(); static MusicLoader::LoaderList s_loaders; }; diff --git a/include/Nazara/Core/ByteStream.hpp b/include/Nazara/Core/ByteStream.hpp index fe1516b06..fab7c8f4a 100644 --- a/include/Nazara/Core/ByteStream.hpp +++ b/include/Nazara/Core/ByteStream.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2015 Jérôme Leclercq +// Copyright (C) 2015 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 @@ -19,7 +19,7 @@ namespace Nz { public: inline ByteStream(Stream* stream = nullptr); - ByteStream(ByteArray* byteArray, UInt32 openMode = OpenMode_ReadWrite); + ByteStream(ByteArray* byteArray, OpenModeFlags openMode = OpenMode_ReadWrite); ByteStream(void* ptr, Nz::UInt64 size); ByteStream(const void* ptr, Nz::UInt64 size); ByteStream(const ByteStream&) = delete; @@ -36,7 +36,7 @@ namespace Nz inline void SetDataEndianness(Endianness endiannes); inline void SetStream(Stream* stream); - void SetStream(ByteArray* byteArray, UInt32 openMode = OpenMode_ReadWrite); + void SetStream(ByteArray* byteArray, OpenModeFlags openMode = OpenMode_ReadWrite); void SetStream(void* ptr, Nz::UInt64 size); void SetStream(const void* ptr, Nz::UInt64 size); diff --git a/include/Nazara/Core/Enums.hpp b/include/Nazara/Core/Enums.hpp index 7a5c161ab..765505575 100644 --- a/include/Nazara/Core/Enums.hpp +++ b/include/Nazara/Core/Enums.hpp @@ -7,6 +7,8 @@ #ifndef NAZARA_ENUMS_CORE_HPP #define NAZARA_ENUMS_CORE_HPP +#include + namespace Nz { enum CoordSys @@ -73,23 +75,31 @@ namespace Nz HashType_Max = HashType_Whirlpool }; - enum OpenModeFlags + enum OpenMode { - OpenMode_NotOpen = 0x00, // Use the current mod of opening + OpenMode_NotOpen, // Use the current mod of opening - OpenMode_Append = 0x01, // Disable writing on existing parts and put the cursor at the end - OpenMode_Lock = 0x02, // Disable modifying the file before it is open - OpenMode_MustExit = 0x04, // Fail if the file doesn't exists, even if opened in write mode - OpenMode_ReadOnly = 0x08, // Open in read only - OpenMode_Text = 0x10, // Open in text mod - OpenMode_Truncate = 0x20, // Create the file if it doesn't exist and empty it if it exists - OpenMode_WriteOnly = 0x40, // Open in write only, create the file if it doesn't exist + OpenMode_Append, // Disable writing on existing parts and put the cursor at the end + OpenMode_Lock, // Disable modifying the file before it is open + OpenMode_MustExist, // Fail if the file doesn't exists, even if opened in write mode + OpenMode_ReadOnly, // Open in read only + OpenMode_Text, // Open in text mod + OpenMode_Truncate, // Create the file if it doesn't exist and empty it if it exists + OpenMode_WriteOnly, // Open in write only, create the file if it doesn't exist - OpenMode_ReadWrite = OpenMode_ReadOnly | OpenMode_WriteOnly, // Open in read and write - - OpenMode_Max = OpenMode_WriteOnly * 2 - 1 + OpenMode_Max = OpenMode_WriteOnly }; + template<> + struct EnableFlagsOperators + { + static constexpr bool value = true; + }; + + using OpenModeFlags = Flags; + + constexpr OpenModeFlags OpenMode_ReadWrite = OpenMode_ReadOnly | OpenMode_WriteOnly; + enum ParameterType { ParameterType_Boolean, @@ -173,16 +183,24 @@ namespace Nz SphereType_Max = SphereType_UV }; - enum StreamOptionFlags + enum StreamOption { - StreamOption_None = 0, + StreamOption_None, - StreamOption_Sequential = 0x1, - StreamOption_Text = 0x2, + StreamOption_Sequential, + StreamOption_Text, - StreamOption_Max = StreamOption_Text * 2 - 1 + StreamOption_Max = StreamOption_Text }; + template<> + struct EnableFlagsOperators + { + static constexpr bool value = true; + }; + + using StreamOptionFlags = Flags; + enum Ternary { Ternary_False, diff --git a/include/Nazara/Core/File.hpp b/include/Nazara/Core/File.hpp index 59b2b5457..d4d1e6522 100644 --- a/include/Nazara/Core/File.hpp +++ b/include/Nazara/Core/File.hpp @@ -31,7 +31,7 @@ namespace Nz public: File(); File(const String& filePath); - File(const String& filePath, UInt32 openMode); + File(const String& filePath, OpenModeFlags openMode); File(const File&) = delete; File(File&& file) noexcept; ~File(); @@ -57,8 +57,8 @@ namespace Nz bool IsOpen() const; - bool Open(unsigned int openMode = OpenMode_NotOpen); - bool Open(const String& filePath, unsigned int openMode = OpenMode_NotOpen); + bool Open(OpenModeFlags openMode = OpenMode_NotOpen); + bool Open(const String& filePath, OpenModeFlags openMode = OpenMode_NotOpen); bool Rename(const String& newFilePath); diff --git a/include/Nazara/Core/Flags.hpp b/include/Nazara/Core/Flags.hpp new file mode 100644 index 000000000..e56d723e5 --- /dev/null +++ b/include/Nazara/Core/Flags.hpp @@ -0,0 +1,60 @@ +// Copyright (C) 2016 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_FLAGS_HPP +#define NAZARA_FLAGS_HPP + +#include +#include + +namespace Nz +{ + template + class Flags + { + static_assert(std::is_enum::value, "Type must be an enumeration"); + + public: + constexpr Flags(UInt32 value); + constexpr Flags(E enumVal); + + explicit constexpr operator bool() const; + explicit constexpr operator UInt32() const; + + constexpr Flags operator~() const; + constexpr Flags operator&(Flags rhs) const; + constexpr Flags operator|(Flags rhs) const; + constexpr Flags operator^(Flags rhs) const; + + constexpr bool operator==(Flags rhs) const; + constexpr bool operator!=(Flags rhs) const; + + /*constexpr*/ Flags& operator|=(Flags rhs); + /*constexpr*/ Flags& operator&=(Flags rhs); + /*constexpr*/ Flags& operator^=(Flags rhs); + + static constexpr UInt32 GetFlagValue(E enumValue); + + private: + UInt32 m_value; + }; + + // From: https://www.justsoftwaresolutions.co.uk/cplusplus/using-enum-classes-as-bitfields.html + template + struct EnableFlagsOperators + { + static constexpr bool value = false; + }; + + template constexpr std::enable_if_t::value, Flags> operator~(E lhs); + template constexpr std::enable_if_t::value, Flags> operator|(E lhs, E rhs); + template constexpr std::enable_if_t::value, Flags> operator&(E lhs, E rhs); + template constexpr std::enable_if_t::value, Flags> operator^(E lhs, E rhs); +} + +#include + +#endif // NAZARA_FLAGS_HPP diff --git a/include/Nazara/Core/Flags.inl b/include/Nazara/Core/Flags.inl new file mode 100644 index 000000000..7a23861a2 --- /dev/null +++ b/include/Nazara/Core/Flags.inl @@ -0,0 +1,134 @@ +// Copyright (C) 2015 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 + +#include +#include + +namespace Nz +{ + /*! + * \ingroup core + * \class Nz::Flags + * \brief Core class that represents a set of bits + * + * This class meets the requirements of Container, AllocatorAwareContainer, SequenceContainer + */ + + template + constexpr Flags::Flags(UInt32 value) : + m_value(value) + { + } + + template + constexpr Flags::Flags(E enumVal) : + Flags(GetFlagValue(enumVal)) + { + } + + template + constexpr Flags::operator bool() const + { + return m_value != 0; + } + + template + constexpr Flags::operator UInt32() const + { + return m_value; + } + + template + constexpr Flags Flags::operator~() const + { + return Flags(~m_value); + } + + template + constexpr Flags Flags::operator&(Flags rhs) const + { + return Flags(m_value & rhs.m_value); + } + + template + constexpr Flags Flags::operator|(Flags rhs) const + { + return Flags(m_value | rhs.m_value); + } + + template + constexpr Flags Flags::operator^(Flags rhs) const + { + return Flags(m_value ^ rhs.m_value); + } + + template + constexpr bool Flags::operator==(Flags rhs) const + { + return m_value == rhs.m_value; + } + + template + constexpr bool Flags::operator!=(Flags rhs) const + { + return !operator==(rhs); + } + + template + /*constexpr*/ Flags& Flags::operator|=(Flags rhs) + { + m_value |= rhs.m_value; + + return *this; + } + + template + /*constexpr*/ Flags& Flags::operator&=(Flags rhs) + { + m_value &= rhs.m_value; + + return *this; + } + + template + /*constexpr*/ Flags& Flags::operator^=(Flags rhs) + { + m_value ^= rhs.m_value; + + return *this; + } + + template + constexpr UInt32 Flags::GetFlagValue(E enumValue) + { + return 1U << static_cast(enumValue); + } + + + template + constexpr std::enable_if_t::value, Flags> operator~(E lhs) + { + return ~Flags(lhs); + } + + template + constexpr std::enable_if_t::value, Flags> operator|(E lhs, E rhs) + { + return Flags(lhs) | rhs; + } + + template + constexpr std::enable_if_t::value, Flags> operator&(E lhs, E rhs) + { + return Flags(lhs) & rhs; + } + + template + constexpr std::enable_if_t::value, Flags> operator^(E lhs, E rhs) + { + return Flags(lhs) ^ rhs; + } +} + +#include diff --git a/include/Nazara/Core/MemoryStream.hpp b/include/Nazara/Core/MemoryStream.hpp index f5d15fcf0..929e8e5bd 100644 --- a/include/Nazara/Core/MemoryStream.hpp +++ b/include/Nazara/Core/MemoryStream.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2015 Jérôme Leclercq +// Copyright (C) 2015 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 @@ -18,7 +18,7 @@ namespace Nz { public: inline MemoryStream(); - inline MemoryStream(ByteArray* byteArray, UInt32 openMode = OpenMode_ReadWrite); + inline MemoryStream(ByteArray* byteArray, OpenModeFlags openMode = OpenMode_ReadWrite); MemoryStream(const MemoryStream&) = default; MemoryStream(MemoryStream&&) = default; ~MemoryStream() = default; @@ -32,7 +32,7 @@ namespace Nz UInt64 GetCursorPos() const override; UInt64 GetSize() const override; - void SetBuffer(ByteArray* byteArray, UInt32 openMode = OpenMode_ReadWrite); + void SetBuffer(ByteArray* byteArray, OpenModeFlags openMode = OpenMode_ReadWrite); bool SetCursorPos(UInt64 offset) override; MemoryStream& operator=(const MemoryStream&) = default; diff --git a/include/Nazara/Core/MemoryStream.inl b/include/Nazara/Core/MemoryStream.inl index 79a19f467..6cdf06b26 100644 --- a/include/Nazara/Core/MemoryStream.inl +++ b/include/Nazara/Core/MemoryStream.inl @@ -24,7 +24,7 @@ namespace Nz * \param byteArray Bytes to stream * \param openMode Reading/writing mode for the stream */ - inline MemoryStream::MemoryStream(ByteArray* byteArray, UInt32 openMode) : + inline MemoryStream::MemoryStream(ByteArray* byteArray, OpenModeFlags openMode) : MemoryStream() { SetBuffer(byteArray, openMode); diff --git a/include/Nazara/Core/Stream.hpp b/include/Nazara/Core/Stream.hpp index 63d7e781b..e4949d441 100644 --- a/include/Nazara/Core/Stream.hpp +++ b/include/Nazara/Core/Stream.hpp @@ -32,8 +32,8 @@ namespace Nz virtual UInt64 GetCursorPos() const = 0; virtual String GetDirectory() const; virtual String GetPath() const; - inline UInt32 GetOpenMode() const; - inline UInt32 GetStreamOptions() const; + inline OpenModeFlags GetOpenMode() const; + inline StreamOptionFlags GetStreamOptions() const; virtual UInt64 GetSize() const = 0; @@ -55,14 +55,14 @@ namespace Nz Stream& operator=(Stream&&) = default; protected: - inline Stream(UInt32 streamOptions = StreamOption_None, UInt32 openMode = OpenMode_NotOpen); + inline Stream(StreamOptionFlags streamOptions = StreamOption_None, OpenModeFlags openMode = OpenMode_NotOpen); virtual void FlushStream() = 0; virtual std::size_t ReadBlock(void* buffer, std::size_t size) = 0; virtual std::size_t WriteBlock(const void* buffer, std::size_t size) = 0; - UInt32 m_openMode; - UInt32 m_streamOptions; + OpenModeFlags m_openMode; + StreamOptionFlags m_streamOptions; }; } diff --git a/include/Nazara/Core/Stream.inl b/include/Nazara/Core/Stream.inl index aae7fe155..f4f1557d7 100644 --- a/include/Nazara/Core/Stream.inl +++ b/include/Nazara/Core/Stream.inl @@ -15,7 +15,7 @@ namespace Nz * \param openMode Reading/writing mode for the stream */ - inline Stream::Stream(UInt32 streamOptions, UInt32 openMode) : + inline Stream::Stream(StreamOptionFlags streamOptions, OpenModeFlags openMode) : m_openMode(openMode), m_streamOptions(streamOptions) { @@ -53,7 +53,7 @@ namespace Nz * \return Reading/writing mode for the stream */ - inline UInt32 Stream::GetOpenMode() const + inline OpenModeFlags Stream::GetOpenMode() const { return m_openMode; } @@ -63,7 +63,7 @@ namespace Nz * \return Options of the stream */ - inline UInt32 Stream::GetStreamOptions() const + inline StreamOptionFlags Stream::GetStreamOptions() const { return m_streamOptions; } @@ -116,7 +116,7 @@ namespace Nz * \param size Size meant to be read * * \remark Produces a NazaraAssert if stream is not readable - * \remark If preallocated space of buffer is less than the size, the behaviour is undefined + * \remark If preallocated space of buffer is less than the size, the behavior is undefined */ inline std::size_t Stream::Read(void* buffer, std::size_t size) @@ -134,7 +134,7 @@ namespace Nz * \param size Size meant to be written * * \remark Produces a NazaraAssert if stream is not writable - * \remark If preallocated space of buffer is less than the size, the behaviour is undefined + * \remark If preallocated space of buffer is less than the size, the behavior is undefined */ inline std::size_t Stream::Write(const void* buffer, std::size_t size) diff --git a/include/Nazara/Core/String.hpp b/include/Nazara/Core/String.hpp index 765ef8b85..ba7f34ff7 100644 --- a/include/Nazara/Core/String.hpp +++ b/include/Nazara/Core/String.hpp @@ -82,6 +82,7 @@ namespace Nz char* GetBuffer(); std::size_t GetCapacity() const; + std::size_t GetCharacterPosition(std::size_t characterIndex) const; const char* GetConstBuffer() const; std::size_t GetLength() const; std::size_t GetSize() const; diff --git a/include/Nazara/Graphics.hpp b/include/Nazara/Graphics.hpp index 252110d9d..3d7edd264 100644 --- a/include/Nazara/Graphics.hpp +++ b/include/Nazara/Graphics.hpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include diff --git a/include/Nazara/Graphics/CullingList.hpp b/include/Nazara/Graphics/CullingList.hpp new file mode 100644 index 000000000..f8c50d83d --- /dev/null +++ b/include/Nazara/Graphics/CullingList.hpp @@ -0,0 +1,180 @@ +// Copyright (C) 2015 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_CULLINGLIST_HPP +#define NAZARA_CULLINGLIST_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + template + class CullingList + { + public: + template class Entry; + class NoTestEntry; + class SphereEntry; + class VolumeEntry; + + template friend class Entry; + friend NoTestEntry; + friend SphereEntry; + friend VolumeEntry; + + using ResultContainer = std::vector; + + CullingList() = default; + CullingList(const CullingList& renderable) = delete; + CullingList(CullingList&& renderable) = delete; + ~CullingList(); + + std::size_t Cull(const Frustumf& frustum, bool* forceInvalidation = nullptr); + + NoTestEntry RegisterNoTest(const T* renderable); + SphereEntry RegisterSphereTest(const T* renderable); + VolumeEntry RegisterVolumeTest(const T* renderable); + + CullingList& operator=(const CullingList& renderable) = delete; + CullingList& operator=(CullingList&& renderable) = delete; + + // STL API + typename ResultContainer::iterator begin(); + typename ResultContainer::const_iterator begin() const; + + typename ResultContainer::const_iterator cbegin() const; + typename ResultContainer::const_iterator cend() const; + typename ResultContainer::const_reverse_iterator crbegin() const; + typename ResultContainer::const_reverse_iterator crend() const; + + bool empty() const; + + typename ResultContainer::iterator end(); + typename ResultContainer::const_iterator end() const; + + typename ResultContainer::reverse_iterator rbegin(); + typename ResultContainer::const_reverse_iterator rbegin() const; + + typename ResultContainer::reverse_iterator rend(); + typename ResultContainer::const_reverse_iterator rend() const; + + typename ResultContainer::size_type size() const; + + NazaraSignal(OnCullingListRelease, CullingList* /*cullingList*/); + + private: + inline void NotifyForceInvalidation(CullTest type, std::size_t index); + inline void NotifyMovement(CullTest type, std::size_t index, void* oldPtr, void* newPtr); + inline void NotifyRelease(CullTest type, std::size_t index); + inline void NotifySphereUpdate(std::size_t index, const Spheref& sphere); + inline void NotifyVolumeUpdate(std::size_t index, const BoundingVolumef& boundingVolume); + + struct NoTestVisibilityEntry + { + NoTestEntry* entry; + const T* renderable; + bool forceInvalidation; + }; + + struct SphereVisibilityEntry + { + Spheref sphere; + SphereEntry* entry; + const T* renderable; + bool forceInvalidation; + }; + + struct VolumeVisibilityEntry + { + BoundingVolumef volume; + VolumeEntry* entry; + const T* renderable; + bool forceInvalidation; + }; + + std::vector m_noTestList; + std::vector m_sphereTestList; + std::vector m_volumeTestList; + ResultContainer m_results; + }; + + template + template + class CullingList::Entry + { + public: + Entry(); + Entry(const Entry&) = delete; + Entry(Entry&& entry); + ~Entry(); + + void ForceInvalidation(); + + CullingList* GetParent() const; + + void UpdateIndex(std::size_t index); + + Entry& operator=(const Entry&) = delete; + Entry& operator=(Entry&& entry); + + protected: + Entry(CullingList* parent, std::size_t index); + + std::size_t m_index; + CullingList* m_parent; + }; + + template + class CullingList::NoTestEntry : public CullingList::template Entry + { + friend CullingList; + + public: + NoTestEntry(); + + private: + NoTestEntry(CullingList* parent, std::size_t index); + }; + + template + class CullingList::SphereEntry : public CullingList::template Entry + { + friend CullingList; + + public: + SphereEntry(); + + void UpdateSphere(const Spheref& sphere); + + private: + SphereEntry(CullingList* parent, std::size_t index); + }; + + template + class CullingList::VolumeEntry : public CullingList::template Entry + { + friend CullingList; + + public: + VolumeEntry(); + + void UpdateVolume(const BoundingVolumef& sphere); + + private: + VolumeEntry(CullingList* parent, std::size_t index); + }; +} + +#include + +#endif // NAZARA_CULLINGLIST_HPP diff --git a/include/Nazara/Graphics/CullingList.inl b/include/Nazara/Graphics/CullingList.inl new file mode 100644 index 000000000..d4f80b3d7 --- /dev/null +++ b/include/Nazara/Graphics/CullingList.inl @@ -0,0 +1,431 @@ +// Copyright (C) 2015 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 +#include + +namespace Nz +{ + template + CullingList::~CullingList() + { + OnCullingListRelease(this); + } + + template + std::size_t CullingList::Cull(const Frustumf& frustum, bool* forceInvalidation) + { + m_results.clear(); + + bool forcedInvalidation = false; + + std::size_t visibleHash = 0U; + + for (NoTestVisibilityEntry& entry : m_noTestList) + { + m_results.push_back(entry.renderable); + Nz::HashCombine(visibleHash, entry.renderable); + + if (entry.forceInvalidation) + { + forcedInvalidation = true; + entry.forceInvalidation = false; + } + } + + for (SphereVisibilityEntry& entry : m_sphereTestList) + { + if (frustum.Contains(entry.sphere)) + { + m_results.push_back(entry.renderable); + Nz::HashCombine(visibleHash, entry.renderable); + + if (entry.forceInvalidation) + { + forcedInvalidation = true; + entry.forceInvalidation = false; + } + } + } + + for (VolumeVisibilityEntry& entry : m_volumeTestList) + { + if (frustum.Contains(entry.volume)) + { + m_results.push_back(entry.renderable); + Nz::HashCombine(visibleHash, entry.renderable); + + if (entry.forceInvalidation) + { + forcedInvalidation = true; + entry.forceInvalidation = false; + } + } + } + + if (forceInvalidation) + *forceInvalidation = forcedInvalidation; + + return visibleHash; + } + + template + typename CullingList::NoTestEntry CullingList::RegisterNoTest(const T* renderable) + { + NoTestEntry entry(this, m_noTestList.size()); + m_noTestList.emplace_back(NoTestVisibilityEntry{&entry, renderable, false}); //< Address of entry will be updated when moving + + return entry; + } + + template + typename CullingList::SphereEntry CullingList::RegisterSphereTest(const T* renderable) + { + SphereEntry entry(this, m_sphereTestList.size()); + m_sphereTestList.emplace_back(SphereVisibilityEntry{Nz::Spheref(), &entry, renderable, false}); //< Address of entry will be updated when moving + + return entry; + } + + template + typename CullingList::VolumeEntry CullingList::RegisterVolumeTest(const T* renderable) + { + VolumeEntry entry(this, m_volumeTestList.size()); + m_volumeTestList.emplace_back(VolumeVisibilityEntry{Nz::BoundingVolumef(), &entry, renderable, false}); //< Address of entry will be updated when moving + + return entry; + } + + // Interface STD + template + typename CullingList::ResultContainer::iterator CullingList::begin() + { + return m_results.begin(); + } + + template + typename CullingList::ResultContainer::const_iterator CullingList::begin() const + { + return m_results.begin(); + } + + template + typename CullingList::ResultContainer::const_iterator CullingList::cbegin() const + { + return m_results.cbegin(); + } + + template + typename CullingList::ResultContainer::const_iterator CullingList::cend() const + { + return m_results.cend(); + } + + template + typename CullingList::ResultContainer::const_reverse_iterator CullingList::crbegin() const + { + return m_results.crbegin(); + } + + template + typename CullingList::ResultContainer::const_reverse_iterator CullingList::crend() const + { + return m_results.crend(); + } + + template + bool CullingList::empty() const + { + return m_results.empty(); + } + + template + typename CullingList::ResultContainer::iterator CullingList::end() + { + return m_results.end(); + } + + template + typename CullingList::ResultContainer::const_iterator CullingList::end() const + { + return m_results.end(); + } + + template + typename CullingList::ResultContainer::reverse_iterator CullingList::rbegin() + { + return m_results.rbegin(); + } + + template + typename CullingList::ResultContainer::const_reverse_iterator CullingList::rbegin() const + { + return m_results.rbegin(); + } + + template + typename CullingList::ResultContainer::reverse_iterator CullingList::rend() + { + return m_results.rend(); + } + + template + typename CullingList::ResultContainer::const_reverse_iterator CullingList::rend() const + { + return m_results.rend(); + } + + template + typename CullingList::ResultContainer::size_type CullingList::size() const + { + return m_results.size(); + } + + template + void CullingList::NotifyForceInvalidation(CullTest type, std::size_t index) + { + switch (type) + { + case CullTest::NoTest: + { + m_noTestList[index].forceInvalidation = true; + break; + } + + case CullTest::Sphere: + { + m_sphereTestList[index].forceInvalidation = true; + break; + } + + case CullTest::Volume: + { + m_volumeTestList[index].forceInvalidation = true; + break; + } + + default: + NazaraInternalError("Unhandled culltype"); + break; + } + } + + template + void CullingList::NotifyMovement(CullTest type, std::size_t index, void* oldPtr, void* newPtr) + { + switch (type) + { + case CullTest::NoTest: + { + NoTestVisibilityEntry& entry = m_noTestList[index]; + NazaraAssert(entry.entry == oldPtr, "Invalid entry"); + + entry.entry = static_cast(newPtr); + break; + } + + case CullTest::Sphere: + { + SphereVisibilityEntry& entry = m_sphereTestList[index]; + NazaraAssert(entry.entry == oldPtr, "Invalid sphere entry"); + + entry.entry = static_cast(newPtr); + break; + } + + case CullTest::Volume: + { + VolumeVisibilityEntry& entry = m_volumeTestList[index]; + NazaraAssert(entry.entry == oldPtr, "Invalid volume entry"); + + entry.entry = static_cast(newPtr); + break; + } + + default: + NazaraInternalError("Unhandled culltype"); + break; + } + } + + template + void CullingList::NotifyRelease(CullTest type, std::size_t index) + { + switch (type) + { + case CullTest::NoTest: + { + m_noTestList[index] = std::move(m_noTestList.back()); + m_noTestList[index].entry->UpdateIndex(index); + m_noTestList.pop_back(); + break; + } + + case CullTest::Sphere: + { + m_sphereTestList[index] = std::move(m_sphereTestList.back()); + m_sphereTestList[index].entry->UpdateIndex(index); + m_sphereTestList.pop_back(); + break; + } + + case CullTest::Volume: + { + m_volumeTestList[index] = std::move(m_volumeTestList.back()); + m_volumeTestList[index].entry->UpdateIndex(index); + m_volumeTestList.pop_back(); + break; + } + + default: + NazaraInternalError("Unhandled culltype"); + break; + } + } + + template + void CullingList::NotifySphereUpdate(std::size_t index, const Spheref& sphere) + { + m_sphereTestList[index].sphere = sphere; + } + + template + void CullingList::NotifyVolumeUpdate(std::size_t index, const BoundingVolumef& boundingVolume) + { + m_volumeTestList[index].volume = boundingVolume; + } + + ////////////////////////////////////////////////////////////////////////// + + template + template + CullingList::Entry::Entry() : + m_parent(nullptr) + { + } + + template + template + CullingList::Entry::Entry(CullingList* parent, std::size_t index) : + m_index(index), + m_parent(parent) + { + } + + template + template + CullingList::Entry::Entry(Entry&& entry) : + m_index(entry.m_index), + m_parent(entry.m_parent) + { + if (m_parent) + m_parent->NotifyMovement(Type, m_index, &entry, this); + + entry.m_parent = nullptr; + } + + template + template + CullingList::Entry::~Entry() + { + if (m_parent) + m_parent->NotifyRelease(Type, m_index); + } + + template + template + void CullingList::Entry::ForceInvalidation() + { + m_parent->NotifyForceInvalidation(Type, m_index); + } + + template + template + CullingList* CullingList::Entry::GetParent() const + { + return m_parent; + } + + template + template + void CullingList::Entry::UpdateIndex(std::size_t index) + { + m_index = index; + } + + template + template + #ifdef NAZARA_COMPILER_MSVC + // MSVC bug + typename CullingList::Entry& CullingList::Entry::operator=(Entry&& entry) + #else + typename CullingList::template Entry& CullingList::Entry::operator=(Entry&& entry) + #endif + { + m_index = entry.m_index; + m_parent = entry.m_parent; + if (m_parent) + m_parent->NotifyMovement(Type, m_index, &entry, this); + + entry.m_parent = nullptr; + + return *this; + } + + ////////////////////////////////////////////////////////////////////////// + + template + CullingList::NoTestEntry::NoTestEntry() : + Entry() + { + } + + template + CullingList::NoTestEntry::NoTestEntry(CullingList* parent, std::size_t index) : + Entry(parent, index) + { + } + + ////////////////////////////////////////////////////////////////////////// + + template + CullingList::SphereEntry::SphereEntry() : + Entry() + { + } + + template + CullingList::SphereEntry::SphereEntry(CullingList* parent, std::size_t index) : + Entry(parent, index) + { + } + + template + void CullingList::SphereEntry::UpdateSphere(const Spheref& sphere) + { + this->m_parent->NotifySphereUpdate(this->m_index, sphere); + } + + ////////////////////////////////////////////////////////////////////////// + + template + CullingList::VolumeEntry::VolumeEntry() : + Entry() + { + } + + template + CullingList::VolumeEntry::VolumeEntry(CullingList* parent, std::size_t index) : + Entry(parent, index) + { + } + + template + void CullingList::VolumeEntry::UpdateVolume(const BoundingVolumef& volume) + { + this->m_parent->NotifyVolumeUpdate(this->m_index, volume); + } +} + +#include diff --git a/include/Nazara/Graphics/Enums.hpp b/include/Nazara/Graphics/Enums.hpp index d378058f7..fd87cac6c 100644 --- a/include/Nazara/Graphics/Enums.hpp +++ b/include/Nazara/Graphics/Enums.hpp @@ -19,6 +19,13 @@ namespace Nz BackgroundType_Max = BackgroundType_User }; + enum class CullTest + { + NoTest, + Sphere, + Volume + }; + enum ProjectionType { ProjectionType_Orthogonal, diff --git a/include/Nazara/Graphics/InstancedRenderable.hpp b/include/Nazara/Graphics/InstancedRenderable.hpp index 8b44d7512..3f117c84b 100644 --- a/include/Nazara/Graphics/InstancedRenderable.hpp +++ b/include/Nazara/Graphics/InstancedRenderable.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -31,15 +32,17 @@ namespace Nz public: struct InstanceData; - InstancedRenderable() = default; + inline InstancedRenderable(); inline InstancedRenderable(const InstancedRenderable& renderable); InstancedRenderable(InstancedRenderable&& renderable) = delete; virtual ~InstancedRenderable(); + virtual void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const = 0; + + virtual bool Cull(const Frustumf& frustum, const InstanceData& instanceData) const; + inline void EnsureBoundingVolumeUpdated() const; - virtual void AddToRenderQueue(AbstractRenderQueue* renderQueue, const InstanceData& instanceData) const = 0; - virtual bool Cull(const Frustumf& frustum, const InstanceData& instanceData) const; virtual const BoundingVolumef& GetBoundingVolume() const; virtual void InvalidateData(InstanceData* instanceData, UInt32 flags) const; virtual void UpdateBoundingVolume(InstanceData* instanceData) const; @@ -49,6 +52,7 @@ namespace Nz InstancedRenderable& operator=(InstancedRenderable&& renderable) = delete; // Signals: + NazaraSignal(OnInstancedRenderableInvalidateBoundingVolume, const InstancedRenderable* /*instancedRenderable*/); NazaraSignal(OnInstancedRenderableInvalidateData, const InstancedRenderable* /*instancedRenderable*/, UInt32 /*flags*/); NazaraSignal(OnInstancedRenderableRelease, const InstancedRenderable* /*instancedRenderable*/); @@ -83,14 +87,16 @@ namespace Nz }; protected: - virtual void MakeBoundingVolume() const = 0; - void InvalidateBoundingVolume(); + inline void InvalidateBoundingVolume(); inline void InvalidateInstanceData(UInt32 flags); - inline void UpdateBoundingVolume() const; + + virtual void MakeBoundingVolume() const = 0; mutable BoundingVolumef m_boundingVolume; private: + inline void UpdateBoundingVolume() const; + mutable bool m_boundingVolumeUpdated; static InstancedRenderableLibrary::LibraryMap s_library; diff --git a/include/Nazara/Graphics/InstancedRenderable.inl b/include/Nazara/Graphics/InstancedRenderable.inl index 7f2537fbf..5ee49dc6a 100644 --- a/include/Nazara/Graphics/InstancedRenderable.inl +++ b/include/Nazara/Graphics/InstancedRenderable.inl @@ -4,12 +4,19 @@ namespace Nz { + /*! + * \brief Constructs a InstancedRenderable object by default + */ + inline InstancedRenderable::InstancedRenderable() : + m_boundingVolumeUpdated(false) + { + } + /*! * \brief Constructs a InstancedRenderable object by assignation * * \param renderable InstancedRenderable to copy into this */ - inline InstancedRenderable::InstancedRenderable(const InstancedRenderable& renderable) : RefCounted(), m_boundingVolume(renderable.m_boundingVolume), @@ -34,6 +41,8 @@ namespace Nz inline void InstancedRenderable::InvalidateBoundingVolume() { m_boundingVolumeUpdated = false; + + OnInstancedRenderableInvalidateBoundingVolume(this); } /*! @@ -69,6 +78,7 @@ namespace Nz inline void InstancedRenderable::UpdateBoundingVolume() const { MakeBoundingVolume(); + m_boundingVolumeUpdated = true; } } diff --git a/include/Nazara/Graphics/ParticleGroup.hpp b/include/Nazara/Graphics/ParticleGroup.hpp index 35feaa674..460694160 100644 --- a/include/Nazara/Graphics/ParticleGroup.hpp +++ b/include/Nazara/Graphics/ParticleGroup.hpp @@ -44,6 +44,8 @@ namespace Nz void* GenerateParticle(); void* GenerateParticles(unsigned int count); + inline void* GetBuffer(); + inline const void* GetBuffer() const; const ParticleDeclarationConstRef& GetDeclaration() const; std::size_t GetMaxParticleCount() const; std::size_t GetParticleCount() const; @@ -94,4 +96,6 @@ namespace Nz }; } +#include + #endif // NAZARA_PARTICLEGROUP_HPP diff --git a/include/Nazara/Graphics/ParticleGroup.inl b/include/Nazara/Graphics/ParticleGroup.inl new file mode 100644 index 000000000..f0e205346 --- /dev/null +++ b/include/Nazara/Graphics/ParticleGroup.inl @@ -0,0 +1,40 @@ +// Copyright (C) 2016 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 +#include +#include + +namespace Nz +{ + /*! + * \brief Gets a raw pointer to the particle buffer + * + * This can be useful when working directly with a struct, or needing to iterate over all particles. + * + * \return Pointer to the buffer + * + * \see GetParticleCount + */ + inline void* ParticleGroup::GetBuffer() + { + return m_buffer.data(); + } + + /*! + * \brief Gets a raw pointer to the particle buffer + * + * This can be useful when working directly with a struct, or needing to iterate over all particles. + * + * \return Pointer to the buffer + * + * \see GetParticleCount + */ + inline const void* ParticleGroup::GetBuffer() const + { + return m_buffer.data(); + } +} + +#include diff --git a/include/Nazara/Graphics/ParticleMapper.hpp b/include/Nazara/Graphics/ParticleMapper.hpp index e66b519a7..ffbe2a5ad 100644 --- a/include/Nazara/Graphics/ParticleMapper.hpp +++ b/include/Nazara/Graphics/ParticleMapper.hpp @@ -22,6 +22,7 @@ namespace Nz template SparsePtr GetComponentPtr(ParticleComponent component); template SparsePtr GetComponentPtr(ParticleComponent component) const; + inline void* GetPointer(); private: const ParticleDeclaration* m_declaration; diff --git a/include/Nazara/Graphics/ParticleMapper.inl b/include/Nazara/Graphics/ParticleMapper.inl index 7d33bb655..1a4566c33 100644 --- a/include/Nazara/Graphics/ParticleMapper.inl +++ b/include/Nazara/Graphics/ParticleMapper.inl @@ -68,6 +68,18 @@ namespace Nz return SparsePtr(); } } + + /*! + * \brief Gets a raw pointer to the particle buffer + * + * This can be useful when working directly with a struct + * + * \return Pointer to the buffer + */ + inline void* ParticleMapper::GetPointer() + { + return m_ptr; + } } #include diff --git a/include/Nazara/Graphics/ParticleStruct.hpp b/include/Nazara/Graphics/ParticleStruct.hpp index 895e8fca2..b4f55a3a1 100644 --- a/include/Nazara/Graphics/ParticleStruct.hpp +++ b/include/Nazara/Graphics/ParticleStruct.hpp @@ -21,16 +21,16 @@ namespace Nz Vector3f normal; Vector3f position; Vector3f velocity; - UInt32 life; + float life; float rotation; }; struct ParticleStruct_Model { + Quaternionf rotation; Vector3f position; Vector3f velocity; - UInt32 life; - Quaternionf rotation; + float life; }; struct ParticleStruct_Sprite @@ -38,7 +38,7 @@ namespace Nz Color color; Vector3f position; Vector3f velocity; - UInt32 life; + float life; float rotation; }; } diff --git a/include/Nazara/Graphics/Renderable.hpp b/include/Nazara/Graphics/Renderable.hpp index f8d441955..412caa301 100644 --- a/include/Nazara/Graphics/Renderable.hpp +++ b/include/Nazara/Graphics/Renderable.hpp @@ -25,7 +25,9 @@ namespace Nz virtual ~Renderable(); virtual void AddToRenderQueue(AbstractRenderQueue* renderQueue, const Matrix4f& transformMatrix) const = 0; + virtual bool Cull(const Frustumf& frustum, const Matrix4f& transformMatrix) const; + inline void EnsureBoundingVolumeUpdated() const; virtual const BoundingVolumef& GetBoundingVolume() const; virtual void UpdateBoundingVolume(const Matrix4f& transformMatrix); @@ -36,11 +38,12 @@ namespace Nz protected: virtual void MakeBoundingVolume() const = 0; inline void InvalidateBoundingVolume(); - inline void UpdateBoundingVolume() const; mutable BoundingVolumef m_boundingVolume; private: + inline void UpdateBoundingVolume() const; + mutable bool m_boundingVolumeUpdated; }; } diff --git a/include/Nazara/Graphics/TextSprite.inl b/include/Nazara/Graphics/TextSprite.inl index 2ed880a38..d5db90805 100644 --- a/include/Nazara/Graphics/TextSprite.inl +++ b/include/Nazara/Graphics/TextSprite.inl @@ -149,6 +149,7 @@ namespace Nz { m_scale = scale; + InvalidateBoundingVolume(); InvalidateVertices(); } diff --git a/include/Nazara/Lua/LuaInstance.inl b/include/Nazara/Lua/LuaInstance.inl index 9bc20c73a..99ef94ea4 100644 --- a/include/Nazara/Lua/LuaInstance.inl +++ b/include/Nazara/Lua/LuaInstance.inl @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -99,19 +100,50 @@ namespace Nz } template - std::enable_if_t::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, TypeTag) + std::enable_if_t::value && !EnableFlagsOperators::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, TypeTag) { using UnderlyingT = std::underlying_type_t; return LuaImplQueryArg(instance, index, reinterpret_cast(arg), TypeTag()); } template - std::enable_if_t::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, T defValue, TypeTag) + std::enable_if_t::value && !EnableFlagsOperators::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, T defValue, TypeTag) { using UnderlyingT = std::underlying_type_t; return LuaImplQueryArg(instance, index, reinterpret_cast(arg), static_cast(defValue), TypeTag()); } + template + std::enable_if_t::value && EnableFlagsOperators::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, TypeTag) + { + using UnderlyingT = std::underlying_type_t; + + UnderlyingT pot2Val; + unsigned int ret = LuaImplQueryArg(instance, index, &pot2Val, TypeTag()); + + *arg = static_cast(IntegralLog2Pot(pot2Val)); + return ret; + } + + template + std::enable_if_t::value && EnableFlagsOperators::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, T defValue, TypeTag) + { + using UnderlyingT = std::underlying_type_t; + + UnderlyingT pot2Val; + unsigned int ret = LuaImplQueryArg(instance, index, &pot2Val, 1U << static_cast(defValue), TypeTag()); + + *arg = static_cast(IntegralLog2Pot(pot2Val)); + return ret; + } + + template + unsigned int LuaImplQueryArg(const LuaInstance& instance, int index, Flags* arg, TypeTag>) + { + *arg = Flags(instance.CheckBoundInteger(index)); + return 1; + } + template std::enable_if_t::value, unsigned int> LuaImplQueryArg(const LuaInstance& instance, int index, T* arg, TypeTag) { @@ -184,12 +216,26 @@ namespace Nz } template - std::enable_if_t::value, int> LuaImplReplyVal(const LuaInstance& instance, T val, TypeTag) + std::enable_if_t::value && !EnableFlagsOperators::value, int> LuaImplReplyVal(const LuaInstance& instance, T val, TypeTag) { using EnumT = typename std::underlying_type::type; return LuaImplReplyVal(instance, static_cast(val), TypeTag()); } + template + std::enable_if_t::value && EnableFlagsOperators::value, int> LuaImplReplyVal(const LuaInstance& instance, T val, TypeTag) + { + Flags flags(val); + return LuaImplReplyVal(instance, flags, TypeTag()); + } + + template + int LuaImplReplyVal(const LuaInstance& instance, Flags val, TypeTag>) + { + instance.PushInteger(UInt32(val)); + return 1; + } + template std::enable_if_t::value, int> LuaImplReplyVal(const LuaInstance& instance, T val, TypeTag) { diff --git a/include/Nazara/Network/NetPacket.hpp b/include/Nazara/Network/NetPacket.hpp index 272808a33..7eef2979a 100644 --- a/include/Nazara/Network/NetPacket.hpp +++ b/include/Nazara/Network/NetPacket.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2015 Jérôme Leclercq +// Copyright (C) 2015 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 @@ -56,7 +56,7 @@ namespace Nz void OnEmptyStream() override; void FreeStream(); - void InitStream(std::size_t minCapacity, UInt64 cursorPos, UInt32 openMode); + void InitStream(std::size_t minCapacity, UInt64 cursorPos, OpenModeFlags openMode); static bool Initialize(); static void Uninitialize(); diff --git a/include/Nazara/Prerequesites.hpp b/include/Nazara/Prerequesites.hpp index dbe478661..13a044f68 100644 --- a/include/Nazara/Prerequesites.hpp +++ b/include/Nazara/Prerequesites.hpp @@ -28,17 +28,14 @@ // Try to identify the compiler #if defined(__BORLANDC__) #define NAZARA_COMPILER_BORDLAND - #define NAZARA_COMPILER_SUPPORTS_CPP11 (defined(__cplusplus) && __cplusplus >= 201103L) #define NAZARA_DEPRECATED(txt) #define NAZARA_FUNCTION __FUNC__ #elif defined(__clang__) #define NAZARA_COMPILER_CLANG - #define NAZARA_COMPILER_SUPPORTS_CPP11 (defined(__cplusplus) && __cplusplus >= 201103L) #define NAZARA_DEPRECATED(txt) __attribute__((__deprecated__(txt))) #define NAZARA_FUNCTION __PRETTY_FUNCTION__ #elif defined(__GNUC__) || defined(__MINGW32__) #define NAZARA_COMPILER_GCC - #define NAZARA_COMPILER_SUPPORTS_CPP11 (defined(__cplusplus) && __cplusplus >= 201103L) #define NAZARA_DEPRECATED(txt) __attribute__((__deprecated__(txt))) #define NAZARA_FUNCTION __PRETTY_FUNCTION__ @@ -50,26 +47,31 @@ #endif #elif defined(__INTEL_COMPILER) || defined(__ICL) #define NAZARA_COMPILER_INTEL - #define NAZARA_COMPILER_SUPPORTS_CPP11 (defined(__cplusplus) && __cplusplus >= 201103L) #define NAZARA_DEPRECATED(txt) #define NAZARA_FUNCTION __FUNCTION__ #elif defined(_MSC_VER) #define NAZARA_COMPILER_MSVC - #define NAZARA_COMPILER_SUPPORTS_CPP11 (_MSC_VER >= 1900) #define NAZARA_DEPRECATED(txt) __declspec(deprecated(txt)) #define NAZARA_FUNCTION __FUNCSIG__ + #if _MSC_VER >= 1900 + #define NAZARA_COMPILER_SUPPORTS_CPP11 + #endif + #pragma warning(disable: 4251) #else #define NAZARA_COMPILER_UNKNOWN - #define NAZARA_COMPILER_SUPPORTS_CPP11 (defined(__cplusplus) && __cplusplus >= 201103L) #define NAZARA_DEPRECATED(txt) #define NAZARA_FUNCTION __func__ // __func__ has been standardized in C++ 2011 #pragma message This compiler is not fully supported #endif -#if !NAZARA_COMPILER_SUPPORTS_CPP11 +#if !defined(NAZARA_COMPILER_SUPPORTS_CPP11) && defined(__cplusplus) && __cplusplus >= 201103L + #define NAZARA_COMPILER_SUPPORTS_CPP11 +#endif + +#ifndef NAZARA_COMPILER_SUPPORTS_CPP11 #error Nazara requires a C++11 compliant compiler #endif diff --git a/include/Nazara/Renderer/RenderWindow.hpp b/include/Nazara/Renderer/RenderWindow.hpp index 82c80b342..a92ed3352 100644 --- a/include/Nazara/Renderer/RenderWindow.hpp +++ b/include/Nazara/Renderer/RenderWindow.hpp @@ -23,13 +23,14 @@ namespace Nz { public: inline RenderWindow(); - inline RenderWindow(VideoMode mode, const String& title, UInt32 style = WindowStyle_Default, const RenderWindowParameters& parameters = RenderWindowParameters()); + inline RenderWindow(VideoMode mode, const String& title, WindowStyleFlags style = WindowStyle_Default, const RenderWindowParameters& parameters = RenderWindowParameters()); inline RenderWindow(WindowHandle handle, const RenderWindowParameters& parameters = RenderWindowParameters()); + RenderWindow(const RenderWindow&) = delete; RenderWindow(RenderWindow&&) = delete; ///TODO virtual ~RenderWindow(); - inline bool Create(VideoMode mode, const String& title, UInt32 style = WindowStyle_Default, const RenderWindowParameters& parameters = RenderWindowParameters()); + inline bool Create(VideoMode mode, const String& title, WindowStyleFlags style = WindowStyle_Default, const RenderWindowParameters& parameters = RenderWindowParameters()); inline bool Create(WindowHandle handle, const RenderWindowParameters& parameters = RenderWindowParameters()); void Display(); diff --git a/include/Nazara/Renderer/RenderWindow.inl b/include/Nazara/Renderer/RenderWindow.inl index a7ff34c62..882ad8dd5 100644 --- a/include/Nazara/Renderer/RenderWindow.inl +++ b/include/Nazara/Renderer/RenderWindow.inl @@ -12,7 +12,7 @@ namespace Nz { } - inline RenderWindow::RenderWindow(VideoMode mode, const String& title, UInt32 style, const RenderWindowParameters& parameters) : + inline RenderWindow::RenderWindow(VideoMode mode, const String& title, WindowStyleFlags style, const RenderWindowParameters& parameters) : RenderWindow() { ErrorFlags errFlags(ErrorFlag_ThrowException, true); @@ -27,7 +27,7 @@ namespace Nz Create(handle, parameters); } - inline bool RenderWindow::Create(VideoMode mode, const String& title, UInt32 style, const RenderWindowParameters& parameters) + inline bool RenderWindow::Create(VideoMode mode, const String& title, WindowStyleFlags style, const RenderWindowParameters& parameters) { m_parameters = parameters; diff --git a/include/Nazara/Renderer/Texture.hpp b/include/Nazara/Renderer/Texture.hpp new file mode 100644 index 000000000..6d52beb6f --- /dev/null +++ b/include/Nazara/Renderer/Texture.hpp @@ -0,0 +1,139 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_TEXTURE_HPP +#define NAZARA_TEXTURE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class Texture; + + using TextureConstRef = ObjectRef; + using TextureLibrary = ObjectLibrary; + using TextureManager = ResourceManager; + using TextureRef = ObjectRef; + + struct TextureImpl; + + class NAZARA_RENDERER_API Texture : public AbstractImage, public Resource + { + friend TextureLibrary; + friend TextureManager; + friend class Renderer; + + public: + Texture() = default; + Texture(ImageType type, PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth = 1, UInt8 levelCount = 1); + explicit Texture(const Image& image); + Texture(const Texture&) = delete; + Texture(Texture&&) = delete; + ~Texture(); + + bool Create(ImageType type, PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth = 1, UInt8 levelCount = 1); + void Destroy(); + + bool Download(Image* image) const; + + bool EnableMipmapping(bool enable); + + void EnsureMipmapsUpdate() const; + + unsigned int GetDepth(UInt8 level = 0) const override; + PixelFormatType GetFormat() const override; + unsigned int GetHeight(UInt8 level = 0) const override; + UInt8 GetLevelCount() const override; + UInt8 GetMaxLevel() const override; + std::size_t GetMemoryUsage() const override; + std::size_t GetMemoryUsage(UInt8 level) const override; + Vector3ui GetSize(UInt8 level = 0) const override; + ImageType GetType() const override; + unsigned int GetWidth(UInt8 level = 0) const override; + + bool HasMipmaps() const; + + void InvalidateMipmaps(); + bool IsValid() const; + + // Load + bool LoadFromFile(const String& filePath, const ImageParams& params = ImageParams(), bool generateMipmaps = true); + bool LoadFromImage(const Image& image, bool generateMipmaps = true); + bool LoadFromMemory(const void* data, std::size_t size, const ImageParams& params = ImageParams(), bool generateMipmaps = true); + bool LoadFromStream(Stream& stream, const ImageParams& params = ImageParams(), bool generateMipmaps = true); + + // LoadArray + bool LoadArrayFromFile(const String& filePath, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2)); + bool LoadArrayFromImage(const Image& image, bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2)); + bool LoadArrayFromMemory(const void* data, std::size_t size, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2)); + bool LoadArrayFromStream(Stream& stream, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2)); + + // LoadCubemap + bool LoadCubemapFromFile(const String& filePath, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const CubemapParams& cubemapParams = CubemapParams()); + bool LoadCubemapFromImage(const Image& image, bool generateMipmaps = true, const CubemapParams& params = CubemapParams()); + bool LoadCubemapFromMemory(const void* data, std::size_t size, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const CubemapParams& cubemapParams = CubemapParams()); + bool LoadCubemapFromStream(Stream& stream, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const CubemapParams& cubemapParams = CubemapParams()); + + // LoadFace + bool LoadFaceFromFile(CubemapFace face, const String& filePath, const ImageParams& params = ImageParams()); + bool LoadFaceFromMemory(CubemapFace face, const void* data, std::size_t size, const ImageParams& params = ImageParams()); + bool LoadFaceFromStream(CubemapFace face, Stream& stream, const ImageParams& params = ImageParams()); + + // Save + bool SaveToFile(const String& filePath, const ImageParams& params = ImageParams()); + bool SaveToStream(Stream& stream, const String& format, const ImageParams& params = ImageParams()); + + bool SetMipmapRange(UInt8 minLevel, UInt8 maxLevel); + + bool Update(const Image& image, UInt8 level = 0); + bool Update(const Image& image, const Boxui& box, UInt8 level = 0); + bool Update(const Image& image, const Rectui& rect, unsigned int z = 0, UInt8 level = 0); + bool Update(const UInt8* pixels, unsigned int srcWidth = 0, unsigned int srcHeight = 0, UInt8 level = 0) override; + bool Update(const UInt8* pixels, const Boxui& box, unsigned int srcWidth = 0, unsigned int srcHeight = 0, UInt8 level = 0) override; + bool Update(const UInt8* pixels, const Rectui& rect, unsigned int z = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0, UInt8 level = 0) override; + + // Fonctions OpenGL + unsigned int GetOpenGLID() const; + + Texture& operator=(const Texture&) = delete; + Texture& operator=(Texture&&) = delete; + + static bool IsFormatSupported(PixelFormatType format); + static bool IsMipmappingSupported(); + static bool IsTypeSupported(ImageType type); + template static TextureRef New(Args&&... args); + + // Signals: + NazaraSignal(OnTextureDestroy, const Texture* /*texture*/); + NazaraSignal(OnTextureRelease, const Texture* /*texture*/); + + private: + bool CreateTexture(bool proxy); + + static bool Initialize(); + static void Uninitialize(); + + TextureImpl* m_impl = nullptr; + + static TextureLibrary::LibraryMap s_library; + static TextureManager::ManagerMap s_managerMap; + static TextureManager::ManagerParams s_managerParameters; + }; +} + +#include + +#endif // NAZARA_TEXTURE_HPP diff --git a/include/Nazara/Utility/AbstractTextDrawer.hpp b/include/Nazara/Utility/AbstractTextDrawer.hpp index 9f941b9c9..dd05e5af6 100644 --- a/include/Nazara/Utility/AbstractTextDrawer.hpp +++ b/include/Nazara/Utility/AbstractTextDrawer.hpp @@ -22,6 +22,7 @@ namespace Nz { public: struct Glyph; + struct Line; AbstractTextDrawer() = default; virtual ~AbstractTextDrawer(); @@ -31,15 +32,24 @@ namespace Nz virtual std::size_t GetFontCount() const = 0; virtual const Glyph& GetGlyph(std::size_t index) const = 0; virtual std::size_t GetGlyphCount() const = 0; + virtual const Line& GetLine(std::size_t index) const = 0; + virtual std::size_t GetLineCount() const = 0; struct Glyph { Color color; + Rectf bounds; Rectui atlasRect; Vector2f corners[4]; AbstractImage* atlas; bool flipped; }; + + struct Line + { + Rectf bounds; + std::size_t glyphIndex; + }; }; } diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index 9390b7991..2c162cd7d 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -7,6 +7,8 @@ #ifndef NAZARA_ENUMS_UTILITY_HPP #define NAZARA_ENUMS_UTILITY_HPP +#include + namespace Nz { enum AnimationType @@ -430,20 +432,29 @@ namespace Nz WindowEventType_Max = WindowEventType_TextEntered }; - enum WindowStyleFlags + enum WindowStyle { - WindowStyle_None = 0x0, ///< Window has no border nor titlebar. - WindowStyle_Fullscreen = 0x1, ///< At the window creation, the OS tries to set it in fullscreen. + WindowStyle_None, ///< Window has no border nor titlebar. + WindowStyle_Fullscreen, ///< At the window creation, the OS tries to set it in fullscreen. - WindowStyle_Closable = 0x2, ///< Allows the window to be closed by a button in the titlebar, generating a Quit event. - WindowStyle_Resizable = 0x4, ///< Allows the window to be resized by dragging its corners or by a button of the titlebar. - WindowStyle_Titlebar = 0x8, ///< Adds a titlebar to the window, this option is automatically enabled if buttons of the titlebar are enabled. + WindowStyle_Closable, ///< Allows the window to be closed by a button in the titlebar, generating a Quit event. + WindowStyle_Resizable, ///< Allows the window to be resized by dragging its corners or by a button of the titlebar. + WindowStyle_Titlebar, ///< Adds a titlebar to the window, this option is automatically enabled if buttons of the titlebar are enabled. - WindowStyle_Threaded = 0x10, ///< Runs the window into a thread, allowing the application to keep updating while resizing/dragging the window. + WindowStyle_Threaded, ///< Runs the window into a thread, allowing the application to keep updating while resizing/dragging the window. - WindowStyle_Default = WindowStyle_Closable | WindowStyle_Resizable | WindowStyle_Titlebar, - WindowStyle_Max = WindowStyle_Threaded*2-1 + WindowStyle_Max = WindowStyle_Threaded }; + + template<> + struct EnableFlagsOperators + { + static constexpr bool value = true; + }; + + using WindowStyleFlags = Flags; + + constexpr WindowStyleFlags WindowStyle_Default = WindowStyle_Closable | WindowStyle_Resizable | WindowStyle_Titlebar; } #endif // NAZARA_ENUMS_UTILITY_HPP diff --git a/include/Nazara/Utility/Mesh.hpp b/include/Nazara/Utility/Mesh.hpp index 60ccb98b1..38067ce81 100644 --- a/include/Nazara/Utility/Mesh.hpp +++ b/include/Nazara/Utility/Mesh.hpp @@ -28,25 +28,15 @@ namespace Nz { struct NAZARA_UTILITY_API MeshParams : ResourceParameters { - MeshParams(); // Vérifie que le storage par défaut est supporté (software autrement) + MeshParams(); - // La transformation appliquée à tous les sommets du mesh - Matrix4f matrix = Matrix4f::Identity(); - - // Si ceci sera le stockage utilisé par les buffers - UInt32 storage = DataStorage_Hardware; - - // Charger une version animée du mesh si possible ? - bool animated = true; - - // Faut-il centrer le mesh autour de l'origine ? - bool center = false; - - // Faut-il retourner les UV ? - bool flipUVs = false; - - // Faut-il optimiser les index buffers ? (Rendu plus rapide, mais le chargement dure plus longtemps) - bool optimizeIndexBuffers = true; + Matrix4f matrix = Matrix4f::Identity(); ///< A matrix which will transform every vertex position + UInt32 storage = DataStorage_Hardware; ///< The place where the buffers will be allocated + Vector2f texCoordOffset = {0.f, 0.f}; ///< Offset to apply on the texture coordinates (not scaled) + Vector2f texCoordScale = {1.f, 1.f}; ///< Scale to apply on the texture coordinates + bool animated = true; ///< If true, will load an animated version of the model if possible + bool center = false; ///< If true, will center the mesh vertices around the origin + bool optimizeIndexBuffers = true; ///< Optimize the index buffers after loading, improve cache locality (and thus rendering speed) but increase loading time. bool IsValid() const; }; diff --git a/include/Nazara/Utility/SimpleTextDrawer.hpp b/include/Nazara/Utility/SimpleTextDrawer.hpp index b2f2bf4f9..7c2db6c20 100644 --- a/include/Nazara/Utility/SimpleTextDrawer.hpp +++ b/include/Nazara/Utility/SimpleTextDrawer.hpp @@ -36,6 +36,8 @@ namespace Nz std::size_t GetFontCount() const override; const Glyph& GetGlyph(std::size_t index) const override; std::size_t GetGlyphCount() const override; + const Line& GetLine(std::size_t index) const override; + std::size_t GetLineCount() const override; UInt32 GetStyle() const; const String& GetText() const; @@ -68,6 +70,7 @@ namespace Nz NazaraSlot(Font, OnFontRelease, m_fontReleaseSlot); mutable std::vector m_glyphs; + mutable std::vector m_lines; Color m_color; FontRef m_font; mutable Rectf m_workingBounds; diff --git a/include/Nazara/Utility/Window.hpp b/include/Nazara/Utility/Window.hpp index 0f7688a81..5ecabd8dd 100644 --- a/include/Nazara/Utility/Window.hpp +++ b/include/Nazara/Utility/Window.hpp @@ -36,7 +36,7 @@ namespace Nz public: inline Window(); - inline Window(VideoMode mode, const String& title, UInt32 style = WindowStyle_Default); + inline Window(VideoMode mode, const String& title, WindowStyleFlags style = WindowStyle_Default); inline Window(WindowHandle handle); Window(const Window&) = delete; inline Window(Window&& window) noexcept; @@ -44,7 +44,7 @@ namespace Nz inline void Close(); - bool Create(VideoMode mode, const String& title, UInt32 style = WindowStyle_Default); + bool Create(VideoMode mode, const String& title, WindowStyleFlags style = WindowStyle_Default); bool Create(WindowHandle handle); void Destroy(); @@ -62,7 +62,7 @@ namespace Nz unsigned int GetHeight() const; Vector2i GetPosition() const; Vector2ui GetSize() const; - UInt32 GetStyle() const; + WindowStyleFlags GetStyle() const; String GetTitle() const; unsigned int GetWidth() const; diff --git a/include/Nazara/Utility/Window.inl b/include/Nazara/Utility/Window.inl index cceefebef..0fce86ba6 100644 --- a/include/Nazara/Utility/Window.inl +++ b/include/Nazara/Utility/Window.inl @@ -21,7 +21,7 @@ namespace Nz { } - inline Window::Window(VideoMode mode, const String& title, UInt32 style) : + inline Window::Window(VideoMode mode, const String& title, WindowStyleFlags style) : Window() { ErrorFlags flags(ErrorFlag_ThrowException, true); diff --git a/plugins/Assimp/CustomStream.cpp b/plugins/Assimp/CustomStream.cpp index 643a5b13f..6dbdd90b6 100644 --- a/plugins/Assimp/CustomStream.cpp +++ b/plugins/Assimp/CustomStream.cpp @@ -69,7 +69,7 @@ size_t StreamWrite(aiFile* file, const char* buffer, size_t size, size_t count) aiFile* StreamOpener(aiFileIO* fileIO, const char* filePath, const char* openMode) { - FileIOUserdata* fileIOUserdata = reinterpret_cast(fileIO->UserData); + FileIOUserdata* fileIOUserdata = reinterpret_cast(fileIO->UserData); bool isOriginalStream = (std::strcmp(filePath, fileIOUserdata->originalFilePath) == 0); if (!isOriginalStream && strstr(filePath, StreamPath) != 0) @@ -83,13 +83,13 @@ aiFile* StreamOpener(aiFileIO* fileIO, const char* filePath, const char* openMod ErrorFlags errFlags(ErrorFlag_ThrowExceptionDisabled, true); ///TODO: Move to File::DecodeOpenMode - UInt32 openModeEnum = 0; + OpenModeFlags openModeEnum = 0; if (std::strchr(openMode, 'r')) { openModeEnum |= OpenMode_ReadOnly; if (std::strchr(openMode, '+')) - openModeEnum |= OpenMode_ReadWrite | OpenMode_MustExit; + openModeEnum |= OpenMode_ReadWrite | OpenMode_MustExist; } else if (std::strchr(openMode, 'w')) { @@ -133,10 +133,10 @@ aiFile* StreamOpener(aiFileIO* fileIO, const char* filePath, const char* openMod void StreamCloser(aiFileIO* fileIO, aiFile* file) { - FileIOUserdata* fileIOUserdata = reinterpret_cast(fileIO->UserData); - Stream* fileUserdata = reinterpret_cast(file->UserData); - - if (fileUserdata != fileIOUserdata->originalStream) + FileIOUserdata* fileIOUserdata = reinterpret_cast(fileIO->UserData); + Stream* fileUserdata = reinterpret_cast(file->UserData); + + if (fileUserdata != fileIOUserdata->originalStream) delete reinterpret_cast(file->UserData); delete file; diff --git a/plugins/Assimp/Plugin.cpp b/plugins/Assimp/Plugin.cpp index a668ec634..746549568 100644 --- a/plugins/Assimp/Plugin.cpp +++ b/plugins/Assimp/Plugin.cpp @@ -97,17 +97,14 @@ bool Load(Mesh* mesh, Stream& stream, const MeshParams& parameters) unsigned int postProcess = aiProcess_CalcTangentSpace | aiProcess_JoinIdenticalVertices | aiProcess_MakeLeftHanded | aiProcess_Triangulate | aiProcess_RemoveComponent | aiProcess_GenSmoothNormals - | aiProcess_SplitLargeMeshes | aiProcess_LimitBoneWeights - | aiProcess_ImproveCacheLocality | aiProcess_RemoveRedundantMaterials - | aiProcess_FixInfacingNormals | aiProcess_SortByPType - | aiProcess_FindInvalidData | aiProcess_GenUVCoords - | aiProcess_TransformUVCoords | aiProcess_OptimizeMeshes - | aiProcess_OptimizeGraph | aiProcess_FlipWindingOrder + | aiProcess_SplitLargeMeshes | aiProcess_LimitBoneWeights + | aiProcess_ImproveCacheLocality | aiProcess_RemoveRedundantMaterials + | aiProcess_FixInfacingNormals | aiProcess_SortByPType + | aiProcess_FindInvalidData | aiProcess_GenUVCoords + | aiProcess_TransformUVCoords | aiProcess_OptimizeMeshes + | aiProcess_OptimizeGraph | aiProcess_FlipWindingOrder | aiProcess_Debone; - if (parameters.flipUVs) - postProcess |= aiProcess_FlipUVs; - if (parameters.optimizeIndexBuffers) postProcess |= aiProcess_ImproveCacheLocality; @@ -157,7 +154,7 @@ bool Load(Mesh* mesh, Stream& stream, const MeshParams& parameters) if (animatedMesh) { mesh->CreateSkeletal(joints.size()); - + Skeleton* skeleton = mesh->GetSkeleton(); // First, assign names @@ -172,9 +169,9 @@ bool Load(Mesh* mesh, Stream& stream, const MeshParams& parameters) else { mesh->CreateStatic(); - + // aiMaterial index in scene => Material index and data in Mesh - std::unordered_map> materials; + std::unordered_map> materials; for (unsigned int i = 0; i < scene->mNumMeshes; ++i) { @@ -219,7 +216,7 @@ bool Load(Mesh* mesh, Stream& stream, const MeshParams& parameters) vertex->position = parameters.matrix * Vector3f(position.x, position.y, position.z); vertex->normal.Set(normal.x, normal.y, normal.z); vertex->tangent.Set(tangent.x, tangent.y, tangent.z); - vertex->uv.Set(uv.x, uv.y); + vertex->uv.Set(parameters.texCoordOffset + Vector2f(uv.x, uv.y) * parameters.texCoordScale); vertex++; } @@ -311,7 +308,7 @@ bool Load(Mesh* mesh, Stream& stream, const MeshParams& parameters) mesh->AddSubMesh(subMesh); } - mesh->SetMaterialCount(std::max(materials.size(), 1)); + mesh->SetMaterialCount(std::max(materials.size(), 1)); for (const auto& pair : materials) mesh->SetMaterialData(pair.second.first, pair.second.second); } diff --git a/src/Nazara/Audio/Music.cpp b/src/Nazara/Audio/Music.cpp index 1f0df6ba5..b2b0e7e3b 100644 --- a/src/Nazara/Audio/Music.cpp +++ b/src/Nazara/Audio/Music.cpp @@ -61,8 +61,6 @@ namespace Nz * \return true if creation was succesful * * \param soundStream Sound stream which is the source for the music - * - * \remark Produces a NazaraError if soundStream is invalid with NAZARA_AUDIO_SAFE defined */ bool Music::Create(SoundStream* soundStream) @@ -86,13 +84,14 @@ namespace Nz /*! * \brief Destroys the current music and frees resources + * + * \remark If the Music is playing, it is stopped first. */ - void Music::Destroy() { if (m_impl) { - Stop(); + StopThread(); delete m_impl; m_impl = nullptr; @@ -104,18 +103,11 @@ namespace Nz * * \param loop Should music loop * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \remark Music must be valid when calling this function */ - void Music::EnableLooping(bool loop) { - #if NAZARA_AUDIO_SAFE - if (!m_impl) - { - NazaraError("Music not created"); - return; - } - #endif + NazaraAssert(m_impl, "Music not created"); m_impl->loop = loop; } @@ -124,18 +116,11 @@ namespace Nz * \brief Gets the duration of the music * \return Duration of the music in milliseconds * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \remark Music must be valid when calling this function */ - UInt32 Music::GetDuration() const { - #if NAZARA_AUDIO_SAFE - if (!m_impl) - { - NazaraError("Music not created"); - return 0; - } - #endif + NazaraAssert(m_impl, "Music not created"); return m_impl->stream->GetDuration(); } @@ -144,18 +129,11 @@ namespace Nz * \brief Gets the format of the music * \return Enumeration of type AudioFormat (mono, stereo, ...) * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \remark Music must be valid when calling this function */ - AudioFormat Music::GetFormat() const { - #if NAZARA_AUDIO_SAFE - if (!m_impl) - { - NazaraError("Music not created"); - return AudioFormat_Unknown; - } - #endif + NazaraAssert(m_impl, "Music not created"); return m_impl->stream->GetFormat(); } @@ -164,7 +142,7 @@ namespace Nz * \brief Gets the current offset in the music * \return Offset in milliseconds (works with entire seconds) * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \remark Music must be valid when calling this function */ UInt32 Music::GetPlayingOffset() const { @@ -183,7 +161,7 @@ namespace Nz * \brief Gets the number of samples in the music * \return Count of samples (number of seconds * sample rate * channel count) * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \remark Music must be valid when calling this function */ UInt64 Music::GetSampleCount() const { @@ -196,7 +174,7 @@ namespace Nz * \brief Gets the rates of sample in the music * \return Rate of sample in Hertz (Hz) * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \remark Music must be valid when calling this function */ UInt32 Music::GetSampleRate() const { @@ -209,8 +187,7 @@ namespace Nz * \brief Gets the status of the music * \return Enumeration of type SoundStatus (Playing, Stopped, ...) * - * \remark If the music is not playing, Stopped is returned - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \remark Music must be valid when calling this function */ SoundStatus Music::GetStatus() const { @@ -229,44 +206,37 @@ namespace Nz * \brief Checks whether the music is looping * \return true if it is the case * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \remark Music must be valid when calling this function */ - bool Music::IsLooping() const { - #if NAZARA_AUDIO_SAFE - if (!m_impl) - { - NazaraError("Music not created"); - return false; - } - #endif + NazaraAssert(m_impl, "Music not created"); return m_impl->loop; } /*! - * \brief Loads the music from file - * \return true if loading is successful + * \brief Opens the music from a file + * \return true if the file was successfully opened * * \param filePath Path to the file * \param params Parameters for the music */ - bool Music::OpenFromFile(const String& filePath, const MusicParams& params) { return MusicLoader::LoadFromFile(this, filePath, params); } /*! - * \brief Loads the music from memory + * \brief Opens the music from memory * \return true if loading is successful * * \param data Raw memory * \param size Size of the memory * \param params Parameters for the music + * + * \remark The memory pointer must stay valid (accessible) as long as the music is playing */ - bool Music::OpenFromMemory(const void* data, std::size_t size, const MusicParams& params) { return MusicLoader::LoadFromMemory(this, data, size, params); @@ -278,8 +248,9 @@ namespace Nz * * \param stream Stream to the music * \param params Parameters for the music + * + * \remark The stream must stay valid as long as the music is playing */ - bool Music::OpenFromStream(Stream& stream, const MusicParams& params) { return MusicLoader::LoadFromStream(this, stream, params); @@ -287,8 +258,9 @@ namespace Nz /*! * \brief Pauses the music + * + * \remark Music must be valid when calling this function */ - void Music::Pause() { alSourcePause(m_source); @@ -297,18 +269,16 @@ namespace Nz /*! * \brief Plays the music * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * Plays/Resume the music. + * If the music is currently playing, resets the playing offset to the beginning offset. + * If the music is currently paused, resumes the playing. + * If the music is currently stopped, starts the playing at the previously set playing offset. + * + * \remark Music must be valid when calling this function */ - void Music::Play() { - #if NAZARA_AUDIO_SAFE - if (!m_impl) - { - NazaraError("Music not created"); - return; - } - #endif + NazaraAssert(m_impl, "Music not created"); // Maybe we are already playing if (m_impl->streaming) @@ -336,25 +306,20 @@ namespace Nz } /*! - * \brief Sets the playing offset for the music + * \brief Changes the playing offset of the music * - * \param offset Offset in the music in milliseconds + * If the music is not playing, this sets the playing offset for the next Play call * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \param offset The offset in milliseconds + * + * \remark Music must be valid when calling this function */ - void Music::SetPlayingOffset(UInt32 offset) { - #if NAZARA_AUDIO_SAFE - if (!m_impl) - { - NazaraError("Music not created"); - return; - } - #endif + NazaraAssert(m_impl, "Music not created"); bool isPlaying = m_impl->streaming; - + if (isPlaying) Stop(); @@ -368,33 +333,16 @@ namespace Nz /*! * \brief Stops the music * - * \remark Produces a NazaraError if there is no music with NAZARA_AUDIO_SAFE defined + * \remark Music must be valid when calling this function */ - void Music::Stop() { - #if NAZARA_AUDIO_SAFE - if (!m_impl) - { - NazaraError("Music not created"); - return; - } - #endif + NazaraAssert(m_impl, "Music not created"); - if (m_impl->streaming) - { - m_impl->streaming = false; - m_impl->thread.Join(); - } + StopThread(); + SetPlayingOffset(0); } - /*! - * \brief Fills the buffer and queues it up - * \return true if operation was successful - * - * \param buffer Index of the buffer - */ - bool Music::FillAndQueueBuffer(unsigned int buffer) { std::size_t sampleCount = m_impl->chunkSamples.size(); @@ -425,10 +373,6 @@ namespace Nz return sampleRead != sampleCount; // End of stream (Does not happen when looping) } - /*! - * \brief Thread function for the music - */ - void Music::MusicThread() { // Allocation of streaming buffers @@ -463,11 +407,11 @@ namespace Nz { ALuint buffer; alSourceUnqueueBuffers(m_source, 1, &buffer); - + ALint bits, size; alGetBufferi(buffer, AL_BITS, &bits); alGetBufferi(buffer, AL_SIZE, &size); - + if (bits != 0) m_impl->processedSamples += (8 * size) / bits; @@ -495,5 +439,14 @@ namespace Nz alDeleteBuffers(NAZARA_AUDIO_STREAMED_BUFFER_COUNT, buffers); } + void Music::StopThread() + { + if (m_impl->streaming) + { + m_impl->streaming = false; + m_impl->thread.Join(); + } + } + MusicLoader::LoaderList Music::s_loaders; } diff --git a/src/Nazara/Core/ByteStream.cpp b/src/Nazara/Core/ByteStream.cpp index bca3db240..bc52f1782 100644 --- a/src/Nazara/Core/ByteStream.cpp +++ b/src/Nazara/Core/ByteStream.cpp @@ -24,7 +24,7 @@ namespace Nz * \param openMode Reading/writing mode for the stream */ - ByteStream::ByteStream(ByteArray* byteArray, UInt32 openMode) : + ByteStream::ByteStream(ByteArray* byteArray, OpenModeFlags openMode) : ByteStream() { SetStream(byteArray, openMode); @@ -67,7 +67,7 @@ namespace Nz * \param openMode Reading/writing mode for the stream */ - void ByteStream::SetStream(ByteArray* byteArray, UInt32 openMode) + void ByteStream::SetStream(ByteArray* byteArray, OpenModeFlags openMode) { std::unique_ptr stream(new MemoryStream(byteArray, openMode)); diff --git a/src/Nazara/Core/File.cpp b/src/Nazara/Core/File.cpp index 1fd77546f..35706fb70 100644 --- a/src/Nazara/Core/File.cpp +++ b/src/Nazara/Core/File.cpp @@ -64,7 +64,7 @@ namespace Nz * \param openMode Flag of the file */ - File::File(const String& filePath, UInt32 openMode) : + File::File(const String& filePath, OpenModeFlags openMode) : File() { Open(filePath, openMode); @@ -311,7 +311,7 @@ namespace Nz * \remark Produces a NazaraError if OS error to open a file */ - bool File::Open(unsigned int openMode) + bool File::Open(OpenModeFlags openMode) { NazaraLock(m_mutex) @@ -352,7 +352,7 @@ namespace Nz * \remark Produces a NazaraError if OS error to open a file */ - bool File::Open(const String& filePath, unsigned int openMode) + bool File::Open(const String& filePath, OpenModeFlags openMode) { NazaraLock(m_mutex) diff --git a/src/Nazara/Core/MemoryStream.cpp b/src/Nazara/Core/MemoryStream.cpp index bb77f35f8..a2fb7ff2b 100644 --- a/src/Nazara/Core/MemoryStream.cpp +++ b/src/Nazara/Core/MemoryStream.cpp @@ -65,7 +65,7 @@ namespace Nz * \remark Produces a NazaraAssert if byteArray is nullptr */ - void MemoryStream::SetBuffer(ByteArray* byteArray, UInt32 openMode) + void MemoryStream::SetBuffer(ByteArray* byteArray, OpenModeFlags openMode) { NazaraAssert(byteArray, "Invalid ByteArray"); diff --git a/src/Nazara/Core/Posix/FileImpl.cpp b/src/Nazara/Core/Posix/FileImpl.cpp index 037d795f0..5603ed79b 100644 --- a/src/Nazara/Core/Posix/FileImpl.cpp +++ b/src/Nazara/Core/Posix/FileImpl.cpp @@ -49,7 +49,7 @@ namespace Nz return static_cast(position); } - bool FileImpl::Open(const String& filePath, UInt32 mode) + bool FileImpl::Open(const String& filePath, OpenModeFlags mode) { int flags; mode_t permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; @@ -66,6 +66,9 @@ namespace Nz if (mode & OpenMode_Append) flags |= O_APPEND; + if (mode & OpenMode_MustExist) + flags &= ~O_CREAT; + if (mode & OpenMode_Truncate) flags |= O_TRUNC; diff --git a/src/Nazara/Core/Posix/FileImpl.hpp b/src/Nazara/Core/Posix/FileImpl.hpp index 4981a832e..51f966980 100644 --- a/src/Nazara/Core/Posix/FileImpl.hpp +++ b/src/Nazara/Core/Posix/FileImpl.hpp @@ -36,7 +36,7 @@ namespace Nz bool EndOfFile() const; void Flush(); UInt64 GetCursorPos() const; - bool Open(const String& filePath, UInt32 mode); + bool Open(const String& filePath, OpenModeFlags mode); std::size_t Read(void* buffer, std::size_t size); bool SetCursorPos(CursorPosition pos, Int64 offset); bool SetSize(UInt64 size); diff --git a/src/Nazara/Core/String.cpp b/src/Nazara/Core/String.cpp index 5019f0885..ac01bf92c 100644 --- a/src/Nazara/Core/String.cpp +++ b/src/Nazara/Core/String.cpp @@ -2094,6 +2094,43 @@ namespace Nz return m_sharedString->capacity; } + /*! + * \brief Gets the index where a character begin + * + * Iterate through the string to find the starting position of a specific character index + * This is useful because non-ASCII characters may be encoded using multiple bytes. + * + * \param characterIndex Index of the character to search for + * + * \return Starting index + */ + std::size_t String::GetCharacterPosition(std::size_t characterIndex) const + { + const char* ptr = m_sharedString->string.get(); + const char* end = &m_sharedString->string[m_sharedString->size]; + + try + { + utf8::advance(ptr, characterIndex, end); + + return ptr - m_sharedString->string.get(); + } + catch (utf8::not_enough_room& e) + { + // Returns npos + } + catch (utf8::exception& e) + { + NazaraError("UTF-8 error: " + String(e.what())); + } + catch (std::exception& e) + { + NazaraError(e.what()); + } + + return npos; + } + /*! * \brief Gets the raw buffer * \return Raw buffer @@ -5948,7 +5985,7 @@ namespace std char c; - for (;;) + for (;;) { is.get(c); if (c != delim && c != '\0') diff --git a/src/Nazara/Core/Win32/FileImpl.cpp b/src/Nazara/Core/Win32/FileImpl.cpp index 5ed051adb..1fb5a19eb 100644 --- a/src/Nazara/Core/Win32/FileImpl.cpp +++ b/src/Nazara/Core/Win32/FileImpl.cpp @@ -55,20 +55,20 @@ namespace Nz return position.QuadPart; } - bool FileImpl::Open(const String& filePath, UInt32 mode) + bool FileImpl::Open(const String& filePath, OpenModeFlags mode) { DWORD access = 0; DWORD shareMode = FILE_SHARE_READ; DWORD openMode = 0; - + if (mode & OpenMode_ReadOnly) { access |= GENERIC_READ; - if (mode & OpenMode_MustExit || (mode & OpenMode_WriteOnly) == 0) + if (mode & OpenMode_MustExist || (mode & OpenMode_WriteOnly) == 0) openMode |= OPEN_EXISTING; } - + if (mode & OpenMode_WriteOnly) { if (mode & OpenMode_Append) @@ -78,7 +78,7 @@ namespace Nz if (mode & OpenMode_Truncate) openMode |= CREATE_ALWAYS; - else if (mode & OpenMode_MustExit) + else if (mode & OpenMode_MustExist) openMode |= OPEN_EXISTING; else openMode |= OPEN_ALWAYS; diff --git a/src/Nazara/Core/Win32/FileImpl.hpp b/src/Nazara/Core/Win32/FileImpl.hpp index 9a669cb19..dabfc266c 100644 --- a/src/Nazara/Core/Win32/FileImpl.hpp +++ b/src/Nazara/Core/Win32/FileImpl.hpp @@ -29,7 +29,7 @@ namespace Nz bool EndOfFile() const; void Flush(); UInt64 GetCursorPos() const; - bool Open(const String& filePath, UInt32 mode); + bool Open(const String& filePath, OpenModeFlags mode); std::size_t Read(void* buffer, std::size_t size); bool SetCursorPos(CursorPosition pos, Int64 offset); bool SetSize(UInt64 size); diff --git a/src/Nazara/Graphics/ForwardRenderQueue.cpp b/src/Nazara/Graphics/ForwardRenderQueue.cpp index 97c3a53d5..6c6915214 100644 --- a/src/Nazara/Graphics/ForwardRenderQueue.cpp +++ b/src/Nazara/Graphics/ForwardRenderQueue.cpp @@ -527,6 +527,24 @@ namespace Nz layers.erase(it++); else { + for (auto& pipelinePair : layer.billboards) + { + auto& pipelineEntry = pipelinePair.second; + + if (pipelineEntry.enabled) + { + for (auto& matIt : pipelinePair.second.materialMap) + { + auto& entry = matIt.second; + auto& billboardVector = entry.billboards; + + billboardVector.clear(); + } + } + + pipelineEntry.enabled = false; + } + for (auto& pipelinePair : layer.basicSprites) { auto& pipelineEntry = pipelinePair.second; diff --git a/src/Nazara/Graphics/ForwardRenderTechnique.cpp b/src/Nazara/Graphics/ForwardRenderTechnique.cpp index 7792a93b2..76541c982 100644 --- a/src/Nazara/Graphics/ForwardRenderTechnique.cpp +++ b/src/Nazara/Graphics/ForwardRenderTechnique.cpp @@ -561,8 +561,6 @@ namespace Nz Renderer::DrawIndexedPrimitives(PrimitiveMode_TriangleList, 0, renderedBillboardCount * 6); } while (billboardCount > 0); - - billboardVector.clear(); } } } @@ -772,7 +770,6 @@ namespace Nz } } } - instances.clear(); } } } diff --git a/src/Nazara/Graphics/TextSprite.cpp b/src/Nazara/Graphics/TextSprite.cpp index 42dba4aaf..7e8402e20 100644 --- a/src/Nazara/Graphics/TextSprite.cpp +++ b/src/Nazara/Graphics/TextSprite.cpp @@ -108,6 +108,8 @@ namespace Nz for (std::size_t i = 0; i < glyphCount; ++i) { const AbstractTextDrawer::Glyph& glyph = drawer.GetGlyph(i); + if (!glyph.atlas) + continue; Texture* texture = static_cast(glyph.atlas); if (lastTexture != texture) @@ -149,6 +151,8 @@ namespace Nz for (unsigned int i = 0; i < glyphCount; ++i) { const AbstractTextDrawer::Glyph& glyph = drawer.GetGlyph(i); + if (!glyph.atlas) + continue; Texture* texture = static_cast(glyph.atlas); if (lastTexture != texture) @@ -200,8 +204,8 @@ namespace Nz void TextSprite::MakeBoundingVolume() const { Rectf bounds(m_localBounds); - Vector2f max = bounds.GetMaximum(); - Vector2f min = bounds.GetMinimum(); + Vector2f max = m_scale * bounds.GetMaximum(); + Vector2f min = m_scale * bounds.GetMinimum(); m_boundingVolume.Set(min.x * Vector3f::Right() + min.y * Vector3f::Down(), max.x * Vector3f::Right() + max.y * Vector3f::Down()); } diff --git a/src/Nazara/Network/NetPacket.cpp b/src/Nazara/Network/NetPacket.cpp index dcac9e178..900170b89 100644 --- a/src/Nazara/Network/NetPacket.cpp +++ b/src/Nazara/Network/NetPacket.cpp @@ -127,7 +127,7 @@ namespace Nz * \remark Produces a NazaraAssert if cursor position is greather than the capacity */ - void NetPacket::InitStream(std::size_t minCapacity, UInt64 cursorPos, UInt32 openMode) + void NetPacket::InitStream(std::size_t minCapacity, UInt64 cursorPos, OpenModeFlags openMode) { NazaraAssert(minCapacity >= cursorPos, "Cannot init stream with a smaller capacity than wanted cursor pos"); diff --git a/src/Nazara/Renderer/RenderTexture.cpp b/src/Nazara/Renderer/RenderTexture.cpp deleted file mode 100644 index d90ba5f1a..000000000 --- a/src/Nazara/Renderer/RenderTexture.cpp +++ /dev/null @@ -1,855 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - namespace - { - struct Attachment - { - NazaraSlot(RenderBuffer, OnRenderBufferDestroy, renderBufferDestroySlot); - NazaraSlot(Texture, OnTextureDestroy, textureDestroySlot); - - RenderBufferRef buffer; - TextureRef texture; - - AttachmentPoint attachmentPoint; - bool isBuffer; - bool isUsed = false; - unsigned int height; - unsigned int width; - }; - - unsigned int attachmentIndex[AttachmentPoint_Max+1] = - { - 3, // AttachmentPoint_Color - 0, // AttachmentPoint_Depth - 1, // AttachmentPoint_DepthStencil - 2 // AttachmentPoint_Stencil - }; - - AttachmentPoint FormatTypeToAttachment(PixelFormatType format) - { - const PixelFormatInfo& info = PixelFormat::GetInfo(format); - switch (info.content) - { - case PixelFormatContent_ColorRGBA: - return AttachmentPoint_Color; - - case PixelFormatContent_DepthStencil: - return (!info.greenMask.TestAny()) ? AttachmentPoint_Depth : AttachmentPoint_DepthStencil; - - case PixelFormatContent_Stencil: - return AttachmentPoint_Stencil; - - case PixelFormatContent_Undefined: - break; - } - - NazaraInternalError("Unexpected pixel format content: 0x" + String::Number(info.content, 16)); - return AttachmentPoint_Max; - } - - GLuint lockedPrevious = 0; - UInt8 lockedLevel = 0; - } - - struct RenderTextureImpl - { - NazaraSlot(Context, OnContextDestroy, contextDestroySlot); - - GLuint fbo; - std::vector attachments; - std::vector colorTargets; - mutable std::vector drawBuffers; - const Context* context; - bool complete = false; - bool userDefinedTargets = false; - unsigned int height; - unsigned int width; - }; - - bool RenderTexture::AttachBuffer(AttachmentPoint attachmentPoint, UInt8 index, RenderBuffer* buffer) - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Render texture not created"); - return false; - } - - if (attachmentPoint != AttachmentPoint_Color) - { - if (index > 0) - { - NazaraError("Index must be 0 for non-color attachments"); - return false; - } - } - else - { - if (index >= Renderer::GetMaxColorAttachments()) - { - NazaraError("Color index is over max color attachments (" + String::Number(index) + " >= " + String::Number(Renderer::GetMaxColorAttachments()) + ")"); - return false; - } - } - - if (!buffer || !buffer->IsValid()) - { - NazaraError("Invalid render buffer"); - return false; - } - - unsigned int depthStencilIndex = attachmentIndex[AttachmentPoint_DepthStencil]; - if (m_impl->attachments.size() > depthStencilIndex && m_impl->attachments[depthStencilIndex].isUsed) - { - if (attachmentPoint == AttachmentPoint_Depth) - { - NazaraError("Depth target already attached by DepthStencil attachment"); - return false; - } - else if (attachmentPoint == AttachmentPoint_Stencil) - { - NazaraError("Stencil target already attached by DepthStencil attachment"); - return false; - } - } - - AttachmentPoint targetAttachmentPoint = FormatTypeToAttachment(buffer->GetFormat()); - if (targetAttachmentPoint != attachmentPoint && targetAttachmentPoint != AttachmentPoint_DepthStencil && - attachmentPoint != AttachmentPoint_Depth && attachmentPoint != AttachmentPoint_Stencil) - { - NazaraError("Pixel format type does not match attachment point type"); - return false; - } - #endif - - if (!Lock()) - { - NazaraError("Failed to lock render texture"); - return false; - } - - // Détachement de l'attache précédente (Si il y a) - Detach(attachmentPoint, index); - - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, OpenGL::Attachment[attachmentPoint]+index, GL_RENDERBUFFER, buffer->GetOpenGLID()); - - Unlock(); - - unsigned int attachIndex = attachmentIndex[attachmentPoint] + index; - if (attachIndex >= m_impl->attachments.size()) - m_impl->attachments.resize(attachIndex+1); - - Attachment& attachment = m_impl->attachments[attachIndex]; - attachment.attachmentPoint = attachmentPoint; - attachment.buffer = buffer; - attachment.renderBufferDestroySlot.Connect(buffer->OnRenderBufferDestroy, std::bind(&RenderTexture::OnRenderBufferDestroy, this, std::placeholders::_1, attachIndex)); - attachment.isBuffer = true; - attachment.isUsed = true; - attachment.height = buffer->GetHeight(); - attachment.width = buffer->GetWidth(); - - InvalidateSize(); - InvalidateTargets(); - - return true; - } - - bool RenderTexture::AttachBuffer(AttachmentPoint attachmentPoint, UInt8 index, PixelFormatType format, unsigned int width, unsigned int height) - { - RenderBufferRef renderBuffer = RenderBuffer::New(); - if (!renderBuffer->Create(format, width, height)) - { - NazaraError("Failed to create RenderBuffer"); - return false; - } - - if (!AttachBuffer(attachmentPoint, index, renderBuffer)) - { - NazaraError("Failed to attach buffer"); - return false; - } - - return true; - } - - bool RenderTexture::AttachTexture(AttachmentPoint attachmentPoint, UInt8 index, Texture* texture, unsigned int z) - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Render texture not created"); - return false; - } - - if (attachmentPoint != AttachmentPoint_Color) - { - if (index > 0) - { - NazaraError("Index must be 0 for non-color attachments"); - return false; - } - } - else - { - if (index >= Renderer::GetMaxColorAttachments()) - { - NazaraError("Color index is over max color attachments (" + String::Number(index) + " >= " + String::Number(Renderer::GetMaxColorAttachments()) + ")"); - return false; - } - } - - if (attachmentPoint == AttachmentPoint_Stencil) - { - NazaraError("Targeting stencil-only textures is not supported"); - return false; - } - - unsigned int depthStencilIndex = attachmentIndex[AttachmentPoint_DepthStencil]; - if (attachmentPoint == AttachmentPoint_Depth && m_impl->attachments.size() > depthStencilIndex && - m_impl->attachments[depthStencilIndex].isUsed) - { - NazaraError("Depth target already attached by DepthStencil attachment"); - return false; - } - - if (!texture || !texture->IsValid()) - { - NazaraError("Invalid texture"); - return false; - } - - unsigned int depth = (texture->GetType() == ImageType_Cubemap) ? 6 : texture->GetDepth(); - if (z >= depth) - { - NazaraError("Z value exceeds depth (" + String::Number(z) + " >= (" + String::Number(depth) + ')'); - return false; - } - - AttachmentPoint targetAttachmentPoint = FormatTypeToAttachment(texture->GetFormat()); - if (targetAttachmentPoint != attachmentPoint && targetAttachmentPoint != AttachmentPoint_DepthStencil && - attachmentPoint != AttachmentPoint_Depth && attachmentPoint != AttachmentPoint_Stencil) - { - NazaraError("Pixel format type does not match attachment point type"); - return false; - } - #endif - - if (!Lock()) - { - NazaraError("Failed to lock render texture"); - return false; - } - - // Détachement de l'attache précédente (Si il y a) - Detach(attachmentPoint, index); - - switch (texture->GetType()) - { - case ImageType_1D: - glFramebufferTexture1D(GL_DRAW_FRAMEBUFFER, OpenGL::Attachment[attachmentPoint]+index, GL_TEXTURE_1D, texture->GetOpenGLID(), 0); - break; - - case ImageType_1D_Array: - case ImageType_2D_Array: - glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, OpenGL::Attachment[attachmentPoint]+index, texture->GetOpenGLID(), 0, z); - break; - - case ImageType_2D: - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, OpenGL::Attachment[attachmentPoint]+index, GL_TEXTURE_2D, texture->GetOpenGLID(), 0); - break; - - case ImageType_3D: - glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, OpenGL::Attachment[attachmentPoint]+index, GL_TEXTURE_3D, texture->GetOpenGLID(), 0, z); - break; - - case ImageType_Cubemap: - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, OpenGL::Attachment[attachmentPoint]+index, OpenGL::CubemapFace[z], texture->GetOpenGLID(), 0); - break; - } - - Unlock(); - - unsigned int attachIndex = attachmentIndex[attachmentPoint] + index; - if (attachIndex >= m_impl->attachments.size()) - m_impl->attachments.resize(attachIndex+1); - - Attachment& attachment = m_impl->attachments[attachIndex]; - attachment.attachmentPoint = attachmentPoint; - attachment.isBuffer = false; - attachment.isUsed = true; - attachment.height = texture->GetHeight(); - attachment.texture = texture; - attachment.textureDestroySlot.Connect(texture->OnTextureDestroy, std::bind(&RenderTexture::OnTextureDestroy, this, std::placeholders::_1, attachIndex)); - attachment.width = texture->GetWidth(); - - InvalidateSize(); - InvalidateTargets(); - - return true; - } - - bool RenderTexture::Create(bool lock) - { - Destroy(); - - #if NAZARA_RENDERER_SAFE - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return false; - } - #endif - - std::unique_ptr impl(new RenderTextureImpl); - - impl->fbo = 0; - glGenFramebuffers(1, &impl->fbo); - - if (!impl->fbo) - { - NazaraError("Failed to create framebuffer"); - return false; - } - - m_impl = impl.release(); - m_impl->context = Context::GetCurrent(); - m_impl->contextDestroySlot.Connect(m_impl->context->OnContextDestroy, this, &RenderTexture::OnContextDestroy); - - m_checked = false; - m_drawBuffersUpdated = true; - m_sizeUpdated = false; - m_targetsUpdated = true; - - if (lock) - { - // En cas d'exception, la ressource sera quand même libérée - CallOnExit onExit([this] () - { - Destroy(); - }); - - if (!Lock()) - { - NazaraError("Failed to lock render texture"); - return false; - } - - onExit.Reset(); - } - - OnRenderTargetParametersChange(this); - OnRenderTargetSizeChange(this); - - return true; - } - - void RenderTexture::Destroy() - { - if (m_impl) - { - if (IsActive()) - Renderer::SetTarget(nullptr); - - // Le FBO devant être supprimé dans son contexte d'origine, nous déléguons sa suppression à la classe OpenGL - // Celle-ci va libérer le FBO dès que possible (la prochaine fois que son contexte d'origine sera actif) - OpenGL::DeleteFrameBuffer(m_impl->context, m_impl->fbo); - - delete m_impl; // Enlève également une références sur les Texture/RenderBuffer - m_impl = nullptr; - } - } - - void RenderTexture::Detach(AttachmentPoint attachmentPoint, UInt8 index) - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Render texture not created"); - return; - } - - if (attachmentPoint != AttachmentPoint_Color && index > 0) - { - NazaraError("Index must be 0 for non-color attachments"); - return; - } - #endif - - unsigned int attachIndex = attachmentIndex[attachmentPoint] + index; - if (attachIndex >= m_impl->attachments.size()) - return; - - Attachment& attachement = m_impl->attachments[attachIndex]; - if (!attachement.isUsed) - return; - - if (!Lock()) - { - NazaraError("Failed to lock render texture"); - return; - } - - attachement.isUsed = false; - - if (attachement.isBuffer) - { - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, OpenGL::Attachment[attachmentPoint]+index, GL_RENDERBUFFER, 0); - - attachement.buffer = nullptr; - attachement.renderBufferDestroySlot.Disconnect(); - } - else - { - if (glFramebufferTexture) - glFramebufferTexture(GL_DRAW_FRAMEBUFFER, OpenGL::Attachment[attachmentPoint]+index, 0, 0); - else - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, OpenGL::Attachment[attachmentPoint]+index, 0, 0, 0); - - attachement.texture = nullptr; - attachement.textureDestroySlot.Disconnect(); - } - - InvalidateSize(); - - if (attachement.attachmentPoint == AttachmentPoint_Color) - InvalidateTargets(); - - Unlock(); - - m_checked = false; - } - - unsigned int RenderTexture::GetHeight() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - if (!m_sizeUpdated) - UpdateSize(); - - return m_impl->height; - } - - RenderTargetParameters RenderTexture::GetParameters() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - ///TODO - return RenderTargetParameters(); - } - - Vector2ui RenderTexture::GetSize() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - if (!m_sizeUpdated) - UpdateSize(); - - return Vector2ui(m_impl->width, m_impl->height); - } - - unsigned int RenderTexture::GetWidth() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - if (!m_sizeUpdated) - UpdateSize(); - - return m_impl->width; - } - - bool RenderTexture::IsComplete() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - if (!m_checked) - { - if (!Lock()) - { - NazaraError("Failed to lock render texture"); - return false; - } - - GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - Unlock(); - - m_impl->complete = false; - - switch (status) - { - case GL_FRAMEBUFFER_COMPLETE: - m_impl->complete = true; - break; - - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - NazaraError("Incomplete attachment"); - break; - - case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: - NazaraInternalError("Incomplete draw buffer"); - break; - - case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: - NazaraInternalError("Incomplete read buffer"); - break; - - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - NazaraError("Incomplete missing attachment"); - break; - - case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: - NazaraError("Incomplete multisample"); - break; - - case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: - NazaraError("Incomplete layer targets"); - break; - - case GL_FRAMEBUFFER_UNSUPPORTED: - NazaraError("Render texture has unsupported attachments"); - break; - - default: - NazaraInternalError("Unknown error"); - } - - m_checked = true; - } - - return m_impl->complete; - } - - bool RenderTexture::IsRenderable() const - { - return IsComplete() && !m_impl->attachments.empty(); - } - - bool RenderTexture::Lock() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - #if NAZARA_RENDERER_SAFE - if (Context::GetCurrent() != m_impl->context) - { - NazaraError("RenderTexture cannot be used with this context"); - return false; - } - #endif - - if (lockedLevel++ == 0) - { - GLint previous; - glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &previous); - - lockedPrevious = previous; - - if (lockedPrevious != m_impl->fbo) - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_impl->fbo); - } - - return true; - } - - void RenderTexture::SetColorTargets(const UInt8* targets, unsigned int targetCount) const - { - NazaraAssert(m_impl, "Invalid render texture"); - - #if NAZARA_RENDERER_SAFE - for (unsigned int i = 0; i < targetCount; ++i) - { - unsigned int index = attachmentIndex[AttachmentPoint_Color] + targets[i]; - if (index >= m_impl->attachments.size() || !m_impl->attachments[index].isUsed) - { - NazaraError("Target " + String::Number(targets[i]) + " not attached"); - return; - } - } - #endif - - m_impl->colorTargets.resize(targetCount); - std::memcpy(&m_impl->colorTargets[0], targets, targetCount*sizeof(UInt8)); - - m_impl->userDefinedTargets = true; - InvalidateTargets(); - } - - void RenderTexture::SetColorTargets(const std::initializer_list& targets) const - { - NazaraAssert(m_impl, "Invalid render texture"); - - #if NAZARA_RENDERER_SAFE - for (UInt8 target : targets) - { - unsigned int index = attachmentIndex[AttachmentPoint_Color] + target; - if (index >= m_impl->attachments.size() || !m_impl->attachments[index].isUsed) - { - NazaraError("Target " + String::Number(target) + " not attached"); - return; - } - } - #endif - - m_impl->colorTargets.resize(targets.size()); - - UInt8* ptr = &m_impl->colorTargets[0]; - for (UInt8 index : targets) - *ptr++ = index; - - m_impl->userDefinedTargets = true; - InvalidateTargets(); - } - - void RenderTexture::Unlock() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - #if NAZARA_RENDERER_SAFE - if (Context::GetCurrent() != m_impl->context) - { - NazaraError("RenderTexture cannot be used with this context"); - return; - } - - if (lockedLevel == 0) - { - NazaraWarning("Unlock called on non-locked texture"); - return; - } - #endif - - if (--lockedLevel == 0 && lockedPrevious != m_impl->fbo) // Ici, il est important qu'un FBO soit débindé si l'ancien était 0 - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, lockedPrevious); - } - - unsigned int RenderTexture::GetOpenGLID() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - #if NAZARA_RENDERER_SAFE - if (Context::GetCurrent() != m_impl->context) - { - NazaraError("RenderTexture cannot be used with this context"); - return 0; - } - #endif - - return m_impl->fbo; - } - - bool RenderTexture::HasContext() const - { - return false; - } - - void RenderTexture::Blit(RenderTexture* src, Rectui srcRect, RenderTexture* dst, Rectui dstRect, UInt32 buffers, bool bilinearFilter) - { - NazaraAssert(src && src->IsValid(), "Invalid source render texture"); - NazaraAssert(dst && dst->IsValid(), "Invalid destination render texture"); - - #if NAZARA_RENDERER_SAFE - if (srcRect.x+srcRect.width > src->GetWidth() || srcRect.y+srcRect.height > src->GetHeight()) - { - NazaraError("Source rectangle dimensions are out of bounds"); - return; - } - - if (dstRect.x+dstRect.width > dst->GetWidth() || dstRect.y+dstRect.height > dst->GetHeight()) - { - NazaraError("Destination rectangle dimensions are out of bounds"); - return; - } - - if (bilinearFilter && (buffers & RendererBuffer_Depth || buffers & RendererBuffer_Stencil)) - { - NazaraError("Filter cannot be bilinear when blitting depth/stencil buffers"); - return; - } - #endif - - GLbitfield mask = 0; - if (buffers & RendererBuffer_Color) - mask |= GL_COLOR_BUFFER_BIT; - - if (buffers & RendererBuffer_Depth) - mask |= GL_DEPTH_BUFFER_BIT; - - if (buffers & RendererBuffer_Stencil) - mask |= GL_STENCIL_BUFFER_BIT; - - GLint previousDrawBuffer, previousReadBuffer; - glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &previousDrawBuffer); - glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &previousReadBuffer); - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst->GetOpenGLID()); - glBindFramebuffer(GL_READ_FRAMEBUFFER, src->GetOpenGLID()); - - glBlitFramebuffer(srcRect.x, srcRect.y, srcRect.x + srcRect.width, srcRect.y + srcRect.height, - dstRect.x, dstRect.y, dstRect.x + dstRect.width, dstRect.y + dstRect.height, - mask, (bilinearFilter) ? GL_LINEAR : GL_NEAREST); - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, previousDrawBuffer); - glBindFramebuffer(GL_READ_FRAMEBUFFER, previousReadBuffer); - } - - bool RenderTexture::Activate() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - #if NAZARA_RENDERER_SAFE - if (Context::GetCurrent() != m_impl->context) - { - NazaraError("RenderTexture cannot be used with this context"); - return false; - } - #endif - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_impl->fbo); - - m_drawBuffersUpdated = false; - - return true; - } - - void RenderTexture::Desactivate() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - #if NAZARA_RENDERER_SAFE - if (Context::GetCurrent() != m_impl->context) - { - NazaraError("RenderTexture cannot be used with this context"); - return; - } - #endif - - glFlush(); - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - } - - void RenderTexture::EnsureTargetUpdated() const - { - if (!m_drawBuffersUpdated) - UpdateDrawBuffers(); - - for (UInt8 index : m_impl->colorTargets) - { - Attachment& attachment = m_impl->attachments[attachmentIndex[AttachmentPoint_Color] + index]; - if (!attachment.isBuffer) - attachment.texture->InvalidateMipmaps(); - } - } - - void RenderTexture::OnContextDestroy(const Context* context) - { - NazaraAssert(m_impl, "Invalid internal state"); - NazaraUnused(context); - - #ifdef NAZARA_DEBUG - if (m_impl->context != context) - { - NazaraInternalError("Not listening to " + String::Pointer(context)); - return; - } - #endif - - Destroy(); - } - - void RenderTexture::OnRenderBufferDestroy(const RenderBuffer* renderBuffer, unsigned int attachmentIndex) - { - NazaraAssert(m_impl, "Invalid internal state"); - NazaraAssert(attachmentIndex < m_impl->attachments.size(), "Invalid attachment index"); - NazaraAssert(m_impl->attachments[attachmentIndex].isBuffer, "Invalid attachment state"); - NazaraUnused(renderBuffer); - - Attachment& attachment = m_impl->attachments[attachmentIndex]; - attachment.buffer = nullptr; - attachment.isUsed = false; - attachment.renderBufferDestroySlot.Disconnect(); - - InvalidateTargets(); - } - - void RenderTexture::OnTextureDestroy(const Texture* texture, unsigned int attachmentIndex) - { - NazaraAssert(m_impl, "Invalid internal state"); - NazaraAssert(attachmentIndex < m_impl->attachments.size(), "Invalid attachment index"); - NazaraAssert(!m_impl->attachments[attachmentIndex].isBuffer, "Invalid attachment state"); - NazaraUnused(texture); - NazaraUnused(attachmentIndex); - - InvalidateTargets(); - } - - void RenderTexture::UpdateDrawBuffers() const - { - if (!m_targetsUpdated) - UpdateTargets(); - - glDrawBuffers(m_impl->drawBuffers.size(), &m_impl->drawBuffers[0]); - - m_drawBuffersUpdated = true; - } - - void RenderTexture::UpdateSize() const - { - m_impl->width = 0; - m_impl->height = 0; - for (Attachment& attachment : m_impl->attachments) - { - if (attachment.isUsed) - { - m_impl->height = std::max(m_impl->height, attachment.height); - m_impl->width = std::max(m_impl->width, attachment.width); - } - } - - m_sizeUpdated = true; - } - - void RenderTexture::UpdateTargets() const - { - if (!m_impl->userDefinedTargets) - { - m_impl->colorTargets.clear(); - - unsigned int colorIndex = 0; - for (unsigned int index = attachmentIndex[AttachmentPoint_Color]; index < m_impl->attachments.size(); ++index) - m_impl->colorTargets.push_back(colorIndex++); - } - - if (m_impl->colorTargets.empty()) - { - m_impl->drawBuffers.resize(1); - m_impl->drawBuffers[0] = GL_NONE; - } - else - { - m_impl->drawBuffers.resize(m_impl->colorTargets.size()); - GLenum* ptr = &m_impl->drawBuffers[0]; - for (UInt8 index : m_impl->colorTargets) - *ptr++ = GL_COLOR_ATTACHMENT0 + index; - } - - m_targetsUpdated = true; - } -} diff --git a/src/Nazara/Renderer/RenderWindow.cpp b/src/Nazara/Renderer/RenderWindow.cpp index 117caaadf..b90f51903 100644 --- a/src/Nazara/Renderer/RenderWindow.cpp +++ b/src/Nazara/Renderer/RenderWindow.cpp @@ -10,12 +10,6 @@ namespace Nz { - RenderWindow::~RenderWindow() - { - // Nécessaire si Window::Destroy est appelé par son destructeur - OnWindowDestroy(); - } - void RenderWindow::Display() { if (m_framerateLimit > 0) diff --git a/src/Nazara/Utility/Formats/MD2Loader.cpp b/src/Nazara/Utility/Formats/MD2Loader.cpp index dde203482..04628ba90 100644 --- a/src/Nazara/Utility/Formats/MD2Loader.cpp +++ b/src/Nazara/Utility/Formats/MD2Loader.cpp @@ -81,15 +81,14 @@ namespace Nz return false; } - /// Création du mesh - // Le moteur ne supporte plus les animations image-clé, nous ne pouvons charger qu'en statique - if (!mesh->CreateStatic()) // Ne devrait jamais échouer + // Since the engine no longer supports keyframe animations, let's make a static mesh + if (!mesh->CreateStatic()) { NazaraInternalError("Failed to create mesh"); return false; } - /// Chargement des skins + // Extract skins (texture name) if (header.num_skins > 0) { mesh->SetMaterialCount(header.num_skins); @@ -109,16 +108,15 @@ namespace Nz } } - /// Chargement des submesh - // Actuellement le loader ne charge qu'un submesh IndexBufferRef indexBuffer = IndexBuffer::New(false, header.num_tris*3, parameters.storage, BufferUsage_Static); - /// Lecture des triangles + // Extract triangles data std::vector triangles(header.num_tris); stream.SetCursorPos(header.offset_tris); stream.Read(&triangles[0], header.num_tris*sizeof(MD2_Triangle)); + // And convert them into an index buffer BufferMapper indexMapper(indexBuffer, BufferAccess_DiscardAndWrite); UInt16* index = static_cast(indexMapper.GetPointer()); @@ -135,7 +133,7 @@ namespace Nz SwapBytes(&triangles[i].texCoords[2], sizeof(UInt16)); #endif - // On respécifie le triangle dans l'ordre attendu + // Reverse winding order *index++ = triangles[i].vertices[0]; *index++ = triangles[i].vertices[2]; *index++ = triangles[i].vertices[1]; @@ -143,10 +141,11 @@ namespace Nz indexMapper.Unmap(); + // Optimize if requested (improves cache locality) if (parameters.optimizeIndexBuffers) indexBuffer->Optimize(); - /// Lecture des coordonnées de texture + // Extracting texture coordinates std::vector texCoords(header.num_st); stream.SetCursorPos(header.offset_st); @@ -168,15 +167,15 @@ namespace Nz return false; } - /// Chargement des vertices + // Extracting vertices stream.SetCursorPos(header.offset_frames); - std::unique_ptr vertices(new MD2_Vertex[header.num_vertices]); + std::vector vertices(header.num_vertices); Vector3f scale, translate; stream.Read(scale, sizeof(Vector3f)); stream.Read(translate, sizeof(Vector3f)); - stream.Read(nullptr, 16*sizeof(char)); // Nom de la frame, inutile ici - stream.Read(vertices.get(), header.num_vertices*sizeof(MD2_Vertex)); + stream.Read(nullptr, 16*sizeof(char)); //< Frame name, unused + stream.Read(vertices.data(), header.num_vertices*sizeof(MD2_Vertex)); #ifdef NAZARA_BIG_ENDIAN SwapBytes(&scale.x, sizeof(float)); @@ -196,23 +195,26 @@ namespace Nz BufferMapper vertexMapper(vertexBuffer, BufferAccess_DiscardAndWrite); MeshVertex* vertex = static_cast(vertexMapper.GetPointer()); - /// Chargement des coordonnées de texture - const unsigned int indexFix[3] = {0, 2, 1}; // Pour respécifier les indices dans le bon ordre + // Loading texture coordinates + const unsigned int indexFix[3] = {0, 2, 1}; + Vector2f invSkinSize(1.f / header.skinwidth, 1.f / header.skinheight); for (unsigned int i = 0; i < header.num_tris; ++i) { for (unsigned int j = 0; j < 3; ++j) { - const unsigned int fixedIndex = indexFix[j]; - const MD2_TexCoord& texC = texCoords[triangles[i].texCoords[fixedIndex]]; - float u = static_cast(texC.u) / header.skinwidth; - float v = static_cast(texC.v) / header.skinheight; + const unsigned int fixedIndex = indexFix[j]; //< Reverse winding order - vertex[triangles[i].vertices[fixedIndex]].uv.Set(u, (parameters.flipUVs) ? 1.f - v : v); + const MD2_TexCoord& texC = texCoords[triangles[i].texCoords[fixedIndex]]; + Vector2f uv(texC.u, texC.v); + uv *= invSkinSize; + + vertex[triangles[i].vertices[fixedIndex]].uv.Set(parameters.texCoordOffset + uv * parameters.texCoordScale); } } - /// Chargement des positions - // Pour que le modèle soit correctement aligné, on génère un quaternion que nous appliquerons à chacune des vertices + // Loading vertex position + + // Align the model to our coordinates system Quaternionf rotationQuat = EulerAnglesf(-90.f, 90.f, 0.f); Nz::Matrix4f matrix = Matrix4f::Transform(translate, rotationQuat, scale); matrix *= parameters.matrix; diff --git a/src/Nazara/Utility/Formats/MD5MeshLoader.cpp b/src/Nazara/Utility/Formats/MD5MeshLoader.cpp index 59988405a..bccf17568 100644 --- a/src/Nazara/Utility/Formats/MD5MeshLoader.cpp +++ b/src/Nazara/Utility/Formats/MD5MeshLoader.cpp @@ -184,7 +184,7 @@ namespace Nz } vertices->position = finalPos; - vertices->uv.Set(vertex.uv.x, (parameters.flipUVs) ? 1.f - vertex.uv.y : vertex.uv.y); // Inversion des UV si demandé + vertices->uv.Set(parameters.texCoordOffset + vertex.uv * parameters.texCoordScale); vertices++; } @@ -254,7 +254,7 @@ namespace Nz VertexBufferRef vertexBuffer = VertexBuffer::New(VertexDeclaration::Get(VertexLayout_XYZ_Normal_UV_Tangent), vertexCount, parameters.storage); BufferMapper vertexMapper(vertexBuffer, BufferAccess_WriteOnly); - MeshVertex* vertex = static_cast(vertexMapper.GetPointer()); + MeshVertex* vertices = static_cast(vertexMapper.GetPointer()); for (const MD5MeshParser::Vertex& md5Vertex : md5Mesh.vertices) { // Skinning MD5 (Formule d'Id Tech) @@ -268,9 +268,9 @@ namespace Nz } // On retourne le modèle dans le bon sens - vertex->position = matrix * finalPos; - vertex->uv.Set(md5Vertex.uv.x, (parameters.flipUVs) ? 1.f - md5Vertex.uv.y : md5Vertex.uv.y); // Inversion des UV si demandé - vertex++; + vertices->position = matrix * finalPos; + vertices->uv.Set(parameters.texCoordOffset + md5Vertex.uv * parameters.texCoordScale); + vertices++; } vertexMapper.Unmap(); diff --git a/src/Nazara/Utility/Formats/OBJLoader.cpp b/src/Nazara/Utility/Formats/OBJLoader.cpp index 2a59ba703..d65d3e913 100644 --- a/src/Nazara/Utility/Formats/OBJLoader.cpp +++ b/src/Nazara/Utility/Formats/OBJLoader.cpp @@ -265,8 +265,8 @@ namespace Nz if (vertexIndices.texCoord > 0) { - const Vector3f& uvw = texCoords[vertexIndices.texCoord-1]; - vertex.uv.Set(uvw.x, (parameters.flipUVs) ? 1.f - uvw.y : uvw.y); // Inversion des UVs si demandé + Vector2f uv = Vector2f(texCoords[vertexIndices.texCoord - 1]); + vertex.uv.Set(parameters.texCoordOffset + uv * parameters.texCoordScale); } else hasTexCoords = false; diff --git a/src/Nazara/Utility/SimpleTextDrawer.cpp b/src/Nazara/Utility/SimpleTextDrawer.cpp index 0d06fa0ba..cdf6f8ceb 100644 --- a/src/Nazara/Utility/SimpleTextDrawer.cpp +++ b/src/Nazara/Utility/SimpleTextDrawer.cpp @@ -103,6 +103,24 @@ namespace Nz return m_glyphs.size(); } + const AbstractTextDrawer::Line& SimpleTextDrawer::GetLine(std::size_t index) const + { + NazaraAssert(index < m_lines.size(), "Line index out of range"); + + if (!m_glyphUpdated) + UpdateGlyphs(); + + return m_lines[index]; + } + + std::size_t SimpleTextDrawer::GetLineCount() const + { + if (!m_glyphUpdated) + UpdateGlyphs(); + + return m_lines.size(); + } + UInt32 SimpleTextDrawer::GetStyle() const { return m_style; @@ -218,10 +236,16 @@ namespace Nz m_bounds.MakeZero(); m_colorUpdated = true; m_drawPos.Set(0, m_characterSize); //< Our draw "cursor" + m_lines.clear(); m_glyphs.clear(); m_glyphUpdated = true; m_previousCharacter = 0; m_workingBounds.MakeZero(); //< Compute bounds as float to speedup bounds computation (as casting between floats and integers is costly) + + if (m_font) + m_lines.emplace_back(Line{Rectf(0.f, 0.f, 0.f, m_font->GetSizeInfo(m_characterSize).lineHeight), 0}); + else + m_lines.emplace_back(Line{Rectf::Zero(), 0}); } void SimpleTextDrawer::ConnectFontSlots() @@ -264,19 +288,16 @@ namespace Nz m_previousCharacter = character; bool whitespace = true; + int advance = 0; switch (character) { case ' ': - m_drawPos.x += sizeInfo.spaceAdvance; - break; - case '\n': - m_drawPos.x = 0; - m_drawPos.y += sizeInfo.lineHeight; + advance = sizeInfo.spaceAdvance; break; case '\t': - m_drawPos.x += sizeInfo.spaceAdvance * 4; + advance = sizeInfo.spaceAdvance * 4; break; default: @@ -284,61 +305,93 @@ namespace Nz break; } - if (whitespace) - continue; // White spaces are blanks and invisible, move the draw position and skip the rest - - const Font::Glyph& fontGlyph = m_font->GetGlyph(m_characterSize, m_style, character); - if (!fontGlyph.valid) - continue; // Glyph failed to load, just skip it (can't do much) - Glyph glyph; - glyph.atlas = m_font->GetAtlas()->GetLayer(fontGlyph.layerIndex); - glyph.atlasRect = fontGlyph.atlasRect; - glyph.color = m_color; - glyph.flipped = fontGlyph.flipped; - - int advance = fontGlyph.advance; - - Rectf bounds(fontGlyph.aabb); - bounds.x += m_drawPos.x; - bounds.y += m_drawPos.y; - - if (fontGlyph.requireFauxBold) + if (!whitespace) { - // Let's simulate bold by enlarging the glyph (not a neat idea, but should work) - Vector2f center = bounds.GetCenter(); + const Font::Glyph& fontGlyph = m_font->GetGlyph(m_characterSize, m_style, character); + if (!fontGlyph.valid) + continue; // Glyph failed to load, just skip it (can't do much) - // Enlarge by 10% - bounds.width *= 1.1f; - bounds.height *= 1.1f; + advance = fontGlyph.advance; - // Replace it at the correct height - Vector2f offset(bounds.GetCenter() - center); - bounds.y -= offset.y; + glyph.atlas = m_font->GetAtlas()->GetLayer(fontGlyph.layerIndex); + glyph.atlasRect = fontGlyph.atlasRect; + glyph.color = m_color; + glyph.flipped = fontGlyph.flipped; - // Adjust advance (+10%) - advance += advance / 10; + if (fontGlyph.requireFauxBold) + { + // Let's simulate bold by enlarging the glyph (not a neat idea, but should work) + Vector2f center = glyph.bounds.GetCenter(); + + // Enlarge by 10% + glyph.bounds.width *= 1.1f; + glyph.bounds.height *= 1.1f; + + // Replace it at the correct height + Vector2f offset(glyph.bounds.GetCenter() - center); + glyph.bounds.y -= offset.y; + + // Adjust advance (+10%) + advance += advance / 10; + } + + glyph.bounds.Set(fontGlyph.aabb); + glyph.bounds.x += m_drawPos.x; + glyph.bounds.y += m_drawPos.y; + + // We "lean" the glyph to simulate italics style + float italic = (fontGlyph.requireFauxItalic) ? 0.208f : 0.f; + float italicTop = italic * glyph.bounds.y; + float italicBottom = italic * glyph.bounds.GetMaximum().y; + + glyph.corners[0].Set(glyph.bounds.x - italicTop, glyph.bounds.y); + glyph.corners[1].Set(glyph.bounds.x + glyph.bounds.width - italicTop, glyph.bounds.y); + glyph.corners[2].Set(glyph.bounds.x - italicBottom, glyph.bounds.y + glyph.bounds.height); + glyph.corners[3].Set(glyph.bounds.x + glyph.bounds.width - italicBottom, glyph.bounds.y + glyph.bounds.height); + } + else + { + glyph.atlas = nullptr; + + glyph.bounds.Set(m_drawPos.x, m_drawPos.y, float(advance), 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': + { + if (!m_glyphs.empty()) + { + Glyph& glyph = m_glyphs.back(); + m_lines.back().bounds.ExtendTo(glyph.bounds); + } + + advance = 0; + m_drawPos.x = 0; + m_drawPos.y += sizeInfo.lineHeight; + + m_lines.emplace_back(Line{Rectf(0.f, sizeInfo.lineHeight * m_lines.size(), 0.f, sizeInfo.lineHeight), m_glyphs.size() + 1}); + break; + } + } } - // We "lean" the glyph to simulate italics style - float italic = (fontGlyph.requireFauxItalic) ? 0.208f : 0.f; - float italicTop = italic * bounds.y; - float italicBottom = italic * bounds.GetMaximum().y; - - glyph.corners[0].Set(bounds.x - italicTop, bounds.y); - glyph.corners[1].Set(bounds.x + bounds.width - italicTop, bounds.y); - glyph.corners[2].Set(bounds.x - italicBottom, bounds.y + bounds.height); - glyph.corners[3].Set(bounds.x + bounds.width - italicBottom, bounds.y + bounds.height); + m_lines.back().bounds.ExtendTo(glyph.bounds); if (!m_workingBounds.IsValid()) - m_workingBounds.Set(glyph.corners[0]); - - for (unsigned int i = 0; i < 4; ++i) - m_workingBounds.ExtendTo(glyph.corners[i]); + m_workingBounds.Set(glyph.bounds); + else + m_workingBounds.ExtendTo(glyph.bounds); m_drawPos.x += advance; m_glyphs.push_back(glyph); } + m_lines.back().bounds.ExtendTo(m_glyphs.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))); } diff --git a/src/Nazara/Utility/Win32/WindowImpl.cpp b/src/Nazara/Utility/Win32/WindowImpl.cpp index 558a44ddb..e32caf95f 100644 --- a/src/Nazara/Utility/Win32/WindowImpl.cpp +++ b/src/Nazara/Utility/Win32/WindowImpl.cpp @@ -81,7 +81,7 @@ namespace Nz { } - bool WindowImpl::Create(const VideoMode& mode, const String& title, UInt32 style) + bool WindowImpl::Create(const VideoMode& mode, const String& title, WindowStyleFlags style) { bool async = (style & WindowStyle_Threaded) != 0; bool fullscreen = (style & WindowStyle_Fullscreen) != 0; @@ -259,7 +259,7 @@ namespace Nz return m_size; } - UInt32 WindowImpl::GetStyle() const + WindowStyleFlags WindowImpl::GetStyle() const { return m_style; } diff --git a/src/Nazara/Utility/Win32/WindowImpl.hpp b/src/Nazara/Utility/Win32/WindowImpl.hpp index bb718738a..ae08e42ad 100644 --- a/src/Nazara/Utility/Win32/WindowImpl.hpp +++ b/src/Nazara/Utility/Win32/WindowImpl.hpp @@ -37,7 +37,7 @@ namespace Nz WindowImpl(WindowImpl&&) = delete; ///TODO? ~WindowImpl() = default; - bool Create(const VideoMode& mode, const String& title, UInt32 style); + bool Create(const VideoMode& mode, const String& title, WindowStyleFlags style); bool Create(WindowHandle handle); void Destroy(); @@ -49,7 +49,7 @@ namespace Nz unsigned int GetHeight() const; Vector2i GetPosition() const; Vector2ui GetSize() const; - UInt32 GetStyle() const; + WindowStyleFlags GetStyle() const; String GetTitle() const; unsigned int GetWidth() const; @@ -93,7 +93,7 @@ namespace Nz HCURSOR m_cursor; HWND m_handle; LONG_PTR m_callback; - UInt32 m_style; + WindowStyleFlags m_style; Vector2i m_maxSize; Vector2i m_minSize; Vector2i m_mousePos; diff --git a/src/Nazara/Utility/Window.cpp b/src/Nazara/Utility/Window.cpp index 803badb85..73c91168a 100644 --- a/src/Nazara/Utility/Window.cpp +++ b/src/Nazara/Utility/Window.cpp @@ -34,7 +34,7 @@ namespace Nz Destroy(); } - bool Window::Create(VideoMode mode, const String& title, UInt32 style) + bool Window::Create(VideoMode mode, const String& title, WindowStyleFlags style) { // Si la fenêtre est déjà ouverte, nous conservons sa position bool opened = IsOpen(); @@ -228,7 +228,7 @@ namespace Nz return m_impl->GetSize(); } - UInt32 Window::GetStyle() const + WindowStyleFlags Window::GetStyle() const { #if NAZARA_UTILITY_SAFE if (!m_impl) diff --git a/src/Nazara/Utility/X11/WindowImpl.cpp b/src/Nazara/Utility/X11/WindowImpl.cpp index 297583a0f..700b8c6ee 100644 --- a/src/Nazara/Utility/X11/WindowImpl.cpp +++ b/src/Nazara/Utility/X11/WindowImpl.cpp @@ -113,7 +113,7 @@ namespace Nz UpdateEventQueue(nullptr); } - bool WindowImpl::Create(const VideoMode& mode, const String& title, UInt32 style) + bool WindowImpl::Create(const VideoMode& mode, const String& title, WindowStyleFlags style) { bool fullscreen = (style & Nz::WindowStyle_Fullscreen) != 0; m_eventListener = true; @@ -336,7 +336,7 @@ namespace Nz return Vector2ui(m_size_hints.width, m_size_hints.height); } - UInt32 WindowImpl::GetStyle() const + WindowStyleFlags WindowImpl::GetStyle() const { return m_style; } diff --git a/src/Nazara/Utility/X11/WindowImpl.hpp b/src/Nazara/Utility/X11/WindowImpl.hpp index 70a699421..414140179 100644 --- a/src/Nazara/Utility/X11/WindowImpl.hpp +++ b/src/Nazara/Utility/X11/WindowImpl.hpp @@ -35,7 +35,7 @@ namespace Nz WindowImpl(WindowImpl&&) = delete; ///TODO? ~WindowImpl(); - bool Create(const VideoMode& mode, const String& title, UInt32 style); + bool Create(const VideoMode& mode, const String& title, WindowStyleFlags style); bool Create(WindowHandle handle); void Destroy(); @@ -47,7 +47,7 @@ namespace Nz unsigned int GetHeight() const; Vector2i GetPosition() const; Vector2ui GetSize() const; - UInt32 GetStyle() const; + WindowStyleFlags GetStyle() const; String GetTitle() const; unsigned int GetWidth() const; @@ -108,7 +108,7 @@ namespace Nz xcb_randr_get_screen_info_reply_t m_oldVideoMode; xcb_size_hints_t m_size_hints; Thread m_thread; - UInt32 m_style; + WindowStyleFlags m_style; Window* m_parent; bool m_eventListener; bool m_ownsWindow; diff --git a/tests/Engine/Network/TCP.cpp b/tests/Engine/Network/TCP.cpp index c088d8b2f..2c34e0b0b 100644 --- a/tests/Engine/Network/TCP.cpp +++ b/tests/Engine/Network/TCP.cpp @@ -14,6 +14,7 @@ SCENARIO("TCP", "[NETWORK][TCP]") std::uniform_int_distribution dis(1025, 65535); Nz::UInt16 port = dis(rd); + Nz::TcpServer server; server.EnableBlocking(false);