bool Texture2D::BeginLoad(Deserializer& source) { // 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; } // Load the image data for EndLoad() loadImage_ = new Image(context_); if (!loadImage_->Load(source)) { loadImage_.Reset(); return false; } // Precalculate mip levels if async loading if (GetAsyncLoadState() == ASYNC_LOADING) loadImage_->PrecalculateLevels(); // Load the optional parameters file ResourceCache* cache = GetSubsystem<ResourceCache>(); String xmlName = ReplaceExtension(GetName(), ".xml"); loadParameters_ = cache->GetTempResource<XMLFile>(xmlName, false); return true; }
bool SpriteSheet2D::BeginLoadFromXMLFile(Deserializer& source) { loadXMLFile_ = new XMLFile(context_); if (!loadXMLFile_->Load(source)) { URHO3D_LOGERROR("Could not load sprite sheet"); loadXMLFile_.Reset(); return false; } SetMemoryUse(source.GetSize()); XMLElement rootElem = loadXMLFile_->GetRoot("TextureAtlas"); if (!rootElem) { URHO3D_LOGERROR("Invalid sprite sheet"); loadXMLFile_.Reset(); return false; } // If we're async loading, request the texture now. Finish during EndLoad(). loadTextureName_ = GetParentPath(GetName()) + rootElem.GetAttribute("imagePath"); if (GetAsyncLoadState() == ASYNC_LOADING) GetSubsystem<ResourceCache>()->BackgroundLoadResource<Texture2D>(loadTextureName_, true, this); return true; }
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 Texture2DArray::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 layerElem = textureElem.GetChild("layer"); while (layerElem) { QString name = layerElem.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); layerElem = layerElem.GetNext("layer"); } // 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; }
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 Material::BeginLoad(Deserializer& source) { // In headless mode, do not actually load the material, just return success Graphics* graphics = GetSubsystem<Graphics>(); if (!graphics) return true; loadXMLFile_ = new XMLFile(context_); if (loadXMLFile_->Load(source)) { // If async loading, scan the XML content beforehand for technique & texture resources // and request them to also be loaded. Can not do anything else at this point if (GetAsyncLoadState() == ASYNC_LOADING) { ResourceCache* cache = GetSubsystem<ResourceCache>(); XMLElement rootElem = loadXMLFile_->GetRoot(); XMLElement techniqueElem = rootElem.GetChild("technique"); while (techniqueElem) { cache->BackgroundLoadResource<Technique>(techniqueElem.GetAttribute("name"), true, this); techniqueElem = techniqueElem.GetNext("technique"); } XMLElement textureElem = rootElem.GetChild("texture"); while (textureElem) { String name = textureElem.GetAttribute("name"); // Detect cube maps by file extension: they are defined by an XML file /// \todo Differentiate with 3D textures by actually reading the XML content if (GetExtension(name) == ".xml") { #ifdef DESKTOP_GRAPHICS TextureUnit unit = TU_DIFFUSE; if (textureElem.HasAttribute("unit")) unit = ParseTextureUnitName(textureElem.GetAttribute("unit")); if (unit == TU_VOLUMEMAP) cache->BackgroundLoadResource<Texture3D>(name, true, this); else #endif cache->BackgroundLoadResource<TextureCube>(name, true, this); } else cache->BackgroundLoadResource<Texture2D>(name, true, this); textureElem = textureElem.GetNext("texture"); } } return true; } else { ResetToDefaults(); loadXMLFile_.Reset(); return false; } }
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 SpriteSheet2D::BeginLoadFromPListFile(Deserializer& source) { loadPListFile_ = new PListFile(context_); if (!loadPListFile_->Load(source)) { URHO3D_LOGERROR("Could not load sprite sheet"); loadPListFile_.Reset(); return false; } SetMemoryUse(source.GetSize()); const PListValueMap& root = loadPListFile_->GetRoot(); const PListValueMap& metadata = root["metadata"]->GetValueMap(); const String& textureFileName = metadata["realTextureFileName"]->GetString(); // If we're async loading, request the texture now. Finish during EndLoad(). loadTextureName_ = GetParentPath(GetName()) + textureFileName; if (GetAsyncLoadState() == ASYNC_LOADING) GetSubsystem<ResourceCache>()->BackgroundLoadResource<Texture2D>(loadTextureName_, true, this); return true; }
bool ParticleEffect::Load(const XMLElement& source) { // Reset to defaults first so that missing parameters in case of a live reload behave as expected material_.Reset(); numParticles_ = DEFAULT_NUM_PARTICLES; updateInvisible_ = false; relative_ = true; scaled_ = true; sorted_ = false; fixedScreenSize_ = false; animationLodBias_ = 0.0f; emitterType_ = EMITTER_SPHERE; emitterSize_ = Vector3::ZERO; directionMin_ = DEFAULT_DIRECTION_MIN; directionMax_ = DEFAULT_DIRECTION_MAX; constantForce_ = Vector3::ZERO; dampingForce_ = 0.0f; activeTime_ = 0.0f; inactiveTime_ = 0.0; emissionRateMin_ = DEFAULT_EMISSION_RATE; emissionRateMax_ = DEFAULT_EMISSION_RATE; sizeMin_ = DEFAULT_PARTICLE_SIZE; sizeMax_ = DEFAULT_PARTICLE_SIZE; timeToLiveMin_ = DEFAULT_TIME_TO_LIVE; timeToLiveMax_ = DEFAULT_TIME_TO_LIVE; velocityMin_ = DEFAULT_VELOCITY; velocityMax_ = DEFAULT_VELOCITY; rotationMin_ = 0.0f; rotationMax_ = 0.0f; rotationSpeedMin_ = 0.0f; rotationSpeedMax_ = 0.0f; sizeAdd_ = 0.0f; sizeMul_ = 1.0f; colorFrames_.Clear(); textureFrames_.Clear(); faceCameraMode_ = FC_ROTATE_XYZ; if (source.IsNull()) { URHO3D_LOGERROR("Can not load particle effect from null XML element"); return false; } if (source.HasChild("material")) { loadMaterialName_ = source.GetChild("material").GetAttribute("name"); // If async loading, can not GetResource() the material. But can do a background request for it if (GetAsyncLoadState() == ASYNC_LOADING) GetSubsystem<ResourceCache>()->BackgroundLoadResource<Material>(loadMaterialName_, true, this); } if (source.HasChild("numparticles")) SetNumParticles((unsigned)source.GetChild("numparticles").GetInt("value")); if (source.HasChild("updateinvisible")) updateInvisible_ = source.GetChild("updateinvisible").GetBool("enable"); if (source.HasChild("relative")) relative_ = source.GetChild("relative").GetBool("enable"); if (source.HasChild("scaled")) scaled_ = source.GetChild("scaled").GetBool("enable"); if (source.HasChild("sorted")) sorted_ = source.GetChild("sorted").GetBool("enable"); if (source.HasChild("fixedscreensize")) fixedScreenSize_ = source.GetChild("fixedscreensize").GetBool("enable"); if (source.HasChild("animlodbias")) SetAnimationLodBias(source.GetChild("animlodbias").GetFloat("value")); if (source.HasChild("emittertype")) { String type = source.GetChild("emittertype").GetAttributeLower("value"); if (type == "point") { // Point emitter type is deprecated, handled as zero sized sphere emitterType_ = EMITTER_SPHERE; emitterSize_ = Vector3::ZERO; } else emitterType_ = (EmitterType)GetStringListIndex(type.CString(), emitterTypeNames, EMITTER_SPHERE); } if (source.HasChild("emittersize")) emitterSize_ = source.GetChild("emittersize").GetVector3("value"); if (source.HasChild("emitterradius")) emitterSize_.x_ = emitterSize_.y_ = emitterSize_.z_ = source.GetChild("emitterradius").GetFloat("value"); if (source.HasChild("direction")) GetVector3MinMax(source.GetChild("direction"), directionMin_, directionMax_); if (source.HasChild("constantforce")) constantForce_ = source.GetChild("constantforce").GetVector3("value"); if (source.HasChild("dampingforce")) dampingForce_ = source.GetChild("dampingforce").GetFloat("value"); if (source.HasChild("activetime")) activeTime_ = source.GetChild("activetime").GetFloat("value"); if (activeTime_ < 0.0f) activeTime_ = M_INFINITY; if (source.HasChild("inactivetime")) inactiveTime_ = source.GetChild("inactivetime").GetFloat("value"); if (inactiveTime_ < 0.0f) inactiveTime_ = M_INFINITY; if (source.HasChild("emissionrate")) GetFloatMinMax(source.GetChild("emissionrate"), emissionRateMin_, emissionRateMax_); if (source.HasChild("interval")) { float intervalMin = 0.0f; float intervalMax = 0.0f; GetFloatMinMax(source.GetChild("interval"), intervalMin, intervalMax); emissionRateMax_ = 1.0f / intervalMin; emissionRateMin_ = 1.0f / intervalMax; } if (source.HasChild("particlesize")) GetVector2MinMax(source.GetChild("particlesize"), sizeMin_, sizeMax_); if (source.HasChild("timetolive")) GetFloatMinMax(source.GetChild("timetolive"), timeToLiveMin_, timeToLiveMax_); if (source.HasChild("velocity")) GetFloatMinMax(source.GetChild("velocity"), velocityMin_, velocityMax_); if (source.HasChild("rotation")) GetFloatMinMax(source.GetChild("rotation"), rotationMin_, rotationMax_); if (source.HasChild("rotationspeed")) GetFloatMinMax(source.GetChild("rotationspeed"), rotationSpeedMin_, rotationSpeedMax_); if (source.HasChild("faceCameraMode")) { String type = source.GetChild("faceCameraMode").GetAttributeLower("value"); faceCameraMode_ = (FaceCameraMode)GetStringListIndex(type.CString(), faceCameraModeNames, FC_ROTATE_XYZ); } if (source.HasChild("sizedelta")) { XMLElement deltaElem = source.GetChild("sizedelta"); if (deltaElem.HasAttribute("add")) sizeAdd_ = deltaElem.GetFloat("add"); if (deltaElem.HasAttribute("mul")) sizeMul_ = deltaElem.GetFloat("mul"); } if (source.HasChild("color")) { ColorFrame colorFrame(source.GetChild("color").GetColor("value")); SetColorFrame(0, colorFrame); } if (source.HasChild("colorfade")) { Vector<ColorFrame> fades; for (XMLElement colorFadeElem = source.GetChild("colorfade"); colorFadeElem; colorFadeElem = colorFadeElem.GetNext("colorfade")) fades.Push(ColorFrame(colorFadeElem.GetColor("color"), colorFadeElem.GetFloat("time"))); SetColorFrames(fades); } if (colorFrames_.Empty()) colorFrames_.Push(ColorFrame(Color::WHITE)); if (source.HasChild("texanim")) { Vector<TextureFrame> animations; for (XMLElement animElem = source.GetChild("texanim"); animElem; animElem = animElem.GetNext("texanim")) { TextureFrame animation; animation.uv_ = animElem.GetRect("uv"); animation.time_ = animElem.GetFloat("time"); animations.Push(animation); } SetTextureFrames(animations); } return true; }
bool Texture3D::BeginLoad(Deserializer& source) { auto* 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; }
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; }
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 ParticleEffect2D::BeginLoad(Deserializer& source) { 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"); 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; }