void UI::LoadDefaultPlayerSkin() { ResourceCache* cache = GetSubsystem<ResourceCache>(); String skin = "DefaultUI/skin/skin.tb.txt"; String overrideSkin; // see if we have an override skin SharedPtr<File> skinFile = cache->GetFile("UI/Skin/skin.ui.txt", false); if (skinFile.NotNull()) { skinFile->Close(); skin = "UI/Skin/skin.ui.txt"; } // see if we have an override skin SharedPtr<File> overrideFile = cache->GetFile("UI/Skin/Override/skin.ui.txt", false); if (overrideFile.NotNull()) { overrideFile->Close(); overrideSkin = "UI/Skin/Override/skin.ui.txt"; } LoadSkin(skin, overrideSkin); if (skin == "DefaultUI/skin/skin.tb.txt") { AddFont("DefaultUI/fonts/vera.ttf", "Vera"); SetDefaultFont("Vera", 12); } }
static int js_module_read_file(duk_context* ctx) { JSVM* vm = JSVM::GetJSVM(ctx); ResourceCache* cache = vm->GetContext()->GetSubsystem<ResourceCache>(); String path = duk_to_string(ctx, 0); SharedPtr<File> file = cache->GetFile(path); if (!file->IsOpen()) { duk_push_string(ctx, "Unable to open module file"); duk_throw(ctx); return 0; } unsigned size = file->GetSize(); SharedArrayPtr<char> data; data = new char[size + 1]; data[size] = '\0'; file->Read(data, size); duk_push_string(ctx, data); return 1; }
void UI::TBFileReader(const char* filename, void** data, unsigned* length) { *data = 0; *length = 0; ResourceCache* cache = uiContext_->GetSubsystem<ResourceCache>(); SharedPtr<File> file = cache->GetFile(filename); if (!file || !file->IsOpen()) { LOGERRORF("UI::TBFileReader: Unable to load file: %s", filename); return; } unsigned size = file->GetSize(); if (!size) return; void* _data = malloc(size); if (!_data) return; if (file->Read(_data, size) != size) { free(_data); return; } *length = size; *data = _data; }
UIAbout::UIAbout(Context* context): UIModalOpWindow(context) { UI* tbui = GetSubsystem<UI>(); window_->SetText("About the Atomic Game Engine"); tbui->LoadResourceFile(window_->GetContentRoot(), "AtomicEditor/editor/ui/about.tb.txt"); TBEditField* age_license = window_->GetWidgetByIDAndType<TBEditField>(TBIDC("age_license")); assert(age_license); TBEditField* thirdparty_license = window_->GetWidgetByIDAndType<TBEditField>(TBIDC("thirdparty_license")); assert(thirdparty_license); TBEditField* externaltool_license = window_->GetWidgetByIDAndType<TBEditField>(TBIDC("externaltool_license")); assert(externaltool_license); TBEditField* about_text = window_->GetWidgetByIDAndType<TBEditField>(TBIDC("about_text")); assert(about_text); ResourceCache* cache = GetSubsystem<ResourceCache>(); SharedPtr<File> file = cache->GetFile("AtomicEditor/eulas/atomic_game_engine_eula.txt"); String text; file->ReadText(text); age_license->SetText(text.CString()); file = cache->GetFile("AtomicEditor/eulas/atomic_thirdparty_eula.txt"); file->ReadText(text); thirdparty_license->SetText(text.CString()); file = cache->GetFile("AtomicEditor/eulas/atomic_external_tools_eula.txt"); file->ReadText(text); externaltool_license->SetText(text.CString()); GenerateAboutText(text); about_text->SetText(text.CString()); window_->ResizeToFitContent(); Center(); TBTabContainer* container = window_->GetWidgetByIDAndType<TBTabContainer>(TBIDC("tabcontainer")); assert(container); container->SetValue(0); }
UIEulaAgreement::UIEulaAgreement(Context* context): UIModalOpWindow(context) { UI* tbui = GetSubsystem<UI>(); window_->SetSettings(WINDOW_SETTINGS_DEFAULT & ~WINDOW_SETTINGS_CLOSE_BUTTON); window_->SetText("License Agreement"); tbui->LoadResourceFile(window_->GetContentRoot(), "ClockworkEditor/editor/ui/eulaagreement.tb.txt"); eulaCheck_ = window_->GetWidgetByIDAndType<TBCheckBox>(TBIDC("eula_check")); assert(eulaCheck_); TBEditField* age_license = window_->GetWidgetByIDAndType<TBEditField>(TBIDC("age_license")); assert(age_license); TBEditField* thirdparty_license = window_->GetWidgetByIDAndType<TBEditField>(TBIDC("thirdparty_license")); assert(thirdparty_license); TBEditField* externaltool_license = window_->GetWidgetByIDAndType<TBEditField>(TBIDC("externaltool_license")); assert(externaltool_license); ResourceCache* cache = GetSubsystem<ResourceCache>(); SharedPtr<File> file = cache->GetFile("ClockworkEditor/eulas/clockwork_game_engine_eula.txt"); String text; file->ReadText(text); age_license->SetText(text.CString()); file = cache->GetFile("ClockworkEditor/eulas/clockwork_thirdparty_eula.txt"); file->ReadText(text); thirdparty_license->SetText(text.CString()); file = cache->GetFile("ClockworkEditor/eulas/clockwork_external_tools_eula.txt"); file->ReadText(text); externaltool_license->SetText(text.CString()); window_->ResizeToFitContent(); Center(); TBTabContainer* container = window_->GetWidgetByIDAndType<TBTabContainer>(TBIDC("tabcontainer")); assert(container); container->SetValue(0); }
void World::InitScene(Context* context_, String sceneFileNam, EWORLDS worldType_) { context = context_; scene = SharedPtr<Scene>(new Scene(context_)); ResourceCache* cache = context_->GetSubsystem<ResourceCache>(); SharedPtr<File> sceneFile = cache->GetFile("Scenes/" + sceneFileNam); scene->LoadXML(*sceneFile); isActive = false; worldType = worldType_; }
bool CEJavascript::ReadZeroTerminatedSourceFile(const String& path, String& source) { ResourceCache* cache = GetSubsystem<ResourceCache>(); SharedPtr<File> file = cache->GetFile(path); if (file.Null() || !file->IsOpen()) return false; file->ReadText(source); return true; }
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; }
bool Shader::ProcessSource(String& code, Deserializer& source) { ResourceCache* cache = GetSubsystem<ResourceCache>(); // If the source if a non-packaged file, store the timestamp File* file = dynamic_cast<File*>(&source); if (file && !file->IsPackaged()) { FileSystem* fileSystem = GetSubsystem<FileSystem>(); String fullName = cache->GetResourceFileName(file->GetName()); unsigned fileTimeStamp = fileSystem->GetLastModifiedTime(fullName); if (fileTimeStamp > timeStamp_) timeStamp_ = fileTimeStamp; } // Store resource dependencies for includes so that we know to reload if any of them changes if (source.GetName() != GetName()) cache->StoreResourceDependency(this, source.GetName()); while (!source.IsEof()) { String line = source.ReadLine(); if (line.StartsWith("#include")) { String includeFileName = GetPath(source.GetName()) + line.Substring(9).Replaced("\"", "").Trimmed(); SharedPtr<File> includeFile = cache->GetFile(includeFileName); if (!includeFile) return false; // Add the include file into the current code recursively if (!ProcessSource(code, *includeFile)) return false; } else { code += line; code += "\n"; } } // Finally insert an empty line to mark the space between files code += "\n"; return true; }
void SceneAndUILoad::CreateScene() { ResourceCache* cache = GetSubsystem<ResourceCache>(); scene_ = new Scene(context_); // Load scene content prepared in the editor (XML format). GetFile() returns an open file from the resource system // which scene.LoadXML() will read SharedPtr<File> file = cache->GetFile("Scenes/SceneLoadExample.xml"); scene_->LoadXML(*file); // Create the camera (not included in the scene file) cameraNode_ = scene_->CreateChild("Camera"); cameraNode_->CreateComponent<Camera>(); // Set an initial position for the camera scene node above the plane cameraNode_->SetPosition(Vector3(0.0f, 2.0f, -10.0f)); }
Scene* Player::LoadScene(const String& filename, Camera *camera) { ResourceCache* cache = GetSubsystem<ResourceCache>(); SharedPtr<File> file = cache->GetFile(filename); if (!file || !file->IsOpen()) { return 0; } Scene* scene = new Scene(context_); if (!scene->LoadXML(*file)) { scene->ReleaseRef(); return 0; } if (currentScene_.Null()) { currentScene_ = scene; if(!camera) { PODVector<Node*> cameraNodes; scene->GetChildrenWithComponent(cameraNodes, Camera::GetTypeStatic(), true); if (cameraNodes.Size()) { camera = cameraNodes[0]->GetComponent<Camera>(); } } viewport_->SetScene(scene); if (camera) viewport_->SetCamera(camera); } return scene; }
void StaticModel::ApplyMaterialList(const String& fileName) { String useFileName = fileName; if (useFileName.Trimmed().Empty() && model_) useFileName = ReplaceExtension(model_->GetName(), ".txt"); ResourceCache* cache = GetSubsystem<ResourceCache>(); SharedPtr<File> file = cache->GetFile(useFileName, false); if (!file) return; unsigned index = 0; while (!file->IsEof() && index < batches_.Size()) { Material* material = cache->GetResource<Material>(file->ReadLine()); if (material) SetMaterial(index, material); ++index; } }
Scene* Player::LoadScene(const String& filename, Camera *camera) { ResourceCache* cache = GetSubsystem<ResourceCache>(); SharedPtr<File> file = cache->GetFile(filename); if (!file || !file->IsOpen()) { return 0; } Scene* scene = new Scene(context_); VariantMap eventData; eventData[PlayerSceneLoadBegin::P_SCENE] = scene; scene->SendEvent(E_PLAYERSCENELOADBEGIN, eventData); if (!scene->LoadXML(*file)) { eventData[PlayerSceneLoadEnd::P_SCENE] = scene; eventData[PlayerSceneLoadEnd::P_SUCCESS] = false; scene->SendEvent(E_PLAYERSCENELOADEND, eventData); scene->ReleaseRef(); return 0; } eventData[PlayerSceneLoadEnd::P_SCENE] = scene; eventData[PlayerSceneLoadEnd::P_SUCCESS] = true; scene->SendEvent(E_PLAYERSCENELOADEND, eventData); loadedScenes_.Push(SharedPtr<Scene>(scene)); if (currentScene_.Null()) { SetCurrentScene(scene, camera); } return scene; }
void ResourceOps::HandleCreate2DLevel(const String& resourcePath, const String& resourceName, bool navigateToResource, bool reportError) { Editor* editor = GetSubsystem<Editor>(); if (!CheckCreate2DLevel(resourcePath, resourceName, reportError)) return; ResourceCache* cache = GetSubsystem<ResourceCache>(); SharedPtr<File> srcFile = cache->GetFile("ClockworkEditor/templates/template_empty.tmx"); if (srcFile.Null() || !srcFile->IsOpen()) { editor->PostModalError("Create Script Error", "Could not open module template"); return; } String fullpath = resourcePath + resourceName; if (!resourceName.EndsWith(".tmx")) fullpath += ".tmx"; if (!CopyFile(srcFile, fullpath)) { String errorMsg; errorMsg.AppendWithFormat("Error copying template:\n\n%s\n\nto:\n\n%s", "ClockworkEditor/template_empty.tmx", fullpath.CString()); editor->PostModalError("Create 2D Level Error", errorMsg); return; } if (navigateToResource) { //ResourceFrame* rframe = GetSubsystem<MainFrame>()->GetResourceFrame(); //rframe->EditResource(fullpath); } GetSubsystem<MainFrame>()->GetProjectFrame()->Refresh(); }
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; }
// 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); }
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 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; }
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 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; } }