bool Engine::Initialize(const VariantMap& parameters) { if (initialized_) return true; PROFILE(InitEngine); // Set headless mode headless_ = GetParameter(parameters, "Headless", false).GetBool(); // Register the rest of the subsystems if (!headless_) { context_->RegisterSubsystem(new Graphics(context_)); context_->RegisterSubsystem(new Renderer(context_)); } else { // Register graphics library objects explicitly in headless mode to allow them to work without using actual GPU resources RegisterGraphicsLibrary(context_); } // In debug mode, check now that all factory created objects can be created without crashing #ifdef _DEBUG const HashMap<ShortStringHash, SharedPtr<ObjectFactory> >& factories = context_->GetObjectFactories(); for (HashMap<ShortStringHash, SharedPtr<ObjectFactory> >::ConstIterator i = factories.Begin(); i != factories.End(); ++i) SharedPtr<Object> object = i->second_->CreateObject(); #endif // Start logging Log* log = GetSubsystem<Log>(); if (log) { if (HasParameter(parameters, "LogLevel")) log->SetLevel(GetParameter(parameters, "LogLevel").GetInt()); log->SetQuiet(GetParameter(parameters, "LogQuiet", false).GetBool()); log->Open(GetParameter(parameters, "LogName", "Urho3D.log").GetString()); } // Set maximally accurate low res timer GetSubsystem<Time>()->SetTimerPeriod(1); // Configure max FPS if (GetParameter(parameters, "FrameLimiter", true) == false) SetMaxFps(0); // Set amount of worker threads according to the available physical CPU cores. Using also hyperthreaded cores results in // unpredictable extra synchronization overhead. Also reserve one core for the main thread unsigned numThreads = GetParameter(parameters, "WorkerThreads", true).GetBool() ? GetNumPhysicalCPUs() - 1 : 0; if (numThreads) { GetSubsystem<WorkQueue>()->CreateThreads(numThreads); LOGINFO(ToString("Created %u worker thread%s", numThreads, numThreads > 1 ? "s" : "")); } // Add resource paths ResourceCache* cache = GetSubsystem<ResourceCache>(); FileSystem* fileSystem = GetSubsystem<FileSystem>(); String exePath = fileSystem->GetProgramDir(); Vector<String> resourcePaths = GetParameter(parameters, "ResourcePaths", "CoreData;Data").GetString().Split(';'); Vector<String> resourcePackages = GetParameter(parameters, "ResourcePackages").GetString().Split(';'); for (unsigned i = 0; i < resourcePaths.Size(); ++i) { bool success = false; // If path is not absolute, prefer to add it as a package if possible if (!IsAbsolutePath(resourcePaths[i])) { String packageName = exePath + resourcePaths[i] + ".pak"; if (fileSystem->FileExists(packageName)) { SharedPtr<PackageFile> package(new PackageFile(context_)); if (package->Open(packageName)) { cache->AddPackageFile(package); success = true; } } if (!success) { String pathName = exePath + resourcePaths[i]; if (fileSystem->DirExists(pathName)) success = cache->AddResourceDir(pathName); } } else { String pathName = resourcePaths[i]; if (fileSystem->DirExists(pathName)) success = cache->AddResourceDir(pathName); } if (!success) { LOGERROR("Failed to add resource path " + resourcePaths[i]); return false; } } // Then add specified packages for (unsigned i = 0; i < resourcePackages.Size(); ++i) { bool success = false; String packageName = exePath + resourcePackages[i]; if (fileSystem->FileExists(packageName)) { SharedPtr<PackageFile> package(new PackageFile(context_)); if (package->Open(packageName)) { cache->AddPackageFile(package); success = true; } } if (!success) { LOGERROR("Failed to add resource package " + resourcePackages[i]); return false; } } // Initialize graphics & audio output if (!headless_) { Graphics* graphics = GetSubsystem<Graphics>(); Renderer* renderer = GetSubsystem<Renderer>(); if (HasParameter(parameters, "ExternalWindow")) graphics->SetExternalWindow(GetParameter(parameters, "ExternalWindow").GetPtr()); graphics->SetForceSM2(GetParameter(parameters, "ForceSM2", false).GetBool()); graphics->SetWindowTitle(GetParameter(parameters, "WindowTitle", "Urho3D").GetString()); if (!graphics->SetMode( GetParameter(parameters, "WindowWidth", 0).GetInt(), GetParameter(parameters, "WindowHeight", 0).GetInt(), GetParameter(parameters, "FullScreen", true).GetBool(), GetParameter(parameters, "WindowResizable", false).GetBool(), GetParameter(parameters, "VSync", false).GetBool(), GetParameter(parameters, "TripleBuffer", false).GetBool(), GetParameter(parameters, "MultiSample", 1).GetInt() )) return false; if (HasParameter(parameters, "RenderPath")) renderer->SetDefaultRenderPath(cache->GetResource<XMLFile>(GetParameter(parameters, "RenderPath").GetString())); renderer->SetDrawShadows(GetParameter(parameters, "Shadows", true).GetBool()); if (renderer->GetDrawShadows() && GetParameter(parameters, "LowQualityShadows", false).GetBool()) renderer->SetShadowQuality(SHADOWQUALITY_LOW_16BIT); if (GetParameter(parameters, "Sound", true).GetBool()) { GetSubsystem<Audio>()->SetMode( GetParameter(parameters, "SoundBuffer", 100).GetInt(), GetParameter(parameters, "SoundMixRate", 44100).GetInt(), GetParameter(parameters, "SoundStereo", true).GetBool(), GetParameter(parameters, "SoundInterpolation", true).GetBool() ); } } // Init FPU state of main thread InitFPU(); frameTimer_.Reset(); initialized_ = true; return true; }