188 Commits

Author SHA1 Message Date
Antoine Pilote
4661c1f00e Update LICENSE 2024-12-06 22:14:24 -05:00
Antoine Pilote
b6721d036a Merge pull request #94 from antopilo/develop
Bumped to develop
2024-12-02 17:05:08 -05:00
Antoine Pilote
31388612bb Merge pull request #93 from xiaohunqupo/patch-1
Update glfw_p5.lua
2024-12-02 17:04:44 -05:00
antopilo
5b529bd97d Fixed game engine not recompiling + improved prefab instancing from TB 2024-12-02 00:12:42 -05:00
antopilo
d93d69d059 Added controller support 2024-12-01 20:52:34 -05:00
antopilo
82459a6e4c Now instancing prefab from trenchbroom correctly 2024-12-01 13:49:06 -05:00
antopilo
5b4d6d915a Now exports prefabs to trenchbroom automatically 2024-12-01 13:21:58 -05:00
antopilo
ea044a2357 Added GetAllFiles to filesystem 2024-12-01 13:21:44 -05:00
antopilo
b6c3220797 Depth of field no unit accurate 2024-12-01 13:06:13 -05:00
antopilo
15051a4eb7 Improved env setting labels 2024-12-01 13:03:58 -05:00
antopilo
ef25a932b5 Now serializing all environment settings + optimized transform system 2024-12-01 12:15:27 -05:00
antopilo
d7e60cfe96 Fixed runtime 2024-12-01 02:30:06 -05:00
antopilo
a27039d7c5 More blending code + ShapeCastSphere now works 2024-12-01 02:11:05 -05:00
antopilo
18eec6c570 No longer using custom panel for skinned model component 2024-12-01 02:10:49 -05:00
antopilo
699375f1a7 Prefab window no longer crashing 2024-12-01 02:10:31 -05:00
antopilo
c8aa609ab1 Added skeletal animation 1D blending 2024-12-01 02:10:19 -05:00
antopilo
6a96ce497c Capsule and Cylinder now correct height in dynamic world 2024-12-01 02:09:29 -05:00
antopilo
fb217221b7 Added new postfx UI widgets in environment properties 2024-12-01 02:09:06 -05:00
antopilo
9238a59a00 Improved play mode startup time 2024-12-01 02:08:32 -05:00
antopilo
f1b4aaad76 Added lens dirt, posterization and pixelization postfx 2024-12-01 02:07:55 -05:00
Danny许
b32ee08b65 Update glfw_p5.lua
Fix link error.
2024-11-26 10:49:04 +08:00
antopilo
b33bfcab57 Added LookAt to transform C# API 2024-11-24 04:18:55 -05:00
antopilo
6744a58043 Fixed crash when deserializing a skinned mesh if no mesh is set 2024-11-24 00:03:13 -05:00
antopilo
32273eece9 Changed default volumetric strength to 1.0 2024-11-24 00:02:51 -05:00
antopilo
d43c48207c Hide camera speed UI if not controlling camera 2024-11-24 00:02:38 -05:00
antopilo
d714ac0f35 Fixed snapping not working on Z axis 2024-11-24 00:02:14 -05:00
antopilo
dd46e32bee Better SSAO + added shader reloading in debug 2024-11-23 19:46:39 -05:00
antopilo
1782f18f26 Added search feature with text hightlight 2024-11-22 01:08:51 -05:00
antopilo
84b2b63ba9 Added shortcut to open resource in component widgets 2024-11-21 22:14:14 -05:00
antopilo
4ab59bf7e8 Moved environment to a resource and a component 2024-11-21 21:06:14 -05:00
Antoine Pilote
d546228089 Merge pull request #92 from antopilo/develop
Merge develop into main
2024-11-20 22:28:05 -05:00
antopilo
9937d35579 updated readme image 2024-11-20 22:26:41 -05:00
antopilo
1063ffcd58 Removed useless menu items 2024-11-20 01:36:52 -05:00
antopilo
e4c11140e0 Better UI 2024-11-20 01:30:57 -05:00
antopilo
9b853aef7e Added separte settings for gizmo, shape drawing, fixed sky, better UI 2024-11-20 00:07:56 -05:00
antopilo
26ad1507eb Merged static resources 2024-11-19 23:23:38 -05:00
antopilo
3fbb1bd33d Merge branch 'develop' of https://github.com/antopilo/Nuake into develop
# Conflicts:
#	Nuake/src/Resource/StaticResources.cpp
2024-11-19 23:23:16 -05:00
antopilo
2c4d0faf64 Added custom titlebar to the editor 2024-11-19 23:22:41 -05:00
antopilo
0ac0934622 Serialize Sky Component 2024-11-11 11:45:12 -05:00
antopilo
0311862b65 Merge branch 'develop' of https://github.com/antopilo/Nuake into develop 2024-11-06 20:40:58 -05:00
antopilo
89209dc7ba Added support for skyboxes using a new SkyBox resource and component 2024-11-06 20:40:38 -05:00
antopilo
e47142a3e4 Swapped for custom glfw 2024-10-29 20:40:47 -04:00
antopilo
5c2311d7b5 Master volume in project settings now works 2024-10-29 20:37:59 -04:00
antopilo
9647cac48b Disabled thumbnails for now 2024-10-28 20:15:43 -04:00
antopilo
03d785f016 Fixed inverted spatialized audio direction in play mode 2024-10-28 20:14:49 -04:00
antopilo
f1be4f7cef Fixed memory leak + added visibility UI node C# endpoints + size 2024-10-19 23:23:26 -04:00
antopilo
cbf11abcf5 Fixed scene leaking 2024-10-19 15:04:32 -04:00
antopilo
3d630483f6 Added world space UI Input aka doom3 UI 2024-10-19 15:04:07 -04:00
antopilo
c432077328 Added exposed var bool + fixed transform panel 2024-10-19 15:02:36 -04:00
antopilo
39cf28c91e Raycasts now returns the body instance it collided with + serialize spot light cones 2024-10-18 00:21:08 -04:00
Antoine Pilote
4e0817b761 Fixed UI not rendering 2024-10-16 12:28:03 -04:00
antopilo
8ed6a53cf4 Setter and Getter for UIResource on component - Removed useless Environment creation 2024-10-15 20:35:42 -04:00
antopilo
534c35c76f Fixed sprites not working 2024-10-15 19:00:56 -04:00
antopilo
28bbb255c5 Model loader now takes into account submeshes transform 2024-09-27 01:39:40 -04:00
antopilo
e18dbd292f Fixed inverted Y velocity in velocity buffer 2024-09-26 18:47:51 -04:00
antopilo
102ccc530b Finally finished TAA 2024-09-25 22:37:31 -04:00
Antoine Pilote
31c8a2e598 Changed format to gl-float 2024-09-25 13:17:25 -04:00
Antoine Pilote
a37bdd9d7a Added debug display with arrows of velocity buffer 2024-09-25 12:58:53 -04:00
antopilo
6e8f14c5da Added velocity buffer + start of TAA implementation 2024-09-24 21:19:56 -04:00
antopilo
bf75c04a8c Made imgui use another ID for prefab window 2024-09-24 19:29:27 -04:00
antopilo
2dfcb683fc Added imguizo + overlay to prefab editor 2024-09-22 00:01:36 -04:00
antopilo
f1c403f94c Can now delete from prefab editor 2024-09-21 23:49:51 -04:00
antopilo
114adab73f Fixed crash when prefab gets instantiated with C# script 2024-09-21 19:26:20 -04:00
antopilo
0e750bda89 work 2024-09-21 14:02:20 -04:00
antopilo
8079c47832 Instancing prefab through code should instance body and scripts immediatly 2024-09-21 13:18:35 -04:00
antopilo
29b35a6932 Can now reparent prefab with drag n drop 2024-09-21 13:02:36 -04:00
antopilo
ef6e7ac0dc Prevented displaying child of prefab 2024-09-21 13:00:35 -04:00
antopilo
0c784d4462 Stopped display child of prefabs 2024-09-21 12:58:01 -04:00
antopilo
954e2110f1 Fixed prefab serialization and instancing into scene 2024-09-21 12:52:56 -04:00
antopilo
3d9cda2990 Minor improvements with prefab deserialization 2024-09-19 21:36:44 -04:00
antopilo
6ac1ff8386 Work 2024-09-19 21:11:07 -04:00
Antoine Pilote
7791cd9f29 Merge pull request #91 from WiggleWizard/feature/cs-scene-callbacks
Exposed subsystem to scene events
2024-09-19 16:55:31 -04:00
WiggleWizard
a487d31c48 Completed work on exposing subsystems to scene events 2024-09-19 21:43:04 +01:00
WiggleWizard
edce52bb17 Finished up MVP for scene callbacks 2024-09-19 18:50:52 +01:00
WiggleWizard
d0c5ef1a1d Initial infrastructure for C# scene callbacks in subsystems 2024-09-19 17:52:19 +01:00
antopilo
98797e15f8 Prefab editor now somewhat works with live-reload 2024-09-19 12:24:05 -04:00
antopilo
216fa230b6 Saving prefab from prefab editor now works 2024-09-19 10:37:22 -04:00
antopilo
616532e78b Added MVP for prefab editor window and made the whole editor modular to support multi-scene editing 2024-09-19 00:56:22 -04:00
antopilo
a87aebe12b Merge branch 'develop' of https://github.com/antopilo/Nuake into develop 2024-09-18 17:10:18 -04:00
antopilo
7fc10b4e56 Improvements 2024-09-18 17:10:12 -04:00
Antoine Pilote
bd6b4362bc Merge pull request #90 from WiggleWizard/feature/scriptable-subsystems
First pass scriptable subsystems that has the same lifetime of the engine
2024-09-18 16:51:07 -04:00
WiggleWizard
ca645e2026 Fixed a few things 2024-09-18 21:48:14 +01:00
WiggleWizard
066b2998ac Much more stable and simplified subsystem architecture 2024-09-18 21:20:14 +01:00
WiggleWizard
510b577f49 First pass scriptable subsystems that has the same lifetime of the engine 2024-09-18 12:44:46 +01:00
Antoine Pilote
67d7865a20 Merge branch 'develop' of https://github.com/antopilo/nuake into develop 2024-09-17 17:32:13 -04:00
Antoine Pilote
ef0fde5847 Can now drag n drop proejct in project launcher + delete or right click to remove from list 2024-09-17 17:32:05 -04:00
Antoine Pilote
1b2d2985f5 Merge pull request #87 from WiggleWizard/fix/wrenremoval
Removed the last remnants of Wren QQ
2024-09-17 17:20:32 -04:00
Antoine Pilote
07871123cb Fixed runtime linker issues 2024-09-17 12:39:38 -04:00
Antoine Pilote
5f1b9dc65b Merge branch 'develop' of https://github.com/antopilo/nuake into develop 2024-09-17 12:32:48 -04:00
antopilo
c6a2d916a8 Fixed crash when html file is empty and when canvas fails to aprse 2024-09-16 21:42:35 -04:00
antopilo
7ed37d0bbb Fixed crash when canvas parser fails + added resolution settings for worldspace UI 2024-09-16 21:32:17 -04:00
antopilo
f58e09cfc3 Removed overlay when in play mode 2024-09-16 21:31:51 -04:00
antopilo
bd77025ed0 Added script icon in scene hierarchy 2024-09-16 20:55:24 -04:00
antopilo
dd3cc823c0 Improved filesystem browser, color accent, drag n drop, new icons 2024-09-16 20:12:36 -04:00
antopilo
da995b99c8 Renamed textures to Textures 2024-09-16 20:12:02 -04:00
WiggleWizard
1b2abced1e Removed the last remnants of Wren QQ 2024-09-17 00:08:04 +01:00
antopilo
38484415f1 Now displaying camera frustum gizmo 2024-09-16 17:28:01 -04:00
Antoine Pilote
cf9612c5b1 Added a popup to configure trenchbroom when creating a new project 2024-09-16 13:27:22 -04:00
Antoine Pilote
7f92311f12 Fixed crash when ctrl-s in project browser haha 2024-09-16 12:46:15 -04:00
Antoine Pilote
4ac7d1cfc9 Added OpenFolderDialog + now project creation selects folder instead 2024-09-16 12:40:57 -04:00
Antoine Pilote
cff63d71cc Removed glew 2024-09-16 12:18:52 -04:00
Antoine Pilote
4a3d15e7d3 Merge pull request #76 from WiggleWizard/feature/morereflection
Second pass reflection
2024-09-16 11:10:44 -04:00
WiggleWizard
d19ba4f979 Converted last components to new component drawing system 2024-09-16 14:49:25 +01:00
antopilo
ae426f7f17 Added support for SVG images inUI + added a texture flag to flip on load 2024-09-16 08:57:52 -04:00
WiggleWizard
8b2511f995 Better API for binding inspector drawers and added the ability to add whole component drawers 2024-09-16 10:57:22 +01:00
WiggleWizard
d338a98c9b Removed Wren script references in the UI 2024-09-16 10:18:32 +01:00
WiggleWizard
bb43bbe1b8 Fixed rebuild action for quake map component 2024-09-16 10:05:55 +01:00
WiggleWizard
52776186d3 Added the ability to remove components 2024-09-16 00:17:28 +01:00
WiggleWizard
b23d418f23 Compile issues fixed 2024-09-15 23:14:23 +01:00
WiggleWizard
baac971deb A little bit of cleanup 2024-09-15 23:06:06 +01:00
antopilo
24be72b10a Made text calculate proper width with different fonts 2024-09-15 17:29:41 -04:00
WiggleWizard
269533eb03 Particle Emitter Component reflected 2024-09-15 21:34:38 +01:00
WiggleWizard
7846a667a2 Quake Map Component reflected 2024-09-15 21:34:38 +01:00
WiggleWizard
0dcd383dbb Added the ability to add actions (buttons) to the inspector through reflection 2024-09-15 21:34:38 +01:00
WiggleWizard
2b06fe32de Small refactor of trait reflection 2024-09-15 21:34:38 +01:00
WiggleWizard
1d5f578e86 Rigidbody Component reflection 2024-09-15 21:34:38 +01:00
WiggleWizard
6149907576 Skinned Model Component now reflected 2024-09-15 21:34:38 +01:00
WiggleWizard
d8d904b6ba New reflection type DynamicItemList 2024-09-15 21:34:38 +01:00
WiggleWizard
1e570e17fd Made component field type ResourceFile easier to work with 2024-09-15 21:34:38 +01:00
WiggleWizard
d62f241a16 Sphere collider reflection 2024-09-15 21:34:38 +01:00
WiggleWizard
5d0eb4a597 Sprite component reflected 2024-09-15 21:34:37 +01:00
WiggleWizard
dabd9c01a6 Removed trigger zone component 2024-09-15 21:34:37 +01:00
WiggleWizard
aed98dd648 UI system now working well with the new component changes, fixed trait compile issues, fixed inspector rendering issues 2024-09-15 21:34:37 +01:00
WiggleWizard
59505b0664 Fix for audio emitter component not compiling 2024-09-15 21:31:07 +01:00
WiggleWizard
9e94006d2b Added generic ability to (de)serialize ResourceFiles, a templated function to allow easier setting of entt traits and renamed float limits function 2024-09-15 21:31:07 +01:00
WiggleWizard
82771d43da Removed old rubbish from audio emitter component 2024-09-15 21:31:06 +01:00
WiggleWizard
65c8ab79af New component field type to support files
Also fixed Audio System to work with this new supported component field type
2024-09-15 21:31:06 +01:00
WiggleWizard
68ffe1d6b4 Basic inspector reflection working for 2 components 2024-09-15 21:31:06 +01:00
WiggleWizard
90a60e8d87 Initial inspector work to render using reflection 2024-09-15 21:31:06 +01:00
WiggleWizard
56e12c2647 DrawVec3 helper now returns true if changed 2024-09-15 21:31:06 +01:00
WiggleWizard
7d66a19ab2 Architecture rework for components to accomodate for reflection 2024-09-15 21:31:06 +01:00
WiggleWizard
bf6fb0f8b6 Fix for entt update 2024-09-15 21:31:06 +01:00
WiggleWizard
ded6fd2e03 Upgraded entt
Deleted the header only entt lib and added the full and latest library to the dependencies list
2024-09-15 21:31:05 +01:00
antopilo
c2e50822f1 Fixed invalid uniforms in shaders 2024-09-15 16:30:06 -04:00
antopilo
24a4281a3d Added css style propagation + hover propagation from child 2024-09-15 11:08:21 -04:00
Antoine Pilote
c5dca4dc37 Merge pull request #75 from xypherorion/main
FIxed warnings for Premake5 [Issue #74]
2024-09-15 10:28:10 -04:00
Xypher Orion
edc4d43f97 Corrected config 2024-09-15 08:42:27 -04:00
Xypher Orion
a7cbbf2830 Patched for Main Repo Issue #74 2024-09-15 07:31:47 -04:00
antopilo
68ae15594f Started relationional styles 2024-09-14 14:12:08 -04:00
antopilo
79908a12a5 More accurate text size when using px font-size. Added CSS imports to canvas sourceFiles for live reload + started implement descendant css rules 2024-09-14 13:54:23 -04:00
antopilo
fad8b4033b Better default + made root node constraint other nodes 2024-09-13 21:46:21 -04:00
antopilo
efc4b8bae7 Added stylesheet @import into live reload filewatch for a canvas 2024-09-13 21:45:56 -04:00
antopilo
6e92674bba UI hot-reloads if child widgets or stylesheet gets updated 2024-09-13 19:14:46 -04:00
antopilo
ee852f7f3d Prevented abusive resizing when virtual camera is displayed + hide virtual cam in play mode 2024-09-13 18:24:42 -04:00
antopilo
bb0da25682 Fixed newly generated solution not building 2024-09-13 18:24:08 -04:00
antopilo
1b89eaa695 Disabled UI rendering in camera previews 2024-09-13 17:26:21 -04:00
antopilo
89ea32a4b3 Added SceneSwitching, Better font rendering, DOM inspector, Font-family prop 2024-09-13 17:18:09 -04:00
antopilo
4c76e9e493 Can now edit text of text nodes and fetch any other nodes in the DOM from ID 2024-09-13 01:25:41 -04:00
antopilo
3b148b76c4 Started to expose DOM to C# API with support for custom nodes. Currently crash when doing FindNodeByID<T> 2024-09-13 00:51:34 -04:00
Antoine Pilote
9e87dca9ce Set editor viewport dimension for InputManager 2024-09-12 17:01:34 -04:00
Antoine Pilote
5e1483e111 Added mouse position relative to viewport 2024-09-12 13:17:47 -04:00
antopilo
c7621b31e0 Added CustomWidget through C# reflection with callbacks 2024-09-11 22:58:33 -04:00
antopilo
596e4a484c Added C# UIWidget API 2024-09-11 22:58:06 -04:00
antopilo
a5bf5d99c7 Refactor CodeStyle of NuakeUI Renderer 2024-09-11 22:57:36 -04:00
antopilo
8b6991822f Removed NuakeUI FileSystem 2024-09-11 22:57:17 -04:00
antopilo
7ee76a129e Now calls Tick on UI Canvas 2024-09-11 22:57:05 -04:00
antopilo
a75bcc260f Added UI for IsWorldspace 2024-09-11 17:42:04 -04:00
antopilo
f1903de9ab Fixed input manager for UI + WorldSpace UI 2024-09-11 17:41:39 -04:00
Antoine Pilote
40da75eeeb Merge pull request #73 from WiggleWizard/fix/buildoptimizations
Enabled multithreaded compilation and fixed some build warnings
2024-09-11 09:46:12 -04:00
WiggleWizard
7efa69a20d Enabled multithreaded compilation and fixed some build warnings
Enabled MT compilation for all first party TUs and some third party ones too. Disabled specific warnings in third party code, started fixing warnings in first party code as well
2024-09-11 12:03:09 +01:00
Antoine Pilote
706821861b Forgot to push shader source files changes on ui_text.shader 2024-09-11 00:14:46 -04:00
Antoine Pilote
0e78c7d889 Added serialization for UI components 2024-09-10 23:53:29 -04:00
Antoine Pilote
7a5568b513 Removed automatic mipmap generation for texture set from data buffer + exposed subpixel uniforms from text shader 2024-09-10 23:19:32 -04:00
Antoine Pilote
ebedefb6a7 Added UI component, resource & system. Now renders on screen and live reloads 2024-09-10 22:27:15 -04:00
Antoine Pilote
552fe0ee04 Removed annoying debug window 2024-09-10 19:24:24 -04:00
Antoine Pilote
2c48590a4a Added shaders for UI and fixed UI renderer 2024-09-10 19:18:29 -04:00
Antoine Pilote
1949946cdd Removed wrong submodules 2024-09-10 18:10:16 -04:00
Antoine Pilote
dcbd6d0fe3 Merge pull request #72 from WiggleWizard/feature/basiccomponentreflection
Initial reflection for components using the entt reflection API
2024-09-10 12:42:12 -04:00
WiggleWizard
ffc79ccdf4 Initial reflection for components using the entt reflection API
Currently the only system using reflection is the drop down box when clicking "Add Component" in the entity inspector. The other systems and architecture is still designed around concrete compile time typing
2024-09-10 15:53:32 +01:00
Antoine Pilote
7e341b34cf Fixed broken shader uniform caused by automatic casting from uint to int 2024-09-09 21:40:06 -04:00
Antoine Pilote
1051f0cdd3 More work 2024-09-09 21:21:47 -04:00
Antoine Pilote
aef5f65f75 Refactor Shader uniform API + Added back NuakeUI 2024-09-09 20:55:51 -04:00
Antoine Pilote
5a0f7c06f0 Added Yoga 2024-09-09 18:01:05 -04:00
Antoine Pilote
0f14e303b2 Attempt to fix kinematic not generating collision callbacks 2024-09-09 00:09:04 -04:00
Antoine Pilote
22a859b3e1 Prevent .map rebuilding during play mode 2024-09-09 00:08:45 -04:00
Antoine Pilote
e36e33aa9a Renamed exe to Nuake Engine + added C# endpoints i forgot to push 2024-09-08 23:17:51 -04:00
Antoine Pilote
f30e178e87 Added AddComponent C# API + SetGet light intensity 2024-09-08 23:17:28 -04:00
Antoine Pilote
9f09773636 Removed debug window for shadwo maps 2024-09-08 23:17:12 -04:00
Antoine Pilote
73e0498287 Fixed crash in gizmo drawer when selection is invalid 2024-09-08 23:17:02 -04:00
Antoine Pilote
13c0fb414d Fixed crash when trying to generate trenchbroom game config 2024-09-08 23:16:47 -04:00
antopilo
7c123e1c0a Made it possible to open projects directly from the .project file 2024-09-08 15:01:19 -04:00
antopilo
219c9a97cd Made project list in welcome window the same style as template list in new project wizard 2024-09-08 12:32:32 -04:00
antopilo
20ade88fd9 Added a cancel button in new project wizard 2024-09-08 12:32:05 -04:00
Antoine Pilote
6005eb51d3 Merge branch 'develop' of https://github.com/antopilo/Nuake into develop 2024-09-05 21:49:27 -04:00
Antoine Pilote
8d69094cf2 Prevented crash on isValid on entity entity 2024-09-05 21:49:11 -04:00
Antoine Pilote
5034adca8e Now exporting entities to TB on build 2024-09-05 21:48:41 -04:00
Antoine Pilote
81b69749d9 Merge pull request #71 from antopilo/trenchbroom-path-project-settings
Added .project properties to Project Settings
2024-09-05 21:42:40 -04:00
Antoine Pilote
c5563c204c Merge pull request #67 from antopilo/develop
Updated read me
2024-08-16 00:00:58 -04:00
320 changed files with 85492 additions and 53332 deletions

24
.gitmodules vendored
View File

@@ -1,15 +1,6 @@
[submodule "Nuake/dependencies/glfw"]
path = Nuake/dependencies/glfw
url = https://github.com/glfw/glfw.git
[submodule "Nuake/dependencies/assimp"]
path = Nuake/dependencies/assimp
url = https://github.com/assimp/assimp.git
[submodule "Nuake/dependencies/bullet3"]
path = Nuake/dependencies/bullet3
url = https://github.com/bulletphysics/bullet3.git
[submodule "Nuake/dependencies/glew"]
path = Nuake/dependencies/glew
url = https://github.com/nigels-com/glew.git
[submodule "Nuake/dependencies/JoltPhysics"]
path = Nuake/dependencies/JoltPhysics
url = https://github.com/antopilo/JoltPhysics.git
@@ -25,3 +16,18 @@
[submodule "Nuake/dependencies/tracy"]
path = Nuake/dependencies/tracy
url = https://github.com/wolfpld/tracy.git
[submodule "Nuake/dependencies/msdf-atlas-gen"]
path = Nuake/dependencies/msdf-atlas-gen
url = https://github.com/antopilo/msdf-atlas-gen.git
[submodule "Nuake/dependencies/yoga"]
path = Nuake/dependencies/yoga
url = https://github.com/facebook/yoga.git
[submodule "Nuake/dependencies/freetype"]
path = Nuake/dependencies/freetype
url = https://github.com/freetype/freetype.git
[submodule "Nuake/dependencies/entt"]
path = Nuake/dependencies/entt
url = https://github.com/skypjack/entt.git
[submodule "Nuake/dependencies/glfw"]
path = Nuake/dependencies/glfw
url = https://github.com/antopilo/glfw.git

View File

@@ -15,7 +15,6 @@
#include <GLFW/glfw3.h>
#include <src/Vendors/glm/trigonometric.hpp>
#include <src/Scripting/ScriptingEngine.h>
#include <src/Resource/FGD/FGDFile.h>
#include <src/Rendering/Shaders/ShaderManager.h>
#include <src/Rendering/Renderer.h>
@@ -95,6 +94,13 @@ LaunchSettings ParseLaunchSettings(const std::vector<std::string>& arguments)
launchSettings.monitor = stoi(arguments[i + 1]);
}
}
else if (argumentSize == 2 && Nuake::FileSystem::FileExists(arg))
{
if (Nuake::String::EndsWith(arg, ".project"))
{
launchSettings.projectPath = arg;
}
}
i++;
}
@@ -113,11 +119,12 @@ Nuake::Application* Nuake::CreateApplication(int argc, char** argv)
ApplicationSpecification specification
{
.Name = "Editor",
.WindowWidth = 1100,
.WindowHeight = 630,
.WindowWidth = static_cast<uint32_t>(launchSettings.resolution.x),
.WindowHeight = static_cast<uint32_t>(launchSettings.resolution.y),
.VSync = true
};
#ifdef NK_DEBUG
specification.Name += "(DEBUG BUILD)";
#endif

View File

@@ -5,7 +5,7 @@
struct LaunchSettings
{
int32_t monitor = 1;
Nuake::Vector2 resolution = { 1920, 1080 };
Nuake::Vector2 resolution = { 1100, 630 };
std::string windowTitle = "Nuake Editor ";
std::string projectPath;
};

Binary file not shown.

View File

@@ -41,7 +41,6 @@ public:
EditorSelection(const Nuake::Entity& entity)
{
Type = EditorSelectionType::Entity;
Nuake::Engine::GetCurrentScene()->m_SceneRenderer->mOutlineEntityID = (uint32_t)entity.GetHandle();
Entity = entity;
}

View File

@@ -45,7 +45,7 @@ namespace NuakeEditor
if (!FileSystem::DirectoryExists(gameConfigFolderPath))
{
FileSystem::MakeDirectory(gameConfigFolderPath);
FileSystem::MakeDirectory(gameConfigFolderPath, true);
}
const std::string& gameConfigFilePath = gameConfigFolderPath + "GameConfig.cfg";
@@ -65,7 +65,7 @@ namespace NuakeEditor
"packageformat": { "extension": ".zip", "format": "zip" }
},
"textures": {
"root": "textures",
"root": "Textures",
"extensions": [ ".jpg", ".png", ".tga" ]
},
"entities": {

View File

@@ -1,147 +0,0 @@
#pragma once
#include "ComponentPanel.h"
#include "src/FileSystem/FileSystem.h"
#include <src/Core/Maths.h>
#include <src/Scene/Components/AudioEmitterComponent.h>
#include <src/Scene/Entities/ImGuiHelper.h>
class AudioEmitterPanel : ComponentPanel
{
public:
AudioEmitterPanel() = default;
~AudioEmitterPanel() = default;
void Draw(Nuake::Entity entity) override
{
using namespace Nuake;
if (!entity.HasComponent<AudioEmitterComponent>())
return;
auto& component = entity.GetComponent<AudioEmitterComponent>();
BeginComponentTable(AUDIO EMITTER, AudioEmitterComponent);
{
{
ImGui::Text("Audio File");
ImGui::TableNextColumn();
std::string path = component.FilePath;
ImGui::Button(component.FilePath.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0));
if (ImGui::BeginDragDropTarget())
{
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_AudioFile"))
{
char* file = (char*)payload->Data;
std::string fullPath = std::string(file, 256);
path = Nuake::FileSystem::AbsoluteToRelative(fullPath);
component.FilePath = path;
}
ImGui::EndDragDropTarget();
}
ImGui::TableNextColumn();
ComponentTableReset(component.FilePath, "");
}
ImGui::TableNextColumn();
{
ImGui::Text("Playing");
ImGui::TableNextColumn();
UI::ToggleButton("##Player", &component.IsPlaying);
//ImGui::Checkbox("##Playing", &component.IsPlaying);
ImGui::TableNextColumn();
ComponentTableReset(component.IsPlaying, false);
}
ImGui::TableNextColumn();
{
ImGui::Text("Loop");
ImGui::TableNextColumn();
ImGui::Checkbox("##Loop", &component.Loop);
ImGui::TableNextColumn();
ComponentTableReset(component.Loop, false);
}
ImGui::TableNextColumn();
{
ImGui::Text("Volume");
ImGui::TableNextColumn();
ImGui::DragFloat("##Volume", &component.Volume, 0.001f, 0.0f, 2.0f);
ImGui::TableNextColumn();
ComponentTableReset(component.Volume, 1.0f);
}
ImGui::TableNextColumn();
{
ImGui::Text("Playback Speed");
ImGui::TableNextColumn();
ImGui::DragFloat("##PlaybackSpeed", &component.PlaybackSpeed, 0.01f, 0.0001f);
ImGui::TableNextColumn();
ComponentTableReset(component.PlaybackSpeed, 1.0f);
}
ImGui::TableNextColumn();
{
ImGui::Text("Pan");
ImGui::TableNextColumn();
ImGui::DragFloat("##Pan", &component.Pan, 0.01f, -1.0f, 1.0f);
ImGui::TableNextColumn();
ComponentTableReset(component.Pan, 0.0f);
}
ImGui::TableNextColumn();
{
ImGui::Text("Spatialized");
ImGui::TableNextColumn();
ImGui::Checkbox("##Spatialized", &component.Spatialized);
ImGui::TableNextColumn();
ComponentTableReset(component.Spatialized, false);
}
if (component.Spatialized)
{
ImGui::TableNextColumn();
{
ImGui::Text("Min Distance");
ImGui::TableNextColumn();
ImGui::DragFloat("##minDistance", &component.MinDistance, 0.001f, 0.0f);
ImGui::TableNextColumn();
ComponentTableReset(component.MinDistance, 1.0f);
}
ImGui::TableNextColumn();
{
ImGui::Text("Max Distance");
ImGui::TableNextColumn();
ImGui::DragFloat("##maxDistance", &component.MaxDistance, 0.001f, 0.0f);
ImGui::TableNextColumn();
ComponentTableReset(component.MaxDistance, 10.0f);
}
ImGui::TableNextColumn();
{
ImGui::Text("Attenuation Factor");
ImGui::TableNextColumn();
ImGui::DragFloat("##attenuationFactor", &component.AttenuationFactor, 0.001f, 0.0f);
ImGui::TableNextColumn();
ComponentTableReset(component.AttenuationFactor, 1.0f);
}
}
}
EndComponentTable();
}
};

View File

@@ -6,19 +6,20 @@
#include <src/Scene/Components/BoneComponent.h>
#include <src/Scene/Entities/ImGuiHelper.h>
class BonePanel : ComponentPanel
class BonePanel
{
public:
BonePanel() {}
void Draw(Nuake::Entity entity) override
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
{
using namespace Nuake;
if (!entity.HasComponent<BoneComponent>())
Nuake::BoneComponent* componentPtr = componentInstance.try_cast<Nuake::BoneComponent>();
if (componentPtr == nullptr)
{
return;
auto& component = entity.GetComponent<BoneComponent>();
}
Nuake::BoneComponent& component = *componentPtr;
BeginComponentTable(BONE, BoneComponent);
{
{

View File

@@ -3,17 +3,20 @@
#include <src/Scene/Components/CameraComponent.h>
#include "src/FileSystem/FileSystem.h"
class CameraPanel : ComponentPanel {
class CameraPanel {
public:
CameraPanel() {}
void Draw(Nuake::Entity entity) override
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
{
if (!entity.HasComponent<Nuake::CameraComponent>())
using namespace Nuake;
Nuake::CameraComponent* componentPtr = componentInstance.try_cast<Nuake::CameraComponent>();
if (componentPtr == nullptr)
{
return;
auto& component = entity.GetComponent<Nuake::CameraComponent>();
}
Nuake::CameraComponent& component = *componentPtr;
BeginComponentTable(CAMERA, Nuake::CameraComponent);
{
{

View File

@@ -3,48 +3,47 @@
#include <src/Scene/Components/CapsuleColliderComponent.h>
class CapsuleColliderPanel : ComponentPanel
class CapsuleColliderPanel
{
public:
CapsuleColliderPanel() = default;
void Draw(Nuake::Entity entity) override
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
{
using namespace Nuake;
if (!entity.HasComponent<CapsuleColliderComponent>())
Nuake::CapsuleColliderComponent* componentPtr = componentInstance.try_cast<Nuake::CapsuleColliderComponent>();
if (componentPtr == nullptr)
{
return;
}
auto& [Capsule, Radius, Height, IsTrigger] = entity.GetComponent<CapsuleColliderComponent>();
Nuake::CapsuleColliderComponent& component = *componentPtr;
BeginComponentTable(CAPSULE COLLIDER, CapsuleColliderComponent)
{
{
ImGui::Text("Radius");
ImGui::TableNextColumn();
ImGui::DragFloat("##Radius", &Radius, 0.01f, 0.001f);
Radius = std::max(Radius, 0.001f);
ImGui::DragFloat("##Radius", &component.Radius, 0.01f, 0.001f);
component.Radius = std::max(component.Radius, 0.001f);
ImGui::TableNextColumn();
ComponentTableReset(Radius, 0.5f)
ComponentTableReset(component.Radius, 0.5f)
}
ImGui::TableNextColumn();
{
ImGui::Text("Height");
ImGui::TableNextColumn();
ImGui::DragFloat("##Height", &Height, 0.01f, 0.001f);
Height = std::max(Height, 0.001f);
ImGui::DragFloat("##Height", &component.Height, 0.01f, 0.001f);
component.Height = std::max(component.Height, 0.001f);
ImGui::TableNextColumn();
ComponentTableReset(Height, 1.0f)
ComponentTableReset(component.Height, 1.0f)
}
ImGui::TableNextColumn();
{
ImGui::Text("Is Trigger");
ImGui::TableNextColumn();
ImGui::Checkbox("##isTrigger", &IsTrigger);
ImGui::Checkbox("##isTrigger", &component.IsTrigger);
ImGui::TableNextColumn();
ComponentTableReset(IsTrigger, false);
ComponentTableReset(component.IsTrigger, false);
}
}
EndComponentTable()

View File

@@ -3,18 +3,20 @@
#include <src/Scene/Components/CharacterControllerComponent.h>
#include "src/FileSystem/FileSystem.h"
class CharacterControllerPanel : ComponentPanel {
class CharacterControllerPanel
{
public:
CharacterControllerPanel() {}
void Draw(Nuake::Entity entity) override
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
{
if (!entity.HasComponent<Nuake::CharacterControllerComponent>())
return;
using namespace Nuake;
auto& component = entity.GetComponent<Nuake::CharacterControllerComponent>();
Nuake::CharacterControllerComponent* componentPtr = componentInstance.try_cast<Nuake::CharacterControllerComponent>();
if (componentPtr == nullptr)
{
return;
}
Nuake::CharacterControllerComponent& component = *componentPtr;
BeginComponentTable(CHARACTER CONTROLLER, Nuake::CharacterControllerComponent);
{
{
@@ -50,7 +52,7 @@ public:
{
ImGui::Text("Stick to floor step down");
ImGui::TableNextColumn();
ImGui::DragFloat("##StickToFloorStepDown", &component.StickToFloorStepDown.y, -10.0f, 0.01, 0.0f);
ImGui::DragFloat("##StickToFloorStepDown", &component.StickToFloorStepDown.y, -10.0f, 0.01f, 0.0f);
ImGui::TableNextColumn();
ComponentTableReset(component.StickToFloorStepDown.y, -0.5f);
}
@@ -58,7 +60,7 @@ public:
{
ImGui::Text("Step down extra");
ImGui::TableNextColumn();
ImGui::DragFloat("##StepDownExtra", &component.StepDownExtra.y, -10.0f, 0.01, 0.0f);
ImGui::DragFloat("##StepDownExtra", &component.StepDownExtra.y, -10.0f, 0.01f, 0.0f);
ImGui::TableNextColumn();
ComponentTableReset(component.StepDownExtra.y, 0.0f);
}
@@ -66,7 +68,7 @@ public:
{
ImGui::Text("Step up");
ImGui::TableNextColumn();
ImGui::DragFloat("##StepUp", &component.SteppingStepUp.y, 0.0f, 0.01, 10.0f);
ImGui::DragFloat("##StepUp", &component.SteppingStepUp.y, 0.0f, 0.01f, 10.0f);
ImGui::TableNextColumn();
ComponentTableReset(component.SteppingStepUp.y, 0.4f);
}

View File

@@ -26,7 +26,7 @@ ImGui::Text(##name);
bool removed = false; \
bool headerOpened = ImGui::CollapsingHeader(#name, ImGuiTreeNodeFlags_DefaultOpen); \
ImGui::PopStyleVar(); \
if (#name != "TRANSFORM" && ImGui::BeginPopupContextItem()) \
if (strcmp(#name, "TRANSFORM") != 0 && ImGui::BeginPopupContextItem()) \
{ \
if (ImGui::Selectable("Remove")) { removed = true; } \
ImGui::EndPopup(); \
@@ -42,7 +42,7 @@ ImGui::Text(##name);
{ \
delete boldFont; \
ImGui::PopStyleVar(); \
ImGui::Indent(); \
ImGui::Indent(); \
if (ImGui::BeginTable(#name, 3, ImGuiTableFlags_SizingStretchProp)) \
{ \
ImGui::TableSetupColumn("name", 0, 0.25f); \
@@ -93,5 +93,7 @@ ImGui::Text(##name);
class ComponentPanel {
public:
virtual void Draw(Nuake::Entity entity) = 0;
};
virtual void Draw(Nuake::Entity entity);
};
inline void ComponentPanel::Draw(Nuake::Entity entity) {}

View File

@@ -3,48 +3,47 @@
#include <src/Scene/Components/CylinderColliderComponent.h>
class CylinderColliderPanel : ComponentPanel
class CylinderColliderPanel
{
public:
CylinderColliderPanel() = default;
void Draw(Nuake::Entity entity) override
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
{
using namespace Nuake;
if (!entity.HasComponent<CylinderColliderComponent>())
Nuake::CylinderColliderComponent* componentPtr = componentInstance.try_cast<Nuake::CylinderColliderComponent>();
if (componentPtr == nullptr)
{
return;
}
auto& [Cylinder, Radius, Height, IsTrigger] = entity.GetComponent<CylinderColliderComponent>();
Nuake::CylinderColliderComponent& component = *componentPtr;
BeginComponentTable(CYLINDER COLLIDER, CylinderColliderComponent)
{
{
ImGui::Text("Radius");
ImGui::TableNextColumn();
ImGui::DragFloat("##Radius", &Radius, 0.01f, 0.001f);
Radius = std::max(Radius, 0.001f);
ImGui::DragFloat("##Radius", &component.Radius, 0.01f, 0.001f);
component.Radius = std::max(component.Radius, 0.001f);
ImGui::TableNextColumn();
ComponentTableReset(Radius, 0.5f)
ComponentTableReset(component.Radius, 0.5f)
}
ImGui::TableNextColumn();
{
ImGui::Text("Height");
ImGui::TableNextColumn();
ImGui::DragFloat("##Height", &Height, 0.01f, 0.0001f);
Height = std::max(Height, 0.001f);
ImGui::DragFloat("##Height", &component.Height, 0.01f, 0.0001f);
component.Height = std::max(component.Height, 0.001f);
ImGui::TableNextColumn();
ComponentTableReset(Height, 1.0f)
ComponentTableReset(component.Height, 1.0f)
}
ImGui::TableNextColumn();
{
ImGui::Text("Is Trigger");
ImGui::TableNextColumn();
ImGui::Checkbox("##isTrigger", &IsTrigger);
ImGui::Checkbox("##isTrigger", &component.IsTrigger);
ImGui::TableNextColumn();
ComponentTableReset(IsTrigger, false);
ComponentTableReset(component.IsTrigger, false);
}
}
EndComponentTable()

View File

@@ -2,17 +2,18 @@
#include "ComponentPanel.h"
#include "src/Scene/Components/LightComponent.h"
class LightPanel :ComponentPanel {
class LightPanel
{
public:
LightPanel() { }
void Draw(Nuake::Entity entity) override
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
{
if (!entity.HasComponent<Nuake::LightComponent>())
return;
Nuake::LightComponent& component = entity.GetComponent<Nuake::LightComponent>();
Nuake::LightComponent* componentPtr = componentInstance.try_cast<Nuake::LightComponent>();
if (componentPtr == nullptr)
{
return;
}
Nuake::LightComponent& component = *componentPtr;
BeginComponentTable(LIGHT, Nuake::LightComponent);
{

View File

@@ -9,23 +9,25 @@
#include <src/Resource/ResourceLoader.h>
#include <src/Core/String.h>
class MeshColliderPanel : ComponentPanel {
private:
Scope<ModelResourceInspector> _modelInspector;
bool _expanded = false;
class MeshColliderPanel : ComponentPanel
{
public:
MeshColliderPanel()
{
CreateScope<ModelResourceInspector>();
}
void Draw(Nuake::Entity entity) override
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
{
using namespace Nuake;
if (!entity.HasComponent<MeshColliderComponent>())
Nuake::MeshColliderComponent* componentPtr = componentInstance.try_cast<Nuake::MeshColliderComponent>();
if (componentPtr == nullptr)
{
return;
MeshColliderComponent& component = entity.GetComponent<MeshColliderComponent>();
}
Nuake::MeshColliderComponent& component = *componentPtr;
BeginComponentTable(MESH, MeshColliderComponent);
{
ImGui::Text("Model");

View File

@@ -26,13 +26,17 @@ public:
CreateScope<ModelResourceInspector>();
}
void Draw(Nuake::Entity entity) override
void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
{
using namespace Nuake;
if (!entity.HasComponent<ModelComponent>())
Nuake::ModelComponent* componentPtr = componentInstance.try_cast<Nuake::ModelComponent>();
if (componentPtr == nullptr)
{
return;
ModelComponent& component = entity.GetComponent<ModelComponent>();
}
Nuake::ModelComponent& component = *componentPtr;
BeginComponentTable(MESH, ModelComponent);
{
ImGui::Text("Model");

View File

@@ -3,24 +3,25 @@
#include <src/Scene/Entities/ImGuiHelper.h>
#include <src/Scene/Components/NavMeshVolumeComponent.h>
#include "src/AI/NavManager.h"
#include "src/Scene/Components/QuakeMap.h"
#include <src/Core/Maths.h>
#include <src/AI/RecastConfig.h>
class NavMeshVolumePanel : ComponentPanel {
class NavMeshVolumePanel
{
public:
NavMeshVolumePanel() {}
void Draw(Nuake::Entity entity) override
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
{
using namespace Nuake;
if (!entity.HasComponent<NavMeshVolumeComponent>())
Nuake::NavMeshVolumeComponent* componentPtr = componentInstance.try_cast<Nuake::NavMeshVolumeComponent>();
if (componentPtr == nullptr)
{
return;
}
auto& component = entity.GetComponent<NavMeshVolumeComponent>();
Nuake::NavMeshVolumeComponent& component = *componentPtr;
BeginComponentTable(NAVMESH VOLUME, NavMeshVolumeComponent);
{
{
@@ -384,4 +385,4 @@ public:
}
EndComponentTable();
}
};
};

View File

@@ -8,13 +8,50 @@
#include <src/Scene/Components/NetScriptComponent.h>
#include <src/Scene/Entities/ImGuiHelper.h>
const std::string NET_TEMPLATE_SCRIPT_FIRST = R"(using Nuake.Net;
void NetScriptPanel::Draw(Nuake::Entity entity)
namespace NuakeShowcase
{
if (!entity.HasComponent<Nuake::NetScriptComponent>())
return;
class )";
auto& component = entity.GetComponent<Nuake::NetScriptComponent>();
const std::string NET_TEMPLATE_SCRIPT_SECOND = R"( : Entity
{
public override void OnInit()
{
// Called once at the start of the game
}
public override void OnUpdate(float dt)
{
// Called every frame
}
public override void OnFixedUpdate(float dt)
{
// Called every fixed update
}
public override void OnDestroy()
{
// Called at the end of the game fixed update
}
}
}
)";
void NetScriptPanel::Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
{
using namespace Nuake;
Nuake::NetScriptComponent* componentPtr = componentInstance.try_cast<Nuake::NetScriptComponent>();
if (componentPtr == nullptr)
{
return;
}
Nuake::NetScriptComponent& component = *componentPtr;
BeginComponentTable(.NETSCRIPT, Nuake::NetScriptComponent);
{
{
@@ -178,10 +215,14 @@ void NetScriptPanel::Draw(Nuake::Entity entity)
field.Value = field.DefaultValue;
}
bool currentValue = std::any_cast<bool>(field.Value);
const std::string sliderName = "##" + field.Name + "slider";
ImGui::Checkbox(sliderName.c_str(), &currentValue);
field.Value = currentValue;
auto typeName = field.Value.type().name();
if (typeName == std::string("bool"))
{
bool currentValue = std::any_cast<bool>(field.Value);
const std::string sliderName = "##" + field.Name + "slider";
ImGui::Checkbox(sliderName.c_str(), &currentValue);
field.Value = currentValue;
}
}
if (field.Type == Nuake::NetScriptExposedVarType::String)

View File

@@ -1,45 +1,9 @@
#pragma once
#include "ComponentPanel.h"
const std::string NET_TEMPLATE_SCRIPT_FIRST = R"(using Nuake.Net;
namespace NuakeShowcase
class NetScriptPanel
{
class )";
const std::string NET_TEMPLATE_SCRIPT_SECOND = R"( : Entity
{
public override void OnInit()
{
// Called once at the start of the game
}
public override void OnUpdate(float dt)
{
// Called every frame
}
public override void OnFixedUpdate(float dt)
{
// Called every fixed update
}
public override void OnDestroy()
{
// Called at the end of the game fixed update
}
}
}
)";
class NetScriptPanel : ComponentPanel {
public:
NetScriptPanel() {}
void Draw(Nuake::Entity entity) override;
static void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance);
};

View File

@@ -1,155 +0,0 @@
#pragma once
#include "ComponentPanel.h"
#include "src/FileSystem/FileSystem.h"
#include <src/Core/Maths.h>
#include <src/Scene/Components/ParticleEmitterComponent.h>
#include <src/Scene/Entities/ImGuiHelper.h>
#include "MaterialEditor.h"
#include <src/Resource/ResourceLoader.h>
#include <src/Resource/ResourceLoader.h>
class ParticleEmitterPanel : ComponentPanel
{
public:
Scope<ModelResourceInspector> _modelInspector;
ParticleEmitterPanel() {}
void Draw(Nuake::Entity entity) override
{
if (!entity.HasComponent<Nuake::ParticleEmitterComponent>())
return;
auto& component = entity.GetComponent<Nuake::ParticleEmitterComponent>();
BeginComponentTable(PARTICLE EMITTER, Nuake::ParticleEmitterComponent);
{
{
ImGui::Text("Particle Material");
ImGui::TableNextColumn();
std::string label = "Empty";
if (component.ParticleMaterial && !component.ParticleMaterial->Path.empty())
{
label = component.ParticleMaterial->Path;
}
if (ImGui::Button(label.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0)))
{
}
if (ImGui::BeginDragDropTarget())
{
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Material"))
{
char* file = (char*)payload->Data;
std::string fullPath = std::string(file, 256);
fullPath = Nuake::FileSystem::AbsoluteToRelative(fullPath);
Ref<Nuake::Material> material = Nuake::ResourceLoader::LoadMaterial(fullPath);
component.ParticleMaterial = material;
}
ImGui::EndDragDropTarget();
}
//std::string childId = "materialEditorParticle";
//ImGui::BeginChild(childId.c_str(), ImVec2(0, 0), false);
//{
// MaterialEditor editor;
// editor.Draw(component.ParticleMaterial);
//}
//ImGui::EndChild();
ImGui::TableNextColumn();
//ComponentTableReset(component.ParticleColor, Nuake::Vector4(1, 1, 1, 1));
}
ImGui::TableNextColumn();
{
ImGui::Text("Amount");
ImGui::TableNextColumn();
ImGui::DragFloat("##ParticleAmount", &component.Amount, 0.1f, 0.0f, 500.0f);
ImGui::TableNextColumn();
ComponentTableReset(component.Amount, 10.0f);
}
ImGui::TableNextColumn();
{
ImGui::Text("Particle Scale");
ImGui::TableNextColumn();
ImGuiHelper::DrawVec3("##particleSize", &component.ParticleScale);
ImGui::TableNextColumn();
ComponentTableReset(component.ParticleScale, Nuake::Vector3(0.1, 0.1, 0.1));
}
ImGui::TableNextColumn();
{
ImGui::Text("Particle Scale Random");
ImGui::TableNextColumn();
ImGui::DragFloat("##particleSizeRandom", &component.ScaleRandomness, 0.01f, 0.0f);
ImGui::TableNextColumn();
ComponentTableReset(component.ScaleRandomness, 0.0f);
}
ImGui::TableNextColumn();
{
ImGui::Text("Global Space");
ImGui::TableNextColumn();
ImGui::Checkbox("##globalSpace", &component.GlobalSpace);
ImGui::TableNextColumn();
ComponentTableReset(component.GlobalSpace, false);
}
ImGui::TableNextColumn();
{
ImGui::Text("Rate");
ImGui::TableNextColumn();
ImGui::DragFloat("##ParticleRate", &component.Rate, 0.1f, 0.0f, 10.0f);
ImGui::TableNextColumn();
ComponentTableReset(component.Rate, 0.0f);
}
ImGui::TableNextColumn();
{
ImGui::Text("Life");
ImGui::TableNextColumn();
ImGui::DragFloat("##ParticleLife", &component.Life, 0.1f, 0.0f, 100.0f);
ImGui::TableNextColumn();
ComponentTableReset(component.Life, 5.0f);
}
ImGui::TableNextColumn();
{
ImGui::Text("Gravity");
ImGui::TableNextColumn();
ImGuiHelper::DrawVec3("Gravity", &component.Gravity);
ImGui::TableNextColumn();
ComponentTableReset(component.Gravity, Nuake::Vector3(0, -1, 0));
}
ImGui::TableNextColumn();
{
ImGui::Text("Gravity Random");
ImGui::TableNextColumn();
ImGui::DragFloat("##GravityRandom", &component.GravityRandom, 0.01f, 0.0f, 1.0f);
ImGui::TableNextColumn();
ComponentTableReset(component.GravityRandom, 0.0f);
}
ImGui::TableNextColumn();
{
ImGui::Text("Radius");
ImGui::TableNextColumn();
ImGui::DragFloat("##ParticleRadius", &component.Radius, 0.01f, 0.0f, 10.0f);
ImGui::TableNextColumn();
ComponentTableReset(component.Radius, 1.0f);
}
}
EndComponentTable();
}
};

View File

@@ -1,79 +0,0 @@
#pragma once
#include "ComponentPanel.h"
#include <src/Scene/Components/QuakeMap.h>
#include "src/Scene/Systems/QuakeMapBuilder.h"
#include "src/FileSystem/FileSystem.h"
#include <src/AI/NavManager.h>
#include <src/UI/ImUI.h>
class QuakeMapPanel : ComponentPanel {
public:
QuakeMapPanel() {}
void Draw(Nuake::Entity entity) override
{
using namespace Nuake;
if (!entity.HasComponent<Nuake::QuakeMapComponent>())
return;
Nuake::QuakeMapComponent& component = entity.GetComponent<Nuake::QuakeMapComponent>();
BeginComponentTable(QUAKEMAP, Nuake::QuakeMapComponent);
{
{
ImGui::Text("Map");
ImGui::TableNextColumn();
std::string path = component.Path;
ImGui::Button(component.Path.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0));
if (ImGui::BeginDragDropTarget())
{
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Map"))
{
char* file = (char*)payload->Data;
std::string fullPath = std::string(file, 256);
path = Nuake::FileSystem::AbsoluteToRelative(fullPath);
component.Path = path;
}
ImGui::EndDragDropTarget();
}
ImGui::TableNextColumn();
ComponentTableReset(component.Path, "");
}
ImGui::TableNextColumn();
{
ImGui::Text("Collision");
ImGui::TableNextColumn();
ImGui::Checkbox("##Collison", &component.HasCollisions);
ImGui::TableNextColumn();
ComponentTableReset(component.HasCollisions, true);
}
ImGui::TableNextColumn();
{
ImGui::Text("Auto Rebuild");
ImGui::TableNextColumn();
ImGui::Checkbox("##AutoRebuild", &component.AutoRebuild);
ImGui::TableNextColumn();
ComponentTableReset(component.AutoRebuild, false);
}
ImGui::TableNextColumn();
{
ImGui::Text("Build");
ImGui::TableNextColumn();
if (UI::SecondaryButton("Build Geometry"))
{
Nuake::QuakeMapBuilder builder;
builder.BuildQuakeMap(entity, component.HasCollisions);
}
}
}
EndComponentTable();
}
};

View File

@@ -1,62 +0,0 @@
#pragma once
#include "ComponentPanel.h"
#include <src/Scene/Components/RigidbodyComponent.h>
#include "src/FileSystem/FileSystem.h"
class RigidbodyPanel : ComponentPanel {
public:
RigidbodyPanel() {}
void Draw(Nuake::Entity entity) override
{
if (!entity.HasComponent<Nuake::RigidBodyComponent>())
return;
auto& component = entity.GetComponent<Nuake::RigidBodyComponent>();
BeginComponentTable(RIGIDBODY, Nuake::RigidBodyComponent);
{
{
ImGui::Text("Mass");
ImGui::TableNextColumn();
ImGui::DragFloat("##Mass", &component.Mass, 0.01f, 0.1f);
component.Mass = std::max(component.Mass, 0.0f);
ImGui::TableNextColumn();
ComponentTableReset(component.Mass, 0.0f);
}
ImGui::TableNextColumn();
{
ImGui::Text("Lock X axis");
ImGui::TableNextColumn();
ImGui::Checkbox("##lockx", &component.LockX);
ImGui::TableNextColumn();
ComponentTableReset(component.LockX, false);
}
ImGui::TableNextColumn();
{
ImGui::Text("Lock Y axis");
ImGui::TableNextColumn();
ImGui::Checkbox("##locky", &component.LockY);
ImGui::TableNextColumn();
ComponentTableReset(component.LockY, false);
}
ImGui::TableNextColumn();
{
ImGui::Text("Lock Z axis");
ImGui::TableNextColumn();
ImGui::Checkbox("##lockz", &component.LockZ);
ImGui::TableNextColumn();
ComponentTableReset(component.LockZ, false);
}
ImGui::TableNextColumn();
}
EndComponentTable();
}
};

View File

@@ -1,115 +0,0 @@
#include "ScriptPanel.h"
#include "../Windows/FileSystemUI.h"
#include <src/Scene/Components/WrenScriptComponent.h>
#include "src/FileSystem/FileDialog.h"
#include "src/FileSystem/FileSystem.h"
void ScriptPanel::Draw(Nuake::Entity entity)
{
if (!entity.HasComponent<Nuake::WrenScriptComponent>())
return;
Nuake::WrenScriptComponent& component = entity.GetComponent<Nuake::WrenScriptComponent>();
BeginComponentTable(SCRIPT, Nuake::WrenScriptComponent);
{
{
ImGui::Text("Script");
ImGui::TableNextColumn();
std::string path = component.Script;
ImGui::Button( path.empty() ? "Create New" : component.Script.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0));
if (ImGui::BeginDragDropTarget())
{
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Script"))
{
char* file = (char*)payload->Data;
std::string fullPath = std::string(file, 512);
path = Nuake::FileSystem::AbsoluteToRelative(std::move(fullPath));
component.LoadScript(path);
}
ImGui::EndDragDropTarget();
}
component.Script = path;
// Double click on file
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0))
{
if(!component.Script.empty())
{
if (component.mWrenScript)
{
Nuake::OS::OpenIn(component.mWrenScript->GetFile()->GetAbsolutePath());
}
}
else
{
// TODO: Turn into command (Undo/Redo)
std::string pathCreation = Nuake::FileDialog::SaveFile("*.wren");
if (!pathCreation.empty())
{
if (!Nuake::String::EndsWith(pathCreation, ".wren"))
{
pathCreation += ".wren";
}
std::string fileName = Nuake::String::ToUpper(Nuake::FileSystem::GetFileNameFromPath(pathCreation));
fileName = Nuake::String::RemoveWhiteSpace(fileName);
if(!Nuake::String::IsDigit(fileName[0]))
{
Nuake::FileSystem::BeginWriteFile(pathCreation);
Nuake::FileSystem::WriteLine(TEMPLATE_SCRIPT_FIRST + fileName + TEMPLATE_SCRIPT_SECOND);
Nuake::FileSystem::EndWriteFile();
path = Nuake::FileSystem::AbsoluteToRelative(pathCreation);
Nuake::FileSystem::Scan();
Nuake::FileSystemUI::m_CurrentDirectory = Nuake::FileSystem::RootDirectory;
component.LoadScript(path);
component.Script = path;
}
else
{
Nuake::Logger::Log("Cannot create script files that starts with a number.","fileSystem", Nuake::CRITICAL);
}
}
}
}
ImGui::TableNextColumn();
ComponentTableReset(component.Script, "");
}
ImGui::TableNextColumn();
{
ImGui::Text("Module");
ImGui::TableNextColumn();
// Here we create a dropdown for every modules
auto& wrenScript = component.mWrenScript;
if (wrenScript)
{
auto modules = wrenScript->GetModules();
std::vector<const char*> modulesC;
for (auto& m : modules)
{
modulesC.push_back(m.c_str());
}
static int currentModule = (int)component.mModule;
ImGui::Combo("##WrenModule", &currentModule, &modulesC[0], modules.size());
component.mModule = currentModule;
}
ImGui::TableNextColumn();
//ComponentTableReset(component.Class, "");
}
}
EndComponentTable();
}

View File

@@ -1,43 +0,0 @@
#pragma once
#include "ComponentPanel.h"
const std::string TEMPLATE_SCRIPT_FIRST = R"(import "Nuake:Engine" for Engine
import "Nuake:ScriptableEntity" for ScriptableEntity
import "Nuake:Input" for Input
import "Nuake:Math" for Vector3, Math
import "Nuake:Scene" for Scene
class )";
const std::string TEMPLATE_SCRIPT_SECOND = R"( is ScriptableEntity {
construct new() {
}
// Called when the scene gets initialized
init() {
// Engine.Log("Hello World!")
}
// Called every update
update(ts) {
}
// Called 90 times per second
fixedUpdate(ts) {
}
// Called on shutdown
exit() {
}
}
)";
class ScriptPanel : ComponentPanel {
public:
ScriptPanel() {}
void Draw(Nuake::Entity entity) override;
};

View File

@@ -0,0 +1,132 @@
#pragma once
#include <src/Core/Core.h>
#include "ComponentPanel.h"
#include "ModelResourceInspector.h"
#include "../Misc/PopupHelper.h"
#include <src/Scene/Entities/ImGuiHelper.h>
#include <src/Scene/Components/SkinnedModelComponent.h>
#include <src/Resource/ResourceLoader.h>
#include <src/Resource/ResourceManager.h>
#include <src/Core/String.h>
#include <src/Resource/ModelLoader.h>
class SkinnedMeshPanel : ComponentPanel
{
private:
Scope<ModelResourceInspector> _modelInspector;
bool _expanded = false;
std::string _importedPathMesh;
public:
SkinnedMeshPanel()
{
CreateScope<ModelResourceInspector>();
}
void Draw(Nuake::Entity& entity, entt::meta_any& componentInstance)
{
using namespace Nuake;
Nuake::SkinnedModelComponent* componentPtr = componentInstance.try_cast<Nuake::SkinnedModelComponent>();
if (componentPtr == nullptr)
{
return;
}
Nuake::SkinnedModelComponent& component = *componentPtr;
BeginComponentTable(SKINNED MESH, SkinnedModelComponent);
{
ImGui::Text("Model");
ImGui::TableNextColumn();
std::string label = "None";
const bool isModelNone = component.ModelResource == nullptr;
if (!isModelNone)
{
label = std::to_string(component.ModelResource->ID);
}
if (ImGui::Button(label.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0)))
{
if (!isModelNone)
{
if (!_expanded)
{
//_modelInspector = CreateScope<ModelResourceInspector>(component.ModelResource);
}
_expanded = !_expanded;
}
}
if (_expanded)
{
//_modelInspector->Draw();
}
bool shouldConvert = false;
if (ImGui::BeginDragDropTarget())
{
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Model"))
{
char* file = (char*)payload->Data;
std::string fullPath = std::string(file, 256);
fullPath = Nuake::FileSystem::AbsoluteToRelative(fullPath);
if (Nuake::String::EndsWith(fullPath, ".mesh"))
{
//component.ModelPath = fullPath;
//component.ModelResource = ResourceLoader::LoadModel(fullPath);
}
else
{
// Convert to .Model
Ref<Nuake::File> resourceFile = FileSystem::GetFile(fullPath);
component.ModelPath = resourceFile;
component.LoadModel((entt::entity)entity.GetHandle(), entity.GetScene());
_importedPathMesh = fullPath;
auto loader = ModelLoader();
auto modelResource = loader.LoadModel(fullPath);
shouldConvert = true;
}
}
ImGui::EndDragDropTarget();
}
//if (PopupHelper::DefineConfirmationDialog("##ConvertAsset", "Convert Asset"))
//{
// // Convert to disk
// auto loader = ModelLoader();
// Ref<Model> modelResource = loader.LoadModel(_importedPathMesh);
// json serializedData = modelResource->SerializeData();
// const std::string exportedMeshPath = _importedPathMesh + ".mesh";
// FileSystem::BeginWriteFile(exportedMeshPath);
// FileSystem::WriteLine(serializedData.dump());
// FileSystem::EndWriteFile();
// ResourceManager::RegisterResource(modelResource);
// // Update component
// component.ModelPath = exportedMeshPath;
// component.ModelResource = modelResource;
//}
//if (shouldConvert)
//{
// PopupHelper::OpenPopup("##ConvertAsset");
//}
ImGui::TableNextColumn();
//ComponentTableReset(component.ModelPath, "");
}
EndComponentTable();
}
};

View File

@@ -1,172 +0,0 @@
#pragma once
#include <src/Core/Core.h>
#include "ComponentPanel.h"
#include "ModelResourceInspector.h"
#include <src/Scene/Entities/ImGuiHelper.h>
#include <src/Scene/Components/SkinnedModelComponent.h>
#include <src/Resource/ResourceLoader.h>
#include <src/Core/String.h>
class SkinnedModelPanel : ComponentPanel
{
private:
Scope<ModelResourceInspector> m_ModelInspector;
bool m_Expanded = false;
std::string m_QueuedModelPath;
public:
SkinnedModelPanel()
{
CreateScope<ModelResourceInspector>();
}
void Draw(Nuake::Entity entity) override
{
using namespace Nuake;
if (!entity.HasComponent<SkinnedModelComponent>())
return;
SkinnedModelComponent& component = entity.GetComponent<SkinnedModelComponent>();
BeginComponentTable(SKINNED MESH, SkinnedModelComponent);
{
ImGui::Text("Model");
ImGui::TableNextColumn();
std::string label = "None";
const bool isModelNone = component.ModelResource == nullptr;
if (!isModelNone)
{
label = std::to_string(component.ModelResource->ID);
}
if (ImGui::Button(label.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0)))
{
}
if (m_Expanded)
{
m_ModelInspector->Draw();
}
if (ImGui::BeginDragDropTarget())
{
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Model"))
{
char* file = (char*)payload->Data;
std::string fullPath = std::string(file, 256);
fullPath = Nuake::FileSystem::AbsoluteToRelative(fullPath);
if (Nuake::String::EndsWith(fullPath, ".model"))
{
}
else
{
m_QueuedModelPath = fullPath;
ImGui::OpenPopup("Create Skeleton");
}
}
ImGui::EndDragDropTarget();
}
if (ImGui::BeginPopupModal("Create Skeleton", NULL, ImGuiWindowFlags_AlwaysAutoResize))
{
ImGui::SetItemDefaultFocus();
ImGui::Text("Would you like to create the skeleton structure in the scene tree?");
ImGui::Separator();
if (ImGui::Button("OK", ImVec2(120, 0)))
{
component.ModelPath = m_QueuedModelPath;
component.LoadModel();
Scene* scene = entity.GetScene();
scene->CreateSkeleton(entity);
ImGui::CloseCurrentPopup();
}
ImGui::SetItemDefaultFocus();
ImGui::SameLine();
if (ImGui::Button("Cancel", ImVec2(120, 0)))
{
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
ImGui::TableNextColumn();
ComponentTableReset(component.ModelPath, "");
if (component.ModelResource)
{
auto& model = component.ModelResource;
ImGui::TableNextColumn();
{
ImGui::Text("Playing");
ImGui::TableNextColumn();
ImGui::Checkbox("##playing", &model->IsPlaying);
ImGui::TableNextColumn();
ComponentTableReset(model->IsPlaying, true);
ImGui::TableNextColumn();
}
if(model->GetCurrentAnimation())
{
ImGui::Text("Animation");
ImGui::TableNextColumn();
uint32_t animIndex = model->GetCurrentAnimationIndex();
uint32_t oldAnimIndex = animIndex;
auto animations = model->GetAnimations();
if (ImGui::BeginCombo("Type", model->GetCurrentAnimation()->GetName().c_str()))
{
for (int n = 0; n < model->GetAnimationsCount(); n++)
{
bool is_selected = (animIndex == n);
std::string animName = animations[n]->GetName();
if (animName.empty())
{
animName = "Empty";
}
if (ImGui::Selectable(animName.c_str(), is_selected))
{
animIndex = n;
}
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
if (animIndex != oldAnimIndex)
{
model->PlayAnimation(animIndex);
}
ImGui::TableNextColumn();
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0));
std::string resetLabel = std::string(ICON_FA_UNDO) + "##ResetAnimId";
if (ImGui::Button(resetLabel.c_str()))
{
model->PlayAnimation(0);
}
ImGui::PopStyleColor();
}
}
}
EndComponentTable();
}
};

View File

@@ -1,40 +0,0 @@
#pragma once
#include "ComponentPanel.h"
#include <src/Scene/Components/SphereCollider.h>
#include "src/FileSystem/FileSystem.h"
#include <src/Scene/Entities/ImGuiHelper.h>
class SphereColliderPanel : ComponentPanel {
public:
SphereColliderPanel() {}
void Draw(Nuake::Entity entity) override
{
if (!entity.HasComponent<Nuake::SphereColliderComponent>())
return;
auto& component = entity.GetComponent<Nuake::SphereColliderComponent>();
BeginComponentTable(SPHERE COLLIDER, Nuake::SphereColliderComponent);
{
{
ImGui::Text("Size");
ImGui::TableNextColumn();
ImGui::DragFloat("##Radius", &component.Radius, 0.01f, 0.001f);
component.Radius = std::max(component.Radius, 0.001f);
ImGui::TableNextColumn();
ComponentTableReset(component.Radius, 0.5f);
}
ImGui::TableNextColumn();
{
ImGui::Text("Is Trigger");
ImGui::TableNextColumn();
ImGui::Checkbox("##isTrigger", &component.IsTrigger);
ImGui::TableNextColumn();
ComponentTableReset(component.IsTrigger, false);
}
}
EndComponentTable();
}
};

View File

@@ -1,89 +0,0 @@
#pragma once
#include "ComponentPanel.h"
#include "src/FileSystem/FileSystem.h"
#include <src/Core/Maths.h>
#include <src/Scene/Components/SpriteComponent.h>
#include <src/Scene/Entities/ImGuiHelper.h>
class SpritePanel : ComponentPanel
{
public:
SpritePanel() = default;
~SpritePanel() = default;
void Draw(Nuake::Entity entity) override
{
if (!entity.HasComponent<Nuake::SpriteComponent>())
{
return;
}
auto& component = entity.GetComponent<Nuake::SpriteComponent>();
BeginComponentTable(SPRITE, Nuake::SpriteComponent);
{
{
ImGui::Text("Sprite");
ImGui::TableNextColumn();
std::string path = component.SpritePath;
ImGui::Button(path.empty() ? "Drag image" : component.SpritePath.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0));
if (ImGui::BeginDragDropTarget())
{
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_Image"))
{
char* file = (char*)payload->Data;
std::string fullPath = std::string(file, 512);
path = Nuake::FileSystem::AbsoluteToRelative(std::move(fullPath));
component.SpritePath = path;
component.LoadSprite();
}
ImGui::EndDragDropTarget();
}
ImGui::TableNextColumn();
ComponentTableReset(component.LockYRotation, false);
}
ImGui::TableNextColumn();
{
ImGui::Text("Billboard");
ImGui::TableNextColumn();
ImGui::Checkbox("##billboard", &component.Billboard);
ImGui::TableNextColumn();
ComponentTableReset(component.Billboard, false);
}
ImGui::TableNextColumn();
{
ImGui::Text("Lock Y rotation");
ImGui::TableNextColumn();
ImGui::Checkbox("##lockYRotation", &component.LockYRotation);
ImGui::TableNextColumn();
ComponentTableReset(component.LockYRotation, false);
}
ImGui::TableNextColumn();
{
ImGui::Text("Position Based");
if (ImGui::BeginItemTooltip())
{
ImGui::Text("Orientation is based on the position of the camera or the orientation of the camera.");
ImGui::EndTooltip();
}
ImGui::TableNextColumn();
ImGui::Checkbox("##positionbased", &component.PositionFacing);
ImGui::TableNextColumn();
ComponentTableReset(component.LockYRotation, false);
}
}
EndComponentTable();
}
};

View File

@@ -27,14 +27,14 @@ public:
ImGui::TableNextColumn();
Vector3 position = component.GetLocalPosition();
ImGuiHelper::DrawVec3("Translation", &position);
ImGuiHelper::DrawVec3("Translation##" + std::to_string(entity.GetHandle()), &position);
if (position != component.GetLocalPosition())
component.SetLocalPosition(position);
ImGui::TableNextColumn();
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0));
std::string resetLabel = std::string(ICON_FA_UNDO) + "##ResetTranslation";
std::string resetLabel = std::string(ICON_FA_UNDO) + "##ResetTranslation" + std::to_string(entity.GetHandle());
if (ImGui::Button(resetLabel.c_str()))
component.SetLocalPosition(Vector3(0, 0, 0));
@@ -52,7 +52,7 @@ public:
Vector3 eulerDegreesOld = glm::degrees(glm::eulerAngles(currentRotation));
// Draw the ImGui widget for rotation
ImGuiHelper::DrawVec3("Rotation", &eulerDegreesOld);
ImGuiHelper::DrawVec3("Rotation##" + std::to_string(entity.GetHandle()), &eulerDegreesOld);
// Calculate the delta in Euler angles
Vector3 eulerDelta = eulerDegreesOld - glm::degrees(glm::eulerAngles(currentRotation));
@@ -84,7 +84,7 @@ public:
ImGui::TableNextColumn();
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0));
std::string resetLabel = std::string(ICON_FA_UNDO) + "##ResetRotation";
std::string resetLabel = std::string(ICON_FA_UNDO) + "##ResetRotation" + std::to_string(entity.GetHandle());
if (ImGui::Button(resetLabel.c_str()))
{
component.SetLocalRotation(Quat(1, 0, 0, 0));
@@ -97,7 +97,7 @@ public:
ImGui::TableNextColumn();
Vector3 localScale = component.GetLocalScale();
ImGuiHelper::DrawVec3("Scale", &localScale);
ImGuiHelper::DrawVec3("Scale##" + std::to_string(entity.GetHandle()), &localScale);
if (localScale != component.GetLocalScale())
component.SetLocalScale(localScale);
@@ -105,7 +105,7 @@ public:
ImGui::TableNextColumn();
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(1, 1, 1, 0));
std::string resetLabel = std::string(ICON_FA_UNDO) + "##ResetScale";
std::string resetLabel = std::string(ICON_FA_UNDO) + "##ResetScale" + std::to_string(entity.GetHandle());
if (ImGui::Button(resetLabel.c_str()))
component.SetLocalScale(Vector3(1, 1, 1));

View File

@@ -7,6 +7,10 @@
#include <glad/glad.h>
#include "src/UI/NuakeUI.h"
#include "src/UI/UIInputManager.h"
void EditorApplication::OnInit()
{
@@ -70,6 +74,13 @@ void EditorApplication::OnInit()
Engine::GetCurrentScene()->Save();
}
});
m_Window->SetOnDragNDropCallback([&](Window& window, const std::vector<std::string>& paths) {
for (auto& layer : m_LayerStack)
{
layer->OnDragNDrop(paths);
}
});
PushLayer(CreateScope<EditorLayer>());
}

View File

@@ -10,6 +10,15 @@
using namespace NuakeEditor;
class DragNDropModule : public Nuake::IApplicationModule
{
public:
void OnInit() override
{
}
};
class EditorApplication : public Nuake::Application
{
private:

View File

@@ -53,14 +53,18 @@ void EditorLayer::OnUpdate()
m_GizmoDrawer->DrawNavMesh(currentScene, true);
}
if (m_EditorInterface->ShouldDrawCollision())
if (m_EditorInterface->ShouldDrawGizmos())
{
m_GizmoDrawer->DrawGizmos(currentScene, false);
}
if (m_EditorInterface->ShouldDrawShapes())
{
m_GizmoDrawer->DrawShapes(currentScene, false);
}
}
}
sceneFramebuffer->Unbind();
}
@@ -80,4 +84,9 @@ void EditorLayer::OnDetach()
void EditorLayer::OnWindowFocused()
{
m_EditorInterface->OnWindowFocused();
}
}
void EditorLayer::OnDragNDrop(const std::vector<std::string>& paths)
{
m_EditorInterface->OnDragNDrop(paths);
}

View File

@@ -23,6 +23,7 @@ public:
virtual void OnDetach() override;
virtual void OnWindowFocused() override;
virtual void OnDragNDrop(const std::vector<std::string>& paths) override;
private:
CommandBuffer mCommandBuffer;

View File

@@ -8,6 +8,7 @@
#include <src/Scene/Components/SphereCollider.h>
#include <src/Scene/Components/CharacterControllerComponent.h>
#include <src/Scene/Components/BoxCollider.h>
#include "src/Scene/Components/RigidbodyComponent.h"
#include <src/Resource/ModelLoader.h>
#include <src/Rendering/RenderList.h>
@@ -143,6 +144,11 @@ bool GizmoDrawer::IsEntityInSelection(Nuake::Entity entity)
return false;
}
if (!m_Editor->Selection.Entity.IsValid())
{
return false;
}
using namespace Nuake;
const Nuake::Entity selectedEntity = m_Editor->Selection.Entity;
@@ -184,10 +190,10 @@ void GizmoDrawer::DrawAxis(Ref<Scene> scene, bool occluded)
RenderCommand::Enable(RendererEnum::DEPTH_TEST);
{
m_LineShader->Bind();
m_LineShader->SetUniformMat4f("u_View", scene->m_EditorCamera->GetTransform());
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform1f("u_Opacity", occluded ? 0.1f : 0.5f);
m_LineShader->SetUniformVec4("u_Color", {0.0f, 0.0f, 0.0f, 0.0f});
m_LineShader->SetUniform("u_View", scene->m_EditorCamera->GetTransform());
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform("u_Opacity", occluded ? 0.1f : 0.5f);
m_LineShader->SetUniform("u_Color", {0.0f, 0.0f, 0.0f, 0.0f});
m_AxisLineBuffer->Bind();
glLineWidth(1.0f);
Nuake::RenderCommand::DrawLines(0, 6);
@@ -213,29 +219,11 @@ void GizmoDrawer::DrawNavMesh(Ref<Scene> scene, bool occluded)
}
}
void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
void GizmoDrawer::DrawShapes(Ref<Scene> scene, bool occluded)
{
using namespace Nuake;
RenderCommand::Enable(RendererEnum::DEPTH_TEST);
glLineWidth(3.0f);
auto boxColliderView = scene->m_Registry.view<TransformComponent, BoxColliderComponent>();
for (auto e : boxColliderView)
{
auto [transform, box] = scene->m_Registry.get<TransformComponent, BoxColliderComponent>(e);
const Quat& globalRotation = glm::normalize(transform.GetGlobalRotation());
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
m_LineShader->Bind();
m_LineShader->SetUniform1f("u_Opacity", 1.f);
m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix, box.Size));
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_BoxBuffer->Bind();
Nuake::RenderCommand::DrawLines(0, 26);
}
glLineWidth(2.0f);
auto navMeshVolumeView = scene->m_Registry.view<TransformComponent, NavMeshVolumeComponent>();
for (auto e : navMeshVolumeView)
@@ -251,9 +239,26 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
m_LineShader->Bind();
m_LineShader->SetUniform1f("u_Opacity", 0.9f);
m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix, volume.VolumeSize));
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform("u_Opacity", 0.9f);
m_LineShader->SetUniform("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix, volume.VolumeSize));
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
m_BoxBuffer->Bind();
Nuake::RenderCommand::DrawLines(0, 26);
}
auto boxColliderView = scene->m_Registry.view<TransformComponent, BoxColliderComponent>();
for (auto e : boxColliderView)
{
auto [transform, box] = scene->m_Registry.get<TransformComponent, BoxColliderComponent>(e);
const Quat& globalRotation = glm::normalize(transform.GetGlobalRotation());
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
m_LineShader->Bind();
m_LineShader->SetUniform("u_Opacity", 1.f);
m_LineShader->SetUniform("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix, box.Size));
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
m_BoxBuffer->Bind();
Nuake::RenderCommand::DrawLines(0, 26);
@@ -264,9 +269,9 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
{
auto [transform, sphere] = scene->m_Registry.get<TransformComponent, SphereColliderComponent>(e);
m_LineShader->Bind();
m_LineShader->SetUniform1f("u_Opacity", 1.f);
m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])), Vector3(sphere.Radius)));
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform("u_Opacity", 1.f);
m_LineShader->SetUniform("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])), Vector3(sphere.Radius)));
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
m_CircleBuffer->Bind();
Nuake::RenderCommand::DrawLines(0, 128);
@@ -285,14 +290,14 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
Vector3 globalPosition = Vector3(transform.GetGlobalTransform()[3]);
m_LineShader->Bind();
m_LineShader->SetUniform1f("u_Opacity", 1.f);
m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), globalPosition), Vector3(emitter.MaxDistance)));
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform("u_Opacity", 1.f);
m_LineShader->SetUniform("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), globalPosition), Vector3(emitter.MaxDistance)));
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
m_CircleBuffer->Bind();
Nuake::RenderCommand::DrawLines(0, 128);
m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), globalPosition), Vector3(emitter.MinDistance)));
m_LineShader->SetUniform("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), globalPosition), Vector3(emitter.MinDistance)));
Nuake::RenderCommand::DrawLines(0, 128);
}
@@ -313,9 +318,9 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
m_LineShader->Bind();
m_LineShader->SetUniform1f("u_Opacity", 1.f);
m_LineShader->SetUniformMat4f("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix);
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform("u_Opacity", 1.f);
m_LineShader->SetUniform("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix);
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
m_CapsuleGizmo[entityId]->Bind();
Nuake::RenderCommand::DrawLines(0, 264);
@@ -338,9 +343,9 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
m_LineShader->Bind();
m_LineShader->SetUniform1f("u_Opacity", 1.0f);
m_LineShader->SetUniformMat4f("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix);
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform("u_Opacity", 1.0f);
m_LineShader->SetUniform("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix);
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
m_CylinderGizmo[entityId]->Bind();
Nuake::RenderCommand::DrawLines(0, 264);
@@ -371,9 +376,9 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
gizmoPosition = glm::translate(gizmoPosition, { 0, -cylinderLength / 2.0, 0 });
m_LineShader->Bind();
m_LineShader->SetUniform1f("u_Opacity", 1.0f);
m_LineShader->SetUniformMat4f("u_View", gizmoPosition);
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform("u_Opacity", 1.0f);
m_LineShader->SetUniform("u_View", gizmoPosition);
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
m_CylinderGizmo[entityId]->Bind();
Nuake::RenderCommand::DrawLines(0, 264);
@@ -414,9 +419,9 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
{
auto [transform, particle] = scene->m_Registry.get<TransformComponent, ParticleEmitterComponent>(e);
m_LineShader->Bind();
m_LineShader->SetUniform1f("u_Opacity", 1.f);
m_LineShader->SetUniformMat4f("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])), Vector3(particle.Radius)));
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform("u_Opacity", 1.f);
m_LineShader->SetUniform("u_View", glm::scale(glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])), Vector3(particle.Radius)));
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
m_CircleBuffer->Bind();
Nuake::RenderCommand::DrawLines(0, 128);
@@ -445,8 +450,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
m_LineShader->Bind();
m_LineShader->SetUniformMat4f("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix);
m_LineShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
m_LineShader->SetUniform("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix);
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
meshes[mesh.SubMesh]->Bind();
@@ -454,11 +459,42 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
auto camView = scene->m_Registry.view<TransformComponent, CameraComponent>();
for (auto e : camView)
{
auto [transform, camera] = scene->m_Registry.get<TransformComponent, CameraComponent>(e);
const Quat& globalRotation = glm::normalize(transform.GetGlobalRotation());
const Matrix4& rotationMatrix = glm::mat4_cast(globalRotation);
m_LineShader->Bind();
m_LineShader->SetUniform("u_Opacity", 1.f);
const float aspectRatio = camera.CameraInstance->AspectRatio;
const float fov = camera.CameraInstance->Fov;
Matrix4 clampedPerspective = glm::perspectiveFov(glm::radians(fov), 9.0f * aspectRatio, 9.0f, 0.05f, 3.0f);
m_LineShader->SetUniform("u_View", glm::translate(scene->m_EditorCamera->GetTransform(), Vector3(transform.GetGlobalTransform()[3])) * rotationMatrix * glm::inverse(clampedPerspective));
m_LineShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
m_BoxBuffer->Bind();
Nuake::RenderCommand::DrawLines(0, 26);
}
}
void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
{
using namespace Nuake;
auto camView = scene->m_Registry.view<TransformComponent, CameraComponent>();
RenderCommand::Enable(RendererEnum::DEPTH_TEST);
glLineWidth(3.0f);
auto flatShader = ShaderManager::GetShader("Resources/Shaders/flat.shader");
flatShader->Bind();
flatShader->SetUniformMat4f("u_View", scene->m_EditorCamera->GetTransform());
flatShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
flatShader->SetUniform4f("u_Color", 0.5f, 0.5f, 0.5f, 1.0f);
flatShader->SetUniform("u_View", scene->m_EditorCamera->GetTransform());
flatShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
flatShader->SetUniform("u_Color", 0.5f, 0.5f, 0.5f, 1.0f);
RenderCommand::Enable(RendererEnum::DEPTH_TEST);
RenderCommand::Enable(RendererEnum::FACE_CULL);
@@ -469,9 +505,9 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
auto gizmoShader = ShaderManager::GetShader("Resources/Shaders/gizmo.shader");
gizmoShader->Bind();
gizmoShader->SetUniformMat4f("u_View", scene->m_EditorCamera->GetTransform());
gizmoShader->SetUniformMat4f("u_Projection", scene->m_EditorCamera->GetPerspective());
gizmoShader->SetUniform1f("u_Opacity", occluded ? 0.1f : 1.f);
gizmoShader->SetUniform("u_View", scene->m_EditorCamera->GetTransform());
gizmoShader->SetUniform("u_Projection", scene->m_EditorCamera->GetPerspective());
gizmoShader->SetUniform("u_Opacity", occluded ? 0.1f : 1.f);
RenderCommand::Disable(RendererEnum::FACE_CULL);
const Vector3& cameraPosition = scene->m_EditorCamera->GetTranslation();
@@ -479,11 +515,10 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
const Vector3 gizmoSize = Vector3(Engine::GetProject()->Settings.GizmoSize);
// Camera
auto camView = scene->m_Registry.view<TransformComponent, CameraComponent>();
for (auto e : camView)
{
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/camera.png").get());
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/camera.png").get());
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
auto [transform, camera] = scene->m_Registry.get<TransformComponent, CameraComponent>(e);
auto initialTransform = transform.GetGlobalTransform();
@@ -501,6 +536,7 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
}
// Lights
auto lightView = scene->m_Registry.view<TransformComponent, LightComponent>();
for (auto e : lightView)
{
auto [transform, light] = scene->m_Registry.get<TransformComponent, LightComponent>(e);
@@ -522,8 +558,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
texturePath = "Resources/Gizmos/light.png";
}
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture(texturePath).get());
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture(texturePath).get());
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
auto initialTransform = transform.GetGlobalTransform();
Matrix4 particleTransform = initialTransform;
@@ -543,8 +579,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
auto characterControllerView = scene->m_Registry.view<TransformComponent, CharacterControllerComponent>();
for (auto e : characterControllerView)
{
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/player.png").get());
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/player.png").get());
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
auto [transform, characterControllerComponent] = scene->m_Registry.get<TransformComponent, CharacterControllerComponent>(e);
auto initialTransform = transform.GetGlobalTransform();
@@ -566,8 +602,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
auto boneView = scene->m_Registry.view<TransformComponent, BoneComponent>();
for (auto e : boneView)
{
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/bone.png").get());
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/bone.png").get());
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
auto [transform, boneComponent] = scene->m_Registry.get<TransformComponent, BoneComponent>(e);
auto initialTransform = transform.GetGlobalTransform();
@@ -588,8 +624,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
auto audioView = scene->m_Registry.view<TransformComponent, AudioEmitterComponent>();
for (auto e : audioView)
{
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/sound_emitter.png").get());
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/sound_emitter.png").get());
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
auto [transformComponent, audioEmitterComponent] = scene->m_Registry.get<TransformComponent, AudioEmitterComponent>(e);
auto initialTransform = transformComponent.GetGlobalTransform();
@@ -609,8 +645,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
auto rigidbodyView = scene->m_Registry.view<TransformComponent, RigidBodyComponent>();
for (auto e : rigidbodyView)
{
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/rigidbody.png").get());
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/rigidbody.png").get());
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
auto [transformComponent, rigidbodyComponent] = scene->m_Registry.get<TransformComponent, RigidBodyComponent>(e);
auto initialTransform = transformComponent.GetGlobalTransform();
@@ -630,8 +666,8 @@ void GizmoDrawer::DrawGizmos(Ref<Scene> scene, bool occluded)
auto particleEmitterView = scene->m_Registry.view<TransformComponent, ParticleEmitterComponent>();
for (auto e : particleEmitterView)
{
gizmoShader->SetUniformTex("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/particles.png").get());
gizmoShader->SetUniform1i("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
gizmoShader->SetUniform("gizmo_texture", TextureManager::Get()->GetTexture("Resources/Gizmos/particles.png").get());
gizmoShader->SetUniform("u_EntityID", ((int32_t)(uint32_t)(e)) + 1);
auto [transformComponent, particleEmitter] = scene->m_Registry.get<TransformComponent, ParticleEmitterComponent>(e);
auto initialTransform = transformComponent.GetGlobalTransform();

View File

@@ -53,6 +53,7 @@ public:
GizmoDrawer() = default;
~GizmoDrawer() = default;
void DrawShapes(Ref<Scene> scene, bool occluded);
void DrawGizmos(Ref<Scene> scene, bool occluded);
void DrawAxis(Ref<Scene> scene, bool occluded);
void DrawNavMesh(Ref<Scene> scene, bool occluded);

View File

@@ -6,7 +6,7 @@ void ImGuiTextSTD(const std::string& label, std::string& value)
{
char buffer[256];
memset(buffer, 0, sizeof(buffer));
std::strncpy(buffer, value.c_str(), sizeof(buffer));
strncpy_s(buffer, value.c_str(), sizeof(buffer));
if (ImGui::InputText(label.c_str(), buffer, sizeof(buffer)))
{
@@ -18,7 +18,7 @@ void ImGuiTextMultiline(const std::string& label, std::string& value)
{
char buffer[256];
memset(buffer, 0, sizeof(buffer));
std::strncpy(buffer, value.c_str(), sizeof(buffer));
strncpy_s(buffer, value.c_str(), sizeof(buffer));
if (ImGui::InputTextMultiline(label.c_str(), buffer, sizeof(buffer)))
{
value = std::string(buffer);

View File

@@ -4,8 +4,6 @@
void PopupHelper::OpenPopup(const std::string& id)
{
ImGui::TextWrapped(id.c_str());
ImGui::OpenPopup(id.c_str());
}

View File

@@ -94,26 +94,26 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
auto file = FileSystem::GetFile(path);
if (file->GetFileType() == FileType::Prefab)
{
Ref<Scene> scene = Scene::New();
auto cam = scene->CreateEntity("Camera");
TransformComponent& camTransform = cam.GetComponent<TransformComponent>();
camTransform.SetLocalPosition({ 0.0f, 0.0f, 2.0f });
auto& previewLight = scene->CreateEntity("_directionalLight").AddComponent<LightComponent>();
previewLight.SetCastShadows(false);
previewLight.Type = LightType::Directional;
scene->GetEnvironment()->CurrentSkyType = SkyType::ProceduralSky;
scene->GetEnvironment()->ProceduralSkybox->SunDirection = { 0.58f, 0.34f, -0.74f };
auto& camComponent = cam.AddComponent<CameraComponent>();
camComponent.CameraInstance->Fov = 45.0f;
camComponent.CameraInstance->AspectRatio = 1.0f;
m_ShadedFramebuffer->SetTexture(texture);
Ref<Prefab> prefab = Prefab::InstanceInScene(path, scene);
scene->Update(0.01f);
scene->Draw(*m_ShadedFramebuffer.get());
//Ref<Scene> scene = Scene::New();
//auto cam = scene->CreateEntity("Camera");
//TransformComponent& camTransform = cam.GetComponent<TransformComponent>();
//camTransform.SetLocalPosition({ 0.0f, 0.0f, 2.0f });
//
//auto& previewLight = scene->CreateEntity("_directionalLight").AddComponent<LightComponent>();
//previewLight.SetCastShadows(false);
//previewLight.Type = LightType::Directional;
//
//scene->GetEnvironment()->CurrentSkyType = SkyType::ProceduralSky;
//scene->GetEnvironment()->ProceduralSkybox->SunDirection = { 0.58f, 0.34f, -0.74f };
//auto& camComponent = cam.AddComponent<CameraComponent>();
//camComponent.CameraInstance->Fov = 45.0f;
//camComponent.CameraInstance->AspectRatio = 1.0f;
//m_ShadedFramebuffer->SetTexture(texture);
//
//Ref<Prefab> prefab = Prefab::InstanceInScene(path, scene.get());
//
//scene->Update(0.01f);
//scene->Draw(*m_ShadedFramebuffer.get());
// Gbuffer pass
//m_Framebuffer->Bind();
@@ -127,9 +127,9 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
// shader->Bind();
//
// auto cam = Engine::GetCurrentScene()->GetCurrentCamera();
// shader->SetUniformMat4f("u_View", view);
// shader->SetUniformMat4f("u_Projection", ortho);
// shader->SetUniformMat4f("u_Model", Matrix4(1.0f));
// shader->SetUniform("u_View", view);
// shader->SetUniform("u_Projection", ortho);
// shader->SetUniform("u_Model", Matrix4(1.0f));
// Renderer::SphereMesh->Draw(shader, true);
//}
//m_Framebuffer->Unbind();
@@ -143,15 +143,15 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
// RenderCommand::Disable(RendererEnum::FACE_CULL);
// auto shader = ShaderManager::GetShader("Resources/Shaders/deferred.shader");
// shader->Bind();
// shader->SetUniformVec3("u_EyePosition", Vector3(1, 0, 0));
// shader->SetUniform1i("LightCount", 0);
// shader->SetUniform("u_EyePosition", Vector3(1, 0, 0));
// shader->SetUniform("LightCount", 0);
// auto dir = Engine::GetCurrentScene()->GetEnvironment()->ProceduralSkybox->GetSunDirection();
// shader->SetUniform3f("u_DirectionalLight.Direction", 0.6, -0.6, 0.6);
// shader->SetUniform3f("u_DirectionalLight.Color", 10.0f, 10.0f, 10.0f);
// shader->SetUniform1i("u_DirectionalLight.Shadow", 0);
// shader->SetUniform1i("u_DisableSSAO", 1);
// shader->SetUniformMat4f("u_View", view);
// shader->SetUniformMat4f("u_Projection", ortho);
// shader->SetUniform("u_DirectionalLight.Direction", 0.6, -0.6, 0.6);
// shader->SetUniform("u_DirectionalLight.Color", 10.0f, 10.0f, 10.0f);
// shader->SetUniform("u_DirectionalLight.Shadow", 0);
// shader->SetUniform("u_DisableSSAO", 1);
// shader->SetUniform("u_View", view);
// shader->SetUniform("u_Projection", ortho);
//
// m_Framebuffer->GetTexture(GL_DEPTH_ATTACHMENT)->Bind(5);
// m_Framebuffer->GetTexture(GL_COLOR_ATTACHMENT0)->Bind(6);
@@ -159,11 +159,11 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
// m_Framebuffer->GetTexture(GL_COLOR_ATTACHMENT2)->Bind(8);
// m_Framebuffer->GetTexture(GL_COLOR_ATTACHMENT4)->Bind(10);
//
// shader->SetUniform1i("m_Depth", 5);
// shader->SetUniform1i("m_Albedo", 6);
// shader->SetUniform1i("m_Normal", 7);
// shader->SetUniform1i("m_Material", 8);
// shader->SetUniform1i("m_Emissive", 10);
// shader->SetUniform("m_Depth", 5);
// shader->SetUniform("m_Albedo", 6);
// shader->SetUniform("m_Normal", 7);
// shader->SetUniform("m_Material", 8);
// shader->SetUniform("m_Emissive", 10);
//
// Renderer::DrawQuad(Matrix4());
//}
@@ -192,12 +192,8 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
m_ShadedFramebuffer->SetTexture(texture);
ModelComponent& modelComp = scene->CreateEntity("Mesh").AddComponent<ModelComponent>();
modelComp.ModelResource = ResourceLoader::LoadModel(file->GetRelativePath());
AABB aabb = modelComp.ModelResource->GetMeshes()[0]->GetAABB();
Vector3 middlePoint = aabb.Max / 2.0f;
//ModelComponent& modelComp = scene->CreateEntity("Mesh").AddComponent<ModelComponent>();
//modelComp.ModelResource = ResourceLoader::LoadModel(file->GetRelativePath());
scene->Update(0.01f);
scene->Draw(*m_ShadedFramebuffer.get());
}
@@ -215,9 +211,9 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
shader->Bind();
auto cam = Engine::GetCurrentScene()->GetCurrentCamera();
shader->SetUniformMat4f("u_View", view);
shader->SetUniformMat4f("u_Projection", ortho);
shader->SetUniformMat4f("u_Model", Matrix4(1.0f));
shader->SetUniform("u_View", view);
shader->SetUniform("u_Projection", ortho);
shader->SetUniform("u_Model", Matrix4(1.0f));
Ref<Material> material = ResourceLoader::LoadMaterial(path);
material->Bind(shader);
Renderer::SphereMesh->Draw(shader, false);
@@ -233,15 +229,15 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
RenderCommand::Disable(RendererEnum::FACE_CULL);
auto shader = ShaderManager::GetShader("Resources/Shaders/deferred.shader");
shader->Bind();
shader->SetUniformVec3("u_EyePosition", Vector3(1, 0, 0));
shader->SetUniform1i("LightCount", 0);
shader->SetUniform("u_EyePosition", Vector3(1, 0, 0));
shader->SetUniform("LightCount", 0);
auto dir = Engine::GetCurrentScene()->GetEnvironment()->ProceduralSkybox->GetSunDirection();
shader->SetUniform3f("u_DirectionalLight.Direction", 0.6, -0.6, 0.6);
shader->SetUniform3f("u_DirectionalLight.Color", 10.0f, 10.0f, 10.0f);
shader->SetUniform1i("u_DirectionalLight.Shadow", 0);
shader->SetUniform1i("u_DisableSSAO", 1);
shader->SetUniformMat4f("u_View", view);
shader->SetUniformMat4f("u_Projection", ortho);
shader->SetUniform("u_DirectionalLight.Direction", 0.6, -0.6, 0.6);
shader->SetUniform("u_DirectionalLight.Color", 10.0f, 10.0f, 10.0f);
shader->SetUniform("u_DirectionalLight.Shadow", 0);
shader->SetUniform("u_DisableSSAO", 1);
shader->SetUniform("u_View", view);
shader->SetUniform("u_Projection", ortho);
m_Framebuffer->GetTexture(GL_DEPTH_ATTACHMENT)->Bind(5);
m_Framebuffer->GetTexture(GL_COLOR_ATTACHMENT0)->Bind(6);
@@ -249,11 +245,11 @@ Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path,
m_Framebuffer->GetTexture(GL_COLOR_ATTACHMENT2)->Bind(8);
m_Framebuffer->GetTexture(GL_COLOR_ATTACHMENT4)->Bind(10);
shader->SetUniform1i("m_Depth", 5);
shader->SetUniform1i("m_Albedo", 6);
shader->SetUniform1i("m_Normal", 7);
shader->SetUniform1i("m_Material", 8);
shader->SetUniform1i("m_Emissive", 10);
shader->SetUniform("m_Depth", 5);
shader->SetUniform("m_Albedo", 6);
shader->SetUniform("m_Normal", 7);
shader->SetUniform("m_Material", 8);
shader->SetUniform("m_Emissive", 10);
Renderer::DrawQuad(Matrix4());
}

View File

@@ -5,22 +5,22 @@
void ScriptingContext::Initialize()
{
m_Modules =
modules =
{
CreateRef<EditorNetAPI>()
};
for (auto& m : m_Modules)
for (auto& m : modules)
{
m->RegisterMethods();
}
// Load Nuake assembly DLL
/*auto m_LoadContext2 = Nuake::ScriptingEngineNet::Get().GetHostInstance()->CreateAssemblyLoadContext("NuakeEditorContext");
m_NuakeAssembly = Nuake::ScriptingEngineNet::Get().ReloadEngineAPI(m_LoadContext2);
m_EditorAssembly = m_LoadContext2.LoadAssembly("EditorNet.dll");
/*auto loadContext2 = Nuake::ScriptingEngineNet::Get().GetHostInstance()->CreateAssemblyLoadContext("NuakeEditorContext");
nuakeAssembly = Nuake::ScriptingEngineNet::Get().ReloadEngineAPI(loadContext2);
m_EditorAssembly = loadContext2.LoadAssembly("EditorNet.dll");
for (const auto& netModule : m_Modules)
for (const auto& netModule : modules)
{
for (const auto& [methodName, methodPtr] : netModule->GetMethods())
{

View File

@@ -13,13 +13,13 @@ namespace Coral
class ScriptingContext
{
private:
Coral::HostInstance* m_HostInstance;
Coral::AssemblyLoadContext m_LoadContext;
Coral::HostInstance* hostInstance;
Coral::AssemblyLoadContext loadContext;
std::unordered_map<std::string, Coral::AssemblyLoadContext*> m_LoadedAssemblies;
std::vector<Ref<Nuake::NetAPIModule>> m_Modules;
std::unordered_map<std::string, Coral::AssemblyLoadContext*> loadedAssemblies;
std::vector<Ref<Nuake::NetAPIModule>> modules;
Coral::ManagedAssembly m_NuakeAssembly; // Nuake DLL
Coral::ManagedAssembly nuakeAssembly; // Nuake DLL
Coral::ManagedAssembly m_EditorAssembly; // Editor DLL
public:
static ScriptingContext& Get()

View File

@@ -0,0 +1,2 @@
#pragma once

View File

@@ -10,27 +10,27 @@ public:
float dummyVolume = 1.0f;
void Draw()
{
constexpr int numBus = 6;
if(ImGui::Begin("Audio mixer"))
{
for (int i = 0; i < numBus; i++)
{
const std::string busName = "Bus " + std::to_string(i);
//ImGui::BeginTable(busName.c_str(), 1, 0, ImVec2(300, ImGui::GetContentRegionAvail().y));
//
//ImGui::TableSetupColumn(busName.c_str(), 0, 1.0f);
//ImGui::TableNextColumn ();
//ImGui::TableHeader(busName.c_str());
//ImGui::TableNextColumn();
//
//const float height = ImGui::GetContentRegionAvail().y - 50;
//const std::string id = "##Volume" + std::to_string(i);
//ImGui::VSliderFloat(id.c_str(), ImVec2(50, height), &dummyVolume, -60.0f, 6.0f, "%.3dB", ImGuiSliderFlags_Logarithmic);
//ImGui::TableNextColumn();
//ImGui::EndTable();
}
}
//constexpr int numBus = 6;
//if(ImGui::Begin("Audio mixer"))
//{
// for (int i = 0; i < numBus; i++)
// {
// const std::string busName = "Bus " + std::to_string(i);
// //ImGui::BeginTable(busName.c_str(), 1, 0, ImVec2(300, ImGui::GetContentRegionAvail().y));
// //
// //ImGui::TableSetupColumn(busName.c_str(), 0, 1.0f);
// //ImGui::TableNextColumn ();
// //ImGui::TableHeader(busName.c_str());
// //ImGui::TableNextColumn();
// //
// //const float height = ImGui::GetContentRegionAvail().y - 50;
// //const std::string id = "##Volume" + std::to_string(i);
// //ImGui::VSliderFloat(id.c_str(), ImVec2(50, height), &dummyVolume, -60.0f, 6.0f, "%.3dB", ImGuiSliderFlags_Logarithmic);
// //ImGui::TableNextColumn();
// //ImGui::EndTable();
// }
//}
ImGui::End();
//ImGui::End();
}
};

File diff suppressed because it is too large Load Diff

View File

@@ -18,6 +18,7 @@
#include <src/Scripting/ScriptingEngineNet.h>
#include "ProjectSettings/ProjectSettingsWindow.h"
#include "PrefabEditor/PrefabEditorWindow.h"
using namespace NuakeEditor;
@@ -30,14 +31,20 @@ namespace Nuake
class EditorInterface
{
private:
bool m_TitleBarHovered = false;
std::vector<CompilationError> errors;
std::vector<Ref<PrefabEditorWindow>> prefabEditors;
Ref<Scene> SceneSnapshot;
static NuakeEditor::CommandBuffer* mCommandBuffer;
std::string searchQuery = "";
bool isControllingCamera = false;
bool m_DrawGrid = false;
bool m_DrawAxis = true;
bool m_ShowImGuiDemo = false;
bool m_DebugCollisions = true;
bool m_DrawShapes = true;
bool m_DrawGizmos = true;
bool m_DrawCamPreview = false;
bool m_DrawNavMesh = true;
bool m_ShowOverlay = true;
bool m_IsHoveringViewport = false;
@@ -68,34 +75,45 @@ namespace Nuake
AudioWindow* _audioWindow;
FileSystemUI* filesystem;
bool isNewProject = false;
static EditorSelection Selection;
EditorSelectionPanel SelectionPanel;
EditorSelectionPanel* SelectionPanel;
TrenchbroomConfiguratorWindow m_TrenchhbroomConfigurator;
MapImporterWindow m_MapImporter;
ProjectSettingsWindow* m_ProjectSettingsWindow;
Ref<Texture> NuakeTexture;
Ref<Texture> CloseIconTexture;
Ref<Texture> MaximizeTexture;
Ref<Texture> RestoreTexture;
Ref<Texture> MinimizeTexture;
EditorInterface(CommandBuffer& commandBuffer);
static ImFont* bigIconFont;
void BuildFonts();
void DrawTitlebar(float& outHeight);
void Init();
void Draw();
void Update(float ts);
void DrawMenuBar();
bool BeginMenubar(const ImRect& barRectangle);
void EndMenubar();
void SetStatusMessage(const std::string& msg, const Color& color = Color(0.08f, 0.08f, 0.08f, 1.0f)) { m_StatusMessage = msg; m_StatusBarColor = color; }
void DrawViewport();
void DrawStatusBar();
void DrawMenuBars();
void DrawEntityTree(Entity ent);
void DrawEntityTree(Entity ent, bool drawChildrens = true);
void DrawSceneTree();
void DrawLogger();
void DrawProjectSettings();
bool EntityContainsItself(Entity ent1, Entity ent2);
void Overlay();
void OpenPrefabWindow(const std::string& prefabPath);
bool ShouldDrawAxis() const { return m_DrawAxis; }
bool ShouldDrawCollision() const { return m_DebugCollisions; }
bool ShouldDrawShapes() const { return m_DrawShapes; }
bool ShouldDrawGizmos() const { return m_DrawGizmos; }
bool ShouldDrawNavMesh() const { return m_DrawNavMesh; }
bool LoadProject(const std::string& projectPath);
@@ -105,5 +123,6 @@ namespace Nuake
public:
void OnWindowFocused();
void OnDragNDrop(const std::vector<std::string>& paths);
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -7,26 +7,17 @@
#include "../ComponentsPanel/TransformPanel.h"
#include "../ComponentsPanel/LightPanel.h"
#include "../ComponentsPanel/ScriptPanel.h"
#include "../ComponentsPanel/MeshPanel.h"
#include "../ComponentsPanel/QuakeMapPanel.h"
#include "../ComponentsPanel/SkinnedMeshPanel.h"
#include "../ComponentsPanel/CameraPanel.h"
#include "../ComponentsPanel/RigidbodyPanel.h"
#include "../ComponentsPanel/BoxColliderPanel.h"
#include "../ComponentsPanel/CapsuleColliderPanel.h"
#include "../ComponentsPanel/CylinderColliderPanel.h"
#include "../ComponentsPanel/SphereColliderPanel.h"
#include "../ComponentsPanel/MeshColliderPanel.h"
#include "../ComponentsPanel/CharacterControllerPanel.h"
#include "../ComponentsPanel/SpritePanel.h"
#include "../ComponentsPanel/ParticleEmitterPanel.h"
#include "../ComponentsPanel/SkinnedModelPanel.h"
#include "../ComponentsPanel/BonePanel.h"
#include "../ComponentsPanel/AudioEmitterPanel.h"
#include "../ComponentsPanel/NetScriptPanel.h"
#include "../ComponentsPanel/NavMeshVolumePanel.h"
#include <src/Scene/Components/WrenScriptComponent.h>
#include <src/Resource/Prefab.h>
@@ -37,36 +28,23 @@ namespace Nuake
class EditorSelectionPanel
{
using DrawComponentTypeFn = std::function<void(Nuake::Entity& entity, entt::meta_any& componentInstance)>;
using DrawFieldTypeFn = std::function<void(entt::meta_data& fieldMeta, entt::meta_any& componentInstance)>;
private:
TransformPanel mTransformPanel;
LightPanel mLightPanel;
ScriptPanel mScriptPanel;
NetScriptPanel mNetScriptPanel;
MeshPanel mMeshPanel;
SkinnedModelPanel mSkinnedModelPanel;
QuakeMapPanel mQuakeMapPanel;
CameraPanel mCameraPanel;
RigidbodyPanel mRigidbodyPanel;
BoxColliderPanel mBoxColliderPanel;
SphereColliderPanel mSphereColliderPanel;
MeshColliderPanel mMeshColliderPanel;
CapsuleColliderPanel mCapsuleColliderPanel;
CylinderColliderPanel mCylinderColliderPanel;
SpritePanel mSpritePanel;
CharacterControllerPanel mCharacterControllerPanel;
ParticleEmitterPanel mParticleEmitterPanel;
BonePanel mBonePanel;
AudioEmitterPanel mAudioEmitterPanel;
NavMeshVolumePanel mNavMeshVolumePanel;
MeshPanel meshPanel;
SkinnedMeshPanel skinnedMeshPanel;
EditorSelection* selection = nullptr;
Ref<Nuake::File> currentFile;
Ref<Nuake::Resource> selectedResource;
Ref<Nuake::Scene> virtualScene;
public:
EditorSelectionPanel();
EditorSelectionPanel(EditorSelection& selection);
void Draw(EditorSelection selection);
void Draw(EditorSelection selection, const std::string& id = "");
void DrawNone();
void DrawEntity(Nuake::Entity entity);
@@ -75,10 +53,47 @@ public:
void DrawFile(Ref<Nuake::File> file);
void DrawResource(Nuake::Resource resource);
void DrawPrefabPanel(Ref<Nuake::Prefab> prefab);
template<class T, auto Func>
void RegisterComponentDrawer()
{
const auto t = entt::type_id<T>();
ComponentTypeDrawers[t.hash()] = std::bind(Func, std::placeholders::_1, std::placeholders::_2);
}
template<class T, auto Func, class O>
void RegisterComponentDrawer(O* o)
{
ComponentTypeDrawers[entt::type_id<T>().hash()] = std::bind(Func, o, std::placeholders::_1, std::placeholders::_2);
}
template<class T, auto Func, class O>
void RegisterTypeDrawer(O* o)
{
FieldTypeDrawers[entt::type_id<T>().hash()] = std::bind(Func, o, std::placeholders::_1, std::placeholders::_2);
}
protected:
// Drawing functions for each component (for writing very specific inspectors for specific components)
std::unordered_map<entt::id_type, DrawComponentTypeFn> ComponentTypeDrawers;
// List of functions to call for each component field type that needs to be drawn
std::unordered_map<entt::id_type, DrawFieldTypeFn> FieldTypeDrawers;
private:
void ResolveFile(Ref<Nuake::File> file);
void DrawMaterialPanel(Ref<Nuake::Material> material);
void DrawProjectPanel(Ref<Nuake::Project> project);
void DrawWrenScriptPanel(Ref<Nuake::WrenScript> wrenFile);
void DrawNetScriptPanel(Ref<Nuake::File> file);
void DrawComponent(Nuake::Entity& entity, entt::meta_any& component);
void DrawComponentContent(entt::meta_any& component);
void DrawFieldTypeFloat(entt::meta_data& field, entt::meta_any& component);
void DrawFieldTypeBool(entt::meta_data& field, entt::meta_any& component);
void DrawFieldTypeVector2(entt::meta_data& field, entt::meta_any& component);
void DrawFieldTypeVector3(entt::meta_data& field, entt::meta_any& component);
void DrawFieldTypeString(entt::meta_data& field, entt::meta_any& component);
void DrawFieldTypeResourceFile(entt::meta_data& field, entt::meta_any& component);
void DrawFieldTypeDynamicItemList(entt::meta_data& field, entt::meta_any& component);
};

View File

@@ -19,6 +19,7 @@
#include "../Misc/ThumbnailManager.h"
#include <Tracy.hpp>
#include <src/Resource/SkyResource.h>
namespace Nuake
{
@@ -261,6 +262,8 @@ namespace Nuake
OS::OpenTrenchbroomMap(file->GetAbsolutePath());
break;
case FileType::NetScript:
case FileType::UI:
case FileType::CSS:
OS::OpenIn(file->GetAbsolutePath());
break;
case FileType::Scene:
@@ -269,8 +272,10 @@ namespace Nuake
case FileType::Solution:
OS::OpenIn(file->GetAbsolutePath());
break;
case FileType::Prefab:
this->Editor->OpenPrefabWindow(file->GetRelativePath());
break;
}
}
Editor->Selection = EditorSelection(file);
@@ -320,6 +325,18 @@ namespace Nuake
{
dragType = "_AudioFile";
}
else if (fileExtension == ".html")
{
dragType = "_UIFile";
}
else if (fileExtension == ".sky")
{
dragType = "_SkyFile";
}
else if (fileExtension == ".env")
{
dragType = "_EnvFile";
}
ImGui::SetDragDropPayload(dragType.c_str(), (void*)(pathBuffer), sizeof(pathBuffer));
ImGui::Text(file->GetName().c_str());
@@ -380,17 +397,34 @@ namespace Nuake
textureImage = image;
}
}
else if (fileType == FileType::Solution)
{
textureImage = textureMgr->GetTexture("Resources/Images/sln_icon.png");
}
else if (fileType == FileType::Map)
{
textureImage = textureMgr->GetTexture("Resources/Images/trenchbroom_icon.png");
}
else if (fileType == FileType::Env)
{
textureImage = textureMgr->GetTexture("Resources/Images/env_file_icon.png");
}
ImGui::SetCursorPos(prevCursor);
ImGui::Image(reinterpret_cast<ImTextureID>(textureImage->GetID()), ImVec2(100, 100), ImVec2(0, 1), ImVec2(1, 0));
ImGui::PopStyleVar();
auto imguiStyle = ImGui::GetStyle();
auto& imguiStyle = ImGui::GetStyle();
ImVec2 startOffset = ImVec2(imguiStyle.CellPadding.x / 2.0f, 0);
ImVec2 offsetEnd = ImVec2(startOffset.x, imguiStyle.CellPadding.y / 2.0f);
ImU32 rectColor = IM_COL32(255, 255, 255, 16);
ImGui::GetWindowDrawList()->AddRectFilled(prevScreenPos + ImVec2(0, 100) - startOffset, prevScreenPos + ImVec2(100, 150) + offsetEnd, rectColor, 1.0f);
ImU32 rectColor2 = UI::PrimaryCol;
Color fileTypeColor = GetColorByFileType(file->GetFileType());
ImGui::GetWindowDrawList()->AddRectFilled(prevScreenPos + ImVec2(0, 100) - startOffset, prevScreenPos + ImVec2(100, 101) + offsetEnd, IM_COL32(fileTypeColor.r * 255.f, fileTypeColor.g * 255.f, fileTypeColor.b * 255.f, fileTypeColor.a * 255.f), 0.0f);
std::string visibleName = file->GetName();
const uint32_t MAX_CHAR_NAME = 32;
if (file->GetName().size() >= MAX_CHAR_NAME)
@@ -653,36 +687,50 @@ namespace Nuake
RefreshFileBrowser();
}
}
if (ImGui::MenuItem("Wren Script"))
{
std::string path = FileDialog::SaveFile("*.wren");
if (!String::EndsWith(path, ".wren"))
{
path += ".wren";
}
if (!path.empty())
{
std::string fileName = String::ToUpper(FileSystem::GetFileNameFromPath(path));
fileName = String::RemoveWhiteSpace(fileName);
if(!String::IsDigit(fileName[0]))
{
FileSystem::BeginWriteFile(path, true);
FileSystem::WriteLine(TEMPLATE_SCRIPT_FIRST + fileName + TEMPLATE_SCRIPT_SECOND);
FileSystem::EndWriteFile();
RefreshFileBrowser();
if (ImGui::MenuItem("Sky"))
{
const std::string path = FileDialog::SaveFile("*.sky");
if (!path.empty())
{
std::string finalPath = path;
if (!String::EndsWith(path, ".sky"))
{
finalPath = path + ".sky";
}
else
{
Logger::Log("Cannot create script files that starts with a number.", "filesystem", CRITICAL);
}
}
}
Ref<SkyResource> sky = CreateRef<SkyResource>(FileSystem::AbsoluteToRelative(finalPath));
sky->IsEmbedded = false;
auto jsonData = sky->Serialize();
FileSystem::BeginWriteFile(finalPath, true);
FileSystem::WriteLine(jsonData.dump(4));
FileSystem::EndWriteFile();
RefreshFileBrowser();
}
}
if (ImGui::MenuItem("Environment"))
{
const std::string path = FileDialog::SaveFile("*.env");
if (!path.empty())
{
std::string finalPath = path;
if (!String::EndsWith(path, ".env"))
{
finalPath = path + ".env";
}
Ref<Environment> env = CreateRef<Environment>(FileSystem::AbsoluteToRelative(finalPath));
env->IsEmbedded = false;
auto jsonData = env->Serialize();
FileSystem::BeginWriteFile(finalPath, true);
FileSystem::WriteLine(jsonData.dump(4));
FileSystem::EndWriteFile();
RefreshFileBrowser();
}
}
ImGui::EndMenu();
}
@@ -697,6 +745,57 @@ namespace Nuake
Scan();
}
Color FileSystemUI::GetColorByFileType(FileType fileType)
{
switch (fileType)
{
case Nuake::FileType::Unknown:
break;
case Nuake::FileType::Image:
break;
case Nuake::FileType::Material:
break;
case Nuake::FileType::Mesh:
break;
case Nuake::FileType::Script:
return { 1.0, 0.0, 0.0, 1.0 };
break;
case Nuake::FileType::NetScript:
return { 1.0, 0.0, 0.0, 1.0 };
break;
case Nuake::FileType::Project:
return Engine::GetProject()->Settings.PrimaryColor;
break;
case Nuake::FileType::Prefab:
break;
case Nuake::FileType::Scene:
return { 0, 1.0f, 1.0, 1.0 };
break;
case Nuake::FileType::Wad:
break;
case Nuake::FileType::Map:
return { 0.0, 1.0, 0.0, 1.0 };
break;
case Nuake::FileType::Assembly:
break;
case Nuake::FileType::Solution:
break;
case Nuake::FileType::Audio:
return { 0.0, 0.0, 1.0, 1.0 };
break;
case Nuake::FileType::UI:
return { 1.0, 1.0, 0.0, 1.0 };
break;
case Nuake::FileType::CSS:
return { 1.0, 0.0, 1.0, 1.0 };
break;
default:
break;
}
return Color(0, 0, 0, 0);
}
void FileSystemUI::Scan()
{
if (!m_CurrentDirectory)
@@ -915,6 +1014,11 @@ namespace Nuake
{
for (Ref<Directory>& d : m_CurrentDirectory->Directories)
{
if (d->GetName() == "bin" || d->GetName() == ".vs" || d->GetName() == "obj")
{
continue;
}
if(String::Sanitize(d->Name).find(String::Sanitize(m_SearchKeyword)) != std::string::npos)
{
if (i + 1 % amount != 0)
@@ -934,6 +1038,11 @@ namespace Nuake
{
if(m_SearchKeyword.empty() || f->GetName().find(String::Sanitize(m_SearchKeyword)) != std::string::npos)
{
if (f->GetFileType() == FileType::Unknown || f->GetFileType() == FileType::Assembly)
{
continue;
}
if (i + 1 % amount != 0 || i == 1)
{
ImGui::TableNextColumn();
@@ -942,7 +1051,7 @@ namespace Nuake
{
ImGui::TableNextRow();
}
DrawFile(f, i);
i++;
}

View File

@@ -33,6 +33,8 @@ namespace Nuake {
void DrawContextMenu();
void RefreshFileBrowser();
Color GetColorByFileType(FileType fileType);
void Scan();
};
}

View File

@@ -240,7 +240,7 @@ std::vector<std::string> MapImporterWindow::ScanUsedWads()
std::string MapImporterWindow::GetTransformedWadPath(const std::string& path)
{
const std::string& baseTextureDir = "/textures/";
const std::string& baseTextureDir = "/Textures/";
using namespace Nuake;
if (m_WadToMaterialMap.find(path) != m_WadToMaterialMap.end())
@@ -285,7 +285,7 @@ std::string MapImporterWindow::GetTransformedWadPath(const std::string& path)
if (entry.is_regular_file() && stem == upperInput)
{
std::filesystem::path relativePath = std::filesystem::relative(entry.path(), FileSystem::Root + "/textures/");
std::filesystem::path relativePath = std::filesystem::relative(entry.path(), FileSystem::Root + "/Textures/");
std::filesystem::path pathWithoutExtension = relativePath;
pathWithoutExtension = pathWithoutExtension.parent_path(); // Remove the file name

View File

@@ -53,7 +53,7 @@ namespace Nuake
ImGui::PopStyleVar();
}
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.1, 0.1, 0.1, 0.2f));
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.1f, 0.1f, 0.1f, 0.2f));
ImGui::BeginChild("TemplateContainer", { ImGui::GetContentRegionAvail().x - 64.0f, ImGui::GetContentRegionAvail().y }, true, ImGuiChildFlags_AlwaysUseWindowPadding);
{
ImGui::Dummy({ 4, 4 });
@@ -94,7 +94,7 @@ namespace Nuake
if (showTitleEmptyWarning && projectTitle.empty())
{
ImGui::SameLine();
ImGui::TextColored({ 1.0, 0.1, 0.1, 1.0 }, ICON_FA_EXCLAMATION_TRIANGLE);
ImGui::TextColored({ 1.0f, 0.1f, 0.1f, 1.0f }, ICON_FA_EXCLAMATION_TRIANGLE);
Nuake::UI::Tooltip("Title required");
}
@@ -139,28 +139,26 @@ namespace Nuake
ImGui::InputText("##Location", &location); ImGui::SameLine();
if (ImGui::Button((ICON_FA_FOLDER + std::string("##folderOpen")).c_str()))
{
std::string folderPath = Nuake::FileDialog::SaveFile("Project File\0*.project");
std::string folderPath = Nuake::FileDialog::OpenFolder();
folderPath = Nuake::String::ReplaceSlash(folderPath);
if (!folderPath.empty())
{
auto splits = Nuake::String::Split(folderPath, '/');
projectFileName = splits[splits.size() - 1];
if (!Nuake::String::EndsWith(projectFileName, ".project"))
{
projectFileName += ".project";
}
location = "";
for (int i = 0; i < splits.size() - 1; i++)
for (int i = 0; i < splits.size(); i++)
{
location += splits[i] + "/";
}
}
}
projectFileName = Nuake::String::RemoveWhiteSpace(projectTitle) + ".project";
finalLocation = location;
static std::string projectParentPath = location;
projectParentPath = location;
@@ -194,7 +192,12 @@ namespace Nuake
ImGui::Dummy({ 1, ImGui::GetContentRegionAvail().y - 42 });
ImGui::Dummy({ ImGui::GetContentRegionAvail().x - 130, 38 }); ImGui::SameLine();
ImGui::Dummy({ ImGui::GetContentRegionAvail().x - 230 - 16, 38}); ImGui::SameLine();
if (Nuake::UI::SecondaryButton("Cancel", { 100, 38 }))
{
m_Editor->isCreatingNewProject = false;
}
ImGui::SameLine();
if (Nuake::UI::PrimaryButton((ICON_FA_PLUS + std::string(" Create")).c_str(), Nuake::Vector2{ 120, 38 }, Nuake::Color(primaryColor.x, primaryColor.y, primaryColor.z, primaryColor.w)))
{
if (projectTitle.empty())
@@ -240,7 +243,7 @@ namespace Nuake
window->Maximize();
m_Editor->filesystem->m_CurrentDirectory = Nuake::FileSystem::RootDirectory;
m_Editor->isNewProject = true;
m_HasCreatedProject = true;
}
}
@@ -264,7 +267,6 @@ namespace Nuake
void NewProjectWindow::DrawProjectTemplate(uint32_t i, const std::string& title, const std::string& description)
{
opened = true;
ImGui::ShowDemoWindow(&opened);
ImGui::Dummy({ 4, 4 });
ImGui::SameLine();
opened = true;

View File

@@ -0,0 +1,919 @@
#include "PrefabEditorWindow.h"
#include <src/Core/Input.h>
#include <src/Rendering/Buffers/FrameBuffer.h>
#include <src/Rendering/SceneRenderer.h>
#include <src/Resource/Prefab.h>
#include <src/Scene/Scene.h>
#include <src/Scene/EditorCamera.h>
#include <src/Scene/Entities/Entity.h>
#include <src/Rendering/Textures/Texture.h>
#include <imgui/imgui.h>
#include <imgui/imgui_internal.h>
#include <src/Scene/Components/SpriteComponent.h>
#include <src/Scene/Components/ParticleEmitterComponent.h>
#include <src/Scene/Components/RigidbodyComponent.h>
#include <src/Scene/Components/BoxCollider.h>
#include <src/Scene/Components/SphereCollider.h>
#include <src/Scene/Components/AudioEmitterComponent.h>
#include <src/Scene/Components/PrefabComponent.h>
#include <src/Scene/Components/BSPBrushComponent.h>
#include <src/Scene/Components/NetScriptComponent.h>
#include <src/FileSystem/FileDialog.h>
#include <imgui/ImGuizmo.h>
#include <glm/gtc/type_ptr.hpp>
using namespace Nuake;
PrefabEditorWindow::PrefabEditorWindow(Ref<Prefab> inPrefab) :
prefab(inPrefab),
SelectionPanel(CreateScope<EditorSelectionPanel>(Selection))
{
const Vector2 defaultSize = Vector2{ 640, 360 };
viewportFramebuffer = CreateRef<FrameBuffer>(true, defaultSize);
viewportFramebuffer->SetTexture(CreateRef<Texture>(defaultSize, GL_RGB, GL_RGB16F, GL_FLOAT));
virtualScene = CreateRef<Scene>();
virtualScene->GetEnvironment()->CurrentSkyType = SkyType::ProceduralSky;
virtualScene->GetEnvironment()->ProceduralSkybox->SunDirection = { 0.58f, 0.34f, -0.74f };
prefab = Prefab::InstanceInScene(inPrefab->Path, virtualScene.get());
prefab->Path = inPrefab->Path;
Ref<Texture> outputTexture = CreateRef<Texture>(defaultSize, GL_RGB);
outputTexture->SetParameter(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
outputTexture->SetParameter(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
auto& previewLight = virtualScene->CreateEntity("_directionalLight").AddComponent<LightComponent>();
previewLight.Type = LightType::Directional;
previewLight.SetCastShadows(true);
previewLight.SyncDirectionWithSky = true;
previewLight.Strength = 5.5f;
}
void PrefabEditorWindow::Update(float ts)
{
}
void PrefabEditorWindow::Draw()
{
RenderScene();
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None;
ImGuiID dockspace_id = ImGui::GetID(prefab->Path.c_str());
ImVec2 dockspace_size;
if (!isInitialized)
{
ImGui::SetNextWindowSize(ImVec2(1280, 720));
}
if(ImGui::Begin(prefab->Path.c_str(), 0, window_flags))
{
dockspace_size = ImGui::GetContentRegionAvail();
ImGui::DockSpace(dockspace_id, dockspace_size, dockspace_flags);
if (ImGui::BeginMenuBar())
{
if (ImGui::BeginMenu("File"))
{
if(ImGui::MenuItem("Save", "Ctrl+S"))
{
Save();
}
ImGui::EndMenu();
}
ImGui::EndMenuBar();
}
}
ImGui::End();
// Programmatically dock windows using DockBuilder API
if (!isInitialized)
{
isInitialized = true;
// Create dock layout for the embedded dockspace
ImGui::DockBuilderRemoveNode(dockspace_id); // Clear any existing layout
ImGui::DockBuilderAddNode(dockspace_id, dockspace_flags | ImGuiDockNodeFlags_DockSpace);
ImGui::DockBuilderSetNodeSize(dockspace_id, dockspace_size);
// Split the dockspace into two areas: left and right
ImGuiID dock_left_id = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Left, 0.25f, nullptr, &dockspace_id);
ImGuiID dock_r_id = ImGui::DockBuilderSplitNode(dockspace_id, ImGuiDir_Right, 0.66f, nullptr, &dockspace_id);
// Dock windows into the created nodes
ImGui::DockBuilderDockWindow(std::string("Prefab Hierarchy## " + prefab->Path).c_str(), dock_left_id);
ImGui::DockBuilderDockWindow(std::string("Viewport##" + prefab->Path).c_str(), dockspace_id);
ImGui::DockBuilderDockWindow(std::string("Properties##" + prefab->Path).c_str(), dock_r_id);
// Commit the dock layout
ImGui::DockBuilderFinish(dockspace_id);
}
if (ImGui::Begin(std::string("Prefab Hierarchy## " + prefab->Path).c_str()))
{
Ref<Scene> scene = virtualScene;
std::string searchQuery = "";
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 8, 8 });
ImGui::InputTextWithHint("##search", "Search entity", &searchQuery, 0, 0, 0);
ImGui::PopStyleVar();
ImGui::SameLine();
if (UI::PrimaryButton("Add Entity", { ImGui::GetContentRegionAvail().x, 0 }))
{
ImGui::OpenPopup("create_entity_popup");
}
if (ImGui::BeginPopup("create_entity_popup"))
{
Nuake::Entity entity;
if (ImGui::MenuItem("Empty"))
{
entity = scene->CreateEntity("Empty");
}
if (ImGui::BeginMenu("3D"))
{
if (ImGui::MenuItem("Camera"))
{
entity = scene->CreateEntity("Camera");
entity.AddComponent<CameraComponent>();
}
if (ImGui::MenuItem("Model"))
{
entity = scene->CreateEntity("Model");
entity.AddComponent<ModelComponent>();
}
if (ImGui::MenuItem("Skinned Model"))
{
entity = scene->CreateEntity("Skinned Model");
entity.AddComponent<SkinnedModelComponent>();
}
if (ImGui::MenuItem("Sprite"))
{
entity = scene->CreateEntity("Sprite");
entity.AddComponent<SpriteComponent>();
}
if (ImGui::MenuItem("Particle Emitter"))
{
entity = scene->CreateEntity("Particle Emitter");
entity.AddComponent<ParticleEmitterComponent>();
}
if (ImGui::MenuItem("Light"))
{
entity = scene->CreateEntity("Light");
entity.AddComponent<LightComponent>();
}
if (ImGui::MenuItem("Quake Map"))
{
entity = scene->CreateEntity("Quake Map");
entity.AddComponent<QuakeMapComponent>();
}
if (ImGui::MenuItem("NavMesh Volume"))
{
entity = scene->CreateEntity("NavMesh Volume");
entity.AddComponent<NavMeshVolumeComponent>();
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Physics"))
{
if (ImGui::MenuItem("Character Controller"))
{
entity = scene->CreateEntity("Character Controller");
entity.AddComponent<CharacterControllerComponent>();
}
if (ImGui::MenuItem("Rigid Body"))
{
entity = scene->CreateEntity("Rigid Body");
entity.AddComponent<RigidBodyComponent>();
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Colliders"))
{
if (ImGui::MenuItem("Box Collider"))
{
entity = scene->CreateEntity("Box Collider");
entity.AddComponent<BoxColliderComponent>();
}
if (ImGui::MenuItem("Sphere Collider"))
{
entity = scene->CreateEntity("Sphere Collider");
entity.AddComponent<SphereColliderComponent>();
}
if (ImGui::MenuItem("Capsule Collider"))
{
entity = scene->CreateEntity("Capsule Collider");
entity.AddComponent<CapsuleColliderComponent>();
}
if (ImGui::MenuItem("Cylinder Collider"))
{
entity = scene->CreateEntity("Cylinder Collider");
entity.AddComponent<CylinderColliderComponent>();
}
if (ImGui::MenuItem("Mesh Collider"))
{
entity = scene->CreateEntity("Mesh Collider");
entity.AddComponent<MeshColliderComponent>();
}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Audio"))
{
if (ImGui::MenuItem("Audio Emitter"))
{
entity = scene->CreateEntity("Audio Emitter");
entity.AddComponent<AudioEmitterComponent>();
}
ImGui::EndMenu();
}
if (entity.IsValid())
{
if (Selection.Type == EditorSelectionType::Entity && Selection.Entity.IsValid())
{
Selection.Entity.AddChild(entity);
}
else
{
auto& camera = virtualScene->m_EditorCamera;
Vector3 newEntityPos = camera->Translation + camera->Direction;
entity.GetComponent<TransformComponent>().SetLocalPosition(newEntityPos);
}
Selection = EditorSelection(entity);
}
ImGui::EndPopup();
}
// Draw a tree of entities.
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(26.f / 255.0f, 26.f / 255.0f, 26.f / 255.0f, 1));
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 4, 4 });
if (ImGui::BeginChild("Scene tree", ImGui::GetContentRegionAvail(), false))
{
if (ImGui::BeginTable("entity_table", 4, ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_SizingStretchProp))
{
ImGui::TableSetupColumn(" Label", ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_IndentDisable | ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("Script", ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_IndentDisable | ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("Visibility ", ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_IndentDisable | ImGuiTableColumnFlags_WidthFixed);
ImGui::TableHeadersRow();
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0, 0));
std::vector<Nuake::Entity> entities = scene->GetAllEntities();
ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanFullWidth;
std::string name = prefab->Root.GetComponent<NameComponent>().Name;
// If selected add selected flag.
if (Selection.Type == EditorSelectionType::Entity && Selection.Entity == prefab->Root)
base_flags |= ImGuiTreeNodeFlags_Selected;
DrawEntityTree(prefab->Root);
ImGui::PopStyleVar();
}
ImGui::EndTable();
if (QueueDeletion.GetHandle() != -1)
{
virtualScene->DestroyEntity(QueueDeletion);
// Clear Selection
Selection = EditorSelection();
QueueDeletion = Nuake::Entity{ (entt::entity)-1, scene.get() };
}
}
ImGui::EndChild();
ImGui::PopStyleVar();
ImGui::PopStyleColor();
}
ImGui::End();
SelectionPanel->Draw(Selection, prefab->Path);
DrawViewportWindow();
}
void PrefabEditorWindow::DrawViewportWindow()
{
//viewportFramebuffer->Bind();
////RenderCommand::SetClearColor(Color(1, 0, 0, 1));
//viewportFramebuffer->Clear();
//viewportFramebuffer->Unbind();
//RenderScene();
if (ImGui::Begin(std::string("Viewport##" + prefab->Path).c_str()))
{
DrawOverlay();
ImGuizmo::BeginFrame();
ImGuizmo::SetOrthographic(false);
ImVec2 regionAvail = ImGui::GetContentRegionAvail();
Vector2 viewportPanelSize = glm::vec2(regionAvail.x, regionAvail.y);
if (viewportFramebuffer->GetSize() != viewportPanelSize)
viewportFramebuffer->QueueResize(viewportPanelSize);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));\
viewportFramebuffer->QueueResize(viewportPanelSize);
ImGui::Image((void*)viewportFramebuffer->GetTexture(GL_COLOR_ATTACHMENT0)->GetID(), regionAvail, ImVec2(0, 1), ImVec2(1, 0));
ImGui::PopStyleVar();
const Vector2& mousePos = Input::GetMousePosition();
ImVec2 imagePos = ImGui::GetWindowPos() + ImGui::GetCursorPos();
const ImVec2& windowPos = ImGui::GetWindowPos();
const auto windowPosNuake = Vector2(windowPos.x, windowPos.y);
const ImVec2& windowSize = ImGui::GetWindowSize();
const bool isInsideWidth = mousePos.x > windowPos.x && mousePos.x < windowPos.x + windowSize.x;
const bool isInsideHeight = mousePos.y > windowPos.y && mousePos.y < windowPos.y + windowSize.y;
isHoveringViewport = isInsideWidth && isInsideHeight;
ImGuizmo::SetDrawlist();
ImGuizmo::AllowAxisFlip(true);
ImGuizmo::SetRect(imagePos.x, imagePos.y + 0.0f, viewportPanelSize.x, viewportPanelSize.y);
auto& editorCam = virtualScene->m_EditorCamera;
isControllingCamera = editorCam->Update(Engine::GetTimestep(), isHoveringViewport);
if (Selection.Type == EditorSelectionType::Entity && !Engine::IsPlayMode())
{
if (!Selection.Entity.IsValid())
{
Selection = EditorSelection();
}
else
{
TransformComponent& tc = Selection.Entity.GetComponent<TransformComponent>();
Matrix4 transform = tc.GetGlobalTransform();
const auto& editorCam = virtualScene->GetCurrentCamera();
Matrix4 cameraView = editorCam->GetTransform();
Matrix4 cameraProjection = editorCam->GetPerspective();
static Vector3 camPreviousPos = virtualScene->m_EditorCamera->Translation;
static Vector3 camNewPos = Vector3(0, 0, 0);
Vector3 camDelta = camNewPos - camPreviousPos;
Vector3 previousGlobalPos = transform[3];
// Imguizmo calculates the delta from the gizmo,
ImGuizmo::Manipulate(
glm::value_ptr(cameraView),
glm::value_ptr(cameraProjection),
CurrentOperation, CurrentMode,
glm::value_ptr(transform), NULL,
UseSnapping ? &CurrentSnapping.x : NULL
);
if (ImGuizmo::IsUsing())
{
// Since imguizmo returns a transform in global space and we want the local transform,
// we need to multiply by the inverse of the parent's global transform in order to revert
// the changes from the parent transform.
Matrix4 localTransform = Matrix4(transform);
Vector3 newGlobalPos = transform[3];
if (ImGui::IsKeyDown(ImGuiKey_LeftShift))
{
Vector3 positionDelta = newGlobalPos - previousGlobalPos;
virtualScene->m_EditorCamera->Translation += positionDelta;
camNewPos = virtualScene->m_EditorCamera->Translation;
}
ParentComponent& parent = Selection.Entity.GetComponent<ParentComponent>();
if (parent.HasParent)
{
const auto& parentTransformComponent = parent.Parent.GetComponent<TransformComponent>();
const Matrix4& parentTransform = parentTransformComponent.GetGlobalTransform();
localTransform = glm::inverse(parentTransform) * localTransform;
}
// Decompose local transform
float decomposedPosition[3];
float decomposedEuler[3];
float decomposedScale[3];
ImGuizmo::DecomposeMatrixToComponents(glm::value_ptr(localTransform), decomposedPosition, decomposedEuler, decomposedScale);
const auto& localPosition = Vector3(decomposedPosition[0], decomposedPosition[1], decomposedPosition[2]);
const auto& localScale = Vector3(decomposedScale[0], decomposedScale[1], decomposedScale[2]);
localTransform[0] /= localScale.x;
localTransform[1] /= localScale.y;
localTransform[2] /= localScale.z;
const auto& rotationMatrix = Matrix3(localTransform);
const Quat& localRotation = glm::normalize(Quat(rotationMatrix));
const Matrix4& rotationMatrix4 = glm::mat4_cast(localRotation);
const Matrix4& scaleMatrix = glm::scale(Matrix4(1.0f), localScale);
const Matrix4& translationMatrix = glm::translate(Matrix4(1.0f), localPosition);
const Matrix4& newLocalTransform = translationMatrix * rotationMatrix4 * scaleMatrix;
tc.Translation = localPosition;
if (CurrentOperation != ImGuizmo::SCALE)
{
tc.Rotation = localRotation;
}
tc.Scale = localScale;
tc.LocalTransform = newLocalTransform;
tc.Dirty = true;
}
}
}
if (ImGui::IsWindowHovered() && isHoveringViewport && !isViewportFocused && ImGui::GetIO().WantCaptureMouse)
{
ImGui::FocusWindow(ImGui::GetCurrentWindow());
}
isViewportFocused = ImGui::IsWindowFocused();
if (ImGui::GetIO().WantCaptureMouse && isHoveringViewport && ImGui::IsMouseClicked(ImGuiMouseButton_Left) && isViewportFocused)
{
auto& gbuffer = virtualScene->m_SceneRenderer->GetGBuffer();
auto pixelPos = (Input::GetMousePosition() - windowPosNuake);
pixelPos.y = gbuffer.GetSize().y - pixelPos.y; // imgui coords are inverted on the Y axi
gbuffer.Bind();
if (const int result = gbuffer.ReadPixel(3, pixelPos); result > 0)
{
auto ent = Nuake::Entity{ (entt::entity)(result - 1), virtualScene.get() };
if (ent.IsValid())
{
Selection = EditorSelection(ent);
virtualScene->m_SceneRenderer->mOutlineEntityID = (uint32_t)ent.GetHandle();
}
}
else
{
Selection = EditorSelection(); // None
}
gbuffer.Unbind();
}
}
ImGui::End();
}
void PrefabEditorWindow::DrawOverlay()
{
if (Engine::GetGameState() == GameState::Playing)
{
return;
}
// FIXME-VIEWPORT: Select a default viewport
const float DISTANCE = 10.0f;
int corner = 0;
ImGuiIO& io = ImGui::GetIO();
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
window_flags |= ImGuiWindowFlags_NoMove;
ImGuiViewport* viewport = ImGui::GetWindowViewport();
ImVec2 work_area_pos = ImGui::GetCurrentWindow()->Pos; // Instead of using viewport->Pos we use GetWorkPos() to avoid menu bars, if any!
ImVec2 work_area_size = ImGui::GetCurrentWindow()->Size;
ImVec2 window_pos = ImVec2((corner & 1) ? (work_area_pos.x + work_area_size.x - DISTANCE) : (work_area_pos.x + DISTANCE), (corner & 2) ? (work_area_pos.y + work_area_size.y - DISTANCE) : (work_area_pos.y + DISTANCE));
ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f);
ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 32.0f);
if (ImGui::Begin("ActionBar2", 0, window_flags))
{
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 2));
ImGui::PushStyleColor(ImGuiCol_Button, IM_COL32(0, 0, 0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 100);
bool selectedMode = CurrentOperation == ImGuizmo::OPERATION::TRANSLATE;
if (selectedMode)
{
Color color = Engine::GetProject()->Settings.PrimaryColor;
ImGui::PushStyleColor(ImGuiCol_Button, { color.r, color.g, color.b, 1.0f });
}
if (ImGui::Button(ICON_FA_ARROWS_ALT , ImVec2(30, 28)) || (ImGui::Shortcut(ImGuiKey_W, 0, ImGuiInputFlags_RouteGlobalLow) && !ImGui::IsAnyItemActive() && !isControllingCamera))
{
CurrentOperation = ImGuizmo::OPERATION::TRANSLATE;
}
UI::Tooltip("Translate");
if (selectedMode)
{
ImGui::PopStyleColor();
}
ImGui::SameLine();
selectedMode = CurrentOperation == ImGuizmo::OPERATION::ROTATE;
if (selectedMode)
{
Color color = Engine::GetProject()->Settings.PrimaryColor;
ImGui::PushStyleColor(ImGuiCol_Button, { color.r, color.g, color.b, 1.0f });
}
if (ImGui::Button(ICON_FA_SYNC_ALT, ImVec2(30, 28)) || (ImGui::Shortcut(ImGuiKey_E, 0, ImGuiInputFlags_RouteGlobalLow) && !ImGui::IsAnyItemActive() && !isControllingCamera))
{
CurrentOperation = ImGuizmo::OPERATION::ROTATE;
}
UI::Tooltip("Rotate");
if (selectedMode)
{
ImGui::PopStyleColor();
}
ImGui::SameLine();
selectedMode = CurrentOperation == ImGuizmo::OPERATION::SCALE;
if (selectedMode)
{
Color color = Engine::GetProject()->Settings.PrimaryColor;
ImGui::PushStyleColor(ImGuiCol_Button, { color.r, color.g, color.b, 1.0f });
}
if (ImGui::Button(ICON_FA_EXPAND_ALT, ImVec2(30, 28)) || (ImGui::Shortcut(ImGuiKey_R, 0, ImGuiInputFlags_RouteGlobalLow) && !ImGui::IsAnyItemActive() && !isControllingCamera))
{
CurrentOperation = ImGuizmo::OPERATION::SCALE;
}
UI::Tooltip("Scale");
if (selectedMode)
{
ImGui::PopStyleColor();
}
ImGui::SameLine();
selectedMode = CurrentMode == ImGuizmo::MODE::WORLD;
if (selectedMode)
{
Color color = Engine::GetProject()->Settings.PrimaryColor;
ImGui::PushStyleColor(ImGuiCol_Button, { color.r, color.g, color.b, 1.0f });
}
if (ImGui::Button(ICON_FA_GLOBE, ImVec2(30, 28)))
{
CurrentMode = ImGuizmo::MODE::WORLD;
}
UI::Tooltip("Global Transformation");
if (selectedMode)
{
ImGui::PopStyleColor();
}
ImGui::SameLine();
selectedMode = CurrentMode == ImGuizmo::MODE::LOCAL;
if (selectedMode)
{
Color color = Engine::GetProject()->Settings.PrimaryColor;
ImGui::PushStyleColor(ImGuiCol_Button, { color.r, color.g, color.b, 1.0f });
}
if (ImGui::Button(ICON_FA_CUBE, ImVec2(30, 28)))
{
CurrentMode = ImGuizmo::MODE::LOCAL;
}
UI::Tooltip("Local Transformation");
if (selectedMode)
{
ImGui::PopStyleColor();
}
ImGui::SameLine();
ImGui::SameLine();
ImGui::PushItemWidth(75);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { 6, 6 });
ImGui::DragFloat("##snapping", &CurrentSnapping.x, 0.01f, 0.0f, 100.0f);
CurrentSnapping = { CurrentSnapping.x, CurrentSnapping.x, CurrentSnapping.z };
ImGui::PopStyleVar();
ImGui::PopItemWidth();
UI::Tooltip("Snapping");
ImGui::PopStyleVar();
ImGui::PopStyleVar();
ImGui::PopStyleColor();
}
ImGui::PopStyleVar();
ImGui::End();
int corner2 = 1;
work_area_pos = ImGui::GetCurrentWindow()->Pos; // Instead of using viewport->Pos we use GetWorkPos() to avoid menu bars, if any!
work_area_size = ImGui::GetCurrentWindow()->Size;
window_pos = ImVec2((corner2 & 1) ? (work_area_pos.x + work_area_size.x - DISTANCE) : (work_area_pos.x + DISTANCE), (corner2 & 2) ? (work_area_pos.y + work_area_size.y - DISTANCE) : (work_area_pos.y + DISTANCE));
window_pos_pivot = ImVec2((corner2 & 1) ? 1.0f : 0.0f, (corner2 & 2) ? 1.0f : 0.0f);
ImGui::SetNextWindowPos(window_pos + ImVec2(0, 40), ImGuiCond_Always, window_pos_pivot);
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 32.0f);
ImGui::SetNextWindowSize(ImVec2(16, ImGui::GetContentRegionAvail().y - DISTANCE * 2.0 - 40.0));
if (ImGui::Begin("Controls2", 0, window_flags))
{
const auto& editorCam = virtualScene->m_EditorCamera;
const float camSpeed = editorCam->Speed;
const float maxSpeed = 50.0f;
const float minSpeed = 0.05f;
const float normalizedSpeed = glm::clamp((camSpeed / maxSpeed), 0.0f, 1.0f);
ImVec2 start = ImGui::GetWindowPos() - ImVec2(0.0, 4.0);
ImVec2 end = start + ImGui::GetWindowSize() - ImVec2(0, 16.0);
ImVec2 startOffset = ImVec2(start.x, end.y - (normalizedSpeed * (ImGui::GetWindowHeight() - 20.0)));
ImGui::GetWindowDrawList()->AddRectFilled(startOffset + ImVec2(0, 10.0), end + ImVec2(0.0, 20.0), IM_COL32(255, 255, 255, 180), 8.0f, ImDrawFlags_RoundCornersAll);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 100);
ImGui::PopStyleVar();
}
ImGui::PopStyleVar();
ImGui::End();
}
void PrefabEditorWindow::RenderScene()
{
virtualScene->Update(Engine::GetTimestep());
Ref<SceneRenderer> sceneRenderer = virtualScene->m_SceneRenderer;
Ref<EditorCamera> editorCam = virtualScene->m_EditorCamera;
editorCam->OnWindowResize(viewportFramebuffer->GetSize().x, viewportFramebuffer->GetSize().y);
virtualScene->Draw(*viewportFramebuffer.get());
sceneRenderer->BeginRenderScene(editorCam->GetPerspective(), editorCam->GetTransform(), editorCam->Translation);
sceneRenderer->RenderScene(*virtualScene, *viewportFramebuffer.get(), true);
}
void PrefabEditorWindow::DrawEntityTree(Nuake::Entity e)
{
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2{ 0.0f, 0.0f });
ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_FramePadding | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAllColumns;
NameComponent& nameComponent = e.GetComponent<NameComponent>();
std::string name = nameComponent.Name;
ParentComponent& parent = e.GetComponent<ParentComponent>();
if (Selection.Type == EditorSelectionType::Entity && Selection.Entity == e)
base_flags |= ImGuiTreeNodeFlags_Selected;
ImGui::TableNextColumn();
// Write in normal font.
// ImGui::PushFont(normalFont);
// If has no childrens draw tree node leaf
if (parent.Children.size() <= 0)
{
base_flags |= ImGuiTreeNodeFlags_Leaf;
}
if (nameComponent.IsPrefab && e.HasComponent<PrefabComponent>())
{
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(0, 255, 0, 255));
}
else if (e.HasComponent<BSPBrushComponent>())
{
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 255, 255, 120));
}
//if (!m_IsRenaming && m_ShouldUnfoldEntityTree && Selection.Type == EditorSelectionType::Entity && e.GetScene()->EntityIsParent(Selection.Entity, e))
//{
// ImGui::SetNextItemOpen(true);
//}
auto cursorPos = ImGui::GetCursorPos();
ImGui::SetNextItemAllowOverlap();
bool open = ImGui::TreeNodeEx(name.c_str(), base_flags);
if (isRenaming)
{
if (Selection.Type == EditorSelectionType::Entity && Selection.Entity == e)
{
ImGui::SetCursorPosY(cursorPos.y);
ImGui::Indent();
ImGui::InputText("##renamingEntity", &name);
ImGui::Unindent();
if (Input::IsKeyDown(Key::ENTER))
{
nameComponent.Name = name;
isRenaming = false;
}
}
}
bool isDragging = false;
if (nameComponent.IsPrefab && e.HasComponent<PrefabComponent>() || e.HasComponent<BSPBrushComponent>())
{
ImGui::PopStyleColor();
}
else if (!isRenaming && ImGui::BeginDragDropSource())
{
ImGui::SetDragDropPayload("ENTITYPrefab", (void*)&e, sizeof(Nuake::Entity));
ImGui::Text(name.c_str());
ImGui::EndDragDropSource();
}
if (ImGui::BeginDragDropTarget())
{
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ENTITYPrefab"))
{
Nuake::Entity payload_entity = *(const Nuake::Entity*)payload->Data;
// Check if entity is already parent.
ParentComponent& parentPayload = payload_entity.GetComponent<ParentComponent>();
if (!payload_entity.EntityContainsItself(payload_entity, e) && parentPayload.Parent != e && std::count(parent.Children.begin(), parent.Children.end(), payload_entity) == 0)
{
if (parentPayload.HasParent)
{
// Erase remove idiom.
ParentComponent& childOfParent = parentPayload.Parent.GetComponent<ParentComponent>();
childOfParent.Children.erase(std::remove(childOfParent.Children.begin(), childOfParent.Children.end(), payload_entity), childOfParent.Children.end());
}
parentPayload.Parent = e;
parentPayload.HasParent = true;
parent.Children.push_back(payload_entity);
}
}
else if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("_NetScript"))
{
char* file = (char*)payload->Data;
std::string fullPath = std::string(file, 512);
std::string path = Nuake::FileSystem::AbsoluteToRelative(std::move(fullPath));
if (e.HasComponent<NetScriptComponent>())
{
e.GetComponent<NetScriptComponent>().ScriptPath = path;
}
else
{
e.AddComponent<NetScriptComponent>().ScriptPath = path;
}
}
ImGui::EndDragDropTarget();
}
if (!isDragging && ImGui::IsItemHovered() && ImGui::IsMouseReleased(0))
{
// We selected another another that we werent renaming
if (Selection.Entity != e)
{
isRenaming = false;
}
Selection = EditorSelection(e);
}
if (!isDragging && (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(0)) || Input::IsKeyPressed(Key::F2))
{
isRenaming = true;
}
if (!isRenaming && Selection.Type == EditorSelectionType::Entity && Input::IsKeyPressed(Key::DELETE_KEY))
{
QueueDeletion = Selection.Entity;
}
if (ImGui::BeginPopupContextItem())
{
Selection = EditorSelection(e);
Nuake::Entity entity = Selection.Entity;
if (entity.HasComponent<CameraComponent>())
{
// Moves the editor camera to the camera position and direction.
if (ImGui::Selectable("Focus camera"))
{
Ref<EditorCamera> editorCam = virtualScene->m_EditorCamera;
Vector3 camDirection = entity.GetComponent<CameraComponent>().CameraInstance->GetDirection();
camDirection.z *= -1.0f;
editorCam->SetTransform(glm::inverse(entity.GetComponent<TransformComponent>().GetGlobalTransform()));
}
ImGui::Separator();
}
if (ImGui::Selectable("Remove"))
{
QueueDeletion = e;
}
if (entity.GetComponent<ParentComponent>().HasParent && ImGui::Selectable("Move to root"))
{
auto& parentComp = Selection.Entity.GetComponent<ParentComponent>();
if (parentComp.HasParent)
{
auto& parentParentComp = parentComp.Parent.GetComponent<ParentComponent>();
parentParentComp.RemoveChildren(entity);
parentComp.HasParent = false;
}
}
if (ImGui::Selectable("Save entity as a new prefab"))
{
Ref<Prefab> newPrefab = Prefab::CreatePrefabFromEntity(Selection.Entity);
std::string savePath = Nuake::FileDialog::SaveFile("*.prefab");
if (!String::EndsWith(savePath, ".prefab"))
{
savePath += ".prefab";
}
if (!savePath.empty())
{
newPrefab->SaveAs(savePath);
Selection.Entity.AddComponent<PrefabComponent>().PrefabInstance = newPrefab;
}
}
ImGui::EndPopup();
}
ImGui::TableNextColumn();
ImGui::TextColored(ImVec4(0.5, 0.5, 0.5, 1.0), "");
ImGui::TableNextColumn();
{
bool hasScript = e.HasComponent<NetScriptComponent>();
if (hasScript)
{
std::string scrollIcon = std::string(ICON_FA_SCROLL) + "##" + name;
ImGui::PushStyleColor(ImGuiCol_Button, { 0, 0, 0, 0 });
if (ImGui::Button(scrollIcon.c_str(), { 40, 0 }))
{
auto& scriptComponent = e.GetComponent<NetScriptComponent>();
if (!scriptComponent.ScriptPath.empty() && FileSystem::FileExists(scriptComponent.ScriptPath))
{
OS::OpenIn(FileSystem::RelativeToAbsolute(scriptComponent.ScriptPath));
}
}
ImGui::PopStyleColor();
}
}
ImGui::TableNextColumn();
{
bool& isVisible = e.GetComponent<VisibilityComponent>().Visible;
std::string visibilityIcon = isVisible ? ICON_FA_EYE : ICON_FA_EYE_SLASH;
ImGui::PushStyleColor(ImGuiCol_Button, { 0, 0, 0, 0 });
if (ImGui::Button(visibilityIcon.c_str(), { 40, 0 }))
{
isVisible = !isVisible;
}
ImGui::PopStyleColor();
}
if (open)
{
// Caching list to prevent deletion while iterating.
std::vector<Nuake::Entity> childrens = parent.Children;
for (auto& c : childrens)
DrawEntityTree(c);
ImGui::TreePop();
}
ImGui::PopStyleVar();
//ImGui::PopFont();
}
void PrefabEditorWindow::Save()
{
Ref<Prefab> newPrefab = Prefab::CreatePrefabFromEntity(prefab->Root);
newPrefab->Path = prefab->Path;
newPrefab->SaveAs(newPrefab->Path);
}

View File

@@ -0,0 +1,53 @@
#pragma once
#include "src/Core/Core.h"
#include "src/Core/Maths.h"
#include "../EditorSelectionPanel.h"
#include <src/Vendors/imgui/ImGuizmo.h>
namespace Nuake
{
class Prefab;
class Scene;
class FrameBuffer;
class Texture;
class Entity;
}
class PrefabEditorWindow
{
public:
PrefabEditorWindow(Ref<Nuake::Prefab> prefab);
~PrefabEditorWindow() {
ASSERT(false);
};
void Update(float ts);
void Draw();
private:
Ref<Nuake::Prefab> prefab;
Ref<Nuake::Scene> virtualScene;
Ref<Nuake::FrameBuffer> viewportFramebuffer;
Ref<Nuake::Texture> viewportTexture;
bool isViewportFocused;
bool isHoveringViewport;
bool isRenaming;
bool isInitialized = false;
Scope<EditorSelectionPanel> SelectionPanel;
EditorSelection Selection;
Nuake::Entity QueueDeletion;
ImGuizmo::OPERATION CurrentOperation = ImGuizmo::TRANSLATE;
ImGuizmo::MODE CurrentMode = ImGuizmo::WORLD;
bool UseSnapping = true;
Nuake::Vector3 CurrentSnapping = Nuake::Vector3{ 0.0f, 0.0f, 0.0f };
bool isControllingCamera = false;
private:
void DrawViewportWindow();
void DrawOverlay();
void RenderScene();
void DrawEntityTree(Nuake::Entity e);
void Save();
};

View File

@@ -184,11 +184,11 @@ void ProjectSettingsCategoryPhysics::Draw()
Engine::SetPhysicsStep(Engine::GetProject()->Settings.PhysicsStep);
}
ImGui::DragInt("Maximum SubSteps", &Engine::GetProject()->Settings.MaxPhysicsSubStep, 1.0f, 8.0f, 128);
ImGui::DragInt("Maximum SubSteps", &Engine::GetProject()->Settings.MaxPhysicsSubStep, 1, 8, 128);
ImGui::DragInt("Maximum Bodies", &Engine::GetProject()->Settings.MaxPhysicsBodies, 1.0f, 256.0f, 8000);
ImGui::DragInt("Maximum Body Pair", &Engine::GetProject()->Settings.MaxPhysicsBodyPair, 1.0f, 256.0f, 4096.0f);
ImGui::DragInt("Maximum Contact Constraint", &Engine::GetProject()->Settings.MaxPhysicsContactConstraints, 1.0f, 256.0f, 4096.0f);
ImGui::DragInt("Maximum Bodies", &Engine::GetProject()->Settings.MaxPhysicsBodies, 1.0f, 256, 8000);
ImGui::DragInt("Maximum Body Pair", &Engine::GetProject()->Settings.MaxPhysicsBodyPair, 1.0f, 256, 4096);
ImGui::DragInt("Maximum Contact Constraint", &Engine::GetProject()->Settings.MaxPhysicsContactConstraints, 1.0f, 256, 4096);
}
ProjectSettingsCategoryAudio::ProjectSettingsCategoryAudio(Ref<Nuake::Project> project) :

View File

@@ -9,12 +9,12 @@ void UIDemoWindow::Draw()
{
using namespace Nuake;
UI::BeginWindow("UI Demo");
{
UI::PrimaryButton("Primary Button");
UI::SecondaryButton("Secondary Button");
UI::FloatSlider("Float slider", floatSlider);
UI::CheckBox("Checkbox", checkbox);
}
UI::EndWindow();
//UI::BeginWindow("UI Demo");
//{
// UI::PrimaryButton("Primary Button");
// UI::SecondaryButton("Secondary Button");
// UI::FloatSlider("Float slider", floatSlider);
// UI::CheckBox("Checkbox", checkbox);
//}
//UI::EndWindow();
}

View File

@@ -81,6 +81,11 @@ namespace Nuake
ParseRecentFile();
if (_Projects.size() > 0)
{
SelectedProject = 0;
}
// Load Nuake logo
_NuakeLogo = TextureManager::Get()->GetTexture(NUAKE_LOGO_PATH);
}
@@ -110,8 +115,41 @@ namespace Nuake
Engine::GetCurrentWindow()->SetTitle("Nuake Engine - Editing " + project->Name);
}
void WelcomeWindow::ImportProject(const std::string& file)
{
if (file != "" && String::EndsWith(file, ".project"))
{
// Prevent importing the same project twice in the list
bool alreadyContainsProject = false;
for (auto& p : _Projects)
{
if (p.Path == file)
{
alreadyContainsProject = true;
}
}
if (!alreadyContainsProject)
{
_Projects.push_back(ProjectPreview(file));
SaveRecentFile();
}
}
}
void WelcomeWindow::Draw()
{
if (!queuedRemovalPath.empty())
{
std::erase_if(_Projects, [&](ProjectPreview preview)
{
return preview.Path == queuedRemovalPath;
});
queuedRemovalPath = "";
SaveRecentFile();
}
// Make viewport fullscreen
ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->Pos);
@@ -145,6 +183,7 @@ namespace Nuake
DrawRightControls();
ImGui::SameLine();
DrawRecentProjectsSection();
ImGui::End();
@@ -158,36 +197,30 @@ namespace Nuake
ImVec2 projectsWindowSize = ImGui::GetContentRegionAvail();
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0, 0, 0, 0));
ImGui::BeginChild("Projects", projectsWindowSize, false);
ImGui::BeginChild("Projects", projectsWindowSize);
{
//ImGui::Dummy({ 4, 4 });
//ImGui::SameLine();
//{
// auto font = UIFont(Bold);
// ImGui::Text("Recent Projects");
//}
ImGui::PopStyleColor();
for (uint32_t i = 0; i < std::size(_Projects); i++)
{
DrawProjectItem(i);
}
const float itemHeight = 100.0f;
ImGui::Dummy({ 1, 4 });
ImGui::SameLine();
const float itemHeight = 60.0f;
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
if (ImGui::Button("Import an existing project", ImVec2(ImGui::GetContentRegionAvail().x, itemHeight)))
if (UI::SecondaryButton("Import or Drag a Project", Vector2(ImGui::GetContentRegionAvail().x - 8, itemHeight)))
{
const std::string path = FileDialog::OpenFile("Project file(.project)\0*.project\0");
if (path != "" && String::EndsWith(path, ".project"))
{
// Prevent importing the same project twice in the list
bool alreadyContainsProject = false;
for (auto& p : _Projects)
{
if (p.Path == path)
{
alreadyContainsProject = true;
}
}
if (!alreadyContainsProject)
{
_Projects.push_back(ProjectPreview(path));
}
}
ImportProject(path);
}
ImGui::PopStyleColor();
}
@@ -196,8 +229,10 @@ namespace Nuake
void WelcomeWindow::DrawProjectItem(const uint32_t itemIndex)
{
ImGui::Dummy({ 4, 4 });
ImGui::SameLine();
const ProjectPreview& project = _Projects[itemIndex];
const uint32_t itemHeight = 120;
const uint32_t itemHeight = 56;
const float cursorYStart = ImGui::GetCursorPosY();
const std::string selectableName = "##" + std::to_string(itemIndex);
@@ -211,7 +246,24 @@ namespace Nuake
draw_list->ChannelsSetCurrent(1);
//ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0, 0, 0, 0));
bool result = ImGui::Selectable(selectableName.c_str(), SelectedProject == itemIndex, ImGuiSelectableFlags_AllowOverlap | ImGuiSelectableFlags_AllowDoubleClick, ImVec2(ImGui::GetContentRegionAvail().x, itemHeight));
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 8.0f);
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.25, 0.25, 0.5, 0.0));
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.25, 0.25, 0.5, 0.0));
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.25, 0.25, 0.5, 0.0));
bool result = ImGui::Selectable(selectableName.c_str(), SelectedProject == itemIndex, ImGuiSelectableFlags_AllowOverlap | ImGuiSelectableFlags_AllowDoubleClick, ImVec2(ImGui::GetContentRegionAvail().x - 12, itemHeight));
ImGui::PopStyleVar();
if (ImGui::BeginPopupContextWindow(selectableName.c_str()))
{
if (ImGui::MenuItem("Remove from list"))
{
queuedRemovalPath = _Projects[itemIndex].Path;
}
ImGui::EndPopup();
}
if (result)
{
SelectedProject = itemIndex;
@@ -221,12 +273,23 @@ namespace Nuake
{
SaveRecentFile();
queuedProjectPath = _Projects[SelectedProject].Path;
queuedProjectPath = _Projects[itemIndex].Path;
}
//ImGui::PopStyleColor();
draw_list->ChannelsMerge();
ImU32 color = IM_COL32(63, 63, 66, 128);
if (isSelected)
{
color = IM_COL32(63, 69, 79, 255);
}
else if (ImGui::IsItemHovered())
{
color = IM_COL32(20, 20, 20, 128);
}
if (isSelected && ImGui::IsKeyPressed(ImGuiKey_Delete))
{
queuedRemovalPath = _Projects[SelectedProject].Path;
}
if (result)
{
@@ -234,33 +297,62 @@ namespace Nuake
}
//ImGui::PopStyleColor();
const ImVec2 padding = ImVec2(25.0f, 20.0f);
const ImVec2 iconSize = ImVec2(100, 100);
ImGui::SetCursorPos(ImVec2(padding.x / 2.0, padding.y / 2.0) + ImVec2(0, cursorYStart));
draw_list->ChannelsSetCurrent(0);
ImVec2 p_min = ImGui::GetItemRectMin();
ImVec2 p_max = ImGui::GetItemRectMax();
ImGui::GetWindowDrawList()->AddRectFilled(p_min, p_max, color, 4.0f);
draw_list->ChannelsMerge();
ImGui::PopStyleColor(3);
const ImVec2 padding = ImVec2(16.0f, 0.0f);
const ImVec2 iconSize = ImVec2(54, 54.0f);
ImGui::SetCursorPos(ImVec2(padding.x / 2.0, padding.y / 2.0) + ImVec2(4, cursorYStart));
if (project.ProjectIcon)
{
ImGui::Image((ImTextureID)project.ProjectIcon->GetID(), iconSize, ImVec2(0, 1), ImVec2(1, 0));
}
else
{
ImGui::Image((void*)Nuake::TextureManager::Get()->GetTexture("Resources/Images/cube.png")->GetID(), iconSize, ImVec2(0, 1), ImVec2(1, 0));
}
ImGui::SameLine();
ImGui::SetCursorPosX(padding.x + iconSize.x + padding.x);
ImGui::SetCursorPosX(padding.x + iconSize.x);
ImGui::SetCursorPosX(padding.x + iconSize.x + padding.x);
ImGui::SetCursorPosY(cursorYStart + padding.y);
ImGui::SetCursorPosY(cursorYStart + 8.0f);
{
UIFont boldfont = UIFont(Fonts::LargeBold);
ImGui::Text(project.Name.c_str());
UIFont boldfont = UIFont(Fonts::Normal);
if (isSelected)
{
ImGui::TextColored(ImVec4(119.0f / 255.0f, 187.0f / 255.0f, 1, 255.0f), project.Name.c_str());
}
else
{
ImGui::Text(project.Name.c_str());
}
}
ImGui::SetCursorPosY(cursorYStart + padding.y + 34.f);
ImGui::SetCursorPosY(cursorYStart + 28.f);
{
ImGui::SetCursorPosX(padding.x + iconSize.x + padding.x);
UIFont boldfont = UIFont(Fonts::Bold);
ImGui::Text(project.Description.c_str());
ImGui::SetCursorPosX(padding.x + iconSize.x);
UIFont boldfont = UIFont(Fonts::Normal);
if (isSelected)
{
ImGui::TextColored(ImVec4(119.0f / 255.0f, 187.0f / 255.0f, 1, 255.0f), (ICON_FA_INFO_CIRCLE + std::string(" ") + project.Description).c_str());
}
else
{
ImGui::TextColored(ImVec4(1, 1, 1, 0.4), (ICON_FA_INFO_CIRCLE + std::string(" ") + project.Description).c_str());
}
}
ImGui::SetCursorPosY(cursorYStart + itemHeight + 32.0f);
ImGui::SetCursorPosY(cursorYStart + itemHeight + 4.0f);
ImGui::Dummy({ 4, 2 });
}
void WelcomeWindow::DrawRightControls()
@@ -276,56 +368,17 @@ namespace Nuake
const ImVec2 buttonSize = ImVec2(ImGui::GetContentRegionAvail().x, buttonHeight);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.14f, 0.5f));
const std::string buttonLabel = std::string(ICON_FA_FOLDER_PLUS) + " New Game Project...";
const std::string buttonLabel = std::string(ICON_FA_FOLDER_PLUS) + " New Project...";
if (Nuake::UI::PrimaryButton(buttonLabel.c_str(), { buttonSize.x, buttonSize.y }))
{
_Editor->isCreatingNewProject = true;
//
//std::string selectedProject = FileDialog::SaveFile("Project file\0*.project");
//
//if (!selectedProject.empty())
//{
// if(!String::EndsWith(selectedProject, ".project"))
// selectedProject += ".project";
//
// auto backslashSplits = String::Split(selectedProject, '\\');
// auto fileName = backslashSplits[backslashSplits.size() - 1];
// std::string finalPath = String::Split(selectedProject, '.')[0];
// if (String::EndsWith(fileName, ".project"))
// {
// // We need to create a folder
// if (const auto& dirPath = finalPath;
// !std::filesystem::create_directory(dirPath))
// {
// // Should we continue?
// Logger::Log("Failed creating project directory: " + dirPath);
// }
// finalPath += "\\" + fileName;
// }
// auto project = Project::New(String::Split(fileName, '.')[0], "no description", finalPath);
// Engine::LoadProject(project);
// Engine::SetCurrentScene(Scene::New());
// project->Save();
// auto projectPreview = ProjectPreview();
// projectPreview.Name = project->Name;
// projectPreview.Description = project->Description;
// projectPreview.Path = project->FullPath;
// projectPreview.ProjectIcon = nullptr;
// _Projects.push_back(projectPreview);
//}
}
ImGui::PopStyleVar(2);
ImGui::Separator();
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.16f, 0.5f));
const std::string buttonLabelOpen = std::string(ICON_FA_FOLDER_OPEN) + " Load Selected Project";
const std::string buttonLabelOpen = std::string(ICON_FA_FOLDER_OPEN) + " Load Project";
bool hasProjectSelected = false;
if (SelectedProject < std::size(_Projects) && SelectedProject >= 0)
@@ -356,10 +409,10 @@ namespace Nuake
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.09f, 0.5f));
const std::string buttonLabelDoc = std::string(ICON_FA_EXTERNAL_LINK_SQUARE_ALT) + " Documentation";
const std::string buttonLabelDoc = std::string(ICON_FA_EXTERNAL_LINK_SQUARE_ALT) + " Documentation";
if (Nuake::UI::SecondaryButton(buttonLabelDoc, { buttonSize.x, buttonSize.y }))
{
OS::OpenURL("https://nuake.readthedocs.io/en/latest/index.html");
OS::OpenURL("https://docs.readthedocs.io/en/latest/index.html");
}
ImGui::PopStyleVar(2);
}

View File

@@ -42,6 +42,8 @@ namespace Nuake
int32_t SelectedProject = -1;
std::vector<ProjectPreview> _Projects;
std::string queuedProjectPath;
std::string queuedRemovalPath;
public:
WelcomeWindow(Nuake::EditorInterface* editor);
~WelcomeWindow() = default;
@@ -50,6 +52,9 @@ namespace Nuake
bool IsProjectQueued() const { return !queuedProjectPath.empty(); };
void LoadQueuedProject();
void ImportProject(const std::string& file);
private:
void DrawRecentProjectsSection();
void DrawProjectItem(const uint32_t projectPreview);

5
Editor/test.html Normal file
View File

@@ -0,0 +1,5 @@
<div>
<div class="main">
<p>Hello</p>
</div>
</div>

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2023 Antoine Pilote
Copyright (c) 2023-2025 Antoine Pilote
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.

View File

@@ -10,20 +10,24 @@
#include "src/Core/Input.h"
#include "src/Rendering/Renderer.h"
#include "src/Rendering/Renderer2D.h"
#include "src/Scripting/ScriptingEngine.h"
#include "src/Scripting/ScriptingEngineNet.h"
#include "src/Threading/JobSystem.h"
#include "src/Core/RegisterCoreTypes.h"
#include "src/Modules/Modules.h"
#include "src/Subsystems/EngineSubsystemScriptable.h"
#include <GLFW/glfw3.h>
#include <imgui/imgui_impl_glfw.h>
#include <imgui/imgui_impl_opengl3.h>
#include <Tracy.hpp>
namespace Nuake
{
Ref<Project> Engine::currentProject;
Ref<Window> Engine::currentWindow;
std::string Engine::queuedScene = "";
GameState Engine::gameState = GameState::Stopped;
@@ -36,6 +40,10 @@ namespace Nuake
void Engine::Init()
{
//Window::Get()->OnWindowSetScene().AddStatic(&Engine::OnWindowSetScene);
ScriptingEngineNet::Get().OnGameAssemblyLoaded().AddStatic(&Engine::OnScriptingEngineGameAssemblyLoaded);
AudioManager::Get().Initialize();
PhysicsManager::Get().Init();
NavManager::Get().Initialize();
@@ -47,7 +55,11 @@ namespace Nuake
Renderer2D::Init();
Logger::Log("Engine initialized");
RegisterCoreTypes::RegisterCoreComponents();
Modules::StartupModules();
InitializeCoreSubsystems();
}
void Engine::Tick()
@@ -60,10 +72,53 @@ namespace Nuake
timeStep = time - lastFrameTime;
lastFrameTime = time;
if (Engine::IsPlayMode())
{
if (!queuedScene.empty())
{
Ref<Scene> nextScene = Scene::New();
if (FileSystem::FileExists(queuedScene))
{
const std::string& fileContent = FileSystem::ReadFile(queuedScene);
nextScene->Path = queuedScene;
nextScene->Deserialize(json::parse(fileContent));
// Uninit current scene
GetCurrentScene()->OnExit();
// Set new scene
SetCurrentScene(nextScene);
// Init new scene
PhysicsManager::Get().ReInit();
GetCurrentScene()->OnInit();
queuedScene = "";
}
}
}
float scaledTimeStep = timeStep * timeScale;
// Tick all subsystems
if (Engine::IsPlayMode())
{
for (auto subsystem : subsystems)
{
if (subsystem == nullptr)
continue;
if (subsystem->CanEverTick())
{
subsystem->Tick(scaledTimeStep);
}
}
}
// Dont update if no scene is loaded.
if (currentWindow->GetScene())
{
float scaledTimeStep = timeStep * timeScale;
currentWindow->Update(scaledTimeStep);
// Play mode update all the entities, Editor does not.
@@ -92,11 +147,13 @@ namespace Nuake
lastFrameTime = (float)glfwGetTime(); // Reset timestep timer.
// Dont trigger init if already in player mode.
if (GetGameState() == GameState::Playing)
if (GetGameState() == GameState::Playing || GetGameState() == GameState::Loading)
{
Logger::Log("Cannot enter play mode if is already in play mode.", "engine", WARNING);
Logger::Log("Cannot enter play mode if is already in play mode or is loading.", "engine", WARNING);
return;
}
SetGameState(GameState::Loading);
PhysicsManager::Get().ReInit();
@@ -167,11 +224,122 @@ namespace Nuake
return currentWindow->SetScene(scene);
}
bool Engine::QueueSceneSwitch(const std::string& scenePath)
{
if (!IsPlayMode())
{
return false;
}
queuedScene = scenePath;
return true;
}
Ref<Project> Engine::GetProject()
{
return currentProject;
}
Ref<EngineSubsystemScriptable> Engine::GetScriptedSubsystem(const std::string& subsystemName)
{
if (scriptedSubsystemMap.contains(subsystemName))
{
return scriptedSubsystemMap[subsystemName];
}
return nullptr;
}
Ref<EngineSubsystemScriptable> Engine::GetScriptedSubsystem(const int subsystemId)
{
if (subsystemId >= subsystems.size())
{
return nullptr;
}
return std::reinterpret_pointer_cast<EngineSubsystemScriptable>(subsystems[subsystemId]);
}
void Engine::OnWindowSetScene(Ref<Scene> oldScene, Ref<Scene> newScene)
{
// Inform the subsystems that we are going to destroy/swap out the old scene
for (auto subsystem : subsystems)
{
if (subsystem == nullptr)
continue;
subsystem->OnScenePreDestroy(oldScene);
}
// Hook into when the internal pieces of the scene are just about to be ready and when the scene is finally
// ready to present (ie, all initialized and loaded).
if (newScene != nullptr)
{
newScene->OnPreInitialize().AddStatic(&Engine::OnScenePreInitialize, newScene);
newScene->OnPostInitialize().AddStatic(&Engine::OnScenePostInitialize, newScene);
}
}
void Engine::InitializeCoreSubsystems()
{
}
void Engine::OnScriptingEngineGameAssemblyLoaded()
{
if (!Engine::IsPlayMode() && Engine::GetGameState() != GameState::Loading)
{
return;
}
subsystems.clear();
scriptedSubsystemMap.clear();
const Coral::ManagedAssembly& gameAssembly = ScriptingEngineNet::Get().GetGameAssembly();
const auto scriptTypeEngineSubsystem = gameAssembly.GetType("Nuake.Net.EngineSubsystem");
const auto& types = gameAssembly.GetTypes();
for (const auto& type : types)
{
// Initialize all subsystems
if (type->IsSubclassOf(scriptTypeEngineSubsystem))
{
const std::string typeName = std::string(type->GetFullName());
Logger::Log("Creating Scripted Subsystem " + typeName);
Coral::ManagedObject scriptedSubsystem = type->CreateInstance();
scriptedSubsystem.SetPropertyValue("EngineSubsystemID", subsystems.size());
Ref<EngineSubsystemScriptable> subsystemScript = CreateRef<EngineSubsystemScriptable>(scriptedSubsystem);
subsystems.push_back(subsystemScript);
scriptedSubsystemMap[typeName] = subsystemScript;
subsystemScript->Initialize();
}
}
}
void Engine::OnScenePreInitialize(Ref<Scene> scene)
{
for (auto subsystem : subsystems)
{
if (subsystem == nullptr)
continue;
subsystem->OnScenePreInitialize(scene);
}
}
void Engine::OnScenePostInitialize(Ref<Scene> scene)
{
for (auto subsystem : subsystems)
{
if (subsystem == nullptr)
continue;
subsystem->OnScenePostInitialize(scene);
}
}
bool Engine::LoadProject(Ref<Project> project)
{
currentProject = project;

View File

@@ -1,4 +1,5 @@
#pragma once
#include "src/Core/Core.h"
#include "src/Core/Logger.h"
#include "src/Window.h"
@@ -8,9 +9,12 @@ namespace Nuake
{
class Project;
class Scene;
class EngineSubsystem;
class EngineSubsystemScriptable;
enum GameState
{
Loading,
Playing,
Paused,
Stopped
@@ -44,15 +48,33 @@ namespace Nuake
static Ref<Window> GetCurrentWindow();
static bool SetCurrentScene(Ref<Scene> scene);
static bool QueueSceneSwitch(const std::string& scene);
static Ref<Scene> GetCurrentScene();
static bool LoadProject(Ref<Project> project);
static Ref<Project> GetProject();
static Ref<EngineSubsystemScriptable> GetScriptedSubsystem(const std::string& subsystemName);
static Ref<EngineSubsystemScriptable> GetScriptedSubsystem(const int subsystemId);
protected:
static void OnWindowSetScene(Ref<Scene> oldScene, Ref<Scene> newScene);
static void InitializeCoreSubsystems();
static void OnScriptingEngineUninitialize();
static void OnScriptingEngineGameAssemblyLoaded();
static void OnScenePreInitialize(Ref<Scene> scene);
static void OnScenePostInitialize(Ref<Scene> scene);
private:
static Ref<Window> currentWindow;
static Ref<Project> currentProject;
static Ref<Scene> currentScene;
static std::string queuedScene;
static inline std::vector<Ref<EngineSubsystem>> subsystems;
static inline std::unordered_map<std::string, Ref<EngineSubsystemScriptable>> scriptedSubsystemMap;
static GameState gameState;

View File

@@ -11,12 +11,15 @@ project 'assimp'
warnings 'Off'
optimize 'Speed'
cppdialect "C++20"
includedirs {
'build/',
'build/assimp',
'assimp/',
'assimp/contrib/irrXML/',
'assimp/contrib/unzip/',
'assimp/contrib/utf8cpp/source',
'assimp/contrib/zlib/',
'assimp/contrib/rapidjson/include/',
'assimp/code',
@@ -32,6 +35,7 @@ project 'assimp'
'assimp/code/Common/**',
'assimp/code/PostProcessing/**',
'assimp/code/Material/**',
'assimp/code/Geometry/**',
'assimp/code/CApi/**',
-- Importers
'assimp/code/AssetLib/Collada/**',
@@ -99,7 +103,8 @@ project 'assimp'
'ASSIMP_BUILD_NO_X_IMPORTER',
'ASSIMP_BUILD_NO_X3D_IMPORTER',
'ASSIMP_BUILD_NO_XGL_IMPORTER',
'ASSIMP_BUILD_NO_IQM_IMPORTER'
'ASSIMP_BUILD_NO_IQM_IMPORTER',
'ASSIMP_BUILD_NO_USD_IMPORTER'
}
-- Exporters
defines {
@@ -119,6 +124,13 @@ project 'assimp'
'ASSIMP_BUILD_NO_3MF_EXPORTER',
'ASSIMP_BUILD_NO_ASSJSON_EXPORTER'
}
-- When building any Visual Studio solution
filter { "system:windows", "action:vs*"}
flags
{
"MultiProcessorCompile",
}
filter "configurations:Debug"
runtime "Debug"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,91 @@
group "Dependencies"
project "Freetype"
location "freetype"
kind "StaticLib"
staticruntime "on"
language "C"
targetdir ("freetype/bin/" .. outputdir .. "/%{prj.name}")
objdir ("freetype/bin-obj/" .. outputdir .. "/%{prj.name}")
includedirs {
'freetype/include/',
'freetype/',
"freetype/include/config/"
}
defines { "FT2_BUILD_LIBRARY" }
files {
"freetype/src/autofit/autofit.c",
"freetype/src/base/ftbase.c",
"freetype/src/base/ftbbox.c",
"freetype/src/base/ftbdf.c",
"freetype/src/base/ftbitmap.c",
"freetype/src/base/ftcid.c",
"freetype/src/base/ftfstype.c",
"freetype/src/base/ftgasp.c",
"freetype/src/base/ftglyph.c",
"freetype/src/base/ftgxval.c",
"freetype/src/base/ftinit.c",
"freetype/src/base/ftmm.c",
"freetype/src/base/ftotval.c",
"freetype/src/base/ftpatent.c",
"freetype/src/base/ftpfr.c",
"freetype/src/base/ftstroke.c",
"freetype/src/base/ftsynth.c",
"freetype/src/base/ftsystem.c",
"freetype/src/base/fttype1.c",
"freetype/src/base/ftwinfnt.c",
"freetype/src/bdf/bdf.c",
"freetype/src/cache/ftcache.c",
"freetype/src/cff/cff.c",
"freetype/src/cid/type1cid.c",
"freetype/src/gzip/ftgzip.c",
"freetype/src/lzw/ftlzw.c",
"freetype/src/pcf/pcf.c",
"freetype/src/pfr/pfr.c",
"freetype/src/psaux/psaux.c",
"freetype/src/pshinter/pshinter.c",
"freetype/src/psnames/psmodule.c",
"freetype/src/raster/raster.c",
"freetype/src/sfnt/sfnt.c",
"freetype/src/smooth/smooth.c",
"freetype/src/truetype/truetype.c",
"freetype/src/type1/type1.c",
"freetype/src/type42/type42.c",
"freetype/src/winfonts/winfnt.c",
"freetype/src/winfonts/winfnt.c",
"freetype/src/sdf/sdf.c"
}
filter "system:windows"
systemversion "latest"
-- warning C4244: 'function': conversion from '__int64' to 'const unsigned int', possible loss of data
-- warning C4996: 'getenv': This function or variable may be unsafe. Consider using _dupenv_s instead
-- warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead.
-- warning C4267: '=': conversion from 'size_t' to 'FT_Int', possible loss of data
-- warning C4312: 'type cast': conversion from 'unsigned long' to 'void *' of greater size
disablewarnings { "4996", "4267", "4244", "4312" }
defines
{
}
filter "configurations:Debug"
files { "freetype/src/base/ftdebug.c" }
runtime "Debug"
symbols "on"
filter "configurations:Release"
files { "freetype/src/base/ftdebug.c" }
runtime "Release"
optimize "on"
filter "configurations:Dist"
files { "freetype/src/base/ftdebug.c" }
runtime "Release"
optimize "on"
group ""

View File

@@ -10,14 +10,19 @@ project "GLFW"
files
{
"glfw/include/GLFW/glfw3.h",
--"glfw/include/GLFW/glfw3native.h",
"glfw/include/GLFW/glfw3native.h",
"glfw/src/glfw_config.h",
"glfw/src/context.c",
"glfw/src/init.c",
"glfw/src/input.c",
"glfw/src/monitor.c",
"glfw/src/vulkan.c",
"glfw/src/window.c"
"glfw/src/window.c",
"glfw/src/platform.c",
"glfw/src/null_init.c",
"glfw/src/null_joystick.c",
"glfw/src/null_monitor.c",
"glfw/src/null_window.c",
"glfw/src/vulkan.c"
}
filter "system:windows"
@@ -31,6 +36,7 @@ project "GLFW"
"glfw/src/win32_time.c",
"glfw/src/win32_thread.c",
"glfw/src/win32_window.c",
"glfw/src/win32_module.c",
"glfw/src/wgl_context.c",
"glfw/src/egl_context.c",
"glfw/src/osmesa_context.c"
@@ -40,6 +46,8 @@ project "GLFW"
{
"_GLFW_WIN32",
}
disablewarnings { "4996" }
filter "system:linux"
@@ -54,6 +62,7 @@ project "GLFW"
"glfw/src/xkb_unicode.c",
"glfw/src/posix_time.c",
"glfw/src/posix_thread.c",
"glfw/src/posix_module.c",
"glfw/src/glx_context.c",
"glfw/src/egl_context.c",
"glfw/src/osmesa_context.c",
@@ -72,4 +81,4 @@ project "GLFW"
filter "configurations:Release"
runtime "Release"
optimize "on"
optimize "on"

View File

@@ -36,6 +36,14 @@ project 'JoltPhysics'
prebuildcommands {
"cp %{prj.location}./Jolt.cpp %{prj.location}/"
}
-- When building any Visual Studio solution
filter { "system:windows", "action:vs*"}
flags
{
"MultiProcessorCompile",
}
filter "configurations:Debug"
cppdialect "C++17"
runtime "Debug"

View File

@@ -0,0 +1,86 @@
project '*'
includedirs {
'yoga/yoga/'
}
group "Dependencies"
project 'msdf-gen'
kind "StaticLib"
staticruntime "on"
warnings 'Off'
optimize 'Speed'
cppdialect "C++20"
includedirs {
'msdf-atlas-gen/include',
'freetype/include'
}
files {
'msdf-atlas-gen/msdfgen/*.h',
'msdf-atlas-gen/msdfgen/*.cpp',
'msdf-atlas-gen/msdfgen/*.hpp',
'msdf-atlas-gen/msdfgen/Core/*.h',
'msdf-atlas-gen/msdfgen/Core/*.hpp',
'msdf-atlas-gen/msdfgen/Core/*.cpp',
'msdf-atlas-gen/msdfgen/lib/*.cpp',
'msdf-atlas-gen/msdfgen/ext/*.h',
'msdf-atlas-gen/msdfgen/ext/*.cpp'
}
defines {
}
-- When building any Visual Studio solution
filter { "system:windows", "action:vs*"}
flags
{
"MultiProcessorCompile",
}
filter "configurations:Debug"
runtime "Debug"
symbols "on"
filter "configurations:Release"
runtime "Release"
optimize "on"
project 'msdf-atlas-gen'
kind "StaticLib"
staticruntime "on"
warnings 'Off'
optimize 'Speed'
cppdialect "C++20"
includedirs {
'msdf-atlas-gen/include',
'msdf-atlas-gen/msdfgen',
'msdf-atlas-gen/msdfgen/include'
}
files {
'msdf-atlas-gen/msdf-atlas-gen/*.h',
'msdf-atlas-gen/msdf-atlas-gen/*.cpp',
'msdf-atlas-gen/msdf-atlas-gen/*.hpp',
}
links {
'msdf-gen'
}
defines {
}
filter "configurations:Debug"
runtime "Debug"
symbols "on"
filter "configurations:Release"
runtime "Release"
optimize "on"
group ""

View File

@@ -67,7 +67,6 @@ project "Detour"
defines {"DEBUG"}
symbols "On"
postbuildcommands {}
flags {"staticruntime"} -- this is what worked for me
-- linux library cflags and libs
filter {"system:linux", "toolset:gcc"}

View File

@@ -0,0 +1,43 @@
project '*'
includedirs {
'yoga/yoga/'
}
group "Dependencies"
project 'yoga'
kind "StaticLib"
staticruntime "on"
warnings 'Off'
optimize 'Speed'
cppdialect "C++20"
includedirs {
'yoga/'
}
files {
'yoga/yoga/*.cpp',
'yoga/yoga/*.h',
'yoga/yoga/**/*.cpp',
'yoga/yoga/**/*.h',
}
defines {
}
-- When building any Visual Studio solution
filter { "system:windows", "action:vs*"}
flags
{
"MultiProcessorCompile",
}
filter "configurations:Debug"
runtime "Debug"
symbols "on"
filter "configurations:Release"
runtime "Release"
optimize "on"
group ""

View File

@@ -18,6 +18,7 @@ namespace Nuake {
virtual void OnDraw() {};
virtual void OnWindowFocused() {};
virtual void OnDragNDrop(const std::vector<std::string>&) {};
// TODO: OnEvent
inline const std::string& GetName() const { return m_Name; }

View File

@@ -28,7 +28,7 @@ namespace Nuake {
// TODO: Sample rate, back end, buffer size, flags.
#ifdef NK_WIN
m_Soloud->init();
m_Soloud->init(SoLoud::Soloud::LEFT_HANDED_3D);
#else
m_Soloud->init(SoLoud::Soloud::CLIP_ROUNDOFF, SoLoud::Soloud::ALSA);
#endif
@@ -55,6 +55,7 @@ namespace Nuake {
m_ListenerUp.x, m_ListenerUp.y, m_ListenerUp.z
);
m_Soloud->update3dAudio();
}
}
@@ -150,30 +151,35 @@ namespace Nuake {
void AudioManager::AudioUpdate()
{
// Check if we have audio queued
if (m_Soloud->getGlobalVolume() != m_GlobalVolume)
{
m_Soloud->setGlobalVolume(m_GlobalVolume);
}
while (!m_AudioQueue.empty())
{
AudioRequest& audioRequest = m_AudioQueue.front();
Ref<SoLoud::AudioSource> audio = m_WavSamples[audioRequest.audioFile];
SoLoud::handle soloudHandle;
SoLoud::handle handle;
if (!audioRequest.spatialized)
{
soloudHandle = m_Soloud->play(*audio);
m_Soloud->setVolume(soloudHandle, audioRequest.volume);
m_Soloud->setPan(soloudHandle, audioRequest.pan);
handle = m_Soloud->play(*audio);
m_Soloud->setVolume(handle, audioRequest.volume);
m_Soloud->setPan(handle, audioRequest.pan);
}
else
{
const Vector3& position = audioRequest.position;
soloudHandle = m_Soloud->play3d(*audio, position.x, position.y, position.z);
m_Soloud->set3dSourceMinMaxDistance(soloudHandle, audioRequest.MinDistance, audioRequest.MaxDistance);
m_Soloud->set3dSourceAttenuation(soloudHandle, SoLoud::AudioSource::ATTENUATION_MODELS::EXPONENTIAL_DISTANCE, audioRequest.AttenuationFactor);
handle = m_Soloud->play3d(*audio, position.x, position.y, position.z);
m_Soloud->set3dSourceMinMaxDistance(handle, audioRequest.MinDistance, audioRequest.MaxDistance);
m_Soloud->set3dSourceAttenuation(handle, SoLoud::AudioSource::ATTENUATION_MODELS::EXPONENTIAL_DISTANCE, audioRequest.AttenuationFactor);
}
m_Soloud->setRelativePlaySpeed(soloudHandle, audioRequest.speed);
m_Soloud->setLooping(soloudHandle, audioRequest.Loop);
m_Soloud->setRelativePlaySpeed(handle, audioRequest.speed);
m_Soloud->setLooping(handle, audioRequest.Loop);
m_ActiveClips[audioRequest.audioFile] = soloudHandle;
m_ActiveClips[audioRequest.audioFile] = handle;
m_AudioQueue.pop();
}

View File

@@ -6,6 +6,7 @@
#include <vector>
#include <queue>
#include <stdexcept>
#include <cassert>
#define ASSERT(x) if (!(x)) assert(false)

View File

@@ -8,11 +8,16 @@
namespace Nuake
{
Input* Input::s_Instance;
Vector2 Input::s_ViewportPos = Vector2(0,0);
Vector2 Input::s_ViewportSize = Vector2(0, 0);
std::map<int, bool> Input::m_Keys = std::map<int, bool>();
bool Input::m_MouseButtons[5] = { false, false, false, false, false };
float Input::XScroll = 0.0f;
float Input::YScroll = 0.0f;
Vector2 Input::ViewportPosition = Vector2(0, 0);;
Vector2 Input::ViewportSize = Vector2(0, 0);
void Input::ScrollCallback(GLFWwindow* window, double xoffset, double yoffset)
{
XScroll = (float)xoffset;
@@ -75,6 +80,7 @@ namespace Nuake
{
auto window = Window::Get()->GetHandle();
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouse;
}
bool Input::IsMouseHidden()
@@ -87,6 +93,7 @@ namespace Nuake
{
auto window = Window::Get()->GetHandle();
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
}
// Action
@@ -150,14 +157,108 @@ namespace Nuake
return Vector2(xpos, ypos);
}
void Input::SetEditorViewportSize(const Vector2& position, const Vector2& size)
{
s_ViewportPos = position;
s_ViewportSize = size;
}
Vector2 Input::GetEditorViewportMousePosition()
{
if (s_ViewportPos == s_ViewportSize)
{
return GetMousePosition();
}
auto window = Window::Get()->GetHandle();
double xpos, ypos;
glfwGetCursorPos(window, &xpos, &ypos);
Vector2 absolutePosition = { xpos, ypos };
Vector2 offset = absolutePosition - ViewportPosition;
return Vector2(xpos , ypos);
}
void Input::SetMousePosition(const Vector2& position)
{
auto window = Window::Get()->GetHandle();
glfwSetCursorPos(window, position.x, position.y);
}
float Input::GetViewportMouseY()
{
return glm::clamp(GetMouseY() - ViewportPosition.y, 0.0f, ViewportSize.y);
}
float Input::GetViewportMouseX()
{
return glm::clamp(GetMouseX() - ViewportPosition.x, 0.0f, ViewportSize.x);
}
Vector2 Input::GetViewportMousePosition()
{
return glm::clamp(GetMousePosition() - ViewportPosition, { 0, 0 }, ViewportSize);
}
Vector2 Input::GetViewportSize()
{
return ViewportSize;
}
void Input::SetViewportDimensions(const Vector2& pos, const Vector2& size)
{
ViewportPosition = pos;
ViewportSize = size;
}
#pragma endregion
bool Input::IsControllerPresent(int id)
{
if (id > GLFW_JOYSTICK_LAST)
{
return 0;
}
return glfwJoystickPresent(GLFW_JOYSTICK_1 + id);
}
std::string Input::GetControllerName(int id)
{
if (IsControllerPresent(id))
{
return glfwGetJoystickName(id);
}
return "Controller Disconnected";
}
bool Input::IsControllerButtonPressed(int id, ControllerInput input)
{
GLFWgamepadstate state;
if (glfwGetGamepadState(GLFW_JOYSTICK_1 + id, &state))
{
if (state.buttons[static_cast<int>(input)])
{
return true;
}
}
return false;
}
float Input::GetControllerAxis(int id, ControllerAxis axis)
{
GLFWgamepadstate state;
if (glfwGetGamepadState(GLFW_JOYSTICK_1 + id, &state))
{
return state.axes[static_cast<int>(axis)];
}
return 0.0f;
}
bool Input::Init()
{
//auto window = Application::Get().GetWindow()->GetNative();

View File

@@ -1,6 +1,7 @@
#pragma once
#include "src/Core/Maths.h"
#include <string>
#include <map>
#include <utility>
@@ -132,11 +133,43 @@ namespace Nuake
MENU = 348
};
enum class ControllerInput
{
A = 0,
B,
X,
Y,
LEFT_BUMPER,
RIGHT_BUMPER,
BACK,
START,
GUIDE,
LEFT_THUMB,
RIGHT_THUMB,
DPAD_UP,
DPAD_RIGHT,
DPAD_DOWN,
DPAD_LEFT
};
enum class ControllerAxis
{
LEFT_X = 0,
LEFT_Y,
RIGHT_X,
RIGHT_Y,
LEFT_TRIGGER,
RIGHT_TRIGGER
};
class Input
{
private:
static bool m_MouseButtons[5];
static std::map<int, bool> m_Keys;
static Vector2 ViewportPosition;
static Vector2 ViewportSize;
public:
static bool IsKeyPressed(Key keycode);
static bool IsKeyDown(Key keycode);
@@ -153,11 +186,29 @@ namespace Nuake
static bool IsMouseButtonDown(int button);
static bool IsMouseButtonReleased(int button);
// Get mouse position relative to window
static float GetMouseX();
static float GetMouseY();
static Vector2 GetMousePosition();
static void SetEditorViewportSize(const Vector2& position, const Vector2& size);
static Vector2 GetEditorViewportMousePosition();
static void SetMousePosition(const Vector2& position);
// Get mouse position relative to viewport
static float GetViewportMouseY();
static float GetViewportMouseX();
static Vector2 GetViewportMousePosition();
static Vector2 GetViewportSize();
static void SetViewportDimensions(const Vector2& pos, const Vector2& size);
// Controller
static bool IsControllerPresent(int id);
static std::string GetControllerName(int id);
static bool IsControllerButtonPressed(int id, ControllerInput input);
static float GetControllerAxis(int id, ControllerAxis axis);
static bool Init();
static void Update();
@@ -165,5 +216,7 @@ namespace Nuake
private:
static Input* s_Instance;
static Vector2 s_ViewportPos;
static Vector2 s_ViewportSize;
};
}

View File

@@ -0,0 +1,134 @@
#pragma once
#include <functional>
#include <vector>
#define DECLARE_MULTICAST_DELEGATE(multicastDelegateName, ...) typedef MulticastDelegate<__VA_ARGS__> multicastDelegateName;
struct DelegateHandle
{
size_t id = InvalidHandle;
static inline size_t InvalidHandle = static_cast<size_t>(-1);
bool IsValid() const { return id != InvalidHandle; }
void Reset() { id = InvalidHandle; }
// Comparison operators for convenience
bool operator==(const DelegateHandle& other) const { return id == other.id; }
bool operator!=(const DelegateHandle& other) const { return id != other.id; }
};
template<typename... Args>
class MulticastDelegate
{
public:
// Add a callable with bound variables (supports no arguments as well)
template<typename Callable, typename... BoundArgs>
DelegateHandle AddStatic(Callable&& func, BoundArgs&&... boundArgs)
{
size_t id = GetNextID();
auto boundFunction = [=](Args... args) {
if constexpr (sizeof...(Args) > 0)
{
func(boundArgs..., std::forward<Args>(args)...);
}
else
{
func(boundArgs...);
}
};
SetDelegate(id, boundFunction);
return DelegateHandle{ id };
}
template<typename Obj, typename Callable, typename... BoundArgs>
DelegateHandle AddRaw(Obj* object, Callable&& func, BoundArgs&&... boundArgs)
{
size_t id = GetNextID();
auto boundFunction = [=](Args... args) {
if constexpr (sizeof...(Args) > 0)
{
(object->*func)(boundArgs..., std::forward<Args>(args)...);
}
else
{
(object->*func)(boundArgs...);
}
};
SetDelegate(id, boundFunction);
return DelegateHandle{ id };
}
// Remove a callable using the token returned by Add()
void Remove(DelegateHandle& handle)
{
ASSERT(handle.IsValid());
if (handle.IsValid() && handle.id < delegates.size())
{
delegates[handle.id].active = false;
// Mark this slot as reusable
freeIDs.push_back(handle.id);
}
// Invalidate the handle
handle.Reset();
}
// Clear all delegates
void Clear()
{
delegates.clear();
freeIDs.clear();
nextID = 0;
}
// Invoke all callables
void Broadcast(Args... args)
{
for (auto& delegate : delegates)
{
if (delegate.active)
{
delegate.function(std::forward<Args>(args)...);
}
}
}
private:
struct Delegate
{
bool active = false;
std::function<void(Args...)> function;
};
// A vector of delegates with active state
std::vector<Delegate> delegates;
// List of reusable slots
std::vector<size_t> freeIDs;
size_t nextID = 0;
// Get the next available ID, either by reusing a free slot or by creating a new one
size_t GetNextID()
{
if (!freeIDs.empty())
{
size_t id = freeIDs.back();
freeIDs.pop_back();
return id;
}
return nextID++;
}
// Set the delegate in the vector, makes the array larger if necessary
void SetDelegate(size_t id, const std::function<void(Args...)>& func)
{
if (id >= delegates.size())
delegates.resize(id + 1);
delegates[id] = { true, func };
}
};

View File

@@ -0,0 +1,5 @@
#include "ClassDB.h"
namespace Nuake
{
}

View File

@@ -0,0 +1,14 @@
#pragma once
namespace Nuake
{
class ClassDB
{
public:
template<class T>
static void RegisterComponent(T klass)
{
T::InternalInitializeClass();
}
};
}

View File

@@ -0,0 +1,173 @@
#pragma once
#include <entt/entt.hpp>
#include <type_traits>
#define NK_HASHED_STATIC_STR(name) inline static constexpr entt::hashed_string name = entt::hashed_string(#name);
#define NK_ENUM_BITWISE_IMPL(enumClassName) \
inline enumClassName operator|(enumClassName lhs, enumClassName rhs) \
{ \
return static_cast<enumClassName>(ToUnderlying(lhs) | ToUnderlying(rhs)); \
} \
\
inline enumClassName operator&(enumClassName lhs, enumClassName rhs) \
{ \
return static_cast<enumClassName>(ToUnderlying(lhs) & ToUnderlying(rhs)); \
}
namespace Nuake
{
struct HashedFnName
{
NK_HASHED_STATIC_STR(GetComponentName)
NK_HASHED_STATIC_STR(AddToEntity)
NK_HASHED_STATIC_STR(RemoveFromEntity)
NK_HASHED_STATIC_STR(ActionName)
};
struct HashedFieldPropName
{
NK_HASHED_STATIC_STR(FloatStep)
NK_HASHED_STATIC_STR(FloatMin)
NK_HASHED_STATIC_STR(FloatMax)
NK_HASHED_STATIC_STR(ResourceFileType)
};
struct HashedName
{
NK_HASHED_STATIC_STR(DisplayName)
};
enum class ComponentTypeTrait : uint16_t
{
None = 0,
// Exposes the component to be added via the inspector
InspectorExposed = 1 << 0,
};
enum class ComponentFuncTrait : uint16_t
{
None = 0,
// Exposes the component to be added via the inspector
Action = 1 << 0,
};
enum class ComponentFieldTrait : uint16_t
{
None = 0,
// Stops field from showing up in the editor inspector
Internal = 1 << 0,
// Marks the field as temporary (ie, do not serialize)
Transient = 1 << 1,
};
template <typename Enum>
constexpr std::underlying_type_t<Enum> ToUnderlying(Enum e)
{
return static_cast<std::underlying_type_t<Enum>>(e);
}
NK_ENUM_BITWISE_IMPL(ComponentTypeTrait);
NK_ENUM_BITWISE_IMPL(ComponentFuncTrait);
NK_ENUM_BITWISE_IMPL(ComponentFieldTrait);
}
#define NUAKECOMPONENT(klass, componentName) \
public: \
static std::string ClassName() \
{ \
static std::string className = #klass; \
return className; \
} \
\
static std::string ComponentName() \
{ \
static std::string name = componentName; \
return name; \
} \
\
static void AddToEntity(entt::entity entity, entt::registry* enttRegistry) \
{ \
enttRegistry->emplace_or_replace<klass>(entity); \
} \
\
static void RemoveFromEntity(entt::entity entity, entt::registry* enttRegistry) \
{ \
enttRegistry->erase<klass>(entity); \
} \
\
\
static void (*GetInitializeComponentClass())() \
{ \
return &klass::InitializeComponentClass; \
} \
\
inline static auto ComponentFactory = entt::meta<klass>(); \
static void InternalInitializeClass() \
{ \
static bool initialized = false; \
if (initialized) \
return; \
\
ComponentFactory.type(entt::hashed_string(#klass)) \
.traits(ComponentTypeTrait::InspectorExposed); \
ComponentFactory.func<&klass::ComponentName>(HashedFnName::GetComponentName); \
ComponentFactory.func<&klass::AddToEntity>(HashedFnName::AddToEntity); \
ComponentFactory.func<&klass::RemoveFromEntity>(HashedFnName::RemoveFromEntity); \
\
if (klass::GetInitializeComponentClass() != Component::GetInitializeComponentClass()) \
{ \
GetInitializeComponentClass()(); \
} \
\
initialized = true; \
\
} \
\
template<auto Data> \
static auto BindComponentField(const char* varName, const char* displayName) \
{ \
return ComponentFactory \
.data<Data>(entt::hashed_string(varName)) \
.prop(HashedName::DisplayName, displayName); \
} \
\
template<auto Getter, auto Setter> \
static auto BindComponentProperty(const char* varName, const char* displayName) \
{ \
return ComponentFactory \
.data<Getter, Setter>(entt::hashed_string(varName)) \
.prop(HashedName::DisplayName, displayName); \
} \
\
static auto FieldFloatLimits(float stepSize, float min, float max) \
{ \
return ComponentFactory \
.prop(HashedFieldPropName::FloatStep, stepSize) \
.prop(HashedFieldPropName::FloatMin, min) \
.prop(HashedFieldPropName::FloatMax, max); \
} \
\
static auto ResourceFileRestriction(const char* fileType) \
{ \
return ComponentFactory \
.prop(HashedFieldPropName::ResourceFileType, fileType); \
} \
\
template <typename... Enums> \
static auto SetFlags(Enums... enums) \
{ \
static_assert((std::is_enum_v<Enums> && ...), "All arguments must be of enum class type"); \
return ComponentFactory.traits((enums | ...)); \
} \
\
template<auto Func> \
static void BindAction(const char* funcName, const char* actionName) \
{ \
ComponentFactory \
.func<Func>(entt::hashed_string(funcName)) \
.prop(HashedName::DisplayName, actionName); \
SetFlags(ComponentFuncTrait::Action); \
}

View File

@@ -0,0 +1,52 @@
#include "RegisterCoreTypes.h"
#include "src/Scene/Components/AudioEmitterComponent.h"
#include "src/Scene/Components/BoneComponent.h"
#include "src/Scene/Components/BoxCollider.h"
#include "src/Scene/Components/CameraComponent.h"
#include "src/Scene/Components/CapsuleColliderComponent.h"
#include "src/Scene/Components/CharacterControllerComponent.h"
#include "src/Scene/Components/CylinderColliderComponent.h"
#include "src/Scene/Components/MeshCollider.h"
#include "src/Scene/Components/ModelComponent.h"
#include "src/Scene/Components/NavMeshVolumeComponent.h"
#include "src/Scene/Components/NetScriptComponent.h"
#include "src/Scene/Components/ParticleEmitterComponent.h"
#include "src/Scene/Components/QuakeMap.h"
#include "src/Scene/Components/RigidbodyComponent.h"
#include "src/Scene/Components/SkinnedModelComponent.h"
#include "src/Scene/Components/SphereCollider.h"
#include "src/Scene/Components/SpriteComponent.h"
#include "src/Scene/Components/UIComponent.h"
#include "src/Scene/Components/SkyComponent.h"
#include "src/Scene/Components/EnvironmentComponent.h"
namespace Nuake
{
void RegisterCoreTypes::RegisterCoreComponents()
{
UIComponent::InternalInitializeClass();
SpriteComponent::InternalInitializeClass();
SphereColliderComponent::InternalInitializeClass();
SkinnedModelComponent::InternalInitializeClass();
RigidBodyComponent::InternalInitializeClass();
QuakeMapComponent::InternalInitializeClass();
ParticleEmitterComponent::InternalInitializeClass();
NetScriptComponent::InternalInitializeClass();
NavMeshVolumeComponent::InternalInitializeClass();
ModelComponent::InternalInitializeClass();
MeshColliderComponent::InternalInitializeClass();
LightComponent::InternalInitializeClass();
CylinderColliderComponent::InternalInitializeClass();
CharacterControllerComponent::InternalInitializeClass();
CapsuleColliderComponent::InternalInitializeClass();
CameraComponent::InternalInitializeClass();
BoxColliderComponent::InternalInitializeClass();
BoneComponent::InternalInitializeClass();
AudioEmitterComponent::InternalInitializeClass();
SkyComponent::InternalInitializeClass();
EnvironmentComponent::InternalInitializeClass();
}
}

View File

@@ -0,0 +1,11 @@
#pragma once
namespace Nuake
{
class RegisterCoreTypes
{
public:
static void RegisterCoreComponents();
};
}

View File

@@ -16,7 +16,7 @@ File::File(Ref<Directory> parentDir, const std::string& fullPath, const std::str
FileType File::GetFileType() const
{
const std::string ext = GetExtension();
if (ext == ".png" || ext == ".jpg")
if (ext == ".png" || ext == ".jpg" || ext == ".dds")
{
return FileType::Image;
}
@@ -78,8 +78,33 @@ FileType File::GetFileType() const
{
return FileType::Mesh;
}
if (ext == ".glb" || ext == ".gltf" || ext == ".fbx")
{
return FileType::MeshAsset;
}
return FileType::Unkown;
if (ext == ".html")
{
return FileType::UI;
}
if (ext == ".css")
{
return FileType::CSS;
}
if (ext == ".sky")
{
return FileType::Sky;
}
if (ext == ".env")
{
return FileType::Env;
}
return FileType::Unknown;
}
std::string File::GetFileTypeAsString() const
@@ -135,6 +160,26 @@ std::string File::GetFileTypeAsString() const
return "C# Script";
}
if (ext == ".html")
{
return "UI Layout";
}
if (ext == ".css")
{
return "StyleSheet";
}
if (ext == ".sky")
{
return "Sky";
}
if (ext == ".env")
{
return "Environment";
}
return "File";
}

View File

@@ -144,46 +144,59 @@ std::string FileDialog::OpenFolder()
std::string folderPath;
#ifdef NK_WIN
BROWSEINFOA bi;
CHAR szFolder[260] = { 0 };
ZeroMemory(&bi, sizeof(BROWSEINFO));
bi.lpszTitle = "Select a Folder";
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
bi.hwndOwner = glfwGetWin32Window(Engine::GetCurrentWindow()->GetHandle());
bi.pszDisplayName = szFolder;
LPITEMIDLIST pidl = SHBrowseForFolderA(&bi);
if (pidl != NULL)
// Initialize COM library for the current thread
HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr))
{
SHGetPathFromIDListA(pidl, szFolder);
folderPath = std::string(szFolder);
CoTaskMemFree(pidl);
IFileOpenDialog* pFileOpen = NULL;
// Create the FileOpenDialog object
hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL, IID_IFileOpenDialog, (void**)&pFileOpen);
if (SUCCEEDED(hr))
{
// Set the options for the dialog to pick folders
DWORD dwOptions;
hr = pFileOpen->GetOptions(&dwOptions);
if (SUCCEEDED(hr))
{
hr = pFileOpen->SetOptions(dwOptions | FOS_PICKFOLDERS); // Use FOS_PICKFOLDERS to select folders
}
// Show the dialog to the user
hr = pFileOpen->Show(NULL); // NULL here means no parent window
// If the user selects a folder
if (SUCCEEDED(hr))
{
IShellItem* pItem;
hr = pFileOpen->GetResult(&pItem);
if (SUCCEEDED(hr))
{
// Get the selected folder's path
PWSTR pszFolderPath = NULL;
hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFolderPath);
if (SUCCEEDED(hr))
{
// Convert from wide string (PWSTR) to std::string
char szFolderPath[MAX_PATH];
wcstombs(szFolderPath, pszFolderPath, MAX_PATH);
folderPath = std::string(szFolderPath);
// Free memory
CoTaskMemFree(pszFolderPath);
}
pItem->Release();
}
}
pFileOpen->Release();
}
// Uninitialize COM library
CoUninitialize();
}
#endif
#ifdef NK_LINUX
GtkWidget* dialog;
GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER;
gint res;
dialog = gtk_file_chooser_dialog_new("Select Folder",
NULL,
action,
"_Cancel",
GTK_RESPONSE_CANCEL,
"_Select",
GTK_RESPONSE_ACCEPT,
NULL);
res = gtk_dialog_run(GTK_DIALOG(dialog));
if (res == GTK_RESPONSE_ACCEPT) {
char* foldername = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
folderPath = foldername;
g_free(foldername);
}
gtk_widget_destroy(dialog);
#endif
return folderPath;
}

View File

@@ -20,6 +20,8 @@ Ref<filewatch::FileWatch<std::string>> FileSystem::RootFileWatch;
void FileSystem::ScanDirectory(Ref<Directory> directory)
{
directory->Files.clear();
directory->Directories.clear();
for (const auto& entry : std::filesystem::directory_iterator(directory->FullPath))
{
if (entry.is_directory())
@@ -62,6 +64,34 @@ bool FileSystem::FileExists(const std::string& path, bool absolute)
return std::filesystem::exists(fullPath) && std::filesystem::is_regular_file(fullPath);
}
std::vector<Ref<File>> FileSystem::GetAllFiles(const FileType fileType)
{
std::vector<Ref<File>> foundFiles;
std::function<void(Ref<Directory>)> scanDir;
scanDir = [&scanDir, &foundFiles, &fileType](Ref<Directory> dir)
{
// All the files matching the filetype
for (auto& f : dir->Files)
{
if (f->GetFileType() == fileType)
{
foundFiles.push_back(f);
}
}
// Scan sub folder
for (auto& d : dir->Directories)
{
scanDir(d);
}
};
scanDir(RootDirectory);
return foundFiles;
}
void FileSystem::SetRootDirectory(const std::string path)
{
Root = path;
@@ -76,21 +106,30 @@ void FileSystem::SetRootDirectory(const std::string path)
return;
}
if (event == filewatch::Event::added)
{
const std::string& parent = std::filesystem::path(normalizedPath).parent_path().string();
auto parentDirectory = FileSystem::GetDirectory(parent);
auto filePath = std::filesystem::path(normalizedPath);
std::string name = filePath.filename().string();
std::string extension = filePath.extension().string();
Ref<File> newImportedFile = CreateRef<File>(parentDirectory, FileSystem::RelativeToAbsolute(normalizedPath), name, extension);
parentDirectory->Files.push_back(newImportedFile);
}
if(Ref<File> file = GetFile(normalizedPath); file)
{
if (file->GetFileType() == FileType::Unkown)
if (file->GetFileType() == FileType::Unknown)
{
return;
}
Logger::Log(normalizedPath + " event: " + filewatch::event_to_string(event), "filewatcher", VERBOSE);
if (event == filewatch::Event::modified)
{
file->SetHasBeenModified(true);
}
}
}
}
);
Scan();
@@ -121,6 +160,12 @@ std::string FileSystem::GetParentPath(const std::string& fullPath)
return returnvalue + "/";
}
void FileSystem::CopyFileAbsolute(const std::string& src, const std::string& dest)
{
const std::string& destPath = dest + "/" + std::filesystem::path(src).filename().string();
std::filesystem::copy_file(src, destPath, std::filesystem::copy_options::overwrite_existing);
}
std::string FileSystem::ReadFile(const std::string& path, bool absolute)
{
std::string finalPath = path;
@@ -202,8 +247,14 @@ Ref<Directory> FileSystem::GetFileTree()
return RootDirectory;
}
Ref<File> FileSystem::GetFile(const std::string& path)
Ref<File> FileSystem::GetFile(const std::string& inPath)
{
std::string path = inPath;
if (String::BeginsWith(path, "/") || String::BeginsWith(path, "\\"))
{
path = inPath.substr(1, inPath.size() - 1);
}
// Note, Might be broken on other platforms.
auto splits = String::Split(path, '/');
@@ -276,7 +327,6 @@ std::string FileSystem::GetFileNameFromPath(const std::string& path)
return String::Split(split[split.size() - 1], '.')[0];
}
Directory::Directory(const std::string& path)
{
Files = std::vector<Ref<File>>();
@@ -289,3 +339,8 @@ std::string Directory::GetName() const
{
return Name;
}
std::string Directory::GetFullPath() const
{
return FullPath;
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include "src/Core/Core.h"
#include "FileTypes.h"
namespace filewatch
{
@@ -35,8 +36,10 @@ namespace Nuake
static bool MakeDirectory(const std::string& path, bool absolute = false);
static bool DirectoryExists(const std::string& path, bool absolute = false);
static bool FileExists(const std::string& path, bool absolute = false);
static std::vector<Ref<File>> GetAllFiles(const FileType fileType);
static std::string ReadFile(const std::string& path, bool absolute = false);
static void CopyFileAbsolute(const std::string& src, const std::string& dest);
static std::ofstream fileWriter;
static bool BeginWriteFile(const std::string path, bool absolute = false);

View File

@@ -4,10 +4,11 @@ namespace Nuake
{
enum class FileType
{
Unkown,
Unknown,
Image,
Material,
Mesh,
MeshAsset,
Script,
NetScript,
Project,
@@ -17,6 +18,10 @@ namespace Nuake
Map,
Assembly,
Solution,
Audio
Audio,
UI,
CSS,
Sky,
Env
};
}

View File

@@ -164,7 +164,6 @@ namespace Nuake
normal,
position
};
_World->RegisterCollisionCallback(std::move(data));
}
@@ -206,7 +205,7 @@ namespace Nuake
case Layers::MOVING:
return true;
case Layers::SENSORS:
return inLayer2 == BroadPhaseLayers::MOVING;;
return inLayer2 == BroadPhaseLayers::MOVING;
default:
return false;
}
@@ -384,6 +383,11 @@ namespace Nuake
bodySettings.mCollideKinematicVsNonDynamic = true;
}
if (rb->GetForceKinematic())
{
bodySettings.mCollideKinematicVsNonDynamic = true;
}
bodySettings.mAllowedDOFs = (JPH::EAllowedDOFs::All);
if (rb->GetLockXAxis())
@@ -451,7 +455,7 @@ namespace Nuake
}
bodySettings.mUserData = cc->Owner.GetHandle();
bodySettings.mCollideKinematicVsNonDynamic = true;
// Create the actual rigid body
JPH::BodyID body = _JoltBodyInterface->CreateAndAddBody(bodySettings, JPH::EActivation::Activate); // Note that if we run out of bodies this can return nullptr
uint32_t bodyIndex = body.GetIndexAndSequenceNumber();
@@ -533,9 +537,11 @@ namespace Nuake
_JoltBodyInterface->MoveKinematic(bodyId, newPosition, newRotation, Engine::GetFixedTimeStep());
break;
}
case JPH::EMotionType::Dynamic:
case JPH::EMotionType::Static:
{
_JoltBodyInterface->SetPositionAndRotation(bodyId, newPosition, newRotation, JPH::EActivation::DontActivate);
break;
}
}
@@ -574,16 +580,18 @@ namespace Nuake
// Format result
for (int i = 0; i < num_hits; ++i)
{
const float hitFraction = results[i].mFraction;
const JPH::Vec3& hitPosition = ray.GetPointOnRay(results[i].mFraction);
auto bodyId = static_cast<JPH::BodyID>(results[i].mBodyID);
const float hitFraction = collector.mHits[i].mFraction;
const JPH::Vec3& hitPosition = ray.GetPointOnRay(collector.mHits[i].mFraction);
auto bodyId = static_cast<JPH::BodyID>(collector.mHits[i].mBodyID);
auto layer = _JoltBodyInterface->GetObjectLayer(bodyId);
int userData = static_cast<int>(_JoltBodyInterface->GetUserData(bodyId));
ShapeCastResult result
{
Vector3(hitPosition.GetX(), hitPosition.GetY(), hitPosition.GetZ()),
hitFraction,
Vector3(0, 0, 0),
layer
layer,
userData
};
raycastResults.push_back(std::move(result));
@@ -632,12 +640,14 @@ namespace Nuake
auto layer = _JoltBodyInterface->GetObjectLayer(bodyId);
int userData = static_cast<int>(_JoltBodyInterface->GetUserData(bodyId));
ShapeCastResult result
{
Vector3(hitPosition.GetX(), hitPosition.GetY(), hitPosition.GetZ()),
hitFraction,
Vector3(surfaceNormal.GetX(), surfaceNormal.GetY(), surfaceNormal.GetZ()),
static_cast<float>(layer)
static_cast<float>(layer),
userData
};
shapecastResults.push_back(std::move(result));
@@ -978,7 +988,7 @@ namespace Nuake
Capsule* capsule = (Capsule*)shape.get();
const float radius = capsule->GetRadius();
const float height = capsule->GetHeight();
JPH::CapsuleShapeSettings shapeSettings(height / 2.0f, radius);
JPH::CapsuleShapeSettings shapeSettings(height / 4.0f, radius);
result = shapeSettings.Create();
}
break;
@@ -987,7 +997,7 @@ namespace Nuake
Cylinder* capsule = (Cylinder*)shape.get();
const float radius = capsule->GetRadius();
const float height = capsule->GetHeight();
JPH::CylinderShapeSettings shapeSettings(height / 2.0f, radius);
JPH::CylinderShapeSettings shapeSettings(height / 4.0f, radius);
result = shapeSettings.Create();
}
break;

View File

@@ -20,5 +20,6 @@ namespace Nuake
float Fraction;
Vector3 ImpactNormal;
float Layer;
int EntityID;
};
}

View File

@@ -65,11 +65,13 @@ namespace Nuake
void FrameBuffer::Clear()
{
ZoneScoped;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void FrameBuffer::Bind()
{
ZoneScoped;
if (ResizeQueued)
UpdateSize(m_Size);
@@ -96,6 +98,7 @@ namespace Nuake
void FrameBuffer::UpdateSize(Vector2 size)
{
ZoneScoped;
m_Size = size;
ResizeQueued = false;
@@ -137,6 +140,15 @@ namespace Nuake
return pixelData;
}
Vector2 FrameBuffer::ReadVec2(uint32_t attachment, const Vector2 coords)
{
glReadBuffer(GL_COLOR_ATTACHMENT0 + attachment);
unsigned char pixelData[2]; // Store two components for the vec2 (byte)
glReadPixels((int)coords.x, (int)coords.y, 1, 1, GL_RG, GL_UNSIGNED_BYTE, &pixelData);
// Normalize the values (unsigned byte to [0, 1] float)
return Vector2(pixelData[0] / 255.0f, pixelData[1] / 255.0f);
}
float FrameBuffer::ReadDepth(const Vector2& coords)
{
glReadBuffer(GL_DEPTH_ATTACHMENT);

View File

@@ -11,7 +11,7 @@ namespace Nuake
class FrameBuffer
{
private:
unsigned int m_FramebufferID;
uint32_t m_FramebufferID;
unsigned int m_RenderBuffer;
Vector2 m_Size;
@@ -40,6 +40,7 @@ namespace Nuake
uint32_t GetRenderID() const { return m_FramebufferID; }
int ReadPixel(uint32_t attachment, const Vector2 coords);
Vector2 ReadVec2(uint32_t attachment, const Vector2 coords);
float ReadDepth(const Vector2& coords);
void SetDrawBuffer(GLenum draw);
void SetReadBuffer(GLenum read);

View File

@@ -67,7 +67,7 @@ namespace Nuake
Matrix4 Camera::GetPerspective()
{
//TODO: Add perspective options
m_Perspective = glm::perspectiveFov(glm::radians(Fov), 9.0f * AspectRatio, 9.0f, 0.001f, 1000.0f);
m_Perspective = glm::perspectiveFov(glm::radians(Fov), 9.0f * AspectRatio, 9.0f, Near, Far);
return m_Perspective;
}

View File

@@ -27,6 +27,9 @@ namespace Nuake
Matrix4 m_Perspective;
Matrix4 m_View;
float Near = 0.001f;
float Far = 400.0f;
public:
float AspectRatio = 16.0f / 9.0f;
@@ -48,6 +51,9 @@ namespace Nuake
void SetDirection(Vector3 direction);
void SetDirection(const Quat& direction);
float GetNear() const { return Near; }
float GetFar() const { return Far; }
Vector3 GetTranslation();
Vector3 GetDirection();
Matrix4 GetPerspective();

View File

@@ -43,7 +43,7 @@ namespace Nuake {
private:
static const int CSM_SPLIT_AMOUNT = 4;
const float CSM_NEAR_CLIP = 0.001f;
const float CSM_FAR_CLIP = 500.0f;
const float CSM_FAR_CLIP = 400.0f;
const float CSM_CLIP_RANGE = CSM_FAR_CLIP - CSM_NEAR_CLIP;
const float mCascadeNearPlaneOffset = 0.0;

View File

@@ -115,7 +115,7 @@ namespace Nuake
void Mesh::DebugDraw()
{
Renderer::m_DebugShader->Bind();
Renderer::m_DebugShader->SetUniform4f("u_Color", 1.0f, 0.0f, 0.0f, 1.f);
Renderer::m_DebugShader->SetUniform("u_Color", 1.0f, 0.0f, 0.0f, 1.f);
m_VertexArray->Bind();
RenderCommand::DrawElements(RendererEnum::TRIANGLES, m_IndicesCount, RendererEnum::UINT, 0);

View File

@@ -110,7 +110,7 @@ namespace Nuake
void SkinnedMesh::DebugDraw()
{
Renderer::m_DebugShader->Bind();
Renderer::m_DebugShader->SetUniform4f("u_Color", 1.0f, 0.0f, 0.0f, 1.f);
Renderer::m_DebugShader->SetUniform("u_Color", 1.0f, 0.0f, 0.0f, 1.f);
m_VertexArray->Bind();
RenderCommand::DrawElements(RendererEnum::TRIANGLES, (int)m_Indices.size(), RendererEnum::UINT, 0);

View File

@@ -12,6 +12,17 @@ namespace Nuake
m_Iteration = iteration;
}
void Bloom::SetLensDirt(Ref<Texture> texture)
{
m_LensDirt = texture;
m_HasLensDirt = true;
}
void Bloom::ClearLensDirt()
{
m_HasLensDirt = false;
}
void Bloom::SetSource(Ref<Texture> source)
{
if (m_Source == source)
@@ -78,10 +89,10 @@ namespace Nuake
{
m_ThresholdFB->Clear();
shader->Bind();
shader->SetUniform1i("u_Stage", 0);
shader->SetUniform1f("u_Threshold", m_Threshold);
shader->SetUniform("u_Stage", 0);
shader->SetUniform("u_Threshold", m_Threshold);
m_Source->Bind(1);
shader->SetUniform1i("u_Source", 1);
shader->SetUniform("u_Source", 1);
Renderer::DrawQuad(Matrix4());
}
@@ -91,13 +102,13 @@ namespace Nuake
m_DownSampleFB[i]->Bind();
m_DownSampleFB[i]->Clear();
shader->SetUniform1i("u_Stage", 1);
shader->SetUniform("u_Stage", 1);
Ref<Texture> downsampleTexture = i == 0 ? m_ThresholdFB->GetTexture() : m_DownSampleFB[i - 1]->GetTexture();
shader->SetUniformTex("u_Source", downsampleTexture.get(), 1);
shader->SetUniform("u_Source", downsampleTexture.get(), 1);
Vector2 size = i == 0 ? downsampleTexture->GetSize() : m_DownSampleFB[i]->GetTexture()->GetSize();
shader->SetUniformVec2("u_SourceSize", size);
shader->SetUniform("u_SourceSize", size);
Renderer::DrawQuad(Matrix4());
m_DownSampleFB[i]->Unbind();
@@ -109,13 +120,13 @@ namespace Nuake
m_HBlurFB[i]->Bind();
m_HBlurFB[i]->Clear();
shader->SetUniform1i("u_Stage", 2);
shader->SetUniform2f("u_BlurDirection", 0.0f, 1.0f);
shader->SetUniform("u_Stage", 2);
shader->SetUniform("u_BlurDirection", 0.0f, 1.0f);
Ref<Texture> blurTexture = m_DownSampleFB[m_Iteration - i - 1]->GetTexture();
blurTexture->Bind(1);
shader->SetUniform1i("u_Source", 1);
shader->SetUniform2f("u_SourceSize", (float)blurTexture->GetWidth(), (float)blurTexture->GetHeight());
shader->SetUniform("u_Source", 1);
shader->SetUniform("u_SourceSize", (float)blurTexture->GetWidth(), (float)blurTexture->GetHeight());
Renderer::DrawQuad(Matrix4());
m_HBlurFB[i]->Unbind();
@@ -124,12 +135,12 @@ namespace Nuake
m_VBlurFB[i]->Bind();
m_VBlurFB[i]->Clear();
shader->SetUniform1i("u_Stage", 2);
shader->SetUniform2f("u_BlurDirection", 1.0f, 0.0f);
shader->SetUniform("u_Stage", 2);
shader->SetUniform("u_BlurDirection", 1.0f, 0.0f);
m_HBlurFB[i]->GetTexture()->Bind(1);
shader->SetUniform1i("u_Source", 1);
shader->SetUniform2f("u_SourceSize", (float)m_HBlurFB[i]->GetTexture()->GetWidth(), (float)m_HBlurFB[i]->GetTexture()->GetHeight());
shader->SetUniform("u_Source", 1);
shader->SetUniform("u_SourceSize", (float)m_HBlurFB[i]->GetTexture()->GetWidth(), (float)m_HBlurFB[i]->GetTexture()->GetHeight());
Renderer::DrawQuad(Matrix4());
m_VBlurFB[i]->Unbind();
@@ -140,20 +151,20 @@ namespace Nuake
m_UpSampleFB[i]->Clear();
if (i == 0)
{
shader->SetUniform1i("u_Stage", 3);
shader->SetUniform1i("u_Source", 1);
shader->SetUniform("u_Stage", 3);
shader->SetUniform("u_Source", 1);
m_VBlurFB[i]->GetTexture()->Bind(1);
}
if (i > 0)
{
shader->SetUniform1i("u_Stage", 4);
shader->SetUniform("u_Stage", 4);
m_VBlurFB[i]->GetTexture()->Bind(1);
shader->SetUniform1i("u_Source", 1);
shader->SetUniform("u_Source", 1);
m_UpSampleFB[i - 1]->GetTexture()->Bind(2);
shader->SetUniform1i("u_Source2", 2);
shader->SetUniform2f("u_Source2Size", (float)m_UpSampleFB[i]->GetTexture()->GetWidth(), (float)m_UpSampleFB[i]->GetTexture()->GetHeight());
shader->SetUniform("u_Source2", 2);
shader->SetUniform("u_Source2Size", (float)m_UpSampleFB[i]->GetTexture()->GetWidth(), (float)m_UpSampleFB[i]->GetTexture()->GetHeight());
}
Renderer::DrawQuad(Matrix4());
m_UpSampleFB[i]->Unbind();
@@ -161,11 +172,20 @@ namespace Nuake
m_FinalFB->Bind();
m_FinalFB->Clear();
{
shader->SetUniform1i("u_Stage", 5);
shader->SetUniform1i("u_Source", 1);
shader->SetUniform1i("u_Source2", 2);
shader->SetUniform("u_Stage", 5);
shader->SetUniform("u_Source", 1);
shader->SetUniform("u_Source2", 2);
shader->SetUniform("u_HasLensDirt", m_HasLensDirt);
shader->SetUniform("u_LensDirt", 3);
if (m_LensDirt)
{
m_LensDirt->Bind(3);
shader->SetUniform("u_LensDirtIntensity", m_LensDirtIntensity);
}
m_UpSampleFB[m_Iteration - 1]->GetTexture()->Bind(1);
m_Source->Bind(2);
Renderer::DrawQuad(Matrix4());
}

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