/* * GDevelop Core * Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights * reserved. This project is released under the MIT License. */ #include "GDCore/Project/ResourcesManager.h" #include #include #include "GDCore/CommonTools.h" #include "GDCore/Project/Project.h" #include "GDCore/Project/PropertyDescriptor.h" #include "GDCore/Serialization/Serializer.h" #include "GDCore/Serialization/SerializerElement.h" #include "GDCore/Tools/Localization.h" #include "GDCore/Tools/Log.h" namespace gd { gd::String Resource::badStr; Resource ResourcesManager::badResource; #if defined(GD_IDE_ONLY) ResourceFolder ResourcesManager::badFolder; Resource ResourceFolder::badResource; #endif #if defined(GD_IDE_ONLY) void ResourceFolder::Init(const ResourceFolder& other) { name = other.name; resources.clear(); for (std::size_t i = 0; i < other.resources.size(); ++i) { resources.push_back(std::shared_ptr(other.resources[i]->Clone())); } } #endif void ResourcesManager::Init(const ResourcesManager& other) { resources.clear(); for (std::size_t i = 0; i < other.resources.size(); ++i) { resources.push_back(std::shared_ptr(other.resources[i]->Clone())); } #if defined(GD_IDE_ONLY) folders.clear(); for (std::size_t i = 0; i < other.folders.size(); ++i) { folders.push_back(other.folders[i]); } #endif } Resource& ResourcesManager::GetResource(const gd::String& name) { for (std::size_t i = 0; i < resources.size(); ++i) { if (resources[i]->GetName() == name) return *resources[i]; } return badResource; } const Resource& ResourcesManager::GetResource(const gd::String& name) const { for (std::size_t i = 0; i < resources.size(); ++i) { if (resources[i]->GetName() == name) return *resources[i]; } return badResource; } std::shared_ptr ResourcesManager::CreateResource( const gd::String& kind) { if (kind == "image") return std::make_shared(); else if (kind == "audio") return std::make_shared(); else if (kind == "font") return std::make_shared(); else if (kind == "video") return std::make_shared(); else if (kind == "json") return std::make_shared(); std::cout << "Bad resource created (type: " << kind << ")" << std::endl; return std::make_shared(); } bool ResourcesManager::HasResource(const gd::String& name) const { for (std::size_t i = 0; i < resources.size(); ++i) { if (resources[i]->GetName() == name) return true; } return false; } std::vector ResourcesManager::GetAllResourceNames() const { std::vector allResources; for (std::size_t i = 0; i < resources.size(); ++i) allResources.push_back(resources[i]->GetName()); return allResources; } #if defined(GD_IDE_ONLY) std::map Resource::GetProperties() const { std::map nothing; return nothing; } std::map ImageResource::GetProperties() const { std::map properties; properties[_("Smooth the image")] .SetValue(smooth ? "true" : "false") .SetType("Boolean"); properties[_("Always loaded in memory")] .SetValue(alwaysLoaded ? "true" : "false") .SetType("Boolean"); return properties; } bool ImageResource::UpdateProperty(const gd::String& name, const gd::String& value) { if (name == _("Smooth the image")) smooth = value == "1"; else if (name == _("Always loaded in memory")) alwaysLoaded = value == "1"; return true; } bool ResourcesManager::AddResource(const gd::Resource& resource) { if (HasResource(resource.GetName())) return false; std::shared_ptr newResource = std::shared_ptr(resource.Clone()); if (newResource == std::shared_ptr()) return false; resources.push_back(newResource); return true; } bool ResourcesManager::AddResource(const gd::String& name, const gd::String& filename, const gd::String& kind) { if (HasResource(name)) return false; std::shared_ptr res = CreateResource(kind); res->SetFile(filename); res->SetName(name); resources.push_back(res); return true; } std::vector ResourceFolder::GetAllResourceNames() { std::vector allResources; for (std::size_t i = 0; i < resources.size(); ++i) allResources.push_back(resources[i]->GetName()); return allResources; } Resource& ResourceFolder::GetResource(const gd::String& name) { for (std::size_t i = 0; i < resources.size(); ++i) { if (resources[i]->GetName() == name) return *resources[i]; } return badResource; } const Resource& ResourceFolder::GetResource(const gd::String& name) const { for (std::size_t i = 0; i < resources.size(); ++i) { if (resources[i]->GetName() == name) return *resources[i]; } return badResource; } namespace { bool MoveResourceUpInList(std::vector >& resources, const gd::String& name) { std::size_t index = gd::String::npos; for (std::size_t i = 0; i < resources.size(); ++i) { if (resources[i]->GetName() == name) { index = i; break; } } if (index < resources.size() && index > 0) { swap(resources[index], resources[index - 1]); return true; } return false; } bool MoveResourceDownInList(std::vector >& resources, const gd::String& name) { std::size_t index = gd::String::npos; for (std::size_t i = 0; i < resources.size(); ++i) { if (resources[i]->GetName() == name) { index = i; break; } } if (index < resources.size() - 1) { swap(resources[index], resources[index + 1]); return true; } return false; } } // namespace bool ResourceFolder::MoveResourceUpInList(const gd::String& name) { return gd::MoveResourceUpInList(resources, name); } bool ResourceFolder::MoveResourceDownInList(const gd::String& name) { return gd::MoveResourceDownInList(resources, name); } bool ResourcesManager::MoveResourceUpInList(const gd::String& name) { return gd::MoveResourceUpInList(resources, name); } bool ResourcesManager::MoveResourceDownInList(const gd::String& name) { return gd::MoveResourceDownInList(resources, name); } std::size_t ResourcesManager::GetResourcePosition( const gd::String& name) const { for (std::size_t i = 0; i < resources.size(); ++i) { if (resources[i]->GetName() == name) return i; } return gd::String::npos; } void ResourcesManager::MoveResource(std::size_t oldIndex, std::size_t newIndex) { if (oldIndex >= resources.size() || newIndex >= resources.size()) return; auto resource = resources[oldIndex]; resources.erase(resources.begin() + oldIndex); resources.insert(resources.begin() + newIndex, resource); } bool ResourcesManager::MoveFolderUpInList(const gd::String& name) { for (std::size_t i = 1; i < folders.size(); ++i) { if (folders[i].GetName() == name) { std::swap(folders[i], folders[i - 1]); return true; } } return false; } bool ResourcesManager::MoveFolderDownInList(const gd::String& name) { for (std::size_t i = 0; i < folders.size() - 1; ++i) { if (folders[i].GetName() == name) { std::swap(folders[i], folders[i + 1]); return true; } } return false; } std::shared_ptr ResourcesManager::GetResourceSPtr( const gd::String& name) { for (std::size_t i = 0; i < resources.size(); ++i) { if (resources[i]->GetName() == name) return resources[i]; } return std::shared_ptr(); } bool ResourcesManager::HasFolder(const gd::String& name) const { for (std::size_t i = 0; i < folders.size(); ++i) { if (folders[i].GetName() == name) return true; } return false; } const ResourceFolder& ResourcesManager::GetFolder( const gd::String& name) const { for (std::size_t i = 0; i < folders.size(); ++i) { if (folders[i].GetName() == name) return folders[i]; } return badFolder; } ResourceFolder& ResourcesManager::GetFolder(const gd::String& name) { for (std::size_t i = 0; i < folders.size(); ++i) { if (folders[i].GetName() == name) return folders[i]; } return badFolder; } void ResourcesManager::RemoveFolder(const gd::String& name) { for (std::size_t i = 0; i < folders.size();) { if (folders[i].GetName() == name) { folders.erase(folders.begin() + i); } else ++i; } } void ResourcesManager::CreateFolder(const gd::String& name) { ResourceFolder newFolder; newFolder.SetName(name); folders.push_back(newFolder); } std::vector ResourcesManager::GetAllFolderList() { std::vector allFolders; for (std::size_t i = 0; i < folders.size(); ++i) allFolders.push_back(folders[i].GetName()); return allFolders; } bool ResourceFolder::HasResource(const gd::String& name) const { for (std::size_t i = 0; i < resources.size(); ++i) { if (resources[i]->GetName() == name) return true; } return false; } void ResourceFolder::AddResource(const gd::String& name, gd::ResourcesManager& parentManager) { std::shared_ptr resource = parentManager.GetResourceSPtr(name); if (resource != std::shared_ptr()) resources.push_back(resource); } void ResourcesManager::RenameResource(const gd::String& oldName, const gd::String& newName) { for (std::size_t i = 0; i < resources.size(); ++i) { if (resources[i]->GetName() == oldName) resources[i]->SetName(newName); } } void ResourceFolder::RemoveResource(const gd::String& name) { for (std::size_t i = 0; i < resources.size();) { if (resources[i] != std::shared_ptr() && resources[i]->GetName() == name) resources.erase(resources.begin() + i); else ++i; } } void ResourcesManager::RemoveResource(const gd::String& name) { for (std::size_t i = 0; i < resources.size();) { if (resources[i] != std::shared_ptr() && resources[i]->GetName() == name) resources.erase(resources.begin() + i); else ++i; } for (std::size_t i = 0; i < folders.size(); ++i) folders[i].RemoveResource(name); } #endif #if defined(GD_IDE_ONLY) void ResourceFolder::UnserializeFrom(const SerializerElement& element, gd::ResourcesManager& parentManager) { name = element.GetStringAttribute("name"); resources.clear(); SerializerElement& resourcesElement = element.GetChild("resources", 0, "Resources"); resourcesElement.ConsiderAsArrayOf("resource", "Resource"); for (std::size_t i = 0; i < resourcesElement.GetChildrenCount(); ++i) AddResource(resourcesElement.GetChild(i).GetStringAttribute("name"), parentManager); } void ResourceFolder::SerializeTo(SerializerElement& element) const { element.SetAttribute("name", name); SerializerElement& resourcesElement = element.AddChild("resources"); resourcesElement.ConsiderAsArrayOf("resource"); for (std::size_t i = 0; i < resources.size(); ++i) { if (resources[i] == std::shared_ptr()) continue; resourcesElement.AddChild("resource") .SetAttribute("name", resources[i]->GetName()); } } #endif void ResourcesManager::UnserializeFrom(const SerializerElement& element) { resources.clear(); const SerializerElement& resourcesElement = element.GetChild("resources", 0, "Resources"); resourcesElement.ConsiderAsArrayOf("resource", "Resource"); for (std::size_t i = 0; i < resourcesElement.GetChildrenCount(); ++i) { const SerializerElement& resourceElement = resourcesElement.GetChild(i); gd::String kind = resourceElement.GetStringAttribute("kind"); gd::String name = resourceElement.GetStringAttribute("name"); gd::String metadata = resourceElement.GetStringAttribute("metadata", ""); std::shared_ptr resource = CreateResource(kind); resource->SetName(name); resource->SetMetadata(metadata); resource->UnserializeFrom(resourceElement); resources.push_back(resource); } #if defined(GD_IDE_ONLY) folders.clear(); const SerializerElement& resourcesFoldersElement = element.GetChild("resourceFolders", 0, "ResourceFolders"); resourcesFoldersElement.ConsiderAsArrayOf("folder", "Folder"); for (std::size_t i = 0; i < resourcesFoldersElement.GetChildrenCount(); ++i) { ResourceFolder folder; folder.UnserializeFrom(resourcesFoldersElement.GetChild(i), *this); folders.push_back(folder); } #endif } #if defined(GD_IDE_ONLY) void ResourcesManager::SerializeTo(SerializerElement& element) const { SerializerElement& resourcesElement = element.AddChild("resources"); resourcesElement.ConsiderAsArrayOf("resource"); for (std::size_t i = 0; i < resources.size(); ++i) { if (resources[i] == std::shared_ptr()) break; SerializerElement& resourceElement = resourcesElement.AddChild("resource"); resourceElement.SetAttribute("kind", resources[i]->GetKind()); resourceElement.SetAttribute("name", resources[i]->GetName()); resourceElement.SetAttribute("metadata", resources[i]->GetMetadata()); resources[i]->SerializeTo(resourceElement); } SerializerElement& resourcesFoldersElement = element.AddChild("resourceFolders"); resourcesFoldersElement.ConsiderAsArrayOf("folder"); for (std::size_t i = 0; i < folders.size(); ++i) folders[i].SerializeTo(resourcesFoldersElement.AddChild("folder")); } #endif void ImageResource::SetFile(const gd::String& newFile) { file = newFile; // Convert all backslash to slashs. while (file.find('\\') != gd::String::npos) file.replace(file.find('\\'), 1, "/"); } void ImageResource::UnserializeFrom(const SerializerElement& element) { alwaysLoaded = element.GetBoolAttribute("alwaysLoaded"); smooth = element.GetBoolAttribute("smoothed"); SetUserAdded(element.GetBoolAttribute("userAdded")); SetFile(element.GetStringAttribute("file")); } #if defined(GD_IDE_ONLY) void ImageResource::SerializeTo(SerializerElement& element) const { element.SetAttribute("alwaysLoaded", alwaysLoaded); element.SetAttribute("smoothed", smooth); element.SetAttribute("userAdded", IsUserAdded()); element.SetAttribute("file", GetFile()); } #endif void AudioResource::SetFile(const gd::String& newFile) { file = newFile; // Convert all backslash to slashs. while (file.find('\\') != gd::String::npos) file.replace(file.find('\\'), 1, "/"); } void AudioResource::UnserializeFrom(const SerializerElement& element) { SetUserAdded(element.GetBoolAttribute("userAdded")); SetFile(element.GetStringAttribute("file")); } #if defined(GD_IDE_ONLY) void AudioResource::SerializeTo(SerializerElement& element) const { element.SetAttribute("userAdded", IsUserAdded()); element.SetAttribute("file", GetFile()); } #endif void FontResource::SetFile(const gd::String& newFile) { file = newFile; // Convert all backslash to slashs. while (file.find('\\') != gd::String::npos) file.replace(file.find('\\'), 1, "/"); } void FontResource::UnserializeFrom(const SerializerElement& element) { SetUserAdded(element.GetBoolAttribute("userAdded")); SetFile(element.GetStringAttribute("file")); } #if defined(GD_IDE_ONLY) void FontResource::SerializeTo(SerializerElement& element) const { element.SetAttribute("userAdded", IsUserAdded()); element.SetAttribute("file", GetFile()); } #endif void VideoResource::SetFile(const gd::String& newFile) { file = newFile; // Convert all backslash to slashs. while (file.find('\\') != gd::String::npos) file.replace(file.find('\\'), 1, "/"); } void VideoResource::UnserializeFrom(const SerializerElement& element) { SetUserAdded(element.GetBoolAttribute("userAdded")); SetFile(element.GetStringAttribute("file")); } #if defined(GD_IDE_ONLY) void VideoResource::SerializeTo(SerializerElement& element) const { element.SetAttribute("userAdded", IsUserAdded()); element.SetAttribute("file", GetFile()); } #endif void JsonResource::SetFile(const gd::String& newFile) { file = newFile; // Convert all backslash to slashs. while (file.find('\\') != gd::String::npos) file.replace(file.find('\\'), 1, "/"); } void JsonResource::UnserializeFrom(const SerializerElement& element) { SetUserAdded(element.GetBoolAttribute("userAdded")); SetFile(element.GetStringAttribute("file")); DisablePreload(element.GetBoolAttribute("disablePreload", false)); } #if defined(GD_IDE_ONLY) void JsonResource::SerializeTo(SerializerElement& element) const { element.SetAttribute("userAdded", IsUserAdded()); element.SetAttribute("file", GetFile()); element.SetAttribute("disablePreload", IsPreloadDisabled()); } std::map JsonResource::GetProperties() const { std::map properties; properties["disablePreload"] .SetValue(disablePreload ? "true" : "false") .SetType("Boolean") .SetLabel(_("Disable preloading at game startup")); return properties; } bool JsonResource::UpdateProperty(const gd::String& name, const gd::String& value) { if (name == "disablePreload") disablePreload = value == "1"; return true; } #endif #if defined(GD_IDE_ONLY) ResourceFolder::ResourceFolder(const ResourceFolder& other) { Init(other); } ResourceFolder& ResourceFolder::operator=(const ResourceFolder& other) { if (this != &other) Init(other); return *this; } #endif ResourcesManager::ResourcesManager(const ResourcesManager& other) { Init(other); } ResourcesManager& ResourcesManager::operator=(const ResourcesManager& other) { if (this != &other) Init(other); return *this; } ResourcesManager::ResourcesManager() { // ctor } ResourcesManager::~ResourcesManager() { // dtor } } // namespace gd