void ResourceOps::HandleCreateModule(const String& resourcePath, const String& resourceName, bool navigateToResource, bool reportError) { Editor* editor = GetSubsystem<Editor>(); if (!CheckCreateModule(resourcePath, resourceName, reportError)) return; ResourceCache* cache = GetSubsystem<ResourceCache>(); SharedPtr<File> srcFile = cache->GetFile("ClockworkEditor/templates/template_module.js"); if (srcFile.Null() || !srcFile->IsOpen()) { editor->PostModalError("Create Script Error", "Could not open module template"); return; } String fullpath = resourcePath + resourceName; if (!resourceName.EndsWith(".js")) fullpath += ".js"; if (!CopyFile(srcFile, fullpath)) { String errorMsg; errorMsg.AppendWithFormat("Error copying template:\n\n%s\n\nto:\n\n%s", "ClockworkEditor/template_module.js", fullpath.CString()); editor->PostModalError("Create Module Error", errorMsg); return; } if (navigateToResource) { ResourceFrame* rframe = GetSubsystem<MainFrame>()->GetResourceFrame(); rframe->EditResource(fullpath); } GetSubsystem<MainFrame>()->GetProjectFrame()->Refresh(); }
void Cursor::DefineShape(CursorShape shape, Image* image, const IntRect& imageRect, const IntVector2& hotSpot) { if (shape < CS_NORMAL || shape >= CS_MAX_SHAPES) { LOGERROR("Shape index out of bounds, can not define cursor shape"); return; } if (!image) return; ResourceCache* cache = GetSubsystem<ResourceCache>(); CursorShapeInfo& info = shapeInfos_[shape]; // Prefer to get the texture with same name from cache to prevent creating several copies of the texture if (cache->Exists(image->GetName())) info.texture_ = cache->GetResource<Texture2D>(image->GetName()); else { Texture2D* texture = new Texture2D(context_); texture->Load(SharedPtr<Image>(image)); info.texture_ = texture; } info.image_ = image; info.imageRect_ = imageRect; info.hotSpot_ = hotSpot; // Remove existing SDL cursor if (info.osCursor_) { SDL_FreeCursor(info.osCursor_); info.osCursor_ = 0; } // Reset current shape if it was edited if (shape == shape_) ApplyShape(); }
void Engine::DumpResources() { #ifdef ENABLE_LOGGING ResourceCache* cache = GetSubsystem<ResourceCache>(); const HashMap<ShortStringHash, ResourceGroup>& resourceGroups = cache->GetAllResources(); LOGRAW("\n"); for (HashMap<ShortStringHash, ResourceGroup>::ConstIterator i = resourceGroups.Begin(); i != resourceGroups.End(); ++i) { unsigned num = i->second_.resources_.Size(); unsigned memoryUse = i->second_.memoryUse_; if (num) { LOGRAW("Resource type " + i->second_.resources_.Begin()->second_->GetTypeName() + ": count " + String(num) + " memory use " + String(memoryUse) + "\n"); } } LOGRAW("Total memory use of all resources " + String(cache->GetTotalMemoryUse()) + "\n\n"); #endif }
FrItem SceneItem::msgCreate(FrMsg m, FrMsgLength l) { SceneItem *si = new SceneItem(); CborParser parser; CborValue it; cbor_parser_init(m, l, 0, &parser, &it); cbd::Scene scene; cbd::readScene(&it, &scene); Graphics3DSystem *g3ds = Graphics3DSystem::getG3DS(); ResourceCache* cache = si->node->GetSubsystem<ResourceCache>(); SharedPtr<File> file; if (scene.selector == cbd::XmlScene) { file = cache->GetFile(scene.data.XmlScene.value0.c_str()); si->node = g3ds->scene->InstantiateXML(*file, Vector3::ZERO, Quaternion::IDENTITY); } if (scene.selector == cbd::BinaryScene) { file = cache->GetFile(scene.data.BinaryScene.value0.c_str()); si->node = g3ds->scene->Instantiate(*file, Vector3::ZERO, Quaternion::IDENTITY); } return (FrItem)si; }
void Light::SetShapeTextureAttr(ResourceRef value) { ResourceCache* cache = GetSubsystem<ResourceCache>(); shapeTexture_ = static_cast<Texture*>(cache->GetResource(value.type_, value.id_)); }
bool Animation::Load(Deserializer& source) { PROFILE(LoadAnimation); unsigned memoryUse = sizeof(Animation); // Check ID if (source.ReadFileID() != "UANI") { LOGERROR(source.GetName() + " is not a valid animation file"); return false; } // Read name and length animationName_ = source.ReadString(); animationNameHash_ = animationName_; length_ = source.ReadFloat(); tracks_.Clear(); unsigned tracks = source.ReadUInt(); tracks_.Resize(tracks); memoryUse += tracks * sizeof(AnimationTrack); // Read tracks for (unsigned i = 0; i < tracks; ++i) { AnimationTrack& newTrack = tracks_[i]; newTrack.name_ = source.ReadString(); newTrack.nameHash_ = newTrack.name_; newTrack.channelMask_ = source.ReadUByte(); unsigned keyFrames = source.ReadUInt(); newTrack.keyFrames_.Resize(keyFrames); memoryUse += keyFrames * sizeof(AnimationKeyFrame); // Read keyframes of the track for (unsigned j = 0; j < keyFrames; ++j) { AnimationKeyFrame& newKeyFrame = newTrack.keyFrames_[j]; newKeyFrame.time_ = source.ReadFloat(); if (newTrack.channelMask_ & CHANNEL_POSITION) newKeyFrame.position_ = source.ReadVector3(); if (newTrack.channelMask_ & CHANNEL_ROTATION) newKeyFrame.rotation_ = source.ReadQuaternion(); if (newTrack.channelMask_ & CHANNEL_SCALE) newKeyFrame.scale_ = source.ReadVector3(); } } // Optionally read triggers from an XML file ResourceCache* cache = GetSubsystem<ResourceCache>(); String xmlName = ReplaceExtension(GetName(), ".xml"); if (cache->Exists(xmlName)) { XMLFile* file = cache->GetResource<XMLFile>(xmlName); if (file) { XMLElement rootElem = file->GetRoot(); XMLElement triggerElem = rootElem.GetChild("trigger"); while (triggerElem) { if (triggerElem.HasAttribute("normalizedtime")) AddTrigger(triggerElem.GetFloat("normalizedtime"), true, triggerElem.GetVariant()); else if (triggerElem.HasAttribute("time")) AddTrigger(triggerElem.GetFloat("time"), false, triggerElem.GetVariant()); triggerElem = triggerElem.GetNext("trigger"); } memoryUse += triggers_.Size() * sizeof(AnimationTriggerPoint); } } SetMemoryUse(memoryUse); return true; }
bool Texture3D::BeginLoad(Deserializer& source) { ResourceCache* cache = GetSubsystem<ResourceCache>(); // In headless mode, do not actually load the texture, just return success if (!graphics_) return true; // If device is lost, retry later if (graphics_->IsDeviceLost()) { URHO3D_LOGWARNING("Texture load while device is lost"); dataPending_ = true; return true; } String texPath, texName, texExt; SplitPath(GetName(), texPath, texName, texExt); cache->ResetDependencies(this); loadParameters_ = new XMLFile(context_); if (!loadParameters_->Load(source)) { loadParameters_.Reset(); return false; } XMLElement textureElem = loadParameters_->GetRoot(); XMLElement volumeElem = textureElem.GetChild("volume"); XMLElement colorlutElem = textureElem.GetChild("colorlut"); if (volumeElem) { String name = volumeElem.GetAttribute("name"); String volumeTexPath, volumeTexName, volumeTexExt; SplitPath(name, volumeTexPath, volumeTexName, volumeTexExt); // If path is empty, add the XML file path if (volumeTexPath.Empty()) name = texPath + name; loadImage_ = cache->GetTempResource<Image>(name); // Precalculate mip levels if async loading if (loadImage_ && GetAsyncLoadState() == ASYNC_LOADING) loadImage_->PrecalculateLevels(); cache->StoreResourceDependency(this, name); return true; } else if (colorlutElem) { String name = colorlutElem.GetAttribute("name"); String colorlutTexPath, colorlutTexName, colorlutTexExt; SplitPath(name, colorlutTexPath, colorlutTexName, colorlutTexExt); // If path is empty, add the XML file path if (colorlutTexPath.Empty()) name = texPath + name; SharedPtr<File> file = GetSubsystem<ResourceCache>()->GetFile(name); loadImage_ = new Image(context_); if (!loadImage_->LoadColorLUT(*(file.Get()))) { loadParameters_.Reset(); loadImage_.Reset(); return false; } // Precalculate mip levels if async loading if (loadImage_ && GetAsyncLoadState() == ASYNC_LOADING) loadImage_->PrecalculateLevels(); cache->StoreResourceDependency(this, name); return true; } URHO3D_LOGERROR("Texture3D XML data for " + GetName() + " did not contain either volume or colorlut element"); return false; }
Script::Script(Context* context) : Object(context), scriptEngine_(0), immediateContext_(0), scriptNestingLevel_(0), executeConsoleCommands_(false) { scriptEngine_ = asCreateScriptEngine(ANGELSCRIPT_VERSION); if (!scriptEngine_) { URHO3D_LOGERROR("Could not create AngelScript engine"); return; } scriptEngine_->SetUserData(this); scriptEngine_->SetEngineProperty(asEP_USE_CHARACTER_LITERALS, (asPWORD)true); scriptEngine_->SetEngineProperty(asEP_ALLOW_UNSAFE_REFERENCES, (asPWORD)true); scriptEngine_->SetEngineProperty(asEP_ALLOW_IMPLICIT_HANDLE_TYPES, (asPWORD)true); scriptEngine_->SetEngineProperty(asEP_BUILD_WITHOUT_LINE_CUES, (asPWORD)true); scriptEngine_->SetMessageCallback(asMETHOD(Script, MessageCallback), this, asCALL_THISCALL); // Create the context for immediate execution immediateContext_ = scriptEngine_->CreateContext(); immediateContext_->SetExceptionCallback(asMETHOD(Script, ExceptionCallback), this, asCALL_THISCALL); // Register Script library object factories RegisterScriptLibrary(context_); // Register the Array, String & Dictionary API RegisterArray(scriptEngine_); RegisterString(scriptEngine_); RegisterDictionary(scriptEngine_); RegisterScriptInterfaceAPI(scriptEngine_); // Register the rest of the script API RegisterMathAPI(scriptEngine_); RegisterCoreAPI(scriptEngine_); RegisterIOAPI(scriptEngine_); RegisterResourceAPI(scriptEngine_); RegisterSceneAPI(scriptEngine_); RegisterGraphicsAPI(scriptEngine_); RegisterInputAPI(scriptEngine_); RegisterAudioAPI(scriptEngine_); RegisterUIAPI(scriptEngine_); #ifdef URHO3D_NETWORK RegisterNetworkAPI(scriptEngine_); #endif #ifdef URHO3D_DATABASE RegisterDatabaseAPI(scriptEngine_); #endif #ifdef URHO3D_PHYSICS RegisterPhysicsAPI(scriptEngine_); #endif #ifdef URHO3D_NAVIGATION RegisterNavigationAPI(scriptEngine_); #endif #ifdef URHO3D_URHO2D RegisterUrho2DAPI(scriptEngine_); #endif RegisterScriptAPI(scriptEngine_); RegisterEngineAPI(scriptEngine_); // Subscribe to console commands SetExecuteConsoleCommands(true); // Create and register resource router for checking for compiled AngelScript files ResourceCache* cache = GetSubsystem<ResourceCache>(); if (cache) { router_ = new ScriptResourceRouter(context_); cache->AddResourceRouter(router_); } }
// see http://duktape.org/guide.html#modules static int js_module_search(duk_context* ctx) { JSVM* vm = JSVM::GetJSVM(ctx); FileSystem* fs = vm->GetSubsystem<FileSystem>(); ResourceCache* cache = vm->GetSubsystem<ResourceCache>(); int top = duk_get_top(ctx); assert(top == 4); String moduleID = duk_to_string(ctx, 0); if (top > 1) { // require function assert(duk_is_function(ctx, 1)); } if (top > 2) { // exports assert(duk_is_object(ctx, 2)); } if (top > 3) { // module (module.id == a resolved absolute identifier for the module being loaded) assert(duk_is_object(ctx, 3)); } String pathName, fileName, extension; SplitPath(moduleID, pathName, fileName, extension); String path = moduleID; // Do we really want this? It is nice to not have to specify the Atomic path if (fileName.StartsWith("Atomic")) { path = "AtomicModules/" + path + ".js"; } else { path += ".js"; if (!cache->Exists(path)) { const Vector<String>& searchPaths = vm->GetModuleSearchPaths(); for (unsigned i = 0; i < searchPaths.Size(); i++) { String search = searchPaths[i] + path; if (cache->Exists(search)) { path = search; break; } } } } if (cache->Exists(path)) { SharedPtr<File> jsfile(cache->GetFile(path, false)); vm->SetLastModuleSearchFile(jsfile->GetFullPath()); String source; jsfile->ReadText(source); source.Append('\n'); duk_push_string(ctx, source.CString()); return 1; } else { // we're not a JS file, so check if we're a native module const Vector<String>& resourceDirs = cache->GetResourceDirs(); for (unsigned i = 0; i < resourceDirs.Size(); i++) { String pluginLibrary; // TODO: proper platform folder detection #ifdef ATOMIC_PLATFORM_WINDOWS pluginLibrary = resourceDirs.At(i) + "Plugins/Windows/x64/" + moduleID + ".dll"; #elif ATOMIC_PLATFORM_OSX pluginLibrary = resourceDirs.At(i) + "Plugins/Mac/x64/lib" + moduleID + ".dylib"; #endif if (pluginLibrary.Length() && fs->FileExists(pluginLibrary)) { // let duktape know we loaded a native module if (jsplugin_load(vm, pluginLibrary)) { duk_push_undefined(ctx); return 1; } else { duk_push_sprintf(ctx, "Failed loading native plugins: %s", pluginLibrary.CString()); duk_throw(ctx); } } } } duk_push_sprintf(ctx, "Failed loading module: %s", path.CString()); duk_throw(ctx); }
void PrefabImporter::HandlePrefabSave(StringHash eventType, VariantMap& eventData) { using namespace PrefabSave; PrefabComponent* component = static_cast<PrefabComponent*>(eventData[P_PREFABCOMPONENT].GetPtr()); if (component->GetPrefabGUID() != asset_->GetGUID()) return; Node* node = component->GetNode(); if (!node) return; // flip temporary root children and components to not be temporary for save const Vector<SharedPtr<Component>>& rootComponents = node->GetComponents(); const Vector<SharedPtr<Node> >& children = node->GetChildren(); PODVector<Component*> tempComponents; PODVector<Node*> tempChildren; PODVector<Node*> filterNodes; for (unsigned i = 0; i < rootComponents.Size(); i++) { if (rootComponents[i]->IsTemporary()) { rootComponents[i]->SetTemporary(false); tempComponents.Push(rootComponents[i]); // Animated sprites contain a temporary node we don't want to save in the prefab // it would be nice if this was general purpose because have to test this when // breaking node as well if (rootComponents[i]->GetType() == AnimatedSprite2D::GetTypeStatic()) { AnimatedSprite2D* asprite = (AnimatedSprite2D*) rootComponents[i].Get(); if (asprite->GetRootNode()) filterNodes.Push(asprite->GetRootNode()); } } } for (unsigned i = 0; i < children.Size(); i++) { if (filterNodes.Contains(children[i].Get())) continue; if (children[i]->IsTemporary()) { children[i]->SetTemporary(false); tempChildren.Push(children[i]); } } // store original transform Vector3 pos = node->GetPosition(); Quaternion rot = node->GetRotation(); Vector3 scale = node->GetScale(); node->SetPosition(Vector3::ZERO); node->SetRotation(Quaternion::IDENTITY); node->SetScale(Vector3::ONE); component->SetTemporary(true); SharedPtr<File> file(new File(context_, asset_->GetPath(), FILE_WRITE)); node->SaveXML(*file); file->Close(); component->SetTemporary(false); // restore node->SetPosition(pos); node->SetRotation(rot); node->SetScale(scale); for (unsigned i = 0; i < tempComponents.Size(); i++) { tempComponents[i]->SetTemporary(true); } for (unsigned i = 0; i < tempChildren.Size(); i++) { tempChildren[i]->SetTemporary(true); } FileSystem* fs = GetSubsystem<FileSystem>(); fs->Copy(asset_->GetPath(), asset_->GetCachePath()); // reload it immediately so it is ready for use // TODO: The resource cache is reloading after this reload due to catching the file cache ResourceCache* cache = GetSubsystem<ResourceCache>(); XMLFile* xmlfile = cache->GetResource<XMLFile>(asset_->GetGUID()); cache->ReloadResource(xmlfile); VariantMap changedData; changedData[PrefabChanged::P_GUID] = asset_->GetGUID(); SendEvent(E_PREFABCHANGED, changedData); }
void Zone::SetZoneTextureAttr(const ResourceRef& value) { ResourceCache* cache = GetSubsystem<ResourceCache>(); zoneTexture_ = static_cast<Texture*>(cache->GetResource(value.type_, value.name_)); }
void DebugHud::Update() { Graphics* graphics = GetSubsystem<Graphics>(); Renderer* renderer = GetSubsystem<Renderer>(); if (!renderer || !graphics) return; // Ensure UI-elements are not detached if (!statsText_->GetParent()) { UI* ui = GetSubsystem<UI>(); UIElement* uiRoot = ui->GetRoot(); uiRoot->AddChild(statsText_); uiRoot->AddChild(modeText_); uiRoot->AddChild(profilerText_); } if (statsText_->IsVisible()) { unsigned primitives, batches; if (!useRendererStats_) { primitives = graphics->GetNumPrimitives(); batches = graphics->GetNumBatches(); } else { primitives = renderer->GetNumPrimitives(); batches = renderer->GetNumBatches(); } String stats; stats.AppendWithFormat("Triangles %u\nBatches %u\nViews %u\nLights %u\nShadowmaps %u\nOccluders %u", primitives, batches, renderer->GetNumViews(), renderer->GetNumLights(true), renderer->GetNumShadowMaps(true), renderer->GetNumOccluders(true)); if (!appStats_.Empty()) { stats.Append("\n"); for (HashMap<String, String>::ConstIterator i = appStats_.Begin(); i != appStats_.End(); ++i) stats.AppendWithFormat("\n%s %s", i->first_.CString(), i->second_.CString()); } statsText_->SetText(stats); } if (modeText_->IsVisible()) { String mode; mode.AppendWithFormat("Tex:%s Mat:%s Spec:%s Shadows:%s Size:%i Quality:%s Occlusion:%s Instancing:%s API:%s", qualityTexts[renderer->GetTextureQuality()], qualityTexts[renderer->GetMaterialQuality()], renderer->GetSpecularLighting() ? "On" : "Off", renderer->GetDrawShadows() ? "On" : "Off", renderer->GetShadowMapSize(), shadowQualityTexts[renderer->GetShadowQuality()], renderer->GetMaxOccluderTriangles() > 0 ? "On" : "Off", renderer->GetDynamicInstancing() ? "On" : "Off", graphics->GetApiName().CString()); modeText_->SetText(mode); } Profiler* profiler = GetSubsystem<Profiler>(); if (profiler) { if (profilerTimer_.GetMSec(false) >= profilerInterval_) { profilerTimer_.Reset(); if (profilerText_->IsVisible()) { String profilerOutput = profiler->PrintData(false, false, profilerMaxDepth_); profilerText_->SetText(profilerOutput); } profiler->BeginInterval(); } } if (memoryText_->IsVisible()) { ResourceCache* cache = GetSubsystem<ResourceCache>(); memoryText_->SetText(cache->PrintMemoryUsage()); } }
int main(int argc, char** argv) { #ifdef WIN32 const Vector<String>& arguments = ParseArguments(GetCommandLineW()); #else const Vector<String>& arguments = ParseArguments(argc, argv); #endif bool dumpApiMode = false; String outputFile; if (arguments.Size() < 1) ErrorExit("Usage: ScriptCompiler <input file> [resource path for includes]\n" " ScriptCompiler -dumpapi [output file]"); else { if (arguments[0] != "-dumpapi") outputFile = arguments[0]; else { dumpApiMode = true; if (arguments.Size() > 1) outputFile = arguments[1]; } } SharedPtr<Context> context(new Context()); // Note: creating the Engine registers most subsystems which don't require engine initialization SharedPtr<Engine> engine(new Engine(context)); context->RegisterSubsystem(new Script(context)); Log* log = context->GetSubsystem<Log>(); // Register Log subsystem manually if compiled without logging support if (!log) { context->RegisterSubsystem(new Log(context)); log = context->GetSubsystem<Log>(); } log->SetLevel(LOG_WARNING); log->SetTimeStamp(false); if (!dumpApiMode) { String path, file, extension; SplitPath(outputFile, path, file, extension); ResourceCache* cache = context->GetSubsystem<ResourceCache>(); // Add resource path to be able to resolve includes if (arguments.Size() > 1) cache->AddResourceDir(arguments[1]); else cache->AddResourceDir(cache->GetPreferredResourceDir(path)); if (!file.StartsWith("*")) CompileScript(context, outputFile); else { Vector<String> scriptFiles; context->GetSubsystem<FileSystem>()->ScanDir(scriptFiles, path, file + extension, SCAN_FILES, false); for (unsigned i = 0; i < scriptFiles.Size(); ++i) CompileScript(context, path + scriptFiles[i]); } } else { if (!outputFile.Empty()) { log->SetQuiet(true); log->Open(outputFile); } // If without output file, dump to stdout instead context->GetSubsystem<Script>()->DumpAPI(); } return EXIT_SUCCESS; }
bool ShaderVariation::LoadByteCode(const String& binaryShaderName) { ResourceCache* cache = owner_->GetSubsystem<ResourceCache>(); if (!cache->Exists(binaryShaderName)) return false; FileSystem* fileSystem = owner_->GetSubsystem<FileSystem>(); unsigned sourceTimeStamp = owner_->GetTimeStamp(); // If source code is loaded from a package, its timestamp will be zero. Else check that binary is not older // than source if (sourceTimeStamp && fileSystem->GetLastModifiedTime(cache->GetResourceFileName(binaryShaderName)) < sourceTimeStamp) return false; SharedPtr<File> file = cache->GetFile(binaryShaderName); if (!file || file->ReadFileID() != "USHD") { ATOMIC_LOGERROR(binaryShaderName + " is not a valid shader bytecode file"); return false; } /// \todo Check that shader type and model match /*unsigned short shaderType = */file->ReadUShort(); /*unsigned short shaderModel = */file->ReadUShort(); unsigned numParameters = file->ReadUInt(); for (unsigned i = 0; i < numParameters; ++i) { String name = file->ReadString(); unsigned reg = file->ReadUByte(); unsigned regCount = file->ReadUByte(); ShaderParameter parameter; parameter.type_ = type_; parameter.name_ = name; parameter.register_ = reg; parameter.regCount_ = regCount; parameters_[StringHash(name)] = parameter; } unsigned numTextureUnits = file->ReadUInt(); for (unsigned i = 0; i < numTextureUnits; ++i) { /*String unitName = */file->ReadString(); unsigned reg = file->ReadUByte(); if (reg < MAX_TEXTURE_UNITS) useTextureUnit_[reg] = true; } unsigned byteCodeSize = file->ReadUInt(); if (byteCodeSize) { byteCode_.Resize(byteCodeSize); file->Read(&byteCode_[0], byteCodeSize); if (type_ == VS) ATOMIC_LOGDEBUG("Loaded cached vertex shader " + GetFullName()); else ATOMIC_LOGDEBUG("Loaded cached pixel shader " + GetFullName()); return true; } else { ATOMIC_LOGERROR(binaryShaderName + " has zero length bytecode"); return false; } }
static shared_ptr<Tree> load_tree_fromCache(const string& name) { static ResourceCache<Tree> cache(load_tree_xml, "trees"); return cache.load_copy(name); }
void Scene::PreloadResourcesXML(const XMLElement& element) { ResourceCache* cache = GetSubsystem<ResourceCache>(); // Node or Scene attributes do not include any resources; therefore skip to the components XMLElement compElem = element.GetChild("component"); while (compElem) { String typeName = compElem.GetAttribute("type"); const Vector<AttributeInfo>* attributes = context_->GetAttributes(StringHash(typeName)); if (attributes) { XMLElement attrElem = compElem.GetChild("attribute"); unsigned startIndex = 0; while (attrElem) { String name = attrElem.GetAttribute("name"); unsigned i = startIndex; unsigned attempts = attributes->Size(); while (attempts) { const AttributeInfo& attr = attributes->At(i); if ((attr.mode_ & AM_FILE) && !attr.name_.Compare(name, true)) { if (attr.type_ == VAR_RESOURCEREF) { ResourceRef ref = attrElem.GetVariantValue(attr.type_).GetResourceRef(); String name = cache->SanitateResourceName(ref.name_); bool success = cache->BackgroundLoadResource(ref.type_, name); if (success) { ++asyncProgress_.totalResources_; asyncProgress_.resources_.Insert(StringHash(name)); } } else if (attr.type_ == VAR_RESOURCEREFLIST) { ResourceRefList refList = attrElem.GetVariantValue(attr.type_).GetResourceRefList(); for (unsigned k = 0; k < refList.names_.Size(); ++k) { String name = cache->SanitateResourceName(refList.names_[k]); bool success = cache->BackgroundLoadResource(refList.type_, name); if (success) { ++asyncProgress_.totalResources_; asyncProgress_.resources_.Insert(StringHash(name)); } } } startIndex = (i + 1) % attributes->Size(); break; } else { i = (i + 1) % attributes->Size(); --attempts; } } attrElem = attrElem.GetNext("attribute"); } } compElem = compElem.GetNext("component"); } XMLElement childElem = element.GetChild("node"); while (childElem) { PreloadResourcesXML(childElem); childElem = childElem.GetNext("node"); } }
void Scene::PreloadResources(File* file, bool isSceneFile) { ResourceCache* cache = GetSubsystem<ResourceCache>(); // Read node ID (not needed) /*unsigned nodeID = */file->ReadUInt(); // Read Node or Scene attributes; these do not include any resources const Vector<AttributeInfo>* attributes = context_->GetAttributes(isSceneFile ? Scene::GetTypeStatic() : Node::GetTypeStatic()); assert(attributes); for (unsigned i = 0; i < attributes->Size(); ++i) { const AttributeInfo& attr = attributes->At(i); if (!(attr.mode_ & AM_FILE)) continue; Variant varValue = file->ReadVariant(attr.type_); } // Read component attributes unsigned numComponents = file->ReadVLE(); for (unsigned i = 0; i < numComponents; ++i) { VectorBuffer compBuffer(*file, file->ReadVLE()); StringHash compType = compBuffer.ReadStringHash(); // Read component ID (not needed) /*unsigned compID = */compBuffer.ReadUInt(); attributes = context_->GetAttributes(compType); if (attributes) { for (unsigned j = 0; j < attributes->Size(); ++j) { const AttributeInfo& attr = attributes->At(j); if (!(attr.mode_ & AM_FILE)) continue; Variant varValue = compBuffer.ReadVariant(attr.type_); if (attr.type_ == VAR_RESOURCEREF) { const ResourceRef& ref = varValue.GetResourceRef(); // Sanitate resource name beforehand so that when we get the background load event, the name matches exactly String name = cache->SanitateResourceName(ref.name_); bool success = cache->BackgroundLoadResource(ref.type_, name); if (success) { ++asyncProgress_.totalResources_; asyncProgress_.resources_.Insert(StringHash(name)); } } else if (attr.type_ == VAR_RESOURCEREFLIST) { const ResourceRefList& refList = varValue.GetResourceRefList(); for (unsigned k = 0; k < refList.names_.Size(); ++k) { String name = cache->SanitateResourceName(refList.names_[k]); bool success = cache->BackgroundLoadResource(refList.type_, name); if (success) { ++asyncProgress_.totalResources_; asyncProgress_.resources_.Insert(StringHash(name)); } } } } } } // Read child nodes unsigned numChildren = file->ReadVLE(); for (unsigned i = 0; i < numChildren; ++i) PreloadResources(file, false); }
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; }
Shader::~Shader() { ResourceCache* cache = GetSubsystem<ResourceCache>(); if (cache) cache->ResetDependencies(this); }
void Slice::Draw(Ray ray, Vector pos, Vector dir, const Level& level, const ResourceCache& res) { const int wall_height = std::abs(int(mSurface->h / ray.GetDistance())); int wall_start = (mSurface->h / 2) - (wall_height / 2); int wall_end = (mSurface->h / 2) + (wall_height / 2); if (wall_start < 0) { wall_start = 0; } if (wall_end >= mSurface->h) { wall_end = mSurface->h - 1; } // Get the texture that matches the cell type. const auto cell_id = level.mGrid[ray.GetMapIntersectionX()][ray.GetMapIntersectionY()] - 1; //const auto cell_id = level.mGrid[ray.GetMapIntersectionX()][ray.GetMapIntersectionY()] - 1; const auto wall_tex = res.GetWall(cell_id); // Where exactly the wall was hit. double wall_x = ray.GetIntersection().GetY(); wall_x -= std::floor(wall_x); // X-coordinate on the texture. int tex_x = wall_x * wall_tex->w; if (( ray.VerticalSideHit() && dir.GetY() < 0) || (!ray.VerticalSideHit() && dir.GetX() > 0)) { tex_x = wall_tex->w - tex_x - 1; } for (int y = wall_start; y < wall_end; y++) { const int tex_y = (y * 2 - mSurface->h + wall_height) * (wall_tex->h / 2) / wall_height; const auto tex_offset = (wall_tex->pitch * tex_y) + (tex_x * 4); const auto tex_ptr = static_cast<Uint8*>(wall_tex->pixels) + tex_offset; SDL_Color color = { tex_ptr[0], tex_ptr[1], tex_ptr[2] }; if (ray.VerticalSideHit()) { // Give X and Y-sides different brightness. color.r /= 2; color.g /= 2; color.b /= 2; } const auto scr_offset = (mSurface->pitch * y) + (mXCoordinate * 4); const auto scr_ptr = static_cast<Uint8*>(mSurface->pixels) + scr_offset; memcpy(scr_ptr, &color, sizeof(color)); } // Get the texture for the ceiling and floor. // const auto ceiling_tex = res.GetCeiling(0); const auto floor_tex = res.GetWall(2); // Position of the floor at the bottom of the wall. double floor_x_wall; double floor_y_wall; if (!ray.VerticalSideHit() && (dir.GetX() > 0)) { floor_x_wall = ray.GetMapIntersectionX(); floor_y_wall = ray.GetMapIntersectionY() + wall_x; } else if (!ray.VerticalSideHit() && (dir.GetX() < 0)) { floor_x_wall = ray.GetMapIntersectionX() + 1.; floor_y_wall = ray.GetMapIntersectionY() + wall_x; } else if (ray.VerticalSideHit() && (dir.GetY() > 0)) { floor_x_wall = ray.GetMapIntersectionX() + wall_x; floor_y_wall = ray.GetMapIntersectionY(); } else { floor_x_wall = ray.GetMapIntersectionX() + wall_x; floor_y_wall = ray.GetMapIntersectionY() + 1.; } const double dist_wall = ray.GetDistance(); const double dist_player = .0; // Draw the floor from below the wall to the bottom of the screen. for (int y = wall_end; y < mSurface->h; y++) { const double cur_dist = mSurface->h / (2. * y - mSurface->h); const double weight = (cur_dist - dist_player) / (dist_wall - dist_player); double cur_floor_x = weight * floor_x_wall + (1.0 - weight) * pos.GetX(); double cur_floor_y = weight * floor_y_wall + (1.0 - weight) * pos.GetY(); if (cur_floor_x < 0.) { cur_floor_x = 0.; } if (cur_floor_y < 0.) { cur_floor_y = 0.; } const int floor_tex_x = int(cur_floor_x * floor_tex->w / 4) % floor_tex->w; const int floor_tex_y = int(cur_floor_y * floor_tex->h / 4) % floor_tex->h; // const auto ceiling_tex_offset = (ceiling_tex->pitch * floor_tex_y) + (floor_tex_x * 4); // const auto ceiling_tex_ptr = static_cast<Uint8*>(ceiling_tex->pixels) + ceiling_tex_offset; const auto floor_tex_offset = (floor_tex->pitch * floor_tex_y) + (floor_tex_x * 4); const auto floor_tex_ptr = static_cast<Uint8*>(floor_tex->pixels) + floor_tex_offset; // const SDL_Color ceiling_color = { ceiling_tex_ptr[0], ceiling_tex_ptr[1], ceiling_tex_ptr[2] }; SDL_Color floor_color = { floor_tex_ptr[0], floor_tex_ptr[1], floor_tex_ptr[2] }; // Make the floor darker. floor_color.r /= 2; floor_color.g /= 2; floor_color.b /= 2; // const auto ceiling_offset = (mSurface->pitch * (mSurface->h - y - 1)) + (mXCoordinate * 4); // const auto ceiling_ptr = static_cast<Uint8*>(mSurface->pixels) + ceiling_offset; // memcpy(ceiling_ptr, &ceiling_color, sizeof(ceiling_color)); const auto floor_offset = (mSurface->pitch * y) + (mXCoordinate * 4); const auto floor_ptr = static_cast<Uint8*>(mSurface->pixels) + floor_offset; memcpy(floor_ptr, &floor_color, sizeof(floor_color)); } }
void Scene::PreloadResourcesJSON(const JSONValue& value) { // If not threaded, can not background load resources, so rather load synchronously later when needed #ifdef URHO3D_THREADING ResourceCache* cache = GetSubsystem<ResourceCache>(); // Node or Scene attributes do not include any resources; therefore skip to the components JSONArray componentArray = value.Get("components").GetArray(); for (unsigned i = 0; i < componentArray.Size(); i++) { const JSONValue& compValue = componentArray.At(i); String typeName = compValue.Get("type").GetString(); const Vector<AttributeInfo>* attributes = context_->GetAttributes(StringHash(typeName)); if (attributes) { JSONArray attributesArray = compValue.Get("attributes").GetArray(); unsigned startIndex = 0; for (unsigned j = 0; j < attributesArray.Size(); j++) { const JSONValue& attrVal = attributesArray.At(j); String name = attrVal.Get("name").GetString(); unsigned i = startIndex; unsigned attempts = attributes->Size(); while (attempts) { const AttributeInfo& attr = attributes->At(i); if ((attr.mode_ & AM_FILE) && !attr.name_.Compare(name, true)) { if (attr.type_ == VAR_RESOURCEREF) { ResourceRef ref = attrVal.Get("value").GetVariantValue(attr.type_).GetResourceRef(); String name = cache->SanitateResourceName(ref.name_); bool success = cache->BackgroundLoadResource(ref.type_, name); if (success) { ++asyncProgress_.totalResources_; asyncProgress_.resources_.Insert(StringHash(name)); } } else if (attr.type_ == VAR_RESOURCEREFLIST) { ResourceRefList refList = attrVal.Get("value").GetVariantValue(attr.type_).GetResourceRefList(); for (unsigned k = 0; k < refList.names_.Size(); ++k) { String name = cache->SanitateResourceName(refList.names_[k]); bool success = cache->BackgroundLoadResource(refList.type_, name); if (success) { ++asyncProgress_.totalResources_; asyncProgress_.resources_.Insert(StringHash(name)); } } } startIndex = (i + 1) % attributes->Size(); break; } else { i = (i + 1) % attributes->Size(); --attempts; } } } } } JSONArray childrenArray = value.Get("children").GetArray(); for (unsigned i = 0; i < childrenArray.Size(); i++) { const JSONValue& childVal = childrenArray.At(i); PreloadResourcesJSON(childVal); } #endif }
bool TextureCube::BeginLoad(Deserializer& source) { ResourceCache* cache = context_->resourceCache(); // In headless mode, do not actually load the texture, just return success if (!graphics_) return true; // If device is lost, retry later if (graphics_->IsDeviceLost()) { URHO3D_LOGWARNING("Texture load while device is lost"); dataPending_ = true; return true; } cache->ResetDependencies(this); QString texPath, texName, texExt; SplitPath(GetName(), texPath, texName, texExt); loadParameters_ = (new XMLFile(context_)); if (!loadParameters_->Load(source)) { loadParameters_.Reset(); return false; } loadImages_.clear(); XMLElement textureElem = loadParameters_->GetRoot(); XMLElement imageElem = textureElem.GetChild("image"); // Single image and multiple faces with layout if (imageElem) { QString name = imageElem.GetAttribute("name"); // If path is empty, add the XML file path if (GetPath(name).isEmpty()) name = texPath + name; SharedPtr<Image> image = cache->GetTempResource<Image>(name); if (!image) return false; int faceWidth, faceHeight; loadImages_.resize(MAX_CUBEMAP_FACES); if (image->IsCubemap()) { loadImages_[FACE_POSITIVE_X] = image; loadImages_[FACE_NEGATIVE_X] = loadImages_[FACE_POSITIVE_X]->GetNextSibling(); loadImages_[FACE_POSITIVE_Y] = loadImages_[FACE_NEGATIVE_X]->GetNextSibling(); loadImages_[FACE_NEGATIVE_Y] = loadImages_[FACE_POSITIVE_Y]->GetNextSibling(); loadImages_[FACE_POSITIVE_Z] = loadImages_[FACE_NEGATIVE_Y]->GetNextSibling(); loadImages_[FACE_NEGATIVE_Z] = loadImages_[FACE_POSITIVE_Z]->GetNextSibling(); } else { CubeMapLayout layout = (CubeMapLayout)GetStringListIndex(imageElem.GetAttribute("layout"), cubeMapLayoutNames, CML_HORIZONTAL); switch (layout) { case CML_HORIZONTAL: faceWidth = image->GetWidth() / MAX_CUBEMAP_FACES; faceHeight = image->GetHeight(); loadImages_[FACE_POSITIVE_Z] = GetTileImage(image, 0, 0, faceWidth, faceHeight); loadImages_[FACE_POSITIVE_X] = GetTileImage(image, 1, 0, faceWidth, faceHeight); loadImages_[FACE_NEGATIVE_Z] = GetTileImage(image, 2, 0, faceWidth, faceHeight); loadImages_[FACE_NEGATIVE_X] = GetTileImage(image, 3, 0, faceWidth, faceHeight); loadImages_[FACE_POSITIVE_Y] = GetTileImage(image, 4, 0, faceWidth, faceHeight); loadImages_[FACE_NEGATIVE_Y] = GetTileImage(image, 5, 0, faceWidth, faceHeight); break; case CML_HORIZONTALNVIDIA: faceWidth = image->GetWidth() / MAX_CUBEMAP_FACES; faceHeight = image->GetHeight(); for (unsigned i = 0; i < MAX_CUBEMAP_FACES; ++i) loadImages_[i] = GetTileImage(image, i, 0, faceWidth, faceHeight); break; case CML_HORIZONTALCROSS: faceWidth = image->GetWidth() / 4; faceHeight = image->GetHeight() / 3; loadImages_[FACE_POSITIVE_Y] = GetTileImage(image, 1, 0, faceWidth, faceHeight); loadImages_[FACE_NEGATIVE_X] = GetTileImage(image, 0, 1, faceWidth, faceHeight); loadImages_[FACE_POSITIVE_Z] = GetTileImage(image, 1, 1, faceWidth, faceHeight); loadImages_[FACE_POSITIVE_X] = GetTileImage(image, 2, 1, faceWidth, faceHeight); loadImages_[FACE_NEGATIVE_Z] = GetTileImage(image, 3, 1, faceWidth, faceHeight); loadImages_[FACE_NEGATIVE_Y] = GetTileImage(image, 1, 2, faceWidth, faceHeight); break; case CML_VERTICALCROSS: faceWidth = image->GetWidth() / 3; faceHeight = image->GetHeight() / 4; loadImages_[FACE_POSITIVE_Y] = GetTileImage(image, 1, 0, faceWidth, faceHeight); loadImages_[FACE_NEGATIVE_X] = GetTileImage(image, 0, 1, faceWidth, faceHeight); loadImages_[FACE_POSITIVE_Z] = GetTileImage(image, 1, 1, faceWidth, faceHeight); loadImages_[FACE_POSITIVE_X] = GetTileImage(image, 2, 1, faceWidth, faceHeight); loadImages_[FACE_NEGATIVE_Y] = GetTileImage(image, 1, 2, faceWidth, faceHeight); loadImages_[FACE_NEGATIVE_Z] = GetTileImage(image, 1, 3, faceWidth, faceHeight); if (loadImages_[FACE_NEGATIVE_Z]) { loadImages_[FACE_NEGATIVE_Z]->FlipVertical(); loadImages_[FACE_NEGATIVE_Z]->FlipHorizontal(); } break; case CML_BLENDER: faceWidth = image->GetWidth() / 3; faceHeight = image->GetHeight() / 2; loadImages_[FACE_NEGATIVE_X] = GetTileImage(image, 0, 0, faceWidth, faceHeight); loadImages_[FACE_NEGATIVE_Z] = GetTileImage(image, 1, 0, faceWidth, faceHeight); loadImages_[FACE_POSITIVE_X] = GetTileImage(image, 2, 0, faceWidth, faceHeight); loadImages_[FACE_NEGATIVE_Y] = GetTileImage(image, 0, 1, faceWidth, faceHeight); loadImages_[FACE_POSITIVE_Y] = GetTileImage(image, 1, 1, faceWidth, faceHeight); loadImages_[FACE_POSITIVE_Z] = GetTileImage(image, 2, 1, faceWidth, faceHeight); break; } } } // Face per image else { XMLElement faceElem = textureElem.GetChild("face"); while (faceElem) { QString name = faceElem.GetAttribute("name"); // If path is empty, add the XML file path if (GetPath(name).isEmpty()) name = texPath + name; loadImages_.push_back(cache->GetTempResource<Image>(name)); cache->StoreResourceDependency(this, name); faceElem = faceElem.GetNext("face"); } } // Precalculate mip levels if async loading if (GetAsyncLoadState() == ASYNC_LOADING) { for (unsigned i = 0; i < loadImages_.size(); ++i) { if (loadImages_[i]) loadImages_[i]->PrecalculateLevels(); } } return true; }
SceneEditor3D ::SceneEditor3D(Context* context, const String &fullpath, TBTabContainer *container) : ResourceEditor(context, fullpath, container) { ResourceCache* cache = GetSubsystem<ResourceCache>(); scene_ = new Scene(context_); SharedPtr<File> xmlFile = cache->GetFile(fullpath); if (GetExtension(fullpath) == ".scene") scene_->LoadXML(*xmlFile); else scene_->Load(*xmlFile); scene_->SetUpdateEnabled(false); sceneView_ = new SceneView3D(context_, this); // EARLY ACCESS if (fullpath.Find(String("ToonTown")) != String::NPOS) { sceneView_->GetCameraNode()->SetWorldPosition(Vector3(-119.073, 76.1121, 16.47763)); Quaternion q(0.55, 0.14, 0.8, -0.2); sceneView_->SetYaw(q.YawAngle()); sceneView_->SetPitch(q.PitchAngle()); sceneView_->GetCameraNode()->SetWorldRotation(q); } else { Node* playerSpawn = scene_->GetChild("PlayerInfoStart", true); if (playerSpawn) { sceneView_->GetCameraNode()->SetPosition(playerSpawn->GetPosition()); sceneView_->SetYaw(playerSpawn->GetRotation().EulerAngles().y_); } } TBWidgetDelegate* delegate = sceneView_->GetWidgetDelegate(); delegate->SetGravity(WIDGET_GRAVITY_ALL); rootContentWidget_->AddChild(delegate); gizmo3D_ = new Gizmo3D(context_); gizmo3D_->SetView(sceneView_); gizmo3D_->Show(); SubscribeToEvent(E_UPDATE, HANDLER(SceneEditor3D, HandleUpdate)); SubscribeToEvent(E_EDITORACTIVENODECHANGE, HANDLER(SceneEditor3D, HandleEditorActiveNodeChange)); // FIXME: Set the size at the end of setup, so all children are updated accordingly // future size changes will be handled automatically TBRect rect = container_->GetContentRoot()->GetRect(); rootContentWidget_->SetSize(rect.w, rect.h); // TODO: generate this event properly VariantMap eventData; eventData[EditorActiveSceneChange::P_SCENE] = scene_; SendEvent(E_EDITORACTIVESCENECHANGE, eventData); SubscribeToEvent(E_EDITORPLAYSTARTED, HANDLER(SceneEditor3D, HandlePlayStarted)); SubscribeToEvent(E_EDITORPLAYSTOPPED, HANDLER(SceneEditor3D, HandlePlayStopped)); }
bool Shader::ProcessSource(SharedArrayPtr<char>& dest, unsigned& length, const String& fileName) { ResourceCache* cache = GetSubsystem<ResourceCache>(); if (!cache) return false; // Allow to define only a vertex shader or only a pixel shader if (!cache->Exists(fileName)) return true; cache->StoreResourceDependency(this, fileName); Vector<String> glslCode; // Load the shader source code SharedPtr<File> glslFile = cache->GetFile(fileName); if (!glslFile) return false; while (!glslFile->IsEof()) glslCode.Push(glslFile->ReadLine()); // Process the code for includes for (unsigned i = 0; i < glslCode.Size(); ++i) { if (glslCode[i].StartsWith("#include")) { String includeFileName = GetPath(fileName) + glslCode[i].Substring(9).Replaced("\"", "").Trimmed(); SharedPtr<File> glslIncludeFile = cache->GetFile(includeFileName); if (!glslIncludeFile) return false; // Remove the #include line, then include the code glslCode.Erase(i); unsigned pos = i; while (!glslIncludeFile->IsEof()) { glslCode.Insert(pos, glslIncludeFile->ReadLine()); ++pos; } // Finally insert an empty line to mark the space between files glslCode.Insert(pos, ""); } } // Copy the final code into one memory block length = 0; for (unsigned i = 0; i < glslCode.Size(); ++i) length += glslCode[i].Length() + 1; dest = new char[length]; char* destPtr = dest.Get(); for (unsigned i = 0; i < glslCode.Size(); ++i) { memcpy(destPtr, glslCode[i].CString(), glslCode[i].Length()); destPtr += glslCode[i].Length(); *destPtr++ = '\n'; } return true; }
int JSVM::GetRealLineNumber(const String& fileName, const int lineNumber) { int realLineNumber = lineNumber; String mapPath = fileName; if (!mapPath.EndsWith(".js.map")) mapPath += ".js.map"; if (mapPath.EndsWith(".js")) { return realLineNumber; } ResourceCache* cache = GetSubsystem<ResourceCache>(); String path; const Vector<String>& searchPaths = GetModuleSearchPaths(); for (unsigned i = 0; i < searchPaths.Size(); i++) { String checkPath = searchPaths[i] + mapPath; if (cache->Exists(checkPath)) { path = checkPath; break; } } if (!path.Length()) return realLineNumber; SharedPtr<File> mapFile(GetSubsystem<ResourceCache>()->GetFile(path)); //if there's no source map file, maybe you use a pure js, so give an error, or maybe forgot to generate source-maps :( if (mapFile.Null()) { return realLineNumber; } String map; mapFile->ReadText(map); int top = duk_get_top(ctx_); duk_get_global_string(ctx_, "require"); duk_push_string(ctx_, "AtomicEditor/EditorScripts/Lib/jsutils"); if (duk_pcall(ctx_, 1)) { printf("Error: %s\n", duk_safe_to_string(ctx_, -1)); duk_set_top(ctx_, top); return false; } duk_get_prop_string(ctx_, -1, "getRealLineNumber"); duk_push_string(ctx_, map.CString()); duk_push_int(ctx_, lineNumber); bool ok = true; if (duk_pcall(ctx_, 2)) { ok = false; printf("Error: %s\n", duk_safe_to_string(ctx_, -1)); } else { realLineNumber = duk_to_int(ctx_, -1); } duk_set_top(ctx_, top); return realLineNumber; }
SceneEditor3D ::SceneEditor3D(Context* context, const String &fullpath, UITabContainer *container) : ResourceEditor(context, fullpath, container) { ResourceCache* cache = GetSubsystem<ResourceCache>(); scene_ = new Scene(context_); SharedPtr<File> xmlFile = cache->GetFile(fullpath); if (GetExtension(fullpath) == ".scene") scene_->LoadXML(*xmlFile); else scene_->Load(*xmlFile); scene_->SetUpdateEnabled(false); sceneView_ = new SceneView3D(context_, this); // EARLY ACCESS if (fullpath.Find(String("ToonTown")) != String::NPOS) { sceneView_->GetCameraNode()->SetWorldPosition(Vector3(-119.073f, 76.1121f, 16.47763f)); Quaternion q(0.55f, 0.14f, 0.8f, -0.2f); sceneView_->SetYaw(q.YawAngle()); sceneView_->SetPitch(q.PitchAngle()); sceneView_->GetCameraNode()->SetWorldRotation(q); } else { Node* playerSpawn = scene_->GetChild("PlayerInfoStart", true); if (playerSpawn) { sceneView_->GetCameraNode()->SetPosition(playerSpawn->GetPosition()); sceneView_->SetYaw(playerSpawn->GetRotation().EulerAngles().y_); } } sceneView_->SetGravity(UI_GRAVITY_ALL); rootContentWidget_->AddChild(sceneView_); gizmo3D_ = new Gizmo3D(context_); gizmo3D_->SetView(sceneView_); gizmo3D_->Show(); SubscribeToEvent(E_UPDATE, HANDLER(SceneEditor3D, HandleUpdate)); SubscribeToEvent(E_EDITORACTIVENODECHANGE, HANDLER(SceneEditor3D, HandleEditorActiveNodeChange)); SubscribeToEvent(E_GIZMOEDITMODECHANGED, HANDLER(SceneEditor3D, HandleGizmoEditModeChanged)); // FIXME: Set the size at the end of setup, so all children are updated accordingly // future size changes will be handled automatically IntRect rect = container_->GetContentRoot()->GetRect(); rootContentWidget_->SetSize(rect.Width(), rect.Height()); SubscribeToEvent(E_EDITORPLAYSTARTED, HANDLER(SceneEditor3D, HandlePlayStarted)); SubscribeToEvent(E_EDITORPLAYSTOPPED, HANDLER(SceneEditor3D, HandlePlayStopped)); SubscribeToEvent(scene_, E_NODEREMOVED, HANDLER(SceneEditor3D, HandleNodeRemoved)); }
bool ModelImporter::Import() { String ext = asset_->GetExtension(); String modelAssetFilename = asset_->GetPath(); importNode_ = new Node(context_); if (ext == ".mdl") { FileSystem* fs = GetSubsystem<FileSystem>(); ResourceCache* cache = GetSubsystem<ResourceCache>(); // mdl files are native file format that doesn't need to be converted // doesn't allow scale, animations legacy primarily for ToonTown if (!fs->Copy(asset_->GetPath(), asset_->GetCachePath() + ".mdl")) { importNode_= 0; return false; } Model* mdl = cache->GetResource<Model>( asset_->GetCachePath() + ".mdl"); if (!mdl) { importNode_= 0; return false; } // Force a reload, though file watchers will catch this delayed and load again cache->ReloadResource(mdl); importNode_->CreateComponent<StaticModel>()->SetModel(mdl); } else { // skip external animations, they will be brought in when importing their // corresponding model if (!modelAssetFilename.Contains("@")) { ImportModel(); if (importAnimations_) { ImportAnimations(); } AnimatedModel* animatedModel = importNode_->GetComponent<AnimatedModel>(); if (animatedModel) { Model* model = animatedModel->GetModel(); if (model && model->GetAnimationCount()) { // resave with animation info File mdlFile(context_); if (!mdlFile.Open(asset_->GetCachePath() + ".mdl", FILE_WRITE)) { ErrorExit("Could not open output file " + asset_->GetCachePath() + ".mdl"); return false; } model->Save(mdlFile); } } } } File outFile(context_); if (!outFile.Open(asset_->GetCachePath(), FILE_WRITE)) ErrorExit("Could not open output file " + asset_->GetCachePath()); importNode_->SaveXML(outFile); importNode_ = 0; return true; }
bool ScriptFile::AddScriptSection(asIScriptEngine* engine, Deserializer& source) { ResourceCache* cache = GetSubsystem<ResourceCache>(); unsigned dataSize = source.GetSize(); SharedArrayPtr<char> buffer(new char[dataSize]); source.Read((void*)buffer.Get(), dataSize); // Pre-parse for includes // Adapted from Angelscript's scriptbuilder add-on Vector<String> includeFiles; unsigned pos = 0; while(pos < dataSize) { int len; asETokenClass t = engine->ParseToken(&buffer[pos], dataSize - pos, &len); if (t == asTC_COMMENT || t == asTC_WHITESPACE) { pos += len; continue; } // Is this a preprocessor directive? if (buffer[pos] == '#') { int start = pos++; asETokenClass t = engine->ParseToken(&buffer[pos], dataSize - pos, &len); if (t == asTC_IDENTIFIER) { String token(&buffer[pos], len); if (token == "include") { pos += len; t = engine->ParseToken(&buffer[pos], dataSize - pos, &len); if (t == asTC_WHITESPACE) { pos += len; t = engine->ParseToken(&buffer[pos], dataSize - pos, &len); } if (t == asTC_VALUE && len > 2 && buffer[pos] == '"') { // Get the include file String includeFile(&buffer[pos+1], len - 2); pos += len; // If the file is not found as it is, add the path of current file but only if it is found there if (!cache->Exists(includeFile)) { String prefixedIncludeFile = GetPath(GetName()) + includeFile; if (cache->Exists(prefixedIncludeFile)) includeFile = prefixedIncludeFile; } String includeFileLower = includeFile.ToLower(); // If not included yet, store it for later processing if (!includeFiles_.Contains(includeFileLower)) { includeFiles_.Insert(includeFileLower); includeFiles.Push(includeFile); } // Overwrite the include directive with space characters to avoid compiler error memset(&buffer[start], ' ', pos - start); } } } } // Don't search includes within statement blocks or between tokens in statements else { int len; // Skip until ; or { whichever comes first while (pos < dataSize && buffer[pos] != ';' && buffer[pos] != '{') { engine->ParseToken(&buffer[pos], 0, &len); pos += len; } // Skip entire statement block if (pos < dataSize && buffer[pos] == '{') { ++pos; // Find the end of the statement block int level = 1; while (level > 0 && pos < dataSize) { asETokenClass t = engine->ParseToken(&buffer[pos], 0, &len); if (t == asTC_KEYWORD) { if (buffer[pos] == '{') ++level; else if(buffer[pos] == '}') --level; } pos += len; } } else ++pos; } } // Process includes first for (unsigned i = 0; i < includeFiles.Size(); ++i) { cache->StoreResourceDependency(this, includeFiles[i]); SharedPtr<File> file = cache->GetFile(includeFiles[i]); if (file) { if (!AddScriptSection(engine, *file)) return false; } else { LOGERROR("Could not process all the include directives in " + GetName() + ": missing " + includeFiles[i]); return false; } } // Then add this section if (scriptModule_->AddScriptSection(source.GetName().CString(), (const char*)buffer.Get(), dataSize) < 0) { LOGERROR("Failed to add script section " + source.GetName()); return false; } SetMemoryUse(GetMemoryUse() + dataSize); return true; }
bool AnimationSet2D::LoadFolders(const XMLElement& rootElem) { ResourceCache* cache = GetSubsystem<ResourceCache>(); bool async = GetAsyncLoadState() == ASYNC_LOADING; String parentPath = GetParentPath(GetName()); String spriteSheetFilePath = parentPath + GetFileName(GetName()) + ".xml"; SpriteSheet2D* spriteSheet = 0; bool hasSpriteSheet = false; // When async loading, request the sprite sheet for background loading but do not actually get it if (!async) spriteSheet = cache->GetResource<SpriteSheet2D>(spriteSheetFilePath, false); else { hasSpriteSheet = cache->Exists(spriteSheetFilePath); if (hasSpriteSheet) cache->BackgroundLoadResource<SpriteSheet2D>(spriteSheetFilePath, false, this); } for (XMLElement folderElem = rootElem.GetChild("folder"); folderElem; folderElem = folderElem.GetNext("folder")) { unsigned folderId = folderElem.GetUInt("id"); for (XMLElement fileElem = folderElem.GetChild("file"); fileElem; fileElem = fileElem.GetNext("file")) { unsigned fileId = fileElem.GetUInt("id"); String fileName = fileElem.GetAttribute("name"); // When async loading, request the sprites for background loading but do not actually get them if (!async) { SharedPtr<Sprite2D> sprite; if (spriteSheet) sprite = spriteSheet->GetSprite(GetFileName(fileName)); else sprite = (cache->GetResource<Sprite2D>(parentPath + fileName)); if (!sprite) { LOGERROR("Could not load sprite " + fileName); return false; } Vector2 hotSpot(0.0f, 1.0f); if (fileElem.HasAttribute("pivot_x")) hotSpot.x_ = fileElem.GetFloat("pivot_x"); if (fileElem.HasAttribute("pivot_y")) hotSpot.y_ = fileElem.GetFloat("pivot_y"); // If sprite is trimmed, recalculate hot spot const IntVector2& offset = sprite->GetOffset(); if (offset != IntVector2::ZERO) { int width = fileElem.GetInt("width"); int height = fileElem.GetInt("height"); float pivotX = width * hotSpot.x_; float pivotY = height * (1.0f - hotSpot.y_); const IntRect& rectangle = sprite->GetRectangle(); hotSpot.x_ = (offset.x_ + pivotX) / rectangle.Width(); hotSpot.y_ = 1.0f - (offset.y_ + pivotY) / rectangle.Height(); } sprite->SetHotSpot(hotSpot); sprites_[(folderId << 16) + fileId] = sprite; } else if (!hasSpriteSheet) cache->BackgroundLoadResource<Sprite2D>(parentPath + fileName, true, this); } } return true; }