Add support for Tileset resources with .tsj extension (#4737)

This commit is contained in:
Baptiste Augrain
2022-12-23 23:09:16 +01:00
committed by GitHub
parent 7cd97e8cc4
commit 2a38be827c
26 changed files with 206 additions and 11 deletions
@@ -727,6 +727,7 @@ gd::String EventsCodeGenerator::GenerateParameterCodes(
metadata.GetType() == "imageResource" ||
metadata.GetType() == "jsonResource" ||
metadata.GetType() == "tilemapResource" ||
metadata.GetType() == "tilesetResource" ||
metadata.GetType() == "videoResource" ||
// Deprecated, old parameter names:
metadata.GetType() == "password" || metadata.GetType() == "musicfile" ||
@@ -40,6 +40,11 @@ void ArbitraryResourceWorker::ExposeTilemap(gd::String& tilemapName){
// do.
};
void ArbitraryResourceWorker::ExposeTileset(gd::String& tilesetName){
// Nothing to do by default - each child class can define here the action to
// do.
};
void ArbitraryResourceWorker::ExposeVideo(gd::String& videoName){
// Nothing to do by default - each child class can define here the action to
// do.
@@ -137,6 +142,8 @@ void ArbitraryResourceWorker::ExposeEmbeddeds(gd::String& resourceName) {
ExposeJson(potentiallyUpdatedTargetResourceName);
} else if (targetResourceKind == "tilemap") {
ExposeTilemap(potentiallyUpdatedTargetResourceName);
} else if (targetResourceKind == "tileset") {
ExposeTileset(potentiallyUpdatedTargetResourceName);
} else if (targetResourceKind == "video") {
ExposeVideo(potentiallyUpdatedTargetResourceName);
}
@@ -222,6 +229,10 @@ class ResourceWorkerInEventsWorker : public ArbitraryEventsWorker {
gd::String updatedParameterValue = parameterValue;
worker.ExposeTilemap(updatedParameterValue);
instruction.SetParameter(parameterIndex, updatedParameterValue);
} else if (parameterMetadata.GetType() == "tilesetResource") {
gd::String updatedParameterValue = parameterValue;
worker.ExposeTileset(updatedParameterValue);
instruction.SetParameter(parameterIndex, updatedParameterValue);
}
});
@@ -80,6 +80,11 @@ class GD_CORE_API ArbitraryResourceWorker {
*/
virtual void ExposeTilemap(gd::String &tilemapName);
/**
* \brief Expose a Tileset, which is always a reference to a "tileset" resource.
*/
virtual void ExposeTileset(gd::String &tilesetName);
/**
* \brief Expose a video, which is always a reference to a "video" resource.
*/
@@ -41,6 +41,7 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
std::set<gd::String>& GetAllFonts() { return GetAll("font"); };
std::set<gd::String>& GetAllJsons() { return GetAll("json"); };
std::set<gd::String>& GetAllTilemaps() { return GetAll("tilemap"); };
std::set<gd::String>& GetAllTilesets() { return GetAll("tileset"); };
std::set<gd::String>& GetAllVideos() { return GetAll("video"); };
std::set<gd::String>& GetAllBitmapFonts() { return GetAll("bitmapFont"); };
std::set<gd::String>& GetAll(const gd::String& resourceType) {
@@ -49,6 +50,7 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
if (resourceType == "font") return allFonts;
if (resourceType == "json") return allJsons;
if (resourceType == "tilemap") return allTilemaps;
if (resourceType == "tileset") return allTilesets;
if (resourceType == "video") return allVideos;
if (resourceType == "bitmapFont") return allBitmapFonts;
@@ -73,6 +75,9 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
virtual void ExposeTilemap(gd::String& tilemapResourceName) override {
allTilemaps.insert(tilemapResourceName);
};
virtual void ExposeTileset(gd::String& tilesetResourceName) override {
allTilesets.insert(tilesetResourceName);
};
virtual void ExposeVideo(gd::String& videoResourceName) override {
allVideos.insert(videoResourceName);
};
@@ -86,6 +91,7 @@ class ResourcesInUseHelper : public gd::ArbitraryResourceWorker {
std::set<gd::String> allFonts;
std::set<gd::String> allJsons;
std::set<gd::String> allTilemaps;
std::set<gd::String> allTilesets;
std::set<gd::String> allVideos;
std::set<gd::String> allBitmapFonts;
std::set<gd::String> emptyResources;
@@ -52,6 +52,9 @@ class ResourcesRenamer : public gd::ArbitraryResourceWorker {
virtual void ExposeTilemap(gd::String& tilemapResourceName) override {
RenameIfNeeded(tilemapResourceName);
};
virtual void ExposeTileset(gd::String& tilesetResourceName) override {
RenameIfNeeded(tilesetResourceName);
};
virtual void ExposeVideo(gd::String& videoResourceName) override {
RenameIfNeeded(videoResourceName);
};
@@ -149,6 +149,8 @@ void CustomObjectConfiguration::ExposeResources(gd::ArbitraryResourceWorker& wor
worker.ExposeJson(newPropertyValue);
} else if (resourceType == "tilemap") {
worker.ExposeTilemap(newPropertyValue);
} else if (resourceType == "tileset") {
worker.ExposeTileset(newPropertyValue);
} else if (resourceType == "bitmapFont") {
worker.ExposeBitmapFont(newPropertyValue);
}
+36
View File
@@ -87,6 +87,8 @@ std::shared_ptr<Resource> ResourcesManager::CreateResource(
return std::make_shared<JsonResource>();
else if (kind == "tilemap")
return std::make_shared<TilemapResource>();
else if (kind == "tileset")
return std::make_shared<TilesetResource>();
else if (kind == "bitmapFont")
return std::make_shared<BitmapFontResource>();
@@ -686,6 +688,40 @@ bool TilemapResource::UpdateProperty(const gd::String& name,
return true;
}
void TilesetResource::SetFile(const gd::String& newFile) {
file = NormalizePathSeparator(newFile);
}
void TilesetResource::UnserializeFrom(const SerializerElement& element) {
SetUserAdded(element.GetBoolAttribute("userAdded"));
SetFile(element.GetStringAttribute("file"));
DisablePreload(element.GetBoolAttribute("disablePreload", false));
}
void TilesetResource::SerializeTo(SerializerElement& element) const {
element.SetAttribute("userAdded", IsUserAdded());
element.SetAttribute("file", GetFile());
element.SetAttribute("disablePreload", IsPreloadDisabled());
}
std::map<gd::String, gd::PropertyDescriptor> TilesetResource::GetProperties()
const {
std::map<gd::String, gd::PropertyDescriptor> properties;
properties["disablePreload"]
.SetValue(disablePreload ? "true" : "false")
.SetType("Boolean")
.SetLabel(_("Disable preloading at game startup"));
return properties;
}
bool TilesetResource::UpdateProperty(const gd::String& name,
const gd::String& value) {
if (name == "disablePreload") disablePreload = value == "1";
return true;
}
void BitmapFontResource::SetFile(const gd::String& newFile) {
file = NormalizePathSeparator(newFile);
}
+41
View File
@@ -414,6 +414,47 @@ class GD_CORE_API TilemapResource : public Resource {
gd::String file;
};
/**
* \brief Describe a tileset file used by a project.
*
* \see Resource
* \ingroup ResourcesManagement
*/
class GD_CORE_API TilesetResource : public Resource {
public:
TilesetResource() : Resource(), disablePreload(false) { SetKind("tileset"); };
virtual ~TilesetResource(){};
virtual TilesetResource* Clone() const override {
return new TilesetResource(*this);
}
virtual const gd::String& GetFile() const override { return file; };
virtual void SetFile(const gd::String& newFile) override;
virtual bool UseFile() const override { return true; }
std::map<gd::String, gd::PropertyDescriptor> GetProperties() const override;
bool UpdateProperty(const gd::String& name, const gd::String& value) override;
void SerializeTo(SerializerElement& element) const override;
void UnserializeFrom(const SerializerElement& element) override;
/**
* \brief Return true if the loading at game startup must be disabled
*/
bool IsPreloadDisabled() const { return disablePreload; }
/**
* \brief Set if the tilemap preload at game startup must be disabled
*/
void DisablePreload(bool disable = true) { disablePreload = disable; }
private:
bool disablePreload; ///< If "true", don't load the tilemap at game startup
gd::String file;
};
/**
* \brief Describe a bitmap font file used by a project.
*
+3 -2
View File
@@ -89,6 +89,7 @@ const defineTileMap = function (
'tilesetJsonFile',
new gd.PropertyDescriptor(objectContent.tilesetJsonFile || '')
.setType('resource')
.addExtraInfo('tileset')
.addExtraInfo('json')
.setLabel(_('Tileset JSON file (optional)'))
.setDescription(
@@ -254,7 +255,7 @@ const defineTileMap = function (
'JsPlatform/Extensions/tile_map.svg'
)
.addParameter('object', _('Tile map'), 'TileMap', false)
.addParameter('jsonResource', _('Tileset JSON file'), '', false)
.addParameter('tilesetResource', _('Tileset JSON file'), '', false)
.getCodeExtraInformation()
.setFunctionName('isTilesetJsonFile');
@@ -271,7 +272,7 @@ const defineTileMap = function (
'JsPlatform/Extensions/tile_map.svg'
)
.addParameter('object', _('Tile map'), 'TileMap', false)
.addParameter('jsonResource', _('Tileset JSON file'), '', false)
.addParameter('tilesetResource', _('Tileset JSON file'), '', false)
.getCodeExtraInformation()
.setFunctionName('setTilesetJsonFile');
+9 -2
View File
@@ -76,7 +76,12 @@ namespace gdjs {
): void {
const resources = this._resources;
const jsonResources = resources.filter(function (resource) {
return resource.kind === 'json' && !resource.disablePreload;
return (
(resource.kind === 'json' ||
resource.kind === 'tilemap' ||
resource.kind === 'tileset') &&
!resource.disablePreload
);
});
if (jsonResources.length === 0) {
return onComplete(jsonResources.length);
@@ -110,7 +115,9 @@ namespace gdjs {
loadJson(resourceName: string, callback: JsonManagerRequestCallback): void {
const resource = this._resources.find(function (resource) {
return (
(resource.kind === 'json' || resource.kind === 'tilemap') &&
(resource.kind === 'json' ||
resource.kind === 'tilemap' ||
resource.kind === 'tileset') &&
resource.name === resourceName
);
});
+1
View File
@@ -241,4 +241,5 @@ declare type ResourceKind =
| 'video'
| 'json'
| 'tilemap'
| 'tileset'
| 'bitmapFont';
+5
View File
@@ -981,6 +981,11 @@ interface TilemapResource {
};
TilemapResource implements Resource;
interface TilesetResource {
void TilesetResource();
};
TilesetResource implements Resource;
interface InitialInstance {
void InitialInstance();
@@ -189,6 +189,8 @@ void ObjectJsImplementation::ExposeResources(gd::ArbitraryResourceWorker& worker
} else if (resourceType == "tilemap") {
worker.ExposeTilemap(newPropertyValue);
worker.ExposeEmbeddeds(newPropertyValue);
} else if (resourceType == "tileset") {
worker.ExposeTileset(newPropertyValue);
} else if (resourceType == "bitmapFont") {
worker.ExposeBitmapFont(newPropertyValue);
}
+2 -2
View File
@@ -327,13 +327,13 @@ type ParticleEmitterObject_RendererType = 0 | 1 | 2`
shell.sed(
'-i',
/setKind\(kind: string\): void/,
"setKind(kind: 'image' | 'audio' | 'font' | 'video' | 'json' | 'tilemap'): void",
"setKind(kind: 'image' | 'audio' | 'font' | 'video' | 'json' | 'tilemap' | 'tileset'): void",
'types/gdresource.js'
);
shell.sed(
'-i',
/getKind\(\): string/,
"getKind(): 'image' | 'audio' | 'font' | 'video' | 'json' | 'tilemap'",
"getKind(): 'image' | 'audio' | 'font' | 'video' | 'json' | 'tilemap' | 'tileset'",
'types/gdresource.js'
);
+2 -2
View File
@@ -4,8 +4,8 @@ declare class gdResource {
clone(): gdResource;
setName(name: string): void;
getName(): string;
setKind(kind: 'image' | 'audio' | 'font' | 'video' | 'json' | 'tilemap'): void;
getKind(): 'image' | 'audio' | 'font' | 'video' | 'json' | 'tilemap';
setKind(kind: 'image' | 'audio' | 'font' | 'video' | 'json' | 'tilemap' | 'tileset'): void;
getKind(): 'image' | 'audio' | 'font' | 'video' | 'json' | 'tilemap' | 'tileset';
isUserAdded(): boolean;
setUserAdded(yes: boolean): void;
useFile(): boolean;
+6
View File
@@ -0,0 +1,6 @@
// Automatically generated by GDevelop.js/scripts/generate-types.js
declare class gdTilesetResource extends gdResource {
constructor(): void;
delete(): void;
ptr: number;
};
+1
View File
@@ -99,6 +99,7 @@ declare class libGDevelop {
VideoResource: Class<gdVideoResource>;
JsonResource: Class<gdJsonResource>;
TilemapResource: Class<gdTilemapResource>;
TilesetResource: Class<gdTilesetResource>;
InitialInstance: Class<gdInitialInstance>;
InitialInstancesContainer: Class<gdInitialInstancesContainer>;
HighestZOrderFinder: Class<gdHighestZOrderFinder>;
@@ -177,6 +177,7 @@ export const ResourceCard = ({ resource, onChoose, size }: Props) => {
);
case 'json':
case 'tilemap':
case 'tileset':
return (
<GenericCard onChoose={onChoose} resource={resource} size={size}>
<Line justifyContent="center">
@@ -0,0 +1,45 @@
// @flow
import { Trans } from '@lingui/macro';
import React, { Component } from 'react';
import ResourceSelector from '../../ResourcesList/ResourceSelector';
import ResourcesLoader from '../../ResourcesLoader';
import { type ParameterFieldProps } from './ParameterFieldCommons';
export default class TilesetResourceField extends Component<
ParameterFieldProps,
void
> {
_field: ?ResourceSelector;
focus(selectAll: boolean = false) {
if (this._field) this._field.focus(selectAll);
}
render() {
if (!this.props.resourceManagementProps || !this.props.project) {
console.error(
'Missing project or resourceManagementProps for TilesetResourceField'
);
return null;
}
return (
<ResourceSelector
margin={this.props.isInline ? 'none' : 'dense'}
project={this.props.project}
resourceManagementProps={this.props.resourceManagementProps}
resourcesLoader={ResourcesLoader}
resourceKind="tileset"
fallbackResourceKind="json"
fullWidth
initialResourceName={this.props.value}
onChange={this.props.onChange}
floatingLabelText={<Trans>Choose the tileset to use</Trans>}
onRequestClose={this.props.onRequestClose}
onApply={this.props.onApply}
ref={field => (this._field = field)}
/>
);
}
}
@@ -62,6 +62,7 @@ import LeaderboardIdField, {
} from './ParameterFields/LeaderboardIdField';
import { IdentifierField } from './ParameterFields/IdentifierField';
import TilemapResourceField from './ParameterFields/TilemapResourceField';
import TilesetResourceField from './ParameterFields/TilesetResourceField';
const gd: libGDevelop = global.gd;
@@ -107,6 +108,7 @@ const components = {
leaderboardId: LeaderboardIdField,
identifier: IdentifierField,
tilemapResource: TilemapResourceField,
tilesetResource: TilesetResourceField,
};
const inlineRenderers: { [string]: ParameterInlineRenderer } = {
default: renderInlineDefaultField,
@@ -308,7 +308,11 @@ export default class PixiResourcesLoader {
);
const resource = project.getResourcesManager().getResource(resourceName);
if (resource.getKind() !== 'json' && resource.getKind() !== 'tilemap')
if (
resource.getKind() !== 'json' &&
resource.getKind() !== 'tilemap' &&
resource.getKind() !== 'tileset'
)
return Promise.reject(
new Error(`The resource called ${resourceName} is not a json file.`)
);
@@ -33,6 +33,7 @@ const resourceKindToInputAcceptedFiles = {
video: 'video/mp4,video/webm',
json: 'application/json',
tilemap: 'application/json',
tileset: 'application/json',
bitmapFont: '.fnt,.xml',
};
@@ -74,6 +74,7 @@ export default class ResourcePreview extends React.PureComponent<Props, State> {
);
case 'json':
case 'tilemap':
case 'tileset':
return (
<GenericIconPreview
renderIcon={props => <InsertDriveFile {...props} />}
@@ -273,7 +273,11 @@ export default class ResourceSelector extends React.Component<Props, State> {
},
};
resourceExternalEditor.edit(externalEditorOptions);
} else if (resourceKind === 'json' || resourceKind === 'tilemap') {
} else if (
resourceKind === 'json' ||
resourceKind === 'tilemap' ||
resourceKind === 'tileset'
) {
const externalEditorOptions = {
project,
resourcesLoader,
@@ -18,6 +18,7 @@ export type ResourceKind =
| 'video'
| 'json'
| 'tilemap'
| 'tileset'
| 'bitmapFont';
export const allResourceKindsAndMetadata = [
@@ -57,6 +58,12 @@ export const allResourceKindsAndMetadata = [
fileExtensions: ['json', 'ldtk', 'tmj'],
createNewResource: () => new gd.TilemapResource(),
},
{
kind: 'tileset',
displayName: t`Tile Set`,
fileExtensions: ['json', 'tsj'],
createNewResource: () => new gd.TilesetResource(),
},
{
kind: 'bitmapFont',
displayName: t`Bitmap Font`,
+3 -1
View File
@@ -198,7 +198,9 @@ export default class ResourcesList extends React.Component<Props, State> {
case 'json':
return 'res/actions/fichier24.png';
case 'tilemap':
return 'res/actions/star24.png';
return 'res/actions/fichier24.png';
case 'tileset':
return 'res/actions/fichier24.png';
case 'video':
return 'JsPlatform/Extensions/videoicon24.png';
case 'font':