247 Commits

Author SHA1 Message Date
antopilo
076960c41d vma 2024-12-23 23:46:31 -05:00
antopilo
2898a6f5b0 Fixed compilation errors 2024-12-21 11:57:32 -05:00
antopilo
f1a36c495d Removed DOF manual focus serialization, its always on by default 2024-12-02 17:54:27 -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
emerycp
89971b2d77 Added .project properties to Project Settings 2024-09-05 21:37:55 -04:00
Antoine Pilote
43e9d6e7fc rip 2024-09-05 20:01:12 -04:00
Antoine Pilote
2c2ed94eea Fixed other mix shader fail casting 2024-09-05 20:00:19 -04:00
Antoine Pilote
120af20237 Fix outline shader for AMD cards 2024-09-05 19:54:21 -04:00
Antoine Pilote
422331dec2 Automatically refresh filebrowser on window focus, and preserve path after scanning 2024-09-05 19:44:27 -04:00
Antoine Pilote
9e05e6883a Forgot to include functional header 2024-09-05 19:09:45 -04:00
Antoine Pilote
73c927fdaf Added window callbacks for focused and closed 2024-09-05 19:07:48 -04:00
Antoine Pilote
5e3472c256 Fixed Coral crash with base type classes, temp fix for logs crash + added light color param to C# api 2024-09-05 00:52:55 -04:00
Antoine Pilote
732e94899c Added Physics.Raycast and Transform shortcut on entity objects 2024-09-04 22:26:59 -04:00
Antoine Pilote
ea97133e94 Bumped coral 2024-09-04 22:26:34 -04:00
Antoine Pilote
e1550fbff9 Forgot premake45 2024-09-04 21:05:14 -04:00
Antoine Pilote
780b95fba7 Removed line 2024-09-04 21:02:58 -04:00
Antoine Pilote
a2f28c4c86 Added AMD code path 2024-09-04 20:50:57 -04:00
Antoine Pilote
9c5f05f224 Fixed camera preview wrong translation + made it smaller 2024-09-04 20:45:32 -04:00
Antoine Pilote
e607b99191 Added preview window when selecting a camera in the scene 2024-09-04 20:31:43 -04:00
Antoine Pilote
e1813870a2 Fixedruntime refact 2024-09-04 16:38:52 -04:00
Antoine Pilote
ec9748ecd7 Removed old documentation 2024-09-04 01:09:35 -04:00
Antoine Pilote
7140d2b4ff Reverted ImUI namespace to avoir unresolved errors 2024-09-04 01:07:33 -04:00
Antoine Pilote
8c620be479 Fixed compilation errors 2024-09-04 01:02:05 -04:00
Antoine Pilote
10b8c862e7 Applying code standard new window, job, jobsystem and imui 2024-09-04 00:51:43 -04:00
Antoine Pilote
dc3c993962 Refactor pass #3 2024-09-04 00:33:05 -04:00
Antoine Pilote
db0ec40948 Moved project out of engine.h 2024-09-04 00:30:35 -04:00
Antoine Pilote
f650f0485b Forgot to change usage of SetcurrentScene 2024-09-04 00:30:11 -04:00
Antoine Pilote
156bf8c5cc Renamed LoadScene to SetCurrentScene 2024-09-04 00:16:37 -04:00
Antoine Pilote
87f58d890e Moved FileDialog into its own class 2024-09-04 00:14:00 -04:00
Antoine Pilote
c91812c65e Moved FileSystem stuff into seprate files and a FileSystem Folder 2024-09-03 23:49:22 -04:00
Antoine Pilote
db21f342b5 Attempt at fixing AMD Driver crash 2024-09-03 20:28:51 -04:00
Antoine Pilote
adb90b4f42 Fixed typo preventing setting game mode 2024-09-03 20:02:05 -04:00
Antoine Pilote
112718d1ac Removed pch 2024-09-03 19:32:00 -04:00
Antoine Pilote
aaf553f8ba Fixed wrong include 2024-09-03 19:31:07 -04:00
Antoine Pilote
db8ec0fbfd Merge branch 'develop' of https://github.com/antopilo/Nuake into develop 2024-09-03 18:48:10 -04:00
Antoine Pilote
1ac0337863 Refactor pass #1 2024-09-03 18:47:45 -04:00
Antoine Pilote
be725f52f2 Check if .map file exists 2024-09-03 16:41:52 -04:00
Antoine Pilote
55a2403b88 Merge branch 'develop' of https://github.com/antopilo/nuake into develop
# Conflicts:
#	Nuake/src/Rendering/Renderer.cpp
2024-09-03 12:40:19 -04:00
Antoine Pilote
54e5787472 Merge branch 'develop' of https://github.com/antopilo/Nuake into develop 2024-09-02 18:12:49 -04:00
Antoine Pilote
8aef2aaff9 Removed some empty line 2024-09-02 18:12:42 -04:00
Antoine Pilote
ced74170c5 Merge pull request #70 from WiggleWizard/feature/tracy
Tracy MVP integration
2024-09-02 18:12:15 -04:00
Antoine Pilote
000a1d564e Added base 2024-09-02 18:10:36 -04:00
Antoine Pilote
d9237f83d2 Added ground normal & ground velocity C# API e 2024-09-02 18:09:02 -04:00
WiggleWizard
5a801e642c Tracy MVP integration 2024-09-02 20:37:47 +01:00
Antoine Pilote
01000b9d13 Added float type and default values for trenchbroom integration 2024-09-02 14:05:59 -04:00
Antoine Pilote
d20847b4e3 Moved audio update last 2024-09-02 13:03:49 -04:00
Antoine Pilote
c7a1c10ff0 Removed spinning audio thread 2024-09-02 12:59:49 -04:00
Antoine Pilote
5077b1b7f8 Changed to only use 1 file watcher 2024-09-02 12:56:02 -04:00
Antoine Pilote
8f72f1711d Merge branch 'develop' of https://github.com/antopilo/Nuake into develop 2024-09-02 11:34:26 -04:00
Antoine Pilote
7af703b5fc Now scaling depth in viewport Depth mode and removed debug windows 2024-09-02 11:34:23 -04:00
Antoine Pilote
178ad898b9 Merge pull request #68 from WiggleWizard/develop
Initial module architecture
2024-09-02 11:30:52 -04:00
Antoine Pilote
63578ced2d Merge pull request #69 from WiggleWizard/refactor/buildassets
Removed build asset bash script in favor of a pure Lua version to make it easier to maintain and cross-platform
2024-09-02 11:30:16 -04:00
WiggleWizard
5971e4f2d6 Removed build asset bash script in favor of a pure Lua version to make it easier to maintain and cross-platform 2024-09-02 12:33:30 +01:00
WiggleWizard
67a1406e1b Fixed trailing comma missing in list within build script 2024-09-02 11:11:05 +01:00
WiggleWizard
bcf3e9751a Initial module architecture 2024-09-02 10:50:41 +01:00
Antoine Pilote
636736f567 Fixed a bug where bsp wouldnt get serialized properly + displaying brush in darker in scene hierarchy 2024-09-01 23:50:00 -04:00
Antoine Pilote
b7ee13c0eb Fixed crash when live reloading a map and a brush was selected 2024-09-01 23:18:51 -04:00
Antoine Pilote
d289c5431d Added live reloading for quake maps 2024-09-01 23:04:34 -04:00
Antoine Pilote
63712edc6d Added C# Point entities + automatic export of FGD entities 2024-09-01 19:37:05 -04:00
Antoine Pilote
f59a7e931f Now renders func brush materials correclty 2024-08-31 12:33:48 -04:00
Antoine Pilote
8aa41a1bf8 Now diplaying links between brushes 2024-08-31 00:07:45 -04:00
Antoine Pilote
05096355be Fixed spot light transformation 2024-08-29 12:54:31 -04:00
Antoine Pilote
c5563c204c Merge pull request #67 from antopilo/develop
Updated read me
2024-08-16 00:00:58 -04:00
386 changed files with 361632 additions and 328485 deletions

View File

@@ -1,59 +0,0 @@
#!/bin/bash
# Directory containing the files
input_directory="Resources"
# Output C++ header file for variable declarations
output_header="Nuake/src/Resource/StaticResources.h"
# Output C++ source file for data storage
output_source="Nuake/src/Resource/StaticResources.cpp"
# Remove existing header and source files (if any)
rm -f "$output_header" "$output_source"
# Create the C++ header file with an initial guard
echo "#ifndef FILES_DATA_H" >> "$output_header"
echo "#define FILES_DATA_H" >> "$output_header"
echo "#include <string> " >> "$output_header"
echo "namespace Nuake { " >> "$output_header"
echo " namespace StaticResources { " >> "$output_header"
# Create the C++ source file
echo "#include \"StaticResources.h\"" >> "$output_source"
echo "namespace Nuake { " >> "$output_source"
echo " namespace StaticResources { " >> "$output_source"
# Use find to search for files in the directory and its subdirectories
find "$input_directory" -type f -print0 | while IFS= read -r -d $'\0' file_path; do
# Get the relative path of the file within the input_directory
relative_path="${file_path/}"
# Sanitize the relative path to make it suitable for C++ variable names
sanitized_path="${relative_path//[^[:alnum:]_]/_}"
# Generate C++ variable declarations for file path and size
echo "extern const std::string ${sanitized_path}_path;" >> "$output_header"
echo "extern unsigned int ${sanitized_path}_len;" >> "$output_header"
echo "extern unsigned char ${sanitized_path}[];" >> "$output_header"
# Append C++ code to the source file for storing file data
echo -e "\n// Data for file: ${sanitized_path}_path" >> "$output_source"
echo "const std::string ${sanitized_path}_path = R\"(${relative_path})\";" >> "$output_source"
xxd -i "$file_path" | sed -e 's/^/ /' >> "$output_source"
done
echo " }" >> "$output_source"
echo "}">> "$output_source"
echo " }" >> "$output_header"
echo "}">> "$output_header"
# Close the header file guard
echo "#endif // FILES_DATA_H" >> "$output_header"
echo "Header file '$output_header' generated with variable declarations."
echo "Source file '$output_source' generated with file data."

1
.gitignore vendored
View File

@@ -864,3 +864,4 @@ Nuake/dependencies/glad/glad.vcxproj.filters
*.csproj
*.filters
cloc.exe
Nuake/src/Modules/Modules.cpp

27
.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
@@ -22,3 +13,21 @@
[submodule "Nuake/dependencies/recastnavigation"]
path = Nuake/dependencies/recastnavigation
url = https://github.com/antopilo/recastnavigation.git
[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

@@ -1,20 +0,0 @@
# .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/conf.py
# Optionally build your docs in additional formats such as PDF
formats:
- pdf
# Optionally set the version of Python and requirements required to build your docs
python:
version: 3.7
#install:
#- requirements: docs/requirements.txt

View File

@@ -5,23 +5,19 @@
#include <src/Core/Input.h>
#include <src/Scene/Scene.h>
#include <src/Scene/Entities/Entity.h>
#include <src/Scene/Components/Components.h>
#include <src/Scene/Components.h>
#include "src/Windows/EditorInterface.h"
#include <src/Scene/Components/QuakeMap.h>
#include <src/Vendors/imgui/imgui.h>
#include <src/Vendors/imgui/ImGuizmo.h>
#include <src/Physics/PhysicsManager.h>
#include "src/Scene/Components/BoxCollider.h"
#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>
#include <src/Scene/Components/BSPBrushComponent.h>
#include "src/Actions/EditorSelection.h"
#include "src/Misc/GizmoDrawer.h"
@@ -98,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++;
}
@@ -116,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

@@ -1,7 +1,10 @@
#include "Commands.h"
#include <Engine.h>
#include "src/Core/FileSystem.h"
#include "src/FileSystem/FileSystem.h"
#include <filesystem>
namespace NuakeEditor
{
@@ -39,6 +42,12 @@ namespace NuakeEditor
{
const std::string& cleanProjectName = String::Sanitize(mProject->Name);
const std::string& gameConfigFolderPath = mProject->TrenchbroomPath + "/../games/" + cleanProjectName + "/";
if (!FileSystem::DirectoryExists(gameConfigFolderPath))
{
FileSystem::MakeDirectory(gameConfigFolderPath, true);
}
const std::string& gameConfigFilePath = gameConfigFolderPath + "GameConfig.cfg";
FileSystem::BeginWriteFile(gameConfigFilePath, true);
@@ -56,7 +65,7 @@ namespace NuakeEditor
"packageformat": { "extension": ".zip", "format": "zip" }
},
"textures": {
"root": "textures",
"root": "Textures",
"extensions": [ ".jpg", ".png", ".tga" ]
},
"entities": {
@@ -69,8 +78,8 @@ namespace NuakeEditor
"name": "Trigger",
"attribs": [ "transparent" ],
"match": "classname",
"pattern": "trigger_*",
"texture": "trigger"
"pattern": "Trigger*",
"texture": "trigger.png"
}
],
"brushface": [
@@ -135,7 +144,7 @@ namespace NuakeEditor
// Copy Icon.png
if (FileSystem::FileExists("icon.png"))
{
std::filesystem::copy_file(FileSystem::RelativeToAbsolute("icon.png"), gameConfigFolderPath + "Icon.png");
std::filesystem::copy_file(FileSystem::RelativeToAbsolute("icon.png"), gameConfigFolderPath + "Icon.png", std::filesystem::copy_options::overwrite_existing);
}
return true;
}

View File

@@ -1,147 +0,0 @@
#pragma once
#include "ComponentPanel.h"
#include <src/Core/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

@@ -1,24 +1,25 @@
#pragma once
#include "ComponentPanel.h"
#include <src/Core/FileSystem.h>
#include "src/FileSystem/FileSystem.h"
#include <src/Core/Maths.h>
#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

@@ -1,7 +1,7 @@
#pragma once
#include "ComponentPanel.h"
#include <src/Core/FileSystem.h>
#include "src/FileSystem/FileSystem.h"
#include <src/Core/Maths.h>
#include <src/Scene/Components/BoxCollider.h>
#include <src/Scene/Entities/ImGuiHelper.h>

View File

@@ -1,19 +1,22 @@
#pragma once
#include "ComponentPanel.h"
#include <src/Scene/Components/CameraComponent.h>
#include <src/Core/FileSystem.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

@@ -1,20 +1,22 @@
#pragma once
#include "ComponentPanel.h"
#include <src/Scene/Components/CharacterControllerComponent.h>
#include <src/Core/FileSystem.h>
class CharacterControllerPanel : ComponentPanel {
#include "src/FileSystem/FileSystem.h"
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

@@ -1,9 +1,12 @@
#include "MaterialEditor.h"
#include <imgui/imgui.h>
#include <src/Resource/FontAwesome5.h>
#include <src/Vendors/imgui/imgui_internal.h>
#include "../Misc/InterfaceFonts.h"
#include <src/Resource/FontAwesome5.h>
#include <src/Resource/ResourceManager.h>
#include <src/FileSystem/FileDialog.h>
#include <imgui/imgui.h>
#include <src/Vendors/imgui/imgui_internal.h>
void MaterialEditor::Draw(Ref<Nuake::Material> material)
{

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

@@ -8,6 +8,8 @@
#include <src/Scene/Components/ModelComponent.h>
#include <src/Resource/ResourceLoader.h>
#include <src/Resource/ResourceManager.h>
#include <src/Core/String.h>
#include <src/Resource/ModelLoader.h>
@@ -24,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

@@ -1,16 +1,57 @@
#include "NetScriptPanel.h"
#include "../Windows/FileSystemUI.h"
#include <src/Scene/Components/NetScriptComponent.h>
#include <src/Core/FileSystem.h>
#include <src/FileSystem/FileDialog.h>
#include "src/FileSystem/FileSystem.h"
#include <src/Scripting/ScriptingEngineNet.h>
#include <src/Scene/Components/NetScriptComponent.h>
#include <src/Scene/Entities/ImGuiHelper.h>
void NetScriptPanel::Draw(Nuake::Entity entity)
{
if (!entity.HasComponent<Nuake::NetScriptComponent>())
return;
const std::string NET_TEMPLATE_SCRIPT_FIRST = R"(using Nuake.Net;
auto& component = entity.GetComponent<Nuake::NetScriptComponent>();
namespace NuakeShowcase
{
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
}
}
}
)";
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);
{
{
@@ -130,6 +171,11 @@ void NetScriptPanel::Draw(Nuake::Entity entity)
{
if (!field.Value.has_value())
{
if (!field.DefaultValue.has_value())
{
field.DefaultValue = 0.0f;
}
field.Value = field.DefaultValue;
}
@@ -143,6 +189,11 @@ void NetScriptPanel::Draw(Nuake::Entity entity)
{
if (!field.Value.has_value())
{
if (!field.DefaultValue.has_value())
{
field.DefaultValue = 0.0;
}
field.Value = field.DefaultValue;
}
@@ -156,13 +207,22 @@ void NetScriptPanel::Draw(Nuake::Entity entity)
{
if (!field.Value.has_value())
{
if (!field.DefaultValue.has_value())
{
field.DefaultValue = false;
}
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)
@@ -188,6 +248,11 @@ void NetScriptPanel::Draw(Nuake::Entity entity)
{
if (!field.Value.has_value())
{
if (!field.DefaultValue.has_value())
{
field.DefaultValue = Nuake::Vector2(0, 0);
}
field.Value = field.DefaultValue;
}
@@ -203,6 +268,11 @@ void NetScriptPanel::Draw(Nuake::Entity entity)
{
if (!field.Value.has_value())
{
if (!field.DefaultValue.has_value())
{
field.DefaultValue = Nuake::Vector3(0, 0, 0);
}
field.Value = field.DefaultValue;
}

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/Core/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/Core/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/Core/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,114 +0,0 @@
#include "ScriptPanel.h"
#include "../Windows/FileSystemUI.h"
#include <src/Scene/Components/WrenScriptComponent.h>
#include <src/Core/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/Core/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/Core/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,11 +7,15 @@
#include <glad/glad.h>
#include "src/UI/NuakeUI.h"
#include "src/UI/UIInputManager.h"
void EditorApplication::OnInit()
{
using namespace Nuake;
Engine::Init();
m_Window = Engine::GetCurrentWindow();
m_Window->SetSize({ m_Specification.WindowWidth, m_Specification.WindowHeight });
@@ -45,6 +49,39 @@ void EditorApplication::OnInit()
}
}
m_Window->SetOnWindowFocusedCallback([&](Window& window, bool focused)
{
if (!focused)
{
return;
}
for (auto& layer : m_LayerStack)
{
layer->OnWindowFocused();
}
});
m_Window->SetOnWindowClosedCallback([](Window& window)
{
if (Engine::GetProject())
{
Engine::GetProject()->Save();
}
if (Engine::GetCurrentScene())
{
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();
}
@@ -75,4 +79,14 @@ void EditorLayer::OnUpdate()
void EditorLayer::OnDetach()
{
delete m_EditorInterface;
}
}
void EditorLayer::OnWindowFocused()
{
m_EditorInterface->OnWindowFocused();
}
void EditorLayer::OnDragNDrop(const std::vector<std::string>& paths)
{
m_EditorInterface->OnDragNDrop(paths);
}

View File

@@ -22,6 +22,9 @@ public:
virtual void OnUpdate() override;
virtual void OnDetach() override;
virtual void OnWindowFocused() override;
virtual void OnDragNDrop(const std::vector<std::string>& paths) override;
private:
CommandBuffer mCommandBuffer;
Nuake::EditorInterface* m_EditorInterface;

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>
@@ -22,7 +23,9 @@
#include <src/Scene/Components/ParticleEmitterComponent.h>
#include <src/Scene/Components/BoneComponent.h>
#include <src/Scene/Components/AudioEmitterComponent.h>
#include <src/Scene/Components/ParentComponent.h>
#include <DetourDebugDraw.h>
#include <src/Scene/Components/BSPBrushComponent.h>
GizmoDrawer::GizmoDrawer(EditorInterface* editor)
@@ -141,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;
@@ -182,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);
@@ -211,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)
@@ -249,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);
@@ -262,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);
@@ -283,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);
}
@@ -311,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);
@@ -336,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);
@@ -369,23 +376,52 @@ 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);
}
}
auto bspView = scene->m_Registry.view<TransformComponent, BSPBrushComponent>();
for (auto e : bspView)
{
auto [transform, brush] = scene->m_Registry.get<TransformComponent, BSPBrushComponent>(e);
if (brush.target.empty())
{
continue;
}
auto bspView2 = scene->m_Registry.view<TransformComponent, BSPBrushComponent>();
for (auto e2 : bspView2)
{
auto [transform2, brush2] = scene->m_Registry.get<TransformComponent, BSPBrushComponent>(e2);
if (brush2.TargetName.empty())
{
continue;
}
if (brush.target == brush2.TargetName)
{
Vector3 from = transform.GetGlobalTransform()[3];
Vector3 to = transform2.GetGlobalTransform()[3];
scene->m_SceneRenderer->DrawDebugLine(from, to, Color(1, 0, 0, 1), 0.f, 1.0f);
}
}
}
auto particleView = scene->m_Registry.view<TransformComponent, ParticleEmitterComponent>();
for (auto e : particleView)
{
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);
@@ -414,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();
@@ -423,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);
@@ -438,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();
@@ -448,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();
@@ -470,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);
@@ -491,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;
@@ -512,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();
@@ -535,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();
@@ -557,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();
@@ -578,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();
@@ -599,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

@@ -1,10 +1,19 @@
#include "ThumbnailManager.h"
#include <src/Vendors/glm/ext/matrix_clip_space.hpp>
#include <src/FileSystem/FileTypes.h>
#include <src/FileSystem/File.h>
#include <src/Scene/Components/CameraComponent.h>
#include <src/Scene/Components/ModelComponent.h>
#include <src/Rendering/SceneRenderer.h>
#include <src/Resource/ResourceLoader.h>
#include <glad/glad.h>
#include <src/Resource/Prefab.h>
#include <src/Resource/ResourceLoader.h>
#include <src/Vendors/glm/ext/matrix_clip_space.hpp>
#include <glad/glad.h>
#include <Tracy.hpp>
ThumbnailManager::ThumbnailManager()
@@ -39,6 +48,8 @@ bool ThumbnailManager::IsThumbnailLoaded(const std::string& path) const
Ref<Nuake::Texture> ThumbnailManager::GetThumbnail(const std::string& path)
{
ZoneScoped;
if (IsThumbnailLoaded(path))
{
return m_Thumbnails[path];
@@ -71,6 +82,9 @@ void ThumbnailManager::MarkThumbnailAsDirty(const std::string & path)
Ref<Nuake::Texture> ThumbnailManager::GenerateThumbnail(const std::string& path, Ref<Nuake::Texture> texture)
{
ZoneScopedN("GenerateThumbnail");
ZoneText(path.c_str(), path.size());
using namespace Nuake;
const Matrix4 ortho = glm::orthoLH(-0.6f, 0.6f, -0.6f, 0.6f, -100.0f, 100.0f);
@@ -80,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();
@@ -113,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();
@@ -129,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);
@@ -145,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());
//}
@@ -178,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());
}
@@ -201,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);
@@ -219,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);
@@ -235,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

@@ -4,7 +4,7 @@
#include "src/Vendors/imgui/imgui.h"
#include <src/Vendors/imgui/ImGuizmo.h>
#include "src/Core/FileSystem.h"
#include "src/FileSystem/FileSystem.h"
#include "../Actions/EditorSelection.h"
#include "EditorSelectionPanel.h"
@@ -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,39 +75,54 @@ 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);
public:
std::string GetEntityTypeName(const Entity& entity) const;
static void PushCommand(ICommand&& command);
public:
void OnWindowFocused();
void OnDragNDrop(const std::vector<std::string>& paths);
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -2,61 +2,49 @@
#include "../Actions/EditorSelection.h"
#include "src/Scene/Entities/Entity.h"
#include "src/Core/FileSystem.h"
#include "src/FileSystem/FileSystem.h"
#include <src/Resource/Project.h>
#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/Resource/Prefab.h>
namespace Nuake
{
class Scene;
}
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);
@@ -64,11 +52,48 @@ 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

@@ -12,15 +12,19 @@
#include <src/Rendering/Textures/Material.h>
#include "../Misc/PopupHelper.h"
#include <src/FileSystem/FileDialog.h>
#include <src/FileSystem/Directory.h>
#include <src/FileSystem/File.h>
#include "src/Scene/Systems/WadConverter.h"
#include "../Misc/ThumbnailManager.h"
#include <Tracy.hpp>
#include <src/Resource/SkyResource.h>
namespace Nuake
{
Ref<Directory> FileSystemUI::m_CurrentDirectory;
// TODO: add filetree in same panel
void FileSystemUI::Draw()
{
@@ -64,6 +68,8 @@ namespace Nuake
void FileSystemUI::DrawDirectory(Ref<Directory> directory, uint32_t drawId)
{
ZoneScoped;
ImGui::PushFont(FontManager::GetFont(Icons));
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
const char* icon = ICON_FA_FOLDER;
@@ -226,6 +232,8 @@ namespace Nuake
void FileSystemUI::DrawFile(Ref<File> file, uint32_t drawId)
{
ZoneScoped;
ImGui::PushFont(EditorInterface::bigIconFont);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 4.0f);
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, {0.f, 0.f});
@@ -254,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:
@@ -262,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);
@@ -313,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());
@@ -373,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)
@@ -552,7 +593,7 @@ namespace Nuake
}
scene->Path = FileSystem::AbsoluteToRelative(projectPath);
Engine::LoadScene(scene);
Engine::SetCurrentScene(scene);
}
// Rename Popup
@@ -646,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();
}
@@ -687,8 +742,79 @@ namespace Nuake
void FileSystemUI::RefreshFileBrowser()
{
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)
{
return;
}
std::string previousPath = m_CurrentDirectory->FullPath;
FileSystem::Scan();
m_CurrentDirectory = FileSystem::RootDirectory;
if (FileSystem::DirectoryExists(previousPath, true))
{
m_CurrentDirectory = FileSystem::GetDirectory(FileSystem::AbsoluteToRelative(previousPath));
}
else
{
m_CurrentDirectory = FileSystem::RootDirectory;
}
}
float h = 200;
@@ -888,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)
@@ -907,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();
@@ -915,7 +1051,7 @@ namespace Nuake
{
ImGui::TableNextRow();
}
DrawFile(f, i);
i++;
}

View File

@@ -1,5 +1,5 @@
#pragma once
#include <src/Core/FileSystem.h>
#include "src/FileSystem/FileSystem.h"
#include <src/Scene/Entities/Entity.h>
#include "EditorInterface.h"
@@ -32,5 +32,9 @@ namespace Nuake {
bool DeletePopup();
void DrawContextMenu();
void RefreshFileBrowser();
Color GetColorByFileType(FileType fileType);
void Scan();
};
}

View File

@@ -1,11 +1,24 @@
#include "MapImporterWindow.h"
#include <imgui/imgui.h>
#include "../Misc/InterfaceFonts.h"
#include <src/UI/ImUI.h>
#include <src/Core/Logger.h>
#include <regex>
#include <src/Threading/JobSystem.h>
#include <Engine.h>
#include <src/Core/Logger.h>
#include <src/FileSystem/File.h>
#include <src/Threading/JobSystem.h>
#include <src/UI/ImUI.h>
#include <src/FileSystem/FileDialog.h>
#include <src/Core/String.h>
#include <src/Resource/Project.h>
#include <imgui/imgui.h>
#include <filesystem>
#include <fstream>
#include <sstream>
#include <regex>
using namespace Nuake;
void MapImporterWindow::Draw()
{
@@ -227,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())
@@ -272,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

@@ -1,7 +1,7 @@
#pragma once
#include <src/Core/FileSystem.h>
#include <src/Core/FileSystem.h>
#include "src/FileSystem/FileSystem.h"
#include "src/FileSystem/FileSystem.h"
#include <atomic>
class MapImporterWindow

View File

@@ -7,7 +7,8 @@
#include <src/Rendering/Textures/TextureManager.h>
#include <src/Rendering/Textures/Texture.h>
#include <src/Scene/Entities/ImGuiHelper.h>
#include <src/Core/FileSystem.h>
#include <src/FileSystem/FileDialog.h>
#include "src/FileSystem/FileSystem.h"
#include <src/UI/ImUI.h>
#include <src/Core/Logger.h>
#include <src/Resource/Project.h>
@@ -52,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 });
@@ -93,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");
}
@@ -138,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;
@@ -193,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())
@@ -230,7 +234,7 @@ namespace Nuake
Nuake::FileSystem::SetRootDirectory(projectParentPath);
auto project = Nuake::Project::New(projectTitle, description, finalLocation);
Nuake::Engine::LoadProject(project);
Nuake::Engine::LoadScene(Nuake::Scene::New());
Nuake::Engine::SetCurrentScene(Nuake::Scene::New());
project->Settings.PrimaryColor = Nuake::Color(primaryColor.x, primaryColor.y, primaryColor.z, primaryColor.w);
project->Save();
@@ -239,7 +243,7 @@ namespace Nuake
window->Maximize();
m_Editor->filesystem->m_CurrentDirectory = Nuake::FileSystem::RootDirectory;
m_Editor->isNewProject = true;
m_HasCreatedProject = true;
}
}
@@ -263,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

@@ -1,9 +1,12 @@
#include "ProjectInterface.h"
#include <src/Vendors/imgui/imgui.h>
#include "Engine.h"
#include "src/Core/FileSystem.h"
#include <src/FileSystem/FileDialog.h>
#include "src/FileSystem/FileSystem.h"
#include <src/Scripting/ScriptingEngineNet.h>
#include <src/Scripting/ScriptingEngineNet.h>
#include <src/Vendors/imgui/imgui.h>
//#include "ImGuiTextHelper.h"
namespace Nuake {

View File

@@ -1,7 +1,8 @@
#include "ProjectSettingsWindow.h"
#include <imgui/imgui.h>
#include "../../Misc/InterfaceFonts.h"
#include <src/Core/FileSystem.h>
#include <src/FileSystem/FileDialog.h>
#include "src/FileSystem/FileSystem.h"
#include "../EditorInterface.h"
#include "../../Commands/Commands/Commands.h"
#include <src/Audio/AudioManager.h>
@@ -14,23 +15,24 @@ ProjectSettingsCategoryWindowGeneral::ProjectSettingsCategoryWindowGeneral(Ref<N
void ProjectSettingsCategoryWindowGeneral::Draw()
{
using namespace Nuake;
//ImGui::InputText("Project Name", &m_Project->Name);
//ImGui::InputTextMultiline("Project Description", &m_Project->Description);
ImGui::InputText("Project Name", &m_Project->Name);
if (ImGui::Button("Locate"))
{
const std::string& locationPath = Nuake::FileDialog::OpenFile("TrenchBroom (.exe)\0TrenchBroom.exe\0");
ImGui::InputTextMultiline("Project Description", &m_Project->Description);
if (ImGui::Button("Locate"))
{
const std::string& locationPath = Nuake::FileDialog::OpenFile("TrenchBroom (.exe)\0TrenchBroom.exe\0");
if (!locationPath.empty())
{
m_Project->TrenchbroomPath = locationPath;
}
}
if (!locationPath.empty())
{
m_Project->TrenchbroomPath = locationPath;
}
}
ImGui::ColorEdit4("Primary Color", &m_Project->Settings.PrimaryColor.r);
//ImGui::InputText("Trenchbroom Path", &m_Project->TrenchbroomPath);
ImGui::SameLine();
ImGui::InputText("Trenchbroom Path", &m_Project->TrenchbroomPath);
ImGui::ColorEdit4("Primary Color", &m_Project->Settings.PrimaryColor.r);
}
ProjectSettingsWindow::ProjectSettingsWindow()
@@ -63,7 +65,7 @@ void ProjectSettingsWindow::Draw()
return;
}
ImGui::SetNextWindowSizeConstraints({600, 300}, {1280, 720});
ImGui::SetNextWindowSizeConstraints({800, 400}, {1280, 720});
if (ImGui::Begin("Project Settings", &m_DisplayWindow, ImGuiWindowFlags_NoDocking))
{
ImVec4* colors = ImGui::GetStyle().Colors;
@@ -121,7 +123,7 @@ ProjectSettingsCategoryWindowViewport::ProjectSettingsCategoryWindowViewport(Ref
void ProjectSettingsCategoryWindowViewport::Draw()
{
ImGui::DragFloat("Outline Radius", &m_Project->Settings.OutlineRadius, 0.1f, 1.0f, 10.0f);
ImGui::DragFloat("Outline Radius", &m_Project->Settings.OutlineRadius, 0.1f, 1.0f, 90.0f);
ImGui::DragFloat("Gizmo Size", &m_Project->Settings.GizmoSize, 0.01f, 0.05f, 0.5f);
ImGui::Separator();
ImGui::Checkbox("Smooth Camera", &m_Project->Settings.SmoothCamera);
@@ -182,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

@@ -1,11 +1,13 @@
#include "TrenchbroomConfiguratorWindow.h"
#include <Engine.h>
#include <src/Resource/Project.h>
#include <src/UI/ImUI.h>
#include <src/Core/OS.h>
#include <src/Rendering/Textures/TextureManager.h>
#include <src/Resource/Prefab.h>
void TrenchbroomConfiguratorWindow::Update()
{

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

@@ -5,7 +5,8 @@
#include "../Misc/InterfaceFonts.h"
#include <Engine.h>
#include <src/Core/FileSystem.h>
#include <src/FileSystem/FileDialog.h>
#include "src/FileSystem/FileSystem.h"
#include <src/Resource/Project.h>
#include <src/Core/Logger.h>
#include <src/Rendering/Textures/TextureManager.h>
@@ -80,6 +81,11 @@ namespace Nuake
ParseRecentFile();
if (_Projects.size() > 0)
{
SelectedProject = 0;
}
// Load Nuake logo
_NuakeLogo = TextureManager::Get()->GetTexture(NUAKE_LOGO_PATH);
}
@@ -109,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);
@@ -144,6 +183,7 @@ namespace Nuake
DrawRightControls();
ImGui::SameLine();
DrawRecentProjectsSection();
ImGui::End();
@@ -157,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();
}
@@ -195,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);
@@ -210,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;
@@ -220,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)
{
@@ -233,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()
@@ -275,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::LoadScene(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)
@@ -355,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,63 +1,125 @@
#include "Engine.h"
#include "src/Scene/Scene.h"
#include "src/Resource/Project.h"
#include "src/Physics/PhysicsManager.h"
#include <GLFW/glfw3.h>
#include "src/AI/NavManager.h"
#include "src/Audio/AudioManager.h"
#include "src/Core/FileSystem.h"
#include "src/FileSystem/FileSystem.h"
#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 = "";
Ref<Project> Engine::s_CurrentProject;
Ref<Window> Engine::s_CurrentWindow;
GameState Engine::gameState = GameState::Stopped;
GameState Engine::s_GameState = GameState::Stopped;
float Engine::s_LastFrameTime = 0.0f;
float Engine::s_FixedUpdateRate = 1.0f / 90.0f;
float Engine::s_FixedUpdateDifference = 0.f;
float Engine::s_Time = 0.f;
Timestep Engine::s_TimeStep = 0.f;
float Engine::s_TimeScale = 1.0f;
float Engine::lastFrameTime = 0.0f;
float Engine::fixedUpdateRate = 1.0f / 90.0f;
float Engine::fixedUpdateDifference = 0.f;
float Engine::time = 0.f;
Timestep Engine::timeStep = 0.f;
float Engine::timeScale = 1.0f;
void Engine::Init()
{
//Window::Get()->OnWindowSetScene().AddStatic(&Engine::OnWindowSetScene);
ScriptingEngineNet::Get().OnGameAssemblyLoaded().AddStatic(&Engine::OnScriptingEngineGameAssemblyLoaded);
AudioManager::Get().Initialize();
PhysicsManager::Get().Init();
NavManager::Get().Initialize();
// Creates the window
s_CurrentWindow = Window::Get();
currentWindow = Window::Get();
Input::Init();
Renderer2D::Init();
Logger::Log("Engine initialized");
RegisterCoreTypes::RegisterCoreComponents();
Modules::StartupModules();
InitializeCoreSubsystems();
}
void Engine::Tick()
{
ZoneScoped;
JobSystem::Get().Update();
s_Time = static_cast<float>(glfwGetTime());
s_TimeStep = s_Time - s_LastFrameTime;
s_LastFrameTime = s_Time;
time = static_cast<float>(glfwGetTime());
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 (s_CurrentWindow->GetScene())
if (currentWindow->GetScene())
{
float scaledTimeStep = s_TimeStep * s_TimeScale;
s_CurrentWindow->Update(scaledTimeStep);
currentWindow->Update(scaledTimeStep);
// Play mode update all the entities, Editor does not.
if (!Engine::IsPlayMode())
@@ -65,32 +127,33 @@ namespace Nuake
GetCurrentScene()->EditorUpdate(scaledTimeStep);
}
s_FixedUpdateDifference += s_TimeStep;
fixedUpdateDifference += timeStep;
// Fixed update
while (s_FixedUpdateDifference >= s_FixedUpdateRate)
while (fixedUpdateDifference >= fixedUpdateRate)
{
s_CurrentWindow->FixedUpdate(s_FixedUpdateRate * s_TimeScale);
currentWindow->FixedUpdate(fixedUpdateRate * timeScale);
s_FixedUpdateDifference -= s_FixedUpdateRate;
fixedUpdateDifference -= fixedUpdateRate;
}
Input::Update();
AudioManager::Get().AudioUpdate();
}
}
void Engine::EnterPlayMode()
{
s_LastFrameTime = (float)glfwGetTime(); // Reset timestep timer.
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();
@@ -108,22 +171,28 @@ namespace Nuake
void Engine::ExitPlayMode()
{
// Dont trigger exit if already not in play mode.
if (s_GameState != GameState::Stopped)
if (gameState != GameState::Stopped)
{
GetCurrentScene()->OnExit();
Input::ShowMouse();
s_GameState = GameState::Stopped;
gameState = GameState::Stopped;
}
}
void Engine::Draw()
{
ZoneScoped;
RenderCommand::Clear();
// Start imgui frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
{
ZoneScopedN("ImGui New Frame");
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
}
// Draw scene
Window::Get()->Draw();
@@ -131,6 +200,7 @@ namespace Nuake
void Engine::EndDraw()
{
ZoneScoped;
Window::Get()->EndDraw();
}
@@ -141,34 +211,146 @@ namespace Nuake
Ref<Scene> Engine::GetCurrentScene()
{
if (s_CurrentWindow)
if (currentWindow)
{
return s_CurrentWindow->GetScene();
return currentWindow->GetScene();
}
return nullptr;
}
bool Engine::LoadScene(Ref<Scene> scene)
bool Engine::SetCurrentScene(Ref<Scene> scene)
{
return s_CurrentWindow->SetScene(scene);
return currentWindow->SetScene(scene);
}
bool Engine::QueueSceneSwitch(const std::string& scenePath)
{
if (!IsPlayMode())
{
return false;
}
queuedScene = scenePath;
return true;
}
Ref<Project> Engine::GetProject()
{
return s_CurrentProject;
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)
{
s_CurrentProject = project;
currentProject = project;
if (!Engine::LoadScene(s_CurrentProject->DefaultScene))
if (!Engine::SetCurrentScene(currentProject->DefaultScene))
{
return false;
}
FileSystem::SetRootDirectory(FileSystem::GetParentPath(project->FullPath));
ScriptingEngineNet::Get().Initialize();
ScriptingEngineNet::Get().LoadProjectAssembly(project);
return true;
@@ -176,6 +358,6 @@ namespace Nuake
Ref<Window> Engine::GetCurrentWindow()
{
return s_CurrentWindow;
return currentWindow;
}
}

View File

@@ -1,19 +1,20 @@
#pragma once
#include "src/Core/Core.h"
#include "src/Window.h"
#include "src/Scene/Scene.h"
#include "src/Resource/Project.h"
#include "src/Core/Logger.h"
/* TODOS:
*/
#include "src/Window.h"
// Welcome to the Nuake source code.
namespace Nuake
{
class Project;
class Scene;
class EngineSubsystem;
class EngineSubsystemScriptable;
enum GameState
{
Loading,
Playing,
Paused,
Stopped
@@ -21,19 +22,6 @@ namespace Nuake
class Engine
{
private:
static Ref<Window> s_CurrentWindow;
static Ref<Project> s_CurrentProject;
static Ref<Scene> s_CurrentScene;
static GameState s_GameState;
static float s_LastFrameTime;
static float s_FixedUpdateRate;
static float s_FixedUpdateDifference;
static float s_Time;
static Timestep s_TimeStep;
static float s_TimeScale;
public:
static void Init(); // Initialize the engine.
static void Tick(); // Updates everything, called every frame.
@@ -46,23 +34,57 @@ namespace Nuake
static void Draw(); // Start new frame
static void EndDraw(); // Swap buffer
static void SetGameState(GameState gameState) { s_GameState = gameState; }
static GameState GetGameState() { return s_GameState; }
static bool IsPlayMode() { return s_GameState == GameState::Playing; }
static void SetGameState(GameState state) { gameState = state; }
static GameState GetGameState() { return gameState; }
static bool IsPlayMode() { return gameState == GameState::Playing; }
static inline float GetTime() { return s_Time; }
static inline Timestep GetTimestep() { return s_TimeStep; }
static inline void SetPhysicsStep(int amount) { s_FixedUpdateRate = 1.0f / static_cast<float>(amount); }
static inline void SetTimeScale(float timeScale) { s_TimeScale = timeScale; }
static inline float GetTimeScale() { return s_TimeScale; }
static inline float GetTime() { return time; }
static inline Timestep GetTimestep() { return timeStep; }
static inline void SetPhysicsStep(int amount) { fixedUpdateRate = 1.0f / static_cast<float>(amount); }
static inline float GetFixedTimeStep() { return fixedUpdateRate; }
static inline void SetTimeScale(float timeScale) { timeScale = timeScale; }
static inline float GetTimeScale() { return timeScale; }
static Ref<Window> GetCurrentWindow();
static bool LoadScene(Ref<Scene> scene);
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;
static float lastFrameTime;
static float fixedUpdateRate;
static float fixedUpdateDifference;
static float time;
static Timestep timeStep;
static float timeScale;
};
}

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,30 @@
group "Dependencies"
project 'Tracy'
location "tracy"
kind "StaticLib"
staticruntime "on"
warnings 'Off'
includedirs {
"tracy/public/tracy"
}
files {
"tracy/public/tracy/Tracy.hpp",
"tracy/public/TracyClient.cpp"
}
defines {
"TRACY_ENABLE",
"TRACY_ON_DEMAND",
}
filter "configurations:Debug"
runtime "Debug"
symbols "on"
filter "configurations:Release"
runtime "Release"
optimize "on"
group ""

Submodule Nuake/dependencies/vma added at 5a53a19894

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

@@ -3,6 +3,8 @@
#include <filesystem>
#include <Tracy.hpp>
namespace Nuake {
Application::Application(const ApplicationSpecification& appSpecification)
@@ -33,8 +35,11 @@ namespace Nuake {
{
while (!m_Window->ShouldClose())
{
ZoneScoped;
for (auto& layer : m_LayerStack)
{
ZoneScopedN("Layer Update");
layer->OnUpdate();
}
@@ -42,9 +47,12 @@ namespace Nuake {
{
for (auto& layer : m_LayerStack)
{
ZoneScopedN("Layer Draw");
layer->OnDraw();
}
}
FrameMark;
}
}
@@ -55,4 +63,4 @@ namespace Nuake {
layer->OnDetach();
}
}
}
}

View File

@@ -17,6 +17,8 @@ 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

@@ -1,6 +1,6 @@
#include "AudioManager.h"
#include "src/Core/Logger.h"
#include "src/Core/FileSystem.h"
#include "src/FileSystem/FileSystem.h"
#include <soloud.h>
#include "soloud_speech.h"
@@ -11,8 +11,7 @@
namespace Nuake {
AudioManager::AudioManager() :
m_AudioThreadRunning(true)
AudioManager::AudioManager()
{
}
@@ -20,9 +19,6 @@ namespace Nuake {
{
Deinitialize();
m_AudioThreadRunning = false;
m_AudioThread.join();
m_Soloud->deinit();
}
@@ -32,20 +28,11 @@ 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
if (m_AudioThread.joinable())
{
m_AudioThreadRunning = false;
m_AudioThread.join();
}
m_AudioThreadRunning = true;
m_AudioThread = std::thread(&AudioManager::AudioThreadLoop, this);
Logger::Log("Audio manager initialized", "audio", VERBOSE);
}
@@ -68,6 +55,7 @@ namespace Nuake {
m_ListenerUp.x, m_ListenerUp.y, m_ListenerUp.z
);
m_Soloud->update3dAudio();
}
}
@@ -79,9 +67,6 @@ namespace Nuake {
void AudioManager::QueueWavAudio(const AudioRequest& request)
{
// Acquire mutex lock and push to queue
const std::lock_guard<std::mutex> lock(m_AudioQueueMutex);
// Check if file exists and load
const bool fileExists = FileSystem::FileExists(request.audioFile, true);
if (fileExists && !IsWavLoaded(request.audioFile))
@@ -94,9 +79,6 @@ namespace Nuake {
void AudioManager::UpdateVoice(const AudioRequest& request)
{
// Acquire mutex lock
const std::lock_guard<std::mutex> lock(m_AudioQueueMutex);
auto& audioClip = m_ActiveClips[request.audioFile];
if (IsVoiceActive(request.audioFile))
{
@@ -125,8 +107,6 @@ namespace Nuake {
void AudioManager::StopVoice(const std::string& filePath)
{
const std::lock_guard<std::mutex> lock(m_AudioQueueMutex);
if (!IsVoiceActive(filePath))
{
return; // We can't stop a voice that isn't active.
@@ -153,7 +133,7 @@ namespace Nuake {
void AudioManager::LoadWavAudio(const std::string& filePath)
{
const bool STREAMING = true;
const bool STREAMING = false;
if (STREAMING)
{
Ref<SoLoud::WavStream> wavStream = CreateRef<SoLoud::WavStream>();
@@ -166,44 +146,42 @@ namespace Nuake {
wav->load(filePath.c_str());
m_WavSamples[filePath] = wav;
}
}
void AudioManager::AudioThreadLoop()
void AudioManager::AudioUpdate()
{
while(m_AudioThreadRunning)
// Check if we have audio queued
if (m_Soloud->getGlobalVolume() != m_GlobalVolume)
{
// Acquire mutex lock
const std::lock_guard<std::mutex> lock(m_AudioQueueMutex);
m_Soloud->setGlobalVolume(m_GlobalVolume);
}
// Check if we have audio queued
while (!m_AudioQueue.empty())
while (!m_AudioQueue.empty())
{
AudioRequest& audioRequest = m_AudioQueue.front();
Ref<SoLoud::AudioSource> audio = m_WavSamples[audioRequest.audioFile];
SoLoud::handle handle;
if (!audioRequest.spatialized)
{
AudioRequest& audioRequest = m_AudioQueue.front();
Ref<SoLoud::AudioSource> audio = m_WavSamples[audioRequest.audioFile];
SoLoud::handle soloudHandle;
if (!audioRequest.spatialized)
{
soloudHandle = m_Soloud->play(*audio);
m_Soloud->setVolume(soloudHandle, audioRequest.volume);
m_Soloud->setPan(soloudHandle, 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);
}
m_Soloud->setRelativePlaySpeed(soloudHandle, audioRequest.speed);
m_Soloud->setLooping(soloudHandle, audioRequest.Loop);
m_ActiveClips[audioRequest.audioFile] = soloudHandle;
m_AudioQueue.pop();
handle = m_Soloud->play(*audio);
m_Soloud->setVolume(handle, audioRequest.volume);
m_Soloud->setPan(handle, audioRequest.pan);
}
else
{
const Vector3& position = audioRequest.position;
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(handle, audioRequest.speed);
m_Soloud->setLooping(handle, audioRequest.Loop);
m_ActiveClips[audioRequest.audioFile] = handle;
m_AudioQueue.pop();
}
}

View File

@@ -39,10 +39,7 @@ namespace Nuake
Ref<SoLoud::Soloud> m_Soloud;
bool m_AudioThreadRunning;
std::thread m_AudioThread;
std::mutex m_AudioQueueMutex;
std::atomic<bool> m_AudioQueued = { false };
bool m_AudioQueued = false;
std::queue<AudioRequest> m_AudioQueue;
Vector3 m_ListenerPosition;
@@ -87,8 +84,9 @@ namespace Nuake
bool IsVoiceActive(const std::string & voice) const;
void LoadWavAudio(const std::string& filePath);
void AudioUpdate();
private:
void AudioThreadLoop();
void CleanupInactiveVoices();
};

View File

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

View File

@@ -1,404 +0,0 @@
#include "FileSystem.h"
#include "Engine.h"
#include "OS.h"
#include <GLFW/glfw3.h>
#ifdef NK_WIN
#define GLFW_EXPOSE_NATIVE_WIN32
#include "GLFW/glfw3native.h"
#include <commdlg.h>
#endif
#ifdef NK_LINUX
#include "gtk/gtk.h"
#endif
#include <fstream>
#include <iostream>
#include <ShlObj.h>
namespace Nuake
{
namespace fs = std::filesystem;
std::string FileDialog::OpenFile(const char* filter)
{
std::string filePath;
#ifdef NK_WIN
OPENFILENAMEA ofn;
CHAR szFile[260] = { 0 };
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = glfwGetWin32Window(Engine::GetCurrentWindow()->GetHandle());
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = filter;
ofn.nFilterIndex = 1;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
if (GetOpenFileNameA(&ofn) == TRUE)
{
filePath = std::string(ofn.lpstrFile);
}
#endif
#ifdef NK_LINUX
GtkWidget *dialog;
GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN;
gint res;
dialog = gtk_file_chooser_dialog_new("Open File",
NULL,
action,
"_Cancel",
GTK_RESPONSE_CANCEL,
"_Open",
GTK_RESPONSE_ACCEPT,
NULL);
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
if (filter) {
GtkFileFilter *file_filter = gtk_file_filter_new();
gtk_file_filter_set_name(file_filter, "Filter Name");
gtk_file_filter_add_pattern(file_filter, filter);
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), file_filter);
}
res = gtk_dialog_run(GTK_DIALOG(dialog));
if (res == GTK_RESPONSE_ACCEPT) {
char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
filePath = filename;
g_free(filename);
}
gtk_widget_destroy(dialog);
#endif
return filePath;
}
std::string FileDialog::SaveFile(const char* filter)
{
#ifdef NK_WIN
OPENFILENAMEA ofn;
CHAR szFile[260] = { 0 };
ZeroMemory(&ofn, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = glfwGetWin32Window(Engine::GetCurrentWindow()->GetHandle());
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = filter;
ofn.nFilterIndex = 1;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT;
if (GetSaveFileNameA(&ofn) == TRUE)
{
return ofn.lpstrFile;
}
#endif
#ifdef NK_LINUX
GtkWidget *dialog;
GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SAVE;
gint res;
gtk_init(NULL, NULL);
dialog = gtk_file_chooser_dialog_new("Save File",
NULL,
action,
"_Cancel",
GTK_RESPONSE_CANCEL,
"_Save",
GTK_RESPONSE_ACCEPT,
NULL);
GtkFileFilter *file_filter = gtk_file_filter_new();
gtk_file_filter_set_name(file_filter, filter);
gtk_file_filter_add_pattern(file_filter, "*.*"); // You can customize this pattern
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), file_filter);
res = gtk_dialog_run(GTK_DIALOG(dialog));
if (res == GTK_RESPONSE_ACCEPT)
{
char *filename;
GtkFileChooser *chooser = GTK_FILE_CHOOSER(dialog);
filename = gtk_file_chooser_get_filename(chooser);
std::string result(filename);
g_free(filename);
gtk_widget_destroy(dialog);
return result;
}
else
{
gtk_widget_destroy(dialog);
return std::string();
}
#endif
return std::string();
}
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)
{
SHGetPathFromIDListA(pidl, szFolder);
folderPath = std::string(szFolder);
CoTaskMemFree(pidl);
}
#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;
}
std::string FileSystem::Root = "";
Ref<Directory> FileSystem::RootDirectory;
void FileSystem::ScanDirectory(Ref<Directory> directory)
{
for (const auto& entry : std::filesystem::directory_iterator(directory->FullPath))
{
if (entry.is_directory())
{
Ref<Directory> newDir = CreateRef<Directory>();
newDir->FullPath = entry.path().string();
newDir->Name = entry.path().filename().string();
newDir->Parent = directory;
ScanDirectory(newDir);
directory->Directories.push_back(newDir);
}
else if (entry.is_regular_file())
{
std::filesystem::path currentPath = entry.path();
std::string absolutePath = currentPath.string();
std::string name = currentPath.filename().string();
std::string extension = currentPath.extension().string();
Ref<File> newFile = CreateRef<File>(directory, absolutePath, name, extension);
directory->Files.push_back(newFile);
}
}
}
bool FileSystem::DirectoryExists(const std::string& path, bool absolute)
{
const std::string& finalPath = absolute ? path : Root + path;
return std::filesystem::exists(finalPath) && std::filesystem::is_directory(finalPath);
}
bool FileSystem::MakeDirectory(const std::string& path, bool absolute)
{
return std::filesystem::create_directories(absolute ? path : FileSystem::Root + path);
}
bool FileSystem::FileExists(const std::string& path, bool absolute)
{
std::string fullPath = absolute ? path : FileSystem::Root + path;
return std::filesystem::exists(fullPath);
}
void FileSystem::SetRootDirectory(const std::string path)
{
Root = path;
Scan();
}
void FileSystem::Scan()
{
RootDirectory = CreateRef<Directory>(Root);
ScanDirectory(RootDirectory);
}
std::string FileSystem::AbsoluteToRelative(const std::string& path)
{
const fs::path rootPath(Root);
const fs::path absolutePath(path);
return fs::relative(absolutePath, rootPath).generic_string();
}
std::string FileSystem::RelativeToAbsolute(const std::string& path)
{
return Root + path;
}
std::string FileSystem::GetParentPath(const std::string& fullPath)
{
std::filesystem::path pathObj(fullPath);
auto returnvalue = pathObj.parent_path().string();
return returnvalue + "/";
}
std::string FileSystem::ReadFile(const std::string& path, bool absolute)
{
std::string finalPath = path;
if (!absolute)
finalPath = Root + path;
std::ifstream myReadFile(finalPath, std::ios::in | std::ios::binary);
std::string fileContent = "";
std::string allFile = "";
char bom[3];
myReadFile.read(bom, 3);
// Check for UTF-8 BOM (EF BB BF)
if (bom[0] == 0xEF && bom[1] == 0xBB && bom[2] == 0xBF)
{
myReadFile.seekg(3);
}
else
{
myReadFile.seekg(0);
}
// Use a while loop together with the getline() function to read the file line by line
while (getline(myReadFile, fileContent))
{
allFile.append(fileContent + "\n");
}
// Close the file
myReadFile.close();
return allFile;
}
std::ofstream FileSystem::fileWriter;
bool FileSystem::BeginWriteFile(const std::string path, bool absolute)
{
fileWriter = std::ofstream();
fileWriter.open(absolute ? path : FileSystem::Root + path);
return false;
}
bool FileSystem::WriteLine(const std::string line)
{
fileWriter << line.c_str();
return true;
}
void FileSystem::EndWriteFile()
{
fileWriter.close();
}
uintmax_t FileSystem::DeleteFileFromPath(const std::string& path)
{
return std::remove(path.c_str());
}
uintmax_t FileSystem::DeleteFolder(const std::string& path)
{
return std::filesystem::remove_all(path.c_str());
}
std::string FileSystem::GetConfigFolderPath()
{
std::string subFolderPath = OS::GetConfigFolderPath().append("/Nuake/");
if (!DirectoryExists(subFolderPath, true))
{
MakeDirectory(subFolderPath);
}
return subFolderPath;
}
Ref<Directory> FileSystem::GetFileTree()
{
return RootDirectory;
}
Ref<File> FileSystem::GetFile(const std::string& path)
{
// Note, Might be broken on other platforms.
auto splits = String::Split(path, '/');
int currentDepth = -1;
std::string currentDirName = ".";
Ref<Directory> currentDirComparator = RootDirectory;
while (currentDirName == currentDirComparator->Name)
{
currentDepth++;
currentDirName = splits[currentDepth];
// Find next directory
for (auto& d : currentDirComparator->Directories)
{
if (d->Name == currentDirName)
{
currentDirComparator = d;
}
}
// Find in files if can't find in directories.
for (auto& f : currentDirComparator->Files)
{
if (f->GetName() == currentDirName)
{
return f;
}
}
}
return nullptr;
}
std::string FileSystem::GetFileNameFromPath(const std::string& path)
{
const auto& split = String::Split(path, '/');
return String::Split(split[split.size() - 1], '.')[0];
}
Directory::Directory(const std::string& path)
{
Files = std::vector<Ref<File>>();
Directories = std::vector<Ref<Directory>>();
Name = FileSystem::AbsoluteToRelative(path);
FullPath = path;
}
}

View File

@@ -1,248 +0,0 @@
#pragma once
#include "Core.h"
#include "String.h"
#include <string>
#include <filesystem>
#include <iostream>
#include <fstream>
namespace Nuake
{
class FileDialog
{
public:
static std::string OpenFile(const char* filter);
static std::string SaveFile(const char* filter);
static std::string OpenFolder();
};
class Directory;
class File;
class FileSystem
{
public:
static std::string Root;
static Ref<Directory> RootDirectory;
static void SetRootDirectory(const std::string path);
static void Scan();
static std::string AbsoluteToRelative(const std::string& path);
static std::string RelativeToAbsolute(const std::string& path);
static std::string GetParentPath(const std::string& fullPath);
static Ref<Directory> GetFileTree();
static Ref<File> GetFile(const std::string& path);
static std::string GetFileNameFromPath(const std::string& path);
static void ScanDirectory(Ref<Directory> directory);
static void GetDirectories();
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::string ReadFile(const std::string& path, bool absolute = false);
static std::ofstream fileWriter;
static bool BeginWriteFile(const std::string path, bool absolute = false);
static bool WriteLine(const std::string line);
static void EndWriteFile();
static uintmax_t DeleteFileFromPath(const std::string& path);
static uintmax_t DeleteFolder(const std::string& path);
static std::string GetConfigFolderPath();
};
enum class FileType
{
Unkown,
Image,
Material,
Mesh,
Script,
NetScript,
Project,
Prefab,
Scene,
Wad,
Map,
Assembly,
Solution,
Audio
};
class File
{
private:
std::string Type;
std::string Name;
std::string RelativePath;
std::string AbsolutePath;
Ref<Directory> Parent;
public:
std::string GetExtension() const { return Type; }
std::string GetName() const { return Name; }
std::string GetRelativePath() const { return RelativePath; }
std::string GetAbsolutePath() const { return AbsolutePath; }
Ref<Directory> GetParent() const { return Parent; }
FileType GetFileType() const
{
std::string ext = GetExtension();
if (ext == ".png" || ext == ".jpg")
{
return FileType::Image;
}
if (ext == ".ogg" || ext == ".wav")
{
return FileType::Audio;
}
if (ext == ".material")
{
return FileType::Material;
}
if (ext == ".scene")
{
return FileType::Scene;
}
if (ext == ".project")
{
return FileType::Project;
}
if (ext == ".script")
{
return FileType::Script;
}
if (ext == ".prefab")
{
return FileType::Prefab;
}
if (ext == ".wad")
{
return FileType::Wad;
}
if (ext == ".map")
{
return FileType::Map;
}
if (ext == ".dll")
{
return FileType::Assembly;
}
if (ext == ".cs")
{
return FileType::NetScript;
}
if (ext == ".sln")
{
return FileType::Solution;
}
if (ext == ".mesh")
{
return FileType::Mesh;
}
return FileType::Unkown;
}
std::string GetFileTypeAsString() const
{
std::string ext = GetExtension();
if (ext == ".png" || ext == "jpg")
{
return "Image";
}
if (ext == ".material")
{
return "Material";
}
if (ext == ".scene")
{
return "Scene";
}
if (ext == ".project")
{
return "Project";
}
if (ext == ".script")
{
return "Script";
}
if (ext == ".prefab")
{
return "Prefab";
}
if (ext == ".wad")
{
return "Wad";
}
if (ext == ".map")
{
return "Map";
}
if (ext == ".map")
{
return "Assembly";
}
if (ext == ".cs")
{
return "C# Script";
}
return "File";
}
std::string Read()
{
return FileSystem::ReadFile(AbsolutePath, true);
}
bool IsValid()
{
return FileSystem::FileExists(AbsolutePath, true);
}
File(Ref<Directory> parentDir, const std::string& absolutePath, const std::string& name, const std::string& type)
{
AbsolutePath = absolutePath;
Parent = parentDir;
RelativePath = FileSystem::AbsoluteToRelative(absolutePath);
Name = name;
Type = type;
}
};
class Directory
{
public:
std::string Name;
std::string FullPath;
Ref<Directory> Parent;
std::vector<Ref<Directory>> Directories;
std::vector<Ref<File>> Files;
Directory(const std::string& path);
Directory() = default;
~Directory() = default;
};
}

View File

@@ -3,15 +3,21 @@
#include <imgui/imgui_impl_glfw.h>
#include <GLFW/glfw3.h>
#include <Tracy.hpp>
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;
@@ -74,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()
@@ -86,6 +93,7 @@ namespace Nuake
{
auto window = Window::Get()->GetHandle();
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
}
// Action
@@ -149,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();
@@ -167,6 +269,8 @@ namespace Nuake
void Input::Update()
{
ZoneScoped;
// Reset all input to false.
for (auto& k : m_Keys)
{

View File

@@ -1,6 +1,7 @@
#pragma once
#include "src/Core/Maths.h"
#include <string>
#include <map>
#include <utility>
@@ -65,7 +66,7 @@ namespace Nuake
TAB = 258,
BACKSPACE = 259,
INSERT = 260,
DELETE = 261,
DELETE_KEY = 261,
RIGHT = 262,
LEFT = 263,
DOWN = 264,
@@ -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

@@ -1,7 +1,9 @@
#include "OS.h"
#include "src/Window.h"
#include "Engine.h"
#include "src/Resource/Project.h"
#include "src/Window.h"
#include "src/Core/String.h"
#ifdef NK_WIN
#define GLFW_EXPOSE_NATIVE_WIN32
@@ -18,13 +20,17 @@
#include <X11/Xlib.h>
#endif
#include "src/FileSystem/File.h"
#include "src/FileSystem/Directory.h"
#include "GLFW/glfw3.h"
#include "GLFW/glfw3native.h"
#include "imgui/imgui.h"
#include <chrono>
#include <imgui/imgui.h>
#include <Subprocess.hpp>
#include <codecvt>
#include <filesystem>
#include <Subprocess.hpp>
namespace Nuake {

View File

@@ -1,7 +1,7 @@
#pragma once
#include <string>
#include "FileSystem.h"
#include "src/FileSystem/FileSystem.h"
namespace Nuake
{

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); \
}

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