Leviathan  0.8.0.0
Leviathan game engine
Graphics.cpp
Go to the documentation of this file.
1 // ------------------------------------ //
2 #include "Graphics.h"
3 
7 #include "Engine.h"
8 #include "FileSystem.h"
9 #include "GUIOverlayRenderer.h"
10 #include "GeometryHelpers.h"
13 #include "Window.h"
14 
15 #include "BsApplication.h"
16 #include "Components/BsCCamera.h"
17 #include "Scene/BsSceneObject.h"
18 
19 #include "bsfCore/Animation/BsAnimationClip.h"
20 #include "bsfCore/Material/BsShaderManager.h"
21 
22 // Temporary BSF includes before the application has a light-weigth alternative init
23 #include "Animation/BsAnimationManager.h"
24 #include "Audio/BsAudio.h"
25 #include "Audio/BsAudioManager.h"
26 #include "CoreThread/BsCoreObjectManager.h"
27 #include "CoreThread/BsCoreThread.h"
28 #include "Importer/BsImporter.h"
29 #include "Localization/BsStringTableManager.h"
30 #include "Managers/BsGpuProgramManager.h"
31 #include "Managers/BsMeshManager.h"
32 #include "Managers/BsQueryManager.h"
33 #include "Managers/BsRenderStateManager.h"
34 #include "Managers/BsRenderWindowManager.h"
35 #include "Managers/BsResourceListenerManager.h"
36 #include "Material/BsShaderManager.h"
37 #include "Math/BsVector2.h"
38 #include "Particles/BsParticleManager.h"
39 #include "Particles/BsVectorField.h"
40 #include "Physics/BsPhysics.h"
41 #include "Physics/BsPhysicsManager.h"
42 #include "Platform/BsPlatform.h"
43 #include "Profiling/BsProfilerCPU.h"
44 #include "Profiling/BsProfilerGPU.h"
45 #include "Profiling/BsProfilingManager.h"
46 #include "Profiling/BsRenderStats.h"
47 #include "RenderAPI/BsRenderWindow.h"
48 #include "Renderer/BsParamBlocks.h"
49 #include "Renderer/BsRenderer.h"
50 #include "Renderer/BsRendererManager.h"
51 #include "Resources/BsResources.h"
52 #include "Scene/BsGameObjectManager.h"
53 #include "Scene/BsSceneManager.h"
54 #include "Scene/BsSceneObject.h"
55 #include "Threading/BsTaskScheduler.h"
56 #include "Threading/BsThreadPool.h"
57 #include "Utility/BsDeferredCallManager.h"
58 #include "Utility/BsDynLib.h"
59 #include "Utility/BsDynLibManager.h"
60 #include "Utility/BsMessageHandler.h"
61 #include "Utility/BsTime.h"
62 #include "bsfCore/Managers/BsRenderAPIManager.h"
63 
64 // BsApplication
65 #include "2D/BsSpriteManager.h"
66 #include "BsEngineConfig.h"
67 #include "CoreThread/BsCoreObjectManager.h"
68 #include "CoreThread/BsCoreThread.h"
69 #include "Debug/BsDebugDraw.h"
70 #include "FileSystem/BsFileSystem.h"
71 #include "GUI/BsGUIManager.h"
72 #include "GUI/BsProfilerOverlay.h"
73 #include "GUI/BsShortcutManager.h"
74 #include "Importer/BsImporter.h"
75 #include "Input/BsVirtualInput.h"
76 #include "Platform/BsCursor.h"
77 #include "Platform/BsPlatform.h"
78 #include "Profiling/BsProfilingManager.h"
79 #include "Renderer/BsRendererManager.h"
80 #include "Renderer/BsRendererMaterialManager.h"
81 #include "Resources/BsBuiltinResources.h"
82 #include "Resources/BsEngineShaderIncludeHandler.h"
83 #include "Resources/BsPlainTextImporter.h"
84 #include "Resources/BsResources.h"
85 #include "Scene/BsSceneManager.h"
86 #include "Scene/BsSceneObject.h"
87 #include "Script/BsScriptManager.h"
88 
89 
90 
91 #include <SDL.h>
92 #include <SDL_syswm.h>
93 
94 #include <future>
95 #include <regex>
96 
97 #ifdef __linux
98 #include "XLibInclude.h"
99 #endif
100 
101 
102 using namespace Leviathan;
103 // ------------------------------------ //
104 
105 class LeviathanBSFShaderIncludeHandler : public bs::EngineShaderIncludeHandler {
106 public:
107  virtual bs::HShaderInclude findInclude(const bs::String& name) const override
108  {
109  // If the file path is valid just pass it as is
110  const std::string converted(name.c_str(), name.size());
111  if(FileSystem::FileExists(converted))
112  return bs::EngineShaderIncludeHandler::findInclude(name);
113 
114  // We resolve the path and then give it to bsf
115  std::string searched = FileSystem::Get()->SearchForFile(FILEGROUP_SCRIPT,
116  StringOperations::RemoveExtension<std::string>(converted),
117  StringOperations::GetExtension<std::string>(converted), true);
118 
119  if(searched.empty()) {
120  if(name.find("$ENGINE$") == bs::String::npos) {
121  LOG_WARNING(
122  "LeviathanBSFShaderIncludeHandler: could not locate file anywhere: " +
123  converted);
124  }
125 
126  return bs::EngineShaderIncludeHandler::findInclude(name);
127  }
128 
129  return bs::EngineShaderIncludeHandler::findInclude(
130  bs::String(searched.c_str(), searched.size()));
131  }
132 };
133 
134 class LeviathanBSFApplication : public bs::CoreApplication {
135 public:
136  LeviathanBSFApplication(const bs::START_UP_DESC& desc) : bs::CoreApplication(desc) {}
137 
138  bs::SPtr<bs::IShaderIncludeHandler> getShaderIncludeHandler() const override
139  {
140  return bs::bs_shared_ptr_new<LeviathanBSFShaderIncludeHandler>();
141  }
142 
143  // Code from BsCoreApplication.cpp
144  // These are duplicated here due to a bunch of things being private
146  {
147  {
148  Lock lock(mFrameRenderingFinishedMutex);
149 
150  while(!mIsFrameRenderingFinished) {
151  bs::TaskScheduler::instance().addWorker();
152  mFrameRenderingFinishedCondition.wait(lock);
153  bs::TaskScheduler::instance().removeWorker();
154  }
155  }
156  }
157 
159  {
160  bs::Lock lock(mFrameRenderingFinishedMutex);
161 
162  while(!mIsFrameRenderingFinished) {
163  bs::TaskScheduler::instance().addWorker();
164  mFrameRenderingFinishedCondition.wait(lock);
165  bs::TaskScheduler::instance().removeWorker();
166  }
167 
168  mIsFrameRenderingFinished = false;
169  }
170 
172  {
173  bs::Lock lock(mFrameRenderingFinishedMutex);
174 
175  mIsFrameRenderingFinished = true;
176  mFrameRenderingFinishedCondition.notify_one();
177  }
178 
179  // These are private forcing to duplicate these here
181  {
182 #if !BS_FORCE_SINGLETHREADED_RENDERING
183  bs::gProfilerCPU().beginThread("Core");
184 #endif
185  }
186 
188  {
189  bs::ProfilerGPU::instance()._update();
190 
191 #if !BS_FORCE_SINGLETHREADED_RENDERING
192  bs::gProfilerCPU().endThread();
193  bs::gProfiler()._updateCore();
194 #endif
195  }
196 
197  void startUpRenderer() override
198  {
199  // Do nothing, we activate the renderer at a later stage
200  }
201 
202 
203 
204  bs::SPtr<GUIOverlayRenderer> GUIRenderer;
205 };
206 
207 
209 
210  Private(const bs::START_UP_DESC& desc) : Description(desc) {}
211 
212  bs::START_UP_DESC Description;
214 };
215 
216 #ifdef __linux
217 bool HasX11Error = false;
218 
219 int LeviathanX11ErrorHandler(Display* display, XErrorEvent* event)
220 {
221  std::stringstream str;
222  str << "X error received: "
223  << "type " << event->type << ", "
224  << "serial " << event->serial << ", "
225  << "error_code " << static_cast<int>(event->error_code) << ", "
226  << "request_code " << static_cast<int>(event->request_code) << ", "
227  << "minor_code " << static_cast<int>(event->minor_code);
228 
229  LOG_ERROR(str.str());
230  HasX11Error = true;
231  return 0;
232 }
233 #endif
234 
236 
238 {
239  LEVIATHAN_ASSERT(!Initialized, "Graphics not released before destructor");
240 }
241 // ------------------------------------------- //
242 bool Graphics::Init(AppDef* appdef)
243 {
244  // StartUp SDL //
245  if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) != 0) {
246 
247  LOG_ERROR("Graphics: Init: SDL init failed, error: " + std::string(SDL_GetError()));
248  return false;
249  }
250 
251  SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
252 
253  int displays = SDL_GetNumVideoDisplays();
254 
255  LOG_INFO("SDL: display count: " + Convert::ToString(displays));
256 
257  // Get display positions
258  std::vector<SDL_Rect> displayBounds;
259 
260  for(int i = 0; i < displays; i++) {
261 
262  displayBounds.push_back(SDL_Rect());
263 
264  SDL_GetDisplayBounds(i, &displayBounds.back());
265 
266  const char* nameptr = SDL_GetDisplayName(i);
267 
268  const auto name = nameptr ? std::string(nameptr) : std::string("unnamed");
269 
270  // Video modes //
271  int videomodecount = SDL_GetNumDisplayModes(i);
272 
273  std::vector<std::string> videomodes;
274 
275  for(int a = 0; a < videomodecount; a++) {
276 
277 
278  SDL_DisplayMode mode = {SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0};
279 
280  if(SDL_GetDisplayMode(i, a, &mode) == 0) {
281 
282  videomodes.push_back(Convert::ToString(SDL_BITSPERPIXEL(mode.format)) +
283  " bpp " + Convert::ToString(mode.w) + "x" +
284  Convert::ToString(mode.h) + " at " +
285  Convert::ToString(mode.refresh_rate) + "Hz");
286  }
287  }
288 
289 
290  LOG_INFO("Display(" + Convert::ToString(i) + ", " + name + "): top left: (" +
291  Convert::ToString(displayBounds.back().x) + ", " +
292  Convert::ToString(displayBounds.back().y) +
293  ") size: " + Convert::ToString(displayBounds.back().w) + "x" +
294  Convert::ToString(displayBounds.back().h));
295 
296  // LOG_INFO("Supported modes(" + Convert::ToString(videomodes.size()) + "): ");
297  // for(const auto& mode : videomodes){
298 
299  // LOG_WRITE(" " + mode);
300  // }
301  }
302 
303 
304  if(!InitializeBSF(appdef)) {
305 
306  Logger::Get()->Error("Graphics: Init: failed to create bs::framework renderer");
307  return false;
308  }
309 
310 #ifdef __linux
311  // Set X11 error handler to not crash on non-fatal errors
312  XSetErrorHandler(LeviathanX11ErrorHandler);
313 #endif
314 
315  Initialized = true;
316  return true;
317 }
318 
320 {
321  if(Initialized) {
322 
323  ShutdownBSF();
324 
325  SDL_Quit();
326  }
327 
328  Initialized = false;
329  FirstWindowCreated = false;
330  Pimpl.reset();
331 }
332 // ------------------------------------------- //
333 bool Graphics::InitializeBSF(AppDef* appdef)
334 {
335  // Create render API settings
336  bs::START_UP_DESC desc;
337  desc.input = "bsfNullInput";
338  desc.audio = "bsfNullAudio";
339  desc.physics = "bsfNullPhysics";
340  desc.renderer = "bsfRenderBeast";
341  desc.physicsCooking = false;
342 
343  desc.importers.push_back("bsfFreeImgImporter");
344  desc.importers.push_back("bsfFBXImporter");
345  desc.importers.push_back("bsfFontImporter");
346  desc.importers.push_back("bsfSL");
347 
348 #ifdef _WIN32
349  const auto defaultRenderer = "DirectX";
350 #elif defined(__linux__)
351  const auto defaultRenderer = "OpenGL";
352 #else
353  const auto defaultRenderer = "Vulkan";
354 #endif
355 
356  std::string renderAPI;
357  ObjectFileProcessor::LoadValueFromNamedVars<std::string>(
358  appdef->GetValues(), "RenderAPI", renderAPI, defaultRenderer);
359 
360  LOG_INFO("Graphics: preferred rendering API: '" + renderAPI + "'");
361 
362  LOG_WRITE("TODO: add detection if vulkan is available or not");
363 
364  const std::regex vulkan(
365  "Vulkan", std::regex_constants::ECMAScript | std::regex_constants::icase);
366  const std::regex opengl(
367  "OpenGL", std::regex_constants::ECMAScript | std::regex_constants::icase);
368 
369 #ifdef _WIN32
370  const std::regex directx(
371  "DirectX\\s*(11)?", std::regex_constants::ECMAScript | std::regex_constants::icase);
372 #endif //_WIN32
373 
374  if(std::regex_match(renderAPI, vulkan)) {
375  desc.renderAPI = "bsfVulkanRenderAPI";
376  } else if(std::regex_match(renderAPI, opengl)) {
377  desc.renderAPI = "bsfGLRenderAPI";
378  }
379 #ifdef _WIN32
380  else if(std::regex_match(renderAPI, directx)) {
381  desc.renderAPI = "bsfD3D11RenderAPI";
382  }
383 #endif //_WIN32
384  else {
385  LOG_ERROR("Graphics: unknown render API selected: " + renderAPI);
386  return false;
387  }
388 
389  Pimpl = std::make_unique<Private>(desc);
390 
391  return true;
392 }
393 
394 bs::SPtr<bs::RenderWindow> Graphics::RegisterCreatedWindow(Window& window)
395 {
396  if(FirstWindowCreated) {
397  // Register secondary window
398  // TODO: second window setup
399  DEBUG_BREAK;
400  return nullptr;
401 
402  } else {
403  // Finish initializing graphics
404  FirstWindowCreated = true;
405  LOG_INFO("Graphics: doing bs::framework initialization after creating first window");
406 
407  // Setup first window properties
408  auto& windowDesc = Pimpl->Description.primaryWindowDesc;
409  windowDesc.depthBuffer = true;
410 
411  int multiSample;
412 
413  ObjectFileProcessor::LoadValueFromNamedVars<int>(
414  Engine::Get()->GetDefinition()->GetValues(), "WindowMultiSampleCount", multiSample,
415  1);
416 
417  windowDesc.multisampleCount = multiSample;
418  // windowDesc.multisampleHint = "";
419  // Not sure what all settings need to be copied
420  windowDesc.fullscreen = /* window.IsFullScreen() */ false;
421  windowDesc.vsync = false;
422 
423  // Fill video mode info from SDL
424  SDL_DisplayMode dm;
425  if(SDL_GetDesktopDisplayMode(0, &dm) != 0) {
426  LOG_ERROR("Graphics: RegisterCreatedWindow: failed to get desktop display mode:" +
427  std::string(SDL_GetError()));
428  return nullptr;
429  }
430 
431  int32_t width, height;
432  window.GetSize(width, height);
433  windowDesc.videoMode = bs::VideoMode(width, height, dm.refresh_rate, 0);
434 
435 #ifdef _WIN32
436  windowDesc.platformSpecific["externalWindowHandle"] =
437  std::to_string((uint64_t)window.GetNativeHandle());
438 #else
439  windowDesc.platformSpecific["externalWindowHandle"] =
440  std::to_string(window.GetNativeHandle());
441 
442  windowDesc.platformSpecific["externalDisplay"] =
443  std::to_string(window.GetWindowXDisplay());
444 #endif
445 
446  bs::CoreApplication::startUp<LeviathanBSFApplication>(Pimpl->Description);
447 
448  Pimpl->OurApp =
449  static_cast<LeviathanBSFApplication*>(bs::CoreApplication::instancePtr());
450 
451  bs::SPtr<bs::RenderWindow> bsWindow =
452  bs::CoreApplication::instance().getPrimaryWindow();
453 
454  LEVIATHAN_ASSERT(bsWindow, "window creation failed");
455 
456  // Code from BsApplication.cpp
457  using namespace bs;
458 
459  PlainTextImporter* importer = bs_new<PlainTextImporter>();
460  Importer::instance()._registerAssetImporter(importer);
461 
462  // VirtualInput::startUp();
463  BuiltinResources::startUp();
464  RendererMaterialManager::startUp();
465  RendererManager::instance().initialize();
466  SpriteManager::startUp();
467  // GUIManager::startUp();
468  // ShortcutManager::startUp();
469 
470  // bs::Cursor::startUp();
471  // bs::Cursor::instance().setCursor(CursorType::Arrow);
472  // Platform::setIcon(BuiltinResources::instance().getFrameworkIcon());
473 
474  SceneManager::instance().setMainRenderTarget(bsWindow);
475  DebugDraw::startUp();
476 
477  // startUpScriptManager();
478 
479 
480  // Notify engine to register threads to work with Ogre //
481  // Engine::GetEngine()->_NotifyThreadsRegisterOgre();
482 
483  auto shader =
484  bs::gImporter().import<bs::Shader>("Data/Shaders/CoreShaders/ScreenSpaceGUI.bsl");
485 
486  auto material = bs::Material::create(shader);
487 
488  Pimpl->OurApp->GUIRenderer =
489  RendererExtension::create<GUIOverlayRenderer>(GUIOverlayInitializationData{
490  GeometryHelpers::CreateScreenSpaceQuad(-1, -1, 2, 2)->getCore(),
491  material->getCore()});
492 
493  return bsWindow;
494  }
495 }
496 
497 void Graphics::ShutdownBSF()
498 {
499  if(Pimpl) {
500  Pimpl->OurApp->GUIRenderer = nullptr;
501  Pimpl->OurApp->WaitUntilLastFrame();
502  }
503 
504  // A bunch of code here is copy pasted from BsCoreApplication.cpp
505  using namespace bs;
506 
507  // This part is from BsApplication.cpp
508  // Need to clear all objects before I unload any plugins, as they
509  // could have allocated parts or all of those objects.
510  SceneManager::instance().clearScene(true);
511 
512  // Resources too (Prefabs especially, since they hold the same data as a scene)
513  Resources::instance().unloadAll();
514 
515  // Shut down before script manager as scripts could have registered shortcut callbacks
516  // ShortcutManager::shutDown();
517 
518  // ScriptManager::shutDown();
519  DebugDraw::shutDown();
520 
521  // Cleanup any new objects queued for destruction by unloaded scripts
522  CoreObjectManager::instance().syncToCore();
523  gCoreThread().update();
524  gCoreThread().submitAll(true);
525 
526  // bs::Cursor::shutDown();
527 
528  // GUIManager::shutDown();
529  SpriteManager::shutDown();
530  BuiltinResources::shutDown();
531  RendererMaterialManager::shutDown();
532  // VirtualInput::shutDown();
533 
534  bs::CoreApplication::shutDown();
535  Pimpl->OurApp = nullptr;
536 }
537 // ------------------------------------ //
539 {
540  // Logic for this frame is already ready, just tell bsf to render once
541 
542  // A bunch of code here is copy pasted from BsCoreApplication.cpp
543  using namespace bs;
544 
545  gProfilerCPU().beginThread("Sim");
546 
547  // This does unwanted things with X11
548  // Platform::_update();
549 
550  gTime()._update();
551  // gInput()._update();
552  // RenderWindowManager::update needs to happen after Input::update and before
553  // Input::_triggerCallbacks, so that all input is properly captured in case there is a
554  // focus change, and so that focus change is registered before input events are sent out
555  // (mouse press can result in code checking if a window is in focus, so it has to be up to
556  // date)
557  RenderWindowManager::instance()._update();
558  // gInput()._triggerCallbacks();
559  gDebug()._triggerCallbacks();
560 
561  // preUpdate();
562 
563  // Trigger fixed updates if required
564  {
565  UINT64 step;
566  const UINT32 numIterations = gTime()._getFixedUpdateStep(step);
567 
568  const float stepSeconds = step / 1000000.0f;
569  for(UINT32 i = 0; i < numIterations; i++) {
570  // fixedUpdate();
571  PROFILE_CALL(gSceneManager()._fixedUpdate(), "Scene fixed update");
572  // PROFILE_CALL(gPhysics().fixedUpdate(stepSeconds), "Physics simulation");
573 
574  gTime()._advanceFixedUpdate(step);
575  }
576  }
577 
578  PROFILE_CALL(gSceneManager()._update(), "Scene update");
579  // gAudio()._update();
580  // gPhysics().update();
581 
582  // Update plugins
583  // for(auto& pluginUpdateFunc : mPluginUpdateFunctions)
584  // pluginUpdateFunc.second();
585 
586  // postUpdate();
587 
588  PerFrameData perFrameData;
589 
590  // Evaluate animation after scene and plugin updates because the renderer will just now be
591  // displaying the animation we sent on the previous frame, and we want the scene
592  // information to match to what is displayed.
593  perFrameData.animation = AnimationManager::instance().update();
594  perFrameData.particles = ParticleManager::instance().update(*perFrameData.animation);
595 
596  // Send out resource events in case any were loaded/destroyed/modified
597  ResourceListenerManager::instance().update();
598 
599  // Trigger any renderer task callbacks (should be done before scene object update, or core
600  // sync, so objects have a chance to respond to the callback).
601  RendererManager::instance().getActive()->update();
602 
603  gSceneManager()._updateCoreObjectTransforms();
604  PROFILE_CALL(RendererManager::instance().getActive()->renderAll(perFrameData), "Render");
605 
606  // Core and sim thread run in lockstep. This will result in a larger input latency than if
607  // I was running just a single thread. Latency becomes worse if the core thread takes
608  // longer than sim thread, in which case sim thread needs to wait. Optimal solution would
609  // be to get an average difference between sim/core thread and start the sim thread a bit
610  // later so they finish at nearly the same time.
611  Pimpl->OurApp->WaitBeforeStartNextFrame();
612 
613  gCoreThread().queueCommand(
614  std::bind(&LeviathanBSFApplication::beginCoreProfiling, Pimpl->OurApp),
615  CTQF_InternalQueue);
616  gCoreThread().queueCommand(&Platform::_coreUpdate, CTQF_InternalQueue);
617  gCoreThread().queueCommand(
618  std::bind(&ct::RenderWindowManager::_update, ct::RenderWindowManager::instancePtr()),
619  CTQF_InternalQueue);
620 
621  gCoreThread().update();
622  gCoreThread().submitAll();
623 
624  gCoreThread().queueCommand(
626  CTQF_InternalQueue);
627 
628  gCoreThread().queueCommand(
629  std::bind(&ct::QueryManager::_update, ct::QueryManager::instancePtr()),
630  CTQF_InternalQueue);
631  gCoreThread().queueCommand(
632  std::bind(&LeviathanBSFApplication::endCoreProfiling, Pimpl->OurApp),
633  CTQF_InternalQueue);
634 
635  gProfilerCPU().endThread();
636  gProfiler()._update();
637 
638  // At this point I think it is possible that a rendering operation is going on in the
639  // background, but hopefully it is safe to execute game logic
640  return true;
641 }
642 // ------------------------------------ //
644  const std::vector<bs::SPtr<bs::Texture>>& overlays)
645 {
646  std::vector<bs::SPtr<bs::ct::Texture>> coreVersion;
647  coreVersion.reserve(overlays.size());
648 
649  std::transform(overlays.begin(), overlays.end(), std::back_inserter(coreVersion),
650  [](const bs::SPtr<bs::Texture>& item) { return item->getCore(); });
651 
652  std::weak_ptr<GUIOverlayRenderer> rendererExtension = Pimpl->OurApp->GUIRenderer;
653 
654  bs::gCoreThread().queueCommand(
655  [rendererExtension, coreVersion = std::move(coreVersion)]() {
656  const auto locked = rendererExtension.lock();
657  if(locked)
658  locked->UpdateShownOverlays(coreVersion);
659  });
660 }
661 
663 {
664  const auto capabilities = bs::ct::RenderAPI::instance().getCapabilities(0);
665 
666  return capabilities.conventions.ndcYAxis != bs::Conventions::Axis::Down;
667 }
668 // ------------------------------------ //
669 // Resource loading helpers
670 
671 DLLEXPORT bs::HShader Graphics::LoadShaderByName(const std::string& name)
672 {
673  // TODO: .asset detection
674 
676  // Leviathan::StringOperations::RemoveExtension(name, true),
678  // Leviathan::StringOperations::GetExtension(name)
679  "asset");
680 
681  if(file.empty()) {
682  LOG_ERROR("Graphics: LoadShaderByName: could not find resource with name: " + name);
683  return nullptr;
684  }
685 
686  // bs::HShader shader = bs::gImporter().import<bs::Shader>(file.c_str());
687  bs::HShader shader = bs::gResources().load<bs::Shader>(file.c_str());
688 
689  if(!shader) {
690  LOG_ERROR("Graphics: loading asset failed: " + name);
691  }
692 
693  return shader;
694 }
695 
696 DLLEXPORT bs::HTexture Graphics::LoadTextureByName(const std::string& name)
697 {
699  // Leviathan::StringOperations::RemoveExtension(name, true),
701  // Leviathan::StringOperations::GetExtension(name)
702  "asset");
703 
704  if(file.empty()) {
705  LOG_ERROR("Graphics: LoadTextureByName: could not find resource with name: " + name);
706  return nullptr;
707  }
708 
709  // bs::HTexture texture = bs::gImporter().import<bs::Texture>(file.c_str());
710  bs::HTexture texture = bs::gResources().load<bs::Texture>(file.c_str());
711 
712  if(!texture) {
713  LOG_ERROR("Graphics: loading asset failed: " + name);
714  }
715 
716  return texture;
717 }
718 
719 DLLEXPORT bs::HMesh Graphics::LoadMeshByName(const std::string& name)
720 {
722  // Leviathan::StringOperations::RemoveExtension(name, true),
724  // Leviathan::StringOperations::GetExtension(name)
725  "asset");
726 
727  if(file.empty()) {
728  LOG_ERROR("Graphics: LoadMeshByName: could not find resource with name: " + name);
729  return nullptr;
730  }
731 
732  // bs::HMesh mesh = bs::gImporter().import<bs::HMesh>(file.c_str());
733  bs::HMesh mesh = bs::gResources().load<bs::Mesh>(file.c_str());
734 
735  if(!mesh) {
736  LOG_ERROR("Graphics: loading asset failed: " + name);
737  }
738 
739  return mesh;
740 }
741 
742 DLLEXPORT bs::HAnimationClip Graphics::LoadAnimationClipByName(const std::string& name)
743 {
745  // Leviathan::StringOperations::RemoveExtension(name, true),
747  // Leviathan::StringOperations::GetExtension(name)
748  "asset");
749 
750  if(file.empty()) {
751  LOG_ERROR(
752  "Graphics: LoadAnimationClipByName: could not find resource with name: " + name);
753  return nullptr;
754  }
755 
756  // bs::HMesh mesh = bs::gImporter().import<bs::HMesh>(file.c_str());
757  bs::HAnimationClip animationClip = bs::gResources().load<bs::AnimationClip>(file.c_str());
758 
759  if(!animationClip) {
760  LOG_ERROR("Graphics: loading asset failed: " + name);
761  }
762 
763  return animationClip;
764 }
765 
766 // ------------------------------------ //
767 // X11 errors
768 #ifdef __linux
769 DLLEXPORT bool Graphics::HasX11ErrorOccured()
770 {
771  if(HasX11Error) {
772  HasX11Error = false;
773  return true;
774  }
775 
776  return false;
777 }
778 #endif
LeviathanBSFApplication(const bs::START_UP_DESC &desc)
Definition: Graphics.cpp:136
static DLLEXPORT bs::HMesh CreateScreenSpaceQuad(float x, float y, float width, float height, bool autoflipUV=true)
Creates a screen space plane with UV coordinates.
DLLEXPORT unsigned long GetNativeHandle() const
Definition: Window.cpp:915
DLLEXPORT bool Init(AppDef *appdef)
Definition: Graphics.cpp:242
DLLEXPORT bs::HMesh LoadMeshByName(const std::string &name)
Works the same as LoadShaderByName.
Definition: Graphics.cpp:719
static const StringTypeN RemovePath(const StringTypeN &filepath)
DLLEXPORT void GetSize(int32_t &width, int32_t &height) const
Definition: Window.cpp:894
#define LOG_INFO(x)
Definition: Define.h:88
bs::SPtr< bs::RenderWindow > RegisterCreatedWindow(Window &window)
Called when Window objects are created to register them with bsf and with the case of the first windo...
Definition: Graphics.cpp:394
#define LOG_ERROR(x)
Definition: Define.h:90
LeviathanBSFApplication * OurApp
Definition: Graphics.cpp:213
DLLEXPORT bool IsVerticalUVFlipped() const
Definition: Graphics.cpp:662
DLLEXPORT ~Graphics()
Definition: Graphics.cpp:237
DLLEXPORT bs::HTexture LoadTextureByName(const std::string &name)
Works the same as LoadShaderByName.
Definition: Graphics.cpp:696
#define LOG_WARNING(x)
Definition: Define.h:89
DLLEXPORT bs::HAnimationClip LoadAnimationClipByName(const std::string &name)
Works the same as LoadShaderByName.
Definition: Graphics.cpp:742
DLLEXPORT bool Frame()
Definition: Graphics.cpp:538
bs::START_UP_DESC Description
Definition: Graphics.cpp:212
void frameRenderingFinishedCallback()
Definition: Graphics.cpp:171
DLLEXPORT Graphics()
Definition: Graphics.cpp:235
DLLEXPORT NamedVars * GetValues()
Definition: AppDefine.cpp:40
DLLEXPORT bs::HShader LoadShaderByName(const std::string &name)
Finds and loads a shader with the name.
Definition: Graphics.cpp:671
#define LOG_WRITE(x)
Definition: Define.h:91
Definition: SFMLPackets.h:18
static DLLEXPORT FileSystem * Get()
Definition: FileSystem.cpp:74
#define LEVIATHAN_ASSERT(x, msg)
Definition: Define.h:98
bs::SPtr< bs::IShaderIncludeHandler > getShaderIncludeHandler() const override
Definition: Graphics.cpp:138
static std::string ToString(const T &val)
Definition: Convert.h:72
DLLEXPORT void UpdateShownOverlays(const std::vector< bs::SPtr< bs::Texture >> &overlays)
Definition: Graphics.cpp:643
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
bs::SPtr< GUIOverlayRenderer > GUIRenderer
Definition: Graphics.cpp:204
static DLLEXPORT bool FileExists(const std::string &name)
Definition: FileSystem.cpp:451
AppDef * GetDefinition()
Definition: Engine.h:205
DLLEXPORT std::string SearchForFile(FILEGROUP which, const std::string &name, const std::string &extensions, bool searchall=true)
Searches for a file.
Definition: FileSystem.cpp:666
virtual bs::HShaderInclude findInclude(const bs::String &name) const override
Definition: Graphics.cpp:107
#define DLLEXPORT
Definition: Include.h:84
Private(const bs::START_UP_DESC &desc)
Definition: Graphics.cpp:210
static DLLEXPORT Engine * Get()
Definition: Engine.cpp:85
DLLEXPORT void Release()
Definition: Graphics.cpp:319
The access mask controls which registered functions and classes a script sees.
Definition: GameModule.h:12
DLLEXPORT void Error(const std::string &data) override
Definition: Logger.cpp:177
void startUpRenderer() override
Definition: Graphics.cpp:197
std::unique_lock< std::mutex > Lock
Definition: ThreadSafe.h:18