Aeon Engine c550894
AeonGames Open Source Game Engine
Loading...
Searching...
No Matches
AeonEngine.cpp
1/*
2Copyright (C) 2016,2018-2022,2025,2026 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
8 http://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
17#include <iostream>
18#include <memory>
19#include <stdexcept>
21#ifdef _MSC_VER
22#pragma warning( push )
23#pragma warning( disable : PROTOBUF_WARNINGS )
24#endif
25#include <google/protobuf/stubs/common.h>
26#include "configuration.pb.h"
27#ifdef _MSC_VER
28#pragma warning( pop )
29#endif
30#include "aeongames/ProtoBufHelpers.hpp"
31#include "aeongames/Plugin.hpp"
32#include "aeongames/Node.hpp"
33#include "aeongames/AeonEngine.hpp"
34#include "aeongames/Renderer.hpp"
35#include "aeongames/Buffer.hpp"
36#include "aeongames/Texture.hpp"
37#include "aeongames/Mesh.hpp"
38#include "aeongames/Material.hpp"
39#include "aeongames/Pipeline.hpp"
40#include "aeongames/Model.hpp"
41#include "aeongames/Skeleton.hpp"
42#include "aeongames/Animation.hpp"
43#include "aeongames/Package.hpp"
44#include "aeongames/ResourceFactory.hpp"
46#include "aeongames/Utilities.hpp"
47#include "aeongames/Resource.hpp"
48#include "Factory.h"
49#ifdef __unix__
50#include <X11/Xlib.h>
51#include <X11/X.h>
52#endif
53#ifdef _WIN32
54extern "C" {
55 __declspec ( dllexport ) DWORD NvOptimusEnablement{1};
56 __declspec ( dllexport ) int AmdPowerXpressRequestHighPerformance{1};
57}
58#endif
59
60namespace AeonGames
61{
62 static bool gInitialized = false;
63 static ConfigurationMsg gConfigurationMsg;
64#if defined(WIN32)
65 static std::vector<std::tuple<HMODULE, PluginModuleInterface* >> gPlugInCache;
66#else
67 static std::vector<std::tuple<void*, PluginModuleInterface* >> gPlugInCache;
68#endif
69 static std::string gPlugInPath ( std::getenv ( "PATH" ) ? std::getenv ( "PATH" ) : "" );
70 static void LoadPlugin ( const std::string& aDir, const std::string& aFilename )
71 {
72 std::cout << LogLevel::Info << "Plugin: " << aFilename << std::endl;
73#if (defined WIN32)
74 HMODULE plugin = LoadLibraryEx ( aFilename.c_str(), nullptr, 0 );
75 if ( nullptr == plugin )
76 {
77 std::cout << LogLevel::Error << "Failed to load " << aFilename << " Error " << GetLastError() << std::endl;
78 return;
79 }
80 auto* pmi = ( PluginModuleInterface* ) GetProcAddress ( ( HINSTANCE ) plugin, "PMI" );
81 if ( nullptr == pmi )
82 {
83 std::cout << LogLevel::Warning << aFilename << " is not an AeonEngine Plugin." << std::endl;
84 FreeLibrary ( ( HINSTANCE ) plugin );
85 return;
86 }
87#else
88#if defined(__APPLE__)
89#define SO_SUFFIX ".dylib"
90#else
91#define SO_SUFFIX ".so"
92#endif
93 void* plugin;
94 if ( ! ( plugin = dlopen ( aFilename.c_str(), RTLD_NOW | RTLD_GLOBAL ) ) )
95 {
96 if ( ! ( plugin = dlopen ( ( "lib" + aFilename + SO_SUFFIX ).c_str(), RTLD_NOW | RTLD_GLOBAL ) ) )
97 {
98 std::cout << LogLevel::Error << "Failed to load " << aFilename << std::endl;
99 std::cout << LogLevel::Error << "Error " << dlerror() << std::endl;
100 return;
101 }
102 }
103 PluginModuleInterface* pmi = ( PluginModuleInterface* ) dlsym ( plugin, "PMI" );
104 if ( nullptr == pmi )
105 {
106 std::cout << aFilename << " is not an AeonEngine Plugin." << std::endl;
107 dlclose ( plugin );
108 return;
109 }
110#endif
111 if ( pmi->StartUp() )
112 {
113 gPlugInCache.emplace_back ( plugin, pmi );
114 }
115 else
116 {
117#if (defined WIN32)
118 FreeLibrary ( plugin );
119 if ( !FreeLibrary ( ( HINSTANCE ) plugin ) )
120 {
121 std::cout << "FreeLibrary Failed: " << GetLastError() << std::endl;
122 return;
123 }
124#else
125 if ( dlclose ( plugin ) != 0 )
126 {
127 std::cout << dlerror() << std::endl;
128 return;
129 }
130#endif
131 }
132 }
133
134 static std::string gConfigFile{"game/config"};
136 const std::array<OptionHandler, 1> gOptionHandlers
137 {
139 'c',
140 "config",
141 [] ( const char* aArgument, void* aUserData ) -> void {
142 if ( aArgument )
143 {
144 std::cout << LogLevel::Info << "Reading Configuration from " << aArgument << std::endl;
145 gConfigFile = aArgument;
146 }}
147 }
148 };
149
150 bool InitializeGlobalEnvironment ( int argc, char *argv[] )
151 {
152 if ( gInitialized )
153 {
154 return false;
155 }
156 gInitialized = true;
157 GOOGLE_PROTOBUF_VERIFY_VERSION;
158#if _WIN32
159 HANDLE hOut = GetStdHandle ( STD_OUTPUT_HANDLE );
160 DWORD dwMode = 0;
161 GetConsoleMode ( hOut, &dwMode );
162 dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
163 SetConsoleMode ( hOut, dwMode );
164#endif
165 ProcessOpts ( argc, argv, gOptionHandlers.data(), gOptionHandlers.size() );
166 try
167 {
168 LoadProtoBufObject<ConfigurationMsg> ( gConfigurationMsg, gConfigFile, "AEONCFG"_mgk );
169 }
170 catch ( const std::runtime_error& e )
171 {
172 std::cerr << LogLevel::Warning << e.what() << std::endl;
173 }
174
175 gPlugInCache.reserve ( gConfigurationMsg.plugin_size() );
176 for ( auto& i : gConfigurationMsg.plugin() )
177 {
178 LoadPlugin ( gConfigurationMsg.plugindirectory(), i );
179 }
180
181 if ( gConfigurationMsg.package().size() )
182 {
183 try
184 {
185 SetResourcePath ( {gConfigurationMsg.package().begin(), gConfigurationMsg.package().end() } );
186 }
187 catch ( const std::runtime_error& e )
188 {
189 std::cerr << e.what() << std::endl;
190 }
191 }
192
193 RegisterResourceConstructor ( "Model"_crc32,
194 [] ( uint32_t aPath )
195 {
196 auto model = std::make_unique<Model>();
197 model->LoadFromId ( aPath );
198 return model;
199 } );
200
201 RegisterResourceConstructor ( "Skeleton"_crc32,
202 [] ( uint32_t aPath )
203 {
204 auto skeleton = std::make_unique<Skeleton>();
205 skeleton->LoadFromId ( aPath );
206 return skeleton;
207 } );
208 RegisterResourceConstructor ( "Animation"_crc32,
209 [] ( uint32_t aPath )
210 {
211 auto animation = std::make_unique<Animation>();
212 animation->LoadFromId ( aPath );
213 return animation;
214 } );
215
216 RegisterResourceConstructor ( "Texture"_crc32,
217 [] ( uint32_t aPath )
218 {
219 auto texture = std::make_unique<Texture>();
220 texture->LoadFromId ( aPath );
221 return texture;
222 } );
223
224 RegisterResourceConstructor ( "Mesh"_crc32,
225 [] ( uint32_t aPath )
226 {
227 auto mesh = std::make_unique<Mesh>();
228 mesh->LoadFromId ( aPath );
229 return mesh;
230 } );
231
232 RegisterResourceConstructor ( "Pipeline"_crc32,
233 [] ( uint32_t aPath )
234 {
235 auto pipeline = std::make_unique<Pipeline>();
236 pipeline->LoadFromId ( aPath );
237 return pipeline;
238 } );
239
240 RegisterResourceConstructor ( "Material"_crc32,
241 [] ( uint32_t aPath )
242 {
243 auto material = std::make_unique<Material>();
244 material->LoadFromId ( aPath );
245 return material;
246 } );
247
248 return gInitialized;
249 }
250
252 {
253 if ( !gInitialized )
254 {
255 return;
256 }
258 // Register default resource constructors related to renderer
259 UnregisterResourceConstructor ( "Texture"_crc32 );
260 UnregisterResourceConstructor ( "Mesh"_crc32 );
261 UnregisterResourceConstructor ( "Pipeline"_crc32 );
262 UnregisterResourceConstructor ( "Material"_crc32 );
263 UnregisterResourceConstructor ( "Animation"_crc32 );
264 UnregisterResourceConstructor ( "Skeleton"_crc32 );
265 UnregisterResourceConstructor ( "Model"_crc32 );
266 for ( auto& i : gPlugInCache )
267 {
268 std::get<1> ( i )->ShutDown();
269#if (defined WIN32)
270 FreeLibrary ( std::get<0> ( i ) );
271#else
272 dlclose ( std::get<0> ( i ) );
273#endif
274 }
275#if defined(__linux__) && GOOGLE_PROTOBUF_VERSION > 3006001
276 // protobuf 3.6.1 on Linux has a bug in the Shutdown code
277 google::protobuf::ShutdownProtobufLibrary();
278#endif
279 gInitialized = false;
280 }
281
282 static std::vector<Package> gResourcePath{};
283 std::vector<std::string> GetResourcePath()
284 {
285 std::vector<std::string> path;
286 path.reserve ( gResourcePath.size() );
287 for ( auto& i : gResourcePath )
288 {
289 path.emplace_back ( i.GetPath().string() );
290 }
291 return path;
292 }
293 void SetResourcePath ( const std::vector<std::string>& aPath )
294 {
295 gResourcePath.clear();
296 gResourcePath.reserve ( aPath.size() );
297 std::ostringstream stream;
298 for ( auto& i : aPath )
299 {
300 try
301 {
302 gResourcePath.emplace_back ( i );
303 }
304 catch ( const std::runtime_error& e )
305 {
306 stream << e.what() << std::endl;
307 }
308 catch ( ... )
309 {
310 throw;
311 }
312 }
313 if ( stream.rdbuf()->in_avail() > 0 )
314 {
315 std::cout << LogLevel::Error << stream.str() << std::endl;
316 throw std::runtime_error ( stream.str().c_str() );
317 }
318 }
319
320 size_t GetResourceSize ( uint32_t crc )
321 {
322 for ( auto &i : gResourcePath )
323 {
324 auto resource = i.GetIndexTable().find ( crc );
325 if ( resource != i.GetIndexTable().end() )
326 {
327 return i.GetFileSize ( crc );
328 }
329 }
330 return 0;
331 }
332
333 std::string GetResourcePath ( uint32_t crc )
334 {
335 for ( auto &i : gResourcePath )
336 {
337 auto resource = i.GetIndexTable().find ( crc );
338 if ( resource != i.GetIndexTable().end() )
339 {
340 return resource->second;
341 }
342 }
343 return std::string{};
344 }
345
346 size_t GetResourceSize ( const std::string& aFileName )
347 {
348 return GetResourceSize ( crc32i ( aFileName.data(), aFileName.size() ) );
349 }
350 void LoadResource ( uint32_t crc, void* buffer, size_t buffer_size )
351 {
352 for ( auto &i : gResourcePath )
353 {
354 auto resource = i.GetIndexTable().find ( crc );
355 if ( resource != i.GetIndexTable().end() )
356 {
357 i.LoadFile ( crc, buffer, buffer_size );
358 return;
359 }
360 }
361 std::cout << LogLevel::Error << "Resource not found." << std::endl;
362 throw std::runtime_error ( "Resource not found." );
363 }
364 void LoadResource ( const std::string& aFileName, void* buffer, size_t buffer_size )
365 {
366 LoadResource ( crc32i ( aFileName.data(), aFileName.size() ), buffer, buffer_size );
367 }
368}
Defines log severity levels and stream output for the AeonGames engine.
Header for the PKG file specification.
Defines the plugin module interface for dynamically loaded plugins.
Provides the DLL_PROTOBUF export/import macro for protobuf wrapper classes.
Command-line option handler.
<- This is here just for the literals
Definition AABB.hpp:31
DLL void ProcessOpts(int argc, char *argv[], const OptionHandler *aOptionHandler, size_t aOptionHandlerCount)
Process command-line options.
Definition Utilities.cpp:67
DLL std::vector< std::string > GetResourcePath()
Get the list of resource search paths.
DLL size_t GetResourceSize(uint32_t crc)
uint32_t crc32i(const char *message, size_t size, uint32_t previous_crc)
Compute the CRC32 of a given message, continuing from a previous CRC value.
Definition CRC.cpp:27
DLL bool InitializeGlobalEnvironment(int argc=0, char *argv[]=nullptr)
Initialize the global engine environment.
DLL bool UnregisterResourceConstructor(uint32_t aType)
Unregister a resource constructor.
DLL void LoadResource(uint32_t crc, void *buffer, size_t buffer_size)
@ Warning
Potential issues that may need attention.
Definition LogLevel.hpp:32
@ Info
General informational messages.
Definition LogLevel.hpp:30
@ Error
Error conditions.
Definition LogLevel.hpp:33
DLL void FinalizeGlobalEnvironment()
Shut down the global engine environment and release resources.
DLL void ClearAllResources()
Remove all resources from the cache.
DLL void SetResourcePath(const std::vector< std::string > &aPath)
Set the list of resource search paths.
DLL bool RegisterResourceConstructor(uint32_t aType, const std::function< UniqueAnyPtr(uint32_t) > &aConstructor, UniqueAnyPtr &&aDefaultResource=nullptr)
Register a constructor for a resource type.
const std::array< OptionHandler, 1 > gOptionHandlers
Array of command-line option handlers.
void LoadProtoBufObject(T &t, const void *aData, size_t aSize, uint64_t aMagick)
Loads a Protocol Buffer Object from a meory buffer into the provided reference.
StartUpPtr StartUp
Called to initialize the plugin.
Definition Plugin.hpp:38