Skip to content

Commit 77320ce

Browse files
daiyamD8H4ian
authored
Add support for LDtk Tilemaps (#4575)
* Tilemaps made with [LDtk](https://ldtk.io/), a modern 2D level editor, can be now used directly. Make sure to save your map made in LDtk as a JSON file, create a new Tilemap object in GDevelop and in the Tilemap field, choose the LDtk file. * Tilesets used by the LDtk Tilemap are automatically imported in your game - you don't need to import them separately. * For more information, read about the [Tilemap object on the wiki](https://wiki.gdevelop.io/gdevelop5/objects/tilemap). Co-authored-by: Davy Hélard <[email protected]> Co-authored-by: Florian Rival <[email protected]>
1 parent 35833e6 commit 77320ce

File tree

110 files changed

+3498
-1097
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

110 files changed

+3498
-1097
lines changed

Core/GDCore/Events/CodeGeneration/EventsCodeGenerator.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,7 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
726726
metadata.GetType() == "fontResource" ||
727727
metadata.GetType() == "imageResource" ||
728728
metadata.GetType() == "jsonResource" ||
729+
metadata.GetType() == "tilemapResource" ||
729730
metadata.GetType() == "videoResource" ||
730731
// Deprecated, old parameter names:
731732
metadata.GetType() == "password" || metadata.GetType() == "musicfile" ||

Core/GDCore/IDE/Project/ArbitraryResourceWorker.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ void ArbitraryResourceWorker::ExposeJson(gd::String& jsonName){
3535
// do.
3636
};
3737

38+
void ArbitraryResourceWorker::ExposeTilemap(gd::String& tilemapName){
39+
// Nothing to do by default - each child class can define here the action to
40+
// do.
41+
};
42+
3843
void ArbitraryResourceWorker::ExposeVideo(gd::String& videoName){
3944
// Nothing to do by default - each child class can define here the action to
4045
// do.
@@ -92,6 +97,65 @@ void ArbitraryResourceWorker::ExposeResources(
9297
}
9398
}
9499

100+
void ArbitraryResourceWorker::ExposeEmbeddeds(gd::String& resourceName) {
101+
if (resourcesManagers.empty()) return;
102+
gd::ResourcesManager* resourcesManager = resourcesManagers[0];
103+
104+
gd::Resource& resource = resourcesManager->GetResource(resourceName);
105+
106+
if (!resource.GetMetadata().empty()) {
107+
gd::SerializerElement serializerElement =
108+
gd::Serializer::FromJSON(resource.GetMetadata());
109+
110+
if (serializerElement.HasChild("embeddedResourcesMapping")) {
111+
bool anyEmbeddedResourceNameWasRenamed = false;
112+
gd::SerializerElement& embeddedResourcesMappingElement =
113+
serializerElement.GetChild("embeddedResourcesMapping");
114+
115+
for (const auto& child :
116+
embeddedResourcesMappingElement.GetAllChildren()) {
117+
const gd::String& targetResourceName =
118+
child.second->GetValue().GetString();
119+
120+
if (resourcesManager->HasResource(targetResourceName)) {
121+
std::cout << targetResourceName << std::endl;
122+
gd::Resource& targetResource =
123+
resourcesManager->GetResource(targetResourceName);
124+
const gd::String& targetResourceKind = targetResource.GetKind();
125+
126+
gd::String potentiallyUpdatedTargetResourceName = targetResourceName;
127+
128+
if (targetResourceKind == "audio") {
129+
ExposeAudio(potentiallyUpdatedTargetResourceName);
130+
} else if (targetResourceKind == "bitmapFont") {
131+
ExposeBitmapFont(potentiallyUpdatedTargetResourceName);
132+
} else if (targetResourceKind == "font") {
133+
ExposeFont(potentiallyUpdatedTargetResourceName);
134+
} else if (targetResourceKind == "image") {
135+
ExposeImage(potentiallyUpdatedTargetResourceName);
136+
} else if (targetResourceKind == "json") {
137+
ExposeJson(potentiallyUpdatedTargetResourceName);
138+
} else if (targetResourceKind == "tilemap") {
139+
ExposeTilemap(potentiallyUpdatedTargetResourceName);
140+
} else if (targetResourceKind == "video") {
141+
ExposeVideo(potentiallyUpdatedTargetResourceName);
142+
}
143+
144+
if (potentiallyUpdatedTargetResourceName != targetResourceName) {
145+
// The resource name was renamed. Also update the mapping.
146+
child.second->SetStringValue(potentiallyUpdatedTargetResourceName);
147+
anyEmbeddedResourceNameWasRenamed = true;
148+
}
149+
}
150+
}
151+
152+
if (anyEmbeddedResourceNameWasRenamed) {
153+
resource.SetMetadata(gd::Serializer::ToJSON(serializerElement));
154+
}
155+
}
156+
}
157+
}
158+
95159
void ArbitraryResourceWorker::ExposeResource(gd::Resource& resource) {
96160
if (!resource.UseFile()) return;
97161

@@ -154,6 +218,10 @@ class ResourceWorkerInEventsWorker : public ArbitraryEventsWorker {
154218
gd::String updatedParameterValue = parameterValue;
155219
worker.ExposeJson(updatedParameterValue);
156220
instruction.SetParameter(parameterIndex, updatedParameterValue);
221+
} else if (parameterMetadata.GetType() == "tilemapResource") {
222+
gd::String updatedParameterValue = parameterValue;
223+
worker.ExposeTilemap(updatedParameterValue);
224+
instruction.SetParameter(parameterIndex, updatedParameterValue);
157225
}
158226
});
159227

Core/GDCore/IDE/Project/ArbitraryResourceWorker.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ class GD_CORE_API ArbitraryResourceWorker {
7575
*/
7676
virtual void ExposeJson(gd::String &jsonName);
7777

78+
/**
79+
* \brief Expose a Tilemap, which is always a reference to a "tilemap" resource.
80+
*/
81+
virtual void ExposeTilemap(gd::String &tilemapName);
82+
7883
/**
7984
* \brief Expose a video, which is always a reference to a "video" resource.
8085
*/
@@ -96,6 +101,11 @@ class GD_CORE_API ArbitraryResourceWorker {
96101
*/
97102
virtual void ExposeFile(gd::String &resourceFileName) = 0;
98103

104+
/**
105+
* \brief Expose the embedded resources of the specified resource.
106+
*/
107+
virtual void ExposeEmbeddeds(gd::String &resourceName);
108+
99109
protected:
100110
const std::vector<gd::ResourcesManager *> &GetResources() {
101111
return resourcesManagers;

Core/GDCore/IDE/Project/ResourcesInUseHelper.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,15 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
4040
std::set<gd::String>& GetAllAudios() { return GetAll("audio"); };
4141
std::set<gd::String>& GetAllFonts() { return GetAll("font"); };
4242
std::set<gd::String>& GetAllJsons() { return GetAll("json"); };
43+
std::set<gd::String>& GetAllTilemaps() { return GetAll("tilemap"); };
4344
std::set<gd::String>& GetAllVideos() { return GetAll("video"); };
4445
std::set<gd::String>& GetAllBitmapFonts() { return GetAll("bitmapFont"); };
4546
std::set<gd::String>& GetAll(const gd::String& resourceType) {
4647
if (resourceType == "image") return allImages;
4748
if (resourceType == "audio") return allAudios;
4849
if (resourceType == "font") return allFonts;
4950
if (resourceType == "json") return allJsons;
51+
if (resourceType == "tilemap") return allTilemaps;
5052
if (resourceType == "video") return allVideos;
5153
if (resourceType == "bitmapFont") return allBitmapFonts;
5254

@@ -68,6 +70,9 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
6870
virtual void ExposeJson(gd::String& jsonResourceName) override {
6971
allJsons.insert(jsonResourceName);
7072
};
73+
virtual void ExposeTilemap(gd::String& tilemapResourceName) override {
74+
allTilemaps.insert(tilemapResourceName);
75+
};
7176
virtual void ExposeVideo(gd::String& videoResourceName) override {
7277
allVideos.insert(videoResourceName);
7378
};
@@ -80,6 +85,7 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
8085
std::set<gd::String> allAudios;
8186
std::set<gd::String> allFonts;
8287
std::set<gd::String> allJsons;
88+
std::set<gd::String> allTilemaps;
8389
std::set<gd::String> allVideos;
8490
std::set<gd::String> allBitmapFonts;
8591
std::set<gd::String> emptyResources;

Core/GDCore/IDE/Project/ResourcesRenamer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ class ResourcesRenamer : public gd::ArbitraryResourceWorker {
4949
virtual void ExposeJson(gd::String& jsonResourceName) override {
5050
RenameIfNeeded(jsonResourceName);
5151
};
52+
virtual void ExposeTilemap(gd::String& tilemapResourceName) override {
53+
RenameIfNeeded(tilemapResourceName);
54+
};
5255
virtual void ExposeVideo(gd::String& videoResourceName) override {
5356
RenameIfNeeded(videoResourceName);
5457
};

Core/GDCore/Project/CustomObjectConfiguration.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ gd::ObjectConfiguration &CustomObjectConfiguration::GetChildObjectConfiguration(
3838
return badObjectConfiguration;
3939
}
4040
const auto &eventsBasedObject = project->GetEventsBasedObject(GetType());
41-
41+
4242
if (!eventsBasedObject.HasObjectNamed(objectName)) {
4343
gd::LogError("Tried to get the configuration of a child-object:" + objectName
4444
+ " that doesn't exist in the event-based object: " + GetType());
@@ -78,7 +78,7 @@ bool CustomObjectConfiguration::UpdateProperty(const gd::String& propertyName,
7878
}
7979
const auto &eventsBasedObject = project->GetEventsBasedObject(GetType());
8080
const auto &properties = eventsBasedObject.GetPropertyDescriptors();
81-
81+
8282
return gd::CustomConfigurationHelper::UpdateProperty(
8383
properties,
8484
objectContent,
@@ -125,8 +125,7 @@ void CustomObjectConfiguration::DoUnserializeFrom(Project& project,
125125
}
126126
}
127127

128-
void CustomObjectConfiguration::ExposeResources(
129-
gd::ArbitraryResourceWorker& worker) {
128+
void CustomObjectConfiguration::ExposeResources(gd::ArbitraryResourceWorker& worker) {
130129
std::map<gd::String, gd::PropertyDescriptor> properties = GetProperties();
131130

132131
for (auto& property : properties) {
@@ -148,6 +147,8 @@ void CustomObjectConfiguration::ExposeResources(
148147
worker.ExposeVideo(newPropertyValue);
149148
} else if (resourceType == "json") {
150149
worker.ExposeJson(newPropertyValue);
150+
} else if (resourceType == "tilemap") {
151+
worker.ExposeTilemap(newPropertyValue);
151152
} else if (resourceType == "bitmapFont") {
152153
worker.ExposeBitmapFont(newPropertyValue);
153154
}

Core/GDCore/Project/CustomObjectConfiguration.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,9 @@ class CustomObjectConfiguration : public gd::ObjectConfiguration {
8787
/**
8888
* Initialize configuration using another configuration. Used by copy-ctor
8989
* and assign-op.
90-
*
90+
*
9191
* Don't forget to update me if members were changed!
92-
*
92+
*
9393
* It's needed because there is no default copy for childObjectConfigurations
9494
* and it must be a deep copy.
9595
*/

Core/GDCore/Project/ObjectConfiguration.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "GDCore/Project/Behavior.h"
1414
#include "GDCore/Project/EffectsContainer.h"
15+
#include "GDCore/Project/ResourcesManager.h"
1516
#include "GDCore/Project/VariablesContainer.h"
1617
#include "GDCore/String.h"
1718
#include "GDCore/Tools/MakeUnique.h"

Core/GDCore/Project/Project.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -982,8 +982,10 @@ void Project::ExposeResources(gd::ArbitraryResourceWorker& worker) {
982982
// (this time for effects). Ideally, this method could be moved outside of
983983
// gd::Project.
984984

985+
gd::ResourcesManager* resourcesManager = &GetResourcesManager();
986+
985987
// Add project resources
986-
worker.ExposeResources(&GetResourcesManager());
988+
worker.ExposeResources(resourcesManager);
987989
platformSpecificAssets.ExposeResources(worker);
988990

989991
// Add layouts resources

Core/GDCore/Project/ResourcesManager.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ std::shared_ptr<Resource> ResourcesManager::CreateResource(
8585
return std::make_shared<VideoResource>();
8686
else if (kind == "json")
8787
return std::make_shared<JsonResource>();
88+
else if (kind == "tilemap")
89+
return std::make_shared<TilemapResource>();
8890
else if (kind == "bitmapFont")
8991
return std::make_shared<BitmapFontResource>();
9092

@@ -650,6 +652,40 @@ bool JsonResource::UpdateProperty(const gd::String& name,
650652
return true;
651653
}
652654

655+
void TilemapResource::SetFile(const gd::String& newFile) {
656+
file = NormalizePathSeparator(newFile);
657+
}
658+
659+
void TilemapResource::UnserializeFrom(const SerializerElement& element) {
660+
SetUserAdded(element.GetBoolAttribute("userAdded"));
661+
SetFile(element.GetStringAttribute("file"));
662+
DisablePreload(element.GetBoolAttribute("disablePreload", false));
663+
}
664+
665+
void TilemapResource::SerializeTo(SerializerElement& element) const {
666+
element.SetAttribute("userAdded", IsUserAdded());
667+
element.SetAttribute("file", GetFile());
668+
element.SetAttribute("disablePreload", IsPreloadDisabled());
669+
}
670+
671+
std::map<gd::String, gd::PropertyDescriptor> TilemapResource::GetProperties()
672+
const {
673+
std::map<gd::String, gd::PropertyDescriptor> properties;
674+
properties["disablePreload"]
675+
.SetValue(disablePreload ? "true" : "false")
676+
.SetType("Boolean")
677+
.SetLabel(_("Disable preloading at game startup"));
678+
679+
return properties;
680+
}
681+
682+
bool TilemapResource::UpdateProperty(const gd::String& name,
683+
const gd::String& value) {
684+
if (name == "disablePreload") disablePreload = value == "1";
685+
686+
return true;
687+
}
688+
653689
void BitmapFontResource::SetFile(const gd::String& newFile) {
654690
file = NormalizePathSeparator(newFile);
655691
}

0 commit comments

Comments
 (0)