Merge branch 'master' into console-widget

This commit is contained in:
Jérôme Leclercq
2018-04-12 12:47:17 +02:00
1058 changed files with 145127 additions and 7192 deletions

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Application.hpp>
#include <Nazara/Core/Log.hpp>
@@ -12,6 +12,7 @@
#include <NDK/Components/NodeComponent.hpp>
#include <NDK/Systems/RenderSystem.hpp>
#include <NDK/LuaAPI.hpp>
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
#include <Nazara/Utility/SimpleTextDrawer.hpp>
#endif
@@ -106,8 +107,7 @@ namespace Ndk
if (m_shouldQuit)
return false;
m_updateTime = m_updateClock.GetSeconds();
m_updateClock.Restart();
m_updateTime = m_updateClock.Restart() / 1'000'000.f;
for (World& world : m_worlds)
world.Update(m_updateTime);
@@ -147,7 +147,10 @@ namespace Ndk
Nz::Vector2ui windowDimensions;
if (info.window->IsValid())
windowDimensions.Set(info.window->GetWidth(), info.window->GetHeight());
{
windowDimensions = info.window->GetSize();
windowDimensions.y /= 4;
}
else
windowDimensions.MakeZero();
@@ -163,6 +166,7 @@ namespace Ndk
consoleRef.AddLine(str);
});
overlay->lua.LoadLibraries();
LuaAPI::RegisterClasses(overlay->lua);
// Override "print" function to add a line in the console
@@ -213,7 +217,8 @@ namespace Ndk
overlay->resizedSlot.Connect(info.renderTarget->OnRenderTargetSizeChange, [&consoleRef] (const Nz::RenderTarget* renderTarget)
{
consoleRef.SetSize({float(renderTarget->GetWidth()), renderTarget->GetHeight() / 4.f});
Nz::Vector2ui size = renderTarget->GetSize();
consoleRef.SetSize({float(size.x), size.y / 4.f});
});
info.console = std::move(overlay);

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/BaseComponent.hpp>
@@ -63,6 +63,26 @@ namespace Ndk
{
}
/*!
* \brief Operation to perform when the entity is disabled
*
* \remark Disabling an entity will remove it from systems it belongs to, but sometimes the entity will need to do
* additional work in order to be properly disabled (i.e.: disabling physics simulation & collisions)
*/
void BaseComponent::OnEntityDisabled()
{
}
/*!
* \brief Operation to perform when the entity is disabled
*
* \remark Enabling an entity will add it back to systems it belongs to, but sometimes the entity will need to do
* additional work in order to be properly re-enabled (i.e.: enabling physics simulation & collisions)
*/
void BaseComponent::OnEntityEnabled()
{
}
std::vector<BaseComponent::ComponentEntry> BaseComponent::s_entries;
std::unordered_map<ComponentId, ComponentIndex> BaseComponent::s_idToIndex;
}

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/BaseSystem.hpp>
#include <NDK/World.hpp>

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/BaseWidget.hpp>
#include <NDK/Canvas.hpp>
@@ -46,6 +46,15 @@ namespace Ndk
UnregisterFromCanvas();
}
/*!
* \brief Clears keyboard focus if and only if this widget owns it.
*/
void BaseWidget::ClearFocus()
{
if (IsRegisteredToCanvas())
m_canvas->ClearKeyboardOwner(m_canvasIndex);
}
/*!
* \brief Destroy the widget, deleting it in the process.
*
@@ -70,9 +79,9 @@ namespace Ndk
{
m_backgroundSprite = Nz::Sprite::New();
m_backgroundSprite->SetColor(m_backgroundColor);
m_backgroundSprite->SetMaterial(Nz::Material::New((m_backgroundColor.IsOpaque()) ? "Basic2D" : "Translucent2D"));
m_backgroundSprite->SetMaterial(Nz::Material::New((m_backgroundColor.IsOpaque()) ? "Basic2D" : "Translucent2D")); //< TODO: Use a shared material instead of creating one everytime
m_backgroundEntity = CreateEntity();
m_backgroundEntity = CreateEntity(false);
m_backgroundEntity->AddComponent<GraphicsComponent>().Attach(m_backgroundSprite, -1);
m_backgroundEntity->AddComponent<NodeComponent>().SetParent(this);
@@ -85,9 +94,16 @@ namespace Ndk
}
}
void BaseWidget::GrabKeyboard()
/*!
* \brief Checks if this widget has keyboard focus
* \return true if widget has keyboard focus, false otherwhise
*/
bool BaseWidget::HasFocus() const
{
m_canvas->SetKeyboardOwner(this);
if (!IsRegisteredToCanvas())
return false;
return m_canvas->IsKeyboardOwner(m_canvasIndex);
}
void BaseWidget::SetBackgroundColor(const Nz::Color& color)
@@ -109,6 +125,12 @@ namespace Ndk
m_canvas->NotifyWidgetCursorUpdate(m_canvasIndex);
}
void BaseWidget::SetFocus()
{
if (IsRegisteredToCanvas())
m_canvas->SetKeyboardOwner(m_canvasIndex);
}
void BaseWidget::SetSize(const Nz::Vector2f& size)
{
SetContentSize({std::max(size.x - m_padding.left - m_padding.right, 0.f), std::max(size.y - m_padding.top - m_padding.bottom, 0.f)});
@@ -125,26 +147,30 @@ namespace Ndk
else
UnregisterFromCanvas();
for (const EntityHandle& entity : m_entities)
entity->Enable(show);
for (WidgetEntity& entity : m_entities)
entity.handle->Enable(show);
for (const auto& widgetPtr : m_children)
widgetPtr->Show(show);
}
}
EntityHandle BaseWidget::CreateEntity()
const Ndk::EntityHandle& BaseWidget::CreateEntity(bool isContentEntity)
{
EntityHandle newEntity = m_world->CreateEntity();
const EntityHandle& newEntity = m_world->CreateEntity();
newEntity->Enable(m_visible);
m_entities.emplace_back(newEntity);
m_entities.emplace_back();
WidgetEntity& widgetEntity = m_entities.back();
widgetEntity.handle = newEntity;
widgetEntity.isContent = isContentEntity;
return newEntity;
}
void BaseWidget::DestroyEntity(Entity* entity)
{
auto it = std::find(m_entities.begin(), m_entities.end(), entity);
auto it = std::find_if(m_entities.begin(), m_entities.end(), [&](const WidgetEntity& widgetEntity) { return widgetEntity.handle == entity; });
NazaraAssert(it != m_entities.end(), "Entity does not belong to this widget");
m_entities.erase(it);
@@ -152,23 +178,35 @@ namespace Ndk
void BaseWidget::Layout()
{
if (IsRegisteredToCanvas())
m_canvas->NotifyWidgetBoxUpdate(m_canvasIndex);
if (m_backgroundEntity)
m_backgroundSprite->SetSize(m_contentSize.x + m_padding.left + m_padding.right, m_contentSize.y + m_padding.top + m_padding.bottom);
UpdatePositionAndSize();
}
void BaseWidget::InvalidateNode()
{
Node::InvalidateNode();
if (IsRegisteredToCanvas())
m_canvas->NotifyWidgetBoxUpdate(m_canvasIndex);
UpdatePositionAndSize();
}
void BaseWidget::OnKeyPressed(const Nz::WindowEvent::KeyEvent& /*key*/)
bool BaseWidget::IsFocusable() const
{
return false;
}
void BaseWidget::OnFocusLost()
{
}
void BaseWidget::OnFocusReceived()
{
}
bool BaseWidget::OnKeyPressed(const Nz::WindowEvent::KeyEvent& key)
{
return false;
}
void BaseWidget::OnKeyReleased(const Nz::WindowEvent::KeyEvent& /*key*/)
@@ -235,4 +273,25 @@ namespace Ndk
m_canvasIndex = InvalidCanvasIndex;
}
}
void BaseWidget::UpdatePositionAndSize()
{
if (IsRegisteredToCanvas())
m_canvas->NotifyWidgetBoxUpdate(m_canvasIndex);
Nz::Vector2f widgetPos = Nz::Vector2f(GetPosition());
Nz::Vector2f widgetSize = GetSize();
Nz::Vector2f contentPos = widgetPos + GetContentOrigin();
Nz::Vector2f contentSize = GetContentSize();
Nz::Recti fullBounds(Nz::Rectf(widgetPos.x, widgetPos.y, widgetSize.x, widgetSize.y));
Nz::Recti contentBounds(Nz::Rectf(contentPos.x, contentPos.y, contentSize.x, contentSize.y));
for (WidgetEntity& widgetEntity : m_entities)
{
const Ndk::EntityHandle& entity = widgetEntity.handle;
if (entity->HasComponent<GraphicsComponent>())
entity->GetComponent<GraphicsComponent>().SetScissorRect((widgetEntity.isContent) ? contentBounds : fullBounds);
}
}
}

View File

@@ -1,11 +1,8 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Canvas.hpp>
#include <NDK/Components/GraphicsComponent.hpp>
#include <NDK/Components/NodeComponent.hpp>
#include <NDK/World.hpp>
#include <limits>
namespace Ndk
@@ -16,12 +13,12 @@ namespace Ndk
std::size_t Canvas::RegisterWidget(BaseWidget* widget)
{
WidgetBox box;
WidgetEntry box;
box.cursor = widget->GetCursor();
box.widget = widget;
std::size_t index = m_widgetBoxes.size();
m_widgetBoxes.emplace_back(box);
std::size_t index = m_widgetEntries.size();
m_widgetEntries.emplace_back(box);
NotifyWidgetBoxUpdate(index);
return index;
@@ -29,91 +26,106 @@ namespace Ndk
void Canvas::UnregisterWidget(std::size_t index)
{
WidgetBox& entry = m_widgetBoxes[index];
WidgetEntry& entry = m_widgetEntries[index];
if (m_hoveredWidget == &entry)
m_hoveredWidget = nullptr;
if (m_hoveredWidget == index)
m_hoveredWidget = InvalidCanvasIndex;
if (m_keyboardOwner == entry.widget)
m_keyboardOwner = nullptr;
if (m_keyboardOwner == index)
m_keyboardOwner = InvalidCanvasIndex;
if (m_widgetBoxes.size() > 1U)
if (m_widgetEntries.size() > 1U)
{
WidgetBox& lastEntry = m_widgetBoxes.back();
WidgetEntry& lastEntry = m_widgetEntries.back();
std::size_t lastEntryIndex = m_widgetEntries.size() - 1;
entry = std::move(lastEntry);
entry.widget->UpdateCanvasIndex(index);
if (m_hoveredWidget == lastEntryIndex)
m_hoveredWidget = index;
if (m_keyboardOwner == lastEntryIndex)
m_keyboardOwner = index;
}
m_widgetBoxes.pop_back();
m_widgetEntries.pop_back();
}
void Canvas::OnEventMouseButtonPressed(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseButtonEvent& event)
{
if (m_hoveredWidget)
if (m_hoveredWidget != InvalidCanvasIndex)
{
int x = static_cast<int>(std::round(event.x - m_hoveredWidget->box.x));
int y = static_cast<int>(std::round(event.y - m_hoveredWidget->box.y));
WidgetEntry& hoveredWidget = m_widgetEntries[m_hoveredWidget];
m_hoveredWidget->widget->OnMouseButtonPress(x, y, event.button);
int x = static_cast<int>(std::round(event.x - hoveredWidget.box.x));
int y = static_cast<int>(std::round(event.y - hoveredWidget.box.y));
hoveredWidget.widget->OnMouseButtonPress(x, y, event.button);
}
}
void Canvas::OnEventMouseButtonRelease(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseButtonEvent & event)
{
if (m_hoveredWidget)
if (m_hoveredWidget != InvalidCanvasIndex)
{
int x = static_cast<int>(std::round(event.x - m_hoveredWidget->box.x));
int y = static_cast<int>(std::round(event.y - m_hoveredWidget->box.y));
WidgetEntry& hoveredWidget = m_widgetEntries[m_hoveredWidget];
m_hoveredWidget->widget->OnMouseButtonRelease(x, y, event.button);
int x = static_cast<int>(std::round(event.x - hoveredWidget.box.x));
int y = static_cast<int>(std::round(event.y - hoveredWidget.box.y));
hoveredWidget.widget->OnMouseButtonRelease(x, y, event.button);
}
}
void Canvas::OnEventMouseMoved(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseMoveEvent& event)
{
const WidgetBox* bestEntry = nullptr;
std::size_t bestEntry = InvalidCanvasIndex;
float bestEntryArea = std::numeric_limits<float>::infinity();
Nz::Vector3f mousePos(float(event.x), float(event.y), 0.f);
for (const WidgetBox& entry : m_widgetBoxes)
for (std::size_t i = 0; i < m_widgetEntries.size(); ++i)
{
const Nz::Boxf& box = entry.box;
const Nz::Boxf& box = m_widgetEntries[i].box;
if (box.Contains(mousePos))
{
float area = box.width * box.height;
if (area < bestEntryArea)
{
bestEntry = &entry;
bestEntry = i;
bestEntryArea = area;
}
}
}
if (bestEntry)
if (bestEntry != InvalidCanvasIndex)
{
if (m_hoveredWidget != bestEntry)
{
if (m_hoveredWidget)
m_hoveredWidget->widget->OnMouseExit();
if (m_hoveredWidget != InvalidCanvasIndex)
{
WidgetEntry& previouslyHovered = m_widgetEntries[m_hoveredWidget];
previouslyHovered.widget->OnMouseExit();
}
m_hoveredWidget = bestEntry;
m_hoveredWidget->widget->OnMouseEnter();
m_widgetEntries[m_hoveredWidget].widget->OnMouseEnter();
if (m_cursorController)
m_cursorController->UpdateCursor(Nz::Cursor::Get(m_hoveredWidget->cursor));
m_cursorController->UpdateCursor(Nz::Cursor::Get(m_widgetEntries[m_hoveredWidget].cursor));
}
int x = static_cast<int>(std::round(event.x - m_hoveredWidget->box.x));
int y = static_cast<int>(std::round(event.y - m_hoveredWidget->box.y));
WidgetEntry& hoveredWidget = m_widgetEntries[m_hoveredWidget];
bestEntry->widget->OnMouseMoved(x, y, event.deltaX, event.deltaY);
int x = static_cast<int>(std::round(event.x - hoveredWidget.box.x));
int y = static_cast<int>(std::round(event.y - hoveredWidget.box.y));
hoveredWidget.widget->OnMouseMoved(x, y, event.deltaX, event.deltaY);
}
else if (m_hoveredWidget)
else if (m_hoveredWidget != InvalidCanvasIndex)
{
m_hoveredWidget->widget->OnMouseExit();
m_hoveredWidget = nullptr;
m_widgetEntries[m_hoveredWidget].widget->OnMouseExit();
m_hoveredWidget = InvalidCanvasIndex;
if (m_cursorController)
m_cursorController->UpdateCursor(Nz::Cursor::Get(Nz::SystemCursor_Default));
@@ -122,28 +134,78 @@ namespace Ndk
void Canvas::OnEventMouseLeft(const Nz::EventHandler* /*eventHandler*/)
{
if (m_hoveredWidget)
if (m_hoveredWidget != InvalidCanvasIndex)
{
m_hoveredWidget->widget->OnMouseExit();
m_hoveredWidget = nullptr;
m_widgetEntries[m_hoveredWidget].widget->OnMouseExit();
m_hoveredWidget = InvalidCanvasIndex;
}
}
void Canvas::OnEventKeyPressed(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& event)
{
if (m_keyboardOwner)
m_keyboardOwner->OnKeyPressed(event);
if (m_keyboardOwner != InvalidCanvasIndex)
{
if (m_widgetEntries[m_keyboardOwner].widget->OnKeyPressed(event))
return;
if (event.code == Nz::Keyboard::Tab)
{
if (!event.shift)
{
// Forward
for (std::size_t i = m_keyboardOwner + 1; i < m_widgetEntries.size(); ++i)
{
if (m_widgetEntries[i].widget->IsFocusable())
{
SetKeyboardOwner(i);
return;
}
}
for (std::size_t i = 0; i < m_keyboardOwner; ++i)
{
if (m_widgetEntries[i].widget->IsFocusable())
{
SetKeyboardOwner(i);
return;
}
}
}
else
{
// Backward
for (decltype(m_widgetEntries)::reverse_iterator rit{ m_widgetEntries.begin() + m_keyboardOwner }; rit != m_widgetEntries.rend(); ++rit)
{
if (rit->widget->IsFocusable())
{
SetKeyboardOwner(std::distance(m_widgetEntries.begin(), rit.base()) - 1);
return;
}
}
decltype(m_widgetEntries)::reverse_iterator rend { m_widgetEntries.begin() + m_keyboardOwner };
for (auto rit = m_widgetEntries.rbegin(); rit != rend; ++rit)
{
if (rit->widget->IsFocusable())
{
SetKeyboardOwner(std::distance(m_widgetEntries.begin(), rit.base()) - 1);
return;
}
}
}
}
}
}
void Canvas::OnEventKeyReleased(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& event)
{
if (m_keyboardOwner)
m_keyboardOwner->OnKeyReleased(event);
if (m_keyboardOwner != InvalidCanvasIndex)
m_widgetEntries[m_keyboardOwner].widget->OnKeyReleased(event);
}
void Canvas::OnEventTextEntered(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::TextEvent& event)
{
if (m_keyboardOwner)
m_keyboardOwner->OnTextEntered(event.character, event.repeated);
if (m_keyboardOwner != InvalidCanvasIndex)
m_widgetEntries[m_keyboardOwner].widget->OnTextEntered(event.character, event.repeated);
}
}

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Components/CameraComponent.hpp>
#include <Nazara/Renderer/Renderer.hpp>
@@ -334,15 +334,15 @@ namespace Ndk
{
NazaraAssert(m_target, "CameraComponent has no target");
unsigned int targetWidth = m_target->GetWidth();
unsigned int targetHeight = std::max(m_target->GetHeight(), 1U); // Let's make sure we won't divide by zero
Nz::Vector2ui targetSize = m_target->GetSize();
targetSize.y = std::max(targetSize.y, 1U); // Let's make sure we won't divide by zero
// Our target region is expressed as % of the viewport dimensions, let's compute it in pixels
Nz::Rectf fViewport(m_targetRegion);
fViewport.x *= targetWidth;
fViewport.y *= targetHeight;
fViewport.width *= targetWidth;
fViewport.height *= targetHeight;
fViewport.x *= targetSize.x;
fViewport.y *= targetSize.y;
fViewport.width *= targetSize.x;
fViewport.height *= targetSize.y;
// Compute the new aspect ratio, if it's different we need to invalidate the projection matrix
float aspectRatio = fViewport.width/fViewport.height;

View File

@@ -1,10 +1,9 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Components/CollisionComponent2D.hpp>
#include <Nazara/Physics2D/RigidBody2D.hpp>
#include <NDK/Algorithm.hpp>
#include <NDK/World.hpp>
#include <NDK/Components/NodeComponent.hpp>
#include <NDK/Components/PhysicsComponent2D.hpp>
@@ -34,7 +33,7 @@ namespace Ndk
{
// We update the geometry of the PhysiscsObject linked to the PhysicsComponent2D
PhysicsComponent2D& physComponent = m_entity->GetComponent<PhysicsComponent2D>();
physComponent.GetRigidBody().SetGeom(m_geom);
physComponent.GetRigidBody()->SetGeom(m_geom);
}
else
{
@@ -59,7 +58,8 @@ namespace Ndk
NazaraAssert(entityWorld->HasSystem<PhysicsSystem2D>(), "World must have a physics system");
Nz::PhysWorld2D& physWorld = entityWorld->GetSystem<PhysicsSystem2D>().GetWorld();
m_staticBody.reset(new Nz::RigidBody2D(&physWorld, 0.f, m_geom));
m_staticBody = std::make_unique<Nz::RigidBody2D>(&physWorld, 0.f, m_geom);
m_staticBody->SetUserdata(reinterpret_cast<void*>(static_cast<std::ptrdiff_t>(m_entity->GetId())));
Nz::Matrix4f matrix;
if (m_entity->HasComponent<NodeComponent>())

View File

@@ -1,10 +1,9 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Components/CollisionComponent3D.hpp>
#include <Nazara/Physics3D/RigidBody3D.hpp>
#include <NDK/Algorithm.hpp>
#include <NDK/World.hpp>
#include <NDK/Components/PhysicsComponent3D.hpp>
#include <NDK/Systems/PhysicsSystem3D.hpp>
@@ -33,7 +32,7 @@ namespace Ndk
{
// We update the geometry of the PhysiscsObject linked to the PhysicsComponent3D
PhysicsComponent3D& physComponent = m_entity->GetComponent<PhysicsComponent3D>();
physComponent.GetRigidBody().SetGeom(m_geom);
physComponent.GetRigidBody()->SetGeom(m_geom);
}
else
{
@@ -58,8 +57,9 @@ namespace Ndk
NazaraAssert(entityWorld->HasSystem<PhysicsSystem3D>(), "World must have a physics system");
Nz::PhysWorld3D& physWorld = entityWorld->GetSystem<PhysicsSystem3D>().GetWorld();
m_staticBody.reset(new Nz::RigidBody3D(&physWorld, m_geom));
m_staticBody = std::make_unique<Nz::RigidBody3D>(&physWorld, m_geom);
m_staticBody->EnableAutoSleep(false);
m_staticBody->SetUserdata(reinterpret_cast<void*>(static_cast<std::ptrdiff_t>(m_entity->GetId())));
}
/*!
@@ -105,5 +105,17 @@ namespace Ndk
m_staticBody.reset();
}
void CollisionComponent3D::OnEntityDisabled()
{
if (m_staticBody)
m_staticBody->EnableSimulation(false);
}
void CollisionComponent3D::OnEntityEnabled()
{
if (m_staticBody)
m_staticBody->EnableSimulation(true);
}
ComponentIndex CollisionComponent3D::componentIndex;
}

View File

@@ -0,0 +1,6 @@
#include <NDK/Components/ConstraintComponent2D.hpp>
namespace Ndk
{
ComponentIndex ConstraintComponent2D::componentIndex;
}

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Components/GraphicsComponent.hpp>
#include <NDK/World.hpp>
@@ -35,21 +35,10 @@ namespace Ndk
object.dataUpdated = true;
}
object.renderable->AddToRenderQueue(renderQueue, object.data);
object.renderable->AddToRenderQueue(renderQueue, object.data, m_scissorRect);
}
}
/*!
* \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
*
@@ -60,26 +49,29 @@ namespace Ndk
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);
Renderable& entry = m_renderables.back();
entry.data.localMatrix = localMatrix;
entry.data.renderOrder = renderOrder;
entry.renderable = std::move(renderable);
ConnectInstancedRenderableSignals(entry);
std::size_t materialCount = entry.renderable->GetMaterialCount();
for (std::size_t i = 0; i < materialCount; ++i)
RegisterMaterial(entry.renderable->GetMaterial(i));
InvalidateBoundingVolume();
}
/*!
* \brief Invalidates the data for renderable
*
* \param renderable Renderable to invalidate
* \param flags Flags for the instance
* \param index Index of the renderable to invalidate
*
* \remark Produces a NazaraAssert if index is out of bound
*/
void GraphicsComponent::ConnectInstancedRenderableSignals(Renderable& entry)
{
entry.renderableBoundingVolumeInvalidationSlot.Connect(entry.renderable->OnInstancedRenderableInvalidateBoundingVolume, [this](const Nz::InstancedRenderable*) { InvalidateBoundingVolume(); });
entry.renderableDataInvalidationSlot.Connect(entry.renderable->OnInstancedRenderableInvalidateData, std::bind(&GraphicsComponent::InvalidateRenderableData, this, std::placeholders::_1, std::placeholders::_2, m_renderables.size() - 1));
entry.renderableMaterialInvalidationSlot.Connect(entry.renderable->OnInstancedRenderableInvalidateMaterial, this, &GraphicsComponent::InvalidateRenderableMaterial);
entry.renderableReleaseSlot.Connect(entry.renderable->OnInstancedRenderableRelease, this, &GraphicsComponent::Detach);
entry.renderableResetMaterialsSlot.Connect(entry.renderable->OnInstancedRenderableResetMaterials, this, &GraphicsComponent::OnInstancedRenderableResetMaterials);
entry.renderableSkinChangeSlot.Connect(entry.renderable->OnInstancedRenderableSkinChange, this, &GraphicsComponent::OnInstancedRenderableSkinChange);
}
void GraphicsComponent::InvalidateRenderableData(const Nz::InstancedRenderable* renderable , Nz::UInt32 flags, std::size_t index)
{
@@ -94,6 +86,59 @@ namespace Ndk
entry.listEntry.ForceInvalidation();
}
void GraphicsComponent::InvalidateRenderableMaterial(const Nz::InstancedRenderable* renderable, std::size_t skinIndex, std::size_t matIndex, const Nz::MaterialRef& newMat)
{
// Don't listen to dormant materials
if (renderable->GetSkin() != skinIndex)
return;
RegisterMaterial(newMat);
const Nz::MaterialRef& oldMat = renderable->GetMaterial(skinIndex, matIndex);
UnregisterMaterial(oldMat);
}
void Ndk::GraphicsComponent::InvalidateReflectionMap()
{
m_entity->Invalidate();
if (m_reflectiveMaterialCount > 0)
{
if (!m_reflectionMap)
{
m_reflectionMap = Nz::Texture::New();
if (!m_reflectionMap->Create(Nz::ImageType_Cubemap, Nz::PixelFormatType_RGB8, m_reflectionMapSize, m_reflectionMapSize))
{
NazaraWarning("Failed to create reflection map, reflections will be disabled for this entity");
return;
}
}
}
else
m_reflectionMap.Reset();
}
void GraphicsComponent::RegisterMaterial(Nz::Material* material, std::size_t count)
{
auto it = m_materialEntries.find(material);
if (it == m_materialEntries.end())
{
MaterialEntry matEntry;
matEntry.reflectionModelChangeSlot.Connect(material->OnMaterialReflectionModeChange, this, &GraphicsComponent::OnMaterialReflectionChange);
matEntry.renderableCounter = count;
if (material->GetReflectionMode() == Nz::ReflectionMode_RealTime)
{
if (m_reflectiveMaterialCount++ == 0)
InvalidateReflectionMap();
}
m_materialEntries.emplace(material, std::move(matEntry));
}
else
it->second.renderableCounter += count;
}
/*!
* \brief Operation to perform when component is attached to an entity
*/
@@ -150,11 +195,39 @@ namespace Ndk
InvalidateTransformMatrix();
}
/*!
* \brief Operation to perform when the node is invalidated
*
* \param node Pointer to the node
*/
void GraphicsComponent::OnInstancedRenderableResetMaterials(const Nz::InstancedRenderable* renderable, std::size_t newMaterialCount)
{
RegisterMaterial(Nz::Material::GetDefault(), newMaterialCount);
std::size_t materialCount = renderable->GetMaterialCount();
for (std::size_t i = 0; i < materialCount; ++i)
UnregisterMaterial(renderable->GetMaterial(i));
}
void GraphicsComponent::OnInstancedRenderableSkinChange(const Nz::InstancedRenderable* renderable, std::size_t newSkinIndex)
{
std::size_t materialCount = renderable->GetMaterialCount();
for (std::size_t i = 0; i < materialCount; ++i)
RegisterMaterial(renderable->GetMaterial(newSkinIndex, i));
for (std::size_t i = 0; i < materialCount; ++i)
UnregisterMaterial(renderable->GetMaterial(i));
}
void GraphicsComponent::OnMaterialReflectionChange(const Nz::Material* material, Nz::ReflectionMode reflectionMode)
{
// Since this signal is only called when the new reflection mode is different from the current one, no need to compare both
if (material->GetReflectionMode() == Nz::ReflectionMode_RealTime)
{
if (--m_reflectiveMaterialCount == 0)
InvalidateReflectionMap();
}
else if (reflectionMode == Nz::ReflectionMode_RealTime)
{
if (m_reflectiveMaterialCount++ == 0)
InvalidateReflectionMap();
}
}
void GraphicsComponent::OnNodeInvalidated(const Nz::Node* node)
{
@@ -168,6 +241,24 @@ namespace Ndk
entry.listEntry.ForceInvalidation(); //< Force invalidation on movement
}
void GraphicsComponent::UnregisterMaterial(Nz::Material* material)
{
auto it = m_materialEntries.find(material);
NazaraAssert(it != m_materialEntries.end(), "Material not registered");
MaterialEntry& matEntry = it->second;
if (--matEntry.renderableCounter == 0)
{
if (material->GetReflectionMode() == Nz::ReflectionMode_RealTime)
{
if (--m_reflectiveMaterialCount == 0)
InvalidateReflectionMap();
}
m_materialEntries.erase(it);
}
}
/*!
* \brief Updates the bounding volume
*/
@@ -191,7 +282,7 @@ namespace Ndk
boundingVolume.Set(Nz::Boxf(newPos.x, newPos.y, newPos.z, newLengths.x, newLengths.y, newLengths.z));
}
m_boundingVolume.ExtendTo(r.renderable->GetBoundingVolume());
m_boundingVolume.ExtendTo(boundingVolume);
}
RenderSystem& renderSystem = m_entity->GetWorld()->GetSystem<RenderSystem>();

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Components/LightComponent.hpp>

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Components/ListenerComponent.hpp>

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Components/NodeComponent.hpp>

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Components/ParticleEmitterComponent.hpp>
#include <Nazara/Graphics/ParticleGroup.hpp>

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Components/ParticleGroupComponent.hpp>

View File

@@ -1,14 +1,14 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Components/PhysicsComponent2D.hpp>
#include <Nazara/Physics2D/RigidBody2D.hpp>
#include <NDK/Algorithm.hpp>
#include <NDK/World.hpp>
#include <NDK/Components/CollisionComponent2D.hpp>
#include <NDK/Components/NodeComponent.hpp>
#include <NDK/Systems/PhysicsSystem3D.hpp>
#include <NDK/Systems/PhysicsSystem2D.hpp>
#include <memory>
namespace Ndk
{
@@ -41,8 +41,9 @@ namespace Ndk
else
matrix.MakeIdentity();
m_object.reset(new Nz::RigidBody2D(&world, 1.f, geom));
m_object = std::make_unique<Nz::RigidBody2D>(&world, 1.f, geom);
m_object->SetPosition(Nz::Vector2f(matrix.GetTranslation()));
m_object->SetUserdata(reinterpret_cast<void*>(static_cast<std::ptrdiff_t>(m_entity->GetId())));
}
/*!

View File

@@ -1,10 +1,9 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Components/PhysicsComponent3D.hpp>
#include <Nazara/Physics3D/RigidBody3D.hpp>
#include <NDK/Algorithm.hpp>
#include <NDK/World.hpp>
#include <NDK/Components/CollisionComponent3D.hpp>
#include <NDK/Components/NodeComponent.hpp>
@@ -41,8 +40,13 @@ namespace Ndk
else
matrix.MakeIdentity();
m_object.reset(new Nz::RigidBody3D(&world, geom, matrix));
m_object->SetMass(1.f);
m_object = std::make_unique<Nz::RigidBody3D>(&world, geom, matrix);
m_object->SetUserdata(reinterpret_cast<void*>(static_cast<std::ptrdiff_t>(m_entity->GetId())));
if (m_pendingStates.valid)
ApplyPhysicsState(*m_object);
else
m_object->SetMass(1.f);
}
/*!
@@ -58,6 +62,7 @@ namespace Ndk
if (IsComponent<CollisionComponent3D>(component))
{
NazaraAssert(m_object, "Invalid object");
m_object->SetGeom(static_cast<CollisionComponent3D&>(component).GetGeom());
}
}
@@ -75,6 +80,7 @@ namespace Ndk
if (IsComponent<CollisionComponent3D>(component))
{
NazaraAssert(m_object, "Invalid object");
m_object->SetGeom(Nz::NullCollider3D::New());
}
}
@@ -85,7 +91,11 @@ namespace Ndk
void PhysicsComponent3D::OnDetached()
{
m_object.reset();
if (m_object)
{
CopyPhysicsState(*m_object);
m_object.reset();
}
}
void PhysicsComponent3D::OnEntityDestruction()
@@ -94,5 +104,19 @@ namespace Ndk
m_object.reset();
}
void PhysicsComponent3D::OnEntityDisabled()
{
NazaraAssert(m_object, "Invalid physics object");
m_object->EnableSimulation(false);
}
void PhysicsComponent3D::OnEntityEnabled()
{
NazaraAssert(m_object, "Invalid physics object");
m_object->EnableSimulation(true);
}
ComponentIndex PhysicsComponent3D::componentIndex;
}

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Components/VelocityComponent.hpp>

View File

@@ -1,10 +1,11 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Console.hpp>
#include <Nazara/Core/Unicode.hpp>
#include <Nazara/Lua/LuaInstance.hpp>
#include <Nazara/Lua/LuaState.hpp>
#include <Nazara/Platform/Event.hpp>
#include <NDK/Components/GraphicsComponent.hpp>
#include <NDK/Components/NodeComponent.hpp>
#include <NDK/Widgets.hpp>

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Entity.hpp>
#include <NDK/BaseComponent.hpp>
@@ -56,7 +56,7 @@ namespace Ndk
Entity::~Entity()
{
if (m_world)
if (m_world && m_valid)
Destroy();
}
@@ -96,6 +96,10 @@ namespace Ndk
m_components[i]->OnComponentAttached(component);
}
// If we are currently disabled, inform the component
if (!m_enabled)
component.OnEntityDisabled();
return component;
}
@@ -106,7 +110,6 @@ namespace Ndk
* \remark The close is enable by default, even if the original is disabled
* \remark Produces a NazaraAssert if the entity is not valid
*/
const EntityHandle& Entity::Clone() const
{
NazaraAssert(IsValid(), "Invalid entity");
@@ -114,10 +117,34 @@ namespace Ndk
return m_world->CloneEntity(m_id);
}
/*!
* \brief Enables the entity
*
* \param enable Should the entity be enabled
*/
void Entity::Enable(bool enable)
{
if (m_enabled != enable)
{
m_enabled = enable;
if (m_enabled)
{
for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
m_components[i]->OnEntityEnabled();
}
else
{
for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
m_components[i]->OnEntityDisabled();
}
Invalidate();
}
}
/*!
* \brief Kills the entity
*/
void Entity::Kill()
{
m_world->KillEntity(this);

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/EntityList.hpp>
#include <NDK/World.hpp>

View File

@@ -32,28 +32,28 @@ namespace Ndk
stream.BindMethod("IsWritable", &Nz::Stream::IsWritable);
stream.BindMethod("SetCursorPos", &Nz::Stream::SetCursorPos);
stream.BindMethod("Read", [] (Nz::LuaState& lua, Nz::Stream& stream, std::size_t /*argumentCount*/) -> int {
stream.BindMethod("Read", [] (Nz::LuaState& lua, Nz::Stream& instance, std::size_t /*argumentCount*/) -> int {
int argIndex = 2;
std::size_t length = lua.Check<std::size_t>(&argIndex);
std::unique_ptr<char[]> buffer(new char[length]);
std::size_t readLength = stream.Read(buffer.get(), length);
std::size_t readLength = instance.Read(buffer.get(), length);
lua.PushString(Nz::String(buffer.get(), readLength));
return 1;
});
stream.BindMethod("Write", [] (Nz::LuaState& lua, Nz::Stream& stream, std::size_t /*argumentCount*/) -> int {
stream.BindMethod("Write", [] (Nz::LuaState& 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 (stream.IsTextModeEnabled())
lua.Push(stream.Write(Nz::String(buffer, bufferSize)));
if (instance.IsTextModeEnabled())
lua.Push(instance.Write(Nz::String(buffer, bufferSize)));
else
lua.Push(stream.Write(buffer, bufferSize));
lua.Push(instance.Write(buffer, bufferSize));
return 1;
});
}
@@ -103,11 +103,11 @@ namespace Ndk
clock.BindMethod("Unpause", &Nz::Clock::Unpause);
// Manual
clock.BindMethod("__tostring", [] (Nz::LuaState& lua, Nz::Clock& clock, std::size_t /*argumentCount*/) -> int {
clock.BindMethod("__tostring", [] (Nz::LuaState& lua, Nz::Clock& instance, std::size_t /*argumentCount*/) -> int {
Nz::StringStream ss("Clock(Elapsed: ");
ss << clock.GetSeconds();
ss << instance.GetSeconds();
ss << "s, Paused: ";
ss << clock.IsPaused();
ss << instance.IsPaused();
ss << ')';
lua.PushString(ss);
@@ -159,9 +159,9 @@ namespace Ndk
directory.BindStaticMethod("SetCurrent", Nz::Directory::SetCurrent);
// Manual
directory.BindMethod("__tostring", [] (Nz::LuaState& lua, Nz::Directory& dir, std::size_t /*argumentCount*/) -> int {
directory.BindMethod("__tostring", [] (Nz::LuaState& lua, Nz::Directory& instance, std::size_t /*argumentCount*/) -> int {
Nz::StringStream ss("Directory(");
ss << dir.GetPath();
ss << instance.GetPath();
ss << ')';
lua.PushString(ss);
@@ -237,7 +237,7 @@ namespace Ndk
file.BindStaticMethod("Rename", &Nz::File::Rename);
// Manual
file.BindMethod("Open", [] (Nz::LuaState& lua, Nz::File& file, std::size_t argumentCount) -> int
file.BindMethod("Open", [] (Nz::LuaState& lua, Nz::File& instance, std::size_t argumentCount) -> int
{
std::size_t argCount = std::min<std::size_t>(argumentCount, 2U);
@@ -246,13 +246,13 @@ namespace Ndk
{
case 0:
case 1:
return lua.Push(file.Open(lua.Check<Nz::UInt32>(&argIndex, Nz::OpenMode_NotOpen)));
return lua.Push(instance.Open(lua.Check<Nz::UInt32>(&argIndex, Nz::OpenMode_NotOpen)));
case 2:
{
Nz::String filePath = lua.Check<Nz::String>(&argIndex);
Nz::UInt32 openMode = lua.Check<Nz::UInt32>(&argIndex, Nz::OpenMode_NotOpen);
return lua.Push(file.Open(filePath, openMode));
return lua.Push(instance.Open(filePath, openMode));
}
}
@@ -260,7 +260,7 @@ namespace Ndk
return 0;
});
file.BindMethod("SetCursorPos", [] (Nz::LuaState& lua, Nz::File& file, std::size_t argumentCount) -> int
file.BindMethod("SetCursorPos", [] (Nz::LuaState& lua, Nz::File& instance, std::size_t argumentCount) -> int
{
std::size_t argCount = std::min<std::size_t>(argumentCount, 2U);
@@ -268,13 +268,13 @@ namespace Ndk
switch (argCount)
{
case 1:
return lua.Push(file.SetCursorPos(lua.Check<Nz::UInt64>(&argIndex)));
return lua.Push(instance.SetCursorPos(lua.Check<Nz::UInt64>(&argIndex)));
case 2:
{
Nz::CursorPosition curPos = lua.Check<Nz::CursorPosition>(&argIndex);
Nz::Int64 offset = lua.Check<Nz::Int64>(&argIndex);
return lua.Push(file.SetCursorPos(curPos, offset));
return lua.Push(instance.SetCursorPos(curPos, offset));
}
}
@@ -282,10 +282,10 @@ namespace Ndk
return 0;
});
file.BindMethod("__tostring", [] (Nz::LuaState& lua, Nz::File& file, std::size_t /*argumentCount*/) -> int {
file.BindMethod("__tostring", [] (Nz::LuaState& lua, Nz::File& instance, std::size_t /*argumentCount*/) -> int {
Nz::StringStream ss("File(");
if (file.IsOpen())
ss << "Path: " << file.GetPath();
if (instance.IsOpen())
ss << "Path: " << instance.GetPath();
ss << ')';

View File

@@ -1,5 +1,5 @@
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Lua/LuaBinding_Graphics.hpp>
#include <NDK/LuaAPI.hpp>
@@ -32,6 +32,40 @@ namespace Ndk
/*********************************** Nz::InstancedRenderable ***********************************/
instancedRenderable.Reset("InstancedRenderable");
{
instancedRenderable.BindMethod("GetMaterial", [] (Nz::LuaState& lua, Nz::InstancedRenderable* instance, std::size_t argumentCount) -> int
{
std::size_t argCount = std::min<std::size_t>(argumentCount, 2U);
switch (argCount)
{
case 0:
case 1:
{
int argIndex = 2;
std::size_t matIndex(lua.Check<std::size_t>(&argIndex, 0));
return lua.Push(instance->GetMaterial(matIndex));
}
case 2:
{
int argIndex = 2;
std::size_t skinIndex(lua.Check<std::size_t>(&argIndex));
std::size_t matIndex(lua.Check<std::size_t>(&argIndex));
return lua.Push(instance->GetMaterial(skinIndex, matIndex));
}
}
lua.Error("No matching overload for method GetMaterial");
return 0;
});
instancedRenderable.BindMethod("GetMaterialCount", &Nz::InstancedRenderable::GetMaterialCount);
instancedRenderable.BindMethod("GetSkin", &Nz::InstancedRenderable::GetSkin);
instancedRenderable.BindMethod("GetSkinCount", &Nz::InstancedRenderable::GetSkinCount);
instancedRenderable.BindMethod("SetSkin", &Nz::InstancedRenderable::SetSkin);
instancedRenderable.BindMethod("SetSkinCount", &Nz::InstancedRenderable::SetSkinCount);
}
/*********************************** Nz::Material ***********************************/
@@ -92,6 +126,7 @@ namespace Ndk
material.BindMethod("EnableDepthSorting", &Nz::Material::EnableDepthSorting);
material.BindMethod("EnableDepthWrite", &Nz::Material::EnableDepthWrite);
material.BindMethod("EnableFaceCulling", &Nz::Material::EnableFaceCulling);
material.BindMethod("EnableReflectionMapping", &Nz::Material::EnableReflectionMapping);
material.BindMethod("EnableScissorTest", &Nz::Material::EnableScissorTest);
material.BindMethod("EnableShadowCasting", &Nz::Material::EnableShadowCasting);
material.BindMethod("EnableShadowReceive", &Nz::Material::EnableShadowReceive);
@@ -117,6 +152,7 @@ namespace Ndk
//material.BindMethod("GetPipeline", &Nz::Material::GetPipeline);
//material.BindMethod("GetPipelineInfo", &Nz::Material::GetPipelineInfo);
material.BindMethod("GetPointSize", &Nz::Material::GetPointSize);
material.BindMethod("GetReflectionMode", &Nz::Material::GetReflectionMode);
//material.BindMethod("GetShader", &Nz::Material::GetShader);
material.BindMethod("GetShininess", &Nz::Material::GetShininess);
material.BindMethod("GetSpecularColor", &Nz::Material::GetSpecularColor);
@@ -139,6 +175,7 @@ namespace Ndk
material.BindMethod("IsDepthSortingEnabled", &Nz::Material::IsDepthSortingEnabled);
material.BindMethod("IsDepthWriteEnabled", &Nz::Material::IsDepthWriteEnabled);
material.BindMethod("IsFaceCullingEnabled", &Nz::Material::IsFaceCullingEnabled);
material.BindMethod("IsReflectionMappingEnabled", &Nz::Material::IsReflectionMappingEnabled);
material.BindMethod("IsScissorTestEnabled", &Nz::Material::IsScissorTestEnabled);
material.BindMethod("IsStencilTestEnabled", &Nz::Material::IsStencilTestEnabled);
material.BindMethod("IsShadowCastingEnabled", &Nz::Material::IsShadowCastingEnabled);
@@ -160,6 +197,7 @@ namespace Ndk
material.BindMethod("SetFaceFilling", &Nz::Material::SetFaceFilling);
material.BindMethod("SetLineWidth", &Nz::Material::SetLineWidth);
material.BindMethod("SetPointSize", &Nz::Material::SetPointSize);
material.BindMethod("SetReflectionMode", &Nz::Material::SetReflectionMode);
material.BindMethod("SetShininess", &Nz::Material::SetShininess);
material.BindMethod("SetSpecularColor", &Nz::Material::SetSpecularColor);
material.BindMethod("SetSpecularColor", &Nz::Material::SetSpecularColor);
@@ -267,22 +305,72 @@ namespace Ndk
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);
model.BindMethod("SetMaterial", [] (Nz::LuaState& lua, Nz::Model* instance, std::size_t argumentCount) -> int
{
std::size_t argCount = std::min<std::size_t>(argumentCount, 3U);
switch (argCount)
{
case 2:
{
int argIndex = 2;
if (lua.IsOfType(argIndex, Nz::LuaType_Number))
{
std::size_t matIndex(lua.Check<std::size_t>(&argIndex));
Nz::MaterialRef mat(lua.Check<Nz::MaterialRef>(&argIndex));
instance->SetMaterial(matIndex, std::move(mat));
return 0;
}
else if (lua.IsOfType(argIndex, Nz::LuaType_String))
{
Nz::String subMesh(lua.Check<Nz::String>(&argIndex));
Nz::MaterialRef mat(lua.Check<Nz::MaterialRef>(&argIndex));
instance->SetMaterial(subMesh, std::move(mat));
return 0;
}
break;
}
case 3:
{
int argIndex = 2;
if (lua.IsOfType(argIndex, Nz::LuaType_Number))
{
std::size_t skinIndex(lua.Check<std::size_t>(&argIndex));
std::size_t matIndex(lua.Check<std::size_t>(&argIndex));
Nz::MaterialRef mat(lua.Check<Nz::MaterialRef>(&argIndex));
instance->SetMaterial(skinIndex, matIndex, std::move(mat));
return 0;
}
else if (lua.IsOfType(argIndex, Nz::LuaType_String))
{
std::size_t skinIndex(lua.Check<std::size_t>(&argIndex));
Nz::String subMesh(lua.Check<Nz::String>(&argIndex));
Nz::MaterialRef materialRef(lua.Check<Nz::MaterialRef>(&argIndex));
instance->SetMaterial(skinIndex, subMesh, std::move(materialRef));
return 0;
}
break;
}
}
lua.Error("No matching overload for method SetMaterial");
return 0;
});
//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 ***********************************/
@@ -301,7 +389,6 @@ namespace Ndk
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);
@@ -317,12 +404,28 @@ namespace Ndk
sprite.BindMethod("SetMaterial", [] (Nz::LuaState& lua, Nz::SpriteRef& instance, std::size_t /*argumentCount*/) -> int
{
int argIndex = 2;
bool resizeSprite = lua.CheckBoolean(argIndex + 1, true);
if (lua.IsOfType(argIndex, "Material"))
{
bool resizeSprite = lua.CheckBoolean(argIndex + 1, true);
instance->SetMaterial(*static_cast<Nz::MaterialRef*>(lua.ToUserdata(argIndex)), resizeSprite);
else
instance->SetMaterial(lua.Check<Nz::String>(&argIndex), resizeSprite);
}
else if (lua.IsOfType(argIndex, Nz::LuaType_String))
{
bool resizeSprite = lua.CheckBoolean(argIndex + 1, true);
instance->SetMaterial(lua.ToString(argIndex), resizeSprite);
}
else if (lua.IsOfType(argIndex, Nz::LuaType_Number))
{
std::size_t skinIndex(lua.Check<std::size_t>(&argIndex));
bool resizeSprite = lua.CheckBoolean(argIndex + 1, true);
if (lua.IsOfType(argIndex, "Material"))
instance->SetMaterial(skinIndex, *static_cast<Nz::MaterialRef*>(lua.ToUserdata(argIndex)), resizeSprite);
else
instance->SetMaterial(skinIndex, lua.Check<Nz::String>(&argIndex), resizeSprite);
}
return 0;
});
@@ -330,12 +433,28 @@ namespace Ndk
sprite.BindMethod("SetTexture", [] (Nz::LuaState& lua, Nz::SpriteRef& instance, std::size_t /*argumentCount*/) -> int
{
int argIndex = 2;
bool resizeSprite = lua.CheckBoolean(argIndex + 1, true);
if (lua.IsOfType(argIndex, "Texture"))
{
bool resizeSprite = lua.CheckBoolean(argIndex + 1, true);
instance->SetTexture(*static_cast<Nz::TextureRef*>(lua.ToUserdata(argIndex)), resizeSprite);
else
instance->SetTexture(lua.Check<Nz::String>(&argIndex), resizeSprite);
}
else if (lua.IsOfType(argIndex, Nz::LuaType_String))
{
bool resizeSprite = lua.CheckBoolean(argIndex + 1, true);
instance->SetTexture(lua.ToString(argIndex), resizeSprite);
}
else if (lua.IsOfType(argIndex, Nz::LuaType_Number))
{
std::size_t skinIndex(lua.Check<std::size_t>(&argIndex));
bool resizeSprite = lua.CheckBoolean(argIndex + 1, true);
if (lua.IsOfType(argIndex, "Texture"))
instance->SetTexture(skinIndex, *static_cast<Nz::TextureRef*>(lua.ToUserdata(argIndex)), resizeSprite);
else
instance->SetTexture(skinIndex, lua.Check<Nz::String>(&argIndex), resizeSprite);
}
return 0;
});
@@ -366,5 +485,15 @@ namespace Ndk
model.Register(state);
sprite.Register(state);
spriteLibrary.Register(state);
// Nz::ReflectionMode
static_assert(Nz::ReflectionMode_Max + 1 == 3, "Nz::ReflectionMode has been updated but change was not reflected to Lua binding");
state.PushTable(0, 3);
{
state.PushField("Probe", Nz::ReflectionMode_Probe);
state.PushField("RealTime", Nz::ReflectionMode_RealTime);
state.PushField("Skybox", Nz::ReflectionMode_Skybox);
}
state.SetGlobal("ReflectionMode");
}
}

View File

@@ -1,5 +1,5 @@
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Lua/LuaBinding_Platform.hpp>
#include <NDK/LuaAPI.hpp>

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 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
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Lua/LuaBinding_Renderer.hpp>
#include <NDK/LuaAPI.hpp>

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq, Arnaud Cadot
// Copyright (C) 2017 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
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Lua/LuaBinding_SDK.hpp>
#include <NDK/LuaAPI.hpp>
@@ -169,6 +169,12 @@ namespace Ndk
world.BindMethod("CreateEntity", &World::CreateEntity);
world.BindMethod("CreateEntities", &World::CreateEntities);
world.BindMethod("Clear", &World::Clear);
world.BindMethod("DisableProfiler", &World::DisableProfiler);
world.BindMethod("EnableProfiler", &World::EnableProfiler);
world.BindMethod("IsProfilerEnabled", &World::IsProfilerEnabled);
world.BindMethod("Refresh", &World::Refresh);
world.BindMethod("ResetProfiler", &World::ResetProfiler);
world.BindMethod("Update", &World::Update);
world.BindMethod("IsValidHandle", &WorldHandle::IsValid);
}

View File

@@ -1,5 +1,5 @@
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Lua/LuaBinding_Utility.hpp>
#include <NDK/LuaAPI.hpp>
@@ -209,29 +209,29 @@ namespace Ndk
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::LuaState& lua, Nz::Node& node, std::size_t /*argumentCount*/) -> int
node.BindMethod("Move", [] (Nz::LuaState& lua, Nz::Node& instance, std::size_t /*argumentCount*/) -> int
{
int argIndex = 2;
Nz::Vector3f offset = lua.Check<Nz::Vector3f>(&argIndex);
Nz::CoordSys coordSys = lua.Check<Nz::CoordSys>(&argIndex, Nz::CoordSys_Local);
node.Move(offset, coordSys);
instance.Move(offset, coordSys);
return 0;
});
node.BindMethod("Rotate", [] (Nz::LuaState& lua, Nz::Node& node, std::size_t /*argumentCount*/) -> int
node.BindMethod("Rotate", [] (Nz::LuaState& lua, Nz::Node& instance, std::size_t /*argumentCount*/) -> int
{
int argIndex = 2;
Nz::Quaternionf rotation = lua.Check<Nz::Quaternionf>(&argIndex);
Nz::CoordSys coordSys = lua.Check<Nz::CoordSys>(&argIndex, Nz::CoordSys_Local);
node.Rotate(rotation, coordSys);
instance.Rotate(rotation, coordSys);
return 0;
});
node.BindMethod("Scale", [] (Nz::LuaState& lua, Nz::Node& node, std::size_t argumentCount) -> int
node.BindMethod("Scale", [] (Nz::LuaState& lua, Nz::Node& instance, std::size_t argumentCount) -> int
{
std::size_t argCount = std::min<std::size_t>(argumentCount, 4U);
@@ -241,15 +241,15 @@ namespace Ndk
case 1:
{
if (lua.IsOfType(argIndex, Nz::LuaType_Number))
node.Scale(lua.Check<float>(&argIndex));
instance.Scale(lua.Check<float>(&argIndex));
else
node.Scale(lua.Check<Nz::Vector3f>(&argIndex));
instance.Scale(lua.Check<Nz::Vector3f>(&argIndex));
return 0;
}
case 3:
node.Scale(lua.Check<Nz::Vector3f>(&argIndex));
instance.Scale(lua.Check<Nz::Vector3f>(&argIndex));
return 0;
}
@@ -257,7 +257,7 @@ namespace Ndk
return 0;
});
node.BindMethod("SetScale", [] (Nz::LuaState& lua, Nz::Node& node, std::size_t argumentCount) -> int
node.BindMethod("SetScale", [] (Nz::LuaState& lua, Nz::Node& instance, std::size_t argumentCount) -> int
{
std::size_t argCount = std::min<std::size_t>(argumentCount, 4U);
@@ -271,10 +271,10 @@ namespace Ndk
{
float scale = lua.Check<float>(&argIndex);
Nz::CoordSys coordSys = lua.Check<Nz::CoordSys>(&argIndex, Nz::CoordSys_Local);
node.SetScale(scale, coordSys);
instance.SetScale(scale, coordSys);
}
else
node.SetScale(lua.Check<Nz::Vector3f>(&argIndex));
instance.SetScale(lua.Check<Nz::Vector3f>(&argIndex));
return 0;
}
@@ -285,7 +285,7 @@ namespace Ndk
Nz::Vector3f scale = lua.Check<Nz::Vector3f>(&argIndex);
Nz::CoordSys coordSys = lua.Check<Nz::CoordSys>(&argIndex, Nz::CoordSys_Local);
node.SetScale(scale, coordSys);
instance.SetScale(scale, coordSys);
return 0;
}
}
@@ -294,7 +294,7 @@ namespace Ndk
return 0;
});
node.BindMethod("SetInitialScale", [] (Nz::LuaState& lua, Nz::Node& node, std::size_t argumentCount) -> int
node.BindMethod("SetInitialScale", [] (Nz::LuaState& lua, Nz::Node& instance, std::size_t argumentCount) -> int
{
std::size_t argCount = std::min<std::size_t>(argumentCount, 4U);
@@ -304,16 +304,16 @@ namespace Ndk
case 1:
{
if (lua.IsOfType(argIndex, Nz::LuaType_Number))
node.SetInitialScale(lua.Check<float>(&argIndex));
instance.SetInitialScale(lua.Check<float>(&argIndex));
else
node.SetInitialScale(lua.Check<Nz::Vector2f>(&argIndex));
instance.SetInitialScale(lua.Check<Nz::Vector2f>(&argIndex));
return 0;
}
case 2:
case 3:
node.SetInitialScale(lua.Check<Nz::Vector3f>(&argIndex));
instance.SetInitialScale(lua.Check<Nz::Vector3f>(&argIndex));
return 0;
}

View File

@@ -1,12 +1,11 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Sdk.hpp>
#include <Nazara/Audio/Audio.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Core/Log.hpp>
#include <Nazara/Core/ParameterList.hpp>
#include <Nazara/Graphics/Graphics.hpp>
#include <Nazara/Lua/Lua.hpp>
#include <Nazara/Noise/Noise.hpp>
@@ -22,6 +21,7 @@
#include <NDK/Components/PhysicsComponent2D.hpp>
#include <NDK/Components/PhysicsComponent3D.hpp>
#include <NDK/Components/VelocityComponent.hpp>
#include <NDK/Components/ConstraintComponent2D.hpp>
#include <NDK/Systems/PhysicsSystem2D.hpp>
#include <NDK/Systems/PhysicsSystem3D.hpp>
#include <NDK/Systems/VelocitySystem.hpp>
@@ -90,6 +90,7 @@ namespace Ndk
InitializeComponent<PhysicsComponent2D>("NdkPhys2");
InitializeComponent<PhysicsComponent3D>("NdkPhys3");
InitializeComponent<VelocityComponent>("NdkVeloc");
InitializeComponent<VelocityComponent>("NdkCons2");
#ifndef NDK_SERVER
// Client components

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/State.hpp>

View File

@@ -1,12 +1,11 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Systems/ListenerSystem.hpp>
#include <Nazara/Audio/Audio.hpp>
#include <NDK/Components/ListenerComponent.hpp>
#include <NDK/Components/NodeComponent.hpp>
#include <NDK/Components/VelocityComponent.hpp>
namespace Ndk
{
@@ -34,7 +33,7 @@ namespace Ndk
* \param elapsedTime Delta time used for the update
*/
void ListenerSystem::OnUpdate(float /*elapsedTime*/)
void ListenerSystem::OnUpdate(float elapsedTime)
{
std::size_t activeListenerCount = 0;
@@ -45,18 +44,18 @@ namespace Ndk
if (!listener.IsActive())
continue;
Nz::Vector3f oldPos = Nz::Audio::GetListenerPosition();
// We get the position and the rotation to affect these to the listener
const NodeComponent& node = entity->GetComponent<NodeComponent>();
Nz::Audio::SetListenerPosition(node.GetPosition(Nz::CoordSys_Global));
Nz::Vector3f newPos = node.GetPosition(Nz::CoordSys_Global);
Nz::Audio::SetListenerPosition(newPos);
Nz::Audio::SetListenerRotation(node.GetRotation(Nz::CoordSys_Global));
// We verify the presence of a component of velocity
// (The listener'speed does not move it, but disturbs the sound like Doppler effect)
if (entity->HasComponent<VelocityComponent>())
{
const VelocityComponent& velocity = entity->GetComponent<VelocityComponent>();
Nz::Audio::SetListenerVelocity(velocity.linearVelocity);
}
// Compute listener velocity based on their old/new position
Nz::Vector3f velocity = (newPos - oldPos) / elapsedTime;
Nz::Audio::SetListenerVelocity(velocity);
activeListenerCount++;
}

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Systems/ParticleSystem.hpp>
#include <NDK/Components/ParticleGroupComponent.hpp>

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Systems/PhysicsSystem2D.hpp>
#include <Nazara/Physics2D/RigidBody2D.hpp>
@@ -31,18 +31,6 @@ namespace Ndk
Excludes<PhysicsComponent3D>();
}
/*!
* \brief Constructs a PhysicsSystem object by copy semantic
*
* \param system PhysicsSystem to copy
*/
PhysicsSystem2D::PhysicsSystem2D(const PhysicsSystem2D& system) :
System(system),
m_world()
{
}
void PhysicsSystem2D::CreatePhysWorld() const
{
NazaraAssert(!m_world, "Physics world should not be created twice");
@@ -92,9 +80,9 @@ namespace Ndk
NodeComponent& node = entity->GetComponent<NodeComponent>();
PhysicsComponent2D& phys = entity->GetComponent<PhysicsComponent2D>();
Nz::RigidBody2D& body = phys.GetRigidBody();
node.SetRotation(Nz::EulerAnglesf(0.f, 0.f, body.GetRotation()), Nz::CoordSys_Global);
node.SetPosition(Nz::Vector3f(body.GetPosition(), node.GetPosition(Nz::CoordSys_Global).z), Nz::CoordSys_Global);
Nz::RigidBody2D* body = phys.GetRigidBody();
node.SetRotation(Nz::EulerAnglesf(0.f, 0.f, body->GetRotation()), Nz::CoordSys_Global);
node.SetPosition(Nz::Vector3f(body->GetPosition(), node.GetPosition(Nz::CoordSys_Global).z), Nz::CoordSys_Global);
}
float invElapsedTime = 1.f / elapsedTime;

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Systems/PhysicsSystem3D.hpp>
#include <Nazara/Physics3D/RigidBody3D.hpp>
@@ -31,18 +31,6 @@ namespace Ndk
Excludes<PhysicsComponent2D>();
}
/*!
* \brief Constructs a PhysicsSystem object by copy semantic
*
* \param system PhysicsSystem to copy
*/
PhysicsSystem3D::PhysicsSystem3D(const PhysicsSystem3D& system) :
System(system),
m_world()
{
}
void PhysicsSystem3D::CreatePhysWorld() const
{
NazaraAssert(!m_world, "Physics world should not be created twice");
@@ -59,16 +47,32 @@ namespace Ndk
void PhysicsSystem3D::OnEntityValidation(Entity* entity, bool justAdded)
{
// It's possible our entity got revalidated because of the addition/removal of a PhysicsComponent3D
if (!justAdded)
if (entity->HasComponent<PhysicsComponent3D>())
{
// We take the opposite array from which the entity should belong to
auto& entities = (entity->HasComponent<PhysicsComponent3D>()) ? m_staticObjects : m_dynamicObjects;
entities.Remove(entity);
}
if (entity->GetComponent<PhysicsComponent3D>().IsNodeSynchronizationEnabled())
m_dynamicObjects.Insert(entity);
else
m_dynamicObjects.Remove(entity);
auto& entities = (entity->HasComponent<PhysicsComponent3D>()) ? m_dynamicObjects : m_staticObjects;
entities.Insert(entity);
m_staticObjects.Remove(entity);
}
else
{
m_dynamicObjects.Remove(entity);
m_staticObjects.Insert(entity);
// If entities just got added to the system, teleport them to their NodeComponent position/rotation
// This will prevent the physics engine to mess with the scene while correcting position/rotation
if (justAdded)
{
auto& collision = entity->GetComponent<CollisionComponent3D>();
auto& node = entity->GetComponent<NodeComponent>();
Nz::RigidBody3D* physObj = collision.GetStaticBody();
physObj->SetPosition(node.GetPosition());
physObj->SetRotation(node.GetRotation());
}
}
if (!m_world)
CreatePhysWorld();
@@ -92,9 +96,9 @@ namespace Ndk
NodeComponent& node = entity->GetComponent<NodeComponent>();
PhysicsComponent3D& phys = entity->GetComponent<PhysicsComponent3D>();
Nz::RigidBody3D& physObj = phys.GetRigidBody();
node.SetRotation(physObj.GetRotation(), Nz::CoordSys_Global);
node.SetPosition(physObj.GetPosition(), Nz::CoordSys_Global);
Nz::RigidBody3D* physObj = phys.GetRigidBody();
node.SetRotation(physObj->GetRotation(), Nz::CoordSys_Global);
node.SetPosition(physObj->GetPosition(), Nz::CoordSys_Global);
}
float invElapsedTime = 1.f / elapsedTime;
@@ -115,10 +119,10 @@ namespace Ndk
if (newPosition != oldPosition)
{
physObj->SetPosition(newPosition);
physObj->SetVelocity((newPosition - oldPosition) * invElapsedTime);
physObj->SetLinearVelocity((newPosition - oldPosition) * invElapsedTime);
}
else
physObj->SetVelocity(Nz::Vector3f::Zero());
physObj->SetLinearVelocity(Nz::Vector3f::Zero());
if (newRotation != oldRotation)
{

View File

@@ -1,9 +1,12 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Systems/RenderSystem.hpp>
#include <Nazara/Graphics/ColorBackground.hpp>
#include <Nazara/Graphics/ForwardRenderTechnique.hpp>
#include <Nazara/Graphics/SceneData.hpp>
#include <Nazara/Graphics/SkyboxBackground.hpp>
#include <Nazara/Math/Rect.hpp>
#include <Nazara/Renderer/Renderer.hpp>
#include <NDK/Components/CameraComponent.hpp>
@@ -36,7 +39,7 @@ namespace Ndk
ChangeRenderTechnique<Nz::ForwardRenderTechnique>();
SetDefaultBackground(Nz::ColorBackground::New());
SetUpdateOrder(100); //< Render last, after every movement is done
SetUpdateRate(0.f); //< We don't want any rate limit
SetMaximumUpdateRate(0.f); //< We don't want any rate limit
}
/*!
@@ -98,15 +101,19 @@ namespace Ndk
{
m_drawables.Insert(entity);
GraphicsComponent& gfxComponent = entity->GetComponent<GraphicsComponent>();
if (justAdded)
{
GraphicsComponent& gfxComponent = entity->GetComponent<GraphicsComponent>();
gfxComponent.AddToCullingList(&m_drawableCulling);
}
if (gfxComponent.DoesRequireRealTimeReflections())
m_realtimeReflected.Insert(entity);
else
m_realtimeReflected.Remove(entity);
}
else
{
m_drawables.Remove(entity);
m_realtimeReflected.Remove(entity);
if (entity->HasComponent<GraphicsComponent>())
{
@@ -176,6 +183,7 @@ namespace Ndk
m_coordinateSystemInvalidated = false;
}
UpdateDynamicReflections();
UpdatePointSpotShadowMaps();
for (const Ndk::EntityHandle& camera : m_cameras)
@@ -231,8 +239,12 @@ namespace Ndk
Nz::SceneData sceneData;
sceneData.ambientColor = Nz::Color(25, 25, 25);
sceneData.background = m_background;
sceneData.globalReflectionTexture = nullptr;
sceneData.viewer = &camComponent;
if (m_background && m_background->GetBackgroundType() == Nz::BackgroundType_Skybox)
sceneData.globalReflectionTexture = static_cast<Nz::SkyboxBackground*>(m_background.Get())->GetTexture();
m_renderTechnique->Clear(sceneData);
m_renderTechnique->Draw(sceneData);
}
@@ -244,6 +256,19 @@ namespace Ndk
* \param viewer Viewer of the scene
*/
void RenderSystem::UpdateDynamicReflections()
{
Nz::SceneData dummySceneData;
dummySceneData.ambientColor = Nz::Color(0, 0, 0);
dummySceneData.background = nullptr;
dummySceneData.viewer = nullptr; //< Depth technique doesn't require any viewer
for (const Ndk::EntityHandle& handle : m_realtimeReflected)
{
//NazaraWarning("Realtime reflected: #" + handle->ToString());
}
}
void RenderSystem::UpdateDirectionalShadowMaps(const Nz::AbstractViewer& /*viewer*/)
{
if (!m_shadowRT.IsValid())
@@ -322,12 +347,12 @@ namespace Ndk
{
static Nz::Quaternionf rotations[6] =
{
Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), Nz::Vector3f::UnitX()), // nzCubemapFace_PositiveX
Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), -Nz::Vector3f::UnitX()), // nzCubemapFace_NegativeX
Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), -Nz::Vector3f::UnitY()), // nzCubemapFace_PositiveY
Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), Nz::Vector3f::UnitY()), // nzCubemapFace_NegativeY
Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), -Nz::Vector3f::UnitZ()), // nzCubemapFace_PositiveZ
Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), Nz::Vector3f::UnitZ()) // nzCubemapFace_NegativeZ
Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), Nz::Vector3f::UnitX()), // CubemapFace_PositiveX
Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), -Nz::Vector3f::UnitX()), // CubemapFace_NegativeX
Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), -Nz::Vector3f::UnitY()), // CubemapFace_PositiveY
Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), Nz::Vector3f::UnitY()), // CubemapFace_NegativeY
Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), -Nz::Vector3f::UnitZ()), // CubemapFace_PositiveZ
Nz::Quaternionf::RotationBetween(Nz::Vector3f::Forward(), Nz::Vector3f::UnitZ()) // CubemapFace_NegativeZ
};
for (unsigned int face = 0; face < 6; ++face)

View File

@@ -1,6 +1,6 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Systems/VelocitySystem.hpp>
#include <NDK/Components/NodeComponent.hpp>

View File

@@ -1,36 +1,78 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Widgets/ButtonWidget.hpp>
#include <NDK/Components/GraphicsComponent.hpp>
#include <NDK/Components/NodeComponent.hpp>
#include <NDK/World.hpp>
namespace Ndk
{
Nz::Color ButtonWidget::s_color { 74, 74, 74 };
Nz::Color ButtonWidget::s_cornerColor { 180, 180, 180 };
Nz::Color ButtonWidget::s_hoverColor { 128, 128, 128 };
Nz::Color ButtonWidget::s_hoverCornerColor { s_cornerColor };
Nz::Color ButtonWidget::s_pressColor { s_cornerColor };
Nz::Color ButtonWidget::s_pressCornerColor { s_color };
ButtonWidget::ButtonWidget(BaseWidget* parent) :
BaseWidget(parent)
BaseWidget(parent),
m_color { s_color },
m_cornerColor { s_cornerColor },
m_hoverColor { s_hoverColor },
m_hoverCornerColor { s_hoverCornerColor },
m_pressColor { s_pressColor },
m_pressCornerColor { s_pressCornerColor }
{
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->SetColor(m_color);
m_gradientSprite->SetCornerColor(Nz::RectCorner_LeftBottom, m_cornerColor);
m_gradientSprite->SetCornerColor(Nz::RectCorner_RightBottom, m_cornerColor);
m_gradientSprite->SetMaterial(Nz::Material::New("Basic2D"));
m_gradientEntity = CreateEntity();
m_gradientEntity = CreateEntity(false);
m_gradientEntity->AddComponent<NodeComponent>().SetParent(this);
m_gradientEntity->AddComponent<GraphicsComponent>().Attach(m_gradientSprite);
m_textSprite = Nz::TextSprite::New();
m_textEntity = CreateEntity();
m_textEntity = CreateEntity(true);
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite, 1);
Layout();
}
const Nz::Color& ButtonWidget::GetDefaultColor()
{
return s_color;
}
const Nz::Color& ButtonWidget::GetDefaultCornerColor()
{
return s_cornerColor;
}
const Nz::Color& ButtonWidget::GetDefaultHoverColor()
{
return s_hoverColor;
}
const Nz::Color& ButtonWidget::GetDefaultHoverCornerColor()
{
return s_hoverCornerColor;
}
const Nz::Color& ButtonWidget::GetDefaultPressColor()
{
return s_pressColor;
}
const Nz::Color& ButtonWidget::GetDefaultPressCornerColor()
{
return s_pressCornerColor;
}
void ButtonWidget::ResizeToContent()
{
SetContentSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths()));
@@ -40,29 +82,52 @@ namespace Ndk
{
BaseWidget::Layout();
m_gradientSprite->SetSize(GetSize());
Nz::Vector2f origin = GetContentOrigin();
const Nz::Vector2f& contentSize = GetContentSize();
m_gradientEntity->GetComponent<NodeComponent>().SetPosition(origin);
m_gradientSprite->SetSize(contentSize);
Nz::Boxf textBox = m_textEntity->GetComponent<GraphicsComponent>().GetBoundingVolume().aabb;
Nz::Boxf textBox = m_textEntity->GetComponent<GraphicsComponent>().GetBoundingVolume().obb.localBox;
m_textEntity->GetComponent<NodeComponent>().SetPosition(origin.x + contentSize.x / 2 - textBox.width / 2, origin.y + contentSize.y / 2 - textBox.height / 2);
}
void ButtonWidget::OnMouseButtonPress(int /*x*/, int /*y*/, Nz::Mouse::Button button)
{
if (button == Nz::Mouse::Left)
{
m_gradientSprite->SetColor(m_pressColor);
m_gradientSprite->SetCornerColor(Nz::RectCorner_LeftBottom, m_pressCornerColor);
m_gradientSprite->SetCornerColor(Nz::RectCorner_RightBottom, m_pressCornerColor);
m_gradientSprite->SetTexture(m_pressTexture, false);
}
}
void ButtonWidget::OnMouseButtonRelease(int /*x*/, int /*y*/, Nz::Mouse::Button button)
{
if (button == Nz::Mouse::Left)
{
m_gradientSprite->SetColor(m_hoverColor);
m_gradientSprite->SetCornerColor(Nz::RectCorner_LeftBottom, m_hoverCornerColor);
m_gradientSprite->SetCornerColor(Nz::RectCorner_RightBottom, m_hoverCornerColor);
m_gradientSprite->SetTexture(m_hoverTexture, false);
OnButtonTrigger(this);
}
}
void ButtonWidget::OnMouseEnter()
{
m_gradientSprite->SetColor(Nz::Color(128, 128, 128));
m_gradientSprite->SetColor(m_hoverColor);
m_gradientSprite->SetCornerColor(Nz::RectCorner_LeftBottom, m_hoverCornerColor);
m_gradientSprite->SetCornerColor(Nz::RectCorner_RightBottom, m_hoverCornerColor);
m_gradientSprite->SetTexture(m_hoverTexture, false);
}
void ButtonWidget::OnMouseExit()
{
m_gradientSprite->SetColor(Nz::Color(74, 74, 74));
m_gradientSprite->SetColor(m_color);
m_gradientSprite->SetCornerColor(Nz::RectCorner_LeftBottom, m_cornerColor);
m_gradientSprite->SetCornerColor(Nz::RectCorner_RightBottom, m_cornerColor);
m_gradientSprite->SetTexture(m_texture, false);
}
}

View File

@@ -1,14 +1,10 @@
// Copyright (C) 2017 Samy Bensaid
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/World.hpp>
#include <NDK/Widgets/CheckboxWidget.hpp>
#include <NDK/Components/GraphicsComponent.hpp>
#include <Nazara/Utility/SimpleTextDrawer.hpp>
#include <Nazara/Graphics/Material.hpp>
#include <Nazara/Utility/Font.hpp>
#include <Nazara/Utility/FontGlyph.hpp>
#include <algorithm>
namespace Ndk
@@ -32,19 +28,19 @@ namespace Ndk
m_checkboxContentSprite = Nz::Sprite::New(Nz::Material::New("Translucent2D"));
m_textSprite = Nz::TextSprite::New();
m_checkboxBorderEntity = CreateEntity();
m_checkboxBorderEntity = CreateEntity(false);
m_checkboxBorderEntity->AddComponent<NodeComponent>().SetParent(this);
m_checkboxBorderEntity->AddComponent<GraphicsComponent>().Attach(m_checkboxBorderSprite);
m_checkboxBackgroundEntity = CreateEntity();
m_checkboxBackgroundEntity = CreateEntity(false);
m_checkboxBackgroundEntity->AddComponent<NodeComponent>().SetParent(this);
m_checkboxBackgroundEntity->AddComponent<GraphicsComponent>().Attach(m_checkboxBackgroundSprite, 1);
m_checkboxContentEntity = CreateEntity();
m_checkboxContentEntity = CreateEntity(true);
m_checkboxContentEntity->AddComponent<NodeComponent>().SetParent(this);
m_checkboxContentEntity->AddComponent<GraphicsComponent>().Attach(m_checkboxContentSprite, 2);
m_textEntity = CreateEntity();
m_textEntity = CreateEntity(true);
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
@@ -138,7 +134,7 @@ namespace Ndk
Nz::Vector3f textBox = m_textSprite->GetBoundingVolume().obb.localBox.GetLengths();
m_textEntity->GetComponent<NodeComponent>().SetPosition(origin.x + checkboxSize.x + (m_adaptativeMargin ? checkboxSize.x / 2.f : m_textMargin),
origin.y + checkboxSize.y / 2.f - textBox.y / 2.f);
origin.y + checkboxSize.y / 2.f - textBox.y / 2.f);
}
void CheckboxWidget::OnMouseButtonRelease(int x, int y, Nz::Mouse::Button button)

View File

@@ -0,0 +1,37 @@
// Copyright (C) 2017 Samy Bensaid
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Widgets/ImageWidget.hpp>
#include <NDK/Components/NodeComponent.hpp>
#include <NDK/Components/GraphicsComponent.hpp>
namespace Ndk
{
ImageWidget::ImageWidget(BaseWidget* parent) :
BaseWidget(parent)
{
m_entity = CreateEntity(true);
m_entity->AddComponent<NodeComponent>();
auto& gfx = m_entity->AddComponent<GraphicsComponent>();
m_sprite = Nz::Sprite::New();
gfx.Attach(m_sprite);
}
void ImageWidget::ResizeToContent()
{
Nz::Vector3ui textureSize = m_sprite->GetMaterial()->GetDiffuseMap()->GetSize();
SetSize({ static_cast<float>(textureSize.x), static_cast<float>(textureSize.y) });
}
void ImageWidget::Layout()
{
BaseWidget::Layout();
Nz::Vector2f origin = GetContentOrigin();
Nz::Vector2f contentSize = GetContentSize();
m_entity->GetComponent<NodeComponent>().SetPosition(origin);
m_sprite->SetSize(contentSize);
}
}

View File

@@ -1,11 +1,10 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Widgets/LabelWidget.hpp>
#include <NDK/Components/GraphicsComponent.hpp>
#include <NDK/Components/NodeComponent.hpp>
#include <NDK/World.hpp>
namespace Ndk
{
@@ -14,13 +13,20 @@ namespace Ndk
{
m_textSprite = Nz::TextSprite::New();
m_textEntity = CreateEntity();
m_textEntity = CreateEntity(true);
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
Layout();
}
void LabelWidget::Layout()
{
BaseWidget::Layout();
m_textEntity->GetComponent<NodeComponent>().SetPosition(GetContentOrigin());
}
void LabelWidget::ResizeToContent()
{
SetContentSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths()));

View File

@@ -1,10 +1,8 @@
// Copyright (C) 2017 Samy Bensaid
// Copyright (C) 2017 Samy Bensaid
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/World.hpp>
#include <NDK/Widgets/ProgressBarWidget.hpp>
#include <Nazara/Utility/Image.hpp>
#include <NDK/Components/NodeComponent.hpp>
#include <NDK/Components/GraphicsComponent.hpp>
@@ -32,11 +30,11 @@ namespace Ndk
SetBarColor(s_barColor, s_barCornerColor);
m_borderEntity = CreateEntity();
m_borderEntity = CreateEntity(false);
m_borderEntity->AddComponent<NodeComponent>().SetParent(this);
m_borderEntity->AddComponent<GraphicsComponent>().Attach(m_borderSprite);
m_barEntity = CreateEntity();
m_barEntity = CreateEntity(true);
m_barEntity->AddComponent<NodeComponent>().SetParent(this);
GraphicsComponent& graphics = m_barEntity->AddComponent<GraphicsComponent>();
@@ -45,7 +43,7 @@ namespace Ndk
m_textSprite = Nz::TextSprite::New();
m_textEntity = CreateEntity();
m_textEntity = CreateEntity(true);
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);

View File

@@ -1,20 +1,18 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/Widgets/TextAreaWidget.hpp>
#include <Nazara/Core/Unicode.hpp>
#include <NDK/Components/GraphicsComponent.hpp>
#include <NDK/Components/NodeComponent.hpp>
#include <NDK/World.hpp>
#include <limits>
namespace Ndk
{
TextAreaWidget::TextAreaWidget(BaseWidget* parent) :
BaseWidget(parent),
m_echoMode(EchoMode_Normal),
m_cursorPosition(0U, 0U),
m_cursorGlyph(0),
m_multiLineEnabled(false),
m_readOnly(false)
{
@@ -22,14 +20,14 @@ namespace Ndk
m_cursorSprite->SetColor(Nz::Color::Black);
m_cursorSprite->SetSize(1.f, float(m_drawer.GetFont()->GetSizeInfo(m_drawer.GetCharacterSize()).lineHeight));
m_cursorEntity = CreateEntity();
m_cursorEntity = CreateEntity(true);
m_cursorEntity->AddComponent<GraphicsComponent>().Attach(m_cursorSprite, 10);
m_cursorEntity->AddComponent<NodeComponent>().SetParent(this);
m_cursorEntity->Enable(false);
m_textSprite = Nz::TextSprite::New();
m_textEntity = CreateEntity();
m_textEntity = CreateEntity(true);
m_textEntity->AddComponent<GraphicsComponent>().Attach(m_textSprite);
m_textEntity->AddComponent<NodeComponent>().SetParent(this);
@@ -40,9 +38,38 @@ namespace Ndk
void TextAreaWidget::AppendText(const Nz::String& text)
{
m_drawer.AppendText(text);
m_text += text;
switch (m_echoMode)
{
case EchoMode_Normal:
m_drawer.AppendText(text);
break;
case EchoMode_Password:
m_drawer.AppendText(Nz::String(text.GetLength(), '*'));
break;
case EchoMode_PasswordExceptLast:
{
m_drawer.Clear();
std::size_t textLength = m_text.GetLength();
if (textLength >= 2)
{
std::size_t lastCharacterPosition = m_text.GetCharacterPosition(textLength - 2);
if (lastCharacterPosition != Nz::String::npos)
m_drawer.AppendText(Nz::String(textLength - 1, '*'));
}
if (textLength >= 1)
m_drawer.AppendText(m_text.SubString(m_text.GetCharacterPosition(textLength - 1)));
break;
}
}
m_textSprite->Update(m_drawer);
OnTextChanged(this, m_text);
}
std::size_t TextAreaWidget::GetHoveredGlyph(float x, float y) const
@@ -82,18 +109,19 @@ namespace Ndk
void TextAreaWidget::Write(const Nz::String& text)
{
if (m_cursorGlyph >= m_drawer.GetGlyphCount())
std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition);
if (cursorGlyph >= m_drawer.GetGlyphCount())
{
AppendText(text);
SetCursorPosition(m_drawer.GetGlyphCount());
}
else
{
Nz::String currentText = m_drawer.GetText();
currentText.Insert(currentText.GetCharacterPosition(m_cursorGlyph), text);
SetText(currentText);
m_text.Insert(m_text.GetCharacterPosition(cursorGlyph), text);
SetText(m_text);
SetCursorPosition(m_cursorGlyph + text.GetLength());
SetCursorPosition(cursorGlyph + text.GetLength());
}
}
@@ -106,24 +134,43 @@ namespace Ndk
RefreshCursor();
}
void TextAreaWidget::OnKeyPressed(const Nz::WindowEvent::KeyEvent& key)
bool TextAreaWidget::IsFocusable() const
{
return !m_readOnly;
}
void TextAreaWidget::OnFocusLost()
{
m_cursorEntity->Disable();
}
void TextAreaWidget::OnFocusReceived()
{
if (!m_readOnly)
m_cursorEntity->Enable(true);
}
bool TextAreaWidget::OnKeyPressed(const Nz::WindowEvent::KeyEvent& key)
{
switch (key.code)
{
case Nz::Keyboard::Delete:
{
const Nz::String& text = m_drawer.GetText();
std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition);
std::size_t textLength = m_text.GetLength();
if (cursorGlyph > textLength)
return true;
Nz::String newText;
if (m_cursorGlyph > 0)
newText.Append(text.SubString(0, text.GetCharacterPosition(m_cursorGlyph) - 1));
if (cursorGlyph > 0)
newText.Append(m_text.SubString(0, m_text.GetCharacterPosition(cursorGlyph) - 1));
if (m_cursorGlyph < m_drawer.GetGlyphCount())
newText.Append(text.SubString(text.GetCharacterPosition(m_cursorGlyph + 1)));
if (cursorGlyph < textLength)
newText.Append(m_text.SubString(m_text.GetCharacterPosition(cursorGlyph + 1)));
m_drawer.SetText(newText);
m_textSprite->Update(m_drawer);
break;
SetText(newText);
return true;
}
case Nz::Keyboard::Down:
@@ -132,10 +179,10 @@ namespace Ndk
OnTextAreaKeyDown(this, &ignoreDefaultAction);
if (ignoreDefaultAction)
break;
return true;
MoveCursor({0, 1});
break;
return true;
}
case Nz::Keyboard::Left:
@@ -144,10 +191,10 @@ namespace Ndk
OnTextAreaKeyLeft(this, &ignoreDefaultAction);
if (ignoreDefaultAction)
break;
return true;
MoveCursor({-1, 0});
break;
MoveCursor(-1);
return true;
}
case Nz::Keyboard::Right:
@@ -156,10 +203,10 @@ namespace Ndk
OnTextAreaKeyRight(this, &ignoreDefaultAction);
if (ignoreDefaultAction)
break;
return true;
MoveCursor({1, 0});
break;
MoveCursor(1);
return true;
}
case Nz::Keyboard::Up:
@@ -168,42 +215,32 @@ namespace Ndk
OnTextAreaKeyUp(this, &ignoreDefaultAction);
if (ignoreDefaultAction)
break;
return true;
MoveCursor({0, -1});
break;
return true;
}
default:
return false;
}
}
void TextAreaWidget::OnKeyReleased(const Nz::WindowEvent::KeyEvent& key)
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();
SetFocus();
SetCursorPosition(GetHoveredGlyph(float(x), float(y)));
const Padding& padding = GetPadding();
SetCursorPosition(GetHoveredGlyph(float(x - padding.left), float(y - padding.top)));
}
}
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)
@@ -216,19 +253,19 @@ namespace Ndk
bool ignoreDefaultAction = false;
OnTextAreaKeyBackspace(this, &ignoreDefaultAction);
if (ignoreDefaultAction)
std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition);
if (ignoreDefaultAction || cursorGlyph == 0)
break;
const Nz::String& text = m_drawer.GetText();
Nz::String newText;
if (m_cursorGlyph > 1)
newText.Append(text.SubString(0, text.GetCharacterPosition(m_cursorGlyph - 1) - 1));
if (m_cursorGlyph < m_drawer.GetGlyphCount())
newText.Append(text.SubString(text.GetCharacterPosition(m_cursorGlyph)));
if (cursorGlyph > 1)
newText.Append(m_text.SubString(0, m_text.GetCharacterPosition(cursorGlyph - 1) - 1));
MoveCursor({-1, 0});
if (cursorGlyph < m_text.GetLength())
newText.Append(m_text.SubString(m_text.GetCharacterPosition(cursorGlyph)));
MoveCursor(-1);
SetText(newText);
break;
}
@@ -259,15 +296,19 @@ namespace Ndk
void TextAreaWidget::RefreshCursor()
{
if (m_readOnly)
return;
const auto& lineInfo = m_drawer.GetLine(m_cursorPosition.y);
std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition);
std::size_t glyphCount = m_drawer.GetGlyphCount();
float position;
if (glyphCount > 0 && lineInfo.glyphIndex < m_cursorGlyph)
if (glyphCount > 0 && lineInfo.glyphIndex < cursorGlyph)
{
const auto& glyph = m_drawer.GetGlyph(std::min(m_cursorGlyph, glyphCount - 1));
const auto& glyph = m_drawer.GetGlyph(std::min(cursorGlyph, glyphCount - 1));
position = glyph.bounds.x;
if (m_cursorGlyph >= glyphCount)
if (cursorGlyph >= glyphCount)
position += glyph.bounds.width;
}
else
@@ -277,4 +318,23 @@ namespace Ndk
m_cursorEntity->GetComponent<NodeComponent>().SetPosition(contentOrigin.x + position, contentOrigin.y + lineInfo.bounds.y);
}
void TextAreaWidget::UpdateDisplayText()
{
switch (m_echoMode)
{
case EchoMode_Normal:
m_drawer.SetText(m_text);
break;
case EchoMode_Password:
case EchoMode_PasswordExceptLast:
m_drawer.SetText(Nz::String(m_text.GetLength(), '*'));
break;
}
m_textSprite->Update(m_drawer);
SetCursorPosition(m_cursorPosition); //< Refresh cursor position (prevent it from being outside of the text)
}
}

View File

@@ -1,8 +1,9 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Development Kit"
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
#include <NDK/World.hpp>
#include <Nazara/Core/Clock.hpp>
#include <Nazara/Core/Error.hpp>
#include <NDK/BaseComponent.hpp>
#include <NDK/Systems/PhysicsSystem2D.hpp>
@@ -61,11 +62,14 @@ namespace Ndk
{
EntityId id;
EntityBlock* entBlock;
if (!m_freeIdList.empty())
std::size_t freeEntityId = m_freeEntityIds.FindFirst();
if (freeEntityId != m_freeEntityIds.npos)
{
// We get an identifier
id = m_freeIdList.back();
m_freeIdList.pop_back();
m_freeEntityIds.Reset(freeEntityId); //< Remove id from free entity id
id = static_cast<EntityId>(freeEntityId);
entBlock = &m_entities[id];
entBlock->handle.Reset(&entBlock->entity); //< Reset handle (as it was reset when entity got destroyed)
@@ -81,7 +85,7 @@ namespace Ndk
{
NazaraAssert(m_waitingEntities.empty(), "There should be no waiting entities if space is available in main container");
m_entities.push_back(Entity(this, id)); //< We can't use emplace_back due to the scope
m_entities.emplace_back(Entity(this, id)); //< We can't make our vector create the entity due to the scope
entBlock = &m_entities.back();
}
else
@@ -115,15 +119,20 @@ namespace Ndk
void World::Clear() noexcept
{
// First, destruction of entities, then handles
// This is made to avoid that handle warn uselessly entities before their destruction
m_entities.clear();
// Destroy every valid entity first, to ensure entities are still accessible by ID while being destroyed
for (EntityBlock* entBlock : m_entityBlocks)
{
if (entBlock->entity.IsValid())
entBlock->entity.Destroy();
}
m_entityBlocks.clear();
m_freeIdList.clear();
m_entities.clear();
m_waitingEntities.clear();
m_aliveEntities.Clear();
m_dirtyEntities.Clear();
m_freeEntityIds.Clear();
m_killedEntities.Clear();
}
@@ -133,12 +142,11 @@ namespace Ndk
*
* \param id Identifier of the entity
*
* \remark Produces a NazaraError if the entity to clone does not exist
* \remark Cloning a disabled entity will produce an enabled clone
*/
const EntityHandle& World::CloneEntity(EntityId id)
{
EntityHandle original = GetEntity(id);
const EntityHandle& original = GetEntity(id);
if (!original)
{
NazaraError("Invalid entity ID");
@@ -146,6 +154,8 @@ namespace Ndk
}
const EntityHandle& clone = CreateEntity();
if (!original->IsEnabled())
clone->Disable();
const Nz::Bitset<>& componentBits = original->GetComponentBits();
for (std::size_t i = componentBits.FindFirst(); i != componentBits.npos; i = componentBits.FindNext(i))
@@ -154,16 +164,27 @@ namespace Ndk
clone->AddComponent(std::move(component));
}
clone->Enable();
return clone;
}
/*!
* \brief Updates the world
* \brief Refreshes the world
*
* \remark Produces a NazaraAssert if an entity is invalid
* This function will perform all pending operations in the following order:
* - Reorder systems according to their update order if needed
* - Moving newly created entities (whose which allocate never-used id) data and handles to normal entity list, this will invalidate references to world EntityHandle
* - Destroying dead entities and allowing their ids to be used by newly created entities
* - Update dirty entities, destroying their removed components and filtering them along systems
*
* \remark This is called automatically by Update and you most likely won't need to call it yourself
* \remark Calling this outside of Update will not increase the profiler values
*
* \see GetProfilerData
* \see Update
*/
void World::Update()
void World::Refresh()
{
if (!m_orderedSystemsUpdated)
ReorderSystems();
@@ -195,7 +216,7 @@ namespace Ndk
entity->Destroy();
// Send back the identifier of the entity to the free queue
m_freeIdList.push_back(entity->GetId());
m_freeEntityIds.UnboundedSet(entity->GetId());
}
m_killedEntities.Reset();
@@ -240,6 +261,43 @@ namespace Ndk
m_dirtyEntities.Reset();
}
/*!
* \brief Updates the world
* \param elapsedTime Delta time used for the update
*
* This function Refreshes the world and calls the Update function of every active system part of it with the elapsedTime value.
* It also increase the profiler data with the elapsed time passed in Refresh and every system update.
*/
void World::Update(float elapsedTime)
{
if (m_isProfilerEnabled)
{
Nz::UInt64 t1 = Nz::GetElapsedMicroseconds();
Refresh();
Nz::UInt64 t2 = Nz::GetElapsedMicroseconds();
m_profilerData.refreshTime += t2 - t1;
for (auto& systemPtr : m_orderedSystems)
{
systemPtr->Update(elapsedTime);
Nz::UInt64 t3 = Nz::GetElapsedMicroseconds();
m_profilerData.updateTime[systemPtr->GetIndex()] += t3 - t2;
t2 = t3;
}
m_profilerData.updateCount++;
}
else
{
Refresh();
for (auto& systemPtr : m_orderedSystems)
systemPtr->Update(elapsedTime);
}
}
void World::ReorderSystems()
{
m_orderedSystems.clear();