bool Scene::Load(Deserializer& source, bool setInstanceDefault) { PROFILE(LoadScene); StopAsyncLoading(); // Check ID if (source.ReadFileID() != "USCN") { LOGERROR(source.GetName() + " is not a valid scene file"); return false; } LOGINFO("Loading scene from " + source.GetName()); Clear(); // Load the whole scene, then perform post-load if successfully loaded if (Node::Load(source, setInstanceDefault)) { FinishLoading(&source); return true; } else return false; }
bool AnimationSet2D::BeginLoad(Deserializer& source) { loadXMLFile_ = new XMLFile(context_); if (!loadXMLFile_->Load(source)) { LOGERROR("Load XML failed " + source.GetName()); loadXMLFile_.Reset(); return false; } XMLElement rootElem = loadXMLFile_->GetRoot("spriter_data"); if (!rootElem) { LOGERROR("Invalid spriter file " + source.GetName()); loadXMLFile_.Reset(); return false; } // When async loading, preprocess folders for spritesheet / sprite files and request them for background loading if (GetAsyncLoadState() == ASYNC_LOADING) { if (!LoadFolders(rootElem)) { loadXMLFile_.Reset(); return false; } } return true; }
bool JSONFile::BeginLoad(Deserializer& source) { unsigned dataSize = source.GetSize(); if (!dataSize && !source.GetName().Empty()) { LOGERROR("Zero sized JSON data in " + source.GetName()); return false; } SharedArrayPtr<char> buffer(new char[dataSize + 1]); if (source.Read(buffer.Get(), dataSize) != dataSize) return false; buffer[dataSize] = '\0'; rapidjson::Document document; if (document.Parse<0>(buffer).HasParseError()) { LOGERROR("Could not parse JSON data from " + source.GetName()); return false; } ToJSONValue(root_, document); SetMemoryUse(dataSize); return true; }
bool XMLFile::Load(Deserializer& source) { PROFILE(LoadXMLFile); unsigned dataSize = source.GetSize(); if (!dataSize && !source.GetName().Empty()) { LOGERROR("Zero sized XML data in " + source.GetName()); return false; } SharedArrayPtr<char> buffer(new char[dataSize]); if (source.Read(buffer.Get(), dataSize) != dataSize) return false; if (!document_->load_buffer(buffer.Get(), dataSize)) { LOGERROR("Could not parse XML data from " + source.GetName()); return false; } // Note: this probably does not reflect internal data structure size accurately SetMemoryUse(dataSize); return true; }
bool TmxFile2D::BeginLoad(Deserializer& source) { if (GetName().Empty()) SetName(source.GetName()); loadXMLFile_ = new XMLFile(context_); if (!loadXMLFile_->Load(source)) { URHO3D_LOGERROR("Load XML failed " + source.GetName()); loadXMLFile_.Reset(); return false; } XMLElement rootElem = loadXMLFile_->GetRoot("map"); if (!rootElem) { URHO3D_LOGERROR("Invalid tmx file " + source.GetName()); loadXMLFile_.Reset(); return false; } // If we're async loading, request the texture now. Finish during EndLoad(). if (GetAsyncLoadState() == ASYNC_LOADING) { for (XMLElement tileSetElem = rootElem.GetChild("tileset"); tileSetElem; tileSetElem = tileSetElem.GetNext("tileset")) { // Tile set defined in TSX file if (tileSetElem.HasAttribute("source")) { String source = tileSetElem.GetAttribute("source"); SharedPtr<XMLFile> tsxXMLFile = LoadTSXFile(source); if (!tsxXMLFile) return false; tsxXMLFiles_[source] = tsxXMLFile; String textureFilePath = GetParentPath(GetName()) + tsxXMLFile->GetRoot("tileset").GetChild("image").GetAttribute("source"); GetSubsystem<ResourceCache>()->BackgroundLoadResource<Texture2D>(textureFilePath, true, this); } else { String textureFilePath = GetParentPath(GetName()) + tileSetElem.GetChild("image").GetAttribute("source"); GetSubsystem<ResourceCache>()->BackgroundLoadResource<Texture2D>(textureFilePath, true, this); } } for (XMLElement imageLayerElem = rootElem.GetChild("imagelayer"); imageLayerElem; imageLayerElem = imageLayerElem.GetNext("imagelayer")) { String textureFilePath = GetParentPath(GetName()) + imageLayerElem.GetChild("image").GetAttribute("source"); GetSubsystem<ResourceCache>()->BackgroundLoadResource<Texture2D>(textureFilePath, true, this); } } return true; }
bool XMLFile::BeginLoad(Deserializer& source) { unsigned dataSize = source.GetSize(); if (!dataSize && !source.GetName().Empty()) { URHO3D_LOGERROR("Zero sized XML data in " + source.GetName()); return false; } SharedArrayPtr<char> buffer(new char[dataSize]); if (source.Read(buffer.Get(), dataSize) != dataSize) return false; if (!document_->load_buffer(buffer.Get(), dataSize)) { URHO3D_LOGERROR("Could not parse XML data from " + source.GetName()); document_->reset(); return false; } XMLElement rootElem = GetRoot(); String inherit = rootElem.GetAttribute("inherit"); if (!inherit.Empty()) { // The existence of this attribute indicates this is an RFC 5261 patch file ResourceCache* cache = GetSubsystem<ResourceCache>(); // If being async loaded, GetResource() is not safe, so use GetTempResource() instead XMLFile* inheritedXMLFile = GetAsyncLoadState() == ASYNC_DONE ? cache->GetResource<XMLFile>(inherit) : cache->GetTempResource<XMLFile>(inherit); if (!inheritedXMLFile) { URHO3D_LOGERRORF("Could not find inherited XML file: %s", inherit.CString()); return false; } // Patch this XMLFile and leave the original inherited XMLFile as it is pugi::xml_document* patchDocument = document_; document_ = new pugi::xml_document(); document_->reset(*inheritedXMLFile->document_); Patch(rootElem); delete patchDocument; // Store resource dependencies so we know when to reload/repatch when the inherited resource changes cache->StoreResourceDependency(this, inherit); // Approximate patched data size dataSize += inheritedXMLFile->GetMemoryUse(); } // Note: this probably does not reflect internal data structure size accurately SetMemoryUse(dataSize); return true; }
bool Sound::LoadOggVorbis(Deserializer& source) { unsigned dataSize = source.GetSize(); SharedArrayPtr<signed char> data(new signed char[dataSize]); source.Read(data.Get(), dataSize); // Check for validity of data int error; stb_vorbis* vorbis = stb_vorbis_open_memory((unsigned char*)data.Get(), dataSize, &error, 0); if (!vorbis) { LOGERROR("Could not read Ogg Vorbis data from " + source.GetName()); return false; } // Store length, frequency and stereo flag stb_vorbis_info info = stb_vorbis_get_info(vorbis); compressedLength_ = stb_vorbis_stream_length_in_seconds(vorbis); frequency_ = info.sample_rate; stereo_ = info.channels > 1; stb_vorbis_close(vorbis); data_ = data; dataSize_ = dataSize; sixteenBit_ = true; compressed_ = true; SetMemoryUse(dataSize); return true; }
bool Sprite2D::BeginLoad(Deserializer& source) { if (GetName().Empty()) SetName(source.GetName()); // Reload if (texture_) loadTexture_ = texture_; else { loadTexture_ = new Texture2D(context_); loadTexture_->SetName(GetName()); } // In case we're async loading, only call BeginLoad() for the texture (load image but do not upload to GPU) if (!loadTexture_->BeginLoad(source)) { // Reload failed if (loadTexture_ == texture_) texture_.Reset(); loadTexture_.Reset(); return false; } return true; }
bool PListFile::BeginLoad(Deserializer& source) { if (GetName().Empty()) SetName(source.GetName()); XMLFile xmlFile(context_); if (!xmlFile.Load(source)) { URHO3D_LOGERROR("Could not load property list"); return false; } XMLElement plistElem = xmlFile.GetRoot("plist"); if (!plistElem) { URHO3D_LOGERROR("Invalid property list file"); return false; } root_.Clear(); XMLElement dictElem = plistElem.GetChild("dict"); if (!LoadDict(root_, dictElem)) return false; SetMemoryUse(source.GetSize()); return true; }
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 Scene::FinishSaving(Serializer* dest) const { Deserializer* ptr = dynamic_cast<Deserializer*>(dest); if (ptr) { fileName_ = ptr->GetName(); checksum_ = ptr->GetChecksum(); } }
bool Sound::BeginLoad(Deserializer& source) { PROFILE(LoadSound); bool success = false; if (GetExtension(source.GetName()) == ".ogg") success = LoadOggVorbis(source); else if (GetExtension(source.GetName()) == ".wav") success = LoadWav(source); else success = LoadRaw(source); // Load optional parameters if (success) LoadParameters(); return success; }
bool SpriteSheet2D::BeginLoad(Deserializer& source) { if (GetName().Empty()) SetName(source.GetName()); loadTextureName_.Clear(); spriteMapping_.Clear(); String extension = GetExtension(source.GetName()); if (extension == ".plist") return BeginLoadFromPListFile(source); if (extension == ".xml") return BeginLoadFromXMLFile(source); URHO3D_LOGERROR("Unsupported file type"); return false; }
bool Scene::SaveXML(Serializer& dest) const { PROFILE(SaveSceneXML); SharedPtr<XMLFile> xml(new XMLFile(context_)); XMLElement rootElem = xml->CreateRoot("scene"); if (!SaveXML(rootElem)) return false; Deserializer* ptr = dynamic_cast<Deserializer*>(&dest); if (ptr) LOGINFO("Saving scene to " + ptr->GetName()); if (xml->Save(dest)) { FinishSaving(&dest); return true; } else return false; }
bool Scene::LoadXML(Deserializer& source) { PROFILE(LoadSceneXML); StopAsyncLoading(); SharedPtr<XMLFile> xml(new XMLFile(context_)); if (!xml->Load(source)) return false; LOGINFO("Loading scene from " + source.GetName()); Clear(); if (Node::LoadXML(xml->GetRoot())) { FinishLoading(&source); return true; } else return false; }
bool Scene::LoadJSON(Deserializer& source) { URHO3D_PROFILE(LoadSceneJSON); StopAsyncLoading(); SharedPtr<JSONFile> json(new JSONFile(context_)); if (!json->Load(source)) return false; URHO3D_LOGINFO("Loading scene from " + source.GetName()); Clear(); if (Node::LoadJSON(json->GetRoot())) { FinishLoading(&source); return true; } else return false; }
bool Scene::Save(Serializer& dest) const { PROFILE(SaveScene); // Write ID first if (!dest.WriteFileID("USCN")) { LOGERROR("Could not save scene, writing to stream failed"); return false; } Deserializer* ptr = dynamic_cast<Deserializer*>(&dest); if (ptr) LOGINFO("Saving scene to " + ptr->GetName()); if (Node::Save(dest)) { FinishSaving(&dest); return true; } else return false; }
bool Scene::SaveJSON(Serializer& dest, const String& indentation) const { URHO3D_PROFILE(SaveSceneJSON); SharedPtr<JSONFile> json(new JSONFile(context_)); JSONValue rootVal; if (!SaveJSON(rootVal)) return false; Deserializer* ptr = dynamic_cast<Deserializer*>(&dest); if (ptr) URHO3D_LOGINFO("Saving scene to " + ptr->GetName()); json->GetRoot() = rootVal; if (json->Save(dest, indentation)) { FinishSaving(&dest); return true; } else return false; }
bool Model::BeginLoad(Deserializer& source) { // Check ID String id = source.ReadFileID(); bool umdl = false; if (id == "UMDL") // we only support UMDL for some current legacy mdl's (ToonTown) umdl = true; if (!umdl && id != "AMDL") { LOGERROR(source.GetName() + " is not a valid model file"); return false; } geometries_.Clear(); geometryBoneMappings_.Clear(); geometryCenters_.Clear(); morphs_.Clear(); vertexBuffers_.Clear(); indexBuffers_.Clear(); unsigned memoryUse = sizeof(Model); bool async = GetAsyncLoadState() == ASYNC_LOADING; // Read vertex buffers unsigned numVertexBuffers = source.ReadUInt(); vertexBuffers_.Reserve(numVertexBuffers); morphRangeStarts_.Resize(numVertexBuffers); morphRangeCounts_.Resize(numVertexBuffers); loadVBData_.Resize(numVertexBuffers); for (unsigned i = 0; i < numVertexBuffers; ++i) { unsigned vertexCount = source.ReadUInt(); unsigned elementMask = source.ReadUInt(); morphRangeStarts_[i] = source.ReadUInt(); morphRangeCounts_[i] = source.ReadUInt(); SharedPtr<VertexBuffer> buffer(new VertexBuffer(context_)); unsigned vertexSize = VertexBuffer::GetVertexSize(elementMask); // Prepare vertex buffer data to be uploaded during EndLoad() if (async) { loadVBData_[i].vertexCount_ = vertexCount; loadVBData_[i].elementMask_ = elementMask; loadVBData_[i].dataSize_ = vertexCount * vertexSize; loadVBData_[i].data_ = new unsigned char[loadVBData_[i].dataSize_]; source.Read(loadVBData_[i].data_.Get(), loadVBData_[i].dataSize_); } else { // If not async loading, use locking to avoid extra allocation & copy loadVBData_[i].data_.Reset(); // Make sure no previous data buffer->SetShadowed(true); buffer->SetSize(vertexCount, elementMask); void* dest = buffer->Lock(0, vertexCount); source.Read(dest, vertexCount * vertexSize); buffer->Unlock(); } memoryUse += sizeof(VertexBuffer) + vertexCount * vertexSize; vertexBuffers_.Push(buffer); } // Read index buffers unsigned numIndexBuffers = source.ReadUInt(); indexBuffers_.Reserve(numIndexBuffers); loadIBData_.Resize(numIndexBuffers); for (unsigned i = 0; i < numIndexBuffers; ++i) { unsigned indexCount = source.ReadUInt(); unsigned indexSize = source.ReadUInt(); SharedPtr<IndexBuffer> buffer(new IndexBuffer(context_)); // Prepare index buffer data to be uploaded during EndLoad() if (async) { loadIBData_[i].indexCount_ = indexCount; loadIBData_[i].indexSize_ = indexSize; loadIBData_[i].dataSize_ = indexCount * indexSize; loadIBData_[i].data_ = new unsigned char[loadIBData_[i].dataSize_]; source.Read(loadIBData_[i].data_.Get(), loadIBData_[i].dataSize_); } else { // If not async loading, use locking to avoid extra allocation & copy loadIBData_[i].data_.Reset(); // Make sure no previous data buffer->SetShadowed(true); buffer->SetSize(indexCount, indexSize > sizeof(unsigned short)); void* dest = buffer->Lock(0, indexCount); source.Read(dest, indexCount * indexSize); buffer->Unlock(); } memoryUse += sizeof(IndexBuffer) + indexCount * indexSize; indexBuffers_.Push(buffer); } // Read geometries unsigned numGeometries = source.ReadUInt(); geometries_.Reserve(numGeometries); geometryBoneMappings_.Reserve(numGeometries); geometryCenters_.Reserve(numGeometries); loadGeometries_.Resize(numGeometries); for (unsigned i = 0; i < numGeometries; ++i) { // Read bone mappings unsigned boneMappingCount = source.ReadUInt(); PODVector<unsigned> boneMapping(boneMappingCount); for (unsigned j = 0; j < boneMappingCount; ++j) boneMapping[j] = source.ReadUInt(); geometryBoneMappings_.Push(boneMapping); unsigned numLodLevels = source.ReadUInt(); Vector<SharedPtr<Geometry> > geometryLodLevels; geometryLodLevels.Reserve(numLodLevels); loadGeometries_[i].Resize(numLodLevels); for (unsigned j = 0; j < numLodLevels; ++j) { float distance = source.ReadFloat(); PrimitiveType type = (PrimitiveType)source.ReadUInt(); unsigned vbRef = source.ReadUInt(); unsigned ibRef = source.ReadUInt(); unsigned indexStart = source.ReadUInt(); unsigned indexCount = source.ReadUInt(); if (vbRef >= vertexBuffers_.Size()) { LOGERROR("Vertex buffer index out of bounds"); loadVBData_.Clear(); loadIBData_.Clear(); loadGeometries_.Clear(); return false; } if (ibRef >= indexBuffers_.Size()) { LOGERROR("Index buffer index out of bounds"); loadVBData_.Clear(); loadIBData_.Clear(); loadGeometries_.Clear(); return false; } SharedPtr<Geometry> geometry(new Geometry(context_)); geometry->SetLodDistance(distance); // Prepare geometry to be defined during EndLoad() loadGeometries_[i][j].type_ = type; loadGeometries_[i][j].vbRef_ = vbRef; loadGeometries_[i][j].ibRef_ = ibRef; loadGeometries_[i][j].indexStart_ = indexStart; loadGeometries_[i][j].indexCount_ = indexCount; geometryLodLevels.Push(geometry); memoryUse += sizeof(Geometry); } geometries_.Push(geometryLodLevels); } // Read morphs unsigned numMorphs = source.ReadUInt(); morphs_.Reserve(numMorphs); for (unsigned i = 0; i < numMorphs; ++i) { ModelMorph newMorph; newMorph.name_ = source.ReadString(); newMorph.nameHash_ = newMorph.name_; newMorph.weight_ = 0.0f; unsigned numBuffers = source.ReadUInt(); for (unsigned j = 0; j < numBuffers; ++j) { VertexBufferMorph newBuffer; unsigned bufferIndex = source.ReadUInt(); newBuffer.elementMask_ = source.ReadUInt(); newBuffer.vertexCount_ = source.ReadUInt(); // Base size: size of each vertex index unsigned vertexSize = sizeof(unsigned); // Add size of individual elements if (newBuffer.elementMask_ & MASK_POSITION) vertexSize += sizeof(Vector3); if (newBuffer.elementMask_ & MASK_NORMAL) vertexSize += sizeof(Vector3); if (newBuffer.elementMask_ & MASK_TANGENT) vertexSize += sizeof(Vector3); newBuffer.dataSize_ = newBuffer.vertexCount_ * vertexSize; newBuffer.morphData_ = new unsigned char[newBuffer.dataSize_]; source.Read(&newBuffer.morphData_[0], newBuffer.vertexCount_ * vertexSize); newMorph.buffers_[bufferIndex] = newBuffer; memoryUse += sizeof(VertexBufferMorph) + newBuffer.vertexCount_ * vertexSize; } morphs_.Push(newMorph); memoryUse += sizeof(ModelMorph); } // Read skeleton skeleton_.Load(source); memoryUse += skeleton_.GetNumBones() * sizeof(Bone); // Read bounding box boundingBox_ = source.ReadBoundingBox(); // Read geometry centers for (unsigned i = 0; i < geometries_.Size() && !source.IsEof(); ++i) geometryCenters_.Push(source.ReadVector3()); while (geometryCenters_.Size() < geometries_.Size()) geometryCenters_.Push(Vector3::ZERO); memoryUse += sizeof(Vector3) * geometries_.Size(); if (umdl) { SetMemoryUse(memoryUse); return true; } // MODEL_VERSION unsigned version = source.ReadUInt(); ResourceRefList animList = source.ReadResourceRefList(); animationsResources_.Clear(); ResourceCache* cache = GetSubsystem<ResourceCache>(); for (unsigned i = 0; i < animList.names_.Size(); ++i) { AddAnimationResource(cache->GetResource<Animation>(animList.names_[i])); } SetMemoryUse(memoryUse); return true; }
bool Animation::BeginLoad(Deserializer& source) { unsigned memoryUse = sizeof(Animation); // Check ID if (source.ReadFileID() != "UANI") { URHO3D_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(); memoryUse += tracks * sizeof(AnimationTrack); // Read tracks for (unsigned i = 0; i < tracks; ++i) { AnimationTrack* newTrack = CreateTrack(source.ReadString()); 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"); SharedPtr<XMLFile> file(cache->GetTempResource<XMLFile>(xmlName, false)); 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; } // Optionally read triggers from a JSON file String jsonName = ReplaceExtension(GetName(), ".json"); SharedPtr<JSONFile> jsonFile(cache->GetTempResource<JSONFile>(jsonName, false)); if (jsonFile) { const JSONValue& rootVal = jsonFile->GetRoot(); JSONArray triggerArray = rootVal.Get("triggers").GetArray(); for (unsigned i = 0; i < triggerArray.Size(); i++) { const JSONValue& triggerValue = triggerArray.At(i); JSONValue normalizedTimeValue = triggerValue.Get("normalizedTime"); if (!normalizedTimeValue.IsNull()) AddTrigger(normalizedTimeValue.GetFloat(), true, triggerValue.GetVariant()); else { JSONValue timeVal = triggerValue.Get("time"); if (!timeVal.IsNull()) AddTrigger(timeVal.GetFloat(), false, triggerValue.GetVariant()); } } memoryUse += triggers_.Size() * sizeof(AnimationTriggerPoint); SetMemoryUse(memoryUse); return true; } SetMemoryUse(memoryUse); return true; }
bool Shader::Load(Deserializer& source) { PROFILE(LoadShader); Graphics* graphics = GetSubsystem<Graphics>(); if (!graphics) return false; vsSourceCodeLength_ = 0; psSourceCodeLength_ = 0; SharedPtr<XMLFile> xml(new XMLFile(context_)); if (!xml->Load(source)) return false; XMLElement shaders = xml->GetRoot("shaders"); if (!shaders) { LOGERROR("No shaders element in " + source.GetName()); return false; } { PROFILE(ParseShaderDefinition); if (!vsParser_.Parse(VS, shaders)) { LOGERROR("VS: " + vsParser_.GetErrorMessage()); return false; } if (!psParser_.Parse(PS, shaders)) { LOGERROR("PS: " + psParser_.GetErrorMessage()); return false; } } String path, fileName, extension; SplitPath(GetName(), path, fileName, extension); { PROFILE(LoadShaderSource); if (!ProcessSource(vsSourceCode_, vsSourceCodeLength_, path + fileName + ".vert")) return false; if (!ProcessSource(psSourceCode_, psSourceCodeLength_, path + fileName + ".frag")) return false; } // If variations had already been created, release them and set new source code /// \todo Should also update defines for (HashMap<StringHash, SharedPtr<ShaderVariation> >::Iterator i = vsVariations_.Begin(); i != vsVariations_.End(); ++i) { i->second_->Release(); i->second_->SetSourceCode(vsSourceCode_, vsSourceCodeLength_); } for (HashMap<StringHash, SharedPtr<ShaderVariation> >::Iterator i = psVariations_.Begin(); i != psVariations_.End(); ++i) { i->second_->Release(); i->second_->SetSourceCode(psSourceCode_, psSourceCodeLength_); } SetMemoryUse(sizeof(Shader) + 2 * sizeof(ShaderParser) + (vsVariations_.Size() + psVariations_.Size()) * sizeof(ShaderVariation)); return true; }
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 Sound::LoadWav(Deserializer& source) { WavHeader header; // Try to open memset(&header, 0, sizeof header); source.Read(&header.riffText_, 4); header.totalLength_ = source.ReadUInt(); source.Read(&header.waveText_, 4); if (memcmp("RIFF", header.riffText_, 4) || memcmp("WAVE", header.waveText_, 4)) { LOGERROR("Could not read WAV data from " + source.GetName()); return false; } // Search for the FORMAT chunk for (;;) { source.Read(&header.formatText_, 4); header.formatLength_ = source.ReadUInt(); if (!memcmp("fmt ", &header.formatText_, 4)) break; source.Seek(source.GetPosition() + header.formatLength_); if (!header.formatLength_ || source.GetPosition() >= source.GetSize()) { LOGERROR("Could not read WAV data from " + source.GetName()); return false; } } // Read the FORMAT chunk header.format_ = source.ReadUShort(); header.channels_ = source.ReadUShort(); header.frequency_ = source.ReadUInt(); header.avgBytes_ = source.ReadUInt(); header.blockAlign_ = source.ReadUShort(); header.bits_ = source.ReadUShort(); // Skip data if the format chunk was bigger than what we use source.Seek(source.GetPosition() + header.formatLength_ - 16); // Check for correct format if (header.format_ != 1) { LOGERROR("Could not read WAV data from " + source.GetName()); return false; } // Search for the DATA chunk for (;;) { source.Read(&header.dataText_, 4); header.dataLength_ = source.ReadUInt(); if (!memcmp("data", &header.dataText_, 4)) break; source.Seek(source.GetPosition() + header.dataLength_); if (!header.dataLength_ || source.GetPosition() >= source.GetSize()) { LOGERROR("Could not read WAV data from " + source.GetName()); return false; } } // Allocate sound and load audio data unsigned length = header.dataLength_; SetSize(length); SetFormat(header.frequency_, header.bits_ == 16, header.channels_ == 2); source.Read(data_.Get(), length); // Convert 8-bit audio to signed if (!sixteenBit_) { for (unsigned i = 0; i < length; ++i) data_[i] -= 128; } 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 ParticleEffect2D::BeginLoad(Deserializer& source) { if (GetName().Empty()) SetName(source.GetName()); loadSpriteName_.Clear(); XMLFile xmlFile(context_); if (!xmlFile.Load(source)) return false; XMLElement rootElem = xmlFile.GetRoot("particleEmitterConfig"); if (!rootElem) return false; String texture = rootElem.GetChild("texture").GetAttribute("name"); loadSpriteName_ = GetParentPath(GetName()) + texture; // If async loading, request the sprite beforehand if (GetAsyncLoadState() == ASYNC_LOADING) GetSubsystem<ResourceCache>()->BackgroundLoadResource<Sprite2D>(loadSpriteName_, true, this); sourcePositionVariance_ = ReadVector2(rootElem, "sourcePositionVariance"); speed_ = ReadFloat(rootElem, "speed"); speedVariance_ = ReadFloat(rootElem, "speedVariance"); particleLifeSpan_ = Max(0.01f, ReadFloat(rootElem, "particleLifeSpan")); particleLifespanVariance_ = ReadFloat(rootElem, "particleLifespanVariance"); angle_ = ReadFloat(rootElem, "angle"); angleVariance_ = ReadFloat(rootElem, "angleVariance"); gravity_ = ReadVector2(rootElem, "gravity"); radialAcceleration_ = ReadFloat(rootElem, "radialAcceleration"); tangentialAcceleration_ = ReadFloat(rootElem, "tangentialAcceleration"); radialAccelVariance_ = ReadFloat(rootElem, "radialAccelVariance"); tangentialAccelVariance_ = ReadFloat(rootElem, "tangentialAccelVariance"); startColor_ = ReadColor(rootElem, "startColor"); startColorVariance_ = ReadColor(rootElem, "startColorVariance"); finishColor_ = ReadColor(rootElem, "finishColor"); finishColorVariance_ = ReadColor(rootElem, "finishColorVariance"); maxParticles_ = ReadInt(rootElem, "maxParticles"); startParticleSize_ = ReadFloat(rootElem, "startParticleSize"); startParticleSizeVariance_ = ReadFloat(rootElem, "startParticleSizeVariance"); finishParticleSize_ = ReadFloat(rootElem, "finishParticleSize"); // Typo in pex file finishParticleSizeVariance_ = ReadFloat(rootElem, "FinishParticleSizeVariance"); duration_ = M_INFINITY; if (rootElem.HasChild("duration")) { float duration = ReadFloat(rootElem, "duration"); if (duration > 0.0f) duration_ = duration; } emitterType_ = (EmitterType2D)ReadInt(rootElem, "emitterType"); maxRadius_ = ReadFloat(rootElem, "maxRadius"); maxRadiusVariance_ = ReadFloat(rootElem, "maxRadiusVariance"); minRadius_ = ReadFloat(rootElem, "minRadius"); minRadiusVariance_ = ReadFloat(rootElem, "minRadiusVariance"); rotatePerSecond_ = ReadFloat(rootElem, "rotatePerSecond"); rotatePerSecondVariance_ = ReadFloat(rootElem, "rotatePerSecondVariance"); int blendFuncSource = ReadInt(rootElem, "blendFuncSource"); int blendFuncDestination = ReadInt(rootElem, "blendFuncDestination"); blendMode_ = BLEND_ALPHA; for (int i = 0; i < MAX_BLENDMODES; ++i) { if (blendFuncSource == srcBlendFuncs[i] && blendFuncDestination == destBlendFuncs[i]) { blendMode_ = (BlendMode)i; break; } } rotationStart_ = ReadFloat(rootElem, "rotationStart"); rotationStartVariance_ = ReadFloat(rootElem, "rotationStartVariance"); rotationEnd_ = ReadFloat(rootElem, "rotationEnd"); rotationEndVariance_ = ReadFloat(rootElem, "rotationEndVariance"); // Note: not accurate SetMemoryUse(source.GetSize()); return true; }
bool Model::Load(Deserializer& source) { PROFILE(LoadModel); // Check ID if (source.ReadFileID() != "UMDL") { LOGERROR(source.GetName() + " is not a valid model file"); return false; } geometries_.Clear(); geometryBoneMappings_.Clear(); geometryCenters_.Clear(); morphs_.Clear(); vertexBuffers_.Clear(); indexBuffers_.Clear(); unsigned memoryUse = sizeof(Model); // Read vertex buffers unsigned numVertexBuffers = source.ReadUInt(); vertexBuffers_.Reserve(numVertexBuffers); morphRangeStarts_.Resize(numVertexBuffers); morphRangeCounts_.Resize(numVertexBuffers); for (unsigned i = 0; i < numVertexBuffers; ++i) { unsigned vertexCount = source.ReadUInt(); unsigned elementMask = source.ReadUInt(); morphRangeStarts_[i] = source.ReadUInt(); morphRangeCounts_[i] = source.ReadUInt(); SharedPtr<VertexBuffer> buffer(new VertexBuffer(context_)); buffer->SetShadowed(true); buffer->SetSize(vertexCount, elementMask); void* dest = buffer->Lock(0, vertexCount); unsigned vertexSize = buffer->GetVertexSize(); source.Read(dest, vertexCount * vertexSize); buffer->Unlock(); memoryUse += sizeof(VertexBuffer) + vertexCount * vertexSize; vertexBuffers_.Push(buffer); } // Read index buffers unsigned numIndexBuffers = source.ReadUInt(); indexBuffers_.Reserve(numIndexBuffers); for (unsigned i = 0; i < numIndexBuffers; ++i) { unsigned indexCount = source.ReadUInt(); unsigned indexSize = source.ReadUInt(); SharedPtr<IndexBuffer> buffer(new IndexBuffer(context_)); buffer->SetShadowed(true); buffer->SetSize(indexCount, indexSize > sizeof(unsigned short)); void* dest = buffer->Lock(0, indexCount); source.Read(dest, indexCount * indexSize); buffer->Unlock(); memoryUse += sizeof(IndexBuffer) + indexCount * indexSize; indexBuffers_.Push(buffer); } // Read geometries unsigned numGeometries = source.ReadUInt(); geometries_.Reserve(numGeometries); geometryBoneMappings_.Reserve(numGeometries); geometryCenters_.Reserve(numGeometries); for (unsigned i = 0; i < numGeometries; ++i) { // Read bone mappings unsigned boneMappingCount = source.ReadUInt(); PODVector<unsigned> boneMapping(boneMappingCount); for (unsigned j = 0; j < boneMappingCount; ++j) boneMapping[j] = source.ReadUInt(); geometryBoneMappings_.Push(boneMapping); unsigned numLodLevels = source.ReadUInt(); Vector<SharedPtr<Geometry> > geometryLodLevels; geometryLodLevels.Reserve(numLodLevels); for (unsigned j = 0; j < numLodLevels; ++j) { float distance = source.ReadFloat(); PrimitiveType type = (PrimitiveType)source.ReadUInt(); unsigned vertexBufferRef = source.ReadUInt(); unsigned indexBufferRef = source.ReadUInt(); unsigned indexStart = source.ReadUInt(); unsigned indexCount = source.ReadUInt(); if (vertexBufferRef >= vertexBuffers_.Size()) { LOGERROR("Vertex buffer index out of bounds"); return false; } if (indexBufferRef >= indexBuffers_.Size()) { LOGERROR("Index buffer index out of bounds"); return false; } SharedPtr<Geometry> geometry(new Geometry(context_)); geometry->SetVertexBuffer(0, vertexBuffers_[vertexBufferRef]); geometry->SetIndexBuffer(indexBuffers_[indexBufferRef]); geometry->SetDrawRange(type, indexStart, indexCount); geometry->SetLodDistance(distance); geometryLodLevels.Push(geometry); memoryUse += sizeof(Geometry); } geometries_.Push(geometryLodLevels); } // Read morphs unsigned numMorphs = source.ReadUInt(); morphs_.Reserve(numMorphs); for (unsigned i = 0; i < numMorphs; ++i) { ModelMorph newMorph; newMorph.name_ = source.ReadString(); newMorph.nameHash_ = newMorph.name_; newMorph.weight_ = 0.0f; unsigned nubuffers_ = source.ReadUInt(); for (unsigned j = 0; j < nubuffers_; ++j) { VertexBufferMorph newBuffer; unsigned bufferIndex = source.ReadUInt(); newBuffer.elementMask_ = source.ReadUInt(); newBuffer.vertexCount_ = source.ReadUInt(); // Base size: size of each vertex index unsigned vertexSize = sizeof(unsigned); // Add size of individual elements if (newBuffer.elementMask_ & MASK_POSITION) vertexSize += sizeof(Vector3); if (newBuffer.elementMask_ & MASK_NORMAL) vertexSize += sizeof(Vector3); if (newBuffer.elementMask_ & MASK_TANGENT) vertexSize += sizeof(Vector3); newBuffer.morphData_ = new unsigned char[newBuffer.vertexCount_ * vertexSize]; source.Read(&newBuffer.morphData_[0], newBuffer.vertexCount_ * vertexSize); newMorph.buffers_[bufferIndex] = newBuffer; memoryUse += sizeof(VertexBufferMorph) + newBuffer.vertexCount_ * vertexSize; } morphs_.Push(newMorph); memoryUse += sizeof(ModelMorph); } // Read skeleton skeleton_.Load(source); memoryUse += skeleton_.GetNumBones() * sizeof(Bone); // Read bounding box boundingBox_ = source.ReadBoundingBox(); // Read geometry centers for (unsigned i = 0; i < geometries_.Size() && !source.IsEof(); ++i) geometryCenters_.Push(source.ReadVector3()); while (geometryCenters_.Size() < geometries_.Size()) geometryCenters_.Push(Vector3::ZERO); memoryUse += sizeof(Vector3) * geometries_.Size(); SetMemoryUse(memoryUse); return true; }