Aeon Engine c550894
AeonGames Open Source Game Engine
Loading...
Searching...
No Matches
WorldEditor.cpp
1/*
2Copyright (C) 2017-2019,2021,2022,2025 Rodrigo Jose Hernandez Cordoba
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16#include "WorldEditor.h"
17#include "aeongames/Vector3.hpp"
18#include "aeongames/Vector4.hpp"
19#include "aeongames/Renderer.hpp"
20#include "aeongames/AeonEngine.hpp"
21#include "aeongames/Material.hpp"
22#include "RendererSelectDialog.h"
23#include <QMessageBox>
24#include <QFile>
25#include <iostream>
26
27namespace AeonGames
28{
30 {
31 return *mGridPipeline;
32 }
34 {
35 return *mGridMesh;
36 }
38 {
39 return *mXGridMaterial;
40 }
42 {
43 return *mYGridMaterial;
44 }
46 {
47 return *mSolidColorPipeline;
48 }
50 {
51 return *mSolidColorMaterial;
52 }
54 {
55 return *mAABBWireMesh;
56 }
57
59 {
60 return mStringIdMetaType;
61 }
62
64 {
65 return mStringMetaType;
66 }
67
69 {
70 return mPathMetaType;
71 }
72
74 {
75 return mRenderer.get();
76 }
77
78 static void LoadPipeline ( Pipeline& aPipeline, const std::string& aFileName )
79 {
80 QFile pipeline_file ( aFileName.c_str() );
81 if ( !pipeline_file.open ( QIODevice::ReadOnly ) )
82 {
83 throw std::runtime_error ( "Unable to open pipeline." );
84 }
85 QByteArray pipeline_byte_array = pipeline_file.readAll();
86 aPipeline.LoadFromMemory ( pipeline_byte_array.data(), pipeline_byte_array.size() );
87 }
88 static void LoadMaterial ( Material& aMaterial, const std::string& aFileName )
89 {
90 QFile material_file ( aFileName.c_str() );
91 if ( !material_file.open ( QIODevice::ReadOnly ) )
92 {
93 throw std::runtime_error ( "Unable to open material." );
94 }
95 QByteArray material_byte_array = material_file.readAll();
96 aMaterial.LoadFromMemory ( material_byte_array.data(), material_byte_array.size() );
97 }
98
99 static void LoadMesh ( Mesh& aMesh, const std::string& aFileName )
100 {
101 QFile mesh_file ( aFileName.c_str() );
102 if ( !mesh_file.open ( QIODevice::ReadOnly ) )
103 {
104 throw std::runtime_error ( "Unable to open mesh." );
105 }
106 QByteArray mesh_byte_array = mesh_file.readAll();
107 aMesh.LoadFromMemory ( mesh_byte_array.data(), mesh_byte_array.size() );
108 }
109
110 WorldEditor::WorldEditor ( int &argc, char *argv[] ) : QApplication ( argc, argv ),
111 mStringIdMetaType{qRegisterMetaType<StringId>() },
112 mStringMetaType{qRegisterMetaType<std::string>() },
113 mPathMetaType{qRegisterMetaType<std::filesystem::path>() }
114 {
115 setWindowIcon ( QIcon ( ":/icons/magnifying_glass" ) );
116 setOrganizationName ( "AeonGames" );
117 setOrganizationDomain ( "aeongames.com" );
118 setApplicationName ( "AeonGames World Editor" );
119
120 /* Workspace default settings */
121 QSettings settings{};
122 settings.beginGroup ( "Workspace" );
123
124 QSizeF Scale = settings.value ( "Scale", QSizeF ( 780.0f, 780.0f ) ).toSizeF();
125 QColor OddLineColor = settings.value ( "OddLineColor", QColor ( 74, 74, 74 ) ).value<QColor>();
126 QColor EvenLineColor = settings.value ( "EvenLineColor", QColor ( 74, 74, 74 ) ).value<QColor>();
127 QColor XLineColor = settings.value ( "XLineColor", QColor ( 255, 0, 0 ) ).value<QColor>();
128 QColor YLineColor = settings.value ( "YLineColor", QColor ( 0, 255, 0 ) ).value<QColor>();
129 QColor BorderLineColor = settings.value ( "BorderLineColor", QColor ( 74, 74, 74 ) ).value<QColor>();
130 uint32_t HorizontalSpacing = settings.value ( "HorizontalSpacing", uint32_t ( 16 ) ).toUInt();
131 uint32_t VerticalSpacing = settings.value ( "VerticalSpacing", uint32_t ( 16 ) ).toUInt();
132 settings.endGroup();
133
134
135 /* Add a nice renderer selection window.*/
136 QStringList renderer_list;
137 EnumerateRendererConstructors ( [&renderer_list] ( const std::string & aIdentifier )->bool
138 {
139 renderer_list.append ( QString::fromStdString ( aIdentifier ) );
140 return true;
141 } );
142
143 if ( !renderer_list.size() )
144 {
145 throw std::runtime_error ( "No renderer available, cannot continue." );
146 }
147 if ( renderer_list.size() == 1 )
148 {
149 mRendererName = renderer_list.at ( 0 ).toStdString();
150 }
151 else
152 {
153 RendererSelectDialog select_renderer;
154 select_renderer.SetRenderers ( renderer_list );
155 if ( select_renderer.exec() == QDialog::Accepted )
156 {
157 mRendererName = select_renderer.GetSelected().toStdString();
158 }
159 }
160
161 if ( mRendererName.empty() )
162 {
163 throw std::runtime_error ( "No renderer selected, cannot continue." );
164 }
165
166 {
167 mGridPipeline = std::make_unique<Pipeline>();
168 mSolidColorPipeline = std::make_unique<Pipeline>();
169 mXGridMaterial = std::make_unique<Material>();
170 mYGridMaterial = std::make_unique<Material>();
171 mSolidColorMaterial = std::make_unique<Material>();
172
173 LoadMaterial ( *mSolidColorMaterial, ":/materials/solidcolor.mtl" );
174 LoadPipeline ( *mGridPipeline, ":/pipelines/grid.pln" );
175 LoadPipeline ( *mSolidColorPipeline, ":/pipelines/solid_color.pln" );
176 LoadMaterial ( *mXGridMaterial, ":/materials/grid.mtl" );
177
178 mXGridMaterial->Set ( { "Scale", Vector3{static_cast<float> ( Scale.width() ), static_cast<float> ( Scale.height() ), 1.0f} } );
179 mXGridMaterial->Set ( { "StartingPosition", Vector3{0.0f, - static_cast<float> ( Scale.height() / 2 ), 0.0f} } );
180 mXGridMaterial->Set ( { "Offset", Vector3{0.0f, static_cast<float> ( Scale.height() / static_cast<float> ( HorizontalSpacing ) ), 0.0f} } );
181 mXGridMaterial->Set ( { "LineCount", static_cast<uint32_t> ( HorizontalSpacing + 1 ) } );
182 mXGridMaterial->Set ( {"OddLineColor",
183 Vector4
184 {
185 static_cast<float> ( OddLineColor.redF() ),
186 static_cast<float> ( OddLineColor.greenF() ),
187 static_cast<float> ( OddLineColor.blueF() ),
188 static_cast<float> ( OddLineColor.alphaF() )
189 }} );
190 mXGridMaterial->Set ( {"EvenLineColor",
191 Vector4
192 {
193 static_cast<float> ( EvenLineColor.redF() ),
194 static_cast<float> ( EvenLineColor.greenF() ),
195 static_cast<float> ( EvenLineColor.blueF() ),
196 static_cast<float> ( EvenLineColor.alphaF() )
197 }} );
198 mXGridMaterial->Set ( {"CentralLineColor",
199 Vector4
200 {
201 static_cast<float> ( XLineColor.redF() ),
202 static_cast<float> ( XLineColor.greenF() ),
203 static_cast<float> ( XLineColor.blueF() ),
204 static_cast<float> ( XLineColor.alphaF() )
205 }} );
206 mXGridMaterial->Set ( {"BorderLineColor",
207 Vector4
208 {
209 static_cast<float> ( BorderLineColor.redF() ),
210 static_cast<float> ( BorderLineColor.greenF() ),
211 static_cast<float> ( BorderLineColor.blueF() ),
212 static_cast<float> ( BorderLineColor.alphaF() )
213 }} );
214
215 LoadMaterial ( *mYGridMaterial, ":/materials/grid.mtl" );
216 mYGridMaterial->Set ( { "Scale", Vector3{static_cast<float> ( Scale.width() ), static_cast<float> ( Scale.height() ), 1.0f} } );
217 mYGridMaterial->Set ( { "StartingPosition", Vector3{ - static_cast<float> ( Scale.width() / 2 ), 0.0f, 0.0f} } );
218 mYGridMaterial->Set ( { "Offset", Vector3{ ( static_cast<float> ( Scale.width() ) / ( VerticalSpacing ) ), 0.0f, 0.0f} } );
219 mYGridMaterial->Set ( { "LineCount", static_cast<uint32_t> ( VerticalSpacing + 1 ) } );
220 mYGridMaterial->Set ( {"OddLineColor",
221 Vector4
222 {
223 static_cast<float> ( OddLineColor.redF() ),
224 static_cast<float> ( OddLineColor.greenF() ),
225 static_cast<float> ( OddLineColor.blueF() ),
226 static_cast<float> ( OddLineColor.alphaF() )
227 }} );
228 mYGridMaterial->Set ( {"EvenLineColor",
229 Vector4
230 {
231 static_cast<float> ( EvenLineColor.redF() ),
232 static_cast<float> ( EvenLineColor.greenF() ),
233 static_cast<float> ( EvenLineColor.blueF() ),
234 static_cast<float> ( EvenLineColor.alphaF() )
235 }} );
236 mYGridMaterial->Set ( {"CentralLineColor",
237 Vector4
238 {
239 static_cast<float> ( YLineColor.redF() ),
240 static_cast<float> ( YLineColor.greenF() ),
241 static_cast<float> ( YLineColor.blueF() ),
242 static_cast<float> ( YLineColor.alphaF() )
243 }} );
244 mYGridMaterial->Set ( {"BorderLineColor",
245 Vector4
246 {
247 static_cast<float> ( BorderLineColor.redF() ),
248 static_cast<float> ( BorderLineColor.greenF() ),
249 static_cast<float> ( BorderLineColor.blueF() ),
250 static_cast<float> ( BorderLineColor.alphaF() )
251 }} );
252 }
253
254 mGridMesh = std::make_unique<Mesh>();
255 mAABBWireMesh = std::make_unique<Mesh>();
256 LoadMesh ( *mGridMesh, ":/meshes/grid.msh" );
257 LoadMesh ( *mAABBWireMesh, ":/meshes/aabb_wire.msh" );
258 }
259
261 {
262 mGridMesh.reset();
263 mGridPipeline.reset();
264 mXGridMaterial.reset();
265 mYGridMaterial.reset();
266 mAABBWireMesh.reset();
267 mSolidColorMaterial.reset();
268 mSolidColorPipeline.reset();
269 mRenderer.reset();
270 }
271
273 {
274 if ( mRenderer == nullptr )
275 {
276 mRenderer = AeonGames::ConstructRenderer ( mRendererName, aWindow );
277 }
278 else
279 {
280 mRenderer->AttachWindow ( aWindow );
281 }
282 }
284 {
285 mRenderer->DetachWindow ( aWindow );
286 }
287}
Header for the 3D vector class.
Header for the 4D vector class.
Represents a surface material with uniform properties and texture samplers.
Definition Material.hpp:38
Represents a polygon mesh with vertex attributes and index data.
Definition Mesh.hpp:31
Rendering pipeline resource.
Definition Pipeline.hpp:122
DLL void LoadFromMemory(const void *aBuffer, size_t aBufferSize) final
Load pipeline data from a memory buffer.
Definition Pipeline.cpp:209
Abstract base class for rendering backends.
Definition Renderer.hpp:44
Dialog for selecting a rendering backend.
void SetRenderers(const QStringList &renderers)
Populate the dialog with available renderers.
const QString GetSelected() const
Get the name of the selected renderer.
CRC-based compile-time string identifier.
Definition StringId.hpp:31
3D vector class.
Definition Vector3.hpp:32
4D vector class.
Definition Vector4.hpp:31
const Material & GetYGridMaterial() const
Get the Y-axis grid material.
~WorldEditor() final
Destructor.
const Pipeline & GetGridPipeline() const
Get the grid rendering pipeline.
int GetStringIdMetaType() const
Get the Qt meta-type ID for StringId.
int GetStringMetaType() const
Get the Qt meta-type ID for std::string.
void DetachWindowFromRenderer(void *aWindow)
Detach a native window from the renderer.
const Material & GetSolidColorMaterial() const
Get the solid color material.
void AttachWindowToRenderer(void *aWindow)
Attach a native window to the renderer.
const Mesh & GetAABBWireMesh() const
Get the axis-aligned bounding box wireframe mesh.
WorldEditor(int &argc, char *argv[])
Construct the world editor application.
const Mesh & GetGridMesh() const
Get the grid mesh.
Renderer * GetRenderer()
Get the current renderer.
int GetPathMetaType() const
Get the Qt meta-type ID for std::filesystem::path.
const Pipeline & GetSolidColorPipeline() const
Get the solid color rendering pipeline.
const Material & GetXGridMaterial() const
Get the X-axis grid material.
<- This is here just for the literals
Definition AABB.hpp:31
DLL std::unique_ptr< Renderer > ConstructRenderer(uint32_t aIdentifier, void *aWindow)
Constructs a Renderer identified by a numeric identifier.
DLL void EnumerateRendererConstructors(const std::function< bool(const StringId &) > &aEnumerator)
Enumerates Renderer loader identifiers via an enumerator functor.
STL namespace.