Merge branch 'master' into vulkan
This commit is contained in:
commit
8be2342f25
|
|
@ -67,6 +67,9 @@ build/**/*.nativecodeanalysis.all.xml
|
|||
build/**/*.nativecodeanalysis.xml
|
||||
build/**/*.VC.opendb
|
||||
build/**/*.VC.db*
|
||||
build/**/*.json
|
||||
build/**/*.sqlite
|
||||
build/**/*.FileListAbsolute.txt
|
||||
|
||||
# Compiled Object files
|
||||
build/**/*.slo
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
Nazara Engine was originally created in early 2012.
|
||||
It follows a complete overhaul of a previous project in order to offer more features and modularity.
|
||||
|
||||
Jérôme "Lynix" Leclercq - main developper (lynix680@gmail.com)
|
||||
Full Cycle Games - sponsor and contributor since January 2017.
|
||||
174
ChangeLog.md
174
ChangeLog.md
|
|
@ -17,6 +17,11 @@ Miscellaneous:
|
|||
- NDEBUG is now defined in Release
|
||||
- Replaced typedefs keywords with modern using keywords
|
||||
- When supported, projects are now parts of a virtual "workspace group" according to their kind
|
||||
- Fixed .dll copy when building Nazara occuring on Linux when targeting Windows (MinGW)
|
||||
- ⚠ Appveyor nightlies are now compiled with VS2017
|
||||
- Set libraries' rpath to current folder (.)
|
||||
- Add ReleaseWithDebug target
|
||||
- ⚠ **Default font has been changed from Cabin to OpenSans**
|
||||
|
||||
Nazara Engine:
|
||||
- VertexMapper:GetComponentPtr no longer throw an error if component is disabled or incompatible with template type, instead a null pointer is returned.
|
||||
|
|
@ -52,7 +57,7 @@ Nazara Engine:
|
|||
- Fix RigidBody3D copy constructor not copying all physics states (angular/linear damping/velocity, mass center, position and rotation)
|
||||
- Add RigidBody3D simulation control (via EnableSimulation and IsSimulationEnabled), which allows to disable physics and collisions at will.
|
||||
- Fix some uninitialized values (found by Valgrind) in Network module
|
||||
- Fix possible infinite recursion when outputting a Thread::Id object
|
||||
- Fix possible infinite recursion when outputting a Thread::Id object
|
||||
- ⚠️ Replaced implicit conversion from a Nz::String to a std::string by an explicit method ToStdString()
|
||||
- Fix LuaInstance movement constructor/assignment operator which was corrupting Lua memory
|
||||
- Fix potential bug on SocketImpl::Connect (used by TcpClient::Connect) on POSIX platforms
|
||||
|
|
@ -107,7 +112,9 @@ Nazara Engine:
|
|||
- Added AbstractViewer::Project and AbstractViewer::Unproject methods
|
||||
- Added AbstractViewer::ProjectDepth method
|
||||
- Fixed SocketPoller not be able to recover from some errors (like invalid sockets and such)
|
||||
- ⚠️ Replaced currentBitPos and currentByte fields by [read|write][BitPos][Byte] to handle properly bit reading/writing.
|
||||
- Add LuaImplQuery implementation for std::vector
|
||||
- Fixed LuaState::PushGlobal & LuaState::PushField to copy the object before moving it
|
||||
- ⚠️ Replaced currentBitPos and currentByte fields by [read|write][BitPos][Byte] to handle properly bit reading/writing.
|
||||
- InstancedRenderable::SetMaterial methods are now public.
|
||||
- Fixed Model copy constructor not copying materials
|
||||
- ⚠️ Added InstancedRenderable::Clone() method
|
||||
|
|
@ -115,6 +122,106 @@ Nazara Engine:
|
|||
- ⚠️ SocketPoller::Wait now returns the number of socket marked as ready, and takes an additional optional parameter allowing to query the last error.
|
||||
- SocketPoller will now silently ignore "interrupt errors"
|
||||
- Added RigidBody2D::ClosestPointQuery
|
||||
- Fix Sprite copy constructor not copying corner colors
|
||||
- Added ObjectLibrary::Clear method
|
||||
- ⚠️ StackArray class and macro was moved from Core/MemoryHelper.hpp to Core/StackArray.hpp
|
||||
- ⚠️ Renamed NazaraStackAllocation[NoInit] macro to NazaraStackArray[NoInit]
|
||||
- Added StackVector class
|
||||
- ⚠️ Removed Vector[2|3]::Distancef method and made Distance method templated
|
||||
- Added Vector2::Distance static method
|
||||
- ⚠️ Fixed compilation errors on MSVC with flag /permissive- on CullingList class
|
||||
- Added LuaImplQueryArg & LuaImplReplyVal functions for Vector[2|3]<int>
|
||||
- Fixed bug in ENet implementation causing legit reliable packets to be dropped on sequence number overflow
|
||||
- Fixed bug where index wouldn't be used in String::FindLast and String::FindWord
|
||||
- Physics 2D contact callbacks now include an arbiter allowing to query/set parameters about the collision
|
||||
- Added movement with Ctrl in TextAreaWidget
|
||||
- Added Unicode Data downloader/parser
|
||||
- Integrated Unicode Data
|
||||
- Added CullingList::FillWithAllEntries method
|
||||
- Fixed ObjectHandle movement sometimes not resetting its internal pointer
|
||||
- Added BoxCollider2D::GetRadius
|
||||
- Added CircleCollider2D::GetOffset
|
||||
- Added ConvexCollider2D::GetVertices
|
||||
- Added SegmentCollider2D::GetThickness
|
||||
- Fixed vertices generation/render queue submit when using multiples materials on a Tilemap
|
||||
- It is now possible to prevent CompoundCollider2D to override individual colliders properties
|
||||
- Fixed TcpClient::WaitForConnected possible failure (although connected) on Windows/Linux
|
||||
- CullingList now handles box tests
|
||||
- ⚠️ CullingList now handles full and partial visibility testing
|
||||
- Added math class Angle, capable of handling both degrees and radians angles and converting them to euler angles/quaternions to improve 2D interface.
|
||||
- ⚠️ AbstractSocket::OnStateChange has been replaced by OnStateChanged, which is now called after state has been changed (with oldState and newState as parameters).
|
||||
- ⚠️ TcpClient::WaitForconnected now returns the new socket state.
|
||||
- Added TcpClient::PollForConnected
|
||||
- ⚠️ Use of the new Angle class instead of floating point angle
|
||||
- It is now possible to set elasticity/friction/surface bodies of 2D colliders and change it at runtime on RigidBody2D
|
||||
- ObjectHandle were remade and should be way more optimized now
|
||||
- Added ENetHost and ENetPeer accessor to total packet/data received/sent/lost
|
||||
- ⚠ **Changed the way resources were Loaded, almost every LoadFromX and OpenFromX methods are now static and create the object themselves.**
|
||||
- ⚠ SoundStream is now responsible for loaders instead of Music, and is now threadsafe (you can now load a stream only once and play it multiple times at the same time)
|
||||
- Added LuaState::RawEqual
|
||||
- Fixed LuaCoroutine movement assignation operator
|
||||
- Added Arbiter2D::GetBodies
|
||||
- Added RigidBody2D::ForEachArbiter
|
||||
- Added possibility to change the RigidBody2D velocity function called by the physics engine
|
||||
- Fixed MouseButtonEvent and MouseMoveEvent mouse absolute position being unsigned (now signed)
|
||||
- Fixed Window::SetCursor changing cursor even if window was in foreground on Windows
|
||||
- Fixed SystemCursor_Move not showing up on Windows
|
||||
- Fixed Window movement constructor/assignation operator
|
||||
- Window::PushEvent is now public (useful for pushing external events ie. when using Qt or similar framework controlling window)
|
||||
- Fixed TileMap not rendering the right materials if it had no tile using some materials in-between
|
||||
- Added Vector[2|3|4](u)i64 typedefs
|
||||
- Fixed missing static Vector4::DotProduct implementation
|
||||
- ⚠ **By default, Nazara now computes the mass center of all 2D physics object when calling SetGeom**
|
||||
- ⚠ Added Collider2D::ComputeCenterOfMass
|
||||
- Signal now implement a copy constructor and copy assignation operator for convenience
|
||||
- Fixed ENet UnreliableFragment packets sent as Unreliable (and such being incomplete upon reception)
|
||||
- ENet DisconnectLater now reflects libenet behavior (and is waiting for unreliable commands to be sent before disconnecting for good)
|
||||
- ⚠ Collider3D::ForEachPolygon now takes a void(Vector3f\*, std::size_t) callback (instead of void(float\*, std::size_t))
|
||||
- Added Collider2D::ForEachPolygon method
|
||||
- Added RigidBody::[Get|Set]PositionOffset allowing set an offset between body logic position and body physics position (center of mass position)
|
||||
- ⚠ Default TextureSampler WrapMode is now Clamp (instead of Repeat)
|
||||
- Fixed StateMachine ignoring transitions made in Enter/Leave events of states
|
||||
- Fixed Material::Configure resetting textures
|
||||
- ⚠ Renamed TextStyleFlags enum to TextStyle, introduced Flags specialization of TextStyle as TextStyleFlags
|
||||
- ⚠ Font, FontData and SimpleTextDrawer now use a proper TextStyleFlags instead of a UInt32
|
||||
- Almost all Math algorithms are now constexpr
|
||||
- PhysWorld2D: Fixed callbacks not properly replacing each others when registering twice with the same collisionId (pair)
|
||||
- ⚠ **Font, FontData and SimpleTextDrawer now supports text outlining.**
|
||||
- Fixed TextSprite not handling multiple textures well
|
||||
- ⚠ TextSprite will now use multiple render layers by itself (the current one and the one right before, ex: [-1, 0] if base layer is 0) if you use text outlines.
|
||||
- ⚠ SimpleTextDrawer no longer supports faux bold rendering
|
||||
- Added PhysWorld2D::[RaycastQuery, RegionQuery] overloads taking a callback
|
||||
- Added x and y mouse position to MouseWheelEvent
|
||||
- Added SimpleTextDrawer::[Get|Set]MaxLineWidth (which does line wrap)
|
||||
- TypeTag helper struct now includes a Type using
|
||||
- GuillotineBinPack::Insert overload taking multiple rectangles no longer does a heap allocation
|
||||
- StackArray and StackVector now have a default constructor initializing them with no size/capacity
|
||||
- StackArray and StackVector are now movable
|
||||
- Fixed RigidBody2D::Copy not copying kinematic/dynamic/static status
|
||||
- Fixed out-of-bounds access in LuaInstance::LoadLibraries
|
||||
- Add Flags<E>::Clear(Flags) helper method, to clear one or more flags.
|
||||
- Add Flags<E>::Clear() helper method, to reset flags
|
||||
- Add Flags<E>::Set(Flags) helper method, to enable flags
|
||||
- ⚠ Constraint2D are no longer managed by references and are now handled objects
|
||||
- ⚠ Removed all Set methods from math classes taking their own type (e.g. Box::Set(Box))
|
||||
- Added Matrix4::Decompose
|
||||
- ⚠ Node::Get[Position|Rotation|Scale] now defaults to local space
|
||||
- Fixed Node rotation when using a negative scale
|
||||
- Added HandledObject::OnHandledObjectDestruction signal
|
||||
- Added physics function to control sleeping behavior
|
||||
- String::Number is now locale-independent
|
||||
- Added ENetPeer::GetTotalByte[Received|Sent]
|
||||
- Added ENetPeer::GetTotalPacketSent
|
||||
- ⚠ ENetHost::GetTotalReceivedPackets now returns the number of commands received (instead of the number of UDP packets received)
|
||||
- Added EmptyStream class, useful to measure how many bytes some writing operations will take
|
||||
- SegmentCollider2D: Add support for neighbors (aka "ghost vertices"), allowing to prevent seams collisions
|
||||
- ⚠ OBJLoader flips UV by default, fixing a lot of models UV
|
||||
- On Windows, Thread::Set(Current)Name now uses `SetThreadDescription` Win32 function if possible instead of triggering a debugger exception. MinGW builds will use this if available too.
|
||||
- ⚠ Removed Texture(const Image\*) constructor, use Texture::LoadFromImage instead
|
||||
- ⚠ TextDrawers now use floating-point internally and to exposes their Bounds (AbstractTextDrawer::GetBounds() now returns a Rectf)
|
||||
- Added [SimpleTextDrawer|RichTextDrawer] character and line spacing offset properties
|
||||
- Added ENetHost::AllowsIncomingConnections(bool) to disable/re-enable server peers connection
|
||||
- Added ByteArrayPool and PoolByteStream classes
|
||||
|
||||
Nazara Development Kit:
|
||||
- Added ImageWidget (#139)
|
||||
|
|
@ -158,14 +265,65 @@ Nazara Development Kit:
|
|||
- Fix GraphicsComponent bounding volume not taking local matrix in account
|
||||
- ⚠️ Rewrote all render queue system, which should be more efficient, take scissor box into account
|
||||
- ⚠️ All widgets are now bound to a scissor box when rendering
|
||||
- Add DebugComponent (a component able to show aabb/obb/collision mesh)
|
||||
- Add DebugComponent (a component able to show aabb/obb/collision mesh 2D and 3D)
|
||||
- ⚠️ TextAreaWidget now support text selection (WIP)
|
||||
- ⚠️ TextAreaWidget::GetHoveredGlyph now returns a two-dimensional position instead of a single glyph position
|
||||
- Fixed Entity::OnEntityDestruction signal not being properly moved and thus not being called.
|
||||
- Fixed EntityOwner move assignment which was losing entity ownership
|
||||
- Add GraphicsComponent:ForEachRenderable method
|
||||
- Added GraphicsComponent:ForEachRenderable method
|
||||
- Fixed GraphicsComponent reflective material count which was not initialized
|
||||
- Added PhysicsComponent2D::ClosestPointQuery
|
||||
- Fixed GraphicsComponent copy constructor not copying scissor rect
|
||||
- Force parent parameter to be present in widgets constructor
|
||||
- Added the possibility to write only specific characters with a predicate in TextAreaWidget
|
||||
- Enable write of Tab character in TextAreaWidget
|
||||
- It is now possible to disable object culling in the RenderSystem
|
||||
- Make Nz::PhysWorld2D& Ndk::PhysicsSystem2D::GetWorld private and rename it into GetPhysWorld
|
||||
- Make Ndk::PhysicsSystem2D an interface of Nz::PhysWorld2D
|
||||
- ⚠️ GraphicsComponent no longer has a BoundingVolume, it instead has only an AABB with its attached InstancedRenderable getting a BoundingVolume of their own, improving culling possibilities.
|
||||
- RenderSystem now does cull InstancedRenderables attached to a GraphicsComponent, improving performance.
|
||||
- ⚠️ Widgets have been reworked and no longer have padding, but instead have preferred, maximum and minimum size.
|
||||
- ⚠️ BaseWidget::SetSize has been renamed to BaseWidget::Resize
|
||||
- Added BaseWidget::ForEachWidgetChild
|
||||
- Added experimental BoxLayout class
|
||||
- RenderSystem now resolve skinning before render
|
||||
- EntityOwner constructor taking a Entity* is no longer explicit
|
||||
- PhysicsComponent2D now allows massless bodies (zero mass)
|
||||
- ⚠️ Use of the new Angle class instead of floating point angle
|
||||
- Added EntityOwner::Release
|
||||
- Add missing `recomputeMoment` parameter to PhysicsComponent2D::SetMass
|
||||
- Added possibility of disabling synchronization between PhysicsComponent2D and NodeComponent
|
||||
- Fixed GraphicsComponent not invalidating render queue on material change (causing crashes or visual errors)
|
||||
- Added CollisionComponent2D::SetGeomOffset and CollisionComponent2D::Recenter
|
||||
- Added LifetimeComponent and LifetimeSystem
|
||||
- Fixed a subtle bug regarding entities invalidation and kill (ex: if an entity #2 kills entity #1 during Entity::Destroy callbacks, entity #1 will survive destruction).
|
||||
- Added PhysicsSystem2D::[RaycastQuery, RegionQuery] overloads taking a callback
|
||||
- Added TextAreaWidget support for outline
|
||||
- Fixed possible crash when disabling BaseWidget background
|
||||
- Added BaseWidget::OnMouseWheelMoved
|
||||
- Added Entity::OnEntity[Disabled|Enabled] signals
|
||||
- Added BaseWidget::SetParent
|
||||
- BaseWidget::Show will no longer show entities disabled by the widget
|
||||
- BaseWidget now has a rendering rect property (allowing to tell a widget what part of it will be rendered)
|
||||
- Added ScrollAreaWidget
|
||||
- Console has been remade with widgets (allowing to scroll back history, select text, etc.)
|
||||
- Added TextAreaWidget line wrap option
|
||||
- TextAreaWidget will now shift the text to the left/right in order to keep the cursor visible
|
||||
- Added TextAreaWidget::[Get|Set]TextFont
|
||||
- ⚠️ TextAreaWidget::OnTextAreaCursorMove signal now uses a Vector2ui* position as its second argument (instead of a std::size_t*)
|
||||
- Added TextAreaWidget::OnTextAreaSelection
|
||||
- ⚠️ Console class is no longer bound to a LuaState and now has a OnCommand signal
|
||||
- ⚠️ Made AbstractTextAreaWidget which is inherited by TextAreaWidget
|
||||
- ⚠️ Added RichTextAreaWidget
|
||||
- ⚠️ Console now supports text color in history
|
||||
- Added World::CloneEntity overload taking an EntityHandle const reference, allowing to copy entities from other worlds
|
||||
- Fixed PhysicsComponent2D copy not copying physics attributes
|
||||
- Added Entity::DropComponent which detaches a component without necessarily destroying it
|
||||
- ⚠ ConstraintComponent2D has been reworked to handle entity destruction and remove constraints at will
|
||||
- Fixed crash when pressing up/down key with no history in the console
|
||||
- (Rich)TextAreaWidget text style is now alterable
|
||||
- Added CameraComponent::SetProjectionScale
|
||||
- Added (Rich)TextAreaWidget character and line spacing offset properties
|
||||
|
||||
# 0.4:
|
||||
|
||||
|
|
@ -253,8 +411,8 @@ Nazara Engine:
|
|||
- Added [Nz::TcpClient::SendMultiple](https://nazara.digitalpulsesoftware.net/doc/class_nz_1_1_tcp_client.html#a495c32beb46ed9192699a3b82d358035) method, allowing to send multiple buffers at once.
|
||||
- Added [Nz::PlacementDestroy](https://nazara.digitalpulsesoftware.net/doc/namespace_nz.html#a27c8667def991fc896c5beff3e62668a). (ea985fa76586762f008e4054938db3234eeaf0cb)
|
||||
- Added [Nz::String::Format](https://nazara.digitalpulsesoftware.net/doc/class_nz_1_1_string.html#a4b699982e7f9ea38f6d44b43ac1e2040) and [Nz::String::FormatVA](https://nazara.digitalpulsesoftware.net/doc/class_nz_1_1_string.html#abe0fcbce11224b157ac756b60e8dee92) static methods. (cc6e4127dc6c61799a64404770992cef0804ad34).
|
||||
- Added [Nz::ParticleGroup::GetBuffer](https://nazara.digitalpulsesoftware.net/doc/class_nz_1_1_particle_mapper.html#aefe1b251efc8c9b8668842275561be0c) method. (4dc85789b59e50d964c83321dbd4b6485c04bef6)
|
||||
- Added Nz::ParticleMapper::GetPointer method. (1f4e6c2d1594b7bb9dd6f4ea5480fdd16cf5f208)
|
||||
- Added [Nz::ParticleGroup::GetBuffer](https://nazara.digitalpulsesoftware.net/doc/class_nz_1_1_particle_mapper.html#aefe1b251efc8c9b8668842275561be0c) method. (4dc85789b59e50d964c83321dbd4b6485c04bef6)
|
||||
- Added Nz::ParticleMapper::GetPointer method. (1f4e6c2d1594b7bb9dd6f4ea5480fdd16cf5f208)
|
||||
- ⚠️ Structures provied by ParticleStruct header now have a float life. (472d964d587d906764ad1e05bfcc9ab1bf979483)
|
||||
- Fixed scale property of Nz::TextSprite not affecting its bounding volume. (52b29bac775823294c4ad7de70f4dc3f4adfa743)
|
||||
- ⚠️ Nz:MeshParams::flipUVs has been replaced by texCoordOffset and texCoordScale. (a1a7d908adc060fd7a43491c903dfe3b501d98e5)
|
||||
|
|
@ -281,7 +439,7 @@ Nazara Engine:
|
|||
- All noises classes now uses std::mt19937 as a random number generator, to ensure the same results on every machine. (1f5ea9839016964c173d919263827dee69ecb65d)
|
||||
|
||||
Nazara Development Kit:
|
||||
- **Added basic widgets**. (c8a12083b3133e946bf60dd060331a4b4631f8d8)
|
||||
- **Added basic widgets**. (c8a12083b3133e946bf60dd060331a4b4631f8d8)
|
||||
- VelocitySystem will no longer affect entities with PhysicsComponent2D. (a6853234412c744cdcb28344f02f7b0c92704d77)
|
||||
- Fixed EulerAngles constructor in Lua. (d55149a0a70f6230b6f1c3fb50e37dc82a2feb9f)
|
||||
- Fixed Component::OnDetached not being called on entity destruction. (5b777eb4853639d7aeb232ca46d17f0d432f47ca)
|
||||
|
|
@ -292,7 +450,7 @@ Nazara Engine:
|
|||
|
||||
Nazara Engine:
|
||||
- Nazara binaries are now compiled with Run-Time Type-Information. (a70acdc8f44010627a65282fd3099202116d3e13)
|
||||
- Nazara demos are now compiled with relative dependencies on Linux.
|
||||
- Nazara demos are now compiled with relative dependencies on Linux.
|
||||
(d6fbb4c408d48c4a768fad7b43460c76a0df1777)
|
||||
- Added [**Nz::BitCount**](https://nazara.digitalpulsesoftware.net/doc/group__core.html#ga6bfbcff78eb6cfbe3ddaedcfc8c04196) function. (82e31a3ec8449da6618f41690164c2e1d883edb4)
|
||||
- Added [**Nz::Bitset::AppendBits**](https://nazara.digitalpulsesoftware.net/doc/class_nz_1_1_bitset.html#a5ca8f365006c86d6d699d02471904f7e) method. (b018a400499a2356c4455a40d9f6a6c12b3cb36b)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
# Installation
|
||||
|
||||
> **Notice**: For french speakers, a more detailed explanation of the instructions is provided here: [Instructions pour compiler](wiki/(FR)-Compiler-le-moteur).
|
||||
|
||||
The first step to using the engine is to recover it. This can currently be done in two ways:
|
||||
1) This can be don either from the original github (only the development is continuously evolving):
|
||||
```git clone https://github.com/DigitalPulseSoftware/NazaraEngine.git```
|
||||
2) Or by downloading a [zip file](https://github.com/DigitalPulseSoftware/NazaraEngine/archive/master.zip) containing the entire source code of the engine.
|
||||
|
||||
All you have to do is go to the "build/" folder. The compilation system uses [premake](https://premake.github.io/) to generate build systems.
|
||||
|
||||
## Windows
|
||||
For Windows users, they can directly use ".bat" files such as: "Build_VS2017.bat". It will generate a solution "NazaraEngine.sln" ready to use that you can directly build to produce the libs or execute the samples.
|
||||
|
||||
## Linux
|
||||
|
||||
Linux users, can type: "./premake5-linux64 gmake" or with the additional argument "--cc=clang" to configure the C++ compiler used.
|
||||
|
||||
Some additional libraries will be required for compilation depending on the modules used:
|
||||
|
||||
#### Audio module (OpenAL and libsndfile)
|
||||
|
||||
- with apt: `sudo apt-get install libopenal-dev libsndfile1-dev`
|
||||
- with pacman: `sudo pacman -S openal libsndfile`
|
||||
|
||||
#### Platform module (Freetype):
|
||||
|
||||
- with apt: `sudo apt-get install libfreetype6-dev`
|
||||
- with pacman: `sudo pacman -S freetype2`
|
||||
|
||||
#### Utility module (XCB + X11):
|
||||
|
||||
- with apt: `sudo apt-get install libxcb-cursor-dev libxcb-ewmh-dev libxcb-randr0-dev libxcb-icccm4-dev libxcb-keysyms1-dev libx11-dev`
|
||||
- with pacman: `sudo pacman -S libxcb libx11`
|
||||
|
||||
#### OpenGL renderer module:
|
||||
|
||||
- with apt: `sudo apt-get install mesa-common-dev libgl1-mesa-dev`
|
||||
- with pacman: `sudo pacman -S mesa`
|
||||
|
||||
#### Plugin Assimp:
|
||||
|
||||
- with apt: `sudo apt-get install libassimp-dev`
|
||||
- with pacman: `sudo pacman -S assimp`
|
||||
|
||||
#### The one line command to install everything is:
|
||||
|
||||
- with apt: `sudo apt-get install libopenal-dev libsndfile1-dev libfreetype6-dev libxcb-cursor-dev libxcb-ewmh-dev libxcb-randr0-dev libxcb-icccm4-dev libxcb-keysyms1-dev libx11-dev mesa-common-dev libgl1-mesa-dev libassimp-dev`
|
||||
- with pacman: `sudo pacman -S openal libsndfile freetype2 libxcb libx11 mesa assimp`
|
||||
|
||||
## Test
|
||||
|
||||
One should now be able to execute the samples provided in the folder "NazaraEngine/examples/bin/" or the unit tests within "NazaraEngine/tests/".
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
Copyright (c) 2011, Pablo Impallari (www.impallari.com|impallari@gmail.com),
|
||||
Copyright (c) 2011, Igino Marini. (www.ikern.com|mail@iginomarini.com),
|
||||
with Reserved Font Name Cabin.
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
|
@ -15,6 +15,7 @@
|
|||
#include <set>
|
||||
|
||||
#ifndef NDK_SERVER
|
||||
#include <NDK/Canvas.hpp>
|
||||
#include <NDK/Console.hpp>
|
||||
#include <Nazara/Core/Log.hpp>
|
||||
#include <Nazara/Lua/LuaInstance.hpp>
|
||||
|
|
@ -81,7 +82,7 @@ namespace Ndk
|
|||
#ifndef NDK_SERVER
|
||||
struct ConsoleOverlay
|
||||
{
|
||||
std::unique_ptr<Console> console;
|
||||
Console* console;
|
||||
Nz::LuaInstance lua;
|
||||
|
||||
NazaraSlot(Nz::EventHandler, OnEvent, eventSlot);
|
||||
|
|
@ -114,10 +115,11 @@ namespace Ndk
|
|||
Nz::RenderTarget* renderTarget;
|
||||
std::unique_ptr<Nz::Window> window;
|
||||
std::unique_ptr<ConsoleOverlay> console;
|
||||
std::unique_ptr<Canvas> canvas;
|
||||
std::unique_ptr<FPSCounterOverlay> fpsCounter;
|
||||
std::unique_ptr<World> overlayWorld;
|
||||
};
|
||||
|
||||
|
||||
void SetupConsole(WindowInfo& info);
|
||||
void SetupFPSCounter(WindowInfo& info);
|
||||
void SetupOverlay(WindowInfo& info);
|
||||
|
|
|
|||
|
|
@ -112,7 +112,6 @@ namespace Ndk
|
|||
}
|
||||
|
||||
m_overlayFlags |= OverlayFlags_Console;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,8 +26,6 @@ namespace Ndk
|
|||
friend Canvas;
|
||||
|
||||
public:
|
||||
struct Padding;
|
||||
|
||||
BaseWidget(BaseWidget* parent);
|
||||
BaseWidget(const BaseWidget&) = delete;
|
||||
BaseWidget(BaseWidget&&) = delete;
|
||||
|
|
@ -41,54 +39,79 @@ namespace Ndk
|
|||
inline void CenterVertical();
|
||||
|
||||
void ClearFocus();
|
||||
inline void ClearRenderingRect();
|
||||
|
||||
void Destroy();
|
||||
|
||||
void EnableBackground(bool enable);
|
||||
|
||||
template<typename F> void ForEachWidgetChild(F iterator);
|
||||
template<typename F> void ForEachWidgetChild(F iterator) const;
|
||||
|
||||
//virtual BaseWidget* Clone() const = 0;
|
||||
|
||||
inline const Nz::Color& GetBackgroundColor() const;
|
||||
inline Canvas* GetCanvas();
|
||||
inline Nz::SystemCursor GetCursor() const;
|
||||
inline const Padding& GetPadding() const;
|
||||
inline Nz::Vector2f GetContentOrigin() const;
|
||||
inline const Nz::Vector2f& GetContentSize() const;
|
||||
inline float GetHeight() const;
|
||||
|
||||
inline float GetMaximumHeight() const;
|
||||
inline Nz::Vector2f GetMaximumSize() const;
|
||||
inline float GetMaximumWidth() const;
|
||||
|
||||
inline float GetMinimumHeight() const;
|
||||
inline Nz::Vector2f GetMinimumSize() const;
|
||||
inline float GetMinimumWidth() const;
|
||||
|
||||
inline float GetPreferredHeight() const;
|
||||
inline Nz::Vector2f GetPreferredSize() const;
|
||||
inline float GetPreferredWidth() const;
|
||||
|
||||
inline const Nz::Rectf& GetRenderingRect() const;
|
||||
|
||||
inline Nz::Vector2f GetSize() const;
|
||||
inline float GetWidth() const;
|
||||
inline std::size_t GetWidgetChildCount() const;
|
||||
|
||||
bool HasFocus() const;
|
||||
|
||||
inline bool IsVisible() const;
|
||||
|
||||
virtual void ResizeToContent() = 0;
|
||||
void Resize(const Nz::Vector2f& size);
|
||||
|
||||
void SetBackgroundColor(const Nz::Color& color);
|
||||
void SetCursor(Nz::SystemCursor systemCursor);
|
||||
inline void SetContentSize(const Nz::Vector2f& size);
|
||||
void SetFocus();
|
||||
inline void SetPadding(float left, float top, float right, float bottom);
|
||||
void SetSize(const Nz::Vector2f& size);
|
||||
void SetParent(BaseWidget* widget);
|
||||
|
||||
inline void SetFixedHeight(float fixedHeight);
|
||||
inline void SetFixedSize(const Nz::Vector2f& fixedSize);
|
||||
inline void SetFixedWidth(float fixedWidth);
|
||||
|
||||
inline void SetMaximumHeight(float maximumHeight);
|
||||
inline void SetMaximumSize(const Nz::Vector2f& maximumSize);
|
||||
inline void SetMaximumWidth(float maximumWidth);
|
||||
|
||||
inline void SetMinimumHeight(float minimumHeight);
|
||||
inline void SetMinimumSize(const Nz::Vector2f& minimumSize);
|
||||
inline void SetMinimumWidth(float minimumWidth);
|
||||
|
||||
virtual void SetRenderingRect(const Nz::Rectf& renderingRect);
|
||||
|
||||
void Show(bool show = true);
|
||||
|
||||
BaseWidget& operator=(const BaseWidget&) = delete;
|
||||
BaseWidget& operator=(BaseWidget&&) = delete;
|
||||
|
||||
struct Padding
|
||||
{
|
||||
float left;
|
||||
float top;
|
||||
float right;
|
||||
float bottom;
|
||||
};
|
||||
|
||||
protected:
|
||||
const EntityHandle& CreateEntity(bool isContentEntity);
|
||||
const EntityHandle& CreateEntity();
|
||||
void DestroyEntity(Entity* entity);
|
||||
virtual void Layout();
|
||||
|
||||
void InvalidateNode() override;
|
||||
|
||||
Nz::Rectf GetScissorRect() const;
|
||||
|
||||
virtual bool IsFocusable() const;
|
||||
virtual void OnFocusLost();
|
||||
virtual void OnFocusReceived();
|
||||
|
|
@ -98,14 +121,17 @@ namespace Ndk
|
|||
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 OnMouseWheelMoved(int x, int y, float delta);
|
||||
virtual void OnMouseExit();
|
||||
virtual void OnParentResized(const Nz::Vector2f& newSize);
|
||||
virtual void OnTextEntered(char32_t character, bool repeated);
|
||||
|
||||
inline void SetPreferredSize(const Nz::Vector2f& preferredSize);
|
||||
|
||||
private:
|
||||
inline BaseWidget();
|
||||
|
||||
inline void DestroyChild(BaseWidget* widget);
|
||||
void DestroyChild(BaseWidget* widget);
|
||||
void DestroyChildren();
|
||||
inline bool IsRegisteredToCanvas() const;
|
||||
inline void NotifyParentResized(const Nz::Vector2f& newSize);
|
||||
|
|
@ -117,7 +143,10 @@ namespace Ndk
|
|||
struct WidgetEntity
|
||||
{
|
||||
EntityOwner handle;
|
||||
bool isContent;
|
||||
bool isEnabled = true;
|
||||
|
||||
NazaraSlot(Ndk::Entity, OnEntityDisabled, onDisabledSlot);
|
||||
NazaraSlot(Ndk::Entity, OnEntityEnabled, onEnabledSlot);
|
||||
};
|
||||
|
||||
static constexpr std::size_t InvalidCanvasIndex = std::numeric_limits<std::size_t>::max();
|
||||
|
|
@ -127,12 +156,15 @@ namespace Ndk
|
|||
std::vector<std::unique_ptr<BaseWidget>> m_children;
|
||||
Canvas* m_canvas;
|
||||
EntityOwner m_backgroundEntity;
|
||||
Padding m_padding;
|
||||
WorldHandle m_world;
|
||||
Nz::Color m_backgroundColor;
|
||||
Nz::Rectf m_renderingRect;
|
||||
Nz::SpriteRef m_backgroundSprite;
|
||||
Nz::SystemCursor m_cursor;
|
||||
Nz::Vector2f m_contentSize;
|
||||
Nz::Vector2f m_maximumSize;
|
||||
Nz::Vector2f m_minimumSize;
|
||||
Nz::Vector2f m_preferredSize;
|
||||
Nz::Vector2f m_size;
|
||||
BaseWidget* m_widgetParent;
|
||||
bool m_visible;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <NDK/BaseWidget.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Math/Algorithm.hpp>
|
||||
#include <limits>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
|
|
@ -12,12 +13,15 @@ namespace Ndk
|
|||
m_canvasIndex(InvalidCanvasIndex),
|
||||
m_canvas(nullptr),
|
||||
m_backgroundColor(Nz::Color(230, 230, 230, 255)),
|
||||
m_renderingRect(-std::numeric_limits<float>::infinity(), -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity()),
|
||||
m_cursor(Nz::SystemCursor_Default),
|
||||
m_contentSize(50.f, 50.f),
|
||||
m_maximumSize(std::numeric_limits<float>::infinity()),
|
||||
m_minimumSize(0.f),
|
||||
m_preferredSize(-1),
|
||||
m_size(50.f, 50.f),
|
||||
m_widgetParent(nullptr),
|
||||
m_visible(true)
|
||||
{
|
||||
SetPadding(5.f, 5.f, 5.f, 5.f);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
|
|
@ -64,6 +68,25 @@ namespace Ndk
|
|||
SetPosition(GetPosition(Nz::CoordSys_Local).x, (parentSize.y - mySize.y) / 2.f);
|
||||
}
|
||||
|
||||
inline void BaseWidget::ClearRenderingRect()
|
||||
{
|
||||
SetRenderingRect(Nz::Rectf(-std::numeric_limits<float>::infinity(), -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity()));
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
inline void BaseWidget::ForEachWidgetChild(F iterator)
|
||||
{
|
||||
for (const auto& child : m_children)
|
||||
iterator(child.get());
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
inline void BaseWidget::ForEachWidgetChild(F iterator) const
|
||||
{
|
||||
for (const auto& child : m_children)
|
||||
iterator(static_cast<const BaseWidget*>(child.get()));
|
||||
}
|
||||
|
||||
inline const Nz::Color& BaseWidget::GetBackgroundColor() const
|
||||
{
|
||||
return m_backgroundColor;
|
||||
|
|
@ -79,24 +102,74 @@ namespace Ndk
|
|||
return m_cursor;
|
||||
}
|
||||
|
||||
inline const BaseWidget::Padding& BaseWidget::GetPadding() const
|
||||
inline float BaseWidget::GetHeight() const
|
||||
{
|
||||
return m_padding;
|
||||
return m_size.y;
|
||||
}
|
||||
|
||||
inline Nz::Vector2f BaseWidget::GetContentOrigin() const
|
||||
inline float BaseWidget::GetMaximumHeight() const
|
||||
{
|
||||
return { m_padding.left, m_padding.top };
|
||||
return m_maximumSize.y;
|
||||
}
|
||||
|
||||
inline const Nz::Vector2f& BaseWidget::GetContentSize() const
|
||||
inline Nz::Vector2f BaseWidget::GetMaximumSize() const
|
||||
{
|
||||
return m_contentSize;
|
||||
return m_maximumSize;
|
||||
}
|
||||
|
||||
inline float BaseWidget::GetMaximumWidth() const
|
||||
{
|
||||
return m_maximumSize.x;
|
||||
}
|
||||
|
||||
inline float BaseWidget::GetMinimumHeight() const
|
||||
{
|
||||
return m_minimumSize.y;
|
||||
}
|
||||
|
||||
inline Nz::Vector2f BaseWidget::GetMinimumSize() const
|
||||
{
|
||||
return m_minimumSize;
|
||||
}
|
||||
|
||||
inline float BaseWidget::GetMinimumWidth() const
|
||||
{
|
||||
return m_minimumSize.x;
|
||||
}
|
||||
|
||||
inline float BaseWidget::GetPreferredHeight() const
|
||||
{
|
||||
return m_preferredSize.y;
|
||||
}
|
||||
|
||||
inline Nz::Vector2f BaseWidget::GetPreferredSize() const
|
||||
{
|
||||
return m_preferredSize;
|
||||
}
|
||||
|
||||
inline float BaseWidget::GetPreferredWidth() const
|
||||
{
|
||||
return m_preferredSize.x;
|
||||
}
|
||||
|
||||
inline const Nz::Rectf& BaseWidget::GetRenderingRect() const
|
||||
{
|
||||
return m_renderingRect;
|
||||
}
|
||||
|
||||
inline Nz::Vector2f BaseWidget::GetSize() const
|
||||
{
|
||||
return Nz::Vector2f(m_contentSize.x + m_padding.left + m_padding.right, m_contentSize.y + m_padding.top + m_padding.bottom);
|
||||
return Nz::Vector2f(GetWidth(), GetHeight());
|
||||
}
|
||||
|
||||
inline float BaseWidget::GetWidth() const
|
||||
{
|
||||
return m_size.x;
|
||||
}
|
||||
|
||||
inline std::size_t BaseWidget::GetWidgetChildCount() const
|
||||
{
|
||||
return m_children.size();
|
||||
}
|
||||
|
||||
inline bool BaseWidget::IsVisible() const
|
||||
|
|
@ -104,22 +177,79 @@ namespace Ndk
|
|||
return m_visible;
|
||||
}
|
||||
|
||||
inline void BaseWidget::SetContentSize(const Nz::Vector2f& size)
|
||||
inline void BaseWidget::SetFixedHeight(float fixedHeight)
|
||||
{
|
||||
NotifyParentResized(size);
|
||||
m_contentSize = size;
|
||||
|
||||
Layout();
|
||||
SetMaximumHeight(fixedHeight);
|
||||
SetMinimumHeight(fixedHeight);
|
||||
}
|
||||
|
||||
inline void BaseWidget::SetPadding(float left, float top, float right, float bottom)
|
||||
inline void BaseWidget::SetFixedSize(const Nz::Vector2f& fixedSize)
|
||||
{
|
||||
m_padding.left = left;
|
||||
m_padding.top = top;
|
||||
m_padding.bottom = bottom;
|
||||
m_padding.right = right;
|
||||
SetMaximumSize(fixedSize);
|
||||
SetMinimumSize(fixedSize);
|
||||
}
|
||||
|
||||
Layout();
|
||||
inline void BaseWidget::SetFixedWidth(float fixedWidth)
|
||||
{
|
||||
SetMaximumWidth(fixedWidth);
|
||||
SetMinimumWidth(fixedWidth);
|
||||
}
|
||||
|
||||
inline void BaseWidget::SetMaximumHeight(float maximumHeight)
|
||||
{
|
||||
Nz::Vector2f maximumSize = GetMaximumSize();
|
||||
maximumSize.y = maximumHeight;
|
||||
|
||||
SetMaximumSize(maximumSize);
|
||||
}
|
||||
|
||||
inline void BaseWidget::SetMaximumSize(const Nz::Vector2f& maximumSize)
|
||||
{
|
||||
m_maximumSize = maximumSize;
|
||||
|
||||
Nz::Vector2f size = GetSize();
|
||||
if (size.x > m_maximumSize.x || size.y > m_maximumSize.y)
|
||||
Resize(size); //< Will clamp automatically
|
||||
}
|
||||
|
||||
inline void BaseWidget::SetMaximumWidth(float maximumWidth)
|
||||
{
|
||||
Nz::Vector2f maximumSize = GetMaximumSize();
|
||||
maximumSize.x = maximumWidth;
|
||||
|
||||
SetMaximumSize(maximumSize);
|
||||
}
|
||||
|
||||
inline void BaseWidget::SetMinimumHeight(float minimumHeight)
|
||||
{
|
||||
Nz::Vector2f minimumSize = GetMinimumSize();
|
||||
minimumSize.y = minimumHeight;
|
||||
|
||||
SetMinimumSize(minimumSize);
|
||||
}
|
||||
|
||||
inline void BaseWidget::SetMinimumSize(const Nz::Vector2f& minimumSize)
|
||||
{
|
||||
m_minimumSize = minimumSize;
|
||||
|
||||
Nz::Vector2f size = GetSize();
|
||||
if (size.x < m_minimumSize.x || size.y < m_minimumSize.y)
|
||||
Resize(size); //< Will clamp automatically
|
||||
}
|
||||
|
||||
inline void BaseWidget::SetMinimumWidth(float minimumWidth)
|
||||
{
|
||||
Nz::Vector2f minimumSize = GetMinimumSize();
|
||||
minimumSize.x = minimumWidth;
|
||||
|
||||
SetMinimumSize(minimumSize);
|
||||
}
|
||||
|
||||
inline void BaseWidget::SetPreferredSize(const Nz::Vector2f& preferredSize)
|
||||
{
|
||||
m_preferredSize = preferredSize;
|
||||
|
||||
//Resize(m_preferredSize);
|
||||
}
|
||||
|
||||
inline bool BaseWidget::IsRegisteredToCanvas() const
|
||||
|
|
|
|||
|
|
@ -28,11 +28,12 @@ namespace Ndk
|
|||
|
||||
inline const WorldHandle& GetWorld() const;
|
||||
|
||||
void ResizeToContent() override;
|
||||
|
||||
Canvas& operator=(const Canvas&) = delete;
|
||||
Canvas& operator=(Canvas&&) = delete;
|
||||
|
||||
NazaraSignal(OnUnhandledKeyPressed, const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& /*event*/);
|
||||
NazaraSignal(OnUnhandledKeyReleased, const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& /*event*/);
|
||||
|
||||
protected:
|
||||
inline void ClearKeyboardOwner(std::size_t canvasIndex);
|
||||
|
||||
|
|
@ -50,8 +51,9 @@ namespace Ndk
|
|||
private:
|
||||
void OnEventMouseButtonPressed(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::MouseButtonEvent& event);
|
||||
void OnEventMouseButtonRelease(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::MouseButtonEvent& event);
|
||||
void OnEventMouseMoved(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::MouseMoveEvent& event);
|
||||
void OnEventMouseLeft(const Nz::EventHandler* eventHandler);
|
||||
void OnEventMouseMoved(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::MouseMoveEvent& event);
|
||||
void OnEventMouseWheelMoved(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::MouseWheelEvent& event);
|
||||
void OnEventKeyPressed(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::KeyEvent& event);
|
||||
void OnEventKeyReleased(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::KeyEvent& event);
|
||||
void OnEventTextEntered(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::TextEvent& event);
|
||||
|
|
@ -67,8 +69,9 @@ namespace Ndk
|
|||
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, OnMouseMoved, m_mouseMovedSlot);
|
||||
NazaraSlot(Nz::EventHandler, OnMouseWheelMoved, m_mouseWheelMovedSlot);
|
||||
NazaraSlot(Nz::EventHandler, OnTextEntered, m_textEnteredSlot);
|
||||
|
||||
std::size_t m_keyboardOwner;
|
||||
|
|
|
|||
|
|
@ -24,12 +24,10 @@ namespace Ndk
|
|||
m_keyReleasedSlot.Connect(eventHandler.OnKeyReleased, this, &Canvas::OnEventKeyReleased);
|
||||
m_mouseButtonPressedSlot.Connect(eventHandler.OnMouseButtonPressed, this, &Canvas::OnEventMouseButtonPressed);
|
||||
m_mouseButtonReleasedSlot.Connect(eventHandler.OnMouseButtonReleased, this, &Canvas::OnEventMouseButtonRelease);
|
||||
m_mouseMovedSlot.Connect(eventHandler.OnMouseMoved, this, &Canvas::OnEventMouseMoved);
|
||||
m_mouseLeftSlot.Connect(eventHandler.OnMouseLeft, this, &Canvas::OnEventMouseLeft);
|
||||
m_mouseMovedSlot.Connect(eventHandler.OnMouseMoved, this, &Canvas::OnEventMouseMoved);
|
||||
m_mouseWheelMovedSlot.Connect(eventHandler.OnMouseWheelMoved, this, &Canvas::OnEventMouseWheelMoved);
|
||||
m_textEnteredSlot.Connect(eventHandler.OnTextEntered, this, &Canvas::OnEventTextEntered);
|
||||
|
||||
// Disable padding by default
|
||||
SetPadding(0.f, 0.f, 0.f, 0.f);
|
||||
}
|
||||
|
||||
inline Canvas::~Canvas()
|
||||
|
|
@ -61,7 +59,7 @@ namespace Ndk
|
|||
{
|
||||
WidgetEntry& entry = m_widgetEntries[index];
|
||||
|
||||
Nz::Vector3f pos = entry.widget->GetPosition();
|
||||
Nz::Vector3f pos = entry.widget->GetPosition(Nz::CoordSys_Global);
|
||||
Nz::Vector2f size = entry.widget->GetSize();
|
||||
|
||||
entry.box.Set(pos.x, pos.y, pos.z, size.x, size.y, 1.f);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
namespace Ndk
|
||||
{
|
||||
template<typename ComponentType>
|
||||
class Component : public BaseComponent
|
||||
class Component : public BaseComponent, public Nz::HandledObject<ComponentType>
|
||||
{
|
||||
public:
|
||||
Component();
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <NDK/Components/ConstraintComponent2D.hpp>
|
||||
#include <NDK/Components/DebugComponent.hpp>
|
||||
#include <NDK/Components/GraphicsComponent.hpp>
|
||||
#include <NDK/Components/LifetimeComponent.hpp>
|
||||
#include <NDK/Components/LightComponent.hpp>
|
||||
#include <NDK/Components/ListenerComponent.hpp>
|
||||
#include <NDK/Components/NodeComponent.hpp>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Ndk
|
|||
|
||||
using CameraComponentHandle = Nz::ObjectHandle<CameraComponent>;
|
||||
|
||||
class NDK_API CameraComponent : public Component<CameraComponent>, public Nz::AbstractViewer, public Nz::HandledObject<CameraComponent>
|
||||
class NDK_API CameraComponent : public Component<CameraComponent>, public Nz::AbstractViewer
|
||||
{
|
||||
public:
|
||||
inline CameraComponent();
|
||||
|
|
@ -43,6 +43,7 @@ namespace Ndk
|
|||
const Nz::Frustumf& GetFrustum() const override;
|
||||
inline unsigned int GetLayer() const;
|
||||
const Nz::Matrix4f& GetProjectionMatrix() const override;
|
||||
inline const Nz::Vector3f& GetProjectionScale() const;
|
||||
Nz::ProjectionType GetProjectionType() const override;
|
||||
inline const Nz::Vector2f& GetSize() const;
|
||||
const Nz::RenderTarget* GetTarget() const override;
|
||||
|
|
@ -54,6 +55,7 @@ namespace Ndk
|
|||
|
||||
inline void SetFOV(float fov);
|
||||
void SetLayer(unsigned int layer);
|
||||
inline void SetProjectionScale(const Nz::Vector3f& scale);
|
||||
inline void SetProjectionType(Nz::ProjectionType projection);
|
||||
inline void SetSize(const Nz::Vector2f& size);
|
||||
inline void SetSize(float width, float height);
|
||||
|
|
@ -99,6 +101,7 @@ namespace Ndk
|
|||
mutable Nz::Recti m_viewport;
|
||||
const Nz::RenderTarget* m_target;
|
||||
Nz::Vector2f m_size;
|
||||
Nz::Vector3f m_projectionScale;
|
||||
mutable bool m_frustumUpdated;
|
||||
mutable bool m_projectionMatrixUpdated;
|
||||
mutable bool m_viewMatrixUpdated;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ namespace Ndk
|
|||
m_targetRegion(0.f, 0.f, 1.f, 1.f),
|
||||
m_target(nullptr),
|
||||
m_size(0.f),
|
||||
m_projectionScale(1.f, 1.f, 1.f),
|
||||
m_frustumUpdated(false),
|
||||
m_projectionMatrixUpdated(false),
|
||||
m_viewMatrixUpdated(false),
|
||||
|
|
@ -38,12 +39,12 @@ namespace Ndk
|
|||
inline CameraComponent::CameraComponent(const CameraComponent& camera) :
|
||||
Component(camera),
|
||||
AbstractViewer(camera),
|
||||
HandledObject(camera),
|
||||
m_visibilityHash(camera.m_visibilityHash),
|
||||
m_projectionType(camera.m_projectionType),
|
||||
m_targetRegion(camera.m_targetRegion),
|
||||
m_target(nullptr),
|
||||
m_size(camera.m_size),
|
||||
m_projectionScale(camera.m_projectionScale),
|
||||
m_frustumUpdated(false),
|
||||
m_projectionMatrixUpdated(false),
|
||||
m_viewMatrixUpdated(false),
|
||||
|
|
@ -116,11 +117,19 @@ namespace Ndk
|
|||
return m_layer;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the projection scale of the camera
|
||||
* \return Projection scale
|
||||
*/
|
||||
const Nz::Vector3f& CameraComponent::GetProjectionScale() const
|
||||
{
|
||||
return m_projectionScale;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the size of the camera
|
||||
* \return Size of the camera
|
||||
*/
|
||||
|
||||
inline const Nz::Vector2f & CameraComponent::GetSize() const
|
||||
{
|
||||
return m_size;
|
||||
|
|
@ -152,12 +161,23 @@ namespace Ndk
|
|||
InvalidateProjectionMatrix();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the camera projection scale
|
||||
*
|
||||
* \param scale New projection scale
|
||||
*/
|
||||
inline void CameraComponent::SetProjectionScale(const Nz::Vector3f& scale)
|
||||
{
|
||||
m_projectionScale = scale;
|
||||
|
||||
InvalidateProjectionMatrix();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the projection type of the camera
|
||||
*
|
||||
* \param projectionType Projection type of the camera
|
||||
*/
|
||||
|
||||
inline void CameraComponent::SetProjectionType(Nz::ProjectionType projectionType)
|
||||
{
|
||||
m_projectionType = projectionType;
|
||||
|
|
|
|||
|
|
@ -14,10 +14,15 @@
|
|||
|
||||
namespace Ndk
|
||||
{
|
||||
class CollisionComponent2D;
|
||||
|
||||
using CollisionComponent2DHandle = Nz::ObjectHandle<CollisionComponent2D>;
|
||||
|
||||
class NDK_API CollisionComponent2D : public Component<CollisionComponent2D>
|
||||
{
|
||||
friend class PhysicsSystem2D;
|
||||
friend class ConstraintComponent2D;
|
||||
friend class PhysicsComponent2D;
|
||||
friend class PhysicsSystem2D;
|
||||
|
||||
public:
|
||||
CollisionComponent2D(Nz::Collider2DRef geom = Nz::Collider2DRef());
|
||||
|
|
@ -26,8 +31,12 @@ namespace Ndk
|
|||
|
||||
Nz::Rectf GetAABB() const;
|
||||
const Nz::Collider2DRef& GetGeom() const;
|
||||
const Nz::Vector2f& GetGeomOffset() const;
|
||||
|
||||
void Recenter(const Nz::Vector2f& origin);
|
||||
|
||||
void SetGeom(Nz::Collider2DRef geom);
|
||||
void SetGeomOffset(const Nz::Vector2f& geomOffset);
|
||||
|
||||
CollisionComponent2D& operator=(Nz::Collider2DRef geom);
|
||||
CollisionComponent2D& operator=(CollisionComponent2D&& collision) = default;
|
||||
|
|
@ -36,7 +45,10 @@ namespace Ndk
|
|||
|
||||
private:
|
||||
void InitializeStaticBody();
|
||||
Nz::RigidBody2D* GetRigidBody();
|
||||
const Nz::RigidBody2D* GetRigidBody() const;
|
||||
Nz::RigidBody2D* GetStaticBody();
|
||||
const Nz::RigidBody2D* GetStaticBody() const;
|
||||
|
||||
void OnAttached() override;
|
||||
void OnComponentAttached(BaseComponent& component) override;
|
||||
|
|
|
|||
|
|
@ -28,16 +28,6 @@ namespace Ndk
|
|||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the collision box representing the entity
|
||||
* \return The physics collision box
|
||||
*/
|
||||
|
||||
inline Nz::Rectf CollisionComponent2D::GetAABB() const
|
||||
{
|
||||
return m_staticBody->GetAABB();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the geometry representing the entity
|
||||
* \return A constant reference to the physics geometry
|
||||
|
|
@ -62,13 +52,13 @@ namespace Ndk
|
|||
return *this;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the static body used by the entity
|
||||
* \return A pointer to the entity
|
||||
*/
|
||||
|
||||
inline Nz::RigidBody2D* CollisionComponent2D::GetStaticBody()
|
||||
{
|
||||
return m_staticBody.get();
|
||||
}
|
||||
|
||||
inline const Nz::RigidBody2D* CollisionComponent2D::GetStaticBody() const
|
||||
{
|
||||
return m_staticBody.get();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@
|
|||
|
||||
namespace Ndk
|
||||
{
|
||||
class CollisionComponent3D;
|
||||
|
||||
using CollisionComponent3DHandle = Nz::ObjectHandle<CollisionComponent3D>;
|
||||
|
||||
class NDK_API CollisionComponent3D : public Component<CollisionComponent3D>
|
||||
{
|
||||
friend class PhysicsSystem3D;
|
||||
|
|
|
|||
|
|
@ -1,30 +1,47 @@
|
|||
// Copyright (C) 2019 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NDK_COMPONENTS_CONSTRAINTCOMPONENT2D_HPP
|
||||
#define NDK_COMPONENTS_CONSTRAINTCOMPONENT2D_HPP
|
||||
|
||||
#include <NDK/Component.hpp>
|
||||
#include <Nazara/Physics2D/Constraint2D.hpp>
|
||||
#include <Nazara/Math/Vector3.hpp>
|
||||
#include <vector>
|
||||
#include <NDK/Component.hpp>
|
||||
#include <NDK/Entity.hpp>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
class ConstraintComponent2D;
|
||||
|
||||
using ConstraintComponent2DHandle = Nz::ObjectHandle<ConstraintComponent2D>;
|
||||
|
||||
class NDK_API ConstraintComponent2D : public Component<ConstraintComponent2D>
|
||||
{
|
||||
public:
|
||||
ConstraintComponent2D() = default;
|
||||
ConstraintComponent2D(const ConstraintComponent2D& joint) = default;
|
||||
ConstraintComponent2D(const ConstraintComponent2D& joint);
|
||||
ConstraintComponent2D(ConstraintComponent2D&& joint) = default;
|
||||
|
||||
template<typename T, typename... Args> inline Nz::ObjectRef<T> CreateConstraint(const Ndk::EntityHandle& first, const Ndk::EntityHandle& second, Args&&... args);
|
||||
|
||||
template<typename T, typename... Args> T* CreateConstraint(const Ndk::EntityHandle& first, const Ndk::EntityHandle& second, Args&&... args);
|
||||
bool RemoveConstraint(Nz::Constraint2D* constraint);
|
||||
|
||||
static ComponentIndex componentIndex;
|
||||
|
||||
private:
|
||||
struct ConstraintData
|
||||
{
|
||||
std::unique_ptr<Nz::Constraint2D> constraint;
|
||||
|
||||
std::vector<Nz::Constraint2DRef> m_constraints;
|
||||
NazaraSlot(Ndk::Entity, OnEntityDestruction, onBodyADestruction);
|
||||
NazaraSlot(Ndk::Entity, OnEntityDestruction, onBodyBDestruction);
|
||||
};
|
||||
|
||||
std::vector<ConstraintData> m_constraints;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
// Copyright (C) 2019 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#include <NDK/Components/ConstraintComponent2D.hpp>
|
||||
#include <NDK/Components/PhysicsComponent2D.hpp>
|
||||
#include <NDK/Components/CollisionComponent2D.hpp>
|
||||
|
|
@ -5,7 +9,7 @@
|
|||
namespace Ndk
|
||||
{
|
||||
template<typename T, typename ...Args>
|
||||
Nz::ObjectRef<T> ConstraintComponent2D::CreateConstraint(const Ndk::EntityHandle& first, const Ndk::EntityHandle& second, Args && ...args)
|
||||
T* ConstraintComponent2D::CreateConstraint(const Ndk::EntityHandle& first, const Ndk::EntityHandle& second, Args&& ...args)
|
||||
{
|
||||
auto FetchBody = [](const Ndk::EntityHandle& entity) -> Nz::RigidBody2D*
|
||||
{
|
||||
|
|
@ -23,9 +27,20 @@ namespace Ndk
|
|||
Nz::RigidBody2D* secondBody = FetchBody(second);
|
||||
NazaraAssert(secondBody, "Second entity has no CollisionComponent2D nor PhysicsComponent2D component");
|
||||
|
||||
Nz::ObjectRef<T> constraint = T::New(*firstBody, *secondBody, std::forward<Args>(args)...);
|
||||
m_constraints.push_back(constraint);
|
||||
m_constraints.emplace_back();
|
||||
auto& constraintData = m_constraints.back();
|
||||
constraintData.constraint = std::make_unique<T>(*firstBody, *secondBody, std::forward<Args>(args)...);
|
||||
|
||||
return constraint;
|
||||
constraintData.onBodyADestruction.Connect(first->OnEntityDestruction, [this, constraint = constraintData.constraint.get()](const Ndk::Entity* /*entity*/)
|
||||
{
|
||||
RemoveConstraint(constraint);
|
||||
});
|
||||
|
||||
constraintData.onBodyBDestruction.Connect(second->OnEntityDestruction, [this, constraint = constraintData.constraint.get()](const Ndk::Entity* /*entity*/)
|
||||
{
|
||||
RemoveConstraint(constraint);
|
||||
});
|
||||
|
||||
return static_cast<T*>(constraintData.constraint.get());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Ndk
|
|||
{
|
||||
enum class DebugDraw
|
||||
{
|
||||
//TODO: Collider2D
|
||||
Collider2D,
|
||||
Collider3D,
|
||||
GraphicsAABB,
|
||||
GraphicsOBB,
|
||||
|
|
@ -40,6 +40,11 @@ namespace Ndk
|
|||
|
||||
constexpr DebugDrawFlags DebugDraw_None = 0;
|
||||
|
||||
class DebugComponent;
|
||||
class GraphicsComponent;
|
||||
|
||||
using DebugComponentHandle = Nz::ObjectHandle<DebugComponent>;
|
||||
|
||||
class NDK_API DebugComponent : public Component<DebugComponent>
|
||||
{
|
||||
friend class DebugSystem;
|
||||
|
|
@ -61,8 +66,14 @@ namespace Ndk
|
|||
static ComponentIndex componentIndex;
|
||||
|
||||
private:
|
||||
void DetachDebugRenderables(GraphicsComponent& gfxComponent);
|
||||
|
||||
inline const Nz::InstancedRenderableRef& GetDebugRenderable(DebugDraw option) const;
|
||||
inline DebugDrawFlags GetEnabledFlags() const;
|
||||
|
||||
void OnComponentDetached(BaseComponent& component) override;
|
||||
void OnDetached() override;
|
||||
|
||||
inline void UpdateDebugRenderable(DebugDraw option, Nz::InstancedRenderableRef renderable);
|
||||
inline void UpdateEnabledFlags(DebugDrawFlags flags);
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <Nazara/Graphics/CullingList.hpp>
|
||||
#include <Nazara/Graphics/InstancedRenderable.hpp>
|
||||
#include <Nazara/Math/Frustum.hpp>
|
||||
#include <Nazara/Utility/Node.hpp>
|
||||
#include <NDK/Component.hpp>
|
||||
#include <unordered_map>
|
||||
|
|
@ -21,7 +22,7 @@ namespace Ndk
|
|||
using GraphicsComponentCullingList = Nz::CullingList<GraphicsComponent>;
|
||||
using GraphicsComponentHandle = Nz::ObjectHandle<GraphicsComponent>;
|
||||
|
||||
class NDK_API GraphicsComponent : public Component<GraphicsComponent>, public Nz::HandledObject<GraphicsComponent>
|
||||
class NDK_API GraphicsComponent : public Component<GraphicsComponent>
|
||||
{
|
||||
friend class RenderSystem;
|
||||
|
||||
|
|
@ -34,6 +35,7 @@ namespace Ndk
|
|||
|
||||
inline void AddToCullingList(GraphicsComponentCullingList* cullingList) const;
|
||||
void AddToRenderQueue(Nz::AbstractRenderQueue* renderQueue) const;
|
||||
void AddToRenderQueueByCulling(const Nz::Frustumf& frustum, Nz::AbstractRenderQueue* renderQueue) const;
|
||||
|
||||
inline void Attach(Nz::InstancedRenderableRef renderable, int renderOrder = 0);
|
||||
void Attach(Nz::InstancedRenderableRef renderable, const Nz::Matrix4f& localMatrix, int renderOrder = 0);
|
||||
|
|
@ -44,15 +46,19 @@ namespace Ndk
|
|||
|
||||
inline bool DoesRequireRealTimeReflections() const;
|
||||
|
||||
inline void EnsureBoundingVolumesUpdate() const;
|
||||
inline void EnsureTransformMatrixUpdate() const;
|
||||
|
||||
template<typename Func> void ForEachRenderable(const Func& func) const;
|
||||
|
||||
inline void EnsureBoundingVolumeUpdate() const;
|
||||
inline void EnsureTransformMatrixUpdate() const;
|
||||
inline const Nz::Boxf& GetAABB() const;
|
||||
|
||||
inline void GetAttachedRenderables(RenderableList* renderables) const;
|
||||
inline std::size_t GetAttachedRenderableCount() const;
|
||||
|
||||
inline const Nz::BoundingVolumef& GetBoundingVolume() const;
|
||||
inline const Nz::BoundingVolumef& GetBoundingVolume(std::size_t renderableIndex) const;
|
||||
inline const Nz::Matrix4f& GetLocalMatrix(std::size_t renderableIndex) const;
|
||||
inline const Nz::Matrix4f& GetTransformMatrix(std::size_t renderableIndex) const;
|
||||
|
||||
inline void RemoveFromCullingList(GraphicsComponentCullingList* cullingList) const;
|
||||
|
||||
|
|
@ -68,7 +74,8 @@ namespace Ndk
|
|||
|
||||
void ConnectInstancedRenderableSignals(Renderable& renderable);
|
||||
|
||||
inline void InvalidateBoundingVolume() const;
|
||||
inline void ForceCullingInvalidation();
|
||||
inline void InvalidateAABB() const;
|
||||
void InvalidateRenderableData(const Nz::InstancedRenderable* renderable, Nz::UInt32 flags, std::size_t index);
|
||||
void InvalidateRenderableMaterial(const Nz::InstancedRenderable* renderable, std::size_t skinIndex, std::size_t matIndex, const Nz::MaterialRef& newMat);
|
||||
inline void InvalidateRenderables();
|
||||
|
|
@ -89,11 +96,20 @@ namespace Ndk
|
|||
|
||||
void UnregisterMaterial(Nz::Material* material);
|
||||
|
||||
void UpdateBoundingVolume() const;
|
||||
void UpdateBoundingVolumes() const;
|
||||
void UpdateTransformMatrix() const;
|
||||
|
||||
NazaraSlot(Nz::Node, OnNodeInvalidation, m_nodeInvalidationSlot);
|
||||
|
||||
using CullingListBoxEntry = GraphicsComponentCullingList::BoxEntry;
|
||||
|
||||
struct CullingBoxEntry
|
||||
{
|
||||
CullingListBoxEntry listEntry;
|
||||
|
||||
NazaraSlot(GraphicsComponentCullingList, OnCullingListRelease, cullingListReleaseSlot);
|
||||
};
|
||||
|
||||
struct MaterialEntry
|
||||
{
|
||||
NazaraSlot(Nz::Material, OnMaterialReflectionModeChange, reflectionModelChangeSlot);
|
||||
|
|
@ -128,29 +144,21 @@ namespace Ndk
|
|||
NazaraSlot(Nz::InstancedRenderable, OnInstancedRenderableResetMaterials, renderableResetMaterialsSlot);
|
||||
NazaraSlot(Nz::InstancedRenderable, OnInstancedRenderableSkinChange, renderableSkinChangeSlot);
|
||||
|
||||
mutable Nz::BoundingVolumef boundingVolume;
|
||||
mutable Nz::InstancedRenderable::InstanceData data;
|
||||
Nz::InstancedRenderableRef renderable;
|
||||
mutable bool dataUpdated;
|
||||
};
|
||||
|
||||
using VolumeCullingListEntry = GraphicsComponentCullingList::VolumeEntry;
|
||||
|
||||
struct VolumeCullingEntry
|
||||
{
|
||||
VolumeCullingListEntry listEntry;
|
||||
|
||||
NazaraSlot(GraphicsComponentCullingList, OnCullingListRelease, cullingListReleaseSlot);
|
||||
};
|
||||
|
||||
std::size_t m_reflectiveMaterialCount;
|
||||
mutable std::vector<VolumeCullingEntry> m_volumeCullingEntries;
|
||||
mutable std::vector<CullingBoxEntry> m_cullingBoxEntries;
|
||||
std::vector<Renderable> m_renderables;
|
||||
std::unordered_map<const Nz::Material*, MaterialEntry> m_materialEntries;
|
||||
mutable Nz::BoundingVolumef m_boundingVolume;
|
||||
mutable Nz::Boxf m_aabb;
|
||||
mutable Nz::Matrix4f m_transformMatrix;
|
||||
Nz::Recti m_scissorRect;
|
||||
Nz::TextureRef m_reflectionMap;
|
||||
mutable bool m_boundingVolumeUpdated;
|
||||
mutable bool m_boundingVolumesUpdated;
|
||||
mutable bool m_transformMatrixUpdated;
|
||||
unsigned int m_reflectionMapSize;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -22,11 +22,11 @@ namespace Ndk
|
|||
*/
|
||||
inline GraphicsComponent::GraphicsComponent(const GraphicsComponent& graphicsComponent) :
|
||||
Component(graphicsComponent),
|
||||
HandledObject(graphicsComponent),
|
||||
m_reflectiveMaterialCount(0),
|
||||
m_boundingVolume(graphicsComponent.m_boundingVolume),
|
||||
m_aabb(graphicsComponent.m_aabb),
|
||||
m_transformMatrix(graphicsComponent.m_transformMatrix),
|
||||
m_boundingVolumeUpdated(graphicsComponent.m_boundingVolumeUpdated),
|
||||
m_scissorRect(graphicsComponent.m_scissorRect),
|
||||
m_boundingVolumesUpdated(graphicsComponent.m_boundingVolumesUpdated),
|
||||
m_transformMatrixUpdated(graphicsComponent.m_transformMatrixUpdated)
|
||||
{
|
||||
m_renderables.reserve(graphicsComponent.m_renderables.size());
|
||||
|
|
@ -36,12 +36,12 @@ namespace Ndk
|
|||
|
||||
inline void GraphicsComponent::AddToCullingList(GraphicsComponentCullingList* cullingList) const
|
||||
{
|
||||
m_volumeCullingEntries.emplace_back(VolumeCullingEntry{});
|
||||
VolumeCullingEntry& entry = m_volumeCullingEntries.back();
|
||||
m_cullingBoxEntries.emplace_back();
|
||||
CullingBoxEntry& entry = m_cullingBoxEntries.back();
|
||||
entry.cullingListReleaseSlot.Connect(cullingList->OnCullingListRelease, this, &GraphicsComponent::RemoveFromCullingList);
|
||||
entry.listEntry = cullingList->RegisterVolumeTest(this);
|
||||
entry.listEntry = cullingList->RegisterBoxTest(this);
|
||||
|
||||
InvalidateBoundingVolume();
|
||||
InvalidateAABB();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -70,7 +70,7 @@ namespace Ndk
|
|||
InvalidateReflectionMap();
|
||||
}
|
||||
|
||||
InvalidateBoundingVolume();
|
||||
InvalidateAABB();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -85,13 +85,15 @@ namespace Ndk
|
|||
{
|
||||
if (it->renderable == renderable)
|
||||
{
|
||||
InvalidateBoundingVolume();
|
||||
InvalidateAABB();
|
||||
|
||||
std::size_t materialCount = renderable->GetMaterialCount();
|
||||
for (std::size_t i = 0; i < materialCount; ++i)
|
||||
UnregisterMaterial(renderable->GetMaterial(i));
|
||||
|
||||
m_renderables.erase(it);
|
||||
|
||||
ForceCullingInvalidation();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -109,26 +111,14 @@ namespace Ndk
|
|||
return m_reflectiveMaterialCount != 0 && m_reflectionMap;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Calls a function for every renderable attached to this component
|
||||
*
|
||||
* \param func Callback function which will be called with renderable data
|
||||
*/
|
||||
template<typename Func>
|
||||
void GraphicsComponent::ForEachRenderable(const Func& func) const
|
||||
{
|
||||
for (const auto& renderableData : m_renderables)
|
||||
func(renderableData.renderable, renderableData.data.localMatrix, renderableData.data.renderOrder);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Ensures the bounding volume is up to date
|
||||
*/
|
||||
|
||||
inline void GraphicsComponent::EnsureBoundingVolumeUpdate() const
|
||||
inline void GraphicsComponent::EnsureBoundingVolumesUpdate() const
|
||||
{
|
||||
if (!m_boundingVolumeUpdated)
|
||||
UpdateBoundingVolume();
|
||||
if (!m_boundingVolumesUpdated)
|
||||
UpdateBoundingVolumes();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -141,6 +131,17 @@ namespace Ndk
|
|||
UpdateTransformMatrix();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the axis-aligned bounding box of the entity
|
||||
* \return A constant reference to the AABB
|
||||
*/
|
||||
inline const Nz::Boxf& GraphicsComponent::GetAABB() const
|
||||
{
|
||||
EnsureBoundingVolumesUpdate();
|
||||
|
||||
return m_aabb;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the set of renderable elements
|
||||
*
|
||||
|
|
@ -168,28 +169,50 @@ namespace Ndk
|
|||
return m_renderables.size();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the bouding volume of the entity
|
||||
* \return A constant reference to the bounding volume
|
||||
*/
|
||||
|
||||
inline const Nz::BoundingVolumef& GraphicsComponent::GetBoundingVolume() const
|
||||
inline const Nz::BoundingVolumef& GraphicsComponent::GetBoundingVolume(std::size_t renderableIndex) const
|
||||
{
|
||||
EnsureBoundingVolumeUpdate();
|
||||
EnsureBoundingVolumesUpdate();
|
||||
|
||||
return m_boundingVolume;
|
||||
assert(renderableIndex < m_renderables.size());
|
||||
return m_renderables[renderableIndex].boundingVolume;
|
||||
}
|
||||
|
||||
inline const Nz::Matrix4f& GraphicsComponent::GetLocalMatrix(std::size_t renderableIndex) const
|
||||
{
|
||||
assert(renderableIndex < m_renderables.size());
|
||||
return m_renderables[renderableIndex].data.localMatrix;
|
||||
}
|
||||
|
||||
inline const Nz::Matrix4f& GraphicsComponent::GetTransformMatrix(std::size_t renderableIndex) const
|
||||
{
|
||||
EnsureBoundingVolumesUpdate();
|
||||
|
||||
assert(renderableIndex < m_renderables.size());
|
||||
return m_renderables[renderableIndex].data.transformMatrix;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Calls a function for every renderable attached to this component
|
||||
*
|
||||
* \param func Callback function which will be called with renderable data
|
||||
*/
|
||||
template<typename Func>
|
||||
void GraphicsComponent::ForEachRenderable(const Func& func) const
|
||||
{
|
||||
for (const auto& renderableData : m_renderables)
|
||||
func(renderableData.renderable, renderableData.data.localMatrix, renderableData.data.renderOrder);
|
||||
}
|
||||
|
||||
inline void GraphicsComponent::RemoveFromCullingList(GraphicsComponentCullingList* cullingList) const
|
||||
{
|
||||
for (auto it = m_volumeCullingEntries.begin(); it != m_volumeCullingEntries.end(); ++it)
|
||||
for (auto it = m_cullingBoxEntries.begin(); it != m_cullingBoxEntries.end(); ++it)
|
||||
{
|
||||
if (it->listEntry.GetParent() == cullingList)
|
||||
{
|
||||
if (m_volumeCullingEntries.size() > 1)
|
||||
*it = std::move(m_volumeCullingEntries.back());
|
||||
if (m_cullingBoxEntries.size() > 1)
|
||||
*it = std::move(m_cullingBoxEntries.back());
|
||||
|
||||
m_volumeCullingEntries.pop_back();
|
||||
m_cullingBoxEntries.pop_back();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -199,7 +222,7 @@ namespace Ndk
|
|||
{
|
||||
m_scissorRect = scissorRect;
|
||||
|
||||
for (VolumeCullingEntry& entry : m_volumeCullingEntries)
|
||||
for (CullingBoxEntry& entry : m_cullingBoxEntries)
|
||||
entry.listEntry.ForceInvalidation(); //< Invalidate render queues
|
||||
}
|
||||
|
||||
|
|
@ -211,7 +234,7 @@ namespace Ndk
|
|||
{
|
||||
renderable.data.localMatrix = localMatrix;
|
||||
|
||||
InvalidateBoundingVolume();
|
||||
InvalidateAABB();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -233,9 +256,15 @@ namespace Ndk
|
|||
* \brief Invalidates the bounding volume
|
||||
*/
|
||||
|
||||
inline void GraphicsComponent::InvalidateBoundingVolume() const
|
||||
inline void GraphicsComponent::ForceCullingInvalidation()
|
||||
{
|
||||
m_boundingVolumeUpdated = false;
|
||||
for (CullingBoxEntry& entry : m_cullingBoxEntries)
|
||||
entry.listEntry.ForceInvalidation(); //< Invalidate render queues
|
||||
}
|
||||
|
||||
inline void GraphicsComponent::InvalidateAABB() const
|
||||
{
|
||||
m_boundingVolumesUpdated = false;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -256,7 +285,7 @@ namespace Ndk
|
|||
{
|
||||
m_transformMatrixUpdated = false;
|
||||
|
||||
InvalidateBoundingVolume();
|
||||
InvalidateAABB();
|
||||
InvalidateRenderables();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NDK_COMPONENTS_LIFETIMECOMPONENT_HPP
|
||||
#define NDK_COMPONENTS_LIFETIMECOMPONENT_HPP
|
||||
|
||||
#include <NDK/Component.hpp>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
class LifetimeComponent;
|
||||
|
||||
using LifetimeComponentHandle = Nz::ObjectHandle<LifetimeComponent>;
|
||||
|
||||
class NDK_API LifetimeComponent : public Component<LifetimeComponent>
|
||||
{
|
||||
friend class LifetimeSystem;
|
||||
|
||||
public:
|
||||
inline LifetimeComponent(float lifetime);
|
||||
LifetimeComponent(const LifetimeComponent&) = default;
|
||||
~LifetimeComponent() = default;
|
||||
|
||||
inline float GetRemainingTime() const;
|
||||
|
||||
static ComponentIndex componentIndex;
|
||||
|
||||
private:
|
||||
inline bool UpdateLifetime(float elapsedTime);
|
||||
|
||||
float m_lifetime;
|
||||
};
|
||||
}
|
||||
|
||||
#include <NDK/Components/LifetimeComponent.inl>
|
||||
|
||||
#endif // NDK_COMPONENTS_LIFETIMECOMPONENT_HPP
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#include <NDK/Components/LifetimeComponent.hpp>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
inline LifetimeComponent::LifetimeComponent(float lifetime) :
|
||||
m_lifetime(lifetime)
|
||||
{
|
||||
}
|
||||
|
||||
inline float Ndk::LifetimeComponent::GetRemainingTime() const
|
||||
{
|
||||
return m_lifetime;
|
||||
}
|
||||
|
||||
inline bool LifetimeComponent::UpdateLifetime(float elapsedTime)
|
||||
{
|
||||
m_lifetime -= elapsedTime;
|
||||
return m_lifetime < 0.f;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
|
|
@ -13,6 +13,10 @@
|
|||
|
||||
namespace Ndk
|
||||
{
|
||||
class LightComponent;
|
||||
|
||||
using LightComponentHandle = Nz::ObjectHandle<LightComponent>;
|
||||
|
||||
class NDK_API LightComponent : public Component<LightComponent>, public Nz::Light
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@
|
|||
|
||||
namespace Ndk
|
||||
{
|
||||
class ListenerComponent;
|
||||
|
||||
using ListenerComponentHandle = Nz::ObjectHandle<ListenerComponent>;
|
||||
|
||||
class NDK_API ListenerComponent : public Component<ListenerComponent>
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Ndk
|
|||
|
||||
using NodeComponentHandle = Nz::ObjectHandle<NodeComponent>;
|
||||
|
||||
class NDK_API NodeComponent : public Component<NodeComponent>, public Nz::Node, public Nz::HandledObject<NodeComponent>
|
||||
class NDK_API NodeComponent : public Component<NodeComponent>, public Nz::Node
|
||||
{
|
||||
public:
|
||||
NodeComponent() = default;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@
|
|||
|
||||
namespace Ndk
|
||||
{
|
||||
class ParticleEmitterComponent;
|
||||
|
||||
using ParticleEmitterComponentHandle = Nz::ObjectHandle<ParticleEmitterComponent>;
|
||||
|
||||
class NDK_API ParticleEmitterComponent : public Component<ParticleEmitterComponent>, public Nz::ParticleEmitter
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Ndk
|
|||
|
||||
using ParticleGroupComponentHandle = Nz::ObjectHandle<ParticleGroupComponent>;
|
||||
|
||||
class NDK_API ParticleGroupComponent : public Component<ParticleGroupComponent>, public Nz::ParticleGroup, public Nz::HandledObject<ParticleGroupComponent>
|
||||
class NDK_API ParticleGroupComponent : public Component<ParticleGroupComponent>, public Nz::ParticleGroup
|
||||
{
|
||||
public:
|
||||
inline ParticleGroupComponent(unsigned int maxParticleCount, Nz::ParticleLayout layout);
|
||||
|
|
@ -38,4 +38,4 @@ namespace Ndk
|
|||
#include <NDK/Components/ParticleGroupComponent.inl>
|
||||
|
||||
#endif // NDK_COMPONENTS_PARTICLEGROUPCOMPONENT_HPP
|
||||
#endif // NDK_SERVER
|
||||
#endif // NDK_SERVER
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@
|
|||
|
||||
namespace Ndk
|
||||
{
|
||||
class PhysicsComponent2D;
|
||||
|
||||
using PhysicsComponent2DHandle = Nz::ObjectHandle<PhysicsComponent2D>;
|
||||
|
||||
class NDK_API PhysicsComponent2D : public Component<PhysicsComponent2D>
|
||||
{
|
||||
friend class CollisionComponent2D;
|
||||
|
|
@ -20,39 +24,75 @@ namespace Ndk
|
|||
friend class ConstraintComponent2D;
|
||||
|
||||
public:
|
||||
PhysicsComponent2D() = default;
|
||||
using VelocityFunc = Nz::RigidBody2D::VelocityFunc;
|
||||
|
||||
PhysicsComponent2D();
|
||||
PhysicsComponent2D(const PhysicsComponent2D& physics);
|
||||
~PhysicsComponent2D() = default;
|
||||
|
||||
void AddForce(const Nz::Vector2f& force, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||
void AddForce(const Nz::Vector2f& force, const Nz::Vector2f& point, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||
void AddImpulse(const Nz::Vector2f& impulse, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||
void AddImpulse(const Nz::Vector2f& impulse, const Nz::Vector2f& point, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||
void AddTorque(float torque);
|
||||
inline void AddForce(const Nz::Vector2f& force, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||
inline void AddForce(const Nz::Vector2f& force, const Nz::Vector2f& point, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||
inline void AddImpulse(const Nz::Vector2f& impulse, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||
inline void AddImpulse(const Nz::Vector2f& impulse, const Nz::Vector2f& point, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||
inline void AddTorque(const Nz::RadianAnglef& torque);
|
||||
|
||||
bool ClosestPointQuery(const Nz::Vector2f& position, Nz::Vector2f* closestPoint, float* closestDistance) const;
|
||||
inline bool ClosestPointQuery(const Nz::Vector2f& position, Nz::Vector2f* closestPoint, float* closestDistance) const;
|
||||
|
||||
Nz::Rectf GetAABB() const;
|
||||
float GetAngularVelocity() const;
|
||||
Nz::Vector2f GetCenterOfGravity(Nz::CoordSys coordSys = Nz::CoordSys_Local) const;
|
||||
float GetMass() const;
|
||||
Nz::Vector2f GetPosition() const;
|
||||
float GetRotation() const;
|
||||
Nz::Vector2f GetVelocity() const;
|
||||
inline void EnableNodeSynchronization(bool nodeSynchronization);
|
||||
|
||||
bool IsSleeping() const;
|
||||
inline void ForceSleep();
|
||||
inline void ForEachArbiter(const std::function<void(Nz::Arbiter2D&)>& callback);
|
||||
|
||||
void SetAngularVelocity(float angularVelocity);
|
||||
void SetMass(float mass);
|
||||
void SetMassCenter(const Nz::Vector2f& center);
|
||||
void SetPosition(const Nz::Vector2f& position);
|
||||
void SetRotation(float rotation);
|
||||
void SetVelocity(const Nz::Vector2f& velocity);
|
||||
inline Nz::Rectf GetAABB() const;
|
||||
inline float GetAngularDamping() const;
|
||||
inline Nz::RadianAnglef GetAngularVelocity() const;
|
||||
NAZARA_DEPRECATED("Name error, please use GetMassCenter")
|
||||
inline Nz::Vector2f GetCenterOfGravity(Nz::CoordSys coordSys = Nz::CoordSys_Local) const;
|
||||
inline float GetElasticity(std::size_t shapeIndex = 0) const;
|
||||
inline float GetFriction(std::size_t shapeIndex = 0) const;
|
||||
inline float GetMass() const;
|
||||
inline Nz::Vector2f GetMassCenter(Nz::CoordSys coordSys = Nz::CoordSys_Local) const;
|
||||
inline float GetMomentOfInertia() const;
|
||||
inline Nz::Vector2f GetPosition() const;
|
||||
inline Nz::RadianAnglef GetRotation() const;
|
||||
inline Nz::Vector2f GetSurfaceVelocity(std::size_t shapeIndex = 0) const;
|
||||
inline std::size_t GetShapeCount() const;
|
||||
inline Nz::Vector2f GetVelocity() const;
|
||||
const VelocityFunc& GetVelocityFunction() const;
|
||||
|
||||
inline bool IsNodeSynchronizationEnabled() const;
|
||||
inline bool IsSleeping() const;
|
||||
inline bool IsValid() const;
|
||||
|
||||
inline void ResetVelocityFunction();
|
||||
|
||||
inline void SetAngularDamping(float angularDamping);
|
||||
inline void SetAngularVelocity(const Nz::RadianAnglef& angularVelocity);
|
||||
inline void SetElasticity(float elasticity);
|
||||
inline void SetElasticity(std::size_t shapeIndex, float friction);
|
||||
inline void SetFriction(float friction);
|
||||
inline void SetFriction(std::size_t shapeIndex, float friction);
|
||||
inline void SetMass(float mass, bool recomputeMoment = true);
|
||||
inline void SetMassCenter(const Nz::Vector2f& center, Nz::CoordSys coordSys = Nz::CoordSys_Local);
|
||||
inline void SetMomentOfInertia(float moment);
|
||||
inline void SetPosition(const Nz::Vector2f& position);
|
||||
inline void SetRotation(const Nz::RadianAnglef& rotation);
|
||||
inline void SetSurfaceVelocity(const Nz::Vector2f& velocity);
|
||||
inline void SetSurfaceVelocity(std::size_t shapeIndex, const Nz::Vector2f& velocity);
|
||||
inline void SetVelocity(const Nz::Vector2f& velocity);
|
||||
inline void SetVelocityFunction(VelocityFunc velocityFunc);
|
||||
|
||||
inline void UpdateVelocity(const Nz::Vector2f& gravity, float damping, float deltaTime);
|
||||
|
||||
inline void Wakeup();
|
||||
|
||||
static ComponentIndex componentIndex;
|
||||
|
||||
private:
|
||||
inline void ApplyPhysicsState(Nz::RigidBody2D& rigidBody) const;
|
||||
inline void CopyPhysicsState(const Nz::RigidBody2D& rigidBody);
|
||||
Nz::RigidBody2D* GetRigidBody();
|
||||
const Nz::RigidBody2D* GetRigidBody() const;
|
||||
|
||||
void OnAttached() override;
|
||||
void OnComponentAttached(BaseComponent& component) override;
|
||||
|
|
@ -60,7 +100,28 @@ namespace Ndk
|
|||
void OnDetached() override;
|
||||
void OnEntityDestruction() override;
|
||||
|
||||
struct PendingPhysObjectStates
|
||||
{
|
||||
struct ShapeStates
|
||||
{
|
||||
Nz::Vector2f surfaceVelocity;
|
||||
float elasticity;
|
||||
float friction;
|
||||
};
|
||||
|
||||
VelocityFunc velocityFunc;
|
||||
std::vector<ShapeStates> shapes;
|
||||
Nz::RadianAnglef angularVelocity;
|
||||
Nz::Vector2f massCenter;
|
||||
Nz::Vector2f velocity;
|
||||
bool valid = false;
|
||||
float mass;
|
||||
float momentOfInertia;
|
||||
};
|
||||
|
||||
std::unique_ptr<Nz::RigidBody2D> m_object;
|
||||
PendingPhysObjectStates m_pendingStates;
|
||||
bool m_nodeSynchronizationEnabled;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,16 +7,22 @@
|
|||
|
||||
namespace Ndk
|
||||
{
|
||||
/*!
|
||||
* \brief Constructs a PhysicsComponent2D object by default
|
||||
*/
|
||||
inline PhysicsComponent2D::PhysicsComponent2D() :
|
||||
m_nodeSynchronizationEnabled(true)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Constructs a PhysicsComponent2D object by copy semantic
|
||||
*
|
||||
* \param physics PhysicsComponent2D to copy
|
||||
*/
|
||||
|
||||
inline PhysicsComponent2D::PhysicsComponent2D(const PhysicsComponent2D& physics)
|
||||
{
|
||||
// No copy of physical object (because we only create it when attached to an entity)
|
||||
NazaraUnused(physics);
|
||||
CopyPhysicsState(*physics.GetRigidBody());
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -91,7 +97,7 @@ namespace Ndk
|
|||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*/
|
||||
|
||||
inline void PhysicsComponent2D::AddTorque(float torque)
|
||||
inline void PhysicsComponent2D::AddTorque(const Nz::RadianAnglef& torque)
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
|
|
@ -115,6 +121,41 @@ namespace Ndk
|
|||
return m_object->ClosestPointQuery(position, closestPoint, closestDistance);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enables position/rotation synchronization with the NodeComponent
|
||||
*
|
||||
* By default, at every update of the PhysicsSystem2D, the NodeComponent's position and rotation (if any) will be synchronized with
|
||||
* the values of the PhysicsComponent2D. This function allows to enable/disable this behavior on a per-entity basis.
|
||||
*
|
||||
* \param nodeSynchronization Should synchronization occur between NodeComponent and PhysicsComponent2D
|
||||
*/
|
||||
inline void PhysicsComponent2D::EnableNodeSynchronization(bool nodeSynchronization)
|
||||
{
|
||||
m_nodeSynchronizationEnabled = nodeSynchronization;
|
||||
|
||||
if (m_entity)
|
||||
m_entity->Invalidate();
|
||||
}
|
||||
|
||||
/*!
|
||||
TODO
|
||||
*/
|
||||
inline void PhysicsComponent2D::ForceSleep()
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
return m_object->ForceSleep();
|
||||
}
|
||||
|
||||
/*!
|
||||
TODO
|
||||
*/
|
||||
inline void PhysicsComponent2D::ForEachArbiter(const std::function<void(Nz::Arbiter2D&)>& callback)
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
return m_object->ForEachArbiter(callback);
|
||||
}
|
||||
/*!
|
||||
* \brief Gets the AABB of the physics object
|
||||
* \return AABB of the object
|
||||
|
|
@ -128,6 +169,22 @@ namespace Ndk
|
|||
return m_object->GetAABB();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the angular damping or moment of inertia of the physics object
|
||||
* \return Angular damping of the object
|
||||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*
|
||||
* \see GetMomentOfInertia
|
||||
*/
|
||||
|
||||
inline float PhysicsComponent2D::GetAngularDamping() const
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
return m_object->GetAngularDamping();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the angular velocity of the physics object
|
||||
* \return Angular velocity of the object
|
||||
|
|
@ -135,7 +192,7 @@ namespace Ndk
|
|||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*/
|
||||
|
||||
inline float PhysicsComponent2D::GetAngularVelocity() const
|
||||
inline Nz::RadianAnglef PhysicsComponent2D::GetAngularVelocity() const
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
|
|
@ -155,7 +212,37 @@ namespace Ndk
|
|||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
return m_object->GetCenterOfGravity(coordSys);
|
||||
return m_object->GetMassCenter(coordSys);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the elasticity of a shape belonging to this physics object
|
||||
* \return Elasticity of the shape
|
||||
*
|
||||
* \param shapeIndex Shape index of the collider we're interested
|
||||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*/
|
||||
inline float PhysicsComponent2D::GetElasticity(std::size_t shapeIndex) const
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
return m_object->GetElasticity(shapeIndex);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the friction of a shape belonging to this physics object
|
||||
* \return Friction of the shape
|
||||
*
|
||||
* \param shapeIndex Shape index of the collider we're interested
|
||||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*/
|
||||
inline float PhysicsComponent2D::GetFriction(std::size_t shapeIndex) const
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
return m_object->GetFriction(shapeIndex);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -164,7 +251,6 @@ namespace Ndk
|
|||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*/
|
||||
|
||||
inline float PhysicsComponent2D::GetMass() const
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
|
@ -172,6 +258,38 @@ namespace Ndk
|
|||
return m_object->GetMass();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the gravity center of the physics object
|
||||
* \return Gravity center of the object
|
||||
*
|
||||
* \param coordSys System coordinates to consider
|
||||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*/
|
||||
|
||||
inline Nz::Vector2f PhysicsComponent2D::GetMassCenter(Nz::CoordSys coordSys) const
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
return m_object->GetMassCenter(coordSys);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the angular damping or moment of inertia of the physics object
|
||||
* \return Moment of inertia of the object
|
||||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*
|
||||
* \see GetAngularDamping
|
||||
*/
|
||||
|
||||
inline float PhysicsComponent2D::GetMomentOfInertia() const
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
return m_object->GetMomentOfInertia();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the position of the physics object
|
||||
* \return Position of the object
|
||||
|
|
@ -192,21 +310,43 @@ namespace Ndk
|
|||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*/
|
||||
|
||||
inline float PhysicsComponent2D::GetRotation() const
|
||||
inline Nz::RadianAnglef PhysicsComponent2D::GetRotation() const
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
return m_object->GetRotation();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the surface velocity of a shape belonging to this physics object
|
||||
* \return Surface velocity of the shape
|
||||
*
|
||||
* \param shapeIndex Shape index of the collider we're interested
|
||||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*/
|
||||
inline Nz::Vector2f PhysicsComponent2D::GetSurfaceVelocity(std::size_t shapeIndex) const
|
||||
{
|
||||
return m_object->GetSurfaceVelocity(shapeIndex);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the rotation of the physics object
|
||||
* \return Shape count of the object
|
||||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*/
|
||||
inline std::size_t PhysicsComponent2D::GetShapeCount() const
|
||||
{
|
||||
return m_object->GetShapeCount();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the velocity of the physics object
|
||||
* \return Velocity of the object
|
||||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*/
|
||||
|
||||
inline Nz::Vector2f PhysicsComponent2D::GetVelocity() const
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
|
@ -214,13 +354,36 @@ namespace Ndk
|
|||
return m_object->GetVelocity();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the custom velocity function of the physics object
|
||||
* \return Velocity function of the object (may be empty if default function is used)
|
||||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*/
|
||||
inline auto PhysicsComponent2D::GetVelocityFunction() const -> const VelocityFunc&
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
return m_object->GetVelocityFunction();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks if position & rotation are synchronized with NodeComponent
|
||||
* \return true If synchronization is enabled
|
||||
*
|
||||
* \see EnableNodeSynchronization
|
||||
*/
|
||||
inline bool PhysicsComponent2D::IsNodeSynchronizationEnabled() const
|
||||
{
|
||||
return m_nodeSynchronizationEnabled;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the entity is currently sleeping
|
||||
* \return true If it is the case
|
||||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*/
|
||||
|
||||
inline bool PhysicsComponent2D::IsSleeping() const
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
|
@ -228,6 +391,47 @@ namespace Ndk
|
|||
return m_object->IsSleeping();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks if this component is bound to a valid rigid body
|
||||
*
|
||||
* A component may not be bound to a rigid body if the component is not bound to an entity or if this entity is being destroyed
|
||||
*
|
||||
* \return true If bound, false otherwise
|
||||
*/
|
||||
inline bool PhysicsComponent2D::IsValid() const
|
||||
{
|
||||
return bool(m_object);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Reset velocity function to default one
|
||||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*/
|
||||
inline void PhysicsComponent2D::ResetVelocityFunction()
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
return m_object->ResetVelocityFunction();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the angular damping or moment of inertia of the physics object
|
||||
*
|
||||
* \param angularDamping Angular damping of the object
|
||||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*
|
||||
* \see SetMomentOfInertia
|
||||
*/
|
||||
|
||||
inline void PhysicsComponent2D::SetAngularDamping(float angularDamping)
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
m_object->SetAngularDamping(angularDamping);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the angular velocity of the physics object
|
||||
*
|
||||
|
|
@ -235,29 +439,93 @@ namespace Ndk
|
|||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*/
|
||||
|
||||
inline void PhysicsComponent2D::SetAngularVelocity(float angularVelocity)
|
||||
inline void PhysicsComponent2D::SetAngularVelocity(const Nz::RadianAnglef& angularVelocity)
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
m_object->SetAngularVelocity(angularVelocity);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the elasticity of the whole physics object
|
||||
*
|
||||
* Overrides all shapes elasticity with a single value
|
||||
*
|
||||
* \param elasticity Elasticity to be applied
|
||||
*
|
||||
* \remark Elasticity must be positive or zero
|
||||
*/
|
||||
inline void PhysicsComponent2D::SetElasticity(float elasticity)
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
NazaraAssert(elasticity >= 0.f, "Friction must be positive");
|
||||
|
||||
m_object->SetElasticity(elasticity);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the elasticity of a single shape of the physics object
|
||||
*
|
||||
* \param shapeIndex Target shape index
|
||||
* \param elasticity Elasticity to be applied
|
||||
*
|
||||
* \remark Elasticity must be positive or zero
|
||||
*/
|
||||
inline void PhysicsComponent2D::SetElasticity(std::size_t shapeIndex, float elasticity)
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
NazaraAssert(elasticity >= 0.f, "Friction must be positive");
|
||||
|
||||
m_object->SetElasticity(shapeIndex, elasticity);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the friction of the whole physics object
|
||||
*
|
||||
* Overrides all shapes friction with a single value
|
||||
*
|
||||
* \param friction Friction to be applied
|
||||
*
|
||||
* \remark Friction must be positive or zero
|
||||
*/
|
||||
inline void PhysicsComponent2D::SetFriction(float friction)
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
NazaraAssert(friction >= 0.f, "Friction must be positive");
|
||||
|
||||
m_object->SetFriction(friction);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the friction of a single shape of the physics object
|
||||
*
|
||||
* \param shapeIndex Target shape index
|
||||
* \param friction Friction to be applied
|
||||
*
|
||||
* \remark Friction must be positive or zero
|
||||
*/
|
||||
inline void PhysicsComponent2D::SetFriction(std::size_t shapeIndex, float friction)
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
NazaraAssert(friction >= 0.f, "Friction must be positive");
|
||||
|
||||
m_object->SetFriction(shapeIndex, friction);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the mass of the physics object
|
||||
*
|
||||
* \param mass Mass of the object
|
||||
* \param recomputeMoment Should the moment of inertia be recomputed according to the new mass
|
||||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
* \remark Produces a NazaraAssert if the mass is negative
|
||||
* \remark Mass must be positive or zero
|
||||
*/
|
||||
|
||||
inline void PhysicsComponent2D::SetMass(float mass)
|
||||
inline void PhysicsComponent2D::SetMass(float mass, bool recomputeMoment)
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
NazaraAssert(mass > 0.f, "Mass should be positive");
|
||||
NazaraAssert(mass >= 0.f, "Mass should be positive");
|
||||
|
||||
m_object->SetMass(mass);
|
||||
m_object->SetMass(mass, recomputeMoment);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -267,12 +535,27 @@ namespace Ndk
|
|||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*/
|
||||
|
||||
inline void PhysicsComponent2D::SetMassCenter(const Nz::Vector2f& center)
|
||||
inline void PhysicsComponent2D::SetMassCenter(const Nz::Vector2f& center, Nz::CoordSys coordSys)
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
m_object->SetMassCenter(center);
|
||||
m_object->SetMassCenter(center, coordSys);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the angular damping or moment of inertia of the physics object
|
||||
*
|
||||
* \param moment Moment of inertia of the object
|
||||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*
|
||||
* \see SetAngularDamping
|
||||
*/
|
||||
inline void PhysicsComponent2D::SetMomentOfInertia(float moment)
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
m_object->SetMomentOfInertia(moment);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -282,7 +565,6 @@ namespace Ndk
|
|||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*/
|
||||
|
||||
inline void PhysicsComponent2D::SetPosition(const Nz::Vector2f& position)
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
|
@ -297,22 +579,45 @@ namespace Ndk
|
|||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*/
|
||||
|
||||
inline void PhysicsComponent2D::SetRotation(float rotation)
|
||||
inline void PhysicsComponent2D::SetRotation(const Nz::RadianAnglef& rotation)
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
m_object->SetRotation(rotation);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the surface velocity of the whole physics object
|
||||
*
|
||||
* Overrides all shapes surface velocity with a single value
|
||||
*
|
||||
* \param velocity Surface velocity to be applied
|
||||
*/
|
||||
inline void PhysicsComponent2D::SetSurfaceVelocity(const Nz::Vector2f& velocity)
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
m_object->SetSurfaceVelocity(velocity);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the surface velocity of a single shape of the physics object
|
||||
*
|
||||
* \param shapeIndex Target shape index
|
||||
* \param velocity Surface velocity to be applied
|
||||
*/
|
||||
inline void PhysicsComponent2D::SetSurfaceVelocity(std::size_t shapeIndex, const Nz::Vector2f& velocity)
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
m_object->SetSurfaceVelocity(shapeIndex, velocity);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the velocity of the physics object
|
||||
*
|
||||
* \param velocity Velocity of the object
|
||||
*
|
||||
* \remark Produces a NazaraAssert if the physics object is invalid
|
||||
*/
|
||||
|
||||
inline void PhysicsComponent2D::SetVelocity(const Nz::Vector2f& velocity)
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
|
@ -320,13 +625,101 @@ namespace Ndk
|
|||
m_object->SetVelocity(velocity);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets a custom velocity function for the physics object
|
||||
*
|
||||
* A velocity function is called (for non-kinematic and non-static objects) at every physics update to compute the new velocity of the object.
|
||||
* You may call UpdateVelocity (the default velocity function) to let the physics engine compute that itself and then adjust it using GetVelocity/SetVelocity as you need.
|
||||
*
|
||||
* \param velocityFunc New custom velocity function
|
||||
*
|
||||
* \remark Passing an empty VelocityFunc has the same effect as calling ResetVelocityFunction
|
||||
* \see ResetVelocityFunction
|
||||
* \see UpdateVelocity
|
||||
*/
|
||||
inline void PhysicsComponent2D::SetVelocityFunction(VelocityFunc velocityFunc)
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
m_object->SetVelocityFunction(std::move(velocityFunc));
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Calls the physics engine default velocity function
|
||||
*
|
||||
* \param gravity Physics system gravity
|
||||
* \param damping Physics system damping (adjusted to deltaTime)
|
||||
* \param deltaTime Elapsed time since last physics update
|
||||
*/
|
||||
inline void PhysicsComponent2D::UpdateVelocity(const Nz::Vector2f& gravity, float damping, float deltaTime)
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
m_object->UpdateVelocity(gravity, damping, deltaTime);
|
||||
}
|
||||
|
||||
/*!
|
||||
TODO
|
||||
*/
|
||||
inline void PhysicsComponent2D::Wakeup()
|
||||
{
|
||||
NazaraAssert(m_object, "Invalid physics object");
|
||||
|
||||
return m_object->Wakeup();
|
||||
}
|
||||
|
||||
inline void PhysicsComponent2D::ApplyPhysicsState(Nz::RigidBody2D& rigidBody) const
|
||||
{
|
||||
assert(m_pendingStates.valid);
|
||||
|
||||
rigidBody.SetAngularVelocity(m_pendingStates.angularVelocity);
|
||||
rigidBody.SetMass(m_pendingStates.mass);
|
||||
rigidBody.SetMassCenter(m_pendingStates.massCenter);
|
||||
rigidBody.SetMomentOfInertia(m_pendingStates.momentOfInertia);
|
||||
rigidBody.SetVelocity(m_pendingStates.velocity);
|
||||
rigidBody.SetVelocityFunction(m_pendingStates.velocityFunc);
|
||||
|
||||
for (std::size_t i = 0; i < m_pendingStates.shapes.size(); ++i)
|
||||
{
|
||||
auto& shapeData = m_pendingStates.shapes[i];
|
||||
rigidBody.SetElasticity(i, shapeData.elasticity);
|
||||
rigidBody.SetFriction(i, shapeData.friction);
|
||||
rigidBody.SetSurfaceVelocity(i, shapeData.surfaceVelocity);
|
||||
}
|
||||
}
|
||||
|
||||
inline void PhysicsComponent2D::CopyPhysicsState(const Nz::RigidBody2D& rigidBody)
|
||||
{
|
||||
m_pendingStates.valid = true;
|
||||
|
||||
m_pendingStates.angularVelocity = rigidBody.GetAngularVelocity();
|
||||
m_pendingStates.mass = rigidBody.GetMass();
|
||||
m_pendingStates.massCenter = rigidBody.GetMassCenter();
|
||||
m_pendingStates.momentOfInertia = rigidBody.GetMomentOfInertia();
|
||||
m_pendingStates.velocity = rigidBody.GetVelocity();
|
||||
m_pendingStates.velocityFunc = rigidBody.GetVelocityFunction();
|
||||
|
||||
m_pendingStates.shapes.resize(rigidBody.GetShapeCount());
|
||||
for (std::size_t i = 0; i < m_pendingStates.shapes.size(); ++i)
|
||||
{
|
||||
auto& shapeData = m_pendingStates.shapes[i];
|
||||
shapeData.elasticity = rigidBody.GetElasticity(i);
|
||||
shapeData.friction = rigidBody.GetFriction(i);
|
||||
shapeData.surfaceVelocity = rigidBody.GetSurfaceVelocity(i);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the underlying physics object
|
||||
* \return A reference to the physics object
|
||||
*/
|
||||
|
||||
inline Nz::RigidBody2D* PhysicsComponent2D::GetRigidBody()
|
||||
{
|
||||
return m_object.get();
|
||||
}
|
||||
|
||||
inline const Nz::RigidBody2D* PhysicsComponent2D::GetRigidBody() const
|
||||
{
|
||||
return m_object.get();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@
|
|||
|
||||
namespace Ndk
|
||||
{
|
||||
class PhysicsComponent3D;
|
||||
|
||||
using PhysicsComponent3DHandle = Nz::ObjectHandle<PhysicsComponent3D>;
|
||||
|
||||
class NDK_API PhysicsComponent3D : public Component<PhysicsComponent3D>
|
||||
{
|
||||
friend class CollisionComponent3D;
|
||||
|
|
@ -23,49 +27,49 @@ namespace Ndk
|
|||
PhysicsComponent3D(const PhysicsComponent3D& physics);
|
||||
~PhysicsComponent3D() = default;
|
||||
|
||||
void AddForce(const Nz::Vector3f& force, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||
void AddForce(const Nz::Vector3f& force, const Nz::Vector3f& point, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||
void AddTorque(const Nz::Vector3f& torque, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||
inline void AddForce(const Nz::Vector3f& force, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||
inline void AddForce(const Nz::Vector3f& force, const Nz::Vector3f& point, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||
inline void AddTorque(const Nz::Vector3f& torque, Nz::CoordSys coordSys = Nz::CoordSys_Global);
|
||||
|
||||
void EnableAutoSleep(bool autoSleep);
|
||||
void EnableNodeSynchronization(bool nodeSynchronization);
|
||||
inline void EnableAutoSleep(bool autoSleep);
|
||||
inline void EnableNodeSynchronization(bool nodeSynchronization);
|
||||
|
||||
Nz::Boxf GetAABB() const;
|
||||
Nz::Vector3f GetAngularDamping() const;
|
||||
Nz::Vector3f GetAngularVelocity() const;
|
||||
float GetGravityFactor() const;
|
||||
float GetLinearDamping() const;
|
||||
Nz::Vector3f GetLinearVelocity() const;
|
||||
float GetMass() const;
|
||||
Nz::Vector3f GetMassCenter(Nz::CoordSys coordSys = Nz::CoordSys_Local) const;
|
||||
const Nz::Matrix4f& GetMatrix() const;
|
||||
Nz::Vector3f GetPosition() const;
|
||||
Nz::Quaternionf GetRotation() const;
|
||||
inline Nz::Boxf GetAABB() const;
|
||||
inline Nz::Vector3f GetAngularDamping() const;
|
||||
inline Nz::Vector3f GetAngularVelocity() const;
|
||||
inline float GetGravityFactor() const;
|
||||
inline float GetLinearDamping() const;
|
||||
inline Nz::Vector3f GetLinearVelocity() const;
|
||||
inline float GetMass() const;
|
||||
inline Nz::Vector3f GetMassCenter(Nz::CoordSys coordSys = Nz::CoordSys_Local) const;
|
||||
inline const Nz::Matrix4f& GetMatrix() const;
|
||||
inline Nz::Vector3f GetPosition() const;
|
||||
inline Nz::Quaternionf GetRotation() const;
|
||||
|
||||
bool IsAutoSleepEnabled() const;
|
||||
bool IsMoveable() const;
|
||||
bool IsNodeSynchronizationEnabled() const;
|
||||
bool IsSleeping() const;
|
||||
inline bool IsAutoSleepEnabled() const;
|
||||
inline bool IsMoveable() const;
|
||||
inline bool IsNodeSynchronizationEnabled() const;
|
||||
inline bool IsSleeping() const;
|
||||
|
||||
void SetAngularDamping(const Nz::Vector3f& angularDamping);
|
||||
void SetAngularVelocity(const Nz::Vector3f& angularVelocity);
|
||||
void SetGravityFactor(float gravityFactor);
|
||||
void SetLinearDamping(float damping);
|
||||
void SetLinearVelocity(const Nz::Vector3f& velocity);
|
||||
void SetMass(float mass);
|
||||
void SetMassCenter(const Nz::Vector3f& center);
|
||||
void SetMaterial(const Nz::String& materialName);
|
||||
void SetMaterial(int materialIndex);
|
||||
void SetPosition(const Nz::Vector3f& position);
|
||||
void SetRotation(const Nz::Quaternionf& rotation);
|
||||
inline void SetAngularDamping(const Nz::Vector3f& angularDamping);
|
||||
inline void SetAngularVelocity(const Nz::Vector3f& angularVelocity);
|
||||
inline void SetGravityFactor(float gravityFactor);
|
||||
inline void SetLinearDamping(float damping);
|
||||
inline void SetLinearVelocity(const Nz::Vector3f& velocity);
|
||||
inline void SetMass(float mass);
|
||||
inline void SetMassCenter(const Nz::Vector3f& center);
|
||||
inline void SetMaterial(const Nz::String& materialName);
|
||||
inline void SetMaterial(int materialIndex);
|
||||
inline void SetPosition(const Nz::Vector3f& position);
|
||||
inline void SetRotation(const Nz::Quaternionf& rotation);
|
||||
|
||||
static ComponentIndex componentIndex;
|
||||
|
||||
private:
|
||||
void ApplyPhysicsState(Nz::RigidBody3D& rigidBody) const;
|
||||
void CopyPhysicsState(const Nz::RigidBody3D& rigidBody);
|
||||
Nz::RigidBody3D* GetRigidBody();
|
||||
const Nz::RigidBody3D& GetRigidBody() const;
|
||||
inline void ApplyPhysicsState(Nz::RigidBody3D& rigidBody) const;
|
||||
inline void CopyPhysicsState(const Nz::RigidBody3D& rigidBody);
|
||||
inline Nz::RigidBody3D* GetRigidBody();
|
||||
inline const Nz::RigidBody3D& GetRigidBody() const;
|
||||
|
||||
void OnAttached() override;
|
||||
void OnComponentAttached(BaseComponent& component) override;
|
||||
|
|
|
|||
|
|
@ -16,13 +16,14 @@ namespace Ndk
|
|||
|
||||
using VelocityComponentHandle = Nz::ObjectHandle<VelocityComponent>;
|
||||
|
||||
class NDK_API VelocityComponent : public Component<VelocityComponent>, public Nz::HandledObject<VelocityComponent>
|
||||
class NDK_API VelocityComponent : public Component<VelocityComponent>
|
||||
{
|
||||
public:
|
||||
VelocityComponent(const Nz::Vector3f& velocity = Nz::Vector3f::Zero());
|
||||
VelocityComponent(const Nz::Vector3f& velocity = Nz::Vector3f::Zero(), Nz::CoordSys coordSystem = Nz::CoordSys_Global);
|
||||
~VelocityComponent() = default;
|
||||
|
||||
Nz::Vector3f linearVelocity;
|
||||
Nz::CoordSys coordSys;
|
||||
|
||||
VelocityComponent& operator=(const Nz::Vector3f& vel);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ namespace Ndk
|
|||
* \param velocity Linear velocity
|
||||
*/
|
||||
|
||||
inline VelocityComponent::VelocityComponent(const Nz::Vector3f& velocity) :
|
||||
linearVelocity(velocity)
|
||||
inline VelocityComponent::VelocityComponent(const Nz::Vector3f& velocity, Nz::CoordSys coordSystem) :
|
||||
linearVelocity(velocity),
|
||||
coordSys(coordSystem)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,24 +14,29 @@
|
|||
#include <Nazara/Graphics/TextSprite.hpp>
|
||||
#include <Nazara/Utility/Node.hpp>
|
||||
#include <Nazara/Utility/SimpleTextDrawer.hpp>
|
||||
#include <NDK/BaseWidget.hpp>
|
||||
#include <NDK/EntityOwner.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
class LuaState;
|
||||
struct WindowEvent;
|
||||
}
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
class AbstractTextAreaWidget;
|
||||
class Console;
|
||||
class Entity;
|
||||
class RichTextAreaWidget;
|
||||
class ScrollAreaWidget;
|
||||
class TextAreaWidget;
|
||||
|
||||
using ConsoleHandle = Nz::ObjectHandle<Console>;
|
||||
|
||||
class NDK_API Console : public Nz::Node, public Nz::HandledObject<Console>
|
||||
class NDK_API Console : public BaseWidget, public Nz::HandledObject<Console>
|
||||
{
|
||||
public:
|
||||
Console(World& world, const Nz::Vector2f& size, Nz::LuaState& state);
|
||||
Console(BaseWidget* parent);
|
||||
Console(const Console& console) = delete;
|
||||
Console(Console&& console) = default;
|
||||
~Console() = default;
|
||||
|
|
@ -39,34 +44,25 @@ namespace Ndk
|
|||
void AddLine(const Nz::String& text, const Nz::Color& color = Nz::Color::White);
|
||||
|
||||
void Clear();
|
||||
void ClearFocus();
|
||||
|
||||
inline unsigned int GetCharacterSize() const;
|
||||
inline const EntityHandle& GetHistory() const;
|
||||
inline const EntityHandle& GetHistoryBackground() const;
|
||||
inline const EntityHandle& GetInput() const;
|
||||
inline const EntityHandle& GetInputBackground() const;
|
||||
inline const Nz::Vector2f& GetSize() const;
|
||||
inline const RichTextAreaWidget* GetHistory() const;
|
||||
inline const TextAreaWidget* GetInput() const;
|
||||
inline const Nz::FontRef& GetTextFont() const;
|
||||
|
||||
inline bool IsVisible() const;
|
||||
|
||||
void SendCharacter(char32_t character);
|
||||
void SendEvent(const Nz::WindowEvent& event);
|
||||
|
||||
void SetCharacterSize(unsigned int size);
|
||||
void SetSize(const Nz::Vector2f& size);
|
||||
void SetFocus();
|
||||
void SetTextFont(Nz::FontRef font);
|
||||
|
||||
void Show(bool show = true);
|
||||
|
||||
Console& operator=(const Console& console) = delete;
|
||||
Console& operator=(Console&& console) = default;
|
||||
|
||||
NazaraSignal(OnCommand, Console* /*console*/, const Nz::String& /*command*/);
|
||||
|
||||
private:
|
||||
void AddLineInternal(const Nz::String& text, const Nz::Color& color = Nz::Color::White);
|
||||
void ExecuteInput();
|
||||
void Layout();
|
||||
void RefreshHistory();
|
||||
void ExecuteInput(const AbstractTextAreaWidget* textArea, bool* ignoreDefaultAction);
|
||||
void Layout() override;
|
||||
|
||||
struct Line
|
||||
{
|
||||
|
|
@ -77,20 +73,10 @@ namespace Ndk
|
|||
std::size_t m_historyPosition;
|
||||
std::vector<Nz::String> m_commandHistory;
|
||||
std::vector<Line> m_historyLines;
|
||||
EntityOwner m_historyBackground;
|
||||
EntityOwner m_history;
|
||||
EntityOwner m_input;
|
||||
EntityOwner m_inputBackground;
|
||||
ScrollAreaWidget* m_historyArea;
|
||||
RichTextAreaWidget* m_history;
|
||||
TextAreaWidget* m_input;
|
||||
Nz::FontRef m_defaultFont;
|
||||
Nz::LuaState& m_state;
|
||||
Nz::SpriteRef m_historyBackgroundSprite;
|
||||
Nz::SpriteRef m_inputBackgroundSprite;
|
||||
Nz::SimpleTextDrawer m_historyDrawer;
|
||||
Nz::SimpleTextDrawer m_inputDrawer;
|
||||
Nz::TextSpriteRef m_historyTextSprite;
|
||||
Nz::TextSpriteRef m_inputTextSprite;
|
||||
Nz::Vector2f m_size;
|
||||
bool m_opened;
|
||||
unsigned int m_characterSize;
|
||||
unsigned int m_maxHistoryLines;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,51 +19,21 @@ namespace Ndk
|
|||
* \return History of the console
|
||||
*/
|
||||
|
||||
inline const EntityHandle& Console::GetHistory() const
|
||||
inline const RichTextAreaWidget* Console::GetHistory() const
|
||||
{
|
||||
return m_history;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the entity representing the background of the console's history
|
||||
* \return Background history of the console
|
||||
*/
|
||||
|
||||
inline const EntityHandle& Console::GetHistoryBackground() const
|
||||
{
|
||||
return m_historyBackground;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the entity representing the input of the console
|
||||
* \return Input of the console
|
||||
*/
|
||||
|
||||
inline const EntityHandle& Console::GetInput() const
|
||||
inline const TextAreaWidget* Console::GetInput() const
|
||||
{
|
||||
return m_input;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the entity representing the background of the console's input
|
||||
* \return Background input of the console
|
||||
*/
|
||||
|
||||
inline const EntityHandle& Console::GetInputBackground() const
|
||||
{
|
||||
return m_inputBackground;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the size of the console
|
||||
* \return Size (Width, Height) of the console
|
||||
*/
|
||||
|
||||
inline const Nz::Vector2f& Console::GetSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the font used by the console
|
||||
* \return A reference to the font currenty used
|
||||
|
|
@ -73,14 +43,4 @@ namespace Ndk
|
|||
{
|
||||
return m_defaultFont;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether the console is visible
|
||||
* \return true If it is the case
|
||||
*/
|
||||
|
||||
inline bool Console::IsVisible() const
|
||||
{
|
||||
return m_opened;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
#define NDK_ENTITY_HPP
|
||||
|
||||
#include <Nazara/Core/Bitset.hpp>
|
||||
#include <Nazara/Core/HandledObject.hpp>
|
||||
#include <Nazara/Core/MovablePtr.hpp>
|
||||
#include <Nazara/Core/ObjectHandle.hpp>
|
||||
#include <Nazara/Core/Signal.hpp>
|
||||
#include <NDK/Algorithm.hpp>
|
||||
#include <NDK/Prerequisites.hpp>
|
||||
|
|
@ -43,6 +43,10 @@ namespace Ndk
|
|||
const EntityHandle& Clone() const;
|
||||
|
||||
inline void Disable();
|
||||
|
||||
std::unique_ptr<BaseComponent> DropComponent(ComponentIndex index);
|
||||
template<typename ComponentType> std::unique_ptr<BaseComponent> DropComponent();
|
||||
|
||||
void Enable(bool enable = true);
|
||||
|
||||
inline BaseComponent& GetComponent(ComponentIndex index);
|
||||
|
|
@ -61,6 +65,7 @@ namespace Ndk
|
|||
|
||||
void Invalidate();
|
||||
inline bool IsEnabled() const;
|
||||
bool IsDying() const;
|
||||
inline bool IsValid() const;
|
||||
|
||||
inline void RemoveAllComponents();
|
||||
|
|
@ -73,6 +78,8 @@ namespace Ndk
|
|||
Entity& operator=(Entity&&) = delete;
|
||||
|
||||
NazaraSignal(OnEntityDestruction, Entity* /*entity*/);
|
||||
NazaraSignal(OnEntityDisabled, Entity* /*entity*/);
|
||||
NazaraSignal(OnEntityEnabled, Entity* /*entity*/);
|
||||
|
||||
private:
|
||||
Entity(World* world, EntityId id);
|
||||
|
|
@ -80,8 +87,6 @@ namespace Ndk
|
|||
void Create();
|
||||
void Destroy();
|
||||
|
||||
void DestroyComponent(ComponentIndex index);
|
||||
|
||||
inline Nz::Bitset<>& GetRemovedComponentBits();
|
||||
|
||||
inline void RegisterEntityList(EntityList* list);
|
||||
|
|
|
|||
|
|
@ -64,6 +64,15 @@ namespace Ndk
|
|||
* \remark Produces a NazaraAssert if component is not available in this entity
|
||||
*/
|
||||
|
||||
template<typename ComponentType>
|
||||
std::unique_ptr<BaseComponent> Entity::DropComponent()
|
||||
{
|
||||
static_assert(std::is_base_of<BaseComponent, ComponentType>::value, "ComponentType is not a component");
|
||||
|
||||
ComponentIndex index = GetComponentIndex<ComponentType>();
|
||||
return DropComponent(index);
|
||||
}
|
||||
|
||||
template<typename ComponentType>
|
||||
ComponentType& Entity::GetComponent()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,11 +15,12 @@ namespace Ndk
|
|||
{
|
||||
public:
|
||||
EntityOwner() = default;
|
||||
explicit EntityOwner(Entity* entity);
|
||||
EntityOwner(Entity* entity);
|
||||
EntityOwner(const EntityOwner& handle) = delete;
|
||||
EntityOwner(EntityOwner&& handle) noexcept = default;
|
||||
~EntityOwner();
|
||||
|
||||
void Release();
|
||||
void Reset(Entity* entity = nullptr);
|
||||
void Reset(EntityOwner&& handle);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#include <NDK/EntityOwner.hpp>
|
||||
#include <Nazara/Core/StringStream.hpp>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
|
|
@ -36,16 +37,23 @@ namespace Ndk
|
|||
Reset(nullptr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Release the ownership of the entity without killing it
|
||||
*/
|
||||
inline void EntityOwner::Release()
|
||||
{
|
||||
EntityHandle::Reset(nullptr);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Resets the ownership of the entity, previous is killed
|
||||
*
|
||||
* \param entity Entity to own
|
||||
*/
|
||||
|
||||
inline void EntityOwner::Reset(Entity* entity)
|
||||
{
|
||||
if (m_object)
|
||||
m_object->Kill();
|
||||
if (IsValid())
|
||||
GetObject()->Kill();
|
||||
|
||||
EntityHandle::Reset(entity);
|
||||
}
|
||||
|
|
@ -55,11 +63,10 @@ namespace Ndk
|
|||
*
|
||||
* \param handle EntityOwner to move into this
|
||||
*/
|
||||
|
||||
inline void EntityOwner::Reset(EntityOwner&& handle)
|
||||
{
|
||||
Reset(handle.GetObject());
|
||||
handle.m_object = nullptr;
|
||||
handle.Release();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
|||
|
|
@ -125,14 +125,14 @@ namespace Nz
|
|||
state.Pop();
|
||||
}
|
||||
|
||||
mat->Set(values);
|
||||
*mat = Matrix4d(values);
|
||||
return 1;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
if (state.IsOfType(index, "Matrix4"))
|
||||
mat->Set(*static_cast<Matrix4d*>(state.ToUserdata(index)));
|
||||
*mat = *static_cast<Matrix4d*>(state.ToUserdata(index));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -269,6 +269,15 @@ namespace Nz
|
|||
return ret;
|
||||
}
|
||||
|
||||
inline unsigned int LuaImplQueryArg(const LuaState& state, int index, Vector2i* vec, TypeTag<Vector2i>)
|
||||
{
|
||||
Vector2d vecDouble;
|
||||
unsigned int ret = LuaImplQueryArg(state, index, &vecDouble, TypeTag<Vector2d>());
|
||||
|
||||
vec->Set(vecDouble);
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline unsigned int LuaImplQueryArg(const LuaState& state, int index, Vector3d* vec, TypeTag<Vector3d>)
|
||||
{
|
||||
switch (state.GetType(index))
|
||||
|
|
@ -308,6 +317,15 @@ namespace Nz
|
|||
return ret;
|
||||
}
|
||||
|
||||
inline unsigned int LuaImplQueryArg(const LuaState& state, int index, Vector3i* vec, TypeTag<Vector3i>)
|
||||
{
|
||||
Vector3d vecDouble;
|
||||
unsigned int ret = LuaImplQueryArg(state, index, &vecDouble, TypeTag<Vector3d>());
|
||||
|
||||
vec->Set(vecDouble);
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline unsigned int LuaImplQueryArg(const LuaState& state, int index, Ndk::Entity** handle, TypeTag<Ndk::Entity*>)
|
||||
{
|
||||
if (!state.IsOfType(index, LuaType_Nil))
|
||||
|
|
@ -384,7 +402,7 @@ namespace Nz
|
|||
return 1;
|
||||
}
|
||||
|
||||
inline unsigned int LuaImplQueryArg(const LuaState& state, int index, MusicParams* params, TypeTag<MusicParams>)
|
||||
inline unsigned int LuaImplQueryArg(const LuaState& state, int index, SoundBufferParams* params, TypeTag<SoundBufferParams>)
|
||||
{
|
||||
state.CheckType(index, Nz::LuaType_Table);
|
||||
|
||||
|
|
@ -393,7 +411,7 @@ namespace Nz
|
|||
return 1;
|
||||
}
|
||||
|
||||
inline unsigned int LuaImplQueryArg(const LuaState& state, int index, SoundBufferParams* params, TypeTag<SoundBufferParams>)
|
||||
inline unsigned int LuaImplQueryArg(const LuaState& state, int index, SoundStreamParams* params, TypeTag<SoundStreamParams>)
|
||||
{
|
||||
state.CheckType(index, Nz::LuaType_Table);
|
||||
|
||||
|
|
@ -538,6 +556,12 @@ namespace Nz
|
|||
return 1;
|
||||
}
|
||||
|
||||
inline int LuaImplReplyVal(const LuaState& state, Vector2i&& val, TypeTag<Vector2i>)
|
||||
{
|
||||
state.PushInstance<Vector2d>("Vector2", val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int LuaImplReplyVal(const LuaState& state, Vector3d&& val, TypeTag<Vector3d>)
|
||||
{
|
||||
state.PushInstance<Vector3d>("Vector3", val);
|
||||
|
|
@ -556,6 +580,12 @@ namespace Nz
|
|||
return 1;
|
||||
}
|
||||
|
||||
inline int LuaImplReplyVal(const LuaState& state, Vector3i&& val, TypeTag<Vector3i>)
|
||||
{
|
||||
state.PushInstance<Vector3d>("Vector3", val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int LuaImplReplyVal(const LuaState& state, Ndk::Entity* ptr, TypeTag<Ndk::Entity*>)
|
||||
{
|
||||
state.PushInstance<Ndk::EntityHandle>("Entity", ptr);
|
||||
|
|
@ -605,12 +635,24 @@ namespace Nz
|
|||
return 1;
|
||||
}
|
||||
|
||||
inline int LuaImplReplyVal(const LuaState& state, ModelRef&& handle, TypeTag<ModelRef>)
|
||||
{
|
||||
state.PushInstance<ModelRef>("Model", handle);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int LuaImplReplyVal(const LuaState& state, const SoundBuffer* val, TypeTag<const SoundBuffer*>)
|
||||
{
|
||||
state.PushInstance<SoundBufferConstRef>("SoundBuffer", val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int LuaImplReplyVal(const LuaState& state, SoundBufferRef&& handle, TypeTag<SoundBufferRef>)
|
||||
{
|
||||
state.PushInstance<SoundBufferRef>("SoundBuffer", handle);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int LuaImplReplyVal(const LuaState& state, SpriteRef&& handle, TypeTag<SpriteRef>)
|
||||
{
|
||||
state.PushInstance<SpriteRef>("Sprite", handle);
|
||||
|
|
|
|||
|
|
@ -159,8 +159,13 @@ namespace Ndk
|
|||
*/
|
||||
inline bool StateMachine::Update(float elapsedTime)
|
||||
{
|
||||
for (StateTransition& transition : m_transitions)
|
||||
// Use a classic for instead of a range-for because some state may push/pop on enter/leave, adding new transitions as we iterate
|
||||
// (range-for is a problem here because it doesn't handle mutable containers)
|
||||
|
||||
for (std::size_t i = 0; i < m_transitions.size(); ++i)
|
||||
{
|
||||
StateTransition& transition = m_transitions[i];
|
||||
|
||||
switch (transition.type)
|
||||
{
|
||||
case TransitionType::Pop:
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#define NDK_SYSTEMS_GLOBAL_HPP
|
||||
|
||||
#include <NDK/Systems/DebugSystem.hpp>
|
||||
#include <NDK/Systems/LifetimeSystem.hpp>
|
||||
#include <NDK/Systems/ListenerSystem.hpp>
|
||||
#include <NDK/Systems/ParticleSystem.hpp>
|
||||
#include <NDK/Systems/PhysicsSystem2D.hpp>
|
||||
|
|
|
|||
|
|
@ -22,26 +22,33 @@ namespace Ndk
|
|||
DebugSystem();
|
||||
~DebugSystem() = default;
|
||||
|
||||
void EnableDepthBuffer(bool enable);
|
||||
|
||||
inline bool IsDepthBufferEnabled() const;
|
||||
|
||||
static SystemIndex systemIndex;
|
||||
|
||||
private:
|
||||
Nz::InstancedRenderableRef GenerateBox(Nz::Boxf box);
|
||||
Nz::InstancedRenderableRef GenerateCollision2DMesh(Entity* entity, Nz::Vector3f* offset);
|
||||
Nz::InstancedRenderableRef GenerateCollision3DMesh(Entity* entity);
|
||||
|
||||
Nz::MaterialRef GetAABBMaterial();
|
||||
Nz::MaterialRef GetCollisionMaterial();
|
||||
Nz::MaterialRef GetOBBMaterial();
|
||||
std::pair<Nz::IndexBufferRef, Nz::VertexBufferRef> GetBoxMesh();
|
||||
Nz::MaterialRef GetCollisionMaterial();
|
||||
Nz::MaterialRef GetGlobalAABBMaterial();
|
||||
Nz::MaterialRef GetLocalAABBMaterial();
|
||||
Nz::MaterialRef GetOBBMaterial();
|
||||
|
||||
void OnEntityValidation(Entity* entity, bool justAdded) override;
|
||||
|
||||
void OnUpdate(float elapsedTime) override;
|
||||
|
||||
Nz::MaterialRef m_aabbMaterial;
|
||||
Nz::MaterialRef m_globalAabbMaterial;
|
||||
Nz::MaterialRef m_localAabbMaterial;
|
||||
Nz::MaterialRef m_collisionMaterial;
|
||||
Nz::MaterialRef m_obbMaterial;
|
||||
Nz::IndexBufferRef m_boxMeshIndexBuffer;
|
||||
Nz::VertexBufferRef m_boxMeshVertexBuffer;
|
||||
bool m_isDepthBufferEnabled;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,3 +4,10 @@
|
|||
|
||||
#include <NDK/Systems/DebugSystem.hpp>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
inline bool DebugSystem::IsDepthBufferEnabled() const
|
||||
{
|
||||
return m_isDepthBufferEnabled;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NDK_SYSTEMS_LIFETIMESYSTEM_HPP
|
||||
#define NDK_SYSTEMS_LIFETIMESYSTEM_HPP
|
||||
|
||||
#include <NDK/System.hpp>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
class NDK_API LifetimeSystem : public System<LifetimeSystem>
|
||||
{
|
||||
public:
|
||||
LifetimeSystem();
|
||||
~LifetimeSystem() = default;
|
||||
|
||||
static SystemIndex systemIndex;
|
||||
|
||||
private:
|
||||
void OnUpdate(float elapsedTime) override;
|
||||
};
|
||||
}
|
||||
|
||||
#include <NDK/Systems/LifetimeSystem.inl>
|
||||
|
||||
#endif // NDK_SYSTEMS_LIFETIMESYSTEM_HPP
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
|
@ -16,24 +16,114 @@ namespace Ndk
|
|||
{
|
||||
class NDK_API PhysicsSystem2D : public System<PhysicsSystem2D>
|
||||
{
|
||||
friend class CollisionComponent2D;
|
||||
friend class PhysicsComponent2D;
|
||||
|
||||
using ContactEndCallback = std::function<void(PhysicsSystem2D& world, Nz::Arbiter2D& arbiter, const EntityHandle& bodyA, const EntityHandle& bodyB, void* userdata)>;
|
||||
using ContactPreSolveCallback = std::function<bool(PhysicsSystem2D& world, Nz::Arbiter2D& arbiter, const EntityHandle& bodyA, const EntityHandle& bodyB, void* userdata)>;
|
||||
using ContactPostSolveCallback = std::function<void(PhysicsSystem2D& world, Nz::Arbiter2D& arbiter, const EntityHandle& bodyA, const EntityHandle& bodyB, void* userdata)>;
|
||||
using ContactStartCallback = std::function<bool(PhysicsSystem2D& world, Nz::Arbiter2D& arbiter, const EntityHandle& bodyA, const EntityHandle& bodyB, void* userdata)>;
|
||||
|
||||
using DebugDrawCircleCallback = std::function<void(const Nz::Vector2f& origin, const Nz::RadianAnglef& rotation, float radius, Nz::Color outlineColor, Nz::Color fillColor, void* userdata)>;
|
||||
using DebugDrawDotCallback = std::function<void(const Nz::Vector2f& origin, float radius, Nz::Color color, void* userdata)>;
|
||||
using DebugDrawPolygonCallback = std::function<void(const Nz::Vector2f* vertices, std::size_t vertexCount, float radius, Nz::Color outlineColor, Nz::Color fillColor, void* userdata)>;
|
||||
using DebugDrawSegmentCallback = std::function<void(const Nz::Vector2f& first, const Nz::Vector2f& second, Nz::Color color, void* userdata)>;
|
||||
using DebugDrawTickSegmentCallback = std::function<void(const Nz::Vector2f& first, const Nz::Vector2f& second, float thickness, Nz::Color outlineColor, Nz::Color fillColor, void* userdata)>;
|
||||
using DebugDrawGetColorCallback = std::function<Nz::Color(const EntityHandle& body, std::size_t shapeIndex, void* userdata)>;
|
||||
|
||||
public:
|
||||
struct Callback;
|
||||
struct DebugDrawOptions;
|
||||
struct NearestQueryResult;
|
||||
struct RaycastHit;
|
||||
|
||||
PhysicsSystem2D();
|
||||
PhysicsSystem2D(const PhysicsSystem2D& system);
|
||||
~PhysicsSystem2D() = default;
|
||||
|
||||
Nz::PhysWorld2D& GetWorld();
|
||||
const Nz::PhysWorld2D& GetWorld() const;
|
||||
void DebugDraw(const DebugDrawOptions& options, bool drawShapes = true, bool drawConstraints = true, bool drawCollisions = true);
|
||||
|
||||
inline float GetDamping() const;
|
||||
inline Nz::Vector2f GetGravity() const;
|
||||
inline std::size_t GetIterationCount() const;
|
||||
inline std::size_t GetMaxStepCount() const;
|
||||
inline float GetStepSize() const;
|
||||
|
||||
bool NearestBodyQuery(const Nz::Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, EntityHandle* nearestBody = nullptr);
|
||||
bool NearestBodyQuery(const Nz::Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, NearestQueryResult* result);
|
||||
|
||||
void RaycastQuery(const Nz::Vector2f& from, const Nz::Vector2f& to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, const std::function<void(const RaycastHit&)>& callback);
|
||||
bool RaycastQuery(const Nz::Vector2f& from, const Nz::Vector2f& to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, std::vector<RaycastHit>* hitInfos);
|
||||
bool RaycastQueryFirst(const Nz::Vector2f& from, const Nz::Vector2f& to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RaycastHit* hitInfo = nullptr);
|
||||
|
||||
void RegionQuery(const Nz::Rectf& boundingBox, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, const std::function<void(const EntityHandle&)>& callback);
|
||||
void RegionQuery(const Nz::Rectf& boundingBox, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, std::vector<EntityHandle>* bodies);
|
||||
|
||||
void RegisterCallbacks(unsigned int collisionId, Callback callbacks);
|
||||
void RegisterCallbacks(unsigned int collisionIdA, unsigned int collisionIdB, Callback callbacks);
|
||||
|
||||
inline void SetDamping(float dampingValue);
|
||||
inline void SetGravity(const Nz::Vector2f& gravity);
|
||||
inline void SetIterationCount(std::size_t iterationCount);
|
||||
inline void SetMaxStepCount(std::size_t maxStepCount);
|
||||
inline void SetSleepTime(float sleepTime);
|
||||
inline void SetStepSize(float stepSize);
|
||||
|
||||
inline void UseSpatialHash(float cellSize, std::size_t entityCount);
|
||||
|
||||
struct Callback
|
||||
{
|
||||
ContactEndCallback endCallback = nullptr;
|
||||
ContactPreSolveCallback preSolveCallback = nullptr;
|
||||
ContactPostSolveCallback postSolveCallback = nullptr;
|
||||
ContactStartCallback startCallback = nullptr;
|
||||
void* userdata;
|
||||
};
|
||||
|
||||
struct DebugDrawOptions
|
||||
{
|
||||
Nz::Color constraintColor;
|
||||
Nz::Color collisionPointColor;
|
||||
Nz::Color shapeOutlineColor;
|
||||
|
||||
DebugDrawCircleCallback circleCallback;
|
||||
DebugDrawGetColorCallback colorCallback;
|
||||
DebugDrawDotCallback dotCallback;
|
||||
DebugDrawPolygonCallback polygonCallback;
|
||||
DebugDrawSegmentCallback segmentCallback;
|
||||
DebugDrawTickSegmentCallback thickSegmentCallback;
|
||||
|
||||
void* userdata;
|
||||
};
|
||||
|
||||
struct NearestQueryResult
|
||||
{
|
||||
EntityHandle nearestBody;
|
||||
Nz::Vector2f closestPoint;
|
||||
Nz::Vector2f fraction;
|
||||
float distance;
|
||||
};
|
||||
|
||||
struct RaycastHit
|
||||
{
|
||||
EntityHandle body;
|
||||
Nz::Vector2f hitPos;
|
||||
Nz::Vector2f hitNormal;
|
||||
float fraction;
|
||||
};
|
||||
|
||||
static SystemIndex systemIndex;
|
||||
|
||||
private:
|
||||
void CreatePhysWorld() const;
|
||||
const EntityHandle& GetEntityFromBody(const Nz::RigidBody2D& body) const;
|
||||
inline Nz::PhysWorld2D& GetPhysWorld();
|
||||
inline const Nz::PhysWorld2D& GetPhysWorld() const;
|
||||
void OnEntityValidation(Entity* entity, bool justAdded) override;
|
||||
void OnUpdate(float elapsedTime) override;
|
||||
|
||||
EntityList m_dynamicObjects;
|
||||
EntityList m_staticObjects;
|
||||
mutable std::unique_ptr<Nz::PhysWorld2D> m_world; ///TODO: std::optional (Should I make a Nz::Optional class?)
|
||||
mutable std::unique_ptr<Nz::PhysWorld2D> m_physWorld; ///TODO: std::optional (Should I make a Nz::Optional class?)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,19 +2,81 @@
|
|||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#include <NDK/Systems/PhysicsSystem2D.hpp>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
inline float PhysicsSystem2D::GetDamping() const
|
||||
{
|
||||
return GetPhysWorld().GetDamping();
|
||||
}
|
||||
|
||||
inline Nz::Vector2f PhysicsSystem2D::GetGravity() const
|
||||
{
|
||||
return GetPhysWorld().GetGravity();
|
||||
}
|
||||
|
||||
inline std::size_t PhysicsSystem2D::GetIterationCount() const
|
||||
{
|
||||
return GetPhysWorld().GetIterationCount();
|
||||
}
|
||||
|
||||
inline std::size_t PhysicsSystem2D::GetMaxStepCount() const
|
||||
{
|
||||
return GetPhysWorld().GetMaxStepCount();
|
||||
}
|
||||
|
||||
inline float PhysicsSystem2D::GetStepSize() const
|
||||
{
|
||||
return GetPhysWorld().GetStepSize();
|
||||
}
|
||||
|
||||
inline void PhysicsSystem2D::SetDamping(float dampingValue)
|
||||
{
|
||||
GetPhysWorld().SetDamping(dampingValue);
|
||||
}
|
||||
|
||||
inline void PhysicsSystem2D::SetGravity(const Nz::Vector2f& gravity)
|
||||
{
|
||||
GetPhysWorld().SetGravity(gravity);
|
||||
}
|
||||
|
||||
inline void PhysicsSystem2D::SetIterationCount(std::size_t iterationCount)
|
||||
{
|
||||
GetPhysWorld().SetIterationCount(iterationCount);
|
||||
}
|
||||
|
||||
inline void PhysicsSystem2D::SetMaxStepCount(std::size_t maxStepCount)
|
||||
{
|
||||
GetPhysWorld().SetMaxStepCount(maxStepCount);
|
||||
}
|
||||
|
||||
inline void PhysicsSystem2D::SetSleepTime(float sleepTime)
|
||||
{
|
||||
GetPhysWorld().SetSleepTime(sleepTime);
|
||||
}
|
||||
|
||||
inline void PhysicsSystem2D::SetStepSize(float stepSize)
|
||||
{
|
||||
GetPhysWorld().SetStepSize(stepSize);
|
||||
}
|
||||
|
||||
inline void PhysicsSystem2D::UseSpatialHash(float cellSize, std::size_t entityCount)
|
||||
{
|
||||
GetPhysWorld().UseSpatialHash(cellSize, entityCount);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the physical world
|
||||
* \return A reference to the physical world
|
||||
*/
|
||||
|
||||
inline Nz::PhysWorld2D& PhysicsSystem2D::GetWorld()
|
||||
inline Nz::PhysWorld2D& PhysicsSystem2D::GetPhysWorld()
|
||||
{
|
||||
if (!m_world)
|
||||
if (!m_physWorld)
|
||||
CreatePhysWorld();
|
||||
|
||||
return *m_world;
|
||||
return *m_physWorld;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -22,11 +84,11 @@ namespace Ndk
|
|||
* \return A constant reference to the physical world
|
||||
*/
|
||||
|
||||
inline const Nz::PhysWorld2D& PhysicsSystem2D::GetWorld() const
|
||||
inline const Nz::PhysWorld2D& PhysicsSystem2D::GetPhysWorld() const
|
||||
{
|
||||
if (!m_world)
|
||||
if (!m_physWorld)
|
||||
CreatePhysWorld();
|
||||
|
||||
return *m_world;
|
||||
return *m_physWorld;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,12 +25,13 @@ namespace Ndk
|
|||
{
|
||||
public:
|
||||
RenderSystem();
|
||||
inline RenderSystem(const RenderSystem& renderSystem);
|
||||
~RenderSystem() = default;
|
||||
|
||||
template<typename T> T& ChangeRenderTechnique();
|
||||
inline Nz::AbstractRenderTechnique& ChangeRenderTechnique(std::unique_ptr<Nz::AbstractRenderTechnique>&& renderTechnique);
|
||||
|
||||
inline void EnableCulling(bool enable);
|
||||
|
||||
inline const Nz::BackgroundRef& GetDefaultBackground() const;
|
||||
inline const Nz::Matrix4f& GetCoordinateSystemMatrix() const;
|
||||
inline Nz::Vector3f GetGlobalForward() const;
|
||||
|
|
@ -38,6 +39,8 @@ namespace Ndk
|
|||
inline Nz::Vector3f GetGlobalUp() const;
|
||||
inline Nz::AbstractRenderTechnique& GetRenderTechnique() const;
|
||||
|
||||
inline bool IsCullingEnabled() const;
|
||||
|
||||
inline void SetDefaultBackground(Nz::BackgroundRef background);
|
||||
inline void SetGlobalForward(const Nz::Vector3f& direction);
|
||||
inline void SetGlobalRight(const Nz::Vector3f& direction);
|
||||
|
|
@ -72,6 +75,7 @@ namespace Ndk
|
|||
Nz::RenderTexture m_shadowRT;
|
||||
bool m_coordinateSystemInvalidated;
|
||||
bool m_forceRenderQueueInvalidation;
|
||||
bool m_isCullingEnabled;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#include <NDK/Systems/RenderSystem.hpp>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
/*!
|
||||
|
|
@ -26,7 +28,24 @@ namespace Ndk
|
|||
inline Nz::AbstractRenderTechnique& RenderSystem::ChangeRenderTechnique(std::unique_ptr<Nz::AbstractRenderTechnique>&& renderTechnique)
|
||||
{
|
||||
m_renderTechnique = std::move(renderTechnique);
|
||||
return *m_renderTechnique.get();
|
||||
return *m_renderTechnique;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enables/disables object culling
|
||||
*
|
||||
* Object culling is an algorithm used by the render system to detect invisible objects (which will not appear on screen) before they are rendered.
|
||||
* This includes Frustum Culling and potentially Occlusion Culling.
|
||||
*
|
||||
* Disabling this is not recommended, as the system will draw every object in the world which could induce a performance loss.
|
||||
*
|
||||
* \param enable Whether to enable or disable culling
|
||||
*
|
||||
* \see IsCullingEnabled
|
||||
*/
|
||||
inline void RenderSystem::EnableCulling(bool enable)
|
||||
{
|
||||
m_isCullingEnabled = enable;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -89,6 +108,17 @@ namespace Ndk
|
|||
return *m_renderTechnique.get();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Query if culling is enabled (enabled by default)
|
||||
* \return True if culling is enabled, false otherwise
|
||||
*
|
||||
* \see EnableCulling
|
||||
*/
|
||||
inline bool RenderSystem::IsCullingEnabled() const
|
||||
{
|
||||
return m_isCullingEnabled;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the background used for rendering
|
||||
*
|
||||
|
|
|
|||
|
|
@ -5,12 +5,16 @@
|
|||
#ifndef NDK_WIDGETS_GLOBAL_HPP
|
||||
#define NDK_WIDGETS_GLOBAL_HPP
|
||||
|
||||
#include <NDK/Widgets/AbstractTextAreaWidget.hpp>
|
||||
#include <NDK/Widgets/BoxLayout.hpp>
|
||||
#include <NDK/Widgets/ButtonWidget.hpp>
|
||||
#include <NDK/Widgets/CheckboxWidget.hpp>
|
||||
#include <NDK/Widgets/Enums.hpp>
|
||||
#include <NDK/Widgets/ImageWidget.hpp>
|
||||
#include <NDK/Widgets/LabelWidget.hpp>
|
||||
#include <NDK/Widgets/ProgressBarWidget.hpp>
|
||||
#include <NDK/Widgets/RichTextAreaWidget.hpp>
|
||||
#include <NDK/Widgets/ScrollAreaWidget.hpp>
|
||||
#include <NDK/Widgets/TextAreaWidget.hpp>
|
||||
|
||||
#endif // NDK_WIDGETS_GLOBAL_HPP
|
||||
|
|
|
|||
|
|
@ -0,0 +1,135 @@
|
|||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NDK_WIDGETS_ABSTRACTTEXTAREAWIDGET_HPP
|
||||
#define NDK_WIDGETS_ABSTRACTTEXTAREAWIDGET_HPP
|
||||
|
||||
#include <Nazara/Graphics/TextSprite.hpp>
|
||||
#include <Nazara/Utility/AbstractTextDrawer.hpp>
|
||||
#include <NDK/BaseWidget.hpp>
|
||||
#include <NDK/Widgets/Enums.hpp>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
class NDK_API AbstractTextAreaWidget : public BaseWidget
|
||||
{
|
||||
public:
|
||||
using CharacterFilter = std::function<bool(char32_t)>;
|
||||
|
||||
AbstractTextAreaWidget(BaseWidget* parent);
|
||||
AbstractTextAreaWidget(const AbstractTextAreaWidget&) = delete;
|
||||
AbstractTextAreaWidget(AbstractTextAreaWidget&&) = default;
|
||||
~AbstractTextAreaWidget() = default;
|
||||
|
||||
virtual void Clear();
|
||||
|
||||
//virtual TextAreaWidget* Clone() const = 0;
|
||||
|
||||
void EnableLineWrap(bool enable = true);
|
||||
inline void EnableMultiline(bool enable = true);
|
||||
inline void EnableTabWriting(bool enable = true);
|
||||
|
||||
inline void Erase(std::size_t glyphPosition);
|
||||
virtual void Erase(std::size_t firstGlyph, std::size_t lastGlyph) = 0;
|
||||
inline void EraseSelection();
|
||||
|
||||
inline const CharacterFilter& GetCharacterFilter() const;
|
||||
inline const Nz::Vector2ui& GetCursorPosition() const;
|
||||
inline Nz::Vector2ui GetCursorPosition(std::size_t glyphIndex) const;
|
||||
inline EchoMode GetEchoMode() const;
|
||||
inline std::size_t GetGlyphIndex() const;
|
||||
inline std::size_t GetGlyphIndex(const Nz::Vector2ui& cursorPosition) const;
|
||||
inline const Nz::String& GetText() const;
|
||||
|
||||
Nz::Vector2ui GetHoveredGlyph(float x, float y) const;
|
||||
|
||||
inline bool HasSelection() const;
|
||||
|
||||
inline bool IsLineWrapEnabled() const;
|
||||
inline bool IsMultilineEnabled() const;
|
||||
inline bool IsReadOnly() const;
|
||||
inline bool IsTabWritingEnabled() const;
|
||||
|
||||
inline void MoveCursor(int offset);
|
||||
inline void MoveCursor(const Nz::Vector2i& offset);
|
||||
|
||||
inline Nz::Vector2ui NormalizeCursorPosition(Nz::Vector2ui cursorPosition) const;
|
||||
|
||||
inline void SetCharacterFilter(CharacterFilter filter);
|
||||
inline void SetCursorPosition(std::size_t glyphIndex);
|
||||
inline void SetCursorPosition(Nz::Vector2ui cursorPosition);
|
||||
inline void SetEchoMode(EchoMode echoMode);
|
||||
inline void SetReadOnly(bool readOnly = true);
|
||||
inline void SetSelection(Nz::Vector2ui fromPosition, Nz::Vector2ui toPosition);
|
||||
|
||||
inline void Write(const Nz::String& text);
|
||||
inline void Write(const Nz::String& text, const Nz::Vector2ui& glyphPosition);
|
||||
virtual void Write(const Nz::String& text, std::size_t glyphPosition) = 0;
|
||||
|
||||
AbstractTextAreaWidget& operator=(const AbstractTextAreaWidget&) = delete;
|
||||
AbstractTextAreaWidget& operator=(AbstractTextAreaWidget&&) = default;
|
||||
|
||||
NazaraSignal(OnTextAreaCursorMove, const AbstractTextAreaWidget* /*textArea*/, Nz::Vector2ui* /*newCursorPosition*/);
|
||||
NazaraSignal(OnTextAreaKeyBackspace, const AbstractTextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||
NazaraSignal(OnTextAreaKeyDown, const AbstractTextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||
NazaraSignal(OnTextAreaKeyEnd, const AbstractTextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||
NazaraSignal(OnTextAreaKeyHome, const AbstractTextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||
NazaraSignal(OnTextAreaKeyLeft, const AbstractTextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||
NazaraSignal(OnTextAreaKeyReturn, const AbstractTextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||
NazaraSignal(OnTextAreaKeyRight, const AbstractTextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||
NazaraSignal(OnTextAreaKeyUp, const AbstractTextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||
NazaraSignal(OnTextAreaSelection, const AbstractTextAreaWidget* /*textArea*/, Nz::Vector2ui* /*start*/, Nz::Vector2ui* /*end*/);
|
||||
|
||||
protected:
|
||||
virtual Nz::AbstractTextDrawer& GetTextDrawer() = 0;
|
||||
virtual const Nz::AbstractTextDrawer& GetTextDrawer() const = 0;
|
||||
|
||||
void Layout() override;
|
||||
|
||||
virtual void HandleIndentation(bool add) = 0;
|
||||
virtual void HandleSelectionIndentation(bool add) = 0;
|
||||
virtual void HandleWordCursorMove(bool left) = 0;
|
||||
|
||||
bool IsFocusable() const override;
|
||||
void OnFocusLost() override;
|
||||
void OnFocusReceived() override;
|
||||
bool OnKeyPressed(const Nz::WindowEvent::KeyEvent& key) override;
|
||||
void OnKeyReleased(const Nz::WindowEvent::KeyEvent& key) override;
|
||||
void OnMouseButtonPress(int /*x*/, int /*y*/, Nz::Mouse::Button button) override;
|
||||
void OnMouseButtonRelease(int /*x*/, int /*y*/, Nz::Mouse::Button button) override;
|
||||
void OnMouseEnter() override;
|
||||
void OnMouseMoved(int x, int y, int deltaX, int deltaY) override;
|
||||
void OnTextEntered(char32_t character, bool repeated) override;
|
||||
|
||||
inline void SetCursorPositionInternal(std::size_t glyphIndex);
|
||||
inline void SetCursorPositionInternal(Nz::Vector2ui cursorPosition);
|
||||
|
||||
void RefreshCursor();
|
||||
virtual void UpdateDisplayText() = 0;
|
||||
void UpdateTextSprite();
|
||||
|
||||
CharacterFilter m_characterFilter;
|
||||
EchoMode m_echoMode;
|
||||
EntityHandle m_cursorEntity;
|
||||
EntityHandle m_textEntity;
|
||||
Nz::TextSpriteRef m_textSprite;
|
||||
Nz::Vector2ui m_cursorPositionBegin;
|
||||
Nz::Vector2ui m_cursorPositionEnd;
|
||||
Nz::Vector2ui m_selectionCursor;
|
||||
std::vector<Nz::SpriteRef> m_cursorSprites;
|
||||
bool m_isLineWrapEnabled;
|
||||
bool m_isMouseButtonDown;
|
||||
bool m_multiLineEnabled;
|
||||
bool m_readOnly;
|
||||
bool m_tabEnabled; // writes (Shift+)Tab character if set to true
|
||||
};
|
||||
}
|
||||
|
||||
#include <NDK/Widgets/AbstractTextAreaWidget.inl>
|
||||
|
||||
#endif // NDK_WIDGETS_ABSTRACTTEXTAREAWIDGET_HPP
|
||||
|
|
@ -0,0 +1,252 @@
|
|||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#include <NDK/Widgets/AbstractTextAreaWidget.hpp>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
inline void AbstractTextAreaWidget::EnableMultiline(bool enable)
|
||||
{
|
||||
m_multiLineEnabled = enable;
|
||||
}
|
||||
|
||||
inline void AbstractTextAreaWidget::EnableTabWriting(bool enable)
|
||||
{
|
||||
m_tabEnabled = enable;
|
||||
}
|
||||
|
||||
inline void AbstractTextAreaWidget::Erase(std::size_t glyphPosition)
|
||||
{
|
||||
Erase(glyphPosition, glyphPosition + 1U);
|
||||
}
|
||||
|
||||
inline void AbstractTextAreaWidget::EraseSelection()
|
||||
{
|
||||
if (!HasSelection())
|
||||
return;
|
||||
|
||||
Erase(GetGlyphIndex(m_cursorPositionBegin), GetGlyphIndex(m_cursorPositionEnd));
|
||||
}
|
||||
|
||||
inline const AbstractTextAreaWidget::CharacterFilter& AbstractTextAreaWidget::GetCharacterFilter() const
|
||||
{
|
||||
return m_characterFilter;
|
||||
}
|
||||
|
||||
inline const Nz::Vector2ui& AbstractTextAreaWidget::GetCursorPosition() const
|
||||
{
|
||||
return m_cursorPositionBegin;
|
||||
}
|
||||
|
||||
Nz::Vector2ui AbstractTextAreaWidget::GetCursorPosition(std::size_t glyphIndex) const
|
||||
{
|
||||
const Nz::AbstractTextDrawer& textDrawer = GetTextDrawer();
|
||||
|
||||
glyphIndex = std::min(glyphIndex, GetTextDrawer().GetGlyphCount());
|
||||
|
||||
std::size_t lineCount = textDrawer.GetLineCount();
|
||||
std::size_t line = 0U;
|
||||
for (std::size_t i = line + 1; i < lineCount; ++i)
|
||||
{
|
||||
if (textDrawer.GetLine(i).glyphIndex > glyphIndex)
|
||||
break;
|
||||
|
||||
line = i;
|
||||
}
|
||||
|
||||
const auto& lineInfo = textDrawer.GetLine(line);
|
||||
|
||||
Nz::Vector2ui cursorPos;
|
||||
cursorPos.y = static_cast<unsigned int>(line);
|
||||
cursorPos.x = static_cast<unsigned int>(glyphIndex - lineInfo.glyphIndex);
|
||||
|
||||
return cursorPos;
|
||||
}
|
||||
|
||||
inline EchoMode AbstractTextAreaWidget::GetEchoMode() const
|
||||
{
|
||||
return m_echoMode;
|
||||
}
|
||||
|
||||
inline std::size_t AbstractTextAreaWidget::GetGlyphIndex() const
|
||||
{
|
||||
return GetGlyphIndex(m_cursorPositionBegin);
|
||||
}
|
||||
|
||||
inline std::size_t AbstractTextAreaWidget::GetGlyphIndex(const Nz::Vector2ui& cursorPosition) const
|
||||
{
|
||||
const Nz::AbstractTextDrawer& textDrawer = GetTextDrawer();
|
||||
|
||||
std::size_t glyphIndex = textDrawer.GetLine(cursorPosition.y).glyphIndex + cursorPosition.x;
|
||||
if (textDrawer.GetLineCount() > cursorPosition.y + 1)
|
||||
glyphIndex = std::min(glyphIndex, textDrawer.GetLine(cursorPosition.y + 1).glyphIndex - 1);
|
||||
else
|
||||
glyphIndex = std::min(glyphIndex, textDrawer.GetGlyphCount());
|
||||
|
||||
return glyphIndex;
|
||||
}
|
||||
|
||||
inline bool AbstractTextAreaWidget::HasSelection() const
|
||||
{
|
||||
return m_cursorPositionBegin != m_cursorPositionEnd;
|
||||
}
|
||||
|
||||
inline bool AbstractTextAreaWidget::IsLineWrapEnabled() const
|
||||
{
|
||||
return m_isLineWrapEnabled;
|
||||
}
|
||||
|
||||
inline bool AbstractTextAreaWidget::IsMultilineEnabled() const
|
||||
{
|
||||
return m_multiLineEnabled;
|
||||
}
|
||||
|
||||
inline bool AbstractTextAreaWidget::IsTabWritingEnabled() const
|
||||
{
|
||||
return m_tabEnabled;
|
||||
}
|
||||
|
||||
inline bool AbstractTextAreaWidget::IsReadOnly() const
|
||||
{
|
||||
return m_readOnly;
|
||||
}
|
||||
|
||||
inline void AbstractTextAreaWidget::MoveCursor(int offset)
|
||||
{
|
||||
std::size_t cursorGlyph = GetGlyphIndex(m_cursorPositionBegin);
|
||||
if (offset >= 0)
|
||||
SetCursorPosition(cursorGlyph + static_cast<std::size_t>(offset));
|
||||
else
|
||||
{
|
||||
std::size_t nOffset = static_cast<std::size_t>(-offset);
|
||||
if (nOffset >= cursorGlyph)
|
||||
SetCursorPosition(0);
|
||||
else
|
||||
SetCursorPosition(cursorGlyph - nOffset);
|
||||
}
|
||||
}
|
||||
|
||||
inline void AbstractTextAreaWidget::MoveCursor(const Nz::Vector2i& offset)
|
||||
{
|
||||
auto ClampOffset = [] (unsigned int cursorPosition, int cursorOffset) -> unsigned int
|
||||
{
|
||||
if (cursorOffset >= 0)
|
||||
return cursorPosition + cursorOffset;
|
||||
else
|
||||
{
|
||||
unsigned int nOffset = static_cast<unsigned int>(-cursorOffset);
|
||||
if (nOffset >= cursorPosition)
|
||||
return 0;
|
||||
else
|
||||
return cursorPosition - nOffset;
|
||||
}
|
||||
};
|
||||
|
||||
Nz::Vector2ui cursorPosition = m_cursorPositionBegin;
|
||||
cursorPosition.x = ClampOffset(static_cast<unsigned int>(cursorPosition.x), offset.x);
|
||||
cursorPosition.y = ClampOffset(static_cast<unsigned int>(cursorPosition.y), offset.y);
|
||||
|
||||
SetCursorPosition(cursorPosition);
|
||||
}
|
||||
|
||||
inline Nz::Vector2ui AbstractTextAreaWidget::NormalizeCursorPosition(Nz::Vector2ui cursorPosition) const
|
||||
{
|
||||
const Nz::AbstractTextDrawer& textDrawer = GetTextDrawer();
|
||||
|
||||
std::size_t lineCount = textDrawer.GetLineCount();
|
||||
if (cursorPosition.y >= lineCount)
|
||||
cursorPosition.y = static_cast<unsigned int>(lineCount - 1);
|
||||
|
||||
const auto& lineInfo = textDrawer.GetLine(cursorPosition.y);
|
||||
if (cursorPosition.y + 1 < lineCount)
|
||||
{
|
||||
const auto& nextLineInfo = textDrawer.GetLine(cursorPosition.y + 1);
|
||||
cursorPosition.x = std::min(cursorPosition.x, static_cast<unsigned int>(nextLineInfo.glyphIndex - lineInfo.glyphIndex - 1));
|
||||
}
|
||||
|
||||
return cursorPosition;
|
||||
}
|
||||
|
||||
inline void AbstractTextAreaWidget::SetCharacterFilter(CharacterFilter filter)
|
||||
{
|
||||
m_characterFilter = std::move(filter);
|
||||
}
|
||||
|
||||
inline void AbstractTextAreaWidget::SetCursorPosition(std::size_t glyphIndex)
|
||||
{
|
||||
Nz::Vector2ui position = GetCursorPosition(glyphIndex);
|
||||
Nz::Vector2ui newPosition = position;
|
||||
|
||||
OnTextAreaCursorMove(this, &newPosition);
|
||||
|
||||
if (position == newPosition)
|
||||
SetCursorPositionInternal(position);
|
||||
else
|
||||
SetCursorPositionInternal(GetGlyphIndex(newPosition));
|
||||
}
|
||||
|
||||
inline void AbstractTextAreaWidget::SetCursorPosition(Nz::Vector2ui cursorPosition)
|
||||
{
|
||||
OnTextAreaCursorMove(this, &cursorPosition);
|
||||
|
||||
return SetCursorPositionInternal(NormalizeCursorPosition(cursorPosition));
|
||||
}
|
||||
|
||||
inline void AbstractTextAreaWidget::SetEchoMode(EchoMode echoMode)
|
||||
{
|
||||
m_echoMode = echoMode;
|
||||
|
||||
UpdateDisplayText();
|
||||
}
|
||||
|
||||
inline void AbstractTextAreaWidget::SetReadOnly(bool readOnly)
|
||||
{
|
||||
m_readOnly = readOnly;
|
||||
m_cursorEntity->Enable(!m_readOnly && HasFocus());
|
||||
}
|
||||
|
||||
inline void AbstractTextAreaWidget::SetSelection(Nz::Vector2ui fromPosition, Nz::Vector2ui toPosition)
|
||||
{
|
||||
// Ensure begin is before end
|
||||
if (toPosition.y < fromPosition.y || (toPosition.y == fromPosition.y && toPosition.x < fromPosition.x))
|
||||
std::swap(fromPosition, toPosition);
|
||||
|
||||
if (m_cursorPositionBegin != fromPosition || m_cursorPositionEnd != toPosition)
|
||||
{
|
||||
OnTextAreaSelection(this, &fromPosition, &toPosition);
|
||||
|
||||
// Ensure begin is before end a second time (in case signal changed it)
|
||||
if (toPosition.y < fromPosition.y || (toPosition.y == fromPosition.y && toPosition.x < fromPosition.x))
|
||||
std::swap(fromPosition, toPosition);
|
||||
|
||||
m_cursorPositionBegin = NormalizeCursorPosition(fromPosition);
|
||||
m_cursorPositionEnd = NormalizeCursorPosition(toPosition);
|
||||
|
||||
RefreshCursor();
|
||||
}
|
||||
}
|
||||
|
||||
inline void AbstractTextAreaWidget::Write(const Nz::String& text)
|
||||
{
|
||||
Write(text, GetGlyphIndex(m_cursorPositionBegin));
|
||||
}
|
||||
|
||||
inline void AbstractTextAreaWidget::Write(const Nz::String& text, const Nz::Vector2ui& glyphPosition)
|
||||
{
|
||||
Write(text, GetGlyphIndex(glyphPosition));
|
||||
}
|
||||
|
||||
void AbstractTextAreaWidget::SetCursorPositionInternal(std::size_t glyphIndex)
|
||||
{
|
||||
return SetCursorPositionInternal(GetCursorPosition(glyphIndex));
|
||||
}
|
||||
|
||||
inline void AbstractTextAreaWidget::SetCursorPositionInternal(Nz::Vector2ui cursorPosition)
|
||||
{
|
||||
m_cursorPositionBegin = cursorPosition;
|
||||
m_cursorPositionEnd = m_cursorPositionBegin;
|
||||
|
||||
RefreshCursor();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NDK_WIDGETS_BOXLAYOUT_HPP
|
||||
#define NDK_WIDGETS_BOXLAYOUT_HPP
|
||||
|
||||
#include <NDK/Prerequisites.hpp>
|
||||
#include <NDK/BaseWidget.hpp>
|
||||
#include <NDK/Widgets/Enums.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
class NDK_API BoxLayout : public BaseWidget
|
||||
{
|
||||
public:
|
||||
inline BoxLayout(BaseWidget* parent, BoxLayoutOrientation orientation);
|
||||
BoxLayout(const BoxLayout&) = delete;
|
||||
BoxLayout(BoxLayout&&) = default;
|
||||
~BoxLayout() = default;
|
||||
|
||||
void Layout() override;
|
||||
|
||||
BoxLayout& operator=(const BoxLayout&) = delete;
|
||||
BoxLayout& operator=(BoxLayout&&) = default;
|
||||
|
||||
private:
|
||||
struct ChildInfo
|
||||
{
|
||||
BaseWidget* widget;
|
||||
bool isConstrained;
|
||||
float maximumSize;
|
||||
float minimumSize;
|
||||
float size;
|
||||
};
|
||||
|
||||
std::vector<ChildInfo> m_childInfos;
|
||||
BoxLayoutOrientation m_orientation;
|
||||
float m_spacing;
|
||||
};
|
||||
}
|
||||
|
||||
#include <NDK/Widgets/BoxLayout.inl>
|
||||
|
||||
#endif // NDK_WIDGETS_BOXLAYOUT_HPP
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#include <NDK/Widgets/BoxLayout.hpp>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
BoxLayout::BoxLayout(BaseWidget* parent, BoxLayoutOrientation orientation) :
|
||||
BaseWidget(parent),
|
||||
m_orientation(orientation),
|
||||
m_spacing(5.f)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -23,15 +23,11 @@ namespace Ndk
|
|||
class NDK_API ButtonWidget : public BaseWidget
|
||||
{
|
||||
public:
|
||||
ButtonWidget(BaseWidget* parent = nullptr);
|
||||
ButtonWidget(BaseWidget* parent);
|
||||
ButtonWidget(const ButtonWidget&) = delete;
|
||||
ButtonWidget(ButtonWidget&&) = default;
|
||||
~ButtonWidget() = default;
|
||||
|
||||
//virtual ButtonWidget* Clone() const = 0;
|
||||
|
||||
void ResizeToContent() override;
|
||||
|
||||
inline const Nz::Color& GetColor() const;
|
||||
inline const Nz::Color& GetCornerColor() const;
|
||||
inline const Nz::Color& GetHoverColor() const;
|
||||
|
|
|
|||
|
|
@ -93,6 +93,10 @@ namespace Ndk
|
|||
{
|
||||
m_textSprite->Update(drawer);
|
||||
|
||||
Nz::Vector2f textSize = Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths());
|
||||
SetMinimumSize(textSize);
|
||||
SetPreferredSize(textSize + Nz::Vector2f(20.f, 10.f));
|
||||
|
||||
Layout();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ namespace Ndk
|
|||
friend class Sdk;
|
||||
|
||||
public:
|
||||
CheckboxWidget(BaseWidget* parent = nullptr);
|
||||
CheckboxWidget(BaseWidget* parent);
|
||||
CheckboxWidget(const CheckboxWidget&) = delete;
|
||||
CheckboxWidget(CheckboxWidget&&) = default;
|
||||
~CheckboxWidget() = default;
|
||||
|
|
@ -53,7 +53,6 @@ namespace Ndk
|
|||
void SetState(CheckboxState state);
|
||||
inline void SetTextMargin(float margin);
|
||||
|
||||
void ResizeToContent() override;
|
||||
inline void UpdateText(const Nz::AbstractTextDrawer& drawer);
|
||||
|
||||
|
||||
|
|
@ -68,6 +67,7 @@ namespace Ndk
|
|||
|
||||
void Layout() override;
|
||||
void UpdateCheckbox();
|
||||
void UpdateSize();
|
||||
|
||||
void OnMouseButtonRelease(int x, int y, Nz::Mouse::Button button) override;
|
||||
inline bool ContainsCheckbox(int x, int y) const;
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ namespace Ndk
|
|||
m_checkboxBackgroundSprite->SetSize(size - GetCheckboxBorderSize() * 2.f);
|
||||
m_checkboxContentSprite->SetSize(GetCheckboxSize() - GetCheckboxBorderSize() * 2.f - Nz::Vector2f { 4.f, 4.f });
|
||||
|
||||
UpdateSize();
|
||||
Layout();
|
||||
}
|
||||
|
||||
|
|
@ -77,6 +78,8 @@ namespace Ndk
|
|||
inline void CheckboxWidget::UpdateText(const Nz::AbstractTextDrawer& drawer)
|
||||
{
|
||||
m_textSprite->Update(drawer);
|
||||
|
||||
UpdateSize();
|
||||
Layout();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,12 @@
|
|||
|
||||
namespace Ndk
|
||||
{
|
||||
enum BoxLayoutOrientation
|
||||
{
|
||||
BoxLayoutOrientation_Horizontal,
|
||||
BoxLayoutOrientation_Vertical
|
||||
};
|
||||
|
||||
enum CheckboxState
|
||||
{
|
||||
CheckboxState_Checked,
|
||||
|
|
|
|||
|
|
@ -19,21 +19,19 @@ namespace Ndk
|
|||
class NDK_API ImageWidget : public BaseWidget
|
||||
{
|
||||
public:
|
||||
ImageWidget(BaseWidget* parent = nullptr);
|
||||
ImageWidget(BaseWidget* parent);
|
||||
ImageWidget(const ImageWidget&) = delete;
|
||||
ImageWidget(ImageWidget&&) = default;
|
||||
~ImageWidget() = default;
|
||||
|
||||
//virtual ImageWidget* Clone() const = 0;
|
||||
|
||||
void ResizeToContent() override;
|
||||
|
||||
inline const Nz::Color& GetColor() const;
|
||||
inline const Nz::TextureRef& GetTexture() const;
|
||||
inline const Nz::Rectf& GetTextureCoords() const;
|
||||
|
||||
inline void SetColor(const Nz::Color& color);
|
||||
inline void SetTexture(const Nz::TextureRef& texture, bool resizeToContent = true);
|
||||
inline void SetTexture(const Nz::TextureRef& texture);
|
||||
inline void SetTextureCoords(const Nz::Rectf& coords);
|
||||
inline void SetTextureRect(const Nz::Rectui& rect);
|
||||
|
||||
|
|
|
|||
|
|
@ -26,12 +26,13 @@ namespace Ndk
|
|||
m_sprite->SetColor(color);
|
||||
}
|
||||
|
||||
inline void ImageWidget::SetTexture(const Nz::TextureRef& texture, bool resizeToContent)
|
||||
inline void ImageWidget::SetTexture(const Nz::TextureRef& texture)
|
||||
{
|
||||
m_sprite->SetTexture(texture, false);
|
||||
|
||||
if (resizeToContent)
|
||||
ResizeToContent();
|
||||
Nz::Vector2f textureSize = Nz::Vector2f(Nz::Vector2ui(m_sprite->GetMaterial()->GetDiffuseMap()->GetSize()));
|
||||
SetMinimumSize(textureSize);
|
||||
SetPreferredSize(textureSize);
|
||||
}
|
||||
|
||||
inline void ImageWidget::SetTextureCoords(const Nz::Rectf& coords)
|
||||
|
|
|
|||
|
|
@ -21,23 +21,17 @@ namespace Ndk
|
|||
class NDK_API LabelWidget : public BaseWidget
|
||||
{
|
||||
public:
|
||||
LabelWidget(BaseWidget* parent = nullptr);
|
||||
LabelWidget(BaseWidget* parent);
|
||||
LabelWidget(const LabelWidget&) = delete;
|
||||
LabelWidget(LabelWidget&&) = default;
|
||||
~LabelWidget() = default;
|
||||
|
||||
//virtual LabelWidget* Clone() const = 0;
|
||||
|
||||
void ResizeToContent() override;
|
||||
|
||||
inline void UpdateText(const Nz::AbstractTextDrawer& drawer);
|
||||
|
||||
LabelWidget& operator=(const LabelWidget&) = delete;
|
||||
LabelWidget& operator=(LabelWidget&&) = default;
|
||||
|
||||
private:
|
||||
void Layout() override;
|
||||
|
||||
EntityHandle m_textEntity;
|
||||
Nz::TextSpriteRef m_textSprite;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,5 +9,9 @@ namespace Ndk
|
|||
inline void LabelWidget::UpdateText(const Nz::AbstractTextDrawer& drawer)
|
||||
{
|
||||
m_textSprite->Update(drawer);
|
||||
|
||||
Nz::Vector2f size = Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths());
|
||||
SetMinimumSize(size);
|
||||
SetPreferredSize(size);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// 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 Prerequisites.hpp
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ namespace Ndk
|
|||
friend class Sdk;
|
||||
|
||||
public:
|
||||
ProgressBarWidget(BaseWidget* parent = nullptr);
|
||||
ProgressBarWidget(BaseWidget* parent);
|
||||
ProgressBarWidget(const ProgressBarWidget&) = delete;
|
||||
ProgressBarWidget(ProgressBarWidget&&) = default;
|
||||
~ProgressBarWidget() = default;
|
||||
|
|
@ -67,8 +67,6 @@ namespace Ndk
|
|||
inline void SetTextMargin(float margin);
|
||||
inline void SetTextColor(const Nz::Color& color);
|
||||
|
||||
inline void ResizeToContent() override {}
|
||||
|
||||
NazaraSignal(OnValueChanged, const ProgressBarWidget* /*progressBar*/);
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// 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 Prerequisites.hpp
|
||||
|
||||
|
|
@ -148,9 +148,8 @@ namespace Ndk
|
|||
{
|
||||
if (IsTextEnabled())
|
||||
{
|
||||
Nz::Vector2f size = GetContentSize();
|
||||
m_textSprite->Update(Nz::SimpleTextDrawer::Draw(Nz::String::Number(m_value).Append('%'),
|
||||
static_cast<unsigned>(std::min(size.x, size.y) / 2.f), 0u, m_textColor));
|
||||
Nz::Vector2f size = GetSize();
|
||||
m_textSprite->Update(Nz::SimpleTextDrawer::Draw(Nz::String::Number(m_value).Append('%'), static_cast<unsigned int>(std::min(size.x, size.y) / 2.f), 0u, m_textColor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NDK_WIDGETS_RICHTEXTAREAWIDGET_HPP
|
||||
#define NDK_WIDGETS_RICHTEXTAREAWIDGET_HPP
|
||||
|
||||
#include <Nazara/Utility/RichTextDrawer.hpp>
|
||||
#include <NDK/Widgets/AbstractTextAreaWidget.hpp>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
class NDK_API RichTextAreaWidget : public AbstractTextAreaWidget
|
||||
{
|
||||
public:
|
||||
RichTextAreaWidget(BaseWidget* parent);
|
||||
RichTextAreaWidget(const RichTextAreaWidget&) = delete;
|
||||
RichTextAreaWidget(RichTextAreaWidget&&) = default;
|
||||
~RichTextAreaWidget() = default;
|
||||
|
||||
void AppendText(const Nz::String& text);
|
||||
|
||||
void Clear() override;
|
||||
|
||||
void Erase(std::size_t firstGlyph, std::size_t lastGlyph) override;
|
||||
|
||||
inline unsigned int GetCharacterSize() const;
|
||||
inline float GetCharacterSpacingOffset() const;
|
||||
inline float GetLineSpacingOffset() const;
|
||||
inline const Nz::Color& GetTextColor() const;
|
||||
inline Nz::Font* GetTextFont() const;
|
||||
inline const Nz::Color& GetTextOutlineColor() const;
|
||||
inline float GetTextOutlineThickness() const;
|
||||
inline Nz::TextStyleFlags GetTextStyle() const;
|
||||
|
||||
inline void SetCharacterSize(unsigned int characterSize);
|
||||
inline void SetCharacterSpacingOffset(float offset);
|
||||
inline void SetLineSpacingOffset(float offset);
|
||||
inline void SetTextColor(const Nz::Color& color);
|
||||
inline void SetTextFont(Nz::FontRef font);
|
||||
inline void SetTextOutlineColor(const Nz::Color& color);
|
||||
inline void SetTextOutlineThickness(float thickness);
|
||||
inline void SetTextStyle(Nz::TextStyleFlags style);
|
||||
|
||||
void Write(const Nz::String& text, std::size_t glyphPosition) override;
|
||||
|
||||
RichTextAreaWidget& operator=(const RichTextAreaWidget&) = delete;
|
||||
RichTextAreaWidget& operator=(RichTextAreaWidget&&) = default;
|
||||
|
||||
private:
|
||||
Nz::AbstractTextDrawer& GetTextDrawer() override;
|
||||
const Nz::AbstractTextDrawer& GetTextDrawer() const override;
|
||||
|
||||
void HandleIndentation(bool add) override;
|
||||
void HandleSelectionIndentation(bool add) override;
|
||||
void HandleWordCursorMove(bool left) override;
|
||||
|
||||
void UpdateDisplayText() override;
|
||||
|
||||
Nz::RichTextDrawer m_drawer;
|
||||
};
|
||||
}
|
||||
|
||||
#include <NDK/Widgets/RichTextAreaWidget.inl>
|
||||
|
||||
#endif // NDK_WIDGETS_TEXTAREAWIDGET_HPP
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#include <NDK/Widgets/RichTextAreaWidget.hpp>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
inline unsigned int RichTextAreaWidget::GetCharacterSize() const
|
||||
{
|
||||
return m_drawer.GetDefaultCharacterSize();
|
||||
}
|
||||
|
||||
inline float RichTextAreaWidget::GetCharacterSpacingOffset() const
|
||||
{
|
||||
return m_drawer.GetDefaultCharacterSpacingOffset();
|
||||
}
|
||||
|
||||
inline float RichTextAreaWidget::GetLineSpacingOffset() const
|
||||
{
|
||||
return m_drawer.GetDefaultLineSpacingOffset();
|
||||
}
|
||||
|
||||
inline const Nz::Color& RichTextAreaWidget::GetTextColor() const
|
||||
{
|
||||
return m_drawer.GetDefaultColor();
|
||||
}
|
||||
|
||||
inline Nz::Font* RichTextAreaWidget::GetTextFont() const
|
||||
{
|
||||
return m_drawer.GetDefaultFont();
|
||||
}
|
||||
|
||||
inline const Nz::Color& RichTextAreaWidget::GetTextOutlineColor() const
|
||||
{
|
||||
return m_drawer.GetDefaultOutlineColor();
|
||||
}
|
||||
|
||||
inline float RichTextAreaWidget::GetTextOutlineThickness() const
|
||||
{
|
||||
return m_drawer.GetDefaultOutlineThickness();
|
||||
}
|
||||
|
||||
inline Nz::TextStyleFlags RichTextAreaWidget::GetTextStyle() const
|
||||
{
|
||||
return m_drawer.GetDefaultStyle();
|
||||
}
|
||||
|
||||
inline void RichTextAreaWidget::SetCharacterSize(unsigned int characterSize)
|
||||
{
|
||||
m_drawer.SetDefaultCharacterSize(characterSize);
|
||||
}
|
||||
|
||||
inline void RichTextAreaWidget::SetCharacterSpacingOffset(float offset)
|
||||
{
|
||||
m_drawer.SetDefaultCharacterSpacingOffset(offset);
|
||||
}
|
||||
|
||||
inline void RichTextAreaWidget::SetLineSpacingOffset(float offset)
|
||||
{
|
||||
m_drawer.SetDefaultLineSpacingOffset(offset);
|
||||
}
|
||||
|
||||
inline void RichTextAreaWidget::SetTextColor(const Nz::Color& color)
|
||||
{
|
||||
m_drawer.SetDefaultColor(color);
|
||||
}
|
||||
|
||||
inline void RichTextAreaWidget::SetTextFont(Nz::FontRef font)
|
||||
{
|
||||
m_drawer.SetDefaultFont(std::move(font));
|
||||
}
|
||||
|
||||
inline void RichTextAreaWidget::SetTextOutlineColor(const Nz::Color& color)
|
||||
{
|
||||
m_drawer.SetDefaultOutlineColor(color);
|
||||
}
|
||||
|
||||
inline void RichTextAreaWidget::SetTextOutlineThickness(float thickness)
|
||||
{
|
||||
m_drawer.SetDefaultOutlineThickness(thickness);
|
||||
}
|
||||
|
||||
inline void RichTextAreaWidget::SetTextStyle(Nz::TextStyleFlags style)
|
||||
{
|
||||
m_drawer.SetDefaultStyle(style);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
// Copyright (C) 2019 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NDK_WIDGETS_SCROLLAREAWIDGET_HPP
|
||||
#define NDK_WIDGETS_SCROLLAREAWIDGET_HPP
|
||||
|
||||
#include <NDK/Prerequisites.hpp>
|
||||
#include <NDK/BaseWidget.hpp>
|
||||
#include <Nazara/Graphics/TextSprite.hpp>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
class NDK_API ScrollAreaWidget : public BaseWidget
|
||||
{
|
||||
public:
|
||||
ScrollAreaWidget(BaseWidget* parent, BaseWidget* content);
|
||||
ScrollAreaWidget(const ScrollAreaWidget&) = delete;
|
||||
ScrollAreaWidget(ScrollAreaWidget&&) = default;
|
||||
~ScrollAreaWidget() = default;
|
||||
|
||||
void EnableScrollbar(bool enable);
|
||||
|
||||
inline float GetScrollHeight() const;
|
||||
inline float GetScrollRatio() const;
|
||||
|
||||
inline bool HasScrollbar() const;
|
||||
inline bool IsScrollbarEnabled() const;
|
||||
inline bool IsScrollbarVisible() const;
|
||||
|
||||
inline void ScrollToHeight(float height);
|
||||
void ScrollToRatio(float ratio);
|
||||
|
||||
ScrollAreaWidget& operator=(const ScrollAreaWidget&) = delete;
|
||||
ScrollAreaWidget& operator=(ScrollAreaWidget&&) = default;
|
||||
|
||||
private:
|
||||
enum class ScrollBarStatus
|
||||
{
|
||||
Grabbed,
|
||||
Hovered,
|
||||
None
|
||||
};
|
||||
|
||||
Nz::Rectf GetScrollbarRect() const;
|
||||
|
||||
void Layout() override;
|
||||
|
||||
void OnMouseButtonPress(int x, int y, Nz::Mouse::Button button) override;
|
||||
void OnMouseButtonRelease(int x, int y, Nz::Mouse::Button button) override;
|
||||
void OnMouseExit() override;
|
||||
void OnMouseMoved(int x, int y, int deltaX, int deltaY) override;
|
||||
void OnMouseWheelMoved(int x, int y, float delta) override;
|
||||
|
||||
void UpdateScrollbarStatus(ScrollBarStatus status);
|
||||
|
||||
BaseWidget* m_content;
|
||||
EntityHandle m_scrollbarBackgroundEntity;
|
||||
EntityHandle m_scrollbarEntity;
|
||||
Nz::SpriteRef m_scrollbarBackgroundSprite;
|
||||
Nz::SpriteRef m_scrollbarSprite;
|
||||
Nz::Vector2i m_grabbedDelta;
|
||||
ScrollBarStatus m_scrollbarStatus;
|
||||
bool m_isScrollbarEnabled;
|
||||
bool m_hasScrollbar;
|
||||
float m_scrollRatio;
|
||||
};
|
||||
}
|
||||
|
||||
#include <NDK/Widgets/ScrollAreaWidget.inl>
|
||||
|
||||
#endif // NDK_WIDGETS_SCROLLAREAWIDGET_HPP
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright (C) 2019 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#include <NDK/Widgets/ScrollAreaWidget.hpp>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
inline float ScrollAreaWidget::GetScrollHeight() const
|
||||
{
|
||||
return m_scrollRatio * m_content->GetHeight();
|
||||
}
|
||||
|
||||
inline float ScrollAreaWidget::GetScrollRatio() const
|
||||
{
|
||||
return m_scrollRatio;
|
||||
}
|
||||
|
||||
inline bool ScrollAreaWidget::HasScrollbar() const
|
||||
{
|
||||
return m_hasScrollbar;
|
||||
}
|
||||
|
||||
inline bool ScrollAreaWidget::IsScrollbarEnabled() const
|
||||
{
|
||||
return m_isScrollbarEnabled;
|
||||
}
|
||||
|
||||
inline bool ScrollAreaWidget::IsScrollbarVisible() const
|
||||
{
|
||||
return HasScrollbar() && IsScrollbarEnabled();
|
||||
}
|
||||
|
||||
inline void ScrollAreaWidget::ScrollToHeight(float height)
|
||||
{
|
||||
float contentHeight = m_content->GetHeight();
|
||||
ScrollToRatio(height / contentHeight);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,108 +7,68 @@
|
|||
#ifndef NDK_WIDGETS_TEXTAREAWIDGET_HPP
|
||||
#define NDK_WIDGETS_TEXTAREAWIDGET_HPP
|
||||
|
||||
#include <Nazara/Graphics/TextSprite.hpp>
|
||||
#include <Nazara/Utility/SimpleTextDrawer.hpp>
|
||||
#include <NDK/BaseWidget.hpp>
|
||||
#include <NDK/Widgets/Enums.hpp>
|
||||
#include <vector>
|
||||
#include <NDK/Widgets/AbstractTextAreaWidget.hpp>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
class NDK_API TextAreaWidget : public BaseWidget
|
||||
class NDK_API TextAreaWidget : public AbstractTextAreaWidget
|
||||
{
|
||||
public:
|
||||
TextAreaWidget(BaseWidget* parent = nullptr);
|
||||
TextAreaWidget(BaseWidget* parent);
|
||||
TextAreaWidget(const TextAreaWidget&) = delete;
|
||||
TextAreaWidget(TextAreaWidget&&) = default;
|
||||
~TextAreaWidget() = default;
|
||||
|
||||
void AppendText(const Nz::String& text);
|
||||
|
||||
inline void Clear();
|
||||
void Clear() override;
|
||||
|
||||
//virtual TextAreaWidget* Clone() const = 0;
|
||||
|
||||
inline void EnableMultiline(bool enable = true);
|
||||
|
||||
void EraseSelection();
|
||||
using AbstractTextAreaWidget::Erase;
|
||||
void Erase(std::size_t firstGlyph, std::size_t lastGlyph) override;
|
||||
|
||||
inline unsigned int GetCharacterSize() const;
|
||||
inline const Nz::Vector2ui& GetCursorPosition() const;
|
||||
inline Nz::Vector2ui GetCursorPosition(std::size_t glyphIndex) const;
|
||||
inline const Nz::String& GetDisplayText() const;
|
||||
inline EchoMode GetEchoMode() const;
|
||||
inline std::size_t GetGlyphIndex(const Nz::Vector2ui& cursorPosition);
|
||||
inline float GetCharacterSpacingOffset() const;
|
||||
inline float GetLineSpacingOffset() const;
|
||||
inline const Nz::String& GetText() const;
|
||||
inline const Nz::Color& GetTextColor() const;
|
||||
|
||||
Nz::Vector2ui GetHoveredGlyph(float x, float y) const;
|
||||
|
||||
inline bool HasSelection() const;
|
||||
|
||||
inline bool IsMultilineEnabled() const;
|
||||
inline bool IsReadOnly() const;
|
||||
|
||||
inline void MoveCursor(int offset);
|
||||
inline void MoveCursor(const Nz::Vector2i& offset);
|
||||
|
||||
void ResizeToContent() override;
|
||||
inline Nz::Font* GetTextFont() const;
|
||||
inline const Nz::Color& GetTextOulineColor() const;
|
||||
inline float GetTextOulineThickness() const;
|
||||
inline Nz::TextStyleFlags GetTextStyle() const;
|
||||
|
||||
inline void SetCharacterSize(unsigned int characterSize);
|
||||
inline void SetCursorPosition(std::size_t glyphIndex);
|
||||
inline void SetCursorPosition(Nz::Vector2ui cursorPosition);
|
||||
inline void SetEchoMode(EchoMode echoMode);
|
||||
inline void SetReadOnly(bool readOnly = true);
|
||||
inline void SetSelection(Nz::Vector2ui fromPosition, Nz::Vector2ui toPosition);
|
||||
inline void SetCharacterSpacingOffset(float offset);
|
||||
inline void SetLineSpacingOffset(float offset);
|
||||
inline void SetText(const Nz::String& text);
|
||||
inline void SetTextColor(const Nz::Color& text);
|
||||
inline void SetTextFont(Nz::FontRef font);
|
||||
inline void SetTextOutlineColor(const Nz::Color& color);
|
||||
inline void SetTextOutlineThickness(float thickness);
|
||||
inline void SetTextStyle(Nz::TextStyleFlags style);
|
||||
|
||||
void Write(const Nz::String& text);
|
||||
using AbstractTextAreaWidget::Write;
|
||||
void Write(const Nz::String& text, std::size_t glyphPosition) override;
|
||||
|
||||
TextAreaWidget& operator=(const TextAreaWidget&) = delete;
|
||||
TextAreaWidget& operator=(TextAreaWidget&&) = default;
|
||||
|
||||
NazaraSignal(OnTextAreaCursorMove, const TextAreaWidget* /*textArea*/, std::size_t* /*newCursorPosition*/);
|
||||
NazaraSignal(OnTextAreaKeyBackspace, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||
NazaraSignal(OnTextAreaKeyDown, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||
NazaraSignal(OnTextAreaKeyEnd, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||
NazaraSignal(OnTextAreaKeyHome, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||
NazaraSignal(OnTextAreaKeyLeft, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||
NazaraSignal(OnTextAreaKeyReturn, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||
NazaraSignal(OnTextAreaKeyRight, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||
NazaraSignal(OnTextAreaKeyUp, const TextAreaWidget* /*textArea*/, bool* /*ignoreDefaultAction*/);
|
||||
NazaraSignal(OnTextChanged, const TextAreaWidget* /*textArea*/, const Nz::String& /*text*/);
|
||||
NazaraSignal(OnTextChanged, const AbstractTextAreaWidget* /*textArea*/, const Nz::String& /*text*/);
|
||||
|
||||
private:
|
||||
void Layout() override;
|
||||
Nz::AbstractTextDrawer& GetTextDrawer() override;
|
||||
const Nz::AbstractTextDrawer& GetTextDrawer() const override;
|
||||
|
||||
bool IsFocusable() const override;
|
||||
void OnFocusLost() override;
|
||||
void OnFocusReceived() override;
|
||||
bool OnKeyPressed(const Nz::WindowEvent::KeyEvent& key) override;
|
||||
void OnKeyReleased(const Nz::WindowEvent::KeyEvent& key) override;
|
||||
void OnMouseButtonPress(int /*x*/, int /*y*/, Nz::Mouse::Button button) override;
|
||||
void OnMouseButtonRelease(int /*x*/, int /*y*/, Nz::Mouse::Button button) override;
|
||||
void OnMouseEnter() override;
|
||||
void OnMouseMoved(int x, int y, int deltaX, int deltaY) override;
|
||||
void OnTextEntered(char32_t character, bool repeated) override;
|
||||
void HandleIndentation(bool add) override;
|
||||
void HandleSelectionIndentation(bool add) override;
|
||||
void HandleWordCursorMove(bool left) override;
|
||||
|
||||
void RefreshCursor();
|
||||
void UpdateDisplayText();
|
||||
void UpdateDisplayText() override;
|
||||
void UpdateMinimumSize();
|
||||
|
||||
EchoMode m_echoMode;
|
||||
EntityHandle m_cursorEntity;
|
||||
EntityHandle m_textEntity;
|
||||
Nz::SimpleTextDrawer m_drawer;
|
||||
Nz::String m_text;
|
||||
Nz::TextSpriteRef m_textSprite;
|
||||
Nz::Vector2ui m_cursorPositionBegin;
|
||||
Nz::Vector2ui m_cursorPositionEnd;
|
||||
Nz::Vector2ui m_selectionCursor;
|
||||
std::vector<Nz::SpriteRef> m_cursorSprites;
|
||||
bool m_isMouseButtonDown;
|
||||
bool m_multiLineEnabled;
|
||||
bool m_readOnly;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,75 +6,24 @@
|
|||
|
||||
namespace Ndk
|
||||
{
|
||||
inline void TextAreaWidget::Clear()
|
||||
{
|
||||
m_cursorPositionBegin.MakeZero();
|
||||
m_cursorPositionEnd.MakeZero();
|
||||
m_drawer.Clear();
|
||||
m_text.Clear();
|
||||
m_textSprite->Update(m_drawer);
|
||||
|
||||
RefreshCursor();
|
||||
OnTextChanged(this, m_text);
|
||||
}
|
||||
|
||||
inline void TextAreaWidget::EnableMultiline(bool enable)
|
||||
{
|
||||
m_multiLineEnabled = enable;
|
||||
}
|
||||
|
||||
inline unsigned int TextAreaWidget::GetCharacterSize() const
|
||||
{
|
||||
return m_drawer.GetCharacterSize();
|
||||
}
|
||||
|
||||
inline const Nz::Vector2ui& TextAreaWidget::GetCursorPosition() const
|
||||
{
|
||||
return m_cursorPositionBegin;
|
||||
}
|
||||
|
||||
Nz::Vector2ui TextAreaWidget::GetCursorPosition(std::size_t glyphIndex) const
|
||||
{
|
||||
glyphIndex = std::min(glyphIndex, m_drawer.GetGlyphCount());
|
||||
|
||||
std::size_t lineCount = m_drawer.GetLineCount();
|
||||
std::size_t line = 0U;
|
||||
for (std::size_t i = line + 1; i < lineCount; ++i)
|
||||
{
|
||||
if (m_drawer.GetLine(i).glyphIndex > glyphIndex)
|
||||
break;
|
||||
|
||||
line = i;
|
||||
}
|
||||
|
||||
const auto& lineInfo = m_drawer.GetLine(line);
|
||||
|
||||
Nz::Vector2ui cursorPos;
|
||||
cursorPos.y = static_cast<unsigned int>(line);
|
||||
cursorPos.x = static_cast<unsigned int>(glyphIndex - lineInfo.glyphIndex);
|
||||
|
||||
return cursorPos;
|
||||
}
|
||||
|
||||
inline const Nz::String& TextAreaWidget::GetDisplayText() const
|
||||
{
|
||||
return m_drawer.GetText();
|
||||
}
|
||||
|
||||
inline std::size_t TextAreaWidget::GetGlyphIndex(const Nz::Vector2ui& cursorPosition)
|
||||
inline float TextAreaWidget::GetCharacterSpacingOffset() const
|
||||
{
|
||||
std::size_t glyphIndex = m_drawer.GetLine(cursorPosition.y).glyphIndex + cursorPosition.x;
|
||||
if (m_drawer.GetLineCount() > cursorPosition.y + 1)
|
||||
glyphIndex = std::min(glyphIndex, m_drawer.GetLine(cursorPosition.y + 1).glyphIndex - 1);
|
||||
else
|
||||
glyphIndex = std::min(glyphIndex, m_drawer.GetGlyphCount());
|
||||
|
||||
return glyphIndex;
|
||||
return m_drawer.GetCharacterSpacingOffset();
|
||||
}
|
||||
|
||||
inline EchoMode TextAreaWidget::GetEchoMode() const
|
||||
inline float TextAreaWidget::GetLineSpacingOffset() const
|
||||
{
|
||||
return m_echoMode;
|
||||
return m_drawer.GetLineSpacingOffset();
|
||||
}
|
||||
|
||||
inline const Nz::String& TextAreaWidget::GetText() const
|
||||
|
|
@ -87,126 +36,47 @@ namespace Ndk
|
|||
return m_drawer.GetColor();
|
||||
}
|
||||
|
||||
inline bool TextAreaWidget::HasSelection() const
|
||||
inline Nz::Font* TextAreaWidget::GetTextFont() const
|
||||
{
|
||||
return m_cursorPositionBegin != m_cursorPositionEnd;
|
||||
return m_drawer.GetFont();
|
||||
}
|
||||
|
||||
inline bool TextAreaWidget::IsMultilineEnabled() const
|
||||
inline const Nz::Color& TextAreaWidget::GetTextOulineColor() const
|
||||
{
|
||||
return m_multiLineEnabled;
|
||||
return m_drawer.GetOutlineColor();
|
||||
}
|
||||
|
||||
inline bool TextAreaWidget::IsReadOnly() const
|
||||
inline float TextAreaWidget::GetTextOulineThickness() const
|
||||
{
|
||||
return m_readOnly;
|
||||
return m_drawer.GetOutlineThickness();
|
||||
}
|
||||
|
||||
inline void TextAreaWidget::MoveCursor(int offset)
|
||||
inline Nz::TextStyleFlags TextAreaWidget::GetTextStyle() const
|
||||
{
|
||||
std::size_t cursorGlyph = GetGlyphIndex(m_cursorPositionBegin);
|
||||
if (offset >= 0)
|
||||
SetCursorPosition(cursorGlyph + static_cast<std::size_t>(offset));
|
||||
else
|
||||
{
|
||||
std::size_t nOffset = static_cast<std::size_t>(-offset);
|
||||
if (nOffset >= cursorGlyph)
|
||||
SetCursorPosition(0);
|
||||
else
|
||||
SetCursorPosition(cursorGlyph - nOffset);
|
||||
}
|
||||
}
|
||||
|
||||
inline void TextAreaWidget::MoveCursor(const Nz::Vector2i& offset)
|
||||
{
|
||||
auto ClampOffset = [] (unsigned int cursorPosition, int cursorOffset) -> unsigned int
|
||||
{
|
||||
if (cursorOffset >= 0)
|
||||
return cursorPosition + cursorOffset;
|
||||
else
|
||||
{
|
||||
unsigned int nOffset = static_cast<unsigned int>(-cursorOffset);
|
||||
if (nOffset >= cursorPosition)
|
||||
return 0;
|
||||
else
|
||||
return cursorPosition - nOffset;
|
||||
}
|
||||
};
|
||||
|
||||
Nz::Vector2ui cursorPosition = m_cursorPositionBegin;
|
||||
cursorPosition.x = ClampOffset(static_cast<unsigned int>(cursorPosition.x), offset.x);
|
||||
cursorPosition.y = ClampOffset(static_cast<unsigned int>(cursorPosition.y), offset.y);
|
||||
|
||||
SetCursorPosition(cursorPosition);
|
||||
return m_drawer.GetStyle();
|
||||
}
|
||||
|
||||
inline void TextAreaWidget::SetCharacterSize(unsigned int characterSize)
|
||||
{
|
||||
m_drawer.SetCharacterSize(characterSize);
|
||||
}
|
||||
|
||||
inline void TextAreaWidget::SetCursorPosition(std::size_t glyphIndex)
|
||||
{
|
||||
OnTextAreaCursorMove(this, &glyphIndex);
|
||||
|
||||
m_cursorPositionBegin = GetCursorPosition(glyphIndex);
|
||||
m_cursorPositionEnd = m_cursorPositionBegin;
|
||||
|
||||
RefreshCursor();
|
||||
}
|
||||
|
||||
inline void TextAreaWidget::SetCursorPosition(Nz::Vector2ui cursorPosition)
|
||||
{
|
||||
std::size_t lineCount = m_drawer.GetLineCount();
|
||||
if (cursorPosition.y >= lineCount)
|
||||
cursorPosition.y = static_cast<unsigned int>(lineCount - 1);
|
||||
|
||||
m_cursorPositionBegin = cursorPosition;
|
||||
|
||||
const auto& lineInfo = m_drawer.GetLine(cursorPosition.y);
|
||||
if (cursorPosition.y + 1 < lineCount)
|
||||
{
|
||||
const auto& nextLineInfo = m_drawer.GetLine(cursorPosition.y + 1);
|
||||
cursorPosition.x = std::min(cursorPosition.x, static_cast<unsigned int>(nextLineInfo.glyphIndex - lineInfo.glyphIndex - 1));
|
||||
}
|
||||
|
||||
m_cursorPositionEnd = m_cursorPositionBegin;
|
||||
|
||||
std::size_t glyphIndex = lineInfo.glyphIndex + cursorPosition.x;
|
||||
|
||||
OnTextAreaCursorMove(this, &glyphIndex);
|
||||
|
||||
RefreshCursor();
|
||||
}
|
||||
|
||||
inline void TextAreaWidget::SetEchoMode(EchoMode echoMode)
|
||||
{
|
||||
m_echoMode = echoMode;
|
||||
|
||||
UpdateMinimumSize();
|
||||
UpdateDisplayText();
|
||||
}
|
||||
|
||||
inline void TextAreaWidget::SetReadOnly(bool readOnly)
|
||||
inline void TextAreaWidget::SetCharacterSpacingOffset(float offset)
|
||||
{
|
||||
m_readOnly = readOnly;
|
||||
m_cursorEntity->Enable(!m_readOnly && HasFocus());
|
||||
m_drawer.SetCharacterSpacingOffset(offset);
|
||||
|
||||
UpdateMinimumSize();
|
||||
UpdateDisplayText();
|
||||
}
|
||||
|
||||
inline void TextAreaWidget::SetSelection(Nz::Vector2ui fromPosition, Nz::Vector2ui toPosition)
|
||||
inline void TextAreaWidget::SetLineSpacingOffset(float offset)
|
||||
{
|
||||
///TODO: Check if position are valid
|
||||
m_drawer.SetLineSpacingOffset(offset);
|
||||
|
||||
// Ensure begin is before end
|
||||
if (toPosition.y < fromPosition.y || (toPosition.y == fromPosition.y && toPosition.x < fromPosition.x))
|
||||
std::swap(fromPosition, toPosition);
|
||||
|
||||
if (m_cursorPositionBegin != fromPosition || m_cursorPositionEnd != toPosition)
|
||||
{
|
||||
m_cursorPositionBegin = fromPosition;
|
||||
m_cursorPositionEnd = toPosition;
|
||||
|
||||
RefreshCursor();
|
||||
}
|
||||
UpdateDisplayText();
|
||||
}
|
||||
|
||||
inline void TextAreaWidget::SetText(const Nz::String& text)
|
||||
|
|
@ -221,6 +91,34 @@ namespace Ndk
|
|||
{
|
||||
m_drawer.SetColor(text);
|
||||
|
||||
m_textSprite->Update(m_drawer);
|
||||
UpdateDisplayText();
|
||||
}
|
||||
|
||||
inline void TextAreaWidget::SetTextFont(Nz::FontRef font)
|
||||
{
|
||||
m_drawer.SetFont(font);
|
||||
|
||||
UpdateDisplayText();
|
||||
}
|
||||
|
||||
inline void TextAreaWidget::SetTextOutlineColor(const Nz::Color& color)
|
||||
{
|
||||
m_drawer.SetOutlineColor(color);
|
||||
|
||||
UpdateDisplayText();
|
||||
}
|
||||
|
||||
inline void TextAreaWidget::SetTextOutlineThickness(float thickness)
|
||||
{
|
||||
m_drawer.SetOutlineThickness(thickness);
|
||||
|
||||
UpdateDisplayText();
|
||||
}
|
||||
|
||||
inline void TextAreaWidget::SetTextStyle(Nz::TextStyleFlags style)
|
||||
{
|
||||
m_drawer.SetStyle(style);
|
||||
|
||||
UpdateDisplayText();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ namespace Ndk
|
|||
|
||||
void Clear() noexcept;
|
||||
const EntityHandle& CloneEntity(EntityId id);
|
||||
const EntityHandle& CloneEntity(const EntityHandle& entity);
|
||||
|
||||
inline void DisableProfiler();
|
||||
inline void EnableProfiler(bool enable = true);
|
||||
|
|
@ -67,6 +68,8 @@ namespace Ndk
|
|||
inline void KillEntity(Entity* entity);
|
||||
inline void KillEntities(const EntityVector& list);
|
||||
|
||||
inline bool IsEntityDying(const Entity* entity) const;
|
||||
inline bool IsEntityDying(EntityId id) const;
|
||||
inline bool IsEntityValid(const Entity* entity) const;
|
||||
inline bool IsEntityIdValid(EntityId id) const;
|
||||
inline bool IsProfilerEnabled() const;
|
||||
|
|
@ -96,6 +99,12 @@ namespace Ndk
|
|||
inline void InvalidateSystemOrder();
|
||||
void ReorderSystems();
|
||||
|
||||
struct DoubleBitset
|
||||
{
|
||||
Nz::Bitset<Nz::UInt64> front;
|
||||
Nz::Bitset<Nz::UInt64> back;
|
||||
};
|
||||
|
||||
struct EntityBlock
|
||||
{
|
||||
EntityBlock(Entity&& e) :
|
||||
|
|
@ -117,9 +126,9 @@ namespace Ndk
|
|||
std::vector<std::unique_ptr<EntityBlock>> m_waitingEntities;
|
||||
EntityList m_aliveEntities;
|
||||
ProfilerData m_profilerData;
|
||||
Nz::Bitset<Nz::UInt64> m_dirtyEntities;
|
||||
DoubleBitset m_dirtyEntities;
|
||||
Nz::Bitset<Nz::UInt64> m_freeEntityIds;
|
||||
Nz::Bitset<Nz::UInt64> m_killedEntities;
|
||||
DoubleBitset m_killedEntities;
|
||||
bool m_orderedSystemsUpdated;
|
||||
bool m_isProfilerEnabled;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ namespace Ndk
|
|||
inline void World::KillEntity(Entity* entity)
|
||||
{
|
||||
if (IsEntityValid(entity))
|
||||
m_killedEntities.UnboundedSet(entity->GetId(), true);
|
||||
m_killedEntities.front.UnboundedSet(entity->GetId(), true);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -324,13 +324,34 @@ namespace Ndk
|
|||
KillEntity(entity);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether or not an entity is dying (has been killed this update)
|
||||
* \return true If the entity exists and is dying
|
||||
*
|
||||
* \param entity Pointer to the entity
|
||||
*/
|
||||
inline bool World::IsEntityDying(const Entity* entity) const
|
||||
{
|
||||
return entity && IsEntityDying(entity->GetId());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether or not an entity is dying (has been killed this update)
|
||||
* \return true If it is the case, false if the entity is alive (and hasn't been killed yet) or if the entity id is invalid
|
||||
*
|
||||
* \param id Identifier of the entity
|
||||
*/
|
||||
inline bool World::IsEntityDying(EntityId id) const
|
||||
{
|
||||
return m_killedEntities.front.UnboundedTest(id);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks whether or not an entity is valid
|
||||
* \return true If it is the case
|
||||
*
|
||||
* \param entity Pointer to the entity
|
||||
*/
|
||||
|
||||
inline bool World::IsEntityValid(const Entity* entity) const
|
||||
{
|
||||
return entity && entity->GetWorld() == this && IsEntityIdValid(entity->GetId());
|
||||
|
|
@ -446,13 +467,13 @@ namespace Ndk
|
|||
|
||||
inline void World::Invalidate()
|
||||
{
|
||||
m_dirtyEntities.Resize(m_entityBlocks.size(), false);
|
||||
m_dirtyEntities.Set(true); // Activation of all bits
|
||||
m_dirtyEntities.front.Resize(m_entityBlocks.size(), false);
|
||||
m_dirtyEntities.front.Set(true); // Activation of all bits
|
||||
}
|
||||
|
||||
inline void World::Invalidate(EntityId id)
|
||||
{
|
||||
m_dirtyEntities.UnboundedSet(id, true);
|
||||
m_dirtyEntities.front.UnboundedSet(id, true);
|
||||
}
|
||||
|
||||
inline void World::InvalidateSystemOrder()
|
||||
|
|
|
|||
|
|
@ -147,16 +147,22 @@ namespace Ndk
|
|||
|
||||
Nz::Vector2ui windowDimensions;
|
||||
if (info.window->IsValid())
|
||||
{
|
||||
windowDimensions = info.window->GetSize();
|
||||
windowDimensions.y /= 4;
|
||||
}
|
||||
else
|
||||
windowDimensions.MakeZero();
|
||||
|
||||
overlay->console = std::make_unique<Console>(*info.overlayWorld, Nz::Vector2f(windowDimensions), overlay->lua);
|
||||
Nz::LuaInstance& lua = overlay->lua;
|
||||
|
||||
overlay->console = info.canvas->Add<Console>();
|
||||
overlay->console->OnCommand.Connect([&lua](Ndk::Console* console, const Nz::String& command)
|
||||
{
|
||||
if (!lua.Execute(command))
|
||||
console->AddLine(lua.GetLastError(), Nz::Color::Red);
|
||||
});
|
||||
|
||||
Console& consoleRef = *overlay->console;
|
||||
consoleRef.Resize({float(windowDimensions.x), windowDimensions.y / 4.f});
|
||||
consoleRef.Show(false);
|
||||
|
||||
// Redirect logs toward the console
|
||||
overlay->logSlot.Connect(Nz::Log::OnLogWrite, [&consoleRef] (const Nz::String& str)
|
||||
|
|
@ -164,11 +170,11 @@ namespace Ndk
|
|||
consoleRef.AddLine(str);
|
||||
});
|
||||
|
||||
overlay->lua.LoadLibraries();
|
||||
LuaAPI::RegisterClasses(overlay->lua);
|
||||
lua.LoadLibraries();
|
||||
LuaAPI::RegisterClasses(lua);
|
||||
|
||||
// Override "print" function to add a line in the console
|
||||
overlay->lua.PushFunction([&consoleRef] (Nz::LuaState& state)
|
||||
lua.PushFunction([&consoleRef] (Nz::LuaState& state)
|
||||
{
|
||||
Nz::StringStream stream;
|
||||
|
||||
|
|
@ -192,31 +198,37 @@ namespace Ndk
|
|||
consoleRef.AddLine(stream);
|
||||
return 0;
|
||||
});
|
||||
overlay->lua.SetGlobal("print");
|
||||
lua.SetGlobal("print");
|
||||
|
||||
// Define a few base variables to allow our interface to interact with the application
|
||||
overlay->lua.PushGlobal("Application", Ndk::Application::Instance());
|
||||
overlay->lua.PushGlobal("Console", consoleRef.CreateHandle());
|
||||
lua.PushGlobal("Application", Ndk::Application::Instance());
|
||||
lua.PushGlobal("Console", consoleRef.CreateHandle());
|
||||
|
||||
// Setup a few event callback to handle the console
|
||||
Nz::EventHandler& eventHandler = info.window->GetEventHandler();
|
||||
|
||||
overlay->eventSlot.Connect(eventHandler.OnEvent, [&consoleRef] (const Nz::EventHandler*, const Nz::WindowEvent& event)
|
||||
{
|
||||
if (consoleRef.IsVisible())
|
||||
consoleRef.SendEvent(event);
|
||||
});
|
||||
|
||||
overlay->keyPressedSlot.Connect(eventHandler.OnKeyPressed, [&consoleRef] (const Nz::EventHandler*, const Nz::WindowEvent::KeyEvent& event)
|
||||
{
|
||||
if (event.code == Nz::Keyboard::F9)
|
||||
consoleRef.Show(!consoleRef.IsVisible());
|
||||
{
|
||||
// Toggle console visibility and focus
|
||||
if (consoleRef.IsVisible())
|
||||
{
|
||||
consoleRef.ClearFocus();
|
||||
consoleRef.Show(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
consoleRef.Show(true);
|
||||
consoleRef.SetFocus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
overlay->resizedSlot.Connect(info.renderTarget->OnRenderTargetSizeChange, [&consoleRef] (const Nz::RenderTarget* renderTarget)
|
||||
{
|
||||
Nz::Vector2ui size = renderTarget->GetSize();
|
||||
consoleRef.SetSize({float(size.x), size.y / 4.f});
|
||||
consoleRef.Resize({float(size.x), size.y / 4.f});
|
||||
});
|
||||
|
||||
info.console = std::move(overlay);
|
||||
|
|
@ -238,6 +250,9 @@ namespace Ndk
|
|||
{
|
||||
info.overlayWorld = std::make_unique<World>(false); //< No default system
|
||||
|
||||
if (info.window->IsValid())
|
||||
info.canvas = std::make_unique<Canvas>(info.overlayWorld->CreateHandle(), info.window->GetEventHandler(), info.window->GetCursorController().CreateHandle());
|
||||
|
||||
RenderSystem& renderSystem = info.overlayWorld->AddSystem<RenderSystem>();
|
||||
renderSystem.ChangeRenderTechnique<Nz::ForwardRenderTechnique>();
|
||||
renderSystem.SetDefaultBackground(nullptr);
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ namespace Ndk
|
|||
m_backgroundSprite->SetColor(m_backgroundColor);
|
||||
m_backgroundSprite->SetMaterial(Nz::Material::New((m_backgroundColor.IsOpaque()) ? "Basic2D" : "Translucent2D")); //< TODO: Use a shared material instead of creating one everytime
|
||||
|
||||
m_backgroundEntity = CreateEntity(false);
|
||||
m_backgroundEntity = CreateEntity();
|
||||
m_backgroundEntity->AddComponent<GraphicsComponent>().Attach(m_backgroundSprite, -1);
|
||||
m_backgroundEntity->AddComponent<NodeComponent>().SetParent(this);
|
||||
|
||||
|
|
@ -89,14 +89,15 @@ namespace Ndk
|
|||
}
|
||||
else
|
||||
{
|
||||
m_backgroundEntity->Kill();
|
||||
DestroyEntity(m_backgroundEntity);
|
||||
m_backgroundEntity.Reset();
|
||||
m_backgroundSprite.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Checks if this widget has keyboard focus
|
||||
* \return true if widget has keyboard focus, false otherwhise
|
||||
* \return true if widget has keyboard focus, false otherwise
|
||||
*/
|
||||
bool BaseWidget::HasFocus() const
|
||||
{
|
||||
|
|
@ -106,6 +107,19 @@ namespace Ndk
|
|||
return m_canvas->IsKeyboardOwner(m_canvasIndex);
|
||||
}
|
||||
|
||||
void BaseWidget::Resize(const Nz::Vector2f& size)
|
||||
{
|
||||
// Adjust new size
|
||||
Nz::Vector2f newSize = size;
|
||||
newSize.Maximize(m_minimumSize);
|
||||
newSize.Minimize(m_maximumSize);
|
||||
|
||||
NotifyParentResized(newSize);
|
||||
m_size = newSize;
|
||||
|
||||
Layout();
|
||||
}
|
||||
|
||||
void BaseWidget::SetBackgroundColor(const Nz::Color& color)
|
||||
{
|
||||
m_backgroundColor = color;
|
||||
|
|
@ -131,9 +145,27 @@ namespace Ndk
|
|||
m_canvas->SetKeyboardOwner(m_canvasIndex);
|
||||
}
|
||||
|
||||
void BaseWidget::SetSize(const Nz::Vector2f& size)
|
||||
void BaseWidget::SetParent(BaseWidget* widget)
|
||||
{
|
||||
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)});
|
||||
Canvas* oldCanvas = m_canvas;
|
||||
Canvas* newCanvas = widget->GetCanvas();
|
||||
|
||||
// Changing a widget canvas is a problem because of the canvas entities
|
||||
NazaraAssert(oldCanvas == newCanvas, "Transferring a widget between canvas is not yet supported");
|
||||
|
||||
Node::SetParent(widget);
|
||||
m_widgetParent = widget;
|
||||
|
||||
Layout();
|
||||
}
|
||||
|
||||
void BaseWidget::SetRenderingRect(const Nz::Rectf& renderingRect)
|
||||
{
|
||||
m_renderingRect = renderingRect;
|
||||
|
||||
UpdatePositionAndSize();
|
||||
for (const auto& widgetPtr : m_children)
|
||||
widgetPtr->UpdatePositionAndSize();
|
||||
}
|
||||
|
||||
void BaseWidget::Show(bool show)
|
||||
|
|
@ -148,22 +180,45 @@ namespace Ndk
|
|||
UnregisterFromCanvas();
|
||||
|
||||
for (WidgetEntity& entity : m_entities)
|
||||
entity.handle->Enable(show);
|
||||
{
|
||||
if (entity.isEnabled)
|
||||
{
|
||||
entity.handle->Enable(show); //< This will override isEnabled
|
||||
entity.isEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& widgetPtr : m_children)
|
||||
widgetPtr->Show(show);
|
||||
}
|
||||
}
|
||||
|
||||
const Ndk::EntityHandle& BaseWidget::CreateEntity(bool isContentEntity)
|
||||
const EntityHandle& BaseWidget::CreateEntity()
|
||||
{
|
||||
const EntityHandle& newEntity = m_world->CreateEntity();
|
||||
newEntity->Enable(m_visible);
|
||||
|
||||
m_entities.emplace_back();
|
||||
WidgetEntity& widgetEntity = m_entities.back();
|
||||
widgetEntity.handle = newEntity;
|
||||
widgetEntity.isContent = isContentEntity;
|
||||
WidgetEntity& newWidgetEntity = m_entities.back();
|
||||
newWidgetEntity.handle = newEntity;
|
||||
newWidgetEntity.onDisabledSlot.Connect(newEntity->OnEntityDisabled, [this](Entity* 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");
|
||||
|
||||
it->isEnabled = false;
|
||||
});
|
||||
|
||||
newWidgetEntity.onEnabledSlot.Connect(newEntity->OnEntityEnabled, [this](Entity* 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");
|
||||
|
||||
if (!IsVisible())
|
||||
entity->Disable(); // Next line will override isEnabled status
|
||||
|
||||
it->isEnabled = true;
|
||||
});
|
||||
|
||||
return newEntity;
|
||||
}
|
||||
|
|
@ -178,8 +233,8 @@ namespace Ndk
|
|||
|
||||
void BaseWidget::Layout()
|
||||
{
|
||||
if (m_backgroundEntity)
|
||||
m_backgroundSprite->SetSize(m_contentSize.x + m_padding.left + m_padding.right, m_contentSize.y + m_padding.top + m_padding.bottom);
|
||||
if (m_backgroundSprite)
|
||||
m_backgroundSprite->SetSize(m_size.x, m_size.y);
|
||||
|
||||
UpdatePositionAndSize();
|
||||
}
|
||||
|
|
@ -191,6 +246,19 @@ namespace Ndk
|
|||
UpdatePositionAndSize();
|
||||
}
|
||||
|
||||
Nz::Rectf BaseWidget::GetScissorRect() const
|
||||
{
|
||||
Nz::Vector2f widgetPos = Nz::Vector2f(GetPosition(Nz::CoordSys_Global));
|
||||
Nz::Vector2f widgetSize = GetSize();
|
||||
|
||||
Nz::Rectf widgetRect(widgetPos.x, widgetPos.y, widgetSize.x, widgetSize.y);
|
||||
Nz::Rectf widgetRenderingRect(widgetPos.x + m_renderingRect.x, widgetPos.y + m_renderingRect.y, m_renderingRect.width, m_renderingRect.height);
|
||||
|
||||
widgetRect.Intersect(widgetRenderingRect, &widgetRect);
|
||||
|
||||
return widgetRect;
|
||||
}
|
||||
|
||||
bool BaseWidget::IsFocusable() const
|
||||
{
|
||||
return false;
|
||||
|
|
@ -229,6 +297,10 @@ namespace Ndk
|
|||
{
|
||||
}
|
||||
|
||||
void BaseWidget::OnMouseWheelMoved(int /*x*/, int /*y*/, float /*delta*/)
|
||||
{
|
||||
}
|
||||
|
||||
void BaseWidget::OnMouseExit()
|
||||
{
|
||||
}
|
||||
|
|
@ -279,19 +351,22 @@ namespace Ndk
|
|||
if (IsRegisteredToCanvas())
|
||||
m_canvas->NotifyWidgetBoxUpdate(m_canvasIndex);
|
||||
|
||||
Nz::Vector2f widgetPos = Nz::Vector2f(GetPosition());
|
||||
Nz::Vector2f widgetSize = GetSize();
|
||||
Nz::Rectf scissorRect = GetScissorRect();
|
||||
|
||||
Nz::Vector2f contentPos = widgetPos + GetContentOrigin();
|
||||
Nz::Vector2f contentSize = GetContentSize();
|
||||
if (m_widgetParent)
|
||||
{
|
||||
Nz::Rectf parentScissorRect = m_widgetParent->GetScissorRect();
|
||||
|
||||
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));
|
||||
if (!scissorRect.Intersect(parentScissorRect, &scissorRect))
|
||||
scissorRect = parentScissorRect;
|
||||
}
|
||||
|
||||
Nz::Recti fullBounds(scissorRect);
|
||||
for (WidgetEntity& widgetEntity : m_entities)
|
||||
{
|
||||
const Ndk::EntityHandle& entity = widgetEntity.handle;
|
||||
if (entity->HasComponent<GraphicsComponent>())
|
||||
entity->GetComponent<GraphicsComponent>().SetScissorRect((widgetEntity.isContent) ? contentBounds : fullBounds);
|
||||
entity->GetComponent<GraphicsComponent>().SetScissorRect(fullBounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,10 +7,6 @@
|
|||
|
||||
namespace Ndk
|
||||
{
|
||||
void Canvas::ResizeToContent()
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t Canvas::RegisterWidget(BaseWidget* widget)
|
||||
{
|
||||
WidgetEntry box;
|
||||
|
|
@ -65,7 +61,7 @@ namespace Ndk
|
|||
}
|
||||
}
|
||||
|
||||
void Canvas::OnEventMouseButtonRelease(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseButtonEvent & event)
|
||||
void Canvas::OnEventMouseButtonRelease(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseButtonEvent& event)
|
||||
{
|
||||
if (m_hoveredWidget != InvalidCanvasIndex)
|
||||
{
|
||||
|
|
@ -132,6 +128,19 @@ namespace Ndk
|
|||
}
|
||||
}
|
||||
|
||||
void Canvas::OnEventMouseWheelMoved(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::MouseWheelEvent& event)
|
||||
{
|
||||
if (m_hoveredWidget != InvalidCanvasIndex)
|
||||
{
|
||||
WidgetEntry& hoveredWidget = m_widgetEntries[m_hoveredWidget];
|
||||
|
||||
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->OnMouseWheelMoved(x, y, event.delta);
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::OnEventMouseLeft(const Nz::EventHandler* /*eventHandler*/)
|
||||
{
|
||||
if (m_hoveredWidget != InvalidCanvasIndex)
|
||||
|
|
@ -141,7 +150,7 @@ namespace Ndk
|
|||
}
|
||||
}
|
||||
|
||||
void Canvas::OnEventKeyPressed(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& event)
|
||||
void Canvas::OnEventKeyPressed(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::KeyEvent& event)
|
||||
{
|
||||
if (m_keyboardOwner != InvalidCanvasIndex)
|
||||
{
|
||||
|
|
@ -195,12 +204,16 @@ namespace Ndk
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
OnUnhandledKeyPressed(eventHandler, event);
|
||||
}
|
||||
|
||||
void Canvas::OnEventKeyReleased(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::KeyEvent& event)
|
||||
void Canvas::OnEventKeyReleased(const Nz::EventHandler* eventHandler, const Nz::WindowEvent::KeyEvent& event)
|
||||
{
|
||||
if (m_keyboardOwner != InvalidCanvasIndex)
|
||||
m_widgetEntries[m_keyboardOwner].widget->OnKeyReleased(event);
|
||||
|
||||
OnUnhandledKeyReleased(eventHandler, event);
|
||||
}
|
||||
|
||||
void Canvas::OnEventTextEntered(const Nz::EventHandler* /*eventHandler*/, const Nz::WindowEvent::TextEvent& event)
|
||||
|
|
|
|||
|
|
@ -154,11 +154,10 @@ namespace Ndk
|
|||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the layer of the camera in case of multiples fields
|
||||
* \brief Sets the layer of the camera in case of multiples layers
|
||||
*
|
||||
* \param layer Layer of the camera
|
||||
*/
|
||||
|
||||
void CameraComponent::SetLayer(unsigned int layer)
|
||||
{
|
||||
m_layer = layer;
|
||||
|
|
@ -169,7 +168,6 @@ namespace Ndk
|
|||
/*!
|
||||
* \brief Operation to perform when component is attached to an entity
|
||||
*/
|
||||
|
||||
void CameraComponent::OnAttached()
|
||||
{
|
||||
if (m_entity->HasComponent<NodeComponent>())
|
||||
|
|
@ -304,6 +302,8 @@ namespace Ndk
|
|||
break;
|
||||
}
|
||||
|
||||
m_projectionMatrix *= Nz::Matrix4f::Scale(m_projectionScale);
|
||||
|
||||
m_projectionMatrixUpdated = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,29 +17,57 @@ namespace Ndk
|
|||
* \brief NDK class that represents a two-dimensional collision geometry
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief Gets the collision box representing the entity
|
||||
* \return The physics collision box
|
||||
*/
|
||||
Nz::Rectf CollisionComponent2D::GetAABB() const
|
||||
{
|
||||
return GetRigidBody()->GetAABB();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Gets the position offset between the actual rigid body center of mass position and the origin of the geometry
|
||||
* \return Position offset
|
||||
*/
|
||||
const Nz::Vector2f& CollisionComponent2D::GetGeomOffset() const
|
||||
{
|
||||
return GetRigidBody()->GetPositionOffset();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Convenience function to align center of geometry to a specific point
|
||||
*
|
||||
* \param geomOffset Position offset
|
||||
*
|
||||
* \remark This does not change the center of mass
|
||||
*/
|
||||
void CollisionComponent2D::Recenter(const Nz::Vector2f& origin)
|
||||
{
|
||||
const Nz::RigidBody2D* rigidBody = GetRigidBody();
|
||||
SetGeomOffset(origin - rigidBody->GetAABB().GetCenter() + rigidBody->GetPositionOffset());
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets geometry for the entity
|
||||
*
|
||||
* \param geom Geometry used for collisions
|
||||
*
|
||||
* \remark Produces a NazaraAssert if the entity has no physics component and has no static body
|
||||
*/
|
||||
|
||||
void CollisionComponent2D::SetGeom(Nz::Collider2DRef geom)
|
||||
{
|
||||
m_geom = std::move(geom);
|
||||
|
||||
if (m_entity->HasComponent<PhysicsComponent2D>())
|
||||
{
|
||||
// We update the geometry of the PhysiscsObject linked to the PhysicsComponent2D
|
||||
PhysicsComponent2D& physComponent = m_entity->GetComponent<PhysicsComponent2D>();
|
||||
physComponent.GetRigidBody()->SetGeom(m_geom);
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraAssert(m_staticBody, "An entity without physics component should have a static body");
|
||||
m_staticBody->SetGeom(m_geom);
|
||||
}
|
||||
GetRigidBody()->SetGeom(m_geom);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the position offset between the actual rigid body center of mass position and the origin of the geometry
|
||||
*
|
||||
* \param geomOffset Position offset
|
||||
*/
|
||||
void CollisionComponent2D::SetGeomOffset(const Nz::Vector2f& geomOffset)
|
||||
{
|
||||
GetRigidBody()->SetPositionOffset(geomOffset);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -48,7 +76,6 @@ namespace Ndk
|
|||
* \remark Produces a NazaraAssert if entity is invalid
|
||||
* \remark Produces a NazaraAssert if entity is not linked to a world, or the world has no physics system
|
||||
*/
|
||||
|
||||
void CollisionComponent2D::InitializeStaticBody()
|
||||
{
|
||||
NazaraAssert(m_entity, "Invalid entity");
|
||||
|
|
@ -56,7 +83,7 @@ namespace Ndk
|
|||
|
||||
NazaraAssert(entityWorld, "Entity must have world");
|
||||
NazaraAssert(entityWorld->HasSystem<PhysicsSystem2D>(), "World must have a physics system");
|
||||
Nz::PhysWorld2D& physWorld = entityWorld->GetSystem<PhysicsSystem2D>().GetWorld();
|
||||
Nz::PhysWorld2D& physWorld = entityWorld->GetSystem<PhysicsSystem2D>().GetPhysWorld();
|
||||
|
||||
m_staticBody = std::make_unique<Nz::RigidBody2D>(&physWorld, 0.f, m_geom);
|
||||
m_staticBody->SetUserdata(reinterpret_cast<void*>(static_cast<std::ptrdiff_t>(m_entity->GetId())));
|
||||
|
|
@ -68,7 +95,34 @@ namespace Ndk
|
|||
matrix.MakeIdentity();
|
||||
|
||||
m_staticBody->SetPosition(Nz::Vector2f(matrix.GetTranslation()));
|
||||
}
|
||||
|
||||
Nz::RigidBody2D* CollisionComponent2D::GetRigidBody()
|
||||
{
|
||||
if (m_entity->HasComponent<PhysicsComponent2D>())
|
||||
{
|
||||
PhysicsComponent2D& physComponent = m_entity->GetComponent<PhysicsComponent2D>();
|
||||
return physComponent.GetRigidBody();
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraAssert(m_staticBody, "An entity without physics component should have a static body");
|
||||
return m_staticBody.get();
|
||||
}
|
||||
}
|
||||
|
||||
const Nz::RigidBody2D* CollisionComponent2D::GetRigidBody() const
|
||||
{
|
||||
if (m_entity->HasComponent<PhysicsComponent2D>())
|
||||
{
|
||||
PhysicsComponent2D& physComponent = m_entity->GetComponent<PhysicsComponent2D>();
|
||||
return physComponent.GetRigidBody();
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraAssert(m_staticBody, "An entity without physics component should have a static body");
|
||||
return m_staticBody.get();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
|||
|
|
@ -1,6 +1,23 @@
|
|||
// Copyright (C) 2019 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#include <NDK/Components/ConstraintComponent2D.hpp>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
ConstraintComponent2D::ConstraintComponent2D(const ConstraintComponent2D& /*joint*/)
|
||||
{
|
||||
}
|
||||
|
||||
bool ConstraintComponent2D::RemoveConstraint(Nz::Constraint2D* constraintPtr)
|
||||
{
|
||||
auto it = std::find_if(m_constraints.begin(), m_constraints.end(), [constraintPtr](const ConstraintData& constraintData) { return constraintData.constraint.get() == constraintPtr; });
|
||||
if (it != m_constraints.end())
|
||||
m_constraints.erase(it);
|
||||
|
||||
return !m_constraints.empty();
|
||||
}
|
||||
|
||||
ComponentIndex ConstraintComponent2D::componentIndex;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,33 @@
|
|||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#include <NDK/Components/DebugComponent.hpp>
|
||||
#include <NDK/Components/GraphicsComponent.hpp>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
void DebugComponent::DetachDebugRenderables(GraphicsComponent& gfxComponent)
|
||||
{
|
||||
for (auto& renderable : m_debugRenderables)
|
||||
{
|
||||
if (renderable)
|
||||
{
|
||||
gfxComponent.Detach(renderable);
|
||||
renderable.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DebugComponent::OnComponentDetached(BaseComponent& component)
|
||||
{
|
||||
if (IsComponent<GraphicsComponent>(component))
|
||||
DetachDebugRenderables(static_cast<GraphicsComponent&>(component));
|
||||
}
|
||||
|
||||
void DebugComponent::OnDetached()
|
||||
{
|
||||
if (m_entity->HasComponent<GraphicsComponent>())
|
||||
DetachDebugRenderables(m_entity->GetComponent<GraphicsComponent>());
|
||||
}
|
||||
|
||||
ComponentIndex DebugComponent::componentIndex;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ namespace Ndk
|
|||
*/
|
||||
void GraphicsComponent::AddToRenderQueue(Nz::AbstractRenderQueue* renderQueue) const
|
||||
{
|
||||
EnsureBoundingVolumesUpdate();
|
||||
EnsureTransformMatrixUpdate();
|
||||
|
||||
RenderSystem& renderSystem = m_entity->GetWorld()->GetSystem<RenderSystem>();
|
||||
|
|
@ -30,7 +31,6 @@ namespace Ndk
|
|||
{
|
||||
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;
|
||||
}
|
||||
|
|
@ -39,6 +39,34 @@ namespace Ndk
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds the renderable elements to the render queue if their bounding volume intersects with the frustum
|
||||
*
|
||||
* \param frustum Queue to be added
|
||||
* \param renderQueue Queue to be added
|
||||
*/
|
||||
void GraphicsComponent::AddToRenderQueueByCulling(const Nz::Frustumf& frustum, Nz::AbstractRenderQueue* renderQueue) const
|
||||
{
|
||||
EnsureBoundingVolumesUpdate();
|
||||
EnsureTransformMatrixUpdate();
|
||||
|
||||
RenderSystem& renderSystem = m_entity->GetWorld()->GetSystem<RenderSystem>();
|
||||
|
||||
for (const Renderable& object : m_renderables)
|
||||
{
|
||||
if (frustum.Contains(object.boundingVolume))
|
||||
{
|
||||
if (!object.dataUpdated)
|
||||
{
|
||||
object.renderable->UpdateData(&object.data);
|
||||
object.dataUpdated = true;
|
||||
}
|
||||
|
||||
object.renderable->AddToRenderQueue(renderQueue, object.data, m_scissorRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Attaches a renderable to the entity with a specific matrix
|
||||
*
|
||||
|
|
@ -60,12 +88,13 @@ namespace Ndk
|
|||
for (std::size_t i = 0; i < materialCount; ++i)
|
||||
RegisterMaterial(entry.renderable->GetMaterial(i));
|
||||
|
||||
InvalidateBoundingVolume();
|
||||
InvalidateAABB();
|
||||
ForceCullingInvalidation();
|
||||
}
|
||||
|
||||
void GraphicsComponent::ConnectInstancedRenderableSignals(Renderable& entry)
|
||||
{
|
||||
entry.renderableBoundingVolumeInvalidationSlot.Connect(entry.renderable->OnInstancedRenderableInvalidateBoundingVolume, [this](const Nz::InstancedRenderable*) { InvalidateBoundingVolume(); });
|
||||
entry.renderableBoundingVolumeInvalidationSlot.Connect(entry.renderable->OnInstancedRenderableInvalidateBoundingVolume, [this](const Nz::InstancedRenderable*) { InvalidateAABB(); });
|
||||
entry.renderableDataInvalidationSlot.Connect(entry.renderable->OnInstancedRenderableInvalidateData, std::bind(&GraphicsComponent::InvalidateRenderableData, this, std::placeholders::_1, std::placeholders::_2, m_renderables.size() - 1));
|
||||
entry.renderableMaterialInvalidationSlot.Connect(entry.renderable->OnInstancedRenderableInvalidateMaterial, this, &GraphicsComponent::InvalidateRenderableMaterial);
|
||||
entry.renderableReleaseSlot.Connect(entry.renderable->OnInstancedRenderableRelease, this, &GraphicsComponent::Detach);
|
||||
|
|
@ -82,8 +111,7 @@ namespace Ndk
|
|||
r.dataUpdated = false;
|
||||
r.renderable->InvalidateData(&r.data, flags);
|
||||
|
||||
for (VolumeCullingEntry& entry : m_volumeCullingEntries)
|
||||
entry.listEntry.ForceInvalidation();
|
||||
ForceCullingInvalidation();
|
||||
}
|
||||
|
||||
void GraphicsComponent::InvalidateRenderableMaterial(const Nz::InstancedRenderable* renderable, std::size_t skinIndex, std::size_t matIndex, const Nz::MaterialRef& newMat)
|
||||
|
|
@ -96,9 +124,11 @@ namespace Ndk
|
|||
|
||||
const Nz::MaterialRef& oldMat = renderable->GetMaterial(skinIndex, matIndex);
|
||||
UnregisterMaterial(oldMat);
|
||||
|
||||
ForceCullingInvalidation();
|
||||
}
|
||||
|
||||
void Ndk::GraphicsComponent::InvalidateReflectionMap()
|
||||
void GraphicsComponent::InvalidateReflectionMap()
|
||||
{
|
||||
m_entity->Invalidate();
|
||||
|
||||
|
|
@ -202,6 +232,8 @@ namespace Ndk
|
|||
std::size_t materialCount = renderable->GetMaterialCount();
|
||||
for (std::size_t i = 0; i < materialCount; ++i)
|
||||
UnregisterMaterial(renderable->GetMaterial(i));
|
||||
|
||||
ForceCullingInvalidation();
|
||||
}
|
||||
|
||||
void GraphicsComponent::OnInstancedRenderableSkinChange(const Nz::InstancedRenderable* renderable, std::size_t newSkinIndex)
|
||||
|
|
@ -212,6 +244,8 @@ namespace Ndk
|
|||
|
||||
for (std::size_t i = 0; i < materialCount; ++i)
|
||||
UnregisterMaterial(renderable->GetMaterial(i));
|
||||
|
||||
ForceCullingInvalidation();
|
||||
}
|
||||
|
||||
void GraphicsComponent::OnMaterialReflectionChange(const Nz::Material* material, Nz::ReflectionMode reflectionMode)
|
||||
|
|
@ -234,11 +268,10 @@ namespace Ndk
|
|||
NazaraUnused(node);
|
||||
|
||||
// Our view matrix depends on NodeComponent position/rotation
|
||||
InvalidateBoundingVolume();
|
||||
InvalidateAABB();
|
||||
InvalidateTransformMatrix();
|
||||
|
||||
for (VolumeCullingEntry& entry : m_volumeCullingEntries)
|
||||
entry.listEntry.ForceInvalidation(); //< Force invalidation on movement
|
||||
ForceCullingInvalidation(); //< Force invalidation on movement for now (FIXME)
|
||||
}
|
||||
|
||||
void GraphicsComponent::UnregisterMaterial(Nz::Material* material)
|
||||
|
|
@ -263,36 +296,38 @@ namespace Ndk
|
|||
* \brief Updates the bounding volume
|
||||
*/
|
||||
|
||||
void GraphicsComponent::UpdateBoundingVolume() const
|
||||
void GraphicsComponent::UpdateBoundingVolumes() const
|
||||
{
|
||||
EnsureTransformMatrixUpdate();
|
||||
|
||||
m_boundingVolume.MakeNull();
|
||||
for (const Renderable& r : m_renderables)
|
||||
{
|
||||
Nz::BoundingVolumef boundingVolume = r.renderable->GetBoundingVolume();
|
||||
|
||||
// Adjust renderable bounding volume by local matrix
|
||||
if (boundingVolume.IsFinite())
|
||||
{
|
||||
Nz::Boxf localBox = boundingVolume.obb.localBox;
|
||||
Nz::Vector3f newPos = r.data.localMatrix * localBox.GetPosition();
|
||||
Nz::Vector3f newCorner = r.data.localMatrix * (localBox.GetPosition() + localBox.GetLengths());
|
||||
Nz::Vector3f newLengths = newCorner - newPos;
|
||||
|
||||
boundingVolume.Set(Nz::Boxf(newPos.x, newPos.y, newPos.z, newLengths.x, newLengths.y, newLengths.z));
|
||||
}
|
||||
|
||||
m_boundingVolume.ExtendTo(boundingVolume);
|
||||
}
|
||||
|
||||
RenderSystem& renderSystem = m_entity->GetWorld()->GetSystem<RenderSystem>();
|
||||
|
||||
m_boundingVolume.Update(Nz::Matrix4f::ConcatenateAffine(renderSystem.GetCoordinateSystemMatrix(), m_transformMatrix));
|
||||
m_boundingVolumeUpdated = true;
|
||||
m_aabb.Set(-1.f, -1.f, -1.f);
|
||||
|
||||
for (VolumeCullingEntry& entry : m_volumeCullingEntries)
|
||||
entry.listEntry.UpdateVolume(m_boundingVolume);
|
||||
bool isAabbSet = false;
|
||||
|
||||
for (const Renderable& r : m_renderables)
|
||||
{
|
||||
r.boundingVolume = r.renderable->GetBoundingVolume();
|
||||
r.data.transformMatrix = Nz::Matrix4f::ConcatenateAffine(renderSystem.GetCoordinateSystemMatrix(), Nz::Matrix4f::ConcatenateAffine(r.data.localMatrix, m_transformMatrix));
|
||||
if (r.boundingVolume.IsFinite())
|
||||
{
|
||||
r.boundingVolume.Update(r.data.transformMatrix);
|
||||
|
||||
if (isAabbSet)
|
||||
m_aabb.ExtendTo(r.boundingVolume.aabb);
|
||||
else
|
||||
{
|
||||
m_aabb.Set(r.boundingVolume.aabb);
|
||||
isAabbSet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_boundingVolumesUpdated = true;
|
||||
|
||||
for (CullingBoxEntry& entry : m_cullingBoxEntries)
|
||||
entry.listEntry.UpdateBox(m_aabb);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#include <NDK/Components/LifetimeComponent.hpp>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
ComponentIndex LifetimeComponent::componentIndex;
|
||||
}
|
||||
|
|
@ -29,11 +29,19 @@ namespace Ndk
|
|||
World* entityWorld = m_entity->GetWorld();
|
||||
NazaraAssert(entityWorld->HasSystem<PhysicsSystem2D>(), "World must have a 2D physics system");
|
||||
|
||||
Nz::PhysWorld2D& world = entityWorld->GetSystem<PhysicsSystem2D>().GetWorld();
|
||||
Nz::PhysWorld2D& world = entityWorld->GetSystem<PhysicsSystem2D>().GetPhysWorld();
|
||||
|
||||
Nz::Vector2f positionOffset;
|
||||
|
||||
Nz::Collider2DRef geom;
|
||||
if (m_entity->HasComponent<CollisionComponent2D>())
|
||||
geom = m_entity->GetComponent<CollisionComponent2D>().GetGeom();
|
||||
{
|
||||
const CollisionComponent2D& entityCollision = m_entity->GetComponent<CollisionComponent2D>();
|
||||
geom = entityCollision.GetGeom();
|
||||
positionOffset = entityCollision.GetStaticBody()->GetPositionOffset(); //< Calling GetGeomOffset would retrieve current component which is not yet initialized
|
||||
}
|
||||
else
|
||||
positionOffset = Nz::Vector2f::Zero();
|
||||
|
||||
Nz::Matrix4f matrix;
|
||||
if (m_entity->HasComponent<NodeComponent>())
|
||||
|
|
@ -42,8 +50,12 @@ namespace Ndk
|
|||
matrix.MakeIdentity();
|
||||
|
||||
m_object = std::make_unique<Nz::RigidBody2D>(&world, 1.f, geom);
|
||||
m_object->SetPositionOffset(positionOffset);
|
||||
m_object->SetPosition(Nz::Vector2f(matrix.GetTranslation()));
|
||||
m_object->SetUserdata(reinterpret_cast<void*>(static_cast<std::ptrdiff_t>(m_entity->GetId())));
|
||||
|
||||
if (m_pendingStates.valid)
|
||||
ApplyPhysicsState(*m_object);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -86,7 +98,11 @@ namespace Ndk
|
|||
|
||||
void PhysicsComponent2D::OnDetached()
|
||||
{
|
||||
m_object.reset();
|
||||
if (m_object)
|
||||
{
|
||||
CopyPhysicsState(*m_object);
|
||||
m_object.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsComponent2D::OnEntityDestruction()
|
||||
|
|
|
|||
|
|
@ -4,14 +4,12 @@
|
|||
|
||||
#include <NDK/Console.hpp>
|
||||
#include <Nazara/Core/Unicode.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>
|
||||
#include <NDK/World.hpp>
|
||||
|
||||
///TODO: For now is unable to display different color in the history, it needs a RichTextDrawer to do so
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
namespace
|
||||
|
|
@ -34,71 +32,76 @@ namespace Ndk
|
|||
* \param instance Lua instance that will interact with the world
|
||||
*/
|
||||
|
||||
Console::Console(World& world, const Nz::Vector2f& size, Nz::LuaState& state) :
|
||||
Console::Console(BaseWidget* parent) :
|
||||
BaseWidget(parent),
|
||||
m_historyPosition(0),
|
||||
m_defaultFont(Nz::Font::GetDefault()),
|
||||
m_state(state),
|
||||
m_size(size),
|
||||
m_opened(false),
|
||||
m_characterSize(24)
|
||||
m_characterSize(24),
|
||||
m_maxHistoryLines(200)
|
||||
{
|
||||
Nz::MaterialRef backgroundMaterial = Nz::Material::New();
|
||||
backgroundMaterial->EnableBlending(true);
|
||||
backgroundMaterial->EnableDepthBuffer(false);
|
||||
backgroundMaterial->SetDstBlend(Nz::BlendFunc_InvSrcAlpha);
|
||||
backgroundMaterial->SetSrcBlend(Nz::BlendFunc_SrcAlpha);
|
||||
|
||||
// History bakckground
|
||||
m_historyBackgroundSprite = Nz::Sprite::New();
|
||||
m_historyBackgroundSprite->SetColor(Nz::Color(80, 80, 160, 128));
|
||||
m_historyBackgroundSprite->SetMaterial(backgroundMaterial);
|
||||
|
||||
m_historyBackground = world.CreateEntity();
|
||||
m_historyBackground->Enable(m_opened);
|
||||
m_historyBackground->AddComponent<Ndk::GraphicsComponent>().Attach(m_historyBackgroundSprite, -1);
|
||||
m_historyBackground->AddComponent<Ndk::NodeComponent>().SetParent(this);
|
||||
|
||||
// History
|
||||
m_historyDrawer.SetCharacterSize(m_characterSize);
|
||||
m_historyDrawer.SetColor(Nz::Color(200, 200, 200));
|
||||
m_historyDrawer.SetFont(m_defaultFont);
|
||||
m_history = Add<RichTextAreaWidget>();
|
||||
m_history->EnableBackground(true);
|
||||
m_history->EnableLineWrap(true);
|
||||
m_history->SetReadOnly(true);
|
||||
m_history->SetBackgroundColor(Nz::Color(80, 80, 160, 128));
|
||||
|
||||
m_historyTextSprite = Nz::TextSprite::New();
|
||||
|
||||
m_history = world.CreateEntity();
|
||||
m_history->Enable(m_opened);
|
||||
m_history->AddComponent<Ndk::GraphicsComponent>().Attach(m_historyTextSprite);
|
||||
|
||||
Ndk::NodeComponent& historyNode = m_history->AddComponent<Ndk::NodeComponent>();
|
||||
historyNode.SetParent(this);
|
||||
|
||||
// Input background
|
||||
m_inputBackgroundSprite = Nz::Sprite::New();
|
||||
m_inputBackgroundSprite->SetColor(Nz::Color(255, 255, 255, 200));
|
||||
m_inputBackgroundSprite->SetMaterial(backgroundMaterial);
|
||||
|
||||
m_inputBackground = world.CreateEntity();
|
||||
m_inputBackground->Enable(m_opened);
|
||||
m_inputBackground->AddComponent<Ndk::GraphicsComponent>().Attach(m_inputBackgroundSprite, -1);
|
||||
m_inputBackground->AddComponent<Ndk::NodeComponent>().SetParent(this);
|
||||
m_historyArea = Add<ScrollAreaWidget>(m_history);
|
||||
|
||||
// Input
|
||||
m_inputDrawer.SetColor(Nz::Color::Black);
|
||||
m_inputDrawer.SetCharacterSize(m_characterSize);
|
||||
m_inputDrawer.SetFont(m_defaultFont);
|
||||
m_inputDrawer.SetText(s_inputPrefix);
|
||||
m_input = Add<TextAreaWidget>();
|
||||
m_input->EnableBackground(true);
|
||||
m_input->SetText(s_inputPrefix);
|
||||
m_input->SetTextColor(Nz::Color::Black);
|
||||
|
||||
m_inputTextSprite = Nz::TextSprite::New();
|
||||
m_inputTextSprite->Update(m_inputDrawer);
|
||||
m_input->OnTextAreaKeyReturn.Connect(this, &Console::ExecuteInput);
|
||||
|
||||
m_input = world.CreateEntity();
|
||||
m_input->Enable(m_opened);
|
||||
m_input->AddComponent<Ndk::GraphicsComponent>().Attach(m_inputTextSprite);
|
||||
// Protect input prefix from erasure/selection
|
||||
m_input->SetCursorPosition(s_inputPrefixSize);
|
||||
|
||||
Ndk::NodeComponent& inputNode = m_input->AddComponent<Ndk::NodeComponent>();
|
||||
inputNode.SetParent(this);
|
||||
m_input->OnTextAreaCursorMove.Connect([](const AbstractTextAreaWidget* textArea, Nz::Vector2ui* newCursorPos)
|
||||
{
|
||||
newCursorPos->x = std::max(newCursorPos->x, static_cast<unsigned int>(s_inputPrefixSize));
|
||||
});
|
||||
|
||||
Layout();
|
||||
m_input->OnTextAreaSelection.Connect([](const AbstractTextAreaWidget* textArea, Nz::Vector2ui* start, Nz::Vector2ui* end)
|
||||
{
|
||||
start->x = std::max(start->x, static_cast<unsigned int>(s_inputPrefixSize));
|
||||
end->x = std::max(end->x, static_cast<unsigned int>(s_inputPrefixSize));
|
||||
});
|
||||
|
||||
m_input->OnTextAreaKeyBackspace.Connect([](const AbstractTextAreaWidget* textArea, bool* ignoreDefaultAction)
|
||||
{
|
||||
if (textArea->GetGlyphIndex() < s_inputPrefixSize)
|
||||
*ignoreDefaultAction = true;
|
||||
});
|
||||
|
||||
// Handle history
|
||||
m_input->OnTextAreaKeyUp.Connect([&] (const AbstractTextAreaWidget* textArea, bool* ignoreDefaultAction)
|
||||
{
|
||||
*ignoreDefaultAction = true;
|
||||
|
||||
if (m_commandHistory.empty())
|
||||
return;
|
||||
|
||||
if (m_historyPosition > 0)
|
||||
m_historyPosition--;
|
||||
|
||||
m_input->SetText(s_inputPrefix + m_commandHistory[m_historyPosition]);
|
||||
});
|
||||
|
||||
m_input->OnTextAreaKeyDown.Connect([&] (const AbstractTextAreaWidget* textArea, bool* ignoreDefaultAction)
|
||||
{
|
||||
*ignoreDefaultAction = true;
|
||||
|
||||
if (m_commandHistory.empty())
|
||||
return;
|
||||
|
||||
if (++m_historyPosition >= m_commandHistory.size())
|
||||
m_historyPosition = 0;
|
||||
|
||||
m_input->SetText(s_inputPrefix + m_commandHistory[m_historyPosition]);
|
||||
});
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -107,110 +110,41 @@ namespace Ndk
|
|||
* \param text New line of text
|
||||
* \param color Color for the text
|
||||
*/
|
||||
|
||||
void Console::AddLine(const Nz::String& text, const Nz::Color& color)
|
||||
{
|
||||
AddLineInternal(text, color);
|
||||
RefreshHistory();
|
||||
if (m_historyLines.size() >= m_maxHistoryLines)
|
||||
m_historyLines.erase(m_historyLines.begin());
|
||||
|
||||
m_historyLines.emplace_back(Line{ color, text });
|
||||
m_history->SetTextColor(color);
|
||||
m_history->AppendText(text + '\n');
|
||||
m_history->Resize(m_history->GetPreferredSize());
|
||||
m_historyArea->Resize(m_historyArea->GetSize());
|
||||
m_historyArea->ScrollToRatio(1.f);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Clears the console
|
||||
*
|
||||
* Clears the console history and input
|
||||
*/
|
||||
|
||||
void Console::Clear()
|
||||
{
|
||||
m_historyLines.clear();
|
||||
RefreshHistory();
|
||||
m_history->Clear();
|
||||
m_history->Resize(m_history->GetPreferredSize());
|
||||
m_historyArea->Resize(m_historyArea->GetSize());
|
||||
m_input->SetText(s_inputPrefix);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sends a character to the console
|
||||
* \brief Clears the console focus
|
||||
*
|
||||
* \param character Character that will be added to the console
|
||||
* Clear console input widget focus (if owned)
|
||||
*/
|
||||
|
||||
void Console::SendCharacter(char32_t character)
|
||||
void Console::ClearFocus()
|
||||
{
|
||||
switch (character)
|
||||
{
|
||||
case '\b':
|
||||
{
|
||||
Nz::String input = m_inputDrawer.GetText();
|
||||
if (input.GetLength() <= s_inputPrefixSize) // Prevent removal of the input prefix
|
||||
return; // Ignore if no user character is there
|
||||
|
||||
input.Resize(-1, Nz::String::HandleUtf8);
|
||||
m_inputDrawer.SetText(input);
|
||||
break;
|
||||
}
|
||||
|
||||
case '\r':
|
||||
case '\n':
|
||||
ExecuteInput();
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
if (Nz::Unicode::GetCategory(character) == Nz::Unicode::Category_Other_Control)
|
||||
return;
|
||||
|
||||
m_inputDrawer.AppendText(Nz::String::Unicode(character));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_inputTextSprite->Update(m_inputDrawer);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sends an event to the console
|
||||
*
|
||||
* \param event Event to be takin into consideration by the console
|
||||
*/
|
||||
void Console::SendEvent(const Nz::WindowEvent& event)
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case Nz::WindowEventType_TextEntered:
|
||||
SendCharacter(event.text.character);
|
||||
break;
|
||||
|
||||
case Nz::WindowEventType_KeyPressed:
|
||||
{
|
||||
switch (event.key.code)
|
||||
{
|
||||
case Nz::Keyboard::Down:
|
||||
case Nz::Keyboard::Up:
|
||||
{
|
||||
if (event.key.code == Nz::Keyboard::Up)
|
||||
m_historyPosition = std::min<std::size_t>(m_commandHistory.size(), m_historyPosition + 1);
|
||||
else
|
||||
{
|
||||
if (m_historyPosition > 1)
|
||||
m_historyPosition--;
|
||||
else if (m_historyPosition == 0)
|
||||
m_historyPosition = 1;
|
||||
}
|
||||
|
||||
if (!m_commandHistory.empty())
|
||||
{
|
||||
Nz::String text = m_commandHistory[m_commandHistory.size() - m_historyPosition];
|
||||
m_inputDrawer.SetText(s_inputPrefix + text);
|
||||
m_inputTextSprite->Update(m_inputDrawer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
m_input->ClearFocus();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -218,30 +152,23 @@ namespace Ndk
|
|||
*
|
||||
* \param size Size of the font
|
||||
*/
|
||||
|
||||
void Console::SetCharacterSize(unsigned int size)
|
||||
{
|
||||
m_characterSize = size;
|
||||
|
||||
m_historyDrawer.SetCharacterSize(m_characterSize);
|
||||
m_historyTextSprite->Update(m_historyDrawer);
|
||||
m_inputDrawer.SetCharacterSize(m_characterSize);
|
||||
m_inputTextSprite->Update(m_inputDrawer);
|
||||
m_history->SetCharacterSize(size);
|
||||
m_input->SetCharacterSize(size);
|
||||
|
||||
Layout();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Sets the console size
|
||||
* \brief Give the console input focus
|
||||
*
|
||||
* \param size (Width, Height) of the console
|
||||
*/
|
||||
|
||||
void Console::SetSize(const Nz::Vector2f& size)
|
||||
void Console::SetFocus()
|
||||
{
|
||||
m_size = size;
|
||||
m_historyBackgroundSprite->SetSize(m_size);
|
||||
Layout();
|
||||
m_input->SetFocus();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -251,121 +178,55 @@ namespace Ndk
|
|||
*
|
||||
* \remark Produces a NazaraAssert if font is invalid or null
|
||||
*/
|
||||
|
||||
void Console::SetTextFont(Nz::FontRef font)
|
||||
{
|
||||
NazaraAssert(font && font->IsValid(), "Invalid font");
|
||||
|
||||
m_defaultFont = std::move(font);
|
||||
m_historyDrawer.SetFont(m_defaultFont);
|
||||
m_inputDrawer.SetFont(m_defaultFont);
|
||||
m_history->SetTextFont(m_defaultFont);
|
||||
m_input->SetTextFont(m_defaultFont);
|
||||
|
||||
Layout();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Shows the console
|
||||
*
|
||||
* \param show Should the console be showed
|
||||
*/
|
||||
|
||||
void Console::Show(bool show)
|
||||
{
|
||||
if (m_opened != show)
|
||||
{
|
||||
m_historyBackground->Enable(show);
|
||||
m_history->Enable(show);
|
||||
m_input->Enable(show);
|
||||
m_inputBackground->Enable(show);
|
||||
|
||||
m_opened = show;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Adds a line to the history of the console
|
||||
*
|
||||
* \param text New line of text
|
||||
* \param color Color for the text
|
||||
*/
|
||||
|
||||
void Console::AddLineInternal(const Nz::String& text, const Nz::Color& color)
|
||||
{
|
||||
m_historyLines.emplace_back(Line{color, text});
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Performs this action when an input is added to the console
|
||||
*/
|
||||
|
||||
void Console::ExecuteInput()
|
||||
void Console::ExecuteInput(const AbstractTextAreaWidget* textArea, bool* ignoreDefaultAction)
|
||||
{
|
||||
Nz::String input = m_inputDrawer.GetText();
|
||||
NazaraAssert(textArea == m_input, "Unexpected signal from an other text area");
|
||||
|
||||
*ignoreDefaultAction = true;
|
||||
|
||||
Nz::String input = m_input->GetText();
|
||||
Nz::String inputCmd = input.SubString(s_inputPrefixSize);
|
||||
m_inputDrawer.SetText(s_inputPrefix);
|
||||
m_input->SetText(s_inputPrefix);
|
||||
|
||||
if (m_commandHistory.empty() || m_commandHistory.back() != inputCmd)
|
||||
m_commandHistory.push_back(inputCmd);
|
||||
|
||||
m_historyPosition = 0;
|
||||
m_historyPosition = m_commandHistory.size();
|
||||
|
||||
AddLineInternal(input); //< With the input prefix
|
||||
AddLine(input); //< With the input prefix
|
||||
|
||||
if (!m_state.Execute(inputCmd))
|
||||
AddLineInternal(m_state.GetLastError(), Nz::Color::Red);
|
||||
|
||||
RefreshHistory();
|
||||
OnCommand(this, inputCmd);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Places the console according to its layout
|
||||
*/
|
||||
|
||||
void Console::Layout()
|
||||
{
|
||||
Nz::Vector2f origin = Nz::Vector2f(GetPosition());
|
||||
const Nz::Vector2f& size = GetSize();
|
||||
|
||||
unsigned int lineHeight = m_defaultFont->GetSizeInfo(m_characterSize).lineHeight;
|
||||
float historyHeight = size.y - lineHeight;
|
||||
|
||||
Ndk::NodeComponent& inputNode = m_input->GetComponent<Ndk::NodeComponent>();
|
||||
inputNode.SetPosition(0.f, m_size.y - lineHeight - 5.f);
|
||||
m_historyArea->SetPosition(origin.x, origin.y);
|
||||
m_historyArea->Resize({ size.x, historyHeight - 4.f });
|
||||
|
||||
float historyHeight = m_size.y - lineHeight - 5.f - 2.f;
|
||||
m_historyBackgroundSprite->SetSize(m_size.x, historyHeight);
|
||||
|
||||
m_maxHistoryLines = static_cast<unsigned int>(std::ceil(historyHeight / lineHeight));
|
||||
|
||||
Ndk::NodeComponent& historyNode = m_history->GetComponent<Ndk::NodeComponent>();
|
||||
historyNode.SetPosition(0.f, historyHeight - m_maxHistoryLines * lineHeight);
|
||||
|
||||
Ndk::NodeComponent& inputBackgroundNode = m_inputBackground->GetComponent<Ndk::NodeComponent>();
|
||||
inputBackgroundNode.SetPosition(0.f, historyHeight + 2.f);
|
||||
|
||||
m_inputBackgroundSprite->SetSize(m_size.x, m_size.y - historyHeight);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Refreshes the history of the console
|
||||
*/
|
||||
|
||||
void Console::RefreshHistory()
|
||||
{
|
||||
m_historyDrawer.Clear();
|
||||
auto it = m_historyLines.end();
|
||||
if (m_historyLines.size() > m_maxHistoryLines)
|
||||
it -= m_maxHistoryLines;
|
||||
else
|
||||
it = m_historyLines.begin();
|
||||
|
||||
for (unsigned int i = 0; i < m_maxHistoryLines; ++i)
|
||||
{
|
||||
if (m_maxHistoryLines - i <= m_historyLines.size() && it != m_historyLines.end())
|
||||
{
|
||||
m_historyDrawer.AppendText(it->text);
|
||||
++it;
|
||||
}
|
||||
|
||||
m_historyDrawer.AppendText(Nz::String('\n'));
|
||||
}
|
||||
|
||||
m_historyTextSprite->Update(m_historyDrawer);
|
||||
m_input->Resize({size.x, size.y - historyHeight});
|
||||
m_input->SetPosition(origin.x, origin.y + historyHeight);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,6 +97,36 @@ namespace Ndk
|
|||
return m_world->CloneEntity(m_id);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Detaches a component from the entity
|
||||
* \return An owning pointer to the component
|
||||
*
|
||||
* Instantly detaches a component from the entity and returns it, allowing to attach it to another entity
|
||||
*
|
||||
* \remark Unlike RemoveComponent, this function instantly removes the component
|
||||
*/
|
||||
std::unique_ptr<BaseComponent> Entity::DropComponent(ComponentIndex index)
|
||||
{
|
||||
if (!HasComponent(index))
|
||||
return nullptr;
|
||||
|
||||
// We get the component and we alert existing components of the deleted one
|
||||
std::unique_ptr<BaseComponent> component = std::move(m_components[index]);
|
||||
m_components[index].reset();
|
||||
|
||||
for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
|
||||
{
|
||||
if (i != index)
|
||||
m_components[i]->OnComponentDetached(*component);
|
||||
}
|
||||
m_componentBits.Reset(index);
|
||||
m_removedComponentBits.UnboundedReset(index);
|
||||
|
||||
component->SetEntity(nullptr);
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Enables the entity
|
||||
*
|
||||
|
|
@ -111,11 +141,15 @@ namespace Ndk
|
|||
{
|
||||
for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
|
||||
m_components[i]->OnEntityEnabled();
|
||||
|
||||
OnEntityEnabled(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
|
||||
m_components[i]->OnEntityDisabled();
|
||||
|
||||
OnEntityDisabled(this);
|
||||
}
|
||||
|
||||
Invalidate();
|
||||
|
|
@ -133,13 +167,22 @@ namespace Ndk
|
|||
/*!
|
||||
* \brief Invalidates the entity
|
||||
*/
|
||||
|
||||
void Entity::Invalidate()
|
||||
{
|
||||
// We alert everyone that we have been updated
|
||||
m_world->Invalidate(m_id);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Checks if the entity has been killed this update
|
||||
* \return True if the entity is currently dying and will be dead at next world refresh
|
||||
*/
|
||||
bool Entity::IsDying() const
|
||||
{
|
||||
return m_world->IsEntityDying(m_id);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Creates the entity
|
||||
*/
|
||||
|
|
@ -195,32 +238,4 @@ namespace Ndk
|
|||
|
||||
m_valid = false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Destroys a component by index
|
||||
*
|
||||
* \param index Index of the component
|
||||
*
|
||||
* \remark If component is not available, no action is performed
|
||||
*/
|
||||
|
||||
void Entity::DestroyComponent(ComponentIndex index)
|
||||
{
|
||||
if (HasComponent(index))
|
||||
{
|
||||
// We get the component and we alert existing components of the deleted one
|
||||
BaseComponent& component = *m_components[index].get();
|
||||
for (std::size_t i = m_componentBits.FindFirst(); i != m_componentBits.npos; i = m_componentBits.FindNext(i))
|
||||
{
|
||||
if (i != index)
|
||||
m_components[i]->OnComponentDetached(component);
|
||||
}
|
||||
|
||||
component.SetEntity(nullptr);
|
||||
|
||||
m_components[index].reset();
|
||||
m_componentBits.Reset(index);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ namespace Ndk
|
|||
|
||||
music.BindMethod("IsLooping", &Nz::Music::IsLooping);
|
||||
|
||||
music.BindMethod("OpenFromFile", &Nz::Music::OpenFromFile, Nz::MusicParams());
|
||||
music.BindMethod("OpenFromFile", &Nz::Music::OpenFromFile, Nz::SoundStreamParams());
|
||||
|
||||
music.BindMethod("Pause", &Nz::Music::Pause);
|
||||
music.BindMethod("Play", &Nz::Music::Play);
|
||||
|
|
@ -138,7 +138,7 @@ namespace Ndk
|
|||
|
||||
soundBuffer.BindMethod("IsValid", &Nz::SoundBuffer::IsValid);
|
||||
|
||||
soundBuffer.BindMethod("LoadFromFile", &Nz::SoundBuffer::LoadFromFile, Nz::SoundBufferParams());
|
||||
soundBuffer.BindStaticMethod("LoadFromFile", &Nz::SoundBuffer::LoadFromFile, Nz::SoundBufferParams());
|
||||
|
||||
soundBuffer.BindStaticMethod("IsFormatSupported", &Nz::SoundBuffer::IsFormatSupported);
|
||||
|
||||
|
|
|
|||
|
|
@ -181,8 +181,6 @@ namespace Ndk
|
|||
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);
|
||||
|
|
@ -205,6 +203,7 @@ namespace Ndk
|
|||
material.BindMethod("SetSrcBlend", &Nz::Material::SetSrcBlend);
|
||||
|
||||
material.BindStaticMethod("GetDefault", &Nz::Material::GetDefault);
|
||||
material.BindStaticMethod("LoadFromFile", &Nz::Material::LoadFromFile, Nz::MaterialParams());
|
||||
|
||||
material.BindMethod("SetAlphaMap", [] (Nz::LuaState& lua, Nz::MaterialRef& instance, std::size_t /*argumentCount*/) -> int
|
||||
{
|
||||
|
|
@ -308,8 +307,6 @@ namespace Ndk
|
|||
//modelClass.SetMethod("GetMesh", &Nz::Model::GetMesh);
|
||||
|
||||
model.BindMethod("IsAnimated", &Nz::Model::IsAnimated);
|
||||
model.BindMethod("LoadFromFile", &Nz::Model::LoadFromFile, Nz::ModelParameters());
|
||||
|
||||
|
||||
model.BindMethod("SetMaterial", [] (Nz::LuaState& lua, Nz::Model* instance, std::size_t argumentCount) -> int
|
||||
{
|
||||
|
|
@ -371,6 +368,8 @@ namespace Ndk
|
|||
|
||||
//modelClass.SetMethod("SetMesh", &Nz::Model::SetMesh);
|
||||
//modelClass.SetMethod("SetSequence", &Nz::Model::SetSequence);
|
||||
|
||||
model.BindStaticMethod("LoadFromFile", &Nz::Model::LoadFromFile, Nz::ModelParameters());
|
||||
}
|
||||
|
||||
/*********************************** Nz::Sprite ***********************************/
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ namespace Ndk
|
|||
{
|
||||
case 1:
|
||||
if (lua.IsOfType(argIndex, "Matrix4"))
|
||||
instance.Set(*static_cast<Nz::Matrix4d*>(lua.ToUserdata(argIndex)));
|
||||
instance = *static_cast<Nz::Matrix4d*>(lua.ToUserdata(argIndex));
|
||||
break;
|
||||
|
||||
case 16:
|
||||
|
|
@ -291,7 +291,7 @@ namespace Ndk
|
|||
for (std::size_t i = 0; i < 16; ++i)
|
||||
values[i] = lua.CheckNumber(argIndex++);
|
||||
|
||||
instance.Set(values);
|
||||
instance = Nz::Matrix4d(values);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,21 +44,6 @@ namespace Ndk
|
|||
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());
|
||||
|
|
@ -71,6 +56,21 @@ namespace Ndk
|
|||
texture.BindStaticMethod("IsFormatSupported", &Nz::Texture::IsFormatSupported);
|
||||
texture.BindStaticMethod("IsMipmappingSupported", &Nz::Texture::IsMipmappingSupported);
|
||||
texture.BindStaticMethod("IsTypeSupported", &Nz::Texture::IsTypeSupported);
|
||||
|
||||
texture.BindStaticMethod("LoadFromFile", &Nz::Texture::LoadFromFile, true, Nz::ImageParams());
|
||||
//TextureRef LoadFromImage(const Image& image, bool generateMipmaps = true);
|
||||
//TextureRef LoadFromMemory(const void* data, std::size_t size, const ImageParams& params = ImageParams(), bool generateMipmaps = true);
|
||||
//TextureRef LoadFromStream(Stream& stream, const ImageParams& params = ImageParams(), bool generateMipmaps = true);
|
||||
|
||||
texture.BindStaticMethod("LoadArrayFromFile", &Nz::Texture::LoadArrayFromFile, Nz::Vector2ui(2, 2), true, Nz::ImageParams());
|
||||
//TextureRef LoadArrayFromImage(const Image& image, bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2));
|
||||
//TextureRef LoadArrayFromMemory(const void* data, std::size_t size, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2));
|
||||
//TextureRef LoadArrayFromStream(Stream& stream, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2));
|
||||
|
||||
//TextureRef LoadCubemapFromFile(const String& filePath, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const CubemapParams& cubemapParams = CubemapParams());
|
||||
//TextureRef LoadCubemapFromImage(const Image& image, bool generateMipmaps = true, const CubemapParams& params = CubemapParams());
|
||||
//TextureRef LoadCubemapFromMemory(const void* data, std::size_t size, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const CubemapParams& cubemapParams = CubemapParams());
|
||||
//TextureRef LoadCubemapFromStream(Stream& stream, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const CubemapParams& cubemapParams = CubemapParams());
|
||||
}
|
||||
|
||||
/*********************************** Nz::TextureLibrary ***********************************/
|
||||
|
|
|
|||
|
|
@ -62,24 +62,14 @@ namespace Ndk
|
|||
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("GetHistory", &Console::GetHistory);
|
||||
//console.BindMethod("GetInput", &Console::GetInput);
|
||||
console.BindMethod("GetTextFont", &Console::GetTextFont);
|
||||
|
||||
console.BindMethod("IsValidHandle", &ConsoleHandle::IsValid);
|
||||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -123,12 +123,13 @@ namespace Ndk
|
|||
lua.Push(instance->GetCachedGlyphCount());
|
||||
return 1;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
{
|
||||
unsigned int characterSize = lua.Check<unsigned int>(&argIndex);
|
||||
Nz::UInt32 style = lua.Check<Nz::UInt32>(&argIndex);
|
||||
Nz::TextStyleFlags style = lua.Check<Nz::TextStyleFlags>(&argIndex);
|
||||
float outlineThickness = lua.Check<float>(&argIndex);
|
||||
|
||||
lua.Push(instance->GetCachedGlyphCount(characterSize, style));
|
||||
lua.Push(instance->GetCachedGlyphCount(characterSize, style, outlineThickness));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -146,9 +147,7 @@ namespace Ndk
|
|||
|
||||
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("Precache", (bool(Nz::Font::*)(unsigned int, Nz::TextStyleFlags, float, const Nz::String&) const) &Nz::Font::Precache);
|
||||
|
||||
font.BindMethod("SetGlyphBorder", &Nz::Font::SetGlyphBorder);
|
||||
font.BindMethod("SetMinimumStepSize", &Nz::Font::SetMinimumStepSize);
|
||||
|
|
@ -157,6 +156,8 @@ namespace Ndk
|
|||
font.BindStaticMethod("GetDefaultGlyphBorder", &Nz::Font::GetDefaultGlyphBorder);
|
||||
font.BindStaticMethod("GetDefaultMinimumStepSize", &Nz::Font::GetDefaultMinimumStepSize);
|
||||
|
||||
font.BindStaticMethod("OpenFromFile", &Nz::Font::OpenFromFile, Nz::FontParams());
|
||||
|
||||
font.BindStaticMethod("SetDefaultGlyphBorder", &Nz::Font::SetDefaultGlyphBorder);
|
||||
font.BindStaticMethod("SetDefaultMinimumStepSize", &Nz::Font::SetDefaultMinimumStepSize);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,11 +17,13 @@
|
|||
#include <NDK/BaseSystem.hpp>
|
||||
#include <NDK/Components/CollisionComponent2D.hpp>
|
||||
#include <NDK/Components/CollisionComponent3D.hpp>
|
||||
#include <NDK/Components/LifetimeComponent.hpp>
|
||||
#include <NDK/Components/NodeComponent.hpp>
|
||||
#include <NDK/Components/PhysicsComponent2D.hpp>
|
||||
#include <NDK/Components/PhysicsComponent3D.hpp>
|
||||
#include <NDK/Components/VelocityComponent.hpp>
|
||||
#include <NDK/Components/ConstraintComponent2D.hpp>
|
||||
#include <NDK/Systems/LifetimeSystem.hpp>
|
||||
#include <NDK/Systems/PhysicsSystem2D.hpp>
|
||||
#include <NDK/Systems/PhysicsSystem3D.hpp>
|
||||
#include <NDK/Systems/VelocitySystem.hpp>
|
||||
|
|
@ -88,6 +90,7 @@ namespace Ndk
|
|||
// Shared components
|
||||
InitializeComponent<CollisionComponent2D>("NdkColl2");
|
||||
InitializeComponent<CollisionComponent3D>("NdkColl3");
|
||||
InitializeComponent<LifetimeComponent>("NdkLiftm");
|
||||
InitializeComponent<NodeComponent>("NdkNode");
|
||||
InitializeComponent<PhysicsComponent2D>("NdkPhys2");
|
||||
InitializeComponent<PhysicsComponent3D>("NdkPhys3");
|
||||
|
|
@ -110,6 +113,7 @@ namespace Ndk
|
|||
BaseSystem::Initialize();
|
||||
|
||||
// Shared systems
|
||||
InitializeSystem<LifetimeSystem>();
|
||||
InitializeSystem<PhysicsSystem2D>();
|
||||
InitializeSystem<PhysicsSystem3D>();
|
||||
InitializeSystem<VelocitySystem>();
|
||||
|
|
|
|||
|
|
@ -8,10 +8,12 @@
|
|||
#include <Nazara/Utility/IndexIterator.hpp>
|
||||
#include <Nazara/Utility/Mesh.hpp>
|
||||
#include <Nazara/Utility/StaticMesh.hpp>
|
||||
#include <NDK/Components/CollisionComponent2D.hpp>
|
||||
#include <NDK/Components/CollisionComponent3D.hpp>
|
||||
#include <NDK/Components/DebugComponent.hpp>
|
||||
#include <NDK/Components/GraphicsComponent.hpp>
|
||||
#include <NDK/Components/NodeComponent.hpp>
|
||||
#include <NDK/Components/PhysicsComponent2D.hpp>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
|
|
@ -20,9 +22,8 @@ namespace Ndk
|
|||
class DebugRenderable : public Nz::InstancedRenderable
|
||||
{
|
||||
public:
|
||||
DebugRenderable(Ndk::Entity* owner, Nz::MaterialRef mat, Nz::IndexBufferRef indexBuffer, Nz::VertexBufferRef vertexBuffer) :
|
||||
DebugRenderable(Ndk::Entity* owner, Nz::IndexBufferRef indexBuffer, Nz::VertexBufferRef vertexBuffer) :
|
||||
m_entityOwner(owner),
|
||||
m_material(std::move(mat)),
|
||||
m_indexBuffer(std::move(indexBuffer)),
|
||||
m_vertexBuffer(std::move(vertexBuffer))
|
||||
{
|
||||
|
|
@ -33,19 +34,20 @@ namespace Ndk
|
|||
m_meshData.vertexBuffer = m_vertexBuffer;
|
||||
}
|
||||
|
||||
void UpdateBoundingVolume(InstanceData* instanceData) const override
|
||||
void UpdateBoundingVolume(InstanceData* /*instanceData*/) const override
|
||||
{
|
||||
}
|
||||
|
||||
void MakeBoundingVolume() const override
|
||||
{
|
||||
m_boundingVolume.MakeNull();
|
||||
// We generate an infinite bounding volume so that we're always considered for rendering when culling does occurs
|
||||
// (bounding volume culling happens only if GraphicsComponent AABB partially fail)
|
||||
m_boundingVolume.MakeInfinite();
|
||||
}
|
||||
|
||||
protected:
|
||||
Ndk::EntityHandle m_entityOwner;
|
||||
Nz::IndexBufferRef m_indexBuffer;
|
||||
Nz::MaterialRef m_material;
|
||||
Nz::MeshData m_meshData;
|
||||
Nz::VertexBufferRef m_vertexBuffer;
|
||||
};
|
||||
|
|
@ -53,7 +55,12 @@ namespace Ndk
|
|||
class AABBDebugRenderable : public DebugRenderable
|
||||
{
|
||||
public:
|
||||
using DebugRenderable::DebugRenderable;
|
||||
AABBDebugRenderable(Ndk::Entity* owner, Nz::MaterialRef globalMaterial, Nz::MaterialRef localMaterial, Nz::IndexBufferRef indexBuffer, Nz::VertexBufferRef vertexBuffer) :
|
||||
DebugRenderable(owner, std::move(indexBuffer), std::move(vertexBuffer)),
|
||||
m_globalMaterial(std::move(globalMaterial)),
|
||||
m_localMaterial(std::move(localMaterial))
|
||||
{
|
||||
}
|
||||
|
||||
void AddToRenderQueue(Nz::AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Nz::Recti& scissorRect) const override
|
||||
{
|
||||
|
|
@ -62,25 +69,43 @@ namespace Ndk
|
|||
const DebugComponent& entityDebug = m_entityOwner->GetComponent<DebugComponent>();
|
||||
const GraphicsComponent& entityGfx = m_entityOwner->GetComponent<GraphicsComponent>();
|
||||
|
||||
Nz::Boxf aabb = entityGfx.GetBoundingVolume().aabb;
|
||||
auto DrawBox = [&](const Nz::Boxf& box, const Nz::MaterialRef& mat)
|
||||
{
|
||||
Nz::Matrix4f transformMatrix = Nz::Matrix4f::Identity();
|
||||
transformMatrix.SetScale(box.GetLengths());
|
||||
transformMatrix.SetTranslation(box.GetCenter());
|
||||
|
||||
Nz::Matrix4f transformMatrix = Nz::Matrix4f::Identity();
|
||||
transformMatrix.SetScale(aabb.GetLengths());
|
||||
transformMatrix.SetTranslation(aabb.GetCenter());
|
||||
renderQueue->AddMesh(0, mat, m_meshData, Nz::Boxf::Zero(), transformMatrix, scissorRect);
|
||||
};
|
||||
|
||||
renderQueue->AddMesh(0, m_material, m_meshData, Nz::Boxf::Zero(), transformMatrix, scissorRect);
|
||||
DrawBox(entityGfx.GetAABB(), m_globalMaterial);
|
||||
|
||||
for (std::size_t i = 0; i < entityGfx.GetAttachedRenderableCount(); ++i)
|
||||
{
|
||||
const Nz::BoundingVolumef& boundingVolume = entityGfx.GetBoundingVolume(i);
|
||||
if (boundingVolume.IsFinite())
|
||||
DrawBox(boundingVolume.aabb, m_localMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<InstancedRenderable> Clone() const override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
Nz::MaterialRef m_globalMaterial;
|
||||
Nz::MaterialRef m_localMaterial;
|
||||
};
|
||||
|
||||
class OBBDebugRenderable : public DebugRenderable
|
||||
{
|
||||
public:
|
||||
using DebugRenderable::DebugRenderable;
|
||||
OBBDebugRenderable(Ndk::Entity* owner, Nz::MaterialRef material, Nz::IndexBufferRef indexBuffer, Nz::VertexBufferRef vertexBuffer) :
|
||||
DebugRenderable(owner, std::move(indexBuffer), std::move(vertexBuffer)),
|
||||
m_material(std::move(material))
|
||||
{
|
||||
}
|
||||
|
||||
void AddToRenderQueue(Nz::AbstractRenderQueue* renderQueue, const InstanceData& instanceData, const Nz::Recti& scissorRect) const override
|
||||
{
|
||||
|
|
@ -89,21 +114,31 @@ namespace Ndk
|
|||
const DebugComponent& entityDebug = m_entityOwner->GetComponent<DebugComponent>();
|
||||
const GraphicsComponent& entityGfx = m_entityOwner->GetComponent<GraphicsComponent>();
|
||||
|
||||
Nz::Boxf obb = entityGfx.GetBoundingVolume().obb.localBox;
|
||||
auto DrawBox = [&](const Nz::Boxf& box, const Nz::Matrix4f& transformMatrix)
|
||||
{
|
||||
Nz::Matrix4f boxMatrix = Nz::Matrix4f::Identity();
|
||||
boxMatrix.SetScale(box.GetLengths());
|
||||
boxMatrix.SetTranslation(box.GetCenter());
|
||||
boxMatrix.ConcatenateAffine(transformMatrix);
|
||||
|
||||
Nz::Matrix4f transformMatrix = instanceData.transformMatrix;
|
||||
Nz::Vector3f obbCenter = transformMatrix.Transform(obb.GetCenter(), 0.f); //< Apply rotation/scale to obb center, to display it at a correct position
|
||||
renderQueue->AddMesh(0, m_material, m_meshData, Nz::Boxf::Zero(), boxMatrix, scissorRect);
|
||||
};
|
||||
|
||||
transformMatrix.ApplyScale(obb.GetLengths());
|
||||
transformMatrix.ApplyTranslation(obbCenter);
|
||||
|
||||
renderQueue->AddMesh(0, m_material, m_meshData, Nz::Boxf::Zero(), transformMatrix, scissorRect);
|
||||
for (std::size_t i = 0; i < entityGfx.GetAttachedRenderableCount(); ++i)
|
||||
{
|
||||
const Nz::BoundingVolumef& boundingVolume = entityGfx.GetBoundingVolume(i);
|
||||
if (boundingVolume.IsFinite())
|
||||
DrawBox(boundingVolume.obb.localBox, entityGfx.GetTransformMatrix(i));
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<InstancedRenderable> Clone() const override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
Nz::MaterialRef m_material;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -118,12 +153,174 @@ namespace Ndk
|
|||
/*!
|
||||
* \brief Constructs an DebugSystem object by default
|
||||
*/
|
||||
DebugSystem::DebugSystem()
|
||||
DebugSystem::DebugSystem() :
|
||||
m_isDepthBufferEnabled(true)
|
||||
{
|
||||
Requires<DebugComponent, GraphicsComponent>();
|
||||
Requires<DebugComponent, GraphicsComponent, NodeComponent>();
|
||||
SetUpdateOrder(1000); //< Update last
|
||||
}
|
||||
|
||||
void DebugSystem::EnableDepthBuffer(bool enable)
|
||||
{
|
||||
m_isDepthBufferEnabled = enable;
|
||||
|
||||
if (m_collisionMaterial)
|
||||
m_collisionMaterial->EnableDepthBuffer(enable);
|
||||
|
||||
if (m_globalAabbMaterial)
|
||||
m_globalAabbMaterial->EnableDepthBuffer(enable);
|
||||
|
||||
if (m_localAabbMaterial)
|
||||
m_localAabbMaterial->EnableDepthBuffer(enable);
|
||||
|
||||
if (m_obbMaterial)
|
||||
m_obbMaterial->EnableDepthBuffer(enable);
|
||||
}
|
||||
|
||||
Nz::InstancedRenderableRef DebugSystem::GenerateBox(Nz::Boxf box)
|
||||
{
|
||||
Nz::MeshRef mesh = Nz::Mesh::New();
|
||||
mesh->CreateStatic();
|
||||
|
||||
mesh->BuildSubMesh(Nz::Primitive::Box(box.GetLengths()));
|
||||
mesh->SetMaterialCount(1);
|
||||
|
||||
Nz::ModelRef model = Nz::Model::New();
|
||||
model->SetMesh(mesh);
|
||||
model->SetMaterial(0, GetOBBMaterial());
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
Nz::InstancedRenderableRef DebugSystem::GenerateCollision2DMesh(Entity* entity, Nz::Vector3f* offset)
|
||||
{
|
||||
if (entity->HasComponent<CollisionComponent2D>())
|
||||
{
|
||||
CollisionComponent2D& entityCollision = entity->GetComponent<CollisionComponent2D>();
|
||||
const Nz::Collider2DRef& geom = entityCollision.GetGeom();
|
||||
|
||||
std::vector<Nz::Vector3f> vertices;
|
||||
std::vector<std::size_t> indices;
|
||||
|
||||
geom->ForEachPolygon([&](const Nz::Vector2f* polygonVertices, std::size_t vertexCount)
|
||||
{
|
||||
std::size_t firstIndex = vertices.size();
|
||||
|
||||
// Don't reserve and let the vector handle its own capacity
|
||||
for (std::size_t i = 0; i < vertexCount; ++i)
|
||||
vertices.emplace_back(*polygonVertices++);
|
||||
|
||||
for (std::size_t i = 0; i < vertexCount - 1; ++i)
|
||||
{
|
||||
indices.push_back(firstIndex + i);
|
||||
indices.push_back(firstIndex + i + 1);
|
||||
}
|
||||
|
||||
indices.push_back(firstIndex + vertexCount - 1);
|
||||
indices.push_back(firstIndex);
|
||||
});
|
||||
|
||||
Nz::IndexBufferRef indexBuffer = Nz::IndexBuffer::New(vertices.size() > 0xFFFF, Nz::UInt32(indices.size()), Nz::DataStorage_Hardware, 0);
|
||||
Nz::IndexMapper indexMapper(indexBuffer, Nz::BufferAccess_WriteOnly);
|
||||
|
||||
Nz::IndexIterator indexPtr = indexMapper.begin();
|
||||
for (std::size_t index : indices)
|
||||
*indexPtr++ = static_cast<Nz::UInt32>(index);
|
||||
|
||||
indexMapper.Unmap();
|
||||
|
||||
Nz::VertexBufferRef vertexBuffer = Nz::VertexBuffer::New(Nz::VertexDeclaration::Get(Nz::VertexLayout_XYZ), Nz::UInt32(vertices.size()), Nz::DataStorage_Hardware, 0);
|
||||
vertexBuffer->Fill(vertices.data(), 0, Nz::UInt32(vertices.size()));
|
||||
|
||||
Nz::MeshRef mesh = Nz::Mesh::New();
|
||||
mesh->CreateStatic();
|
||||
|
||||
Nz::StaticMeshRef subMesh = Nz::StaticMesh::New(vertexBuffer, indexBuffer);
|
||||
subMesh->SetPrimitiveMode(Nz::PrimitiveMode_LineList);
|
||||
subMesh->SetMaterialIndex(0);
|
||||
subMesh->GenerateAABB();
|
||||
|
||||
mesh->SetMaterialCount(1);
|
||||
mesh->AddSubMesh(subMesh);
|
||||
|
||||
Nz::ModelRef model = Nz::Model::New();
|
||||
model->SetMesh(mesh);
|
||||
model->SetMaterial(0, GetCollisionMaterial());
|
||||
|
||||
// Find center of mass
|
||||
if (entity->HasComponent<PhysicsComponent2D>())
|
||||
{
|
||||
const PhysicsComponent2D& entityPhys = entity->GetComponent<PhysicsComponent2D>();
|
||||
*offset = entityPhys.GetMassCenter(Nz::CoordSys_Local) + entityCollision.GetGeomOffset();
|
||||
}
|
||||
else
|
||||
*offset = entityCollision.GetGeomOffset();
|
||||
|
||||
return model;
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Nz::InstancedRenderableRef DebugSystem::GenerateCollision3DMesh(Entity* entity)
|
||||
{
|
||||
if (entity->HasComponent<CollisionComponent3D>())
|
||||
{
|
||||
CollisionComponent3D& entityCollision = entity->GetComponent<CollisionComponent3D>();
|
||||
const Nz::Collider3DRef& geom = entityCollision.GetGeom();
|
||||
|
||||
std::vector<Nz::Vector3f> vertices;
|
||||
std::vector<std::size_t> indices;
|
||||
|
||||
geom->ForEachPolygon([&](const Nz::Vector3f* polygonVertices, std::size_t vertexCount)
|
||||
{
|
||||
std::size_t firstIndex = vertices.size();
|
||||
vertices.resize(firstIndex + vertexCount);
|
||||
std::copy(polygonVertices, polygonVertices + vertexCount, &vertices[firstIndex]);
|
||||
|
||||
for (std::size_t i = 0; i < vertexCount - 1; ++i)
|
||||
{
|
||||
indices.push_back(firstIndex + i);
|
||||
indices.push_back(firstIndex + i + 1);
|
||||
}
|
||||
|
||||
indices.push_back(firstIndex + vertexCount - 1);
|
||||
indices.push_back(firstIndex);
|
||||
});
|
||||
|
||||
Nz::IndexBufferRef indexBuffer = Nz::IndexBuffer::New(vertices.size() > 0xFFFF, Nz::UInt32(indices.size()), Nz::DataStorage_Hardware, 0);
|
||||
Nz::IndexMapper indexMapper(indexBuffer, Nz::BufferAccess_WriteOnly);
|
||||
|
||||
Nz::IndexIterator indexPtr = indexMapper.begin();
|
||||
for (std::size_t index : indices)
|
||||
*indexPtr++ = static_cast<Nz::UInt32>(index);
|
||||
|
||||
indexMapper.Unmap();
|
||||
|
||||
Nz::VertexBufferRef vertexBuffer = Nz::VertexBuffer::New(Nz::VertexDeclaration::Get(Nz::VertexLayout_XYZ), Nz::UInt32(vertices.size()), Nz::DataStorage_Hardware, 0);
|
||||
vertexBuffer->Fill(vertices.data(), 0, Nz::UInt32(vertices.size()));
|
||||
|
||||
Nz::MeshRef mesh = Nz::Mesh::New();
|
||||
mesh->CreateStatic();
|
||||
|
||||
Nz::StaticMeshRef subMesh = Nz::StaticMesh::New(vertexBuffer, indexBuffer);
|
||||
subMesh->SetPrimitiveMode(Nz::PrimitiveMode_LineList);
|
||||
subMesh->SetMaterialIndex(0);
|
||||
subMesh->GenerateAABB();
|
||||
|
||||
mesh->SetMaterialCount(1);
|
||||
mesh->AddSubMesh(subMesh);
|
||||
|
||||
Nz::ModelRef model = Nz::Model::New();
|
||||
model->SetMesh(mesh);
|
||||
model->SetMaterial(0, GetCollisionMaterial());
|
||||
|
||||
return model;
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::pair<Nz::IndexBufferRef, Nz::VertexBufferRef> DebugSystem::GetBoxMesh()
|
||||
{
|
||||
if (!m_boxMeshIndexBuffer)
|
||||
|
|
@ -175,12 +372,73 @@ namespace Ndk
|
|||
return { m_boxMeshIndexBuffer, m_boxMeshVertexBuffer };
|
||||
}
|
||||
|
||||
Nz::MaterialRef DebugSystem::GetGlobalAABBMaterial()
|
||||
{
|
||||
if (!m_globalAabbMaterial)
|
||||
{
|
||||
m_globalAabbMaterial = Nz::Material::New();
|
||||
m_globalAabbMaterial->EnableFaceCulling(false);
|
||||
m_globalAabbMaterial->EnableDepthBuffer(true);
|
||||
m_globalAabbMaterial->SetDiffuseColor(Nz::Color::Orange);
|
||||
m_globalAabbMaterial->SetFaceFilling(Nz::FaceFilling_Line);
|
||||
//m_globalAabbMaterial->SetLineWidth(2.f);
|
||||
}
|
||||
|
||||
return m_globalAabbMaterial;
|
||||
}
|
||||
|
||||
Nz::MaterialRef DebugSystem::GetLocalAABBMaterial()
|
||||
{
|
||||
if (!m_localAabbMaterial)
|
||||
{
|
||||
m_localAabbMaterial = Nz::Material::New();
|
||||
m_localAabbMaterial->EnableFaceCulling(false);
|
||||
m_localAabbMaterial->EnableDepthBuffer(true);
|
||||
m_localAabbMaterial->SetDiffuseColor(Nz::Color::Red);
|
||||
m_localAabbMaterial->SetFaceFilling(Nz::FaceFilling_Line);
|
||||
//m_localAabbMaterial->SetLineWidth(2.f);
|
||||
}
|
||||
|
||||
return m_localAabbMaterial;
|
||||
}
|
||||
|
||||
Nz::MaterialRef DebugSystem::GetCollisionMaterial()
|
||||
{
|
||||
if (!m_collisionMaterial)
|
||||
{
|
||||
m_collisionMaterial = Nz::Material::New();
|
||||
m_collisionMaterial->EnableFaceCulling(false);
|
||||
m_collisionMaterial->EnableDepthBuffer(true);
|
||||
m_collisionMaterial->SetDiffuseColor(Nz::Color::Blue);
|
||||
m_collisionMaterial->SetFaceFilling(Nz::FaceFilling_Line);
|
||||
//m_collisionMaterial->SetLineWidth(2.f);
|
||||
}
|
||||
|
||||
return m_collisionMaterial;
|
||||
}
|
||||
|
||||
Nz::MaterialRef DebugSystem::GetOBBMaterial()
|
||||
{
|
||||
if (!m_obbMaterial)
|
||||
{
|
||||
m_obbMaterial = Nz::Material::New();
|
||||
m_obbMaterial->EnableFaceCulling(false);
|
||||
m_obbMaterial->EnableDepthBuffer(true);
|
||||
m_obbMaterial->SetDiffuseColor(Nz::Color::Green);
|
||||
m_obbMaterial->SetFaceFilling(Nz::FaceFilling_Line);
|
||||
//m_obbMaterial->SetLineWidth(2.f);
|
||||
}
|
||||
|
||||
return m_obbMaterial;
|
||||
}
|
||||
|
||||
void DebugSystem::OnEntityValidation(Entity* entity, bool /*justAdded*/)
|
||||
{
|
||||
static constexpr int DebugDrawOrder = 1'000;
|
||||
|
||||
DebugComponent& entityDebug = entity->GetComponent<DebugComponent>();
|
||||
GraphicsComponent& entityGfx = entity->GetComponent<GraphicsComponent>();
|
||||
NodeComponent& entityNode = entity->GetComponent<NodeComponent>();
|
||||
|
||||
DebugDrawFlags enabledFlags = entityDebug.GetEnabledFlags();
|
||||
DebugDrawFlags flags = entityDebug.GetFlags();
|
||||
|
|
@ -193,17 +451,24 @@ namespace Ndk
|
|||
{
|
||||
switch (option)
|
||||
{
|
||||
case DebugDraw::Collider2D:
|
||||
{
|
||||
Nz::Vector3f offset;
|
||||
Nz::InstancedRenderableRef renderable = GenerateCollision2DMesh(entity, &offset);
|
||||
if (renderable)
|
||||
entityGfx.Attach(renderable, Nz::Matrix4f::Translate(offset), DebugDrawOrder);
|
||||
|
||||
entityDebug.UpdateDebugRenderable(option, std::move(renderable));
|
||||
break;
|
||||
}
|
||||
|
||||
case DebugDraw::Collider3D:
|
||||
{
|
||||
const Nz::Boxf& obb = entityGfx.GetBoundingVolume().obb.localBox;
|
||||
const Nz::Boxf& obb = entityGfx.GetAABB();
|
||||
|
||||
Nz::InstancedRenderableRef renderable = GenerateCollision3DMesh(entity);
|
||||
if (renderable)
|
||||
{
|
||||
renderable->SetPersistent(false);
|
||||
|
||||
entityGfx.Attach(renderable, Nz::Matrix4f::Translate(obb.GetCenter()), DebugDrawOrder);
|
||||
}
|
||||
entityGfx.Attach(renderable, Nz::Matrix4f::Translate(obb.GetCenter() - entityNode.GetPosition()), DebugDrawOrder);
|
||||
|
||||
entityDebug.UpdateDebugRenderable(option, std::move(renderable));
|
||||
break;
|
||||
|
|
@ -213,7 +478,7 @@ namespace Ndk
|
|||
{
|
||||
auto indexVertexBuffers = GetBoxMesh();
|
||||
|
||||
Nz::InstancedRenderableRef renderable = new AABBDebugRenderable(entity, GetAABBMaterial(), indexVertexBuffers.first, indexVertexBuffers.second);
|
||||
Nz::InstancedRenderableRef renderable = new AABBDebugRenderable(entity, GetGlobalAABBMaterial(), GetLocalAABBMaterial(), indexVertexBuffers.first, indexVertexBuffers.second);
|
||||
renderable->SetPersistent(false);
|
||||
|
||||
entityGfx.Attach(renderable, Nz::Matrix4f::Identity(), DebugDrawOrder);
|
||||
|
|
@ -257,125 +522,5 @@ namespace Ndk
|
|||
// Nothing to do
|
||||
}
|
||||
|
||||
Nz::InstancedRenderableRef DebugSystem::GenerateBox(Nz::Boxf box)
|
||||
{
|
||||
Nz::MeshRef mesh = Nz::Mesh::New();
|
||||
mesh->CreateStatic();
|
||||
|
||||
mesh->BuildSubMesh(Nz::Primitive::Box(box.GetLengths()));
|
||||
mesh->SetMaterialCount(1);
|
||||
|
||||
Nz::ModelRef model = Nz::Model::New();
|
||||
model->SetMesh(mesh);
|
||||
model->SetMaterial(0, GetOBBMaterial());
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
Nz::InstancedRenderableRef DebugSystem::GenerateCollision3DMesh(Entity* entity)
|
||||
{
|
||||
if (entity->HasComponent<CollisionComponent3D>())
|
||||
{
|
||||
CollisionComponent3D& entityCollision = entity->GetComponent<CollisionComponent3D>();
|
||||
const Nz::Collider3DRef& geom = entityCollision.GetGeom();
|
||||
|
||||
std::vector<Nz::Vector3f> vertices;
|
||||
std::vector<std::size_t> indices;
|
||||
|
||||
geom->ForEachPolygon([&](const float* polygonVertices, std::size_t vertexCount)
|
||||
{
|
||||
std::size_t firstIndex = vertices.size();
|
||||
|
||||
for (std::size_t i = 0; i < vertexCount; ++i)
|
||||
{
|
||||
const float* vertexData = &polygonVertices[i * 3];
|
||||
vertices.emplace_back(vertexData[0], vertexData[1], vertexData[2]);
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < vertexCount - 1; ++i)
|
||||
{
|
||||
indices.push_back(firstIndex + i);
|
||||
indices.push_back(firstIndex + i + 1);
|
||||
}
|
||||
|
||||
indices.push_back(firstIndex + vertexCount - 1);
|
||||
indices.push_back(firstIndex);
|
||||
});
|
||||
|
||||
Nz::IndexBufferRef indexBuffer = Nz::IndexBuffer::New(vertices.size() > 0xFFFF, Nz::UInt32(indices.size()), Nz::DataStorage_Hardware, 0);
|
||||
Nz::IndexMapper indexMapper(indexBuffer, Nz::BufferAccess_WriteOnly);
|
||||
|
||||
Nz::IndexIterator indexPtr = indexMapper.begin();
|
||||
for (std::size_t index : indices)
|
||||
*indexPtr++ = static_cast<Nz::UInt32>(index);
|
||||
|
||||
indexMapper.Unmap();
|
||||
|
||||
Nz::VertexBufferRef vertexBuffer = Nz::VertexBuffer::New(Nz::VertexDeclaration::Get(Nz::VertexLayout_XYZ), Nz::UInt32(vertices.size()), Nz::DataStorage_Hardware, 0);
|
||||
vertexBuffer->Fill(vertices.data(), 0, Nz::UInt32(vertices.size()));
|
||||
|
||||
Nz::MeshRef mesh = Nz::Mesh::New();
|
||||
mesh->CreateStatic();
|
||||
|
||||
Nz::StaticMeshRef subMesh = Nz::StaticMesh::New(vertexBuffer, indexBuffer);
|
||||
subMesh->SetPrimitiveMode(Nz::PrimitiveMode_LineList);
|
||||
subMesh->SetMaterialIndex(0);
|
||||
subMesh->GenerateAABB();
|
||||
|
||||
mesh->SetMaterialCount(1);
|
||||
mesh->AddSubMesh(subMesh);
|
||||
|
||||
Nz::ModelRef model = Nz::Model::New();
|
||||
model->SetMesh(mesh);
|
||||
model->SetMaterial(0, GetCollisionMaterial());
|
||||
|
||||
return model;
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Nz::MaterialRef DebugSystem::GetAABBMaterial()
|
||||
{
|
||||
if (!m_aabbMaterial)
|
||||
{
|
||||
m_aabbMaterial = Nz::Material::New();
|
||||
m_aabbMaterial->EnableFaceCulling(false);
|
||||
m_aabbMaterial->EnableDepthBuffer(true);
|
||||
m_aabbMaterial->SetDiffuseColor(Nz::Color::Red);
|
||||
m_aabbMaterial->SetFaceFilling(Nz::FaceFilling_Line);
|
||||
}
|
||||
|
||||
return m_aabbMaterial;
|
||||
}
|
||||
|
||||
Nz::MaterialRef DebugSystem::GetCollisionMaterial()
|
||||
{
|
||||
if (!m_collisionMaterial)
|
||||
{
|
||||
m_collisionMaterial = Nz::Material::New();
|
||||
m_collisionMaterial->EnableFaceCulling(false);
|
||||
m_collisionMaterial->EnableDepthBuffer(true);
|
||||
m_collisionMaterial->SetDiffuseColor(Nz::Color::Blue);
|
||||
m_collisionMaterial->SetFaceFilling(Nz::FaceFilling_Line);
|
||||
}
|
||||
|
||||
return m_collisionMaterial;
|
||||
}
|
||||
|
||||
Nz::MaterialRef DebugSystem::GetOBBMaterial()
|
||||
{
|
||||
if (!m_obbMaterial)
|
||||
{
|
||||
m_obbMaterial = Nz::Material::New();
|
||||
m_obbMaterial->EnableFaceCulling(false);
|
||||
m_obbMaterial->EnableDepthBuffer(true);
|
||||
m_obbMaterial->SetDiffuseColor(Nz::Color::Green);
|
||||
m_obbMaterial->SetFaceFilling(Nz::FaceFilling_Line);
|
||||
}
|
||||
|
||||
return m_obbMaterial;
|
||||
}
|
||||
|
||||
SystemIndex DebugSystem::systemIndex;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (C) 2017 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Development Kit"
|
||||
// For conditions of distribution and use, see copyright notice in Prerequisites.hpp
|
||||
|
||||
#include <NDK/Systems/LifetimeSystem.hpp>
|
||||
#include <NDK/Components/LifetimeComponent.hpp>
|
||||
|
||||
namespace Ndk
|
||||
{
|
||||
LifetimeSystem::LifetimeSystem()
|
||||
{
|
||||
Requires<LifetimeComponent>();
|
||||
}
|
||||
|
||||
void LifetimeSystem::OnUpdate(float elapsedTime)
|
||||
{
|
||||
for (const Ndk::EntityHandle& entity : GetEntities())
|
||||
{
|
||||
auto& lifetime = entity->GetComponent<LifetimeComponent>();
|
||||
|
||||
if (lifetime.UpdateLifetime(elapsedTime))
|
||||
entity->Kill();
|
||||
}
|
||||
}
|
||||
|
||||
SystemIndex LifetimeSystem::systemIndex;
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <NDK/Systems/PhysicsSystem2D.hpp>
|
||||
#include <Nazara/Physics2D/RigidBody2D.hpp>
|
||||
#include <NDK/World.hpp>
|
||||
#include <NDK/Components/CollisionComponent2D.hpp>
|
||||
#include <NDK/Components/NodeComponent.hpp>
|
||||
#include <NDK/Components/PhysicsComponent2D.hpp>
|
||||
|
|
@ -33,9 +34,135 @@ namespace Ndk
|
|||
|
||||
void PhysicsSystem2D::CreatePhysWorld() const
|
||||
{
|
||||
NazaraAssert(!m_world, "Physics world should not be created twice");
|
||||
NazaraAssert(!m_physWorld, "Physics world should not be created twice");
|
||||
|
||||
m_world = std::make_unique<Nz::PhysWorld2D>();
|
||||
m_physWorld = std::make_unique<Nz::PhysWorld2D>();
|
||||
}
|
||||
|
||||
void PhysicsSystem2D::DebugDraw(const DebugDrawOptions& options, bool drawShapes, bool drawConstraints, bool drawCollisions)
|
||||
{
|
||||
Nz::PhysWorld2D::DebugDrawOptions worldOptions{ options.constraintColor, options.collisionPointColor, options.shapeOutlineColor };
|
||||
|
||||
if (options.colorCallback)
|
||||
{
|
||||
worldOptions.colorCallback = [&options, this](Nz::RigidBody2D& body, std::size_t shapeIndex, void* userdata)
|
||||
{
|
||||
return options.colorCallback(GetEntityFromBody(body), shapeIndex, userdata);
|
||||
};
|
||||
}
|
||||
|
||||
worldOptions.circleCallback = options.circleCallback;
|
||||
worldOptions.dotCallback = options.dotCallback;
|
||||
worldOptions.polygonCallback = options.polygonCallback;
|
||||
worldOptions.segmentCallback = options.segmentCallback;
|
||||
worldOptions.thickSegmentCallback = options.thickSegmentCallback;
|
||||
|
||||
worldOptions.userdata = options.userdata;
|
||||
|
||||
GetPhysWorld().DebugDraw(worldOptions, drawShapes, drawConstraints, drawCollisions);
|
||||
}
|
||||
|
||||
const EntityHandle& PhysicsSystem2D::GetEntityFromBody(const Nz::RigidBody2D& body) const
|
||||
{
|
||||
auto entityId = static_cast<EntityId>(reinterpret_cast<std::uintptr_t>(body.GetUserdata()));
|
||||
|
||||
auto& world = GetWorld();
|
||||
|
||||
NazaraAssert(world.IsEntityIdValid(entityId), "All Bodies of this world must be part of the physics world by using PhysicsComponent");
|
||||
|
||||
return world.GetEntity(entityId);
|
||||
}
|
||||
|
||||
bool PhysicsSystem2D::NearestBodyQuery(const Nz::Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, EntityHandle* nearestBody)
|
||||
{
|
||||
Nz::RigidBody2D* body;
|
||||
bool res = GetPhysWorld().NearestBodyQuery(from, maxDistance, collisionGroup, categoryMask, collisionMask, &body);
|
||||
|
||||
(*nearestBody) = GetEntityFromBody(*body);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool PhysicsSystem2D::NearestBodyQuery(const Nz::Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, NearestQueryResult* result)
|
||||
{
|
||||
Nz::PhysWorld2D::NearestQueryResult queryResult;
|
||||
if (GetPhysWorld().NearestBodyQuery(from, maxDistance, collisionGroup, categoryMask, collisionMask, &queryResult))
|
||||
{
|
||||
result->nearestBody = GetEntityFromBody(*queryResult.nearestBody);
|
||||
result->closestPoint = std::move(queryResult.closestPoint);
|
||||
result->fraction = std::move(queryResult.fraction);
|
||||
result->distance = queryResult.distance;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void PhysicsSystem2D::RaycastQuery(const Nz::Vector2f & from, const Nz::Vector2f & to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, const std::function<void(const RaycastHit&)>& callback)
|
||||
{
|
||||
return GetPhysWorld().RaycastQuery(from, to, radius, collisionGroup, categoryMask, collisionMask, [this, &callback](const Nz::PhysWorld2D::RaycastHit& hitInfo)
|
||||
{
|
||||
callback({
|
||||
GetEntityFromBody(*hitInfo.nearestBody),
|
||||
hitInfo.hitPos,
|
||||
hitInfo.hitNormal,
|
||||
hitInfo.fraction
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
bool PhysicsSystem2D::RaycastQuery(const Nz::Vector2f& from, const Nz::Vector2f& to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, std::vector<RaycastHit>* hitInfos)
|
||||
{
|
||||
std::vector<Nz::PhysWorld2D::RaycastHit> queryResult;
|
||||
bool res = GetPhysWorld().RaycastQuery(from, to, radius, collisionGroup, categoryMask, collisionMask, &queryResult);
|
||||
|
||||
for (auto& hitResult : queryResult)
|
||||
{
|
||||
hitInfos->push_back({
|
||||
GetEntityFromBody(*hitResult.nearestBody),
|
||||
std::move(hitResult.hitPos),
|
||||
std::move(hitResult.hitNormal),
|
||||
hitResult.fraction
|
||||
});
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool PhysicsSystem2D::RaycastQueryFirst(const Nz::Vector2f& from, const Nz::Vector2f& to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RaycastHit* hitInfo)
|
||||
{
|
||||
Nz::PhysWorld2D::RaycastHit queryResult;
|
||||
if (GetPhysWorld().RaycastQueryFirst(from, to, radius, collisionGroup, categoryMask, collisionMask, &queryResult))
|
||||
{
|
||||
hitInfo->body = GetEntityFromBody(*queryResult.nearestBody);
|
||||
hitInfo->hitPos = std::move(queryResult.hitPos);
|
||||
hitInfo->hitNormal = std::move(queryResult.hitNormal);
|
||||
hitInfo->fraction = queryResult.fraction;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void PhysicsSystem2D::RegionQuery(const Nz::Rectf& boundingBox, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, const std::function<void(const EntityHandle&)>& callback)
|
||||
{
|
||||
return GetPhysWorld().RegionQuery(boundingBox, collisionGroup, categoryMask, collisionMask, [this, &callback](Nz::RigidBody2D* body)
|
||||
{
|
||||
callback(GetEntityFromBody(*body));
|
||||
});
|
||||
}
|
||||
|
||||
void PhysicsSystem2D::RegionQuery(const Nz::Rectf& boundingBox, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, std::vector<EntityHandle>* bodies)
|
||||
{
|
||||
std::vector<Nz::RigidBody2D*> queryResult;
|
||||
GetPhysWorld().RegionQuery(boundingBox, collisionGroup, categoryMask, collisionMask, &queryResult);
|
||||
|
||||
for (auto& body : queryResult)
|
||||
{
|
||||
bodies->emplace_back(GetEntityFromBody(*body));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -47,18 +174,34 @@ namespace Ndk
|
|||
|
||||
void PhysicsSystem2D::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<PhysicsComponent2D>())
|
||||
{
|
||||
// We take the opposite array from which the entity should belong to
|
||||
auto& entities = (entity->HasComponent<PhysicsComponent2D>()) ? m_staticObjects : m_dynamicObjects;
|
||||
entities.Remove(entity);
|
||||
if (entity->GetComponent<PhysicsComponent2D>().IsNodeSynchronizationEnabled())
|
||||
m_dynamicObjects.Insert(entity);
|
||||
else
|
||||
m_dynamicObjects.Remove(entity);
|
||||
|
||||
m_staticObjects.Remove(entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dynamicObjects.Remove(entity);
|
||||
m_staticObjects.Insert(entity);
|
||||
|
||||
// If entities just got added to the system, teleport them to their NodeComponent position/rotation
|
||||
// This will prevent the physics engine to mess with the scene while correcting position/rotation
|
||||
if (justAdded)
|
||||
{
|
||||
auto& collision = entity->GetComponent<CollisionComponent2D>();
|
||||
auto& node = entity->GetComponent<NodeComponent>();
|
||||
|
||||
Nz::RigidBody2D* physObj = collision.GetStaticBody();
|
||||
physObj->SetPosition(Nz::Vector2f(node.GetPosition(Nz::CoordSys_Global)));
|
||||
//physObj->SetRotation(node.GetRotation());
|
||||
}
|
||||
}
|
||||
|
||||
auto& entities = (entity->HasComponent<PhysicsComponent2D>()) ? m_dynamicObjects : m_staticObjects;
|
||||
entities.Insert(entity);
|
||||
|
||||
if (!m_world)
|
||||
if (!m_physWorld)
|
||||
CreatePhysWorld();
|
||||
}
|
||||
|
||||
|
|
@ -70,10 +213,10 @@ namespace Ndk
|
|||
|
||||
void PhysicsSystem2D::OnUpdate(float elapsedTime)
|
||||
{
|
||||
if (!m_world)
|
||||
if (!m_physWorld)
|
||||
return;
|
||||
|
||||
m_world->Step(elapsedTime);
|
||||
m_physWorld->Step(elapsedTime);
|
||||
|
||||
for (const Ndk::EntityHandle& entity : m_dynamicObjects)
|
||||
{
|
||||
|
|
@ -81,7 +224,7 @@ namespace Ndk
|
|||
PhysicsComponent2D& phys = entity->GetComponent<PhysicsComponent2D>();
|
||||
|
||||
Nz::RigidBody2D* body = phys.GetRigidBody();
|
||||
node.SetRotation(Nz::EulerAnglesf(0.f, 0.f, body->GetRotation()), Nz::CoordSys_Global);
|
||||
node.SetRotation(body->GetRotation(), Nz::CoordSys_Global);
|
||||
node.SetPosition(Nz::Vector3f(body->GetPosition(), node.GetPosition(Nz::CoordSys_Global).z), Nz::CoordSys_Global);
|
||||
}
|
||||
|
||||
|
|
@ -97,7 +240,7 @@ namespace Ndk
|
|||
Nz::Vector2f newPosition = Nz::Vector2f(node.GetPosition(Nz::CoordSys_Global));
|
||||
|
||||
// To move static objects and ensure their collisions, we have to specify them a velocity
|
||||
// (/!\: the physical motor does not apply the speed on static objects)
|
||||
// (/!\: the physical engine does not apply the speed on static objects)
|
||||
if (newPosition != oldPosition)
|
||||
{
|
||||
body->SetPosition(newPosition);
|
||||
|
|
@ -106,8 +249,7 @@ namespace Ndk
|
|||
else
|
||||
body->SetVelocity(Nz::Vector2f::Zero());
|
||||
|
||||
/*
|
||||
if (newRotation != oldRotation)
|
||||
/*if (newRotation != oldRotation)
|
||||
{
|
||||
Nz::Quaternionf transition = newRotation * oldRotation.GetConjugate();
|
||||
Nz::EulerAnglesf angles = transition.ToEulerAngles();
|
||||
|
|
@ -119,10 +261,91 @@ namespace Ndk
|
|||
physObj->SetAngularVelocity(angularVelocity);
|
||||
}
|
||||
else
|
||||
physObj->SetAngularVelocity(Nz::Vector3f::Zero());
|
||||
*/
|
||||
physObj->SetAngularVelocity(Nz::Vector3f::Zero());*/
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsSystem2D::RegisterCallbacks(unsigned int collisionId, Callback callbacks)
|
||||
{
|
||||
Nz::PhysWorld2D::Callback worldCallbacks;
|
||||
|
||||
if (callbacks.endCallback)
|
||||
{
|
||||
worldCallbacks.endCallback = [this, cb = std::move(callbacks.endCallback)](Nz::PhysWorld2D& world, Nz::Arbiter2D& arbiter, Nz::RigidBody2D& bodyA, Nz::RigidBody2D& bodyB, void* userdata)
|
||||
{
|
||||
cb(*this, arbiter, GetEntityFromBody(bodyA), GetEntityFromBody(bodyB), userdata);
|
||||
};
|
||||
}
|
||||
|
||||
if (callbacks.preSolveCallback)
|
||||
{
|
||||
worldCallbacks.preSolveCallback = [this, cb = std::move(callbacks.preSolveCallback)](Nz::PhysWorld2D& world, Nz::Arbiter2D& arbiter, Nz::RigidBody2D& bodyA, Nz::RigidBody2D& bodyB, void* userdata)
|
||||
{
|
||||
return cb(*this, arbiter, GetEntityFromBody(bodyA), GetEntityFromBody(bodyB), userdata);
|
||||
};
|
||||
}
|
||||
|
||||
if (callbacks.postSolveCallback)
|
||||
{
|
||||
worldCallbacks.postSolveCallback = [this, cb = std::move(callbacks.postSolveCallback)](Nz::PhysWorld2D& world, Nz::Arbiter2D& arbiter, Nz::RigidBody2D& bodyA, Nz::RigidBody2D& bodyB, void* userdata)
|
||||
{
|
||||
cb(*this, arbiter, GetEntityFromBody(bodyA), GetEntityFromBody(bodyB), userdata);
|
||||
};
|
||||
}
|
||||
|
||||
if (callbacks.startCallback)
|
||||
{
|
||||
worldCallbacks.startCallback = [this, cb = std::move(callbacks.startCallback)](Nz::PhysWorld2D& world, Nz::Arbiter2D& arbiter, Nz::RigidBody2D& bodyA, Nz::RigidBody2D& bodyB, void* userdata)
|
||||
{
|
||||
return cb(*this, arbiter, GetEntityFromBody(bodyA), GetEntityFromBody(bodyB), userdata);
|
||||
};
|
||||
}
|
||||
|
||||
worldCallbacks.userdata = callbacks.userdata;
|
||||
|
||||
m_physWorld->RegisterCallbacks(collisionId, worldCallbacks);
|
||||
}
|
||||
|
||||
void PhysicsSystem2D::RegisterCallbacks(unsigned int collisionIdA, unsigned int collisionIdB, Callback callbacks)
|
||||
{
|
||||
Nz::PhysWorld2D::Callback worldCallbacks;
|
||||
|
||||
if (callbacks.endCallback)
|
||||
{
|
||||
worldCallbacks.endCallback = [this, cb = std::move(callbacks.endCallback)](Nz::PhysWorld2D& world, Nz::Arbiter2D& arbiter, Nz::RigidBody2D& bodyA, Nz::RigidBody2D& bodyB, void* userdata)
|
||||
{
|
||||
cb(*this, arbiter, GetEntityFromBody(bodyA), GetEntityFromBody(bodyB), userdata);
|
||||
};
|
||||
}
|
||||
|
||||
if (callbacks.preSolveCallback)
|
||||
{
|
||||
worldCallbacks.preSolveCallback = [this, cb = std::move(callbacks.preSolveCallback)](Nz::PhysWorld2D& world, Nz::Arbiter2D& arbiter, Nz::RigidBody2D& bodyA, Nz::RigidBody2D& bodyB, void* userdata)
|
||||
{
|
||||
return cb(*this, arbiter, GetEntityFromBody(bodyA), GetEntityFromBody(bodyB), userdata);
|
||||
};
|
||||
}
|
||||
|
||||
if (callbacks.postSolveCallback)
|
||||
{
|
||||
worldCallbacks.postSolveCallback = [this, cb = std::move(callbacks.postSolveCallback)](Nz::PhysWorld2D& world, Nz::Arbiter2D& arbiter, Nz::RigidBody2D& bodyA, Nz::RigidBody2D& bodyB, void* userdata)
|
||||
{
|
||||
cb(*this, arbiter, GetEntityFromBody(bodyA), GetEntityFromBody(bodyB), userdata);
|
||||
};
|
||||
}
|
||||
|
||||
if (callbacks.startCallback)
|
||||
{
|
||||
worldCallbacks.startCallback = [this, cb = std::move(callbacks.startCallback)](Nz::PhysWorld2D& world, Nz::Arbiter2D& arbiter, Nz::RigidBody2D& bodyA, Nz::RigidBody2D& bodyB, void* userdata)
|
||||
{
|
||||
return cb(*this, arbiter, GetEntityFromBody(bodyA), GetEntityFromBody(bodyB), userdata);
|
||||
};
|
||||
}
|
||||
|
||||
worldCallbacks.userdata = callbacks.userdata;
|
||||
|
||||
m_physWorld->RegisterCallbacks(collisionIdA, collisionIdB, worldCallbacks);
|
||||
}
|
||||
|
||||
SystemIndex PhysicsSystem2D::systemIndex;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,8 +69,8 @@ namespace Ndk
|
|||
auto& node = entity->GetComponent<NodeComponent>();
|
||||
|
||||
Nz::RigidBody3D* physObj = collision.GetStaticBody();
|
||||
physObj->SetPosition(node.GetPosition());
|
||||
physObj->SetRotation(node.GetRotation());
|
||||
physObj->SetPosition(node.GetPosition(Nz::CoordSys_Global));
|
||||
physObj->SetRotation(node.GetRotation(Nz::CoordSys_Global));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue