diff --git a/CHANGELOG.MD b/CHANGELOG.MD index d02aa1bd6..4d77d562d 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -1,5 +1,23 @@ # Change Log +## v3.64.0 - Nov 10, 2023 + +* Fixes making thumbnails of single-layer prefabs. +* Allows merging Import and Open buttons in the Asset Pack Entry section. +* [#251](https://github.com/PhaserEditor2D/PhaserEditor2D-v3/issues/251) Fixes sprite positioning in Animations Editor. +* [#209](https://github.com/PhaserEditor2D/PhaserEditor2D-v3/issues/209) Improves scene border painting. +* Improves animations preview UI: + - New Animation preview section. + - New Animations Preview section. + - Shows a preview button in the Animation Key user property. +* Adds new Animation section to Sprite game objects. It is about to auto-start a sprite animation. +* Adds `showBeforeDelay` to the Animations Editor. +* Shows Sprite Animation blocks in the Scene Editor's Blocks view. +* Aseprite animations support. +* New Code Snippets scene elements. +* Optimizes pooling of WEBGL contexts. +* [#295](https://github.com/PhaserEditor2D/PhaserEditor2D-v3/issues/295) Fixes tilemapLayer nullable method factory. + ## v3.63.0 - Sep 30, 2023 * Opens the file given in the `openfile` URL search parameter. Like in `?openfile=some/file`. diff --git a/design/aseprite/aseprite.png b/design/aseprite/aseprite.png new file mode 100644 index 000000000..dc4a83e69 Binary files /dev/null and b/design/aseprite/aseprite.png differ diff --git a/design/texture-packer/phasereditor2d.resources/phasereditor2d.resources@1x.tps b/design/texture-packer/phasereditor2d.resources/phasereditor2d.resources@1x.tps index e13437b97..463a7a4ec 100644 --- a/design/texture-packer/phasereditor2d.resources/phasereditor2d.resources@1x.tps +++ b/design/texture-packer/phasereditor2d.resources/phasereditor2d.resources@1x.tps @@ -183,6 +183,7 @@ x1/dark/align-top.png x1/dark/angle.png x1/dark/animations.png + x1/dark/aseprite.png x1/dark/asset-pack.png x1/dark/bitmapfont-type.png x1/dark/blocks.png @@ -246,6 +247,7 @@ x1/light/align-top.png x1/light/angle.png x1/light/animations.png + x1/light/aseprite.png x1/light/asset-pack.png x1/light/bitmapfont-type.png x1/light/blocks.png diff --git a/design/texture-packer/phasereditor2d.resources/phasereditor2d.resources@2x.tps b/design/texture-packer/phasereditor2d.resources/phasereditor2d.resources@2x.tps index 1c40a3809..49e59b1c9 100644 --- a/design/texture-packer/phasereditor2d.resources/phasereditor2d.resources@2x.tps +++ b/design/texture-packer/phasereditor2d.resources/phasereditor2d.resources@2x.tps @@ -183,6 +183,7 @@ x2/dark/align-top@2x.png x2/dark/angle@2x.png x2/dark/animations@2x.png + x2/dark/aseprite@2x.png x2/dark/asset-pack@2x.png x2/dark/bitmapfont-type@2x.png x2/dark/blocks@2x.png @@ -246,6 +247,7 @@ x2/light/align-top@2x.png x2/light/angle@2x.png x2/light/animations@2x.png + x2/light/aseprite@2x.png x2/light/asset-pack@2x.png x2/light/bitmapfont-type@2x.png x2/light/blocks@2x.png diff --git a/design/texture-packer/phasereditor2d.resources/x1/dark/aseprite.png b/design/texture-packer/phasereditor2d.resources/x1/dark/aseprite.png new file mode 100644 index 000000000..e91ae3f5b Binary files /dev/null and b/design/texture-packer/phasereditor2d.resources/x1/dark/aseprite.png differ diff --git a/design/texture-packer/phasereditor2d.resources/x1/light/aseprite.png b/design/texture-packer/phasereditor2d.resources/x1/light/aseprite.png new file mode 100644 index 000000000..e91ae3f5b Binary files /dev/null and b/design/texture-packer/phasereditor2d.resources/x1/light/aseprite.png differ diff --git a/design/texture-packer/phasereditor2d.resources/x2/dark/aseprite@2x.png b/design/texture-packer/phasereditor2d.resources/x2/dark/aseprite@2x.png new file mode 100644 index 000000000..10ef88565 Binary files /dev/null and b/design/texture-packer/phasereditor2d.resources/x2/dark/aseprite@2x.png differ diff --git a/design/texture-packer/phasereditor2d.resources/x2/light/aseprite@2x.png b/design/texture-packer/phasereditor2d.resources/x2/light/aseprite@2x.png new file mode 100644 index 000000000..10ef88565 Binary files /dev/null and b/design/texture-packer/phasereditor2d.resources/x2/light/aseprite@2x.png differ diff --git a/scripts/make-all-help-files.js b/scripts/make-all-help-files.js index 7bfc38a6d..6bbfbb287 100755 --- a/scripts/make-all-help-files.js +++ b/scripts/make-all-help-files.js @@ -8,6 +8,9 @@ utils.makeHelpFile([ "Phaser.Loader.LoaderPlugin.atlas(textureURL)", "Phaser.Types.Loader.FileTypes.AtlasJSONFileConfig.normalMap", + "Phaser.Loader.LoaderPlugin.aseprite(atlasURL)", + "Phaser.Loader.LoaderPlugin.aseprite(textureURL)", + "Phaser.Loader.LoaderPlugin.atlasXML(atlasURL)", "Phaser.Loader.LoaderPlugin.atlasXML(textureURL)", "Phaser.Types.Loader.FileTypes.AtlasXMLFileConfig.normalMap", @@ -285,7 +288,18 @@ utils.makeHelpFile([ "spine.SkinsAndAnimationBoundsProvider(timeStep)", "spine.AnimationState.timeScale", "spine.AnimationStateData.defaultMix", - "spine.AnimationStateData.setMixWith" + "spine.AnimationStateData.setMixWith", + + "Phaser.Types.Animations.PlayAnimationConfig.frameRate", + "Phaser.Types.Animations.PlayAnimationConfig.delay", + "Phaser.Types.Animations.PlayAnimationConfig.repeat", + "Phaser.Types.Animations.PlayAnimationConfig.repeatDelay", + "Phaser.Types.Animations.PlayAnimationConfig.yoyo", + "Phaser.Types.Animations.PlayAnimationConfig.showOnStart", + "Phaser.Types.Animations.PlayAnimationConfig.hideOnComplete", + "Phaser.Types.Animations.PlayAnimationConfig.showBeforeDelay", + "Phaser.Types.Animations.PlayAnimationConfig.startFrame", + "Phaser.Types.Animations.PlayAnimationConfig.timeScale", ], "../source/editor/plugins/phasereditor2d.resources/_res/phasereditor2d.scene/docs/phaser.json"); @@ -300,7 +314,9 @@ utils.makeHelpFile([ "Phaser.Types.Animations.Animation.yoyo", "Phaser.Types.Animations.Animation.showOnStart", "Phaser.Types.Animations.Animation.hideOnComplete", + "Phaser.Types.Animations.Animation.showBeforeDelay", "Phaser.Types.Animations.Animation.skipMissedFrames", + "Phaser.Types.Animations.PlayAnimationConfig.startFrame", ], "../source/editor/plugins/phasereditor2d.resources/_res/phasereditor2d.animations/docs/phaser-docs.json"); diff --git a/source/editor/plugins/colibri/src/ui/controls/properties/FormBuilder.ts b/source/editor/plugins/colibri/src/ui/controls/properties/FormBuilder.ts index 3056cfc65..017fcf0de 100644 --- a/source/editor/plugins/colibri/src/ui/controls/properties/FormBuilder.ts +++ b/source/editor/plugins/colibri/src/ui/controls/properties/FormBuilder.ts @@ -44,11 +44,20 @@ namespace colibri.ui.controls.properties { return label; } - createButton(parent: HTMLElement, text: string, callback: (e?: MouseEvent) => void) { + createButton(parent: HTMLElement, textOrIcon: string | IImage, callback: (e?: MouseEvent) => void) { const btn = document.createElement("button"); - btn.innerText = text; + if (typeof textOrIcon === "string") { + + btn.innerText = textOrIcon; + + } else { + + const iconControl = new controls.IconControl(textOrIcon); + + btn.appendChild(iconControl.getCanvas()); + } btn.addEventListener("click", e => callback(e)); diff --git a/source/editor/plugins/colibri/src/ui/controls/properties/PropertyPage.ts b/source/editor/plugins/colibri/src/ui/controls/properties/PropertyPage.ts index 774448858..fd18797d8 100644 --- a/source/editor/plugins/colibri/src/ui/controls/properties/PropertyPage.ts +++ b/source/editor/plugins/colibri/src/ui/controls/properties/PropertyPage.ts @@ -192,6 +192,7 @@ namespace colibri.ui.controls.properties { const sortedPanes = this._sectionPanes .map(p => p) .sort((a, b) => + sectionIdList.indexOf(a.getSection().getId()) - sectionIdList.indexOf(b.getSection().getId()) ); diff --git a/source/editor/plugins/colibri/src/ui/controls/properties/PropertySection.ts b/source/editor/plugins/colibri/src/ui/controls/properties/PropertySection.ts index 40187eb37..3afefc04d 100644 --- a/source/editor/plugins/colibri/src/ui/controls/properties/PropertySection.ts +++ b/source/editor/plugins/colibri/src/ui/controls/properties/PropertySection.ts @@ -81,6 +81,7 @@ namespace colibri.ui.controls.properties { } isFillSpace() { + return this._fillSpace; } diff --git a/source/editor/plugins/colibri/src/ui/controls/properties/PropertySectionProvider.ts b/source/editor/plugins/colibri/src/ui/controls/properties/PropertySectionProvider.ts index b34d6f6ad..c9415382b 100644 --- a/source/editor/plugins/colibri/src/ui/controls/properties/PropertySectionProvider.ts +++ b/source/editor/plugins/colibri/src/ui/controls/properties/PropertySectionProvider.ts @@ -11,6 +11,17 @@ namespace colibri.ui.controls.properties { abstract addSections(page: PropertyPage, sections: Array>): void; + sortSections(sections: controls.properties.PropertySection[]) { + + sections.sort((a, b) => { + + const aa = a.isFillSpace() ? 1 : 0; + const bb = b.isFillSpace() ? 1 : 0; + + return aa - bb; + }); + } + getEmptySelectionObject() { return null; diff --git a/source/editor/plugins/colibri/src/ui/controls/viewers/IconGridCellRenderer.ts b/source/editor/plugins/colibri/src/ui/controls/viewers/IconGridCellRenderer.ts index 4b90337d3..1a512167d 100644 --- a/source/editor/plugins/colibri/src/ui/controls/viewers/IconGridCellRenderer.ts +++ b/source/editor/plugins/colibri/src/ui/controls/viewers/IconGridCellRenderer.ts @@ -41,10 +41,12 @@ namespace colibri.ui.controls.viewers { } cellHeight(args: RenderCellArgs): number { + return args.viewer.getCellSize(); } preload(args: PreloadCellArgs): Promise { + return this._icon.preload(); } } diff --git a/source/editor/plugins/colibri/src/ui/controls/viewers/TreeViewerRenderer.ts b/source/editor/plugins/colibri/src/ui/controls/viewers/TreeViewerRenderer.ts index b9fb12acd..ac0563c7a 100644 --- a/source/editor/plugins/colibri/src/ui/controls/viewers/TreeViewerRenderer.ts +++ b/source/editor/plugins/colibri/src/ui/controls/viewers/TreeViewerRenderer.ts @@ -170,7 +170,7 @@ namespace colibri.ui.controls.viewers { y += 15; - } else if (renderer.layout === "full-width") { + } else if (renderer.layout === "full-width" && args.h > ROW_HEIGHT * 2) { args2 = new RenderCellArgs( args.canvasContext, args.x, args.y, args.w, args.h - 20, args.obj, args.viewer); diff --git a/source/editor/plugins/colibri/src/ui/ide/ContentTypeEditorFactory.ts b/source/editor/plugins/colibri/src/ui/ide/ContentTypeEditorFactory.ts index 5228eaaba..89de76b14 100644 --- a/source/editor/plugins/colibri/src/ui/ide/ContentTypeEditorFactory.ts +++ b/source/editor/plugins/colibri/src/ui/ide/ContentTypeEditorFactory.ts @@ -6,14 +6,14 @@ namespace colibri.ui.ide { export class ContentTypeEditorFactory extends EditorFactory { private _name: string; - private _contentType: string; + private _contentTypeSet: Set; private _newEditor?: (factory?: ContentTypeEditorFactory) => EditorPart; - constructor(name: string, contentType: string, newEditor: (factory?: ContentTypeEditorFactory) => EditorPart) { + constructor(name: string, contentType: string | string[], newEditor: (factory?: ContentTypeEditorFactory) => EditorPart) { super(); this._name = name; - this._contentType = contentType; + this._contentTypeSet = new Set(Array.isArray(contentType) ? contentType : [contentType]); this._newEditor = newEditor; } @@ -29,7 +29,7 @@ namespace colibri.ui.ide { const contentType = colibri.Platform.getWorkbench() .getContentTypeRegistry().getCachedContentType(input); - return this._contentType === contentType; + return this._contentTypeSet.has(contentType); } return false; diff --git a/source/editor/plugins/colibri/src/ui/ide/properties/BaseManyImagePreviewSection.ts b/source/editor/plugins/colibri/src/ui/ide/properties/BaseManyImagePreviewSection.ts index 7bf19a05e..0baf2a422 100644 --- a/source/editor/plugins/colibri/src/ui/ide/properties/BaseManyImagePreviewSection.ts +++ b/source/editor/plugins/colibri/src/ui/ide/properties/BaseManyImagePreviewSection.ts @@ -11,7 +11,7 @@ namespace colibri.ui.ide.properties { const viewer = new controls.viewers.TreeViewer("colibri.ui.ide.properties.ManyImagePreviewFormArea"); viewer.setContentProvider(new controls.viewers.ArrayTreeContentProvider()); - viewer.setTreeRenderer(new controls.viewers.GridTreeViewerRenderer(viewer, false, true).setPaintItemShadow(true)); + viewer.setTreeRenderer(this.createTreeRenderer(viewer)); this.prepareViewer(viewer); @@ -35,6 +35,11 @@ namespace colibri.ui.ide.properties { }); } + protected createTreeRenderer(viewer: controls.viewers.TreeViewer): controls.viewers.TreeViewerRenderer { + + return new controls.viewers.GridTreeViewerRenderer(viewer, false, true).setPaintItemShadow(true); + } + protected abstract getViewerInput(): Promise; protected abstract prepareViewer(viewer: controls.viewers.TreeViewer); diff --git a/source/editor/plugins/phasereditor2d.animations/src/AnimationsPlugin.ts b/source/editor/plugins/phasereditor2d.animations/src/AnimationsPlugin.ts index d758e2495..5a8920225 100644 --- a/source/editor/plugins/phasereditor2d.animations/src/AnimationsPlugin.ts +++ b/source/editor/plugins/phasereditor2d.animations/src/AnimationsPlugin.ts @@ -19,6 +19,23 @@ namespace phasereditor2d.animations { super("phasereditor2d.animations"); } + async openAnimationInEditor(anim: pack.core.AnimationConfigInPackItem) { + + const animationsItem = anim.getParent(); + + const file = animationsItem.getAnimationsFile(); + + if (file) { + + const editor = colibri.Platform.getWorkbench().openEditor(file); + + if (editor instanceof ui.editors.AnimationsEditor) { + + editor.selectAnimationByKey(anim.getKey()); + } + } + } + getPhaserDocs() { if (!this._docs) { @@ -26,7 +43,7 @@ namespace phasereditor2d.animations { this._docs = new phasereditor2d.ide.core.PhaserDocs( resources.ResourcesPlugin.getInstance(), "phasereditor2d.animations/docs/phaser-docs.json"); } - + return this._docs; } @@ -48,6 +65,17 @@ namespace phasereditor2d.animations { reg.addExtension( new colibri.ui.ide.commands.CommandExtension(manager => this.registerCommands(manager)) ); + + // asset pack preview extension + + reg.addExtension(new pack.ui.AssetPackPreviewPropertyProviderExtension( + page => new ui.editors.properties.AnimationInfoSection(page), + )); + + scene.ScenePlugin.getInstance().openAnimationInEditor = anim => { + + return this.openAnimationInEditor(anim); + }; } private registerCommands(manager: colibri.ui.ide.commands.CommandManager) { diff --git a/source/editor/plugins/phasereditor2d.animations/src/ui/editors/AnimationsEditor.ts b/source/editor/plugins/phasereditor2d.animations/src/ui/editors/AnimationsEditor.ts index b0f969036..5bfd3ad96 100644 --- a/source/editor/plugins/phasereditor2d.animations/src/ui/editors/AnimationsEditor.ts +++ b/source/editor/plugins/phasereditor2d.animations/src/ui/editors/AnimationsEditor.ts @@ -21,6 +21,8 @@ namespace phasereditor2d.animations.ui.editors { private _currentDependenciesHash: string; private _menuCreator: AnimationsEditorMenuCreator; private _model: AnimationsModel; + private _editorReady = false; + private _selectAnimationKeyOnBoot: string; static getFactory() { @@ -392,9 +394,9 @@ namespace phasereditor2d.animations.ui.editors { this._overlayLayer = new AnimationsOverlayLayer(this); container.appendChild(this._overlayLayer.getCanvas()); - const pool = Phaser.Display.Canvas.CanvasPool; + this._gameCanvas = scene.ScenePlugin.getInstance().getCanvasManager().takeCanvas(); + this._gameCanvas.style.visibility = "hidden"; - this._gameCanvas = pool.create2D(this.getElement(), 100, 100); this._gameCanvas.style.position = "absolute"; this._gameCanvas.tabIndex = 1; container.appendChild(this._gameCanvas); @@ -408,7 +410,11 @@ namespace phasereditor2d.animations.ui.editors { private registerDropListeners() { - this._gameCanvas.addEventListener("dragover", e => { + // canvas can be reused, don't use it for events + + const eventElement = this._gameCanvas.parentElement; + + eventElement.addEventListener("dragover", e => { const dataArray = controls.Controls.getApplicationDragData(); @@ -424,7 +430,7 @@ namespace phasereditor2d.animations.ui.editors { } }); - this._gameCanvas.addEventListener("drop", e => { + eventElement.addEventListener("drop", e => { e.preventDefault(); @@ -440,7 +446,11 @@ namespace phasereditor2d.animations.ui.editors { this._menuCreator = new AnimationsEditorMenuCreator(this); - this._gameCanvas.addEventListener("contextmenu", e => this.onMenu(e)); + // canvas can be reused, don't use it for events + + const eventElement = this._gameCanvas.parentElement; + + eventElement.addEventListener("contextmenu", e => this.onMenu(e)); } private onMenu(e: MouseEvent) { @@ -464,7 +474,7 @@ namespace phasereditor2d.animations.ui.editors { this._scene = new AnimationsScene(this); this._game = new Phaser.Game({ - type: Phaser.CANVAS, + type: scene.ScenePlugin.DEFAULT_EDITOR_CANVAS_CONTEXT, canvas: this._gameCanvas, scale: { mode: Phaser.Scale.NONE @@ -493,6 +503,8 @@ namespace phasereditor2d.animations.ui.editors { this._gameBooted = true; + this._gameCanvas.style.visibility = "visible"; + if (!this._sceneRead) { await this.readScene(); @@ -502,7 +514,21 @@ namespace phasereditor2d.animations.ui.editors { this.refreshOutline(); - this.setSelection([]); + let selection: Phaser.Animations.Animation[] = []; + + if (this._selectAnimationKeyOnBoot) { + + const anims = this.getAnimations(); + + if (anims) { + + selection = anims.filter(a => a.key === this._selectAnimationKeyOnBoot); + } + } + + this.setSelection(selection); + + this._editorReady = true; } private async readScene() { @@ -744,6 +770,18 @@ namespace phasereditor2d.animations.ui.editors { return list; } + selectAnimationByKey(animationKey: string) { + + if (this._editorReady) { + + this.setSelection(this.getAnimations().filter(a => a.key === animationKey)); + + } else { + + this._selectAnimationKeyOnBoot = animationKey; + } + } + getAnimations() { return this._scene.anims["anims"].getArray(); diff --git a/source/editor/plugins/phasereditor2d.animations/src/ui/editors/AnimationsModel.ts b/source/editor/plugins/phasereditor2d.animations/src/ui/editors/AnimationsModel.ts index b4deb8140..f5537eedd 100644 --- a/source/editor/plugins/phasereditor2d.animations/src/ui/editors/AnimationsModel.ts +++ b/source/editor/plugins/phasereditor2d.animations/src/ui/editors/AnimationsModel.ts @@ -73,6 +73,8 @@ namespace phasereditor2d.animations.ui.editors { if (!a.yoyo) delete a.yoyo; + if (!a.showBeforeDelay) delete a.showBeforeDelay; + if (!a.showOnStart) delete a.showOnStart; if (!a.hideOnComplete) delete a.hideOnComplete; diff --git a/source/editor/plugins/phasereditor2d.animations/src/ui/editors/AnimationsScene.ts b/source/editor/plugins/phasereditor2d.animations/src/ui/editors/AnimationsScene.ts index 64a0db46a..3ae9d8bca 100644 --- a/source/editor/plugins/phasereditor2d.animations/src/ui/editors/AnimationsScene.ts +++ b/source/editor/plugins/phasereditor2d.animations/src/ui/editors/AnimationsScene.ts @@ -207,8 +207,8 @@ namespace phasereditor2d.animations.ui.editors { sprite.setScale(scale, scale); - const marginX = size - sprite.width * scale; - const marginY = size - sprite.height * scale; + const marginX = size / 2 - sprite.width * scale / 2; + const marginY = size / 2 - sprite.height * scale / 2; sprite.setData("cell", { x, y, size }); diff --git a/source/editor/plugins/phasereditor2d.animations/src/ui/editors/EditorAnimationCellRenderer.ts b/source/editor/plugins/phasereditor2d.animations/src/ui/editors/EditorAnimationCellRenderer.ts index 3942e6db2..600acd09f 100644 --- a/source/editor/plugins/phasereditor2d.animations/src/ui/editors/EditorAnimationCellRenderer.ts +++ b/source/editor/plugins/phasereditor2d.animations/src/ui/editors/EditorAnimationCellRenderer.ts @@ -37,7 +37,7 @@ namespace phasereditor2d.animations.ui.editors { ctx.save(); - if (cellSize <= controls.ROW_HEIGHT) { + if (cellSize <= controls.ROW_HEIGHT * 2) { const img = this.getImage(frames[0]); diff --git a/source/editor/plugins/phasereditor2d.animations/src/ui/editors/properties/AnimationInfoSection.ts b/source/editor/plugins/phasereditor2d.animations/src/ui/editors/properties/AnimationInfoSection.ts new file mode 100644 index 000000000..44ff4d1c5 --- /dev/null +++ b/source/editor/plugins/phasereditor2d.animations/src/ui/editors/properties/AnimationInfoSection.ts @@ -0,0 +1,92 @@ +namespace phasereditor2d.animations.ui.editors.properties { + + import controls = colibri.ui.controls; + + export class AnimationInfoSection + extends controls.properties.PropertySection { + + constructor(page: controls.properties.PropertyPage) { + super(page, "phasereditor2d.animations.ui.editors.properties", "Animation Info", false); + } + + createForm(parent: HTMLDivElement): void { + + const comp = this.createGridElement(parent, 2); + + { + // Animation Key + this.createLabel(comp, "Animation Key"); + + const btn = this.createButton(comp, "", () => { + + const anim = this.getSelectionFirstElement(); + + AnimationsPlugin.getInstance().openAnimationInEditor(anim); + }); + + this.addUpdater(() => { + + const anim = this.getSelectionFirstElement(); + + btn.textContent = anim.getKey(); + }); + } + + { + // Animations File + this.createLabel(comp, "Animations File"); + + const btn = this.createButton(comp, "", () => { + + const file = this.getSelectionFirstElement().getParent().getAnimationsFile(); + + if (file) { + + colibri.Platform.getWorkbench().openEditor(file); + } + }); + + this.addUpdater(() => { + + const anim = this.getSelectionFirstElement(); + + const file = anim.getParent().getAnimationsFile(); + + btn.textContent = file ? + file.getName() + " - " + file.getParent().getProjectRelativeName() + : ""; + }); + } + + { + // preview button + + this.createButton(comp, "Preview Animation", async () => { + + const elem = this.getSelectionFirstElement(); + + const animAsset = elem.getParent(); + const animationKey = elem.getKey(); + + const dlg = new scene.ui.sceneobjects.AnimationPreviewDialog( + animAsset, { + key: animationKey + }); + + dlg.create(); + + }).style.gridColumn = "span 2"; + } + } + + canEdit(obj: any, n: number): boolean { + + return obj instanceof pack.core.AnimationConfigInPackItem; + } + + canEditNumber(n: number): boolean { + + return n === 1; + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.animations/src/ui/editors/properties/AnimationSection.ts b/source/editor/plugins/phasereditor2d.animations/src/ui/editors/properties/AnimationSection.ts index 5ba86a9fc..90d6abcc0 100644 --- a/source/editor/plugins/phasereditor2d.animations/src/ui/editors/properties/AnimationSection.ts +++ b/source/editor/plugins/phasereditor2d.animations/src/ui/editors/properties/AnimationSection.ts @@ -69,6 +69,8 @@ namespace phasereditor2d.animations.ui.editors.properties { this.createBooleanProperty(comp, "yoyo", "Yoyo"); + this.createBooleanProperty(comp, "showBeforeDelay", "Show Before Delay"); + this.createBooleanProperty(comp, "showOnStart", "Show On Start"); this.createBooleanProperty(comp, "hideOnComplete", "Hide On Complete"); diff --git a/source/editor/plugins/phasereditor2d.files/src/ui/views/FilePropertySectionProvider.ts b/source/editor/plugins/phasereditor2d.files/src/ui/views/FilePropertySectionProvider.ts index 99bfd2fac..41faae380 100644 --- a/source/editor/plugins/phasereditor2d.files/src/ui/views/FilePropertySectionProvider.ts +++ b/source/editor/plugins/phasereditor2d.files/src/ui/views/FilePropertySectionProvider.ts @@ -23,13 +23,7 @@ namespace phasereditor2d.files.ui.views { } } - sections.sort((a, b) => { - - const aa = a.isFillSpace() ? 1 : 0; - const bb = b.isFillSpace() ? 1 : 0; - - return aa - bb; - }); + this.sortSections(sections); } protected acceptSection(section: controls.properties.PropertySection) { diff --git a/source/editor/plugins/phasereditor2d.pack/src/AssetPackPlugin.ts b/source/editor/plugins/phasereditor2d.pack/src/AssetPackPlugin.ts index 85ef122e7..dcfa76ab4 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/AssetPackPlugin.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/AssetPackPlugin.ts @@ -148,6 +148,12 @@ namespace phasereditor2d.pack { 5 )); + reg.addExtension( + new colibri.core.ContentTypeExtension( + [new pack.core.contentTypes.AsepriteContentTypeResolver()], + 4 + )); + reg.addExtension( new colibri.core.ContentTypeExtension( [new pack.core.contentTypes.BitmapFontContentTypeResolver()], @@ -194,6 +200,10 @@ namespace phasereditor2d.pack { iconName: resources.ICON_ANIMATIONS, contentType: core.contentTypes.CONTENT_TYPE_ANIMATIONS }, + { + iconName: resources.ICON_ASEPRITE, + contentType: core.contentTypes.CONTENT_TYPE_ASEPRITE + }, { iconName: resources.ICON_TILEMAP, contentType: core.contentTypes.CONTENT_TYPE_TILEMAP_TILED_JSON diff --git a/source/editor/plugins/phasereditor2d.pack/src/core/AnimationConfigInPackItem.ts b/source/editor/plugins/phasereditor2d.pack/src/core/AnimationConfigInPackItem.ts index f233fdb8f..5df536677 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/core/AnimationConfigInPackItem.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/core/AnimationConfigInPackItem.ts @@ -2,14 +2,21 @@ namespace phasereditor2d.pack.core { export class AnimationConfigInPackItem { + private _parent: BaseAnimationsAssetPackItem; private _key: string; private _frames: AnimationFrameConfigInPackItem[]; - constructor() { + constructor(parent: BaseAnimationsAssetPackItem) { + this._parent = parent; this._frames = []; } + getParent() { + + return this._parent; + } + getKey() { return this._key; @@ -24,5 +31,27 @@ namespace phasereditor2d.pack.core { return this._frames; } + + getPreviewFrame() { + + if (this._frames.length > 0) { + + return this._frames[Math.floor(frames.length / 2)]; + } + + return null; + } + + getPreviewImageAsset() { + + const frame = this.getPreviewFrame(); + + if (frame) { + + return frame.getImageAsset(); + } + + return null; + } } } \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.pack/src/core/AnimationFrameConfigInPackItem.ts b/source/editor/plugins/phasereditor2d.pack/src/core/AnimationFrameConfigInPackItem.ts index 5e38081a3..c8cad091b 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/core/AnimationFrameConfigInPackItem.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/core/AnimationFrameConfigInPackItem.ts @@ -4,6 +4,34 @@ namespace phasereditor2d.pack.core { private _textureKey: string; private _frameKey: string | number; + private _textureFrame: ImageAssetPackItem | AssetPackImageFrame; + + setTextureFrame(textureFrame: ImageAssetPackItem | AssetPackImageFrame) { + + this._textureFrame = textureFrame; + } + + getImageAsset() { + + if (this._textureFrame) { + + if (this._textureFrame instanceof pack.core.ImageAssetPackItem) { + + return this._textureFrame.getFrames()[0]; + + } else if (this._textureFrame instanceof pack.core.AssetPackImageFrame) { + + return this._textureFrame; + } + } + + return null; + } + + getTextureFrame() { + + return this._textureFrame; + } getTextureKey() { diff --git a/source/editor/plugins/phasereditor2d.pack/src/core/AnimationsAssetPackItem.ts b/source/editor/plugins/phasereditor2d.pack/src/core/AnimationsAssetPackItem.ts index cf0ac5234..a7ac0a8a2 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/core/AnimationsAssetPackItem.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/core/AnimationsAssetPackItem.ts @@ -1,72 +1,45 @@ -/// +/// namespace phasereditor2d.pack.core { - import controls = colibri.ui.controls; + export class AnimationsAssetPackItem extends BaseAnimationsAssetPackItem { - export class AnimationsAssetPackItem extends AssetPackItem { + override getAnimationsFile() { - private _animations: AnimationConfigInPackItem[]; - - constructor(pack: AssetPack, data: any) { - super(pack, data); + const url = this.getData()["url"]; + + return this.getFileFromAssetUrl(url); } - getUrl() { - - return this.getData()["url"]; - } + protected override async parseAnimations(animations: AnimationConfigInPackItem[]): Promise { - getAnimations() { - - return this._animations || []; - } - - async preload() { - - if (this._animations) { - - return controls.PreloadResult.NOTHING_LOADED; - } + const file = this.getAnimationsFile(); - this._animations = []; + if (file) { - try { + const content = await colibri.ui.ide.FileUtils.preloadAndGetFileString(file); - const file = this.getFileFromAssetUrl(this.getUrl()); + const data = JSON.parse(content) as Phaser.Types.Animations.JSONAnimations; - if (file) { + for (const animData of data.anims) { - const content = await colibri.ui.ide.FileUtils.preloadAndGetFileString(file); + const animConfig = new AnimationConfigInPackItem(this); - const data = JSON.parse(content) as Phaser.Types.Animations.JSONAnimations; + animConfig.setKey(animData.key); - for (const animData of data.anims) { + for (const frameData of animData.frames) { - const animConfig = new AnimationConfigInPackItem(); + const frameConfig = new AnimationFrameConfigInPackItem(); - animConfig.setKey(animData.key); + frameConfig.setTextureKey(frameData.key); + frameConfig.setFrameKey(frameData.frame); - for (const frameData of animData.frames) { - - const frameConfig = new AnimationFrameConfigInPackItem(); - - frameConfig.setTextureKey(frameData.key); - frameConfig.setFrameKey(frameData.frame); - - animConfig.getFrames().push(frameConfig); - } - - this._animations.push(animConfig); + animConfig.getFrames().push(frameConfig); } - } - - } catch (e) { - console.error(e); + animations.push(animConfig); + } } - - return controls.PreloadResult.RESOURCES_LOADED; } } } \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.pack/src/core/AsepriteAssetPackItem.ts b/source/editor/plugins/phasereditor2d.pack/src/core/AsepriteAssetPackItem.ts new file mode 100644 index 000000000..99584e128 --- /dev/null +++ b/source/editor/plugins/phasereditor2d.pack/src/core/AsepriteAssetPackItem.ts @@ -0,0 +1,118 @@ +/// + +namespace phasereditor2d.pack.core { + + import controls = colibri.ui.controls; + import io = colibri.core.io; + + interface IAsepriteData { + meta: { + frameTags: { + name: string, + from: number, + to: number + }[] + } + } + + export class AsepriteAssetPackItem extends BaseAnimationsAssetPackItem { + + private _atlasItem: AtlasAssetPackItem; + + constructor(pack: AssetPack, data: any) { + super(pack, data); + + this._atlasItem = new AtlasAssetPackItem(this.getPack(), this.getData()); + } + + override getAnimationsFile() { + + const url = this.getData()["atlasURL"]; + + return this.getFileFromAssetUrl(url); + } + + getAtlasFile() { + + return this.getAnimationsFile(); + } + + getTextureFile() { + + const url = this.getData()["textureURL"]; + + return this.getFileFromAssetUrl(url); + } + + preloadImages(): Promise { + + return this._atlasItem.preloadImages(); + } + + async preload(): Promise { + + await this._atlasItem.preload(); + + return super.preload(); + } + + findFrame(frameName: string | number) { + + return this._atlasItem.findFrame(frameName); + } + + getFrames() { + + return this._atlasItem.getFrames(); + } + + protected async parseAnimations(animations: AnimationConfigInPackItem[]): Promise { + + const atlasURL = this.getData().atlasURL; + + const file = this.getFileFromAssetUrl(atlasURL); + + if (file) { + + const content = await colibri.ui.ide.FileUtils.preloadAndGetFileString(file); + + const data = JSON.parse(content) as IAsepriteData; + + for (const animData of data.meta.frameTags) { + + const animConfig = new AnimationConfigInPackItem(this); + + animConfig.setKey(animData.name); + + for(let i = animData.from; i<= animData.to; i++) { + + const frameKey = i.toString(); + + const frameConfig = new AnimationFrameConfigInPackItem(); + + frameConfig.setTextureKey(this.getKey()); + frameConfig.setFrameKey(frameKey); + + animConfig.getFrames().push(frameConfig); + } + + animations.push(animConfig); + } + } + } + + addToPhaserCache(game: Phaser.Game, cache: parsers.AssetPackCache): void { + + const parser = new parsers.AtlasParser(this._atlasItem); + + parser.addToPhaserCache(game, cache); + } + + computeUsedFiles(files: Set) { + + super.computeUsedFiles(files); + + this.addFilesFromDataKey(files, "atlasURL", "textureURL", "normalMap"); + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.pack/src/core/AssetPack.ts b/source/editor/plugins/phasereditor2d.pack/src/core/AssetPack.ts index befc68d7f..073adc7b4 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/core/AssetPack.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/core/AssetPack.ts @@ -14,6 +14,7 @@ namespace phasereditor2d.pack.core { export const SPINE_ATLAS_TYPE = "spineAtlas"; export const SPRITESHEET_TYPE = "spritesheet"; export const ANIMATION_TYPE = "animation"; + export const ASEPRITE_TYPE = "aseprite"; export const AUDIO_TYPE = "audio"; export const AUDIO_SPRITE_TYPE = "audioSprite"; export const BINARY_TYPE = "binary"; diff --git a/source/editor/plugins/phasereditor2d.pack/src/core/AssetPackItem.ts b/source/editor/plugins/phasereditor2d.pack/src/core/AssetPackItem.ts index ad3bc7cf1..321a7e207 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/core/AssetPackItem.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/core/AssetPackItem.ts @@ -99,6 +99,16 @@ namespace phasereditor2d.pack.core { return controls.Controls.resolveNothingLoaded(); } + /** + * For building connections with other assets. + * It is the case of the frames of the sprite animations. + * + * @param finder + */ + async build(finder: pack.core.PackFinder) { + // empty + } + resetCache() { // empty } @@ -111,12 +121,12 @@ namespace phasereditor2d.pack.core { computeHash() { const files = new Set(); - + this.computeUsedFiles(files); const builder = new ide.core.MultiHashBuilder(); - for(const file of files) { + for (const file of files) { builder.addPartialFileToken(file); } diff --git a/source/editor/plugins/phasereditor2d.pack/src/core/BaseAnimationsAssetPackItem.ts b/source/editor/plugins/phasereditor2d.pack/src/core/BaseAnimationsAssetPackItem.ts new file mode 100644 index 000000000..faf035c6c --- /dev/null +++ b/source/editor/plugins/phasereditor2d.pack/src/core/BaseAnimationsAssetPackItem.ts @@ -0,0 +1,62 @@ +/// + +namespace phasereditor2d.pack.core { + + import controls = colibri.ui.controls; + import io = colibri.core.io; + + export abstract class BaseAnimationsAssetPackItem extends AssetPackItem { + + private _animations: AnimationConfigInPackItem[]; + + constructor(pack: AssetPack, data: any) { + super(pack, data); + } + + abstract getAnimationsFile(): io.FilePath; + + getAnimations() { + + return this._animations || []; + } + + async preload(): Promise { + + if (this._animations) { + + return controls.PreloadResult.NOTHING_LOADED; + } + + this._animations = []; + + try { + + await this.parseAnimations(this._animations); + + } catch (e) { + + console.error(e); + } + + return controls.PreloadResult.RESOURCES_LOADED; + } + + protected abstract parseAnimations(animations: AnimationConfigInPackItem[]): Promise; + + async build(finder: PackFinder) { + + for (const anim of this._animations) { + + for (const frameConfig of anim.getFrames()) { + + const textureKey = frameConfig.getTextureKey(); + const frameKey = frameConfig.getFrameKey(); + + const textureFrame = finder.getAssetPackItemOrFrame(textureKey, frameKey); + + frameConfig.setTextureFrame(textureFrame); + } + } + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.pack/src/core/BaseAtlasAssetPackItem.ts b/source/editor/plugins/phasereditor2d.pack/src/core/BaseAtlasAssetPackItem.ts index 8ffb152f6..d2fee1223 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/core/BaseAtlasAssetPackItem.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/core/BaseAtlasAssetPackItem.ts @@ -10,7 +10,7 @@ namespace phasereditor2d.pack.core { super.computeUsedFiles(files); - this.addFilesFromDataKey(files, "atlasURL", "textureURL"); + this.addFilesFromDataKey(files, "atlasURL", "textureURL", "normalMap"); } } } \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.pack/src/core/ImageFrameContainerAssetPackItem.ts b/source/editor/plugins/phasereditor2d.pack/src/core/ImageFrameContainerAssetPackItem.ts index e0acedeb8..86079fed3 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/core/ImageFrameContainerAssetPackItem.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/core/ImageFrameContainerAssetPackItem.ts @@ -181,8 +181,8 @@ namespace phasereditor2d.pack.core { protected abstract createParser(): parsers.ImageFrameParser; - findFrame(frameName: any) { - + findFrame(frameName: string | number) { + return this.getFrames().find(f => f.getName() === frameName); } diff --git a/source/editor/plugins/phasereditor2d.pack/src/core/PackFinder.ts b/source/editor/plugins/phasereditor2d.pack/src/core/PackFinder.ts index 471d63248..2d9f9d6d6 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/core/PackFinder.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/core/PackFinder.ts @@ -25,6 +25,7 @@ namespace phasereditor2d.pack.core { for (const item of items) { const result2 = await item.preload(); + result = Math.max(result, result2); if (monitor) { @@ -33,6 +34,11 @@ namespace phasereditor2d.pack.core { } } + for (const item of items) { + + await item.build(this); + } + return Promise.resolve(result); } @@ -49,6 +55,17 @@ namespace phasereditor2d.pack.core { .filter(i => !filter || filter(i)); } + findAnimationByKey(key: string) { + + return this.getAssets() + + .filter(i => i instanceof BaseAnimationsAssetPackItem) + + .flatMap((i: BaseAnimationsAssetPackItem) => i.getAnimations()) + + .find(a => a.getKey() === key); + } + findAssetPackItem(key: string) { if (!key) { @@ -60,36 +77,12 @@ namespace phasereditor2d.pack.core { .find(item => item.getKey() === key); } - findPackItemOrFrameWithKey(key: string) { - - for (const pack of this._packs) { - - for (const item of pack.getItems()) { - - if (item.getKey() === key) { - return item; - } - - if (item instanceof ImageFrameContainerAssetPackItem) { - - for (const frame of item.getFrames()) { - - if (frame.getName() === key) { - return frame; - } - } - } - } - } - - return null; - } - - getAssetPackItemOrFrame(key: string, frame: any) { + getAssetPackItemOrFrame(key: string, frame: any): ImageAssetPackItem | AssetPackImageFrame { const item = this.findAssetPackItem(key); if (!item) { + return null; } @@ -97,14 +90,20 @@ namespace phasereditor2d.pack.core { return item; - } else if (item instanceof ImageFrameContainerAssetPackItem) { + } else if (item instanceof ImageFrameContainerAssetPackItem + || item instanceof AsepriteAssetPackItem) { const imageFrame = item.findFrame(frame); return imageFrame; } - return item; + if (item instanceof ImageAssetPackItem) { + + return item; + } + + return null; } getAssetPackItemImage(key: string, frame: any): AssetPackImageFrame { @@ -118,7 +117,6 @@ namespace phasereditor2d.pack.core { } else if (asset instanceof AssetPackImageFrame) { return asset; - } return null; diff --git a/source/editor/plugins/phasereditor2d.pack/src/core/contentTypes/AsepriteContentTypeResolver.ts b/source/editor/plugins/phasereditor2d.pack/src/core/contentTypes/AsepriteContentTypeResolver.ts new file mode 100644 index 000000000..0980a70d0 --- /dev/null +++ b/source/editor/plugins/phasereditor2d.pack/src/core/contentTypes/AsepriteContentTypeResolver.ts @@ -0,0 +1,44 @@ +namespace phasereditor2d.pack.core.contentTypes { + + import io = colibri.core.io; + import ide = colibri.ui.ide; + + export const CONTENT_TYPE_ASEPRITE = "Aseprite"; + + export class AsepriteContentTypeResolver implements colibri.core.IContentTypeResolver { + + getId(): string { + return "phasereditor2d.pack.core.AsepriteContentTypeResolver"; + } + + async computeContentType(file: io.FilePath): Promise { + + if (file.getExtension() === "json") { + + const content = await ide.FileUtils.preloadAndGetFileString(file); + + try { + + const data = JSON.parse(content); + + if (data.meta) { + + const app = data.meta.app || ""; + + if (app.indexOf("www.aseprite.org") >= 0) { + + return CONTENT_TYPE_ASEPRITE; + } + } + + } catch (e) { + // nothing + } + } + + return colibri.core.CONTENT_TYPE_ANY; + } + + } + +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.pack/src/core/parsers/AssetPackCache.ts b/source/editor/plugins/phasereditor2d.pack/src/core/parsers/AssetPackCache.ts index 1539e38ee..1dc947085 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/core/parsers/AssetPackCache.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/core/parsers/AssetPackCache.ts @@ -29,11 +29,6 @@ namespace phasereditor2d.pack.core.parsers { this._assets.add(asset); } - getAssets() { - - return this._assets; - } - findAsset(key: string) { for(const asset of this._assets) { @@ -80,7 +75,7 @@ namespace phasereditor2d.pack.core.parsers { const files = new Set(); - for (const asset of this.getAssets()) { + for (const asset of this._assets) { files.add(asset.getPack().getFile()); diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/DefaultAssetPackExtension.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/DefaultAssetPackExtension.ts index bada3b0e4..58ab83d6c 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/ui/DefaultAssetPackExtension.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/DefaultAssetPackExtension.ts @@ -11,6 +11,7 @@ namespace phasereditor2d.pack.ui { core.MULTI_ATLAS_TYPE, core.SPRITESHEET_TYPE, core.ANIMATION_TYPE, + core.ASEPRITE_TYPE, core.BITMAP_FONT_TYPE, core.TILEMAP_CSV_TYPE, core.TILEMAP_IMPACT_TYPE, @@ -45,6 +46,7 @@ namespace phasereditor2d.pack.ui { multiatlas: "Multiatlas", spritesheet: "Spritesheet", animation: "Animation", + aseprite: "Aseprite", bitmapFont: "Bitmap Font", tilemapCSV: "Tilemap CSV", tilemapImpact: "Tilemap Impact", @@ -100,6 +102,9 @@ namespace phasereditor2d.pack.ui { case core.ANIMATION_TYPE: return new core.AnimationsAssetPackItem(pack, data); + case core.ASEPRITE_TYPE: + return new core.AsepriteAssetPackItem(pack, data); + case core.BITMAP_FONT_TYPE: return new core.BitmapFontAssetPackItem(pack, data); @@ -207,6 +212,8 @@ namespace phasereditor2d.pack.ui { core.contentTypes.CONTENT_TYPE_ANIMATIONS, core.ANIMATION_TYPE), + new editor.properties.AsepriteSection(page), + new editor.properties.BitmapFontSection(page), new editor.properties.TilemapCSVSection(page), @@ -320,6 +327,10 @@ namespace phasereditor2d.pack.ui { new ui.properties.ManyImagePreviewSection(page), + new ui.properties.AnimationsPreviewSection(page), + + new ui.properties.AnimationPreviewSection(page), + ...exts.flatMap(ext => ext.getSections(page)) ]; } @@ -422,7 +433,9 @@ namespace phasereditor2d.pack.ui { } else if (element instanceof core.AnimationConfigInPackItem) { - return DefaultAssetPackExtension.getIconRenderer(resources.getIcon(resources.ICON_ANIMATIONS), layout); + // return DefaultAssetPackExtension.getIconRenderer(resources.getIcon(resources.ICON_ANIMATIONS), layout); + + return new viewers.AnimationConfigCellRenderer(); } return undefined; @@ -467,8 +480,16 @@ namespace phasereditor2d.pack.ui { new importers.UnityAtlasImporter(), + new importers.SpineImporter(core.contentTypes.CONTENT_TYPE_SPINE_JSON, core.SPINE_JSON_TYPE), + + new importers.SpineImporter(core.contentTypes.CONTENT_TYPE_SPINE_BINARY, core.SPINE_BINARY_TYPE), + + new importers.SpineAtlasImporter(), + new importers.BitmapFontImporter(), + new importers.AsepriteImporter(), + new importers.SingleFileImporter(webContentTypes.core.CONTENT_TYPE_IMAGE, core.IMAGE_TYPE), new importers.SingleFileImporter(webContentTypes.core.CONTENT_TYPE_SVG, core.IMAGE_TYPE), @@ -480,6 +501,7 @@ namespace phasereditor2d.pack.ui { scale: 0 } }), + new importers.SpritesheetImporter(), new importers.SingleFileImporter(core.contentTypes.CONTENT_TYPE_ANIMATIONS, core.ANIMATION_TYPE), @@ -491,12 +513,6 @@ namespace phasereditor2d.pack.ui { new importers.SingleFileImporter(core.contentTypes.CONTENT_TYPE_TILEMAP_TILED_JSON, core.TILEMAP_TILED_JSON_TYPE), - new importers.SpineImporter(core.contentTypes.CONTENT_TYPE_SPINE_JSON, core.SPINE_JSON_TYPE), - - new importers.SpineImporter(core.contentTypes.CONTENT_TYPE_SPINE_BINARY, core.SPINE_BINARY_TYPE), - - new importers.SpineAtlasImporter(), - new importers.SingleFileImporter(webContentTypes.core.CONTENT_TYPE_JAVASCRIPT, core.PLUGIN_TYPE, false, { start: false, mapping: "" diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/dialogs/AssetSelectionDialog.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/dialogs/AssetSelectionDialog.ts index dba95d3c9..bdf8ed9b5 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/ui/dialogs/AssetSelectionDialog.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/dialogs/AssetSelectionDialog.ts @@ -7,12 +7,15 @@ namespace phasereditor2d.pack.ui.dialogs { private _selectionCallback: (selection: any[]) => void; private _cancelCallback: () => void; private _viewerLayout: "tree" | "grid"; + private _selectOnlyOne: boolean; - constructor(layout: "tree" | "grid" = "grid") { + constructor(layout: "tree" | "grid" = "grid", selectOnlyOne = true) { super(new controls.viewers.TreeViewer("phasereditor2d.pack.ui.dialogs.AssetSelectionDialog"), true); this._viewerLayout = layout; + this._selectOnlyOne = selectOnlyOne; + const size = this.getSize(); this.setSize(size.width, size.height * 1.5); @@ -28,7 +31,7 @@ namespace phasereditor2d.pack.ui.dialogs { this._cancelCallback = callback; } - async getResultPromise(): Promise { + async getResultPromise(): Promise { const promise = new Promise((resolve, reject) => { @@ -39,7 +42,7 @@ namespace phasereditor2d.pack.ui.dialogs { this.setCancelCallback(() => { - reject(); + resolve(undefined); }) }); @@ -50,7 +53,7 @@ namespace phasereditor2d.pack.ui.dialogs { const sel = await this.getResultPromise(); - return sel[0]; + return sel ?? sel[0]; } create(hideParentDialog = true) { @@ -61,7 +64,7 @@ namespace phasereditor2d.pack.ui.dialogs { if (this._viewerLayout === "tree") { - viewer.setTreeRenderer(new controls.viewers.GridTreeViewerRenderer(viewer)); + viewer.setTreeRenderer(new controls.viewers.TreeViewerRenderer(viewer)); } else { @@ -79,15 +82,18 @@ namespace phasereditor2d.pack.ui.dialogs { this.setTitle("Select Asset"); - this.enableButtonOnlyWhenOneElementIsSelected( + const openBtn = this.addOpenButton("Select", sel => { - this.addOpenButton("Select", sel => { + if (this._selectionCallback) { - if (this._selectionCallback) { + this._selectionCallback(sel); + } + }); - this._selectionCallback(sel); - } - })); + if (this._selectOnlyOne) { + + this.enableButtonOnlyWhenOneElementIsSelected(openBtn); + } this.addButton("Cancel", () => { diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/editor/AssetPackEditor.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/editor/AssetPackEditor.ts index e900cd313..15fef9a24 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/ui/editor/AssetPackEditor.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/editor/AssetPackEditor.ts @@ -136,11 +136,24 @@ namespace phasereditor2d.pack.ui.editor { const content = await ide.FileUtils.preloadAndGetFileString(file); + const finder = new pack.core.PackFinder(); + + await finder.preload(); + this._pack = new core.AssetPack(file, content); + for(const item of this._pack.getItems()) { + + await item.preload(); + + await item.build(finder); + } + this.getViewer().repaint(); - await this.updateBlocks(); + await this.refreshBlocks(); + + this._outlineProvider.repaint(); if (this._revealKey) { @@ -201,7 +214,7 @@ namespace phasereditor2d.pack.ui.editor { await this.resetPackCache(); - await this.updateBlocks(); + await this.refreshBlocks(); } private async resetPackCache() { @@ -388,16 +401,20 @@ namespace phasereditor2d.pack.ui.editor { const items = await importData.importer.autoImport(this._pack, importData.files); + const finder = new pack.core.PackFinder(this._pack); + for (const item of items) { await item.preload(); + + await item.build(finder); } this._viewer.repaint(); this.setDirty(true); - await this.updateBlocks(); + await this.refreshBlocks(); this._viewer.setSelection(items); @@ -408,7 +425,7 @@ namespace phasereditor2d.pack.ui.editor { this.getUndoManager().add(new undo.AssetPackEditorOperation(this, before, after)); } - async updateBlocks() { + async refreshBlocks() { if (!this._pack) { return; diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/editor/AssetPackEditorContentProvider.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/editor/AssetPackEditorContentProvider.ts index 931dbfbfd..127ec2a2c 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/ui/editor/AssetPackEditorContentProvider.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/editor/AssetPackEditorContentProvider.ts @@ -13,6 +13,7 @@ namespace phasereditor2d.pack.ui.editor { } getPack() { + return this._editor.getPack(); } @@ -29,6 +30,7 @@ namespace phasereditor2d.pack.ui.editor { getChildren(parent: any): any[] { if (typeof (parent) === "string") { + const type = parent; if (this.getPack()) { diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/editor/AssetPackEditorOutlineContentProvider.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/editor/AssetPackEditorOutlineContentProvider.ts index 679f76ec4..7cc1c05e2 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/ui/editor/AssetPackEditorOutlineContentProvider.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/editor/AssetPackEditorOutlineContentProvider.ts @@ -24,12 +24,17 @@ namespace phasereditor2d.pack.ui.editor { } getChildren(parent: any): any[] { - + if (parent instanceof core.SpineAssetPackItem) { return parent.getGuessSkinItems(); } + if (parent instanceof core.BaseAnimationsAssetPackItem) { + + return parent.getAnimations(); + } + return super.getChildren(parent); } } diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/editor/ImportFileSection.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/editor/ImportFileSection.ts index 6fcd3d574..319b3c6c2 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/ui/editor/ImportFileSection.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/editor/ImportFileSection.ts @@ -16,6 +16,7 @@ namespace phasereditor2d.pack.ui.editor { this.addUpdater(() => { while (comp.children.length > 0) { + comp.children.item(0).remove(); } @@ -58,6 +59,7 @@ namespace phasereditor2d.pack.ui.editor { } canEditNumber(n: number): boolean { + return n > 0; } } diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/editor/properties/AsepriteSection.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/editor/properties/AsepriteSection.ts new file mode 100644 index 000000000..6154484e6 --- /dev/null +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/editor/properties/AsepriteSection.ts @@ -0,0 +1,34 @@ +/// + +namespace phasereditor2d.pack.ui.editor.properties { + + import controls = colibri.ui.controls; + + export class AsepriteSection extends BaseSection { + + constructor(page: controls.properties.PropertyPage) { + super(page, "phasereditor2d.pack.ui.editor.properties.AsepriteSection", "Aseprite", core.ASEPRITE_TYPE); + } + + canEdit(obj: any, n: number) { + + return super.canEdit(obj, n) && obj instanceof core.AsepriteAssetPackItem; + } + + createForm(parent: HTMLDivElement) { + + const comp = this.createGridElement(parent, 3); + + comp.style.gridTemplateColumns = "auto 1fr auto"; + + this.createFileField(comp, "Atlas URL", "atlasURL", core.contentTypes.CONTENT_TYPE_ASEPRITE, + "Phaser.Loader.LoaderPlugin.aseprite(atlasURL)"); + + this.createFileField(comp, "Texture URL", "textureURL", webContentTypes.core.CONTENT_TYPE_IMAGE, + "Phaser.Loader.LoaderPlugin.aseprite(textureURL)"); + + this.createFileField(comp, "Normal Map", "normalMap", webContentTypes.core.CONTENT_TYPE_IMAGE, + "Phaser.Types.Loader.FileTypes.AtlasJSONFileConfig.normalMap"); + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/editor/properties/AssetPackEditorPropertyProvider.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/editor/properties/AssetPackEditorPropertyProvider.ts index 437d10304..014ce89fd 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/ui/editor/properties/AssetPackEditorPropertyProvider.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/editor/properties/AssetPackEditorPropertyProvider.ts @@ -15,6 +15,8 @@ namespace phasereditor2d.pack.ui.editor.properties { .flatMap(ext => ext.createEditorPropertySections(page)); sections.push(...list); + + this.sortSections(sections); } getEmptySelectionObject() { diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/editor/properties/AtlasSection.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/editor/properties/AtlasSection.ts index 58941c5d0..ac16680a9 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/ui/editor/properties/AtlasSection.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/editor/properties/AtlasSection.ts @@ -11,10 +11,12 @@ namespace phasereditor2d.pack.ui.editor.properties { } canEdit(obj: any, n: number) { + return super.canEdit(obj, n) && obj instanceof core.AtlasAssetPackItem; } createForm(parent: HTMLDivElement) { + const comp = this.createGridElement(parent, 3); comp.style.gridTemplateColumns = "auto 1fr auto"; diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/editor/properties/BaseSection.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/editor/properties/BaseSection.ts index 2d8f4c086..ea62c07af 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/ui/editor/properties/BaseSection.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/editor/properties/BaseSection.ts @@ -152,7 +152,9 @@ namespace phasereditor2d.pack.ui.editor.properties { text.value = val === undefined ? "" : val; }); - this.createButton(comp, "Browse", () => { + const icon = colibri.ColibriPlugin.getInstance().getIcon(colibri.ICON_FOLDER); + + this.createButton(comp, icon, () => { this.browseFile_onlyContentType("Select File", contentType, (files) => { diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/editor/properties/BlocksSection.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/editor/properties/BlocksSection.ts index 5b21aa2ad..48baa1a29 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/ui/editor/properties/BlocksSection.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/editor/properties/BlocksSection.ts @@ -18,7 +18,7 @@ namespace phasereditor2d.pack.ui.editor.properties { this.getSelectionFirstElement().setShowAllFilesInBlocks(check.checked); const editor = colibri.Platform.getWorkbench().getActiveEditor() as AssetPackEditor; - editor.updateBlocks(); + editor.refreshBlocks(); editor.setDirty(true); }); diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/importers/AsepriteImporter.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/importers/AsepriteImporter.ts new file mode 100644 index 000000000..fb77da641 --- /dev/null +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/importers/AsepriteImporter.ts @@ -0,0 +1,11 @@ +/// + +namespace phasereditor2d.pack.ui.importers { + + export class AsepriteImporter extends BaseAtlasImporter { + + constructor() { + super(core.contentTypes.CONTENT_TYPE_ASEPRITE, core.ASEPRITE_TYPE); + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/importers/Importer.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/importers/Importer.ts index 9620e6e46..cdf6fbd41 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/ui/importers/Importer.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/importers/Importer.ts @@ -74,6 +74,11 @@ namespace phasereditor2d.pack.ui.importers { await item.preload(); + const finder = new core.PackFinder(); + await finder.preload(); + + await item.build(finder); + return item; } @@ -99,6 +104,12 @@ namespace phasereditor2d.pack.ui.importers { await item.preload(); + const finder = new core.PackFinder(); + + await finder.preload(); + + await item.build(finder); + return item; } } diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/importers/Importers.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/importers/Importers.ts index b678ad245..831c7d6e5 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/ui/importers/Importers.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/importers/Importers.ts @@ -27,6 +27,7 @@ namespace phasereditor2d.pack.ui.importers { } static getImporter(type: string) { + return this.getAll().find(i => i.getType() === type); } } diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/properties/AddFileToPackFileSection.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/properties/AddFileToPackFileSection.ts index c14c74a00..3ff35c285 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/ui/properties/AddFileToPackFileSection.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/properties/AddFileToPackFileSection.ts @@ -29,116 +29,127 @@ namespace phasereditor2d.pack.ui.properties { this.addUpdater(async () => { + comp.innerHTML = ""; + const finder = new core.PackFinder(); await finder.preload(); - const packItems = await this.getPackItems(finder); + await this.buildImportButtons(finder, comp); - comp.innerHTML = ""; + await this.buildOpenButtons(finder, comp); + }); + } - const used = new Set(); + private async buildOpenButtons(finder: core.PackFinder, comp: HTMLDivElement) { - for (const item of packItems) { + const packItems = await this.getPackItems(finder); - const btn = document.createElement("button"); + const used = new Set(); - const key = item.getKey(); - const packPath = item.getPack().getFile().getProjectRelativeName(); - const hash = `${key}@${packPath}`; + for (const item of packItems) { - if (used.has(hash)) { + const btn = document.createElement("button"); - continue; - } + const key = item.getKey(); + const packName = item.getPack().getFile().getName(); + const packPath = item.getPack().getFile().getProjectRelativeName(); + const hash = `${key}@${packPath}`; - used.add(hash); + if (used.has(hash)) { - btn.innerHTML = - `${key} at ${packPath}`; + continue; + } - btn.addEventListener("click", async (e) => { + used.add(hash); - const editor = colibri.Platform.getWorkbench() - .openEditor(item.getPack().getFile()) as editor.AssetPackEditor; + btn.innerHTML = + `Open ${key} at ${packName}`; - editor.revealKey(item.getKey()); - }); + btn.addEventListener("click", async (e) => { - comp.appendChild(btn); - } + const editor = colibri.Platform.getWorkbench() + .openEditor(item.getPack().getFile()) as editor.AssetPackEditor; + + editor.revealKey(item.getKey()); + }); - if (packItems.length === 0) { + comp.appendChild(btn); + } + } - const importList = this.buildImportList(); + private async buildImportButtons(finder: core.PackFinder, comp: HTMLDivElement) { - for (const importData of importList) { + const importersData = await this.buildImportersData(finder); - const btn = document.createElement("button"); + for (const importerData of importersData) { - btn.innerText = `Import as ${importData.importer.getType()} (${importData.files.length})`; + const btn = document.createElement("button"); - btn.addEventListener("click", async (e) => { + const importDesc = importerData.files.length === 1 ? + importerData.files[0].getName() : importerData.files.length.toString(); - const packs = finder.getPacks(); + btn.innerText = `Import as ${importerData.importer.getType()} (${importDesc})`; - const menu = new controls.Menu(); + btn.addEventListener("click", async (e) => { - for (const pack of packs) { + const packs = finder.getPacks(); - const validFiles = importData.files - .filter(file => { + const menu = new controls.Menu(); - const publicRoot = colibri.ui.ide.FileUtils.getPublicRoot(pack.getFile().getParent()); + for (const pack of packs) { - return file.getFullName().startsWith(publicRoot.getFullName()) - }); + const validFiles = importerData.files + .filter(file => { - menu.add(new controls.Action({ - text: "Add To " + pack.getFile().getProjectRelativeName(), - enabled: validFiles.length > 0, - callback: () => { + const publicRoot = colibri.ui.ide.FileUtils.getPublicRoot(pack.getFile().getParent()); - this.importWithImporter(importData, pack); - } - })); + return file.getFullName().startsWith(publicRoot.getFullName()); + }); + + menu.add(new controls.Action({ + text: "Add To " + pack.getFile().getProjectRelativeName(), + enabled: validFiles.length > 0, + callback: () => { + + this.importWithImporter(importerData, pack); } + })); + } - menu.add(new controls.Action({ - text: "Add To New Pack File", - callback: () => { + menu.add(new controls.Action({ + text: "Add To New Pack File", + callback: () => { - const ext = new pack.ui.dialogs.NewAssetPackFileWizardExtension(); + const ext = new pack.ui.dialogs.NewAssetPackFileWizardExtension(); - const dlg = ext.createDialog({ - initialFileLocation: this.getSelectionFirstElement().getParent() - }); + const dlg = ext.createDialog({ + initialFileLocation: this.getSelectionFirstElement().getParent() + }); - dlg.setTitle("New " + ext.getDialogName()); + dlg.setTitle("New " + ext.getDialogName()); - const callback = dlg.getFileCreatedCallback(); + const callback = dlg.getFileCreatedCallback(); - dlg.setFileCreatedCallback(async (file) => { + dlg.setFileCreatedCallback(async (file) => { - await callback(file); + await callback(file); - const content = colibri.ui.ide.FileUtils.getFileString(file); + const content = colibri.ui.ide.FileUtils.getFileString(file); - const pack = new core.AssetPack(file, content); + const pack = new core.AssetPack(file, content); - this.importWithImporter(importData, pack); + this.importWithImporter(importerData, pack); - }); - } - })); + }); + } + })); - menu.createWithEvent(e); - }); + menu.createWithEvent(e); + }); - comp.appendChild(btn); - } - } - }); + comp.appendChild(btn); + } } private async importWithImporter(importData: editor.IImportData, pack: core.AssetPack) { @@ -158,13 +169,25 @@ namespace phasereditor2d.pack.ui.properties { blocks.BlocksPlugin.getInstance().refreshBlocksView(); } - private buildImportList() { + private async buildImportersData(finder: core.PackFinder) { const importList: editor.IImportData[] = []; + const selection: io.FilePath[] = []; + + for (const file of this.getSelection()) { + + const items = await finder.findPackItemsFor(file); + + if (items.length === 0) { + + selection.push(file); + } + } + for (const importer of importers.Importers.getAll()) { - const files = this.getSelection().filter(file => importer.acceptFile(file)); + const files = selection.filter(file => importer.acceptFile(file)); if (files.length > 0) { @@ -193,14 +216,16 @@ namespace phasereditor2d.pack.ui.properties { } } - if (n > 0) { + return n > 0; - const list = this.buildImportList(); + // if (n > 0) { - return list.length > 0; - } + // const list = this.buildImportList(); + + // return list.length > 0; + // } - return false; + // return false; } } } \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/properties/AnimationPreviewSection.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/properties/AnimationPreviewSection.ts new file mode 100644 index 000000000..9022e7710 --- /dev/null +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/properties/AnimationPreviewSection.ts @@ -0,0 +1,26 @@ +namespace phasereditor2d.pack.ui.properties { + + import controls = colibri.ui.controls; + + export class AnimationPreviewSection + extends colibri.ui.ide.properties.BaseImagePreviewSection { + + constructor(page: controls.properties.PropertyPage) { + super(page, "phasereditor2d.pack.ui.properties.AnimationPreviewSection", "Animation Preview", true); + } + + protected getSelectedImage(): controls.IImage { + + const anim = this.getSelection()[0]; + + const img = anim.getPreviewImageAsset(); + + return img; + } + + canEdit(obj: any): boolean { + + return obj instanceof core.AnimationConfigInPackItem; + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/properties/AnimationsPreviewSection.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/properties/AnimationsPreviewSection.ts new file mode 100644 index 000000000..2ce794a4e --- /dev/null +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/properties/AnimationsPreviewSection.ts @@ -0,0 +1,48 @@ +namespace phasereditor2d.pack.ui.properties { + + import controls = colibri.ui.controls; + + export class AnimationsPreviewSection extends colibri.ui.ide.properties.BaseManyImagePreviewSection { + + constructor(page: controls.properties.PropertyPage) { + super(page, "phasereditor2d.pack.ui.properties.AnimationsPreviewSection", "Animations Preview", true); + } + + protected override async getViewerInput() { + + const frames = this.getSelection().flatMap(obj => { + + return obj.getAnimations(); + }); + + return frames; + } + + protected override prepareViewer(viewer: controls.viewers.TreeViewer) { + + viewer.setLabelProvider(new viewers.AssetPackLabelProvider()); + viewer.setCellRendererProvider(new controls.viewers.EmptyCellRendererProvider( + e => new viewers.AnimationConfigCellRenderer("square"))); + + viewer.eventOpenItem.addListener((elem: pack.core.AnimationConfigInPackItem) => { + + AnimationsPreviewSection.openPreviewDialog(elem); + }); + } + + static openPreviewDialog(elem: core.AnimationConfigInPackItem) { + + alert("Preview dialog not found."); + } + + override canEdit(obj: any, n: number): boolean { + + return obj instanceof core.BaseAnimationsAssetPackItem; + } + + override canEditNumber(n: number): boolean { + + return n > 0; + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/properties/AssetPackPreviewPropertyProvider.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/properties/AssetPackPreviewPropertyProvider.ts index 27dc015ea..5283460e3 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/ui/properties/AssetPackPreviewPropertyProvider.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/properties/AssetPackPreviewPropertyProvider.ts @@ -11,6 +11,8 @@ namespace phasereditor2d.pack.ui.properties { sections.push(new pack.ui.properties.AtlasFrameInfoSection(page)); sections.push(new pack.ui.properties.ImagePreviewSection(page)); sections.push(new pack.ui.properties.ManyImagePreviewSection(page)); + sections.push(new pack.ui.properties.AnimationsPreviewSection(page)); + sections.push(new pack.ui.properties.AnimationPreviewSection(page)); sections.push(new pack.ui.properties.BitmapFontPreviewSection(page)); sections.push(new pack.ui.properties.ManyBitmapFontPreviewSection(page)); sections.push(new pack.ui.properties.TilemapTiledSection(page)); @@ -25,6 +27,8 @@ namespace phasereditor2d.pack.ui.properties { sections.push(...ext.getSections(page)); } + + this.sortSections(sections); } } } \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/properties/ManyImagePreviewSection.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/properties/ManyImagePreviewSection.ts index af252ce8d..c2f010ae2 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/ui/properties/ManyImagePreviewSection.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/properties/ManyImagePreviewSection.ts @@ -1,7 +1,6 @@ namespace phasereditor2d.pack.ui.properties { import controls = colibri.ui.controls; - import ide = colibri.ui.ide; export class ManyImagePreviewSection extends colibri.ui.ide.properties.BaseManyImagePreviewSection { diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/viewers/AnimationConfigCellRenderer.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/viewers/AnimationConfigCellRenderer.ts index 840d27439..8f78662bf 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/ui/viewers/AnimationConfigCellRenderer.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/viewers/AnimationConfigCellRenderer.ts @@ -4,12 +4,12 @@ namespace phasereditor2d.pack.ui.viewers { export class AnimationConfigCellRenderer implements controls.viewers.ICellRenderer { - private _finder: pack.core.PackFinder; - public layout: "square" | "full-width" = "full-width"; + public layout: "square" | "full-width"; + private static _finder: pack.core.PackFinder; - constructor(finder: pack.core.PackFinder) { + constructor(layout: "square" | "full-width" = "full-width") { - this._finder = finder; + this.layout = layout; } getAnimationConfig(args: controls.viewers.RenderCellArgs | controls.viewers.PreloadCellArgs): pack.core.AnimationConfigInPackItem { @@ -30,17 +30,13 @@ namespace phasereditor2d.pack.ui.viewers { const cellSize = args.viewer.getCellSize(); - const len = frames.length; - - const indexes = [0, Math.floor(len / 2), len - 1]; - const ctx = args.canvasContext; ctx.save(); - if (cellSize <= controls.ROW_HEIGHT) { + if (cellSize <= controls.ROW_HEIGHT * 2 || this.layout === "square") { - const img = this.getImage(frames[0]); + const img = anim.getPreviewImageAsset(); if (img) { @@ -49,12 +45,16 @@ namespace phasereditor2d.pack.ui.viewers { } else { + const len = frames.length; + + const indexes = [0, Math.floor(len / 2), len - 1]; + // tslint:disable-next-line:prefer-for-of for (let i = 0; i < indexes.length; i++) { const frame = frames[indexes[i]]; - const img = this.getImage(frame); + const img = frame.getImageAsset(); if (img) { @@ -68,13 +68,6 @@ namespace phasereditor2d.pack.ui.viewers { ctx.restore(); } - private getImage(frame: pack.core.AnimationFrameConfigInPackItem) { - - const image = this._finder.getAssetPackItemImage(frame.getTextureKey(), frame.getFrameKey()); - - return image; - } - cellHeight(args: controls.viewers.RenderCellArgs): number { return args.viewer.getCellSize(); @@ -88,11 +81,11 @@ namespace phasereditor2d.pack.ui.viewers { for (const frame of anim.getFrames()) { - const obj = this._finder.getAssetPackItemOrFrame(frame.getTextureKey(), frame.getFrameKey()); + const asset = frame.getTextureFrame(); - if (obj) { + if (asset) { - const objResult = await obj.preload(); + const objResult = await asset.preload(); result = Math.max(result, objResult); } diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/viewers/AnimationsItemCellRenderer.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/viewers/AnimationsItemCellRenderer.ts new file mode 100644 index 000000000..00984872b --- /dev/null +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/viewers/AnimationsItemCellRenderer.ts @@ -0,0 +1,18 @@ +namespace phasereditor2d.pack.ui.viewers { + + import controls = colibri.ui.controls; + + export class AnimationsItemCellRenderer extends controls.viewers.IconImageCellRenderer { + + constructor() { + super(resources.getIcon(resources.ICON_ANIMATIONS)); + } + + async preload(args: controls.viewers.PreloadCellArgs): Promise { + + super.preload(args); + + return (args.obj as pack.core.BaseAnimationsAssetPackItem).preload(); + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/viewers/AsepriteItemCellRenderer.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/viewers/AsepriteItemCellRenderer.ts new file mode 100644 index 000000000..e1d59f670 --- /dev/null +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/viewers/AsepriteItemCellRenderer.ts @@ -0,0 +1,18 @@ +namespace phasereditor2d.pack.ui.viewers { + + import controls = colibri.ui.controls; + + export class AsepriteItemCellRenderer extends controls.viewers.IconImageCellRenderer { + + constructor() { + super(resources.getIcon(resources.ICON_ASEPRITE)); + } + + async preload(args: controls.viewers.PreloadCellArgs): Promise { + + super.preload(args); + + return (args.obj as pack.core.AsepriteAssetPackItem).preload(); + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.pack/src/ui/viewers/AssetPackCellRendererProvider.ts b/source/editor/plugins/phasereditor2d.pack/src/ui/viewers/AssetPackCellRendererProvider.ts index 1e3a4bf6d..9fdafc962 100644 --- a/source/editor/plugins/phasereditor2d.pack/src/ui/viewers/AssetPackCellRendererProvider.ts +++ b/source/editor/plugins/phasereditor2d.pack/src/ui/viewers/AssetPackCellRendererProvider.ts @@ -11,6 +11,7 @@ namespace phasereditor2d.pack.ui.viewers { constructor(layout: "grid" | "tree") { + this._layout = layout; this._fileRendererProvider = new files.ui.viewers.FileCellRendererProvider(layout); @@ -41,6 +42,14 @@ namespace phasereditor2d.pack.ui.viewers { return this._fileRendererProvider.getCellRenderer(element); + } else if (element instanceof pack.core.AnimationsAssetPackItem) { + + return new viewers.AnimationsItemCellRenderer(); + + } else if (element instanceof pack.core.AsepriteAssetPackItem) { + + return new viewers.AsepriteItemCellRenderer(); + } else { const extensions = AssetPackPlugin.getInstance().getExtensions(); diff --git a/source/editor/plugins/phasereditor2d.resources/_res/phasereditor2d.animations/docs/phaser-docs.json b/source/editor/plugins/phasereditor2d.resources/_res/phasereditor2d.animations/docs/phaser-docs.json index 71c70a048..a803a7d63 100644 --- a/source/editor/plugins/phasereditor2d.resources/_res/phasereditor2d.animations/docs/phaser-docs.json +++ b/source/editor/plugins/phasereditor2d.resources/_res/phasereditor2d.animations/docs/phaser-docs.json @@ -7,5 +7,7 @@ "Phaser.Types.Animations.Animation.yoyo": "Should the animation yoyo? (reverse back down to the start) before repeating?", "Phaser.Types.Animations.Animation.showOnStart": "Should sprite.visible = true when the animation starts to play? This happens _after_ any delay, if set.", "Phaser.Types.Animations.Animation.hideOnComplete": "Should sprite.visible = false when the animation finishes?", - "Phaser.Types.Animations.Animation.skipMissedFrames": "Skip frames if the time lags, or always advanced anyway?" + "Phaser.Types.Animations.Animation.showBeforeDelay": "If this animation has a delay, should it show the first frame immediately (true), or only after the delay (false)", + "Phaser.Types.Animations.Animation.skipMissedFrames": "Skip frames if the time lags, or always advanced anyway?", + "Phaser.Types.Animations.PlayAnimationConfig.startFrame": "The frame of the animation to start playback from." } \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.resources/_res/phasereditor2d.pack/docs/phaser-docs.json b/source/editor/plugins/phasereditor2d.resources/_res/phasereditor2d.pack/docs/phaser-docs.json index f8daf0daa..9f18a15f2 100644 --- a/source/editor/plugins/phasereditor2d.resources/_res/phasereditor2d.pack/docs/phaser-docs.json +++ b/source/editor/plugins/phasereditor2d.resources/_res/phasereditor2d.pack/docs/phaser-docs.json @@ -2,6 +2,8 @@ "Phaser.Loader.LoaderPlugin.atlas(atlasURL)": "The absolute or relative URL to load the texture atlas json data file from. If undefined or `null` it will be set to `.json`, i.e. if `key` was \"alien\" then the URL will be \"alien.json\". Or, a well formed JSON object.", "Phaser.Loader.LoaderPlugin.atlas(textureURL)": "The absolute or relative URL to load the texture image file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was \"alien\" then the URL will be \"alien.png\".", "Phaser.Types.Loader.FileTypes.AtlasJSONFileConfig.normalMap": "The filename of an associated normal map. It uses the same path and url to load as the texture image.", + "Phaser.Loader.LoaderPlugin.aseprite(atlasURL)": "The absolute or relative URL to load the texture atlas json data file from. If undefined or `null` it will be set to `.json`, i.e. if `key` was \"alien\" then the URL will be \"alien.json\". Or, a well formed JSON object.", + "Phaser.Loader.LoaderPlugin.aseprite(textureURL)": "The absolute or relative URL to load the texture image file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was \"alien\" then the URL will be \"alien.png\".", "Phaser.Loader.LoaderPlugin.atlasXML(atlasURL)": "The absolute or relative URL to load the texture atlas xml data file from. If undefined or `null` it will be set to `.xml`, i.e. if `key` was \"alien\" then the URL will be \"alien.xml\".", "Phaser.Loader.LoaderPlugin.atlasXML(textureURL)": "The absolute or relative URL to load the texture image file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was \"alien\" then the URL will be \"alien.png\".", "Phaser.Types.Loader.FileTypes.AtlasXMLFileConfig.normalMap": "The filename of an associated normal map. It uses the same path and url to load as the texture image.", diff --git a/source/editor/plugins/phasereditor2d.resources/_res/phasereditor2d.scene/docs/phaser.json b/source/editor/plugins/phasereditor2d.resources/_res/phasereditor2d.scene/docs/phaser.json index 81444c4bc..c99ab5cfc 100644 --- a/source/editor/plugins/phasereditor2d.resources/_res/phasereditor2d.scene/docs/phaser.json +++ b/source/editor/plugins/phasereditor2d.resources/_res/phasereditor2d.scene/docs/phaser.json @@ -177,5 +177,15 @@ "spine.SkinsAndAnimationBoundsProvider(timeStep)": "The time step to use for calculating the bounds. A smaller time step means more precision, but slower calculation.", "spine.AnimationState.timeScale": "Multiplier for the delta time when the animation state is updated, causing time for all animations and mixes to play slower\nor faster. Defaults to 1.\n\nSee TrackEntry {@link TrackEntry#timeScale} for affecting a single animation.", "spine.AnimationStateData.defaultMix": "The mix duration to use when no mix duration has been defined between two animations.", - "spine.AnimationStateData.setMixWith": "Sets the mix duration when changing from the specified animation to the other.\n\nSee {@link TrackEntry#mixDuration}." + "spine.AnimationStateData.setMixWith": "Sets the mix duration when changing from the specified animation to the other.\n\nSee {@link TrackEntry#mixDuration}.", + "Phaser.Types.Animations.PlayAnimationConfig.frameRate": "The frame rate of playback in frames per second (default 24 if duration is null)", + "Phaser.Types.Animations.PlayAnimationConfig.delay": "Delay before starting playback. Value given in milliseconds.", + "Phaser.Types.Animations.PlayAnimationConfig.repeat": "Number of times to repeat the animation (-1 for infinity)", + "Phaser.Types.Animations.PlayAnimationConfig.repeatDelay": "Delay before the animation repeats. Value given in milliseconds.", + "Phaser.Types.Animations.PlayAnimationConfig.yoyo": "Should the animation yoyo? (reverse back down to the start) before repeating?", + "Phaser.Types.Animations.PlayAnimationConfig.showOnStart": "Should sprite.visible = true when the animation starts to play?", + "Phaser.Types.Animations.PlayAnimationConfig.hideOnComplete": "Should sprite.visible = false when the animation finishes?", + "Phaser.Types.Animations.PlayAnimationConfig.showBeforeDelay": "If this animation has a delay, should it show the first frame immediately (true), or only after the delay (false)", + "Phaser.Types.Animations.PlayAnimationConfig.startFrame": "The frame of the animation to start playback from.", + "Phaser.Types.Animations.PlayAnimationConfig.timeScale": "The time scale to be applied to playback of this animation." } \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.resources/icons/atlas@1x.json b/source/editor/plugins/phasereditor2d.resources/icons/atlas@1x.json index 89423aa36..7c6d791fb 100644 --- a/source/editor/plugins/phasereditor2d.resources/icons/atlas@1x.json +++ b/source/editor/plugins/phasereditor2d.resources/icons/atlas@1x.json @@ -80,7 +80,7 @@ "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, "sourceSize": {"w":16,"h":16} }, -"dark/asset-pack.png": +"dark/aseprite.png": { "frame": {"x":1,"y":73,"w":16,"h":16}, "rotated": false, @@ -88,6 +88,14 @@ "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, "sourceSize": {"w":16,"h":16} }, +"dark/asset-pack.png": +{ + "frame": {"x":19,"y":55,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, "dark/bitmapfont-type.png": { "frame": {"x":37,"y":289,"w":15,"h":16}, @@ -98,7 +106,7 @@ }, "dark/blocks.png": { - "frame": {"x":19,"y":55,"w":16,"h":16}, + "frame": {"x":37,"y":37,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -106,7 +114,7 @@ }, "dark/border-bottom.png": { - "frame": {"x":37,"y":37,"w":16,"h":16}, + "frame": {"x":55,"y":19,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -114,7 +122,7 @@ }, "dark/border-center.png": { - "frame": {"x":55,"y":19,"w":16,"h":16}, + "frame": {"x":73,"y":1,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -122,7 +130,7 @@ }, "dark/border-left.png": { - "frame": {"x":73,"y":1,"w":16,"h":16}, + "frame": {"x":1,"y":91,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -130,7 +138,7 @@ }, "dark/border-middle.png": { - "frame": {"x":1,"y":91,"w":16,"h":16}, + "frame": {"x":19,"y":73,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -138,7 +146,7 @@ }, "dark/border-right.png": { - "frame": {"x":19,"y":73,"w":16,"h":16}, + "frame": {"x":37,"y":55,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -146,7 +154,7 @@ }, "dark/border-top.png": { - "frame": {"x":37,"y":55,"w":16,"h":16}, + "frame": {"x":55,"y":37,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -154,7 +162,7 @@ }, "dark/build.png": { - "frame": {"x":55,"y":37,"w":16,"h":16}, + "frame": {"x":73,"y":19,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -162,7 +170,7 @@ }, "dark/collider.png": { - "frame": {"x":73,"y":19,"w":16,"h":16}, + "frame": {"x":91,"y":1,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -170,7 +178,7 @@ }, "dark/column.png": { - "frame": {"x":91,"y":1,"w":16,"h":16}, + "frame": {"x":109,"y":1,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -186,7 +194,7 @@ }, "dark/file-font.png": { - "frame": {"x":54,"y":289,"w":13,"h":16}, + "frame": {"x":91,"y":253,"w":13,"h":16}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":13,"h":16}, @@ -194,7 +202,7 @@ }, "dark/file-image.png": { - "frame": {"x":109,"y":1,"w":16,"h":16}, + "frame": {"x":1,"y":109,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -202,7 +210,7 @@ }, "dark/file-movie.png": { - "frame": {"x":1,"y":109,"w":16,"h":16}, + "frame": {"x":19,"y":91,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -210,7 +218,7 @@ }, "dark/file-new.png": { - "frame": {"x":19,"y":91,"w":16,"h":16}, + "frame": {"x":37,"y":73,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -218,7 +226,7 @@ }, "dark/file-script.png": { - "frame": {"x":37,"y":73,"w":16,"h":16}, + "frame": {"x":55,"y":55,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -226,7 +234,7 @@ }, "dark/file-sound.png": { - "frame": {"x":55,"y":55,"w":16,"h":16}, + "frame": {"x":73,"y":37,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -234,7 +242,7 @@ }, "dark/file-text.png": { - "frame": {"x":73,"y":37,"w":16,"h":16}, + "frame": {"x":91,"y":19,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -242,7 +250,7 @@ }, "dark/grid.png": { - "frame": {"x":91,"y":19,"w":16,"h":16}, + "frame": {"x":109,"y":19,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -250,7 +258,7 @@ }, "dark/group.png": { - "frame": {"x":109,"y":19,"w":16,"h":16}, + "frame": {"x":1,"y":127,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -258,7 +266,7 @@ }, "dark/image-type.png": { - "frame": {"x":109,"y":268,"w":14,"h":14}, + "frame": {"x":91,"y":271,"w":14,"h":14}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":14,"h":14}, @@ -266,7 +274,7 @@ }, "dark/inspector.png": { - "frame": {"x":1,"y":127,"w":16,"h":16}, + "frame": {"x":19,"y":109,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -274,7 +282,7 @@ }, "dark/keyboard-key.png": { - "frame": {"x":19,"y":109,"w":16,"h":16}, + "frame": {"x":37,"y":91,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -282,7 +290,7 @@ }, "dark/layer.png": { - "frame": {"x":37,"y":91,"w":16,"h":16}, + "frame": {"x":55,"y":73,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -290,7 +298,7 @@ }, "dark/list.png": { - "frame": {"x":109,"y":217,"w":16,"h":15}, + "frame": {"x":55,"y":271,"w":16,"h":15}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":15}, @@ -298,7 +306,7 @@ }, "dark/locked.png": { - "frame": {"x":112,"y":284,"w":11,"h":13}, + "frame": {"x":107,"y":287,"w":11,"h":13}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":1,"w":11,"h":13}, @@ -306,7 +314,7 @@ }, "dark/origin-bottomcenter.png": { - "frame": {"x":55,"y":73,"w":16,"h":16}, + "frame": {"x":73,"y":55,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -314,7 +322,7 @@ }, "dark/origin-bottomleft.png": { - "frame": {"x":73,"y":55,"w":16,"h":16}, + "frame": {"x":91,"y":37,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -322,7 +330,7 @@ }, "dark/origin-bottomright.png": { - "frame": {"x":91,"y":37,"w":16,"h":16}, + "frame": {"x":109,"y":37,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -330,7 +338,7 @@ }, "dark/origin-middlecenter.png": { - "frame": {"x":109,"y":37,"w":16,"h":16}, + "frame": {"x":1,"y":145,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -338,7 +346,7 @@ }, "dark/origin-middleleft.png": { - "frame": {"x":1,"y":145,"w":16,"h":16}, + "frame": {"x":19,"y":127,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -346,7 +354,7 @@ }, "dark/origin-middleright.png": { - "frame": {"x":19,"y":127,"w":16,"h":16}, + "frame": {"x":37,"y":109,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -354,7 +362,7 @@ }, "dark/origin-topcenter.png": { - "frame": {"x":37,"y":109,"w":16,"h":16}, + "frame": {"x":55,"y":91,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -362,7 +370,7 @@ }, "dark/origin-topleft.png": { - "frame": {"x":55,"y":91,"w":16,"h":16}, + "frame": {"x":73,"y":73,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -370,7 +378,7 @@ }, "dark/origin-topright.png": { - "frame": {"x":73,"y":73,"w":16,"h":16}, + "frame": {"x":91,"y":55,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -378,7 +386,7 @@ }, "dark/origin.png": { - "frame": {"x":91,"y":55,"w":16,"h":16}, + "frame": {"x":109,"y":55,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -386,7 +394,7 @@ }, "dark/outline.png": { - "frame": {"x":109,"y":55,"w":16,"h":16}, + "frame": {"x":1,"y":163,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -394,7 +402,7 @@ }, "dark/play.png": { - "frame": {"x":84,"y":284,"w":12,"h":14}, + "frame": {"x":107,"y":271,"w":12,"h":14}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":1,"w":12,"h":14}, @@ -402,7 +410,7 @@ }, "dark/project.png": { - "frame": {"x":109,"y":234,"w":16,"h":15}, + "frame": {"x":73,"y":253,"w":16,"h":15}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":16,"h":15}, @@ -418,7 +426,7 @@ }, "dark/scale.png": { - "frame": {"x":1,"y":163,"w":16,"h":16}, + "frame": {"x":19,"y":145,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -426,7 +434,7 @@ }, "dark/select-region.png": { - "frame": {"x":19,"y":145,"w":16,"h":16}, + "frame": {"x":37,"y":127,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -434,7 +442,7 @@ }, "dark/spine.png": { - "frame": {"x":37,"y":127,"w":16,"h":16}, + "frame": {"x":55,"y":109,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -442,7 +450,7 @@ }, "dark/sprite-type.png": { - "frame": {"x":55,"y":109,"w":16,"h":16}, + "frame": {"x":73,"y":91,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -450,7 +458,7 @@ }, "dark/text-type.png": { - "frame": {"x":73,"y":91,"w":16,"h":16}, + "frame": {"x":91,"y":73,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -458,7 +466,7 @@ }, "dark/tilemap-layer.png": { - "frame": {"x":91,"y":73,"w":16,"h":16}, + "frame": {"x":109,"y":73,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -466,7 +474,7 @@ }, "dark/tilemap.png": { - "frame": {"x":109,"y":73,"w":16,"h":16}, + "frame": {"x":1,"y":181,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -474,7 +482,7 @@ }, "dark/tilesprite.png": { - "frame": {"x":91,"y":252,"w":16,"h":14}, + "frame": {"x":55,"y":288,"w":16,"h":14}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":16,"h":14}, @@ -482,7 +490,7 @@ }, "dark/translate.png": { - "frame": {"x":1,"y":181,"w":16,"h":16}, + "frame": {"x":19,"y":163,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -490,7 +498,7 @@ }, "dark/unlocked.png": { - "frame": {"x":73,"y":269,"w":16,"h":13}, + "frame": {"x":54,"y":304,"w":16,"h":13}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":16,"h":13}, @@ -498,7 +506,7 @@ }, "dark/user-component.png": { - "frame": {"x":19,"y":163,"w":16,"h":16}, + "frame": {"x":37,"y":145,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -506,7 +514,7 @@ }, "light/3slice.png": { - "frame": {"x":37,"y":145,"w":16,"h":16}, + "frame": {"x":55,"y":127,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -514,7 +522,7 @@ }, "light/9slice.png": { - "frame": {"x":55,"y":127,"w":16,"h":16}, + "frame": {"x":73,"y":109,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -522,7 +530,7 @@ }, "light/align-bottom.png": { - "frame": {"x":73,"y":109,"w":16,"h":16}, + "frame": {"x":91,"y":91,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -530,7 +538,7 @@ }, "light/align-center.png": { - "frame": {"x":91,"y":91,"w":16,"h":16}, + "frame": {"x":109,"y":91,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -538,7 +546,7 @@ }, "light/align-left.png": { - "frame": {"x":109,"y":91,"w":16,"h":16}, + "frame": {"x":1,"y":199,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -546,7 +554,7 @@ }, "light/align-middle.png": { - "frame": {"x":1,"y":199,"w":16,"h":16}, + "frame": {"x":19,"y":181,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -554,7 +562,7 @@ }, "light/align-right.png": { - "frame": {"x":19,"y":181,"w":16,"h":16}, + "frame": {"x":37,"y":163,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -562,7 +570,7 @@ }, "light/align-top.png": { - "frame": {"x":37,"y":163,"w":16,"h":16}, + "frame": {"x":55,"y":145,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -570,7 +578,7 @@ }, "light/angle.png": { - "frame": {"x":55,"y":145,"w":16,"h":16}, + "frame": {"x":73,"y":127,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -578,7 +586,15 @@ }, "light/animations.png": { - "frame": {"x":73,"y":127,"w":16,"h":16}, + "frame": {"x":91,"y":109,"w":16,"h":16}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, + "sourceSize": {"w":16,"h":16} +}, +"light/aseprite.png": +{ + "frame": {"x":1,"y":73,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -586,7 +602,7 @@ }, "light/asset-pack.png": { - "frame": {"x":91,"y":109,"w":16,"h":16}, + "frame": {"x":109,"y":109,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -594,7 +610,7 @@ }, "light/bitmapfont-type.png": { - "frame": {"x":55,"y":271,"w":15,"h":16}, + "frame": {"x":91,"y":235,"w":15,"h":16}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":15,"h":16}, @@ -602,7 +618,7 @@ }, "light/blocks.png": { - "frame": {"x":109,"y":109,"w":16,"h":16}, + "frame": {"x":1,"y":217,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -610,7 +626,7 @@ }, "light/border-bottom.png": { - "frame": {"x":1,"y":217,"w":16,"h":16}, + "frame": {"x":19,"y":199,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -618,7 +634,7 @@ }, "light/border-center.png": { - "frame": {"x":19,"y":199,"w":16,"h":16}, + "frame": {"x":37,"y":181,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -626,7 +642,7 @@ }, "light/border-left.png": { - "frame": {"x":37,"y":181,"w":16,"h":16}, + "frame": {"x":55,"y":163,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -634,7 +650,7 @@ }, "light/border-middle.png": { - "frame": {"x":55,"y":163,"w":16,"h":16}, + "frame": {"x":73,"y":145,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -642,7 +658,7 @@ }, "light/border-right.png": { - "frame": {"x":73,"y":145,"w":16,"h":16}, + "frame": {"x":91,"y":127,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -658,7 +674,7 @@ }, "light/border-top.png": { - "frame": {"x":91,"y":127,"w":16,"h":16}, + "frame": {"x":109,"y":127,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -666,7 +682,7 @@ }, "light/build.png": { - "frame": {"x":109,"y":127,"w":16,"h":16}, + "frame": {"x":1,"y":235,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -674,7 +690,7 @@ }, "light/collider.png": { - "frame": {"x":1,"y":235,"w":16,"h":16}, + "frame": {"x":19,"y":217,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -682,7 +698,7 @@ }, "light/column.png": { - "frame": {"x":19,"y":217,"w":16,"h":16}, + "frame": {"x":37,"y":199,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -698,7 +714,7 @@ }, "light/file-font.png": { - "frame": {"x":69,"y":289,"w":13,"h":16}, + "frame": {"x":106,"y":253,"w":13,"h":16}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":0,"w":13,"h":16}, @@ -706,7 +722,7 @@ }, "light/file-image.png": { - "frame": {"x":37,"y":199,"w":16,"h":16}, + "frame": {"x":55,"y":181,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -714,7 +730,7 @@ }, "light/file-movie.png": { - "frame": {"x":55,"y":181,"w":16,"h":16}, + "frame": {"x":73,"y":163,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -722,7 +738,7 @@ }, "light/file-new.png": { - "frame": {"x":73,"y":163,"w":16,"h":16}, + "frame": {"x":91,"y":145,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -730,7 +746,7 @@ }, "light/file-script.png": { - "frame": {"x":91,"y":145,"w":16,"h":16}, + "frame": {"x":109,"y":145,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -738,7 +754,7 @@ }, "light/file-sound.png": { - "frame": {"x":109,"y":145,"w":16,"h":16}, + "frame": {"x":1,"y":253,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -746,7 +762,7 @@ }, "light/file-text.png": { - "frame": {"x":1,"y":253,"w":16,"h":16}, + "frame": {"x":19,"y":235,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -754,7 +770,7 @@ }, "light/grid.png": { - "frame": {"x":19,"y":235,"w":16,"h":16}, + "frame": {"x":37,"y":217,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -762,7 +778,7 @@ }, "light/group.png": { - "frame": {"x":37,"y":217,"w":16,"h":16}, + "frame": {"x":55,"y":199,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -770,7 +786,7 @@ }, "light/image-type.png": { - "frame": {"x":84,"y":300,"w":14,"h":14}, + "frame": {"x":91,"y":287,"w":14,"h":14}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":14,"h":14}, @@ -778,7 +794,7 @@ }, "light/inspector.png": { - "frame": {"x":55,"y":199,"w":16,"h":16}, + "frame": {"x":73,"y":181,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -786,7 +802,7 @@ }, "light/keyboard-key.png": { - "frame": {"x":73,"y":181,"w":16,"h":16}, + "frame": {"x":91,"y":163,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -794,7 +810,7 @@ }, "light/layer.png": { - "frame": {"x":91,"y":163,"w":16,"h":16}, + "frame": {"x":109,"y":163,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -802,7 +818,7 @@ }, "light/list.png": { - "frame": {"x":91,"y":235,"w":16,"h":15}, + "frame": {"x":73,"y":270,"w":16,"h":15}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":15}, @@ -810,7 +826,7 @@ }, "light/locked.png": { - "frame": {"x":100,"y":300,"w":11,"h":13}, + "frame": {"x":104,"y":303,"w":11,"h":13}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":3,"y":1,"w":11,"h":13}, @@ -818,7 +834,7 @@ }, "light/origin-bottomcenter.png": { - "frame": {"x":109,"y":163,"w":16,"h":16}, + "frame": {"x":1,"y":271,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -826,7 +842,7 @@ }, "light/origin-bottomleft.png": { - "frame": {"x":1,"y":271,"w":16,"h":16}, + "frame": {"x":19,"y":253,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -834,7 +850,7 @@ }, "light/origin-bottomright.png": { - "frame": {"x":19,"y":253,"w":16,"h":16}, + "frame": {"x":37,"y":235,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -842,7 +858,7 @@ }, "light/origin-middlecenter.png": { - "frame": {"x":37,"y":235,"w":16,"h":16}, + "frame": {"x":55,"y":217,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -850,7 +866,7 @@ }, "light/origin-middleleft.png": { - "frame": {"x":55,"y":217,"w":16,"h":16}, + "frame": {"x":73,"y":199,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -858,7 +874,7 @@ }, "light/origin-middleright.png": { - "frame": {"x":73,"y":199,"w":16,"h":16}, + "frame": {"x":91,"y":181,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -866,7 +882,7 @@ }, "light/origin-topcenter.png": { - "frame": {"x":91,"y":181,"w":16,"h":16}, + "frame": {"x":109,"y":181,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -874,7 +890,7 @@ }, "light/origin-topleft.png": { - "frame": {"x":109,"y":181,"w":16,"h":16}, + "frame": {"x":1,"y":289,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -882,7 +898,7 @@ }, "light/origin-topright.png": { - "frame": {"x":1,"y":289,"w":16,"h":16}, + "frame": {"x":19,"y":271,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -890,7 +906,7 @@ }, "light/origin.png": { - "frame": {"x":19,"y":271,"w":16,"h":16}, + "frame": {"x":37,"y":253,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -898,7 +914,7 @@ }, "light/outline.png": { - "frame": {"x":37,"y":253,"w":16,"h":16}, + "frame": {"x":55,"y":235,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -906,7 +922,7 @@ }, "light/play.png": { - "frame": {"x":98,"y":284,"w":12,"h":14}, + "frame": {"x":90,"y":303,"w":12,"h":14}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":1,"w":12,"h":14}, @@ -914,7 +930,7 @@ }, "light/project.png": { - "frame": {"x":109,"y":251,"w":16,"h":15}, + "frame": {"x":108,"y":235,"w":16,"h":15}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":16,"h":15}, @@ -930,7 +946,7 @@ }, "light/scale.png": { - "frame": {"x":55,"y":235,"w":16,"h":16}, + "frame": {"x":73,"y":217,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -938,7 +954,7 @@ }, "light/select-region.png": { - "frame": {"x":73,"y":217,"w":16,"h":16}, + "frame": {"x":91,"y":199,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -946,7 +962,7 @@ }, "light/spine.png": { - "frame": {"x":91,"y":199,"w":16,"h":16}, + "frame": {"x":109,"y":199,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -954,7 +970,7 @@ }, "light/sprite-type.png": { - "frame": {"x":109,"y":199,"w":16,"h":16}, + "frame": {"x":19,"y":289,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -962,7 +978,7 @@ }, "light/text-type.png": { - "frame": {"x":19,"y":289,"w":16,"h":16}, + "frame": {"x":37,"y":271,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -970,7 +986,7 @@ }, "light/tilemap-layer.png": { - "frame": {"x":37,"y":271,"w":16,"h":16}, + "frame": {"x":55,"y":253,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -978,7 +994,7 @@ }, "light/tilemap.png": { - "frame": {"x":55,"y":253,"w":16,"h":16}, + "frame": {"x":73,"y":235,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -986,7 +1002,7 @@ }, "light/tilesprite.png": { - "frame": {"x":73,"y":253,"w":16,"h":14}, + "frame": {"x":73,"y":287,"w":16,"h":14}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":16,"h":14}, @@ -994,7 +1010,7 @@ }, "light/translate.png": { - "frame": {"x":73,"y":235,"w":16,"h":16}, + "frame": {"x":91,"y":217,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -1002,7 +1018,7 @@ }, "light/unlocked.png": { - "frame": {"x":91,"y":268,"w":16,"h":13}, + "frame": {"x":72,"y":304,"w":16,"h":13}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":16,"h":13}, @@ -1010,7 +1026,7 @@ }, "light/user-component.png": { - "frame": {"x":91,"y":217,"w":16,"h":16}, + "frame": {"x":109,"y":217,"w":16,"h":16}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":16,"h":16}, @@ -1021,8 +1037,8 @@ "version": "1.0", "image": "atlas@1x.png", "format": "RGBA8888", - "size": {"w":126,"h":315}, + "size": {"w":126,"h":318}, "scale": "1", - "smartupdate": "$TexturePacker:SmartUpdate:1d7560dab3bc8230de7b90d61fae75cd:0a0072a306be10c3e37a3d7445f0513b:a6f74b55a90107bc4ae6d23dde1c2d9e$" + "smartupdate": "$TexturePacker:SmartUpdate:8f7e6fa8c50e6e4a1a10036e7c58450f:5241bfccae5d16a07ca49ffa984ca94e:a6f74b55a90107bc4ae6d23dde1c2d9e$" } } diff --git a/source/editor/plugins/phasereditor2d.resources/icons/atlas@1x.png b/source/editor/plugins/phasereditor2d.resources/icons/atlas@1x.png index 9485ae8ba..e34775b8a 100644 Binary files a/source/editor/plugins/phasereditor2d.resources/icons/atlas@1x.png and b/source/editor/plugins/phasereditor2d.resources/icons/atlas@1x.png differ diff --git a/source/editor/plugins/phasereditor2d.resources/icons/atlas@2x.json b/source/editor/plugins/phasereditor2d.resources/icons/atlas@2x.json index d0b4ee4a3..49205b0aa 100644 --- a/source/editor/plugins/phasereditor2d.resources/icons/atlas@2x.json +++ b/source/editor/plugins/phasereditor2d.resources/icons/atlas@2x.json @@ -2,7 +2,7 @@ "dark/3slice@2x.png": { - "frame": {"x":137,"y":228,"w":32,"h":26}, + "frame": {"x":170,"y":228,"w":32,"h":26}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":3,"w":32,"h":26}, @@ -18,7 +18,7 @@ }, "dark/align-bottom@2x.png": { - "frame": {"x":457,"y":159,"w":28,"h":30}, + "frame": {"x":427,"y":191,"w":28,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":1,"w":28,"h":30}, @@ -26,7 +26,7 @@ }, "dark/align-center@2x.png": { - "frame": {"x":235,"y":33,"w":32,"h":28}, + "frame": {"x":235,"y":1,"w":32,"h":28}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":2,"w":32,"h":28}, @@ -34,7 +34,7 @@ }, "dark/align-left@2x.png": { - "frame": {"x":199,"y":97,"w":32,"h":29}, + "frame": {"x":201,"y":1,"w":32,"h":29}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":32,"h":29}, @@ -42,7 +42,7 @@ }, "dark/align-middle@2x.png": { - "frame": {"x":35,"y":205,"w":32,"h":31}, + "frame": {"x":68,"y":171,"w":32,"h":31}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":31}, @@ -50,7 +50,7 @@ }, "dark/align-right@2x.png": { - "frame": {"x":102,"y":135,"w":32,"h":30}, + "frame": {"x":102,"y":168,"w":32,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":30}, @@ -58,7 +58,7 @@ }, "dark/align-top@2x.png": { - "frame": {"x":68,"y":137,"w":32,"h":31}, + "frame": {"x":68,"y":204,"w":32,"h":31}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":31}, @@ -66,7 +66,7 @@ }, "dark/angle@2x.png": { - "frame": {"x":135,"y":34,"w":31,"h":30}, + "frame": {"x":136,"y":34,"w":31,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":31,"h":30}, @@ -74,15 +74,23 @@ }, "dark/animations@2x.png": { - "frame": {"x":69,"y":1,"w":31,"h":31}, + "frame": {"x":69,"y":67,"w":31,"h":31}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":31,"h":31}, "sourceSize": {"w":32,"h":32} }, +"dark/aseprite@2x.png": +{ + "frame": {"x":1,"y":35,"w":32,"h":32}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, + "sourceSize": {"w":32,"h":32} +}, "dark/asset-pack@2x.png": { - "frame": {"x":233,"y":1,"w":30,"h":30}, + "frame": {"x":202,"y":32,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -90,7 +98,7 @@ }, "dark/bitmapfont-type@2x.png": { - "frame": {"x":426,"y":159,"w":29,"h":30}, + "frame": {"x":457,"y":95,"w":29,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":1,"w":29,"h":30}, @@ -98,7 +106,7 @@ }, "dark/blocks@2x.png": { - "frame": {"x":201,"y":64,"w":30,"h":30}, + "frame": {"x":201,"y":96,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -106,7 +114,7 @@ }, "dark/border-bottom@2x.png": { - "frame": {"x":202,"y":128,"w":30,"h":30}, + "frame": {"x":232,"y":128,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -114,7 +122,7 @@ }, "dark/border-center@2x.png": { - "frame": {"x":202,"y":160,"w":30,"h":30}, + "frame": {"x":203,"y":64,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -122,7 +130,7 @@ }, "dark/border-left@2x.png": { - "frame": {"x":167,"y":1,"w":31,"h":30}, + "frame": {"x":168,"y":1,"w":31,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":31,"h":30}, @@ -130,7 +138,7 @@ }, "dark/border-middle@2x.png": { - "frame": {"x":203,"y":192,"w":30,"h":30}, + "frame": {"x":234,"y":32,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -138,7 +146,7 @@ }, "dark/border-right@2x.png": { - "frame": {"x":35,"y":137,"w":31,"h":32}, + "frame": {"x":35,"y":171,"w":31,"h":32}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":31,"h":32}, @@ -146,7 +154,7 @@ }, "dark/border-top@2x.png": { - "frame": {"x":205,"y":224,"w":30,"h":30}, + "frame": {"x":233,"y":96,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -154,7 +162,7 @@ }, "dark/build@2x.png": { - "frame": {"x":233,"y":64,"w":30,"h":30}, + "frame": {"x":235,"y":64,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -162,7 +170,7 @@ }, "dark/collider@2x.png": { - "frame": {"x":136,"y":132,"w":31,"h":30}, + "frame": {"x":136,"y":165,"w":31,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":31,"h":30}, @@ -170,7 +178,7 @@ }, "dark/column@2x.png": { - "frame": {"x":489,"y":1,"w":10,"h":30}, + "frame": {"x":495,"y":1,"w":10,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":11,"y":1,"w":10,"h":30}, @@ -178,7 +186,7 @@ }, "dark/dot@2x.png": { - "frame": {"x":65,"y":238,"w":10,"h":10}, + "frame": {"x":65,"y":239,"w":10,"h":10}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":11,"y":11,"w":10,"h":10}, @@ -186,7 +194,7 @@ }, "dark/file-font@2x.png": { - "frame": {"x":458,"y":191,"w":24,"h":30}, + "frame": {"x":457,"y":191,"w":24,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":1,"w":24,"h":30}, @@ -194,7 +202,7 @@ }, "dark/file-image@2x.png": { - "frame": {"x":265,"y":1,"w":30,"h":30}, + "frame": {"x":266,"y":31,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -202,7 +210,7 @@ }, "dark/file-movie@2x.png": { - "frame": {"x":233,"y":96,"w":30,"h":30}, + "frame": {"x":235,"y":160,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -210,7 +218,7 @@ }, "dark/file-new@2x.png": { - "frame": {"x":234,"y":128,"w":30,"h":30}, + "frame": {"x":264,"y":128,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -218,7 +226,7 @@ }, "dark/file-script@2x.png": { - "frame": {"x":166,"y":99,"w":31,"h":30}, + "frame": {"x":166,"y":132,"w":31,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":31,"h":30}, @@ -226,7 +234,7 @@ }, "dark/file-sound@2x.png": { - "frame": {"x":234,"y":160,"w":30,"h":30}, + "frame": {"x":265,"y":96,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -234,7 +242,7 @@ }, "dark/file-text@2x.png": { - "frame": {"x":102,"y":167,"w":32,"h":30}, + "frame": {"x":102,"y":200,"w":32,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":32,"h":30}, @@ -242,7 +250,7 @@ }, "dark/grid@2x.png": { - "frame": {"x":235,"y":192,"w":30,"h":30}, + "frame": {"x":267,"y":63,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -250,7 +258,7 @@ }, "dark/group@2x.png": { - "frame": {"x":237,"y":224,"w":30,"h":30}, + "frame": {"x":298,"y":31,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -258,7 +266,7 @@ }, "dark/image-type@2x.png": { - "frame": {"x":457,"y":85,"w":24,"h":24}, + "frame": {"x":460,"y":223,"w":24,"h":24}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":4,"y":4,"w":24,"h":24}, @@ -266,7 +274,7 @@ }, "dark/inspector@2x.png": { - "frame": {"x":134,"y":99,"w":30,"h":31}, + "frame": {"x":134,"y":132,"w":30,"h":31}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":31}, @@ -274,7 +282,7 @@ }, "dark/keyboard-key@2x.png": { - "frame": {"x":1,"y":35,"w":32,"h":32}, + "frame": {"x":1,"y":69,"w":32,"h":32}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, @@ -282,7 +290,7 @@ }, "dark/layer@2x.png": { - "frame": {"x":265,"y":63,"w":30,"h":30}, + "frame": {"x":235,"y":192,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -290,7 +298,7 @@ }, "dark/list@2x.png": { - "frame": {"x":303,"y":33,"w":30,"h":28}, + "frame": {"x":303,"y":1,"w":30,"h":28}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":28}, @@ -298,7 +306,7 @@ }, "dark/locked@2x.png": { - "frame": {"x":485,"y":219,"w":20,"h":24}, + "frame": {"x":488,"y":91,"w":20,"h":24}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":7,"y":3,"w":20,"h":24}, @@ -306,7 +314,7 @@ }, "dark/origin-bottomcenter@2x.png": { - "frame": {"x":297,"y":1,"w":30,"h":30}, + "frame": {"x":238,"y":224,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -314,7 +322,7 @@ }, "dark/origin-bottomleft@2x.png": { - "frame": {"x":265,"y":95,"w":30,"h":30}, + "frame": {"x":267,"y":160,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -322,7 +330,7 @@ }, "dark/origin-bottomright@2x.png": { - "frame": {"x":266,"y":127,"w":30,"h":30}, + "frame": {"x":296,"y":128,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -330,7 +338,7 @@ }, "dark/origin-middlecenter@2x.png": { - "frame": {"x":266,"y":159,"w":30,"h":30}, + "frame": {"x":297,"y":95,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -338,7 +346,7 @@ }, "dark/origin-middleleft@2x.png": { - "frame": {"x":267,"y":191,"w":30,"h":30}, + "frame": {"x":299,"y":63,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -346,7 +354,7 @@ }, "dark/origin-middleright@2x.png": { - "frame": {"x":269,"y":223,"w":30,"h":30}, + "frame": {"x":330,"y":31,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -354,7 +362,7 @@ }, "dark/origin-topcenter@2x.png": { - "frame": {"x":297,"y":63,"w":30,"h":30}, + "frame": {"x":267,"y":192,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -362,7 +370,7 @@ }, "dark/origin-topleft@2x.png": { - "frame": {"x":329,"y":1,"w":30,"h":30}, + "frame": {"x":270,"y":224,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -370,7 +378,7 @@ }, "dark/origin-topright@2x.png": { - "frame": {"x":297,"y":95,"w":30,"h":30}, + "frame": {"x":299,"y":160,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -378,7 +386,7 @@ }, "dark/origin@2x.png": { - "frame": {"x":69,"y":34,"w":31,"h":31}, + "frame": {"x":69,"y":100,"w":31,"h":31}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":31,"h":31}, @@ -386,7 +394,7 @@ }, "dark/outline@2x.png": { - "frame": {"x":298,"y":127,"w":30,"h":30}, + "frame": {"x":328,"y":127,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -394,7 +402,7 @@ }, "dark/play@2x.png": { - "frame": {"x":484,"y":191,"w":22,"h":26}, + "frame": {"x":485,"y":159,"w":22,"h":26}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":3,"w":22,"h":26}, @@ -402,7 +410,7 @@ }, "dark/project@2x.png": { - "frame": {"x":335,"y":33,"w":30,"h":28}, + "frame": {"x":335,"y":1,"w":30,"h":28}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":3,"w":30,"h":28}, @@ -418,7 +426,7 @@ }, "dark/scale@2x.png": { - "frame": {"x":136,"y":164,"w":31,"h":30}, + "frame": {"x":168,"y":99,"w":31,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":31,"h":30}, @@ -426,7 +434,7 @@ }, "dark/select-region@2x.png": { - "frame": {"x":137,"y":196,"w":31,"h":30}, + "frame": {"x":136,"y":197,"w":31,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":31,"h":30}, @@ -434,7 +442,7 @@ }, "dark/spine@2x.png": { - "frame": {"x":1,"y":69,"w":32,"h":32}, + "frame": {"x":1,"y":103,"w":32,"h":32}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, @@ -442,7 +450,7 @@ }, "dark/sprite-type@2x.png": { - "frame": {"x":69,"y":67,"w":31,"h":31}, + "frame": {"x":69,"y":133,"w":31,"h":31}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":31,"h":31}, @@ -450,7 +458,7 @@ }, "dark/text-type@2x.png": { - "frame": {"x":298,"y":159,"w":30,"h":30}, + "frame": {"x":329,"y":95,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -458,7 +466,7 @@ }, "dark/tilemap-layer@2x.png": { - "frame": {"x":1,"y":103,"w":32,"h":32}, + "frame": {"x":1,"y":137,"w":32,"h":32}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, @@ -466,7 +474,7 @@ }, "dark/tilemap@2x.png": { - "frame": {"x":1,"y":137,"w":32,"h":32}, + "frame": {"x":1,"y":171,"w":32,"h":32}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, @@ -474,7 +482,7 @@ }, "dark/tilesprite@2x.png": { - "frame": {"x":171,"y":227,"w":32,"h":24}, + "frame": {"x":136,"y":229,"w":32,"h":24}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":4,"w":32,"h":24}, @@ -482,7 +490,7 @@ }, "dark/translate@2x.png": { - "frame": {"x":299,"y":191,"w":30,"h":30}, + "frame": {"x":331,"y":63,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -490,7 +498,7 @@ }, "dark/unlocked@2x.png": { - "frame": {"x":457,"y":59,"w":30,"h":24}, + "frame": {"x":431,"y":1,"w":30,"h":24}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":3,"w":30,"h":24}, @@ -498,7 +506,7 @@ }, "dark/user-component@2x.png": { - "frame": {"x":102,"y":67,"w":30,"h":32}, + "frame": {"x":102,"y":100,"w":30,"h":32}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":30,"h":32}, @@ -506,7 +514,7 @@ }, "light/3slice@2x.png": { - "frame": {"x":1,"y":171,"w":32,"h":32}, + "frame": {"x":1,"y":205,"w":32,"h":32}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, @@ -514,7 +522,7 @@ }, "light/9slice@2x.png": { - "frame": {"x":1,"y":205,"w":32,"h":32}, + "frame": {"x":35,"y":1,"w":32,"h":32}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, @@ -522,7 +530,7 @@ }, "light/align-bottom@2x.png": { - "frame": {"x":429,"y":223,"w":28,"h":30}, + "frame": {"x":430,"y":223,"w":28,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":1,"w":28,"h":30}, @@ -530,7 +538,7 @@ }, "light/align-center@2x.png": { - "frame": {"x":269,"y":33,"w":32,"h":28}, + "frame": {"x":269,"y":1,"w":32,"h":28}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":2,"w":32,"h":28}, @@ -538,7 +546,7 @@ }, "light/align-left@2x.png": { - "frame": {"x":201,"y":33,"w":32,"h":29}, + "frame": {"x":169,"y":65,"w":32,"h":29}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":32,"h":29}, @@ -546,7 +554,7 @@ }, "light/align-middle@2x.png": { - "frame": {"x":68,"y":170,"w":32,"h":31}, + "frame": {"x":69,"y":1,"w":32,"h":31}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":31}, @@ -554,7 +562,7 @@ }, "light/align-right@2x.png": { - "frame": {"x":103,"y":199,"w":32,"h":30}, + "frame": {"x":134,"y":100,"w":32,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":30}, @@ -562,7 +570,7 @@ }, "light/align-top@2x.png": { - "frame": {"x":69,"y":203,"w":32,"h":31}, + "frame": {"x":69,"y":34,"w":32,"h":31}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":31}, @@ -570,7 +578,7 @@ }, "light/angle@2x.png": { - "frame": {"x":169,"y":131,"w":31,"h":30}, + "frame": {"x":169,"y":164,"w":31,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":31,"h":30}, @@ -578,15 +586,23 @@ }, "light/animations@2x.png": { - "frame": {"x":69,"y":100,"w":31,"h":31}, + "frame": {"x":102,"y":67,"w":31,"h":31}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":31,"h":31}, "sourceSize": {"w":32,"h":32} }, +"light/aseprite@2x.png": +{ + "frame": {"x":1,"y":35,"w":32,"h":32}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, + "sourceSize": {"w":32,"h":32} +}, "light/asset-pack@2x.png": { - "frame": {"x":301,"y":223,"w":30,"h":30}, + "frame": {"x":362,"y":31,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -594,7 +610,7 @@ }, "light/bitmapfont-type@2x.png": { - "frame": {"x":427,"y":191,"w":29,"h":30}, + "frame": {"x":459,"y":59,"w":29,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":2,"y":1,"w":29,"h":30}, @@ -602,7 +618,7 @@ }, "light/blocks@2x.png": { - "frame": {"x":329,"y":63,"w":30,"h":30}, + "frame": {"x":299,"y":192,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -610,7 +626,7 @@ }, "light/border-bottom@2x.png": { - "frame": {"x":361,"y":1,"w":30,"h":30}, + "frame": {"x":302,"y":224,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -618,7 +634,7 @@ }, "light/border-center@2x.png": { - "frame": {"x":329,"y":95,"w":30,"h":30}, + "frame": {"x":331,"y":159,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -626,7 +642,7 @@ }, "light/border-left@2x.png": { - "frame": {"x":169,"y":163,"w":31,"h":30}, + "frame": {"x":199,"y":131,"w":31,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":31,"h":30}, @@ -634,7 +650,7 @@ }, "light/border-middle@2x.png": { - "frame": {"x":330,"y":127,"w":30,"h":30}, + "frame": {"x":360,"y":127,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -642,7 +658,7 @@ }, "light/border-right@2x.png": { - "frame": {"x":35,"y":171,"w":31,"h":32}, + "frame": {"x":35,"y":205,"w":31,"h":32}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":31,"h":32}, @@ -658,7 +674,7 @@ }, "light/border-top@2x.png": { - "frame": {"x":330,"y":159,"w":30,"h":30}, + "frame": {"x":361,"y":95,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -666,7 +682,7 @@ }, "light/build@2x.png": { - "frame": {"x":331,"y":191,"w":30,"h":30}, + "frame": {"x":363,"y":63,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -674,7 +690,7 @@ }, "light/collider@2x.png": { - "frame": {"x":170,"y":195,"w":31,"h":30}, + "frame": {"x":169,"y":196,"w":31,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":31,"h":30}, @@ -682,7 +698,7 @@ }, "light/column@2x.png": { - "frame": {"x":487,"y":139,"w":10,"h":30}, + "frame": {"x":490,"y":33,"w":10,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":11,"y":1,"w":10,"h":30}, @@ -690,7 +706,7 @@ }, "light/dot@2x.png": { - "frame": {"x":77,"y":236,"w":10,"h":10}, + "frame": {"x":77,"y":237,"w":10,"h":10}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":11,"y":11,"w":10,"h":10}, @@ -698,7 +714,7 @@ }, "light/file-font@2x.png": { - "frame": {"x":459,"y":223,"w":24,"h":30}, + "frame": {"x":459,"y":159,"w":24,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":1,"w":24,"h":30}, @@ -706,7 +722,7 @@ }, "light/file-image@2x.png": { - "frame": {"x":333,"y":223,"w":30,"h":30}, + "frame": {"x":394,"y":31,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -714,7 +730,7 @@ }, "light/file-movie@2x.png": { - "frame": {"x":361,"y":63,"w":30,"h":30}, + "frame": {"x":331,"y":191,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -722,7 +738,7 @@ }, "light/file-new@2x.png": { - "frame": {"x":393,"y":1,"w":30,"h":30}, + "frame": {"x":334,"y":223,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -730,7 +746,7 @@ }, "light/file-script@2x.png": { - "frame": {"x":168,"y":33,"w":31,"h":30}, + "frame": {"x":202,"y":163,"w":31,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":31,"h":30}, @@ -738,7 +754,7 @@ }, "light/file-sound@2x.png": { - "frame": {"x":361,"y":95,"w":30,"h":30}, + "frame": {"x":363,"y":159,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -746,7 +762,7 @@ }, "light/file-text@2x.png": { - "frame": {"x":134,"y":67,"w":32,"h":30}, + "frame": {"x":135,"y":67,"w":32,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":32,"h":30}, @@ -754,7 +770,7 @@ }, "light/grid@2x.png": { - "frame": {"x":362,"y":127,"w":30,"h":30}, + "frame": {"x":392,"y":127,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -762,7 +778,7 @@ }, "light/group@2x.png": { - "frame": {"x":362,"y":159,"w":30,"h":30}, + "frame": {"x":393,"y":95,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -770,7 +786,7 @@ }, "light/image-type@2x.png": { - "frame": {"x":480,"y":113,"w":24,"h":24}, + "frame": {"x":483,"y":191,"w":24,"h":24}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":4,"y":4,"w":24,"h":24}, @@ -778,7 +794,7 @@ }, "light/inspector@2x.png": { - "frame": {"x":135,"y":1,"w":30,"h":31}, + "frame": {"x":136,"y":1,"w":30,"h":31}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":31}, @@ -786,7 +802,7 @@ }, "light/keyboard-key@2x.png": { - "frame": {"x":35,"y":1,"w":32,"h":32}, + "frame": {"x":35,"y":35,"w":32,"h":32}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, @@ -794,7 +810,7 @@ }, "light/layer@2x.png": { - "frame": {"x":363,"y":191,"w":30,"h":30}, + "frame": {"x":395,"y":63,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -802,7 +818,7 @@ }, "light/list@2x.png": { - "frame": {"x":367,"y":33,"w":30,"h":28}, + "frame": {"x":367,"y":1,"w":30,"h":28}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":28}, @@ -810,7 +826,7 @@ }, "light/locked@2x.png": { - "frame": {"x":458,"y":111,"w":20,"h":24}, + "frame": {"x":488,"y":117,"w":20,"h":24}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":7,"y":3,"w":20,"h":24}, @@ -818,7 +834,7 @@ }, "light/origin-bottomcenter@2x.png": { - "frame": {"x":365,"y":223,"w":30,"h":30}, + "frame": {"x":426,"y":31,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -826,7 +842,7 @@ }, "light/origin-bottomleft@2x.png": { - "frame": {"x":393,"y":63,"w":30,"h":30}, + "frame": {"x":363,"y":191,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -834,7 +850,7 @@ }, "light/origin-bottomright@2x.png": { - "frame": {"x":425,"y":1,"w":30,"h":30}, + "frame": {"x":366,"y":223,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -842,7 +858,7 @@ }, "light/origin-middlecenter@2x.png": { - "frame": {"x":393,"y":95,"w":30,"h":30}, + "frame": {"x":395,"y":159,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -850,7 +866,7 @@ }, "light/origin-middleleft@2x.png": { - "frame": {"x":394,"y":127,"w":30,"h":30}, + "frame": {"x":424,"y":127,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -858,7 +874,7 @@ }, "light/origin-middleright@2x.png": { - "frame": {"x":394,"y":159,"w":30,"h":30}, + "frame": {"x":425,"y":95,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -866,7 +882,7 @@ }, "light/origin-topcenter@2x.png": { - "frame": {"x":395,"y":191,"w":30,"h":30}, + "frame": {"x":427,"y":63,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -874,7 +890,7 @@ }, "light/origin-topleft@2x.png": { - "frame": {"x":397,"y":223,"w":30,"h":30}, + "frame": {"x":458,"y":27,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -882,7 +898,7 @@ }, "light/origin-topright@2x.png": { - "frame": {"x":425,"y":63,"w":30,"h":30}, + "frame": {"x":395,"y":191,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -890,7 +906,7 @@ }, "light/origin@2x.png": { - "frame": {"x":102,"y":1,"w":31,"h":31}, + "frame": {"x":103,"y":1,"w":31,"h":31}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":31,"h":31}, @@ -898,7 +914,7 @@ }, "light/outline@2x.png": { - "frame": {"x":457,"y":1,"w":30,"h":30}, + "frame": {"x":398,"y":223,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -906,7 +922,7 @@ }, "light/play@2x.png": { - "frame": {"x":483,"y":85,"w":22,"h":26}, + "frame": {"x":486,"y":217,"w":22,"h":26}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":5,"y":3,"w":22,"h":26}, @@ -914,7 +930,7 @@ }, "light/project@2x.png": { - "frame": {"x":399,"y":33,"w":30,"h":28}, + "frame": {"x":399,"y":1,"w":30,"h":28}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":3,"w":30,"h":28}, @@ -930,7 +946,7 @@ }, "light/scale@2x.png": { - "frame": {"x":200,"y":1,"w":31,"h":30}, + "frame": {"x":202,"y":195,"w":31,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":1,"w":31,"h":30}, @@ -938,7 +954,7 @@ }, "light/select-region@2x.png": { - "frame": {"x":168,"y":65,"w":31,"h":30}, + "frame": {"x":169,"y":33,"w":31,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":31,"h":30}, @@ -946,7 +962,7 @@ }, "light/spine@2x.png": { - "frame": {"x":35,"y":35,"w":32,"h":32}, + "frame": {"x":35,"y":69,"w":32,"h":32}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, @@ -954,7 +970,7 @@ }, "light/sprite-type@2x.png": { - "frame": {"x":102,"y":34,"w":31,"h":31}, + "frame": {"x":103,"y":34,"w":31,"h":31}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":31,"h":31}, @@ -962,7 +978,7 @@ }, "light/text-type@2x.png": { - "frame": {"x":425,"y":95,"w":30,"h":30}, + "frame": {"x":427,"y":159,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -970,7 +986,7 @@ }, "light/tilemap-layer@2x.png": { - "frame": {"x":35,"y":69,"w":32,"h":32}, + "frame": {"x":35,"y":103,"w":32,"h":32}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, @@ -978,7 +994,7 @@ }, "light/tilemap@2x.png": { - "frame": {"x":35,"y":103,"w":32,"h":32}, + "frame": {"x":35,"y":137,"w":32,"h":32}, "rotated": false, "trimmed": false, "spriteSourceSize": {"x":0,"y":0,"w":32,"h":32}, @@ -986,7 +1002,7 @@ }, "light/tilesprite@2x.png": { - "frame": {"x":431,"y":33,"w":32,"h":24}, + "frame": {"x":204,"y":227,"w":32,"h":24}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":0,"y":4,"w":32,"h":24}, @@ -994,7 +1010,7 @@ }, "light/translate@2x.png": { - "frame": {"x":426,"y":127,"w":30,"h":30}, + "frame": {"x":456,"y":127,"w":30,"h":30}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":1,"w":30,"h":30}, @@ -1002,7 +1018,7 @@ }, "light/unlocked@2x.png": { - "frame": {"x":465,"y":33,"w":30,"h":24}, + "frame": {"x":463,"y":1,"w":30,"h":24}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":3,"w":30,"h":24}, @@ -1010,7 +1026,7 @@ }, "light/user-component@2x.png": { - "frame": {"x":102,"y":101,"w":30,"h":32}, + "frame": {"x":102,"y":134,"w":30,"h":32}, "rotated": false, "trimmed": true, "spriteSourceSize": {"x":1,"y":0,"w":30,"h":32}, @@ -1021,8 +1037,8 @@ "version": "1.0", "image": "atlas@2x.png", "format": "RGBA8888", - "size": {"w":507,"h":255}, + "size": {"w":509,"h":255}, "scale": "1", - "smartupdate": "$TexturePacker:SmartUpdate:5e67f5a1c8c9329ba77181c49fe873a7:f3bdf3a9c6869b70fb67e0931571668d:9eb1a82ac620c259737931966d4495d0$" + "smartupdate": "$TexturePacker:SmartUpdate:83f3fa35535afce5b5ea39c0ff8c8dd2:e9b9cbf5df6beb15642e03aafee2eb0b:9eb1a82ac620c259737931966d4495d0$" } } diff --git a/source/editor/plugins/phasereditor2d.resources/icons/atlas@2x.png b/source/editor/plugins/phasereditor2d.resources/icons/atlas@2x.png index 17d3c6359..1ddbcc945 100644 Binary files a/source/editor/plugins/phasereditor2d.resources/icons/atlas@2x.png and b/source/editor/plugins/phasereditor2d.resources/icons/atlas@2x.png differ diff --git a/source/editor/plugins/phasereditor2d.resources/res.json b/source/editor/plugins/phasereditor2d.resources/res.json index 5117320ca..f0071b57b 100644 --- a/source/editor/plugins/phasereditor2d.resources/res.json +++ b/source/editor/plugins/phasereditor2d.resources/res.json @@ -8,12 +8,16 @@ "Phaser.Types.Animations.Animation.yoyo": "Should the animation yoyo? (reverse back down to the start) before repeating?", "Phaser.Types.Animations.Animation.showOnStart": "Should sprite.visible = true when the animation starts to play? This happens _after_ any delay, if set.", "Phaser.Types.Animations.Animation.hideOnComplete": "Should sprite.visible = false when the animation finishes?", - "Phaser.Types.Animations.Animation.skipMissedFrames": "Skip frames if the time lags, or always advanced anyway?" + "Phaser.Types.Animations.Animation.showBeforeDelay": "If this animation has a delay, should it show the first frame immediately (true), or only after the delay (false)", + "Phaser.Types.Animations.Animation.skipMissedFrames": "Skip frames if the time lags, or always advanced anyway?", + "Phaser.Types.Animations.PlayAnimationConfig.startFrame": "The frame of the animation to start playback from." }, "phasereditor2d.pack/docs/phaser-docs.json": { "Phaser.Loader.LoaderPlugin.atlas(atlasURL)": "The absolute or relative URL to load the texture atlas json data file from. If undefined or `null` it will be set to `.json`, i.e. if `key` was \"alien\" then the URL will be \"alien.json\". Or, a well formed JSON object.", "Phaser.Loader.LoaderPlugin.atlas(textureURL)": "The absolute or relative URL to load the texture image file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was \"alien\" then the URL will be \"alien.png\".", "Phaser.Types.Loader.FileTypes.AtlasJSONFileConfig.normalMap": "The filename of an associated normal map. It uses the same path and url to load as the texture image.", + "Phaser.Loader.LoaderPlugin.aseprite(atlasURL)": "The absolute or relative URL to load the texture atlas json data file from. If undefined or `null` it will be set to `.json`, i.e. if `key` was \"alien\" then the URL will be \"alien.json\". Or, a well formed JSON object.", + "Phaser.Loader.LoaderPlugin.aseprite(textureURL)": "The absolute or relative URL to load the texture image file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was \"alien\" then the URL will be \"alien.png\".", "Phaser.Loader.LoaderPlugin.atlasXML(atlasURL)": "The absolute or relative URL to load the texture atlas xml data file from. If undefined or `null` it will be set to `.xml`, i.e. if `key` was \"alien\" then the URL will be \"alien.xml\".", "Phaser.Loader.LoaderPlugin.atlasXML(textureURL)": "The absolute or relative URL to load the texture image file from. If undefined or `null` it will be set to `.png`, i.e. if `key` was \"alien\" then the URL will be \"alien.png\".", "Phaser.Types.Loader.FileTypes.AtlasXMLFileConfig.normalMap": "The filename of an associated normal map. It uses the same path and url to load as the texture image.", @@ -500,6 +504,16 @@ "spine.SkinsAndAnimationBoundsProvider(timeStep)": "The time step to use for calculating the bounds. A smaller time step means more precision, but slower calculation.", "spine.AnimationState.timeScale": "Multiplier for the delta time when the animation state is updated, causing time for all animations and mixes to play slower\nor faster. Defaults to 1.\n\nSee TrackEntry {@link TrackEntry#timeScale} for affecting a single animation.", "spine.AnimationStateData.defaultMix": "The mix duration to use when no mix duration has been defined between two animations.", - "spine.AnimationStateData.setMixWith": "Sets the mix duration when changing from the specified animation to the other.\n\nSee {@link TrackEntry#mixDuration}." + "spine.AnimationStateData.setMixWith": "Sets the mix duration when changing from the specified animation to the other.\n\nSee {@link TrackEntry#mixDuration}.", + "Phaser.Types.Animations.PlayAnimationConfig.frameRate": "The frame rate of playback in frames per second (default 24 if duration is null)", + "Phaser.Types.Animations.PlayAnimationConfig.delay": "Delay before starting playback. Value given in milliseconds.", + "Phaser.Types.Animations.PlayAnimationConfig.repeat": "Number of times to repeat the animation (-1 for infinity)", + "Phaser.Types.Animations.PlayAnimationConfig.repeatDelay": "Delay before the animation repeats. Value given in milliseconds.", + "Phaser.Types.Animations.PlayAnimationConfig.yoyo": "Should the animation yoyo? (reverse back down to the start) before repeating?", + "Phaser.Types.Animations.PlayAnimationConfig.showOnStart": "Should sprite.visible = true when the animation starts to play?", + "Phaser.Types.Animations.PlayAnimationConfig.hideOnComplete": "Should sprite.visible = false when the animation finishes?", + "Phaser.Types.Animations.PlayAnimationConfig.showBeforeDelay": "If this animation has a delay, should it show the first frame immediately (true), or only after the delay (false)", + "Phaser.Types.Animations.PlayAnimationConfig.startFrame": "The frame of the animation to start playback from.", + "Phaser.Types.Animations.PlayAnimationConfig.timeScale": "The time scale to be applied to playback of this animation." } } \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.resources/src/ResourcesPlugin.ts b/source/editor/plugins/phasereditor2d.resources/src/ResourcesPlugin.ts index f25863e4b..1d879cb5a 100644 --- a/source/editor/plugins/phasereditor2d.resources/src/ResourcesPlugin.ts +++ b/source/editor/plugins/phasereditor2d.resources/src/ResourcesPlugin.ts @@ -9,6 +9,7 @@ namespace phasereditor2d.resources { // phasereditor2d.blocks export const ICON_ASSET_PACK = "asset-pack"; export const ICON_ANIMATIONS = "animations"; + export const ICON_ASEPRITE = "aseprite"; export const ICON_TILEMAP = "tilemap"; export const ICON_TILEMAP_LAYER = "tilemap-layer"; export const ICON_SPINE = "spine"; diff --git a/source/editor/plugins/phasereditor2d.scene/src/ScenePlugin.ts b/source/editor/plugins/phasereditor2d.scene/src/ScenePlugin.ts index a4ab6930e..d3e53a1fa 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ScenePlugin.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ScenePlugin.ts @@ -43,6 +43,7 @@ namespace phasereditor2d.scene { private _docs: phasereditor2d.ide.core.PhaserDocs; private _eventsDocs: phasereditor2d.ide.core.PhaserDocs; private _spineThumbnailCache: ui.SpineThumbnailCache; + private _canvasManager: ui.CanvasManager; static getInstance() { @@ -54,6 +55,11 @@ namespace phasereditor2d.scene { super("phasereditor2d.scene"); } + getCanvasManager() { + + return this._canvasManager; + } + async starting() { const type = window.localStorage.getItem("phasereditor2d.scene.RENDER_TYPE"); @@ -67,6 +73,8 @@ namespace phasereditor2d.scene { this.setDefaultRenderPixelArt(pixelArt); console.log("ScenePlugin: default pixelArt: " + pixelArt); + + this._canvasManager = new ui.CanvasManager(); } setDefaultRenderType(type?: "canvas" | "webgl") { @@ -113,6 +121,8 @@ namespace phasereditor2d.scene { this._sceneFinder = new core.json.SceneFinder(); + this.registerAnimationsPreviewDialogInAssetPack(); + // migrations reg.addExtension(new core.migrations.OriginMigration_v2_to_v3()); @@ -245,6 +255,10 @@ namespace phasereditor2d.scene { ui.sceneobjects.TilemapExtension.getInstance() ); + reg.addExtension( + new ui.codesnippets.CreateFromAsepriteCodeSnippetExtension() + ); + // align extensions reg.addExtension(...ui.editor.layout.DefaultLayoutExtensions.ALL); @@ -289,6 +303,8 @@ namespace phasereditor2d.scene { page => new ui.sceneobjects.ArcadeGeometrySection(page), page => new ui.sceneobjects.ArcadeBodyMovementSection(page), page => new ui.sceneobjects.ArcadeBodyCollisionSection(page), + page => new ui.sceneobjects.SpriteAnimationSection(page), + page => new ui.sceneobjects.SpriteAnimationConfigSection(page), page => new ui.sceneobjects.TextContentSection(page), page => new ui.sceneobjects.TextSection(page), page => new ui.sceneobjects.BitmapTextSection(page), @@ -307,7 +323,8 @@ namespace phasereditor2d.scene { page => new ui.sceneobjects.TextureSection(page), page => new ui.sceneobjects.SpineSection(page), page => new ui.sceneobjects.SpineBoundsProviderSection(page), - page => new ui.sceneobjects.SpineAnimationSection(page) + page => new ui.sceneobjects.SpineAnimationSection(page), + page => new ui.codesnippets.CreateFromAsepriteCodeSnippetSection(page) )); // scene tools @@ -352,6 +369,22 @@ namespace phasereditor2d.scene { )); } + private registerAnimationsPreviewDialogInAssetPack() { + + pack.ui.properties.AnimationsPreviewSection.openPreviewDialog = elem => { + + const dlg = new ui.sceneobjects.AnimationPreviewDialog(elem.getParent(), { + key: elem.getKey() + }); + + dlg.create(); + }; + } + + async openAnimationInEditor(anim: pack.core.AnimationConfigInPackItem) { + // nothing, it is injected in the AnimationsPlugin. + } + getTools() { return colibri.Platform.getExtensions (ui.editor.tools.SceneToolExtension.POINT_ID) @@ -438,6 +471,17 @@ namespace phasereditor2d.scene { return !file.isFolder() && colibri.Platform.getWorkbench().getContentTypeRegistry().getCachedContentType(file) === core.CONTENT_TYPE_SCENE; } + getCodeSnippetExtensions() { + + return colibri.Platform + .getExtensions(ui.codesnippets.CodeSnippetExtension.POINT_ID); + } + + getCodeSnippetExtensionByType(type: string) { + + return this.getCodeSnippetExtensions().find(e => e.getType() === type); + } + getPlainObjectExtensions() { return colibri.Platform diff --git a/source/editor/plugins/phasereditor2d.scene/src/core/code/JavaScriptUnitCodeGenerator.ts b/source/editor/plugins/phasereditor2d.scene/src/core/code/JavaScriptUnitCodeGenerator.ts index 8e7fe1f90..9fa992bef 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/core/code/JavaScriptUnitCodeGenerator.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/core/code/JavaScriptUnitCodeGenerator.ts @@ -418,11 +418,25 @@ namespace phasereditor2d.scene.core.code { this.join(args); if (this.isTypeScript() - && call.getExplicitType() + && (call.getExplicitType() || call.isNonNullAssertion()) && call.isDeclareReturnToVar() && call.getReturnToVar()) { - this.line(`) as ${call.getExplicitType()};`); + let line = ")"; + + if (call.isNonNullAssertion()) { + + line += "!"; + } + + if (call.getExplicitType()) { + + line += ` as ${call.getExplicitType()}`; + } + + line += ";"; + + this.line(line); } else { diff --git a/source/editor/plugins/phasereditor2d.scene/src/core/code/MethodCallCodeDOM.ts b/source/editor/plugins/phasereditor2d.scene/src/core/code/MethodCallCodeDOM.ts index 0effa31fe..58b81fa2a 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/core/code/MethodCallCodeDOM.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/core/code/MethodCallCodeDOM.ts @@ -10,6 +10,7 @@ namespace phasereditor2d.scene.core.code { private _isConstructor: boolean; private _explicitType: string; private _optionalContext: boolean; + private _nonNullAssertion: boolean; constructor(methodName: string, contextExpr = "") { super(); @@ -19,6 +20,17 @@ namespace phasereditor2d.scene.core.code { this._args = []; this._declareReturnToVar = false; this._isConstructor = false; + this._nonNullAssertion = false; + } + + setNonNullAssertion(nonNullAssertion: boolean) { + + this._nonNullAssertion = nonNullAssertion; + } + + isNonNullAssertion() { + + return this._nonNullAssertion; } setOptionalContext(optionalContext: boolean) { diff --git a/source/editor/plugins/phasereditor2d.scene/src/core/code/SceneCodeDOMBuilder.ts b/source/editor/plugins/phasereditor2d.scene/src/core/code/SceneCodeDOMBuilder.ts index b7b490292..82b274716 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/core/code/SceneCodeDOMBuilder.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/core/code/SceneCodeDOMBuilder.ts @@ -382,6 +382,8 @@ namespace phasereditor2d.scene.core.code { varname: "this" }); + this.buildCodeSnippets(result.statements); + lazyStatements.push(...result.lazyStatements); body.push(...result.statements); @@ -420,6 +422,24 @@ namespace phasereditor2d.scene.core.code { return ctrDecl; } + buildCodeSnippets(statements: CodeDOM[]) { + + const snippets = this._scene.getCodeSnippets().getSnippets(); + + if (snippets.length > 0) { + + statements.push(new code.RawCodeDOM("")); + statements.push(new code.RawCodeDOM("// snippets")); + + for (const codeSnippet of snippets) { + + const code = codeSnippet.buildCodeDOM(); + + statements.push(...code); + } + } + } + private buildPrefabTypeScriptDefinitionsCodeDOM(prefabObj: ISceneGameObject, objBuilder: ui.sceneobjects.GameObjectCodeDOMBuilder) { for (const comp of prefabObj.getEditorSupport().getActiveComponents()) { @@ -479,8 +499,11 @@ namespace phasereditor2d.scene.core.code { } const body = createMethodDecl.getBody(); + const lazyStatements: CodeDOM[] = []; + this.buildCodeSnippets(body); + this.addCreateAllPlainObjectCode(body, lazyStatements); for (const obj of this._scene.getGameObjects()) { diff --git a/source/editor/plugins/phasereditor2d.scene/src/core/json/ISceneData.ts b/source/editor/plugins/phasereditor2d.scene/src/core/json/ISceneData.ts index 9e8316326..ff393756c 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/core/json/ISceneData.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/core/json/ISceneData.ts @@ -15,6 +15,7 @@ namespace phasereditor2d.scene.core.json { plainObjects?: IScenePlainObjectData[]; displayList: IObjectData[]; prefabProperties?: any[]; + codeSnippets?: ui.codesnippets.ICodeSnippetData[]; meta: { app: string, url: string, diff --git a/source/editor/plugins/phasereditor2d.scene/src/core/json/SceneWriter.ts b/source/editor/plugins/phasereditor2d.scene/src/core/json/SceneWriter.ts index 14cd95380..6c4e87fc1 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/core/json/SceneWriter.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/core/json/SceneWriter.ts @@ -81,6 +81,15 @@ namespace phasereditor2d.scene.core.json { sceneData.prefabProperties = prefabProperties; } + // code snippets + + const codeSnippets = this._scene.getCodeSnippets(); + + if (codeSnippets.getSnippets().length > 0) { + + sceneData.codeSnippets = codeSnippets.toJSON(); + } + return sceneData; } diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/CanvasManager.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/CanvasManager.ts new file mode 100644 index 000000000..ec21fa5d2 --- /dev/null +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/CanvasManager.ts @@ -0,0 +1,48 @@ +namespace phasereditor2d.scene.ui { + + export class CanvasManager { + + private _freeCanvases: HTMLCanvasElement[]; + private _count: number; + + constructor() { + + this._freeCanvases = []; + this._count = 0; + } + + takeCanvas() { + + if (this._freeCanvases.length === 0) { + + this._count++; + + console.log("CanvasManager: create new canvas. Count new: " + this._count); + + const canvas = document.createElement("canvas"); + + return canvas; + + } else { + + console.log("CanvasManager: reuse canvas. Total available: " + (this._freeCanvases.length - 1)); + + return this._freeCanvases.pop(); + } + } + + releaseCanvas(canvas: HTMLCanvasElement) { + + if (this._freeCanvases.indexOf(canvas) < 0) { + + console.log("CanvasManager: release canvas. Total available: " + (this._freeCanvases.length + 1)); + + this._freeCanvases.push(canvas); + + } else { + + console.log("CanvasManager: Hey, releasing a released canvas?"); + } + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/Scene.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/Scene.ts index 46a65da88..6c085c498 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/Scene.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/Scene.ts @@ -3,7 +3,7 @@ namespace phasereditor2d.scene.ui { export class Scene extends BaseScene { - static CURRENT_VERSION = 4; + static CURRENT_VERSION = 5; private _id: string; private _sceneType: core.json.SceneType; @@ -12,6 +12,7 @@ namespace phasereditor2d.scene.ui { private _prefabProperties: sceneobjects.PrefabUserProperties; private _objectLists: sceneobjects.ObjectLists; private _plainObjects: sceneobjects.IScenePlainObject[]; + private _codeSnippets: codesnippets.CodeSnippets; private _version: number; constructor(editor?: editor.SceneEditor) { @@ -27,6 +28,8 @@ namespace phasereditor2d.scene.ui { this._plainObjects = []; + this._codeSnippets = new codesnippets.CodeSnippets(); + this._prefabProperties = new sceneobjects.PrefabUserProperties(); this._version = Scene.CURRENT_VERSION; @@ -146,6 +149,16 @@ namespace phasereditor2d.scene.ui { this.children.addAt(obj, index, skipCallback); } + getCodeSnippets() { + + return this._codeSnippets; + } + + addCodeSnippet(codeSnippet: codesnippets.CodeSnippet) { + + this._codeSnippets.add(codeSnippet); + } + addPlainObject(obj: sceneobjects.IScenePlainObject) { this._plainObjects.push(obj); diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/SceneMaker.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/SceneMaker.ts index 68e307866..59bbd3f2a 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/SceneMaker.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/SceneMaker.ts @@ -377,6 +377,11 @@ namespace phasereditor2d.scene.ui { this._editorScene.getPrefabUserProperties().readJSON(sceneData.prefabProperties); } + if (sceneData.codeSnippets) { + + this._editorScene.getCodeSnippets().readJSON(sceneData.codeSnippets); + } + this._editorScene.setSceneType(sceneData.sceneType || core.json.SceneType.SCENE); // removes this condition, it is used temporal for compatibility diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/SceneThumbnailImage.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/SceneThumbnailImage.ts index 754c0b188..14f31709c 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/SceneThumbnailImage.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/SceneThumbnailImage.ts @@ -54,7 +54,7 @@ namespace phasereditor2d.scene.ui { if (singleObject) { - if (singleObject instanceof sceneobjects.Container) { + if (singleObject instanceof sceneobjects.Container || singleObject instanceof sceneobjects.Layer) { const container = singleObject as sceneobjects.Container; @@ -80,7 +80,10 @@ namespace phasereditor2d.scene.ui { const cx = s.borderX + s.borderWidth / 2 + dx; const cy = s.borderY + s.borderHeight / 2 + dy; - sprite.setPosition(cx, cy); + if (sprite.setPosition) { + + sprite.setPosition(cx, cy); + } } } else { diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/ThumbnailCache.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/ThumbnailCache.ts index 19679b710..c76006a4a 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/ThumbnailCache.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/ThumbnailCache.ts @@ -11,7 +11,7 @@ namespace phasereditor2d.scene.ui { async clearCache() { - await this._database.clear(); + await this._database?.clear(); } constructor(dbName: string) { diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/blocks/SceneEditorBlocksCellRendererProvider.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/blocks/SceneEditorBlocksCellRendererProvider.ts index aa7dabd62..f13f46206 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/blocks/SceneEditorBlocksCellRendererProvider.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/blocks/SceneEditorBlocksCellRendererProvider.ts @@ -7,7 +7,6 @@ namespace phasereditor2d.scene.ui.blocks { constructor() { super("grid"); - } getCellRenderer(element: any) { @@ -42,6 +41,10 @@ namespace phasereditor2d.scene.ui.blocks { } else if (element instanceof viewers.PhaserTypeSymbol) { return new controls.viewers.IconImageCellRenderer(colibri.ColibriPlugin.getInstance().getIcon(colibri.ICON_FOLDER)); + + } else if (element instanceof pack.core.AnimationConfigInPackItem) { + + return new pack.ui.viewers.AnimationConfigCellRenderer("square"); } return super.getCellRenderer(element); diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/blocks/SceneEditorBlocksContentProvider.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/blocks/SceneEditorBlocksContentProvider.ts index 97e796c44..0f3b19a7c 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/blocks/SceneEditorBlocksContentProvider.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/blocks/SceneEditorBlocksContentProvider.ts @@ -11,6 +11,8 @@ namespace phasereditor2d.scene.ui.blocks { pack.core.MULTI_ATLAS_TYPE, pack.core.UNITY_ATLAS_TYPE, pack.core.SPRITESHEET_TYPE, + pack.core.ANIMATION_TYPE, + pack.core.ASEPRITE_TYPE, pack.core.BITMAP_FONT_TYPE, pack.core.SPINE_JSON_TYPE, pack.core.SPINE_BINARY_TYPE, @@ -156,6 +158,11 @@ namespace phasereditor2d.scene.ui.blocks { return parent.getItems().filter(i => SCENE_EDITOR_BLOCKS_PACK_ITEM_TYPES.has(i.getType())); } + if (parent instanceof pack.core.BaseAnimationsAssetPackItem) { + + return parent.getAnimations(); + } + if (typeof (parent) === "string") { if (SCENE_OBJECT_CATEGORY_SET.has(parent)) { @@ -188,6 +195,10 @@ namespace phasereditor2d.scene.ui.blocks { return this.getPackItems() .filter(item => item instanceof pack.core.BitmapFontAssetPackItem); + case pack.core.ANIMATION_TYPE: + return this.getPackItems() + .filter(item => item instanceof pack.core.BaseAnimationsAssetPackItem); + case BUILTIN_SECTION: return SCENE_OBJECT_CATEGORIES; diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/blocks/SceneEditorBlocksProvider.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/blocks/SceneEditorBlocksProvider.ts index 407e8d0a1..d74f7da5d 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/blocks/SceneEditorBlocksProvider.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/blocks/SceneEditorBlocksProvider.ts @@ -128,6 +128,20 @@ namespace phasereditor2d.scene.ui.blocks { } } + } else if (obj instanceof pack.core.AnimationConfigInPackItem) { + + const item = this.getFreshItem(obj.getParent()) as pack.core.BaseAnimationsAssetPackItem; + + if (item) { + + const found = item.getAnimations().find(a => a.getKey() === obj.getKey()); + + if (found) { + + set.add(found); + } + } + } else { set.add(obj); diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/blocks/SceneEditorBlocksTreeRendererProvider.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/blocks/SceneEditorBlocksTreeRendererProvider.ts index 3c9f49f01..dd981420f 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/blocks/SceneEditorBlocksTreeRendererProvider.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/blocks/SceneEditorBlocksTreeRendererProvider.ts @@ -12,6 +12,7 @@ namespace phasereditor2d.scene.ui.blocks { pack.core.SVG_TYPE, pack.core.ATLAS_TYPE, pack.core.SPRITESHEET_TYPE, + pack.core.ANIMATION_TYPE, pack.core.BITMAP_FONT_TYPE, pack.core.SPINE_JSON_TYPE, pack.core.SPINE_BINARY_TYPE @@ -69,6 +70,11 @@ namespace phasereditor2d.scene.ui.blocks { return true; } + if (obj instanceof pack.core.AnimationConfigInPackItem) { + + return true; + } + return super.isShadowAsChild(obj); } diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/CodeSnippet.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/CodeSnippet.ts new file mode 100644 index 000000000..c79734dc9 --- /dev/null +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/CodeSnippet.ts @@ -0,0 +1,44 @@ +namespace phasereditor2d.scene.ui.codesnippets { + + export interface ICodeSnippetData { + type: string; + id: string; + } + + export abstract class CodeSnippet { + + private _type: string; + private _id: string; + + constructor(type: string) { + + this._type = type; + this._id = Phaser.Utils.String.UUID(); + } + + getId() { + + return this._id; + } + + getType() { + + return this._type; + } + + abstract buildCodeDOM(): core.code.CodeDOM[]; + + abstract getDisplayName(): string; + + writeJSON(data: ICodeSnippetData): void { + + data.type = this._type; + data.id = this._id; + } + + readJSON(data: ICodeSnippetData) { + + this._id = data.id; + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/CodeSnippetExtension.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/CodeSnippetExtension.ts new file mode 100644 index 000000000..81751cf4e --- /dev/null +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/CodeSnippetExtension.ts @@ -0,0 +1,34 @@ + +namespace phasereditor2d.scene.ui.codesnippets { + + export abstract class CodeSnippetExtension extends colibri.Extension { + + static POINT_ID = "phasereditor2d.scene.ui.codesnippets.CodeSnippetExtension"; + + private _name: string; + private _type: string; + + constructor(type: string, name: string) { + super(CodeSnippetExtension.POINT_ID); + + this._type = type; + this._name = name; + } + + getType() { + + return this._type; + } + + getName() { + + return this._name; + } + + abstract isEnabledFor(_editor: editor.SceneEditor): boolean; + + abstract createAndConfigureCodeSnippets(): Promise; + + abstract createEmptyCodeSnippet(): CodeSnippet; + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/CodeSnippetOrderOperation.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/CodeSnippetOrderOperation.ts new file mode 100644 index 000000000..75af7fb3d --- /dev/null +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/CodeSnippetOrderOperation.ts @@ -0,0 +1,127 @@ +/// +namespace phasereditor2d.scene.ui.codesnippets { + + import SceneEditor = editor.SceneEditor; + import DepthMove = editor.undo.DepthMove; + + export class CodeSnippetOrderOperation extends CodeSnippetsSnapshotOperation { + + private _depthMove: editor.undo.DepthMove; + + constructor(editor: SceneEditor, depthMove: DepthMove) { + super(editor); + + this._depthMove = depthMove; + } + + static allow(editor: SceneEditor, move: DepthMove) { + + // sort the selection and filter off non-game-objects + let sel = this.sortedSelection(editor); + + // if the sorted selection contains all the selected objects + if (sel.length !== editor.getSelection().length) { + + return false; + } + + const siblings = editor.getScene().getCodeSnippets().getSnippets(); + + for (const obj of sel) { + + const index = siblings.indexOf(obj); + + let bottomIndex = 0; + const len = siblings.length; + + if (move === "Bottom" || move === "Down") { + + if (index === len - 1) { + + return false; + } + + } else { // Top || Up + + if (index === bottomIndex) { + + return false; + } + } + } + + return true; + } + + protected async performModification() { + + const editor = this.getEditor(); + + const sel = CodeSnippetOrderOperation.sortedSelection(editor); + + const siblings = editor.getScene().getCodeSnippets().getSnippets(); + + switch (this._depthMove) { + + case "Bottom": + + for (const obj of sel) { + + Phaser.Utils.Array.BringToTop(siblings, obj); + } + + break; + + case "Top": + + for (let i = 0; i < sel.length; i++) { + + const obj = sel[sel.length - i - 1]; + + Phaser.Utils.Array.SendToBack(siblings, obj); + } + + break; + + case "Down": + + for (let i = 0; i < sel.length; i++) { + + const obj = sel[sel.length - i - 1]; + + Phaser.Utils.Array.MoveUp(siblings, obj); + } + + break; + + case "Up": + + for (const obj of sel) { + + Phaser.Utils.Array.MoveDown(siblings, obj); + } + + break; + } + + this.getEditor().repaint(); + } + + private static sortedSelection(editor: SceneEditor) { + + const sel = editor.getSelectedCodeSnippets(); + + const siblings = editor.getScene().getCodeSnippets().getSnippets(); + + sel.sort((a, b) => { + + const aa = siblings.indexOf(a); + const bb = siblings.indexOf(b); + + return aa - bb; + }); + + return sel; + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/CodeSnippets.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/CodeSnippets.ts new file mode 100644 index 000000000..ebc5c29cf --- /dev/null +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/CodeSnippets.ts @@ -0,0 +1,59 @@ +namespace phasereditor2d.scene.ui.codesnippets { + + export class CodeSnippets { + + private _list: CodeSnippet[] = []; + + add(snippet: CodeSnippet) { + + this._list.push(snippet); + } + + removeByIds(ids: string[]) { + + const removeSet = new Set(ids); + + this._list = this._list.filter(s => !removeSet.has(s.getId())); + } + + getSnippets() { + + return this._list; + } + + readJSON(codeSnippets: ICodeSnippetData[]) { + + this._list = []; + + for (const snippetData of codeSnippets) { + + const ext = ScenePlugin.getInstance().getCodeSnippetExtensionByType(snippetData.type); + + if (ext) { + + const snippet = ext.createEmptyCodeSnippet(); + + snippet.readJSON(snippetData); + + this.add(snippet); + } + } + } + + toJSON(): ICodeSnippetData[] { + + const result: ICodeSnippetData[] = []; + + for (const snippet of this._list) { + + const data: ICodeSnippetData = {} as any; + + snippet.writeJSON(data); + + result.push(data); + } + + return result; + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/CodeSnippetsSnapshotOperation.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/CodeSnippetsSnapshotOperation.ts new file mode 100644 index 000000000..445d90472 --- /dev/null +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/CodeSnippetsSnapshotOperation.ts @@ -0,0 +1,79 @@ +/// +namespace phasereditor2d.scene.ui.codesnippets { + + import json = core.json; + + export interface ICodeSnippetSnapshot { + + selection: string[]; + codeSnippets: ICodeSnippetData[]; + } + + export class CodeSnippetsSnapshotOperation extends editor.undo.SceneEditorOperation { + + private _before: ICodeSnippetSnapshot; + private _after: ICodeSnippetSnapshot; + private _operation: () => Promise; + + constructor(editor: editor.SceneEditor, operation?: () => Promise) { + super(editor); + + this._operation = operation; + } + + async execute() { + + this._before = this.takeSnapshot(); + + await this.performModification(); + + this._after = this.takeSnapshot(); + + this._editor.setDirty(true); + this._editor.refreshOutline(); + this._editor.repaint(); + this._editor.dispatchSelectionChanged(); + } + + protected async performModification(): Promise { + + if (this._operation) { + + await this._operation(); + } + } + + private takeSnapshot(): ICodeSnippetSnapshot { + + const scene = this.getScene(); + + return { + selection: this.getEditor().getSelectedCodeSnippets().map(s => s.getId()), + codeSnippets: scene.getCodeSnippets().toJSON() + }; + } + + protected loadSnapshot(snapshot: ICodeSnippetSnapshot) { + + const editor = this.getEditor(); + const scene = this.getScene(); + + scene.getCodeSnippets().readJSON(snapshot.codeSnippets); + + editor.setDirty(true); + editor.repaint(); + editor.refreshOutline(); + editor.getSelectionManager().setSelectionByIds(snapshot.selection); + } + + undo(): void { + + this.loadSnapshot(this._before); + } + + redo(): void { + + this.loadSnapshot(this._after); + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/aseprite/CreateFromAsepriteCodeSnippet.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/aseprite/CreateFromAsepriteCodeSnippet.ts new file mode 100644 index 000000000..a4a4019e1 --- /dev/null +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/aseprite/CreateFromAsepriteCodeSnippet.ts @@ -0,0 +1,43 @@ +namespace phasereditor2d.scene.ui.codesnippets { + + export interface ICreateFromAsepriteCodeSnippetData extends ICodeSnippetData { + key: string; + } + + export class CreateFromAsepriteCodeSnippet extends CodeSnippet { + + public assetKey: string; + + constructor() { + super(CreateFromAsepriteCodeSnippetExtension.TYPE); + } + + buildCodeDOM(): core.code.CodeDOM[] { + + const dom = new core.code.MethodCallCodeDOM("createFromAseprite", "this.anims"); + + dom.argLiteral(this.assetKey); + + return [dom]; + } + + getDisplayName(): string { + + return `${this.assetKey} - anims.createFromAseprite`; + } + + writeJSON(data: ICreateFromAsepriteCodeSnippetData): void { + + super.writeJSON(data); + + data.key = this.assetKey; + } + + readJSON(data: ICreateFromAsepriteCodeSnippetData): void { + + super.readJSON(data); + + this.assetKey = data.key; + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/aseprite/CreateFromAsepriteCodeSnippetExtension.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/aseprite/CreateFromAsepriteCodeSnippetExtension.ts new file mode 100644 index 000000000..69ada74f2 --- /dev/null +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/aseprite/CreateFromAsepriteCodeSnippetExtension.ts @@ -0,0 +1,51 @@ +namespace phasereditor2d.scene.ui.codesnippets { + + export class CreateFromAsepriteCodeSnippetExtension extends CodeSnippetExtension { + + static TYPE = "animsCreateFromAseprite"; + + constructor() { + super(CreateFromAsepriteCodeSnippetExtension.TYPE, "Create Animations From Aseprite"); + } + + isEnabledFor(_editor: editor.SceneEditor): boolean { + + return !_editor.getScene().isPrefabSceneType(); + } + + createEmptyCodeSnippet(): CodeSnippet { + + return new CreateFromAsepriteCodeSnippet(); + } + + async createAndConfigureCodeSnippets(): Promise { + + const finder = new pack.core.PackFinder(); + + await finder.preload(); + + const input = finder.getAssets() + .filter(i => i instanceof pack.core.AsepriteAssetPackItem); + + const dlg = new pack.ui.dialogs.AssetSelectionDialog("tree", false); + + dlg.create(); + + dlg.setTitle("Select Aseprite File Key"); + + dlg.getViewer().setInput(input); + + const result = await dlg.getResultPromise() as pack.core.AnimationConfigInPackItem[]; + + const snippets = (result || []).map(a => { + + const snippet = new CreateFromAsepriteCodeSnippet(); + snippet.assetKey = a.getKey(); + + return snippet; + }); + + return snippets; + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/aseprite/CreateFromAsepriteCodeSnippetSection.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/aseprite/CreateFromAsepriteCodeSnippetSection.ts new file mode 100644 index 000000000..4bc439531 --- /dev/null +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/codesnippets/aseprite/CreateFromAsepriteCodeSnippetSection.ts @@ -0,0 +1,81 @@ +/// +namespace phasereditor2d.scene.ui.codesnippets { + + import controls = colibri.ui.controls; + + export class CreateFromAsepriteCodeSnippetSection extends ui.editor.properties.BaseSceneSection { + + constructor(page: controls.properties.PropertyPage) { + super(page, "phasereditor2d.scene.ui.codesnippets.CreateFromAsepriteCodeSnippetSection", "Create From Aseprite") + } + + createForm(parent: HTMLDivElement): void { + + const comp = this.createGridElement(parent, 3); + comp.style.gridTemplateColumns = "auto 1fr auto"; + + this.createLabel(comp, "Aseprite File Key", "The Aseprite animations file key."); + + { + const text = this.createText(comp, false); + + this.addUpdater(() => { + + text.value = this.getSelectionFirstElement().assetKey; + }); + } + + const btnUI = this.createButtonDialog({ + dialogTittle: "Select Animation File Key", + createDialogViewer: async (revealValue: string) => { + + const viewer = new controls.viewers.TreeViewer("phasereditor2d.scene.ui.sceneobjects.CreateFromAsepriteCodeSnippetSection." + this.getId()); + + viewer.setCellRendererProvider(new controls.viewers.EmptyCellRendererProvider(e => new pack.ui.viewers.AnimationsItemCellRenderer())); + viewer.setLabelProvider(new pack.ui.viewers.AssetPackLabelProvider()); + viewer.setTreeRenderer(new controls.viewers.TreeViewerRenderer(viewer)); + viewer.setContentProvider(new controls.viewers.ArrayTreeContentProvider()); + + const finder = new pack.core.PackFinder(); + await finder.preload(); + + const assetItems = finder + .getAssets(i => i instanceof pack.core.AsepriteAssetPackItem); + + viewer.setInput(assetItems); + + viewer.revealAndSelect(assetItems.find(a => a.getKey() === revealValue)); + + return viewer; + }, + getValue: () => { + + return this.getSelectionFirstElement().assetKey || ""; + }, + onValueSelected: (value: string) => { + + this.getEditor().getUndoManager().add(new CodeSnippetsSnapshotOperation(this.getEditor(), async () => { + + this.getSelectionFirstElement().assetKey = value; + })); + }, + dialogElementToString: (viewer: controls.viewers.TreeViewer, value: pack.core.AsepriteAssetPackItem): string => { + + return value.getKey(); + } + }); + + comp.appendChild(btnUI.buttonElement); + } + + canEdit(obj: any, n: number): boolean { + + return obj instanceof codesnippets.CreateFromAsepriteCodeSnippet; + } + + canEditNumber(n: number): boolean { + + return n === 1; + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/OverlayLayer.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/OverlayLayer.ts index 45ade5977..9e1a76629 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/OverlayLayer.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/OverlayLayer.ts @@ -293,11 +293,12 @@ namespace phasereditor2d.scene.ui.editor { const b = camera.getScreenPoint(borderX + borderWidth, borderY + borderHeight); ctx.save(); ctx.strokeStyle = theme.dark ? "#0a0a0a" : "#404040"; - ctx.strokeRect(a.x + 2, a.y + 2, b.x - a.x, b.y - a.y); + ctx.strokeRect(a.x - 2, a.y - 2, b.x - a.x + 4, b.y - a.y + 4); ctx.restore(); ctx.lineWidth = 1; - ctx.strokeRect(a.x, a.y, b.x - a.x, b.y - a.y); + ctx.strokeStyle = theme.dark ? "#a0a0a0" : "#f0f0f0"; + ctx.strokeRect(a.x - 1, a.y - 1, b.x - a.x + 2, b.y - a.y + 2); ctx.restore(); } } diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/SceneEditor.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/SceneEditor.ts index 7337633fc..d50012887 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/SceneEditor.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/SceneEditor.ts @@ -275,13 +275,8 @@ namespace phasereditor2d.scene.ui.editor { this.getElement().appendChild(container); - const pool = Phaser.Display.Canvas.CanvasPool; - - this._gameCanvas = ScenePlugin.DEFAULT_EDITOR_CANVAS_CONTEXT === Phaser.CANVAS - - ? pool.create2D(this.getElement(), 100, 100) - - : pool.createWebGL(this.getElement(), 100, 100); + this._gameCanvas = ScenePlugin.getInstance().getCanvasManager().takeCanvas(); + this._gameCanvas.style.visibility = "hidden"; this._gameCanvas.classList.add("GameCanvas"); @@ -595,6 +590,12 @@ namespace phasereditor2d.scene.ui.editor { return this.getSelection().filter(obj => sceneobjects.ScenePlainObjectEditorSupport.hasEditorSupport(obj)); } + getSelectedCodeSnippets(): codesnippets.CodeSnippet[] { + + return this.getSelection() + .filter(obj => obj instanceof codesnippets.CodeSnippet); + } + getSelectedUserComponentNodes(): sceneobjects.UserComponentNode[] { return this.getSelection().filter(obj => obj instanceof sceneobjects.UserComponentNode); @@ -640,11 +641,6 @@ namespace phasereditor2d.scene.ui.editor { return this._overlayLayer; } - getGameCanvas() { - - return this._gameCanvas; - } - getScene() { return this._scene; @@ -724,6 +720,8 @@ namespace phasereditor2d.scene.ui.editor { if (this._scene) { this._scene.destroyGame(); + + ScenePlugin.getInstance().getCanvasManager().releaseCanvas(this._game.canvas); } this._cellRendererCache.clear(); @@ -866,10 +864,12 @@ namespace phasereditor2d.scene.ui.editor { } getOutlineProvider() { + return this._outlineProvider; } refreshOutline() { + this._outlineProvider.repaint(); } @@ -877,6 +877,8 @@ namespace phasereditor2d.scene.ui.editor { this._gameBooted = true; + this._gameCanvas.style.visibility = "visible"; + if (!this._sceneRead) { await this.readScene(); diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/SceneEditorMenuCreator.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/SceneEditorMenuCreator.ts index ff4167fe9..192d007f3 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/SceneEditorMenuCreator.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/SceneEditorMenuCreator.ts @@ -23,6 +23,8 @@ namespace phasereditor2d.scene.ui.editor { menu.addMenu(this.createAddObjectMenu()) + menu.addMenu(this.createAddCodeSnippetMenu()) + menu.addSeparator(); menu.addMenu(this.createPrefabMenu()); @@ -52,7 +54,40 @@ namespace phasereditor2d.scene.ui.editor { menu.addMenu(this.createCompilerMenu()); } - createScriptingMenu(): controls.Menu { + private createAddCodeSnippetMenu(): controls.Menu { + + const menu = new controls.Menu("Code Snippets"); + + for (const ext of ScenePlugin.getInstance().getCodeSnippetExtensions()) { + + menu.addAction({ + text: "Add " + ext.getName(), + icon: resources.getIcon(resources.ICON_BUILD), + enabled: ext.isEnabledFor(this._editor), + callback: async () => { + + const snippets = await ext.createAndConfigureCodeSnippets(); + + if (snippets) { + + this._editor.getUndoManager().add(new codesnippets.CodeSnippetsSnapshotOperation(this._editor, async () => { + + for (const snippet of snippets) { + + this._editor.getScene().addCodeSnippet(snippet); + } + + this._editor.setSelection(snippets); + })); + } + } + }); + } + + return menu; + } + + private createScriptingMenu(): controls.Menu { const menu = new controls.Menu("Scripting"); @@ -68,7 +103,7 @@ namespace phasereditor2d.scene.ui.editor { } createArcadePhysicsMenu(): controls.Menu { - + const menu = new controls.Menu("Arcade Physics"); menu.addCommand(editor.commands.CMD_ARCADE_ENABLE_BODY, { diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/SelectionManager.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/SelectionManager.ts index af2280d1a..b6838e4da 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/SelectionManager.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/SelectionManager.ts @@ -18,12 +18,16 @@ namespace phasereditor2d.scene.ui.editor { const selection = this._editor.getSelection(); const selectedObjects = this._editor.getSelectedGameObjects(); const selectedPlainObjects = this._editor.getSelectedPlainObjects(); + const selectedCodeSnippets = this._editor.getSelectedCodeSnippets(); list.push(...selectedObjects .map(obj => obj.getEditorSupport().getId())); list.push(...selectedPlainObjects - .map(obj => obj.getEditorSupport().getId())) + .map(obj => obj.getEditorSupport().getId())); + + list.push(...selectedCodeSnippets + .map((s: codesnippets.CodeSnippet) => s.getId())); list.push(...selection .filter(obj => obj instanceof sceneobjects.ObjectList) @@ -31,7 +35,7 @@ namespace phasereditor2d.scene.ui.editor { list.push(...selection .filter(obj => obj instanceof sceneobjects.ObjectListItem) - .map(obj => (obj as sceneobjects.ObjectListItem).getId())) + .map(obj => (obj as sceneobjects.ObjectListItem).getId())); list.push(...selection .filter(i => i instanceof sceneobjects.UserComponentNode) @@ -39,7 +43,7 @@ namespace phasereditor2d.scene.ui.editor { list.push(...selection .filter(obj => obj instanceof sceneobjects.UserProperty) - .map((p: sceneobjects.UserProperty) => `prefabProperty#${p.getName()}`)) + .map((p: sceneobjects.UserProperty) => `prefabProperty#${p.getName()}`)); return list; } @@ -70,17 +74,22 @@ namespace phasereditor2d.scene.ui.editor { map.set(list.getId(), list); - for(const item of list.getItems()) { + for (const item of list.getItems()) { map.set(item.getId(), item); } } - for(const prop of scene.getPrefabUserProperties().getProperties()) { + for (const prop of scene.getPrefabUserProperties().getProperties()) { map.set(`prefabProperty#${prop.getName()}`, prop); } + for (const snippet of scene.getCodeSnippets().getSnippets()) { + + map.set(snippet.getId(), snippet); + } + const sel = selectionIds .map(id => map.get(id)) .filter(obj => obj !== undefined); diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/commands/SceneEditorCommands.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/commands/SceneEditorCommands.ts index c519f7791..255af7b4e 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/commands/SceneEditorCommands.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/commands/SceneEditorCommands.ts @@ -196,6 +196,33 @@ namespace phasereditor2d.scene.ui.editor.commands { this.registerPropertiesCommands(manager); this.registerSpineCommands(manager); + + this.registerCodeSnippetOrderCommands(manager); + } + + static registerCodeSnippetOrderCommands(manager: colibri.ui.ide.commands.CommandManager) { + + const moves: [undo.DepthMove, string][] = [ + ["Up", CMD_SORT_OBJ_UP], + ["Down", CMD_SORT_OBJ_DOWN], + ["Top", CMD_SORT_OBJ_TOP], + ["Bottom", CMD_SORT_OBJ_BOTTOM] + ]; + + for (const tuple of moves) { + + const move = tuple[0]; + const cmd = tuple[1]; + + manager.addHandlerHelper(cmd, + // testFunc + args => isSceneScope(args) && args.activeEditor.getSelection().length > 0 + && codesnippets.CodeSnippetOrderOperation.allow(args.activeEditor as any, move), + // execFunc + args => args.activeEditor.getUndoManager().add( + new codesnippets.CodeSnippetOrderOperation(args.activeEditor as editor.SceneEditor, move) + )); + } } static registerPlainObjectOrderCommands(manager: colibri.ui.ide.commands.CommandManager) { diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/outline/SceneEditorOutlineContentProvider.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/outline/SceneEditorOutlineContentProvider.ts index a00a8a16b..50f59ebf9 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/outline/SceneEditorOutlineContentProvider.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/outline/SceneEditorOutlineContentProvider.ts @@ -44,6 +44,12 @@ namespace phasereditor2d.scene.ui.editor.outline { })); } + if (!scene.isPrefabSceneType() + && scene.getCodeSnippets().getSnippets().length > 0) { + + roots.push(scene.getCodeSnippets()); + } + if (scene.isPrefabSceneType()) { roots.push(scene.getPrefabUserProperties()); @@ -54,6 +60,11 @@ namespace phasereditor2d.scene.ui.editor.outline { getChildren(parent: any): any[] { + if (parent instanceof codesnippets.CodeSnippets) { + + return parent.getSnippets(); + } + if (parent instanceof sceneobjects.PrefabUserProperties) { return parent.getProperties(); diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/outline/SceneEditorOutlineRendererProvider.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/outline/SceneEditorOutlineRendererProvider.ts index 8577a69c8..7a284c860 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/outline/SceneEditorOutlineRendererProvider.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/outline/SceneEditorOutlineRendererProvider.ts @@ -35,6 +35,14 @@ namespace phasereditor2d.scene.ui.editor.outline { } else if (element instanceof sceneobjects.UserProperty) { return new controls.viewers.IconImageCellRenderer(resources.getIcon(resources.ICON_USER_PROPERTY)); + + } else if (element instanceof codesnippets.CodeSnippets) { + + return new controls.viewers.IconImageCellRenderer(colibri.ColibriPlugin.getInstance().getIcon(colibri.ICON_FOLDER)); + + } else if (element instanceof codesnippets.CodeSnippet) { + + return new controls.viewers.IconImageCellRenderer(resources.getIcon(resources.ICON_BUILD)); } const extensions = ScenePlugin.getInstance().getSceneEditorOutlineExtensions(); diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/outline/SceneEditorOutlineStyledLabelProvider.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/outline/SceneEditorOutlineStyledLabelProvider.ts index 6a4d4c346..b07872de4 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/outline/SceneEditorOutlineStyledLabelProvider.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/outline/SceneEditorOutlineStyledLabelProvider.ts @@ -52,6 +52,14 @@ namespace phasereditor2d.scene.ui.editor.outline { } else if (obj instanceof sceneobjects.UserProperty) { return obj.getLabel(); + + } else if (obj instanceof codesnippets.CodeSnippets) { + + return "Code Snippets"; + + } else if (obj instanceof codesnippets.CodeSnippet) { + + return obj.getDisplayName(); } const extensions = ScenePlugin.getInstance().getSceneEditorOutlineExtensions(); diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/undo/DeleteOperation.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/undo/DeleteOperation.ts index 8103fc6c0..a6c03739e 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/undo/DeleteOperation.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/undo/DeleteOperation.ts @@ -45,6 +45,10 @@ namespace phasereditor2d.scene.ui.editor.undo { scene.removePlainObjects(editor.getSelectedPlainObjects()); + const codeSnippetIds = editor.getSelectedCodeSnippets().map(s => s.getId()); + + editor.getScene().getCodeSnippets().removeByIds(codeSnippetIds); + const nodes = editor.getSelectedUserComponentNodes(); for (const node of nodes) { diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/undo/SceneSnapshotOperation.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/undo/SceneSnapshotOperation.ts index 724a3db36..11192633f 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/editor/undo/SceneSnapshotOperation.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/editor/undo/SceneSnapshotOperation.ts @@ -9,6 +9,7 @@ namespace phasereditor2d.scene.ui.editor.undo { lists: json.IObjectListData[]; plainObjects: json.IScenePlainObjectData[], prefabUserProperties: any[]; + codeSnippets: codesnippets.ICodeSnippetData[]; } export class SceneSnapshotOperation extends SceneEditorOperation { @@ -81,7 +82,9 @@ namespace phasereditor2d.scene.ui.editor.undo { prefabUserProperties: scene.getPrefabUserProperties().toJSON(), - selection: this.getEditor().getSelectionManager().getSelectionIds() + codeSnippets: scene.getCodeSnippets().toJSON(), + + selection: this.getEditor().getSelectionManager().getSelectionIds(), }; } @@ -102,6 +105,8 @@ namespace phasereditor2d.scene.ui.editor.undo { scene.getObjectLists().readJSON_lists(snapshot.lists); + scene.getCodeSnippets().readJSON(snapshot.codeSnippets); + scene.getPrefabUserProperties().readJSON(snapshot.prefabUserProperties); editor.setDirty(true); diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/ImageLoaderExtension.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/ImageLoaderExtension.ts index b74ce90e4..f7e717e54 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/ImageLoaderExtension.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/ImageLoaderExtension.ts @@ -29,29 +29,45 @@ namespace phasereditor2d.scene.ui.sceneobjects { acceptAsset(asset: any): boolean { return asset instanceof pack.core.ImageFrameContainerAssetPackItem - || asset instanceof pack.core.AssetPackImageFrame; + || asset instanceof pack.core.AsepriteAssetPackItem + || asset instanceof pack.core.AssetPackImageFrame + || asset instanceof pack.core.AnimationConfigInPackItem; } async updateLoader(scene: BaseScene, asset: any) { - let imageFrameContainerPackItem: pack.core.ImageFrameContainerAssetPackItem = null; + if (asset instanceof pack.core.AnimationConfigInPackItem) { - if (asset instanceof pack.core.ImageFrameContainerAssetPackItem) { + for(const animFrame of asset.getFrames()) { - imageFrameContainerPackItem = asset; + const textureFrame = animFrame.getTextureFrame(); + + if (textureFrame) { + + await this.updateLoader(scene, textureFrame); + } + } + } + + let framesContainer: pack.core.ImageFrameContainerAssetPackItem | pack.core.AsepriteAssetPackItem = null; + + if (asset instanceof pack.core.ImageFrameContainerAssetPackItem + || asset instanceof pack.core.AsepriteAssetPackItem) { + + framesContainer = asset; } else if (asset instanceof pack.core.AssetPackImageFrame) { - imageFrameContainerPackItem = (asset.getPackItem() as pack.core.ImageFrameContainerAssetPackItem); + framesContainer = (asset.getPackItem() as pack.core.ImageFrameContainerAssetPackItem); } - if (imageFrameContainerPackItem !== null) { + if (framesContainer !== null) { - await imageFrameContainerPackItem.preload(); + await framesContainer.preload(); - await imageFrameContainerPackItem.preloadImages(); + await framesContainer.preloadImages(); - imageFrameContainerPackItem.addToPhaserCache(scene.game, scene.getPackCache()); + framesContainer.addToPhaserCache(scene.game, scene.getPackCache()); } } diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/object/properties/SceneGameObjectSection.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/object/properties/SceneGameObjectSection.ts index 05bdbcede..f44282ec9 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/object/properties/SceneGameObjectSection.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/object/properties/SceneGameObjectSection.ts @@ -99,7 +99,7 @@ namespace phasereditor2d.scene.ui.sceneobjects { this.createLock(parent, prop); this.createLabel(parent, prop.label, PhaserHelp(prop.tooltip)) - .style.gridColumn = "2/ span 2"; + .style.gridColumn = "2 / span 2"; this.createFloatField(parent, prop) .style.gridColumn = fullWidth ? "4 / span 3" : "4"; diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/object/properties/SceneObjectSection.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/object/properties/SceneObjectSection.ts index ef11fe665..a225ffad4 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/object/properties/SceneObjectSection.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/object/properties/SceneObjectSection.ts @@ -105,7 +105,6 @@ namespace phasereditor2d.scene.ui.sceneobjects { text.readOnly = forceReadOnly || checkUnlock && !this.isUnlocked(property); - if (readOnlyOnMultiple) { text.readOnly = text.readOnly || readOnlyOnMultiple && this.getSelection().length > 1; @@ -389,8 +388,6 @@ namespace phasereditor2d.scene.ui.sceneobjects { this.addUpdater(() => { - console.log("update button man!"); - result.updateDialogButtonIcon(); }); diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/spine/SpinePreviewManager.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/spine/SpinePreviewManager.ts index 6911f224d..3619a0b3e 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/spine/SpinePreviewManager.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/spine/SpinePreviewManager.ts @@ -14,6 +14,8 @@ namespace phasereditor2d.scene.ui.sceneobjects { if (this._game) { + ScenePlugin.getInstance().getCanvasManager().releaseCanvas(this._game.canvas); + this._game.destroy(true); } } @@ -52,8 +54,14 @@ namespace phasereditor2d.scene.ui.sceneobjects { const { width, height } = this._parent.getBoundingClientRect(); + const canvas = ScenePlugin.getInstance().getCanvasManager().takeCanvas(); + + canvas.style.visibility = "hidden"; + this._game = new Phaser.Game({ + type: ScenePlugin.DEFAULT_EDITOR_CANVAS_CONTEXT, width, height, + canvas, parent: this._parent, transparent: true, fps: { @@ -75,7 +83,13 @@ namespace phasereditor2d.scene.ui.sceneobjects { this._game.scene.add("PreviewScene", PreviewScene, true, data); this._game.scene.add("EventScene", EventScene); - setTimeout(() => this._game.scale.refresh(), 10); + setTimeout(() => { + + canvas.style.visibility = "visible"; + + this._game.scale.refresh(); + + }, 10); } } @@ -90,6 +104,7 @@ namespace phasereditor2d.scene.ui.sceneobjects { class PreviewScene extends Phaser.Scene { private _data: IPreviewSceneData; + private _wheelListener: (e: WheelEvent) => void; init(data: IPreviewSceneData) { @@ -174,7 +189,9 @@ namespace phasereditor2d.scene.ui.sceneobjects { obj.animationState.addListener(eventScene); - this.input.on("wheel", (pointer: any, over: any, deltaX: number, deltaY: number, deltaZ: number) => { + this._wheelListener = (e: WheelEvent) => { + + const deltaY = e.deltaY; const scrollWidth = Math.abs(deltaY) * 2; @@ -185,8 +202,10 @@ namespace phasereditor2d.scene.ui.sceneobjects { const zoomFactor = (deltaY > 0 ? 1 - zoomDelta : 1 + zoomDelta); camera.zoom *= zoomFactor; - camera.zoom = Math.min(4, Math.max(0.2, camera.zoom)); - }); + camera.zoom = Math.min(100, Math.max(0.2, camera.zoom)); + }; + + this.game.canvas.addEventListener("wheel", this._wheelListener); this.game.events.on("updateAnimation", (track: number, animationName: string, loop: boolean) => { @@ -227,6 +246,13 @@ namespace phasereditor2d.scene.ui.sceneobjects { obj.animationStateData.setMix(from, to, duration); } }); + + this.game.events.once(Phaser.Core.Events.DESTROY, () => this.removeListeners()); + } + + private removeListeners() { + + this.game.canvas.removeEventListener("wheel", this._wheelListener); } } diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/AnimationPreviewDialog.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/AnimationPreviewDialog.ts new file mode 100644 index 000000000..ffc675c41 --- /dev/null +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/AnimationPreviewDialog.ts @@ -0,0 +1,75 @@ +namespace phasereditor2d.scene.ui.sceneobjects { + + import controls = colibri.ui.controls; + + export class AnimationPreviewDialog extends controls.dialogs.Dialog { + private _previewManager: AnimationPreviewManager; + private _animationAsset: pack.core.BaseAnimationsAssetPackItem; + private _config: Phaser.Types.Animations.PlayAnimationConfig; + + constructor(animationAsset: pack.core.BaseAnimationsAssetPackItem, config: Phaser.Types.Animations.PlayAnimationConfig) { + super(); + + const size = Math.min(window.innerWidth * 0.5, window.innerHeight * 0.5); + + this.setSize(size, size); + + this._animationAsset = animationAsset; + this._config = config; + } + + protected createDialogArea(): void { + + const clientArea = document.createElement("div") + + clientArea.classList.add("DialogClientArea"); + + this.getElement().appendChild(clientArea); + + this._previewManager = new AnimationPreviewManager(clientArea); + } + + createUI() { + + const finder = new pack.core.PackFinder(); + + finder.preload().then(() => { + + setTimeout(() => { + + this._previewManager.createGame({ + animationAsset: this._animationAsset, + config: this._config, + finder + }); + }, 10); + }); + } + + create(hideParentDialog?: boolean): void { + + super.create(hideParentDialog); + + this.createUI(); + + this.setTitle("Animation Preview"); + + this.addButton("Close", () => this.close()); + + this.addButton("Play", () => { + + this._previewManager.play(false); + }); + + this.addButton("Play Repeat", () => { + + this._previewManager.play(true); + }); + + this.eventDialogClose.addListener(() => { + + this._previewManager.dispose(); + }) + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/AnimationPreviewManager.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/AnimationPreviewManager.ts new file mode 100644 index 000000000..ffee35296 --- /dev/null +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/AnimationPreviewManager.ts @@ -0,0 +1,180 @@ +namespace phasereditor2d.scene.ui.sceneobjects { + + export class AnimationPreviewManager { + + private _parent: HTMLElement; + private _game: Phaser.Game; + + constructor(parent: HTMLElement) { + + this._parent = parent; + } + + dispose() { + + if (this._game) { + + ScenePlugin.getInstance().getCanvasManager().releaseCanvas(this._game.canvas); + + this._game.destroy(false); + } + } + + play(forceRepeat: boolean) { + + this._game.events.emit("play", forceRepeat); + } + + createGame(data: IAnimationPreviewSceneData) { + + const { width, height } = this._parent.getBoundingClientRect(); + + const canvas = ScenePlugin.getInstance().getCanvasManager().takeCanvas(); + + this._game = new Phaser.Game({ + width, height: height - 5, + parent: this._parent, + canvas, + type: ScenePlugin.DEFAULT_EDITOR_CANVAS_CONTEXT, + transparent: true, + pixelArt: true, + fps: { + target: 30, + }, + scale: { + mode: Phaser.Scale.ScaleModes.NONE, + resizeInterval: 10 + } + }); + + canvas.style.visibility = "hidden"; + + this._game.scene.add("PreviewScene", PreviewScene, true, data); + + setTimeout(() => { + + canvas.style.visibility = "visible"; + + this._game.scale.refresh(); + + }, 10); + } + } + + export interface IAnimationPreviewSceneData { + animationAsset: pack.core.BaseAnimationsAssetPackItem; + config: Phaser.Types.Animations.PlayAnimationConfig, + finder: pack.core.PackFinder + } + + class PreviewScene extends Phaser.Scene { + + private _data: IAnimationPreviewSceneData; + private _wheelListener: (e: WheelEvent) => void; + + init(data: IAnimationPreviewSceneData) { + + this._data = data; + } + + preload() { + + const asset = this._data.animationAsset; + + if (asset instanceof pack.core.AnimationsAssetPackItem) { + + const cache = new pack.core.parsers.AssetPackCache(); + + for (const item of this._data.finder.getAssets()) { + + item.addToPhaserCache(this.game, cache); + } + + this.load.animation(asset.getKey(), asset.getAnimationsFile().getExternalUrl()); + + } else { + + const asset2 = asset as pack.core.AsepriteAssetPackItem; + + const textureURL = asset2.getTextureFile().getExternalUrl(); + const atlasURL = asset2.getAnimationsFile().getExternalUrl(); + + this.load.aseprite(asset2.getKey(), textureURL, atlasURL); + } + } + + create() { + + this.anims.createFromAseprite(this._data.animationAsset.getKey()); + + const obj = this.add.sprite(400, 400, null); + + obj.play(this._data.config); + + obj.on("drag", (pointer: any, dragX: number, dragY: number) => { + + obj.setPosition(dragX, dragY); + }); + + const w = 100000; + + obj.setInteractive({ + draggable: true, + hitArea: new Phaser.Geom.Rectangle(-w, -w, w * 2, w * 2), + hitAreaCallback: Phaser.Geom.Rectangle.Contains + }); + + const camera = this.cameras.main; + + const gameWidth = camera.width; + const gameHeight = camera.height; + + const fx = gameWidth / obj.width; + const fy = gameHeight / obj.height; + + const z = Math.min(fx, fy); + + obj.setOrigin(0.5, 0.5); + obj.setPosition(this.game.scale.width / 2, this.game.scale.height / 2); + + camera.zoom = z; + + this._wheelListener = (e: WheelEvent) => { + + const deltaY = e.deltaY; + + const scrollWidth = Math.abs(deltaY) * 2; + + const screenWidth = camera.width; + + const zoomDelta = scrollWidth / (screenWidth + scrollWidth); + + const zoomFactor = (deltaY > 0 ? 1 - zoomDelta : 1 + zoomDelta); + + camera.zoom *= zoomFactor; + camera.zoom = Math.min(100, Math.max(0.2, camera.zoom)); + }; + + this.game.canvas.addEventListener("wheel", this._wheelListener); + + this.game.events.on("play", (forceRepeat: boolean) => { + + if (forceRepeat) { + + obj.play({ ...this._data.config, repeat: -1 }); + + } else { + + obj.play(this._data.config); + } + }); + + this.game.events.once(Phaser.Core.Events.DESTROY, () => this.removeListeners()); + } + + private removeListeners() { + + this.game.canvas.removeEventListener("wheel", this._wheelListener); + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/Sprite.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/Sprite.ts index 10a504f77..5156df3c8 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/Sprite.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/Sprite.ts @@ -1,9 +1,29 @@ namespace phasereditor2d.scene.ui.sceneobjects { + export enum AnimationPlayMethod { + NONE = 0, + PLAY = 1, + PLAY_REVERSE = 2 + } + export class Sprite extends Phaser.GameObjects.Image implements ISceneGameObject { private _editorSupport: SpriteEditorSupport; + public animationPlayMethod: AnimationPlayMethod = AnimationPlayMethod.NONE; + public animationKey = ""; + public animationCustomConfig = false; + public animationFrameRate = 24; + public animationDelay = 0; + public animationRepeat = 0; + public animationRepeatDelay = 0; + public animationYoyo = false; + public animationShowBeforeDelay = false; + public animationShowOnStart = false; + public animationHideOnComplete = false; + public animationStartFrame = 0; + public animationTimeScale = 1; + constructor( scene: Scene, x: number, y: number, texture: string, frame?: string | number) { diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/SpriteAnimationConfigSection.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/SpriteAnimationConfigSection.ts new file mode 100644 index 000000000..0a62d7e90 --- /dev/null +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/SpriteAnimationConfigSection.ts @@ -0,0 +1,55 @@ +namespace phasereditor2d.scene.ui.sceneobjects { + + import controls = colibri.ui.controls; + + export class SpriteAnimationConfigSection extends SceneGameObjectSection { + + constructor(page: controls.properties.PropertyPage) { + super(page, "phasereditor2d.scene.ui.sceneobjects.SpriteAnimationConfigSection", "Animation Configuration"); + } + + protected getSectionHelpPath() { + + return "scene-editor/animations-properties.html"; + } + + createForm(parent: HTMLDivElement) { + + const comp = this.createGridElement(parent, 3); + + this.createNumberPropertyRow(comp, SpriteComponent.animationFrameRate); + + this.createNumberPropertyRow(comp, SpriteComponent.animationDelay); + + this.createNumberPropertyRow(comp, SpriteComponent.animationRepeat); + + this.createNumberPropertyRow(comp, SpriteComponent.animationRepeatDelay); + + this.createPropertyBoolean(comp, SpriteComponent.animationYoyo) + .labelElement.style.gridColumn = "2 / span 2"; + + this.createPropertyBoolean(comp, SpriteComponent.animationShowBeforeDelay) + .labelElement.style.gridColumn = "2 / span 2"; + + this.createPropertyBoolean(comp, SpriteComponent.animationShowOnStart) + .labelElement.style.gridColumn = "2 / span 2"; + + this.createPropertyBoolean(comp, SpriteComponent.animationHideOnComplete) + .labelElement.style.gridColumn = "2 / span 2" + + this.createNumberPropertyRow(comp, SpriteComponent.animationStartFrame); + + this.createNumberPropertyRow(comp, SpriteComponent.animationTimeScale); + } + + canEdit(obj: any, n: number): boolean { + + return obj instanceof Sprite && obj.animationCustomConfig; + } + + canEditNumber(n: number): boolean { + + return n > 0; + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/SpriteAnimationSection.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/SpriteAnimationSection.ts new file mode 100644 index 000000000..05e87f579 --- /dev/null +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/SpriteAnimationSection.ts @@ -0,0 +1,178 @@ +namespace phasereditor2d.scene.ui.sceneobjects { + + import controls = colibri.ui.controls; + + export class SpriteAnimationSection extends SceneGameObjectSection { + + constructor(page: controls.properties.PropertyPage) { + super(page, "phasereditor2d.scene.ui.sceneobjects.SpriteAnimationSection", "Animation"); + } + + protected getSectionHelpPath() { + + return "scene-editor/animations-properties.html"; + } + + createMenu(menu: controls.Menu): void { + + menu.addAction({ + text: "Open Animation File", + callback: async () => { + + const sprite = this.getSelectionFirstElement(); + + const finder = new pack.core.PackFinder(); + + await finder.preload(); + + const anim = finder.findAnimationByKey(sprite.animationKey); + + if (anim) { + + ScenePlugin.getInstance().openAnimationInEditor(anim); + } + } + }); + + super.createMenu(menu); + } + + createForm(parent: HTMLDivElement) { + + const comp = this.createGridElement(parent, 4); + comp.style.gridTemplateColumns = "auto auto 1fr auto"; + + { + const btn = this.createPropertyEnumRow(comp, SpriteComponent.animationPlayMethod); + btn.style.gridColumn = "3 / span 2"; + } + + const animationToolbar = document.createElement("div"); + animationToolbar.style.display = "flex"; + animationToolbar.style.gap = "5px"; + + // play animation + + this.createPropertyStringRow(comp, SpriteComponent.animationKey); + + comp.appendChild(animationToolbar); + + this.createAnimationKeyDialogButton(comp, animationToolbar); + + this.createPreviewDialogButton(animationToolbar); + + // enable config + this.createPropertyBoolean(comp, SpriteComponent.animationCustomConfig); + } + + private createPreviewDialogButton(animationToolbar: HTMLDivElement) { + + const btn = this.createButton(animationToolbar, resources.getIcon(resources.ICON_PLAY), async () => { + + const sprite = this.getSelectionFirstElement(); + + const finder = new pack.core.PackFinder(); + + await finder.preload(); + + const anim = finder.findAnimationByKey(sprite.animationKey); + + if (anim) { + + const config: Phaser.Types.Animations.PlayAnimationConfig = { + key: anim.getKey() + }; + + if (sprite.animationCustomConfig) { + + SpriteComponent.buildPlayConfig(sprite, config); + } + + const dlg = new AnimationPreviewDialog(anim.getParent(), config); + + dlg.create(); + + } else { + + alert("Animation not found."); + } + }); + + btn.style.gridColumn = "1 / span 4"; + } + + private createAnimationKeyDialogButton(comp: HTMLDivElement, animationToolbar: HTMLDivElement) { + + const btnUI = this.createButtonDialog({ + dialogTittle: "Select Animation Key", + createDialogViewer: async (revealValue: string) => { + + const viewer = new controls.viewers.TreeViewer("phasereditor2d.scene.ui.sceneobjects.AnimationSection." + this.getId()); + + viewer.setCellRendererProvider(new controls.viewers.EmptyCellRendererProvider(e => new pack.ui.viewers.AnimationConfigCellRenderer())); + viewer.setLabelProvider(new pack.ui.viewers.AssetPackLabelProvider()); + viewer.setTreeRenderer(new controls.viewers.TreeViewerRenderer(viewer)); + viewer.setContentProvider(new controls.viewers.ArrayTreeContentProvider()); + + const finder = new pack.core.PackFinder(); + await finder.preload(); + + const animations = finder + .getAssets(i => i instanceof pack.core.BaseAnimationsAssetPackItem) + .flatMap((i: pack.core.BaseAnimationsAssetPackItem) => i.getAnimations()); + + viewer.setInput(animations); + + viewer.revealAndSelect(animations.find(a => a.getKey() === revealValue)); + + return viewer; + }, + getValue: () => { + + return this.getSelection()[0].animationKey || ""; + }, + onValueSelected: (value: string) => { + + this.getEditor().getUndoManager().add( + new SimpleOperation(this.getEditor(), this.getSelection(), SpriteComponent.animationKey, value)); + }, + dialogElementToString: (viewer: controls.viewers.TreeViewer, value: pack.core.AnimationConfigInPackItem): string => { + + return value.getKey(); + }, + updateIconCallback: async (iconControl, value) => { + + const finder = new pack.core.PackFinder(); + + await finder.preload(); + + const image = AnimationKeyPropertyType.getAnimationIcon(finder, value); + + iconControl.setIcon(image); + }, + }); + + animationToolbar.appendChild(btnUI.buttonElement); + + this.addUpdater(() => { + + btnUI.buttonElement.disabled = this.getSelection() + .filter(sprite => !sprite.getEditorSupport() + .isUnlockedProperty(SpriteComponent.animationKey)) + .length > 0; + + btnUI.updateDialogButtonIcon(); + }); + } + + canEdit(obj: any, n: number): boolean { + + return obj instanceof Sprite; + } + + canEditNumber(n: number): boolean { + + return n > 0; + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/SpriteComponent.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/SpriteComponent.ts new file mode 100644 index 000000000..2a6bf8df1 --- /dev/null +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/SpriteComponent.ts @@ -0,0 +1,110 @@ +namespace phasereditor2d.scene.ui.sceneobjects { + + export class SpriteComponent extends Component { + + static animationPlayMethod: IEnumProperty = { + name: "animationPlayMethod", + label: "Action", + defValue: AnimationPlayMethod.NONE, + getValue: obj => obj.animationPlayMethod, + setValue: (obj: Sprite, val: AnimationPlayMethod) => { obj.animationPlayMethod = val; }, + getValueLabel: val => { + switch (val) { + + case AnimationPlayMethod.NONE: + return "NONE"; + + case AnimationPlayMethod.PLAY: + return "PLAY"; + + case AnimationPlayMethod.PLAY_REVERSE: + return "PLAY_REVERSE"; + } + }, + values: [AnimationPlayMethod.NONE, AnimationPlayMethod.PLAY, AnimationPlayMethod.PLAY_REVERSE], + }; + + static animationKey = SimpleProperty({ name: "animationKey", codeName: "key" }, "", "Animation Key", "The animation key to auto-play."); + static animationCustomConfig = SimpleProperty("animationCustomConfig", false, "Custom Config", "Set a new configuration?"); + static animationFrameRate = SimpleProperty({ name: "animationFrameRate", codeName: "frameRate" }, 24, "Frame Rate", "phaser:Phaser.Types.Animations.PlayAnimationConfig.frameRate"); + static animationDelay = SimpleProperty({ name: "animationDelay", codeName: "delay" }, 0, "Delay", "phaser:Phaser.Types.Animations.PlayAnimationConfig.delay"); + static animationRepeat = SimpleProperty({ name: "animationRepeat", codeName: "repeat" }, 0, "Repeat", "phaser:Phaser.Types.Animations.PlayAnimationConfig.repeat"); + static animationRepeatDelay = SimpleProperty({ name: "animationRepeatDelay", codeName: "repeatDelay" }, 0, "Repeat Delay", "phaser:Phaser.Types.Animations.PlayAnimationConfig.repeatDelay"); + static animationYoyo = SimpleProperty({ name: "animationYoyo", codeName: "yoyo" }, false, "Yoyo", "phaser:Phaser.Types.Animations.PlayAnimationConfig.yoyo"); + static animationShowBeforeDelay = SimpleProperty({ name: "animationShowBeforeDelay", codeName: "showBeforeDelay" }, false, "Show Before Delay", "phaser:Phaser.Types.Animations.PlayAnimationConfig.showBeforeDelay"); + static animationShowOnStart = SimpleProperty({ name: "animationShowOnStart", codeName: "showOnStart" }, false, "Show Before Start", "phaser:Phaser.Types.Animations.PlayAnimationConfig.showBeforeStart"); + static animationHideOnComplete = SimpleProperty({ name: "animationHideOnComplete", codeName: "hideOnComplete" }, false, "Hide On Complete", "phaser:Phaser.Types.Animations.PlayAnimationConfig.hideOnComplete"); + static animationStartFrame = SimpleProperty({ name: "animationStartFrame", codeName: "startFrame" }, 0, "Start Frame", "phaser:Phaser.Types.Animations.PlayAnimationConfig.startFrame"); + static animationTimeScale = SimpleProperty({ name: "animationTimeScale", codeName: "timeScale" }, 1, "Time Scale", "phaser:Phaser.Types.Animations.PlayAnimationConfig.timeScale"); + + constructor(obj: Sprite) { + super(obj, [ + SpriteComponent.animationPlayMethod, + SpriteComponent.animationKey, + SpriteComponent.animationCustomConfig, + SpriteComponent.animationFrameRate, + SpriteComponent.animationDelay, + SpriteComponent.animationRepeat, + SpriteComponent.animationRepeatDelay, + SpriteComponent.animationYoyo, + SpriteComponent.animationShowBeforeDelay, + SpriteComponent.animationShowOnStart, + SpriteComponent.animationHideOnComplete, + SpriteComponent.animationStartFrame, + SpriteComponent.animationTimeScale, + ]); + } + + buildSetObjectPropertiesCodeDOM(args: ISetObjectPropertiesCodeDOMArgs): void { + + this.buildSetObjectPropertyCodeDOM([SpriteComponent.animationPlayMethod], args2 => { + + const sprite = args.obj as Sprite; + + const method = sprite.animationPlayMethod; + + if (method === AnimationPlayMethod.PLAY || method === AnimationPlayMethod.PLAY_REVERSE) { + + const name = method === AnimationPlayMethod.PLAY ? "play" : "playReverse"; + + const call = new core.code.MethodCallCodeDOM(name, args.objectVarName); + + if (sprite.animationCustomConfig) { + + const config: Phaser.Types.Animations.PlayAnimationConfig = {} as any; + + SpriteComponent.buildPlayConfig(sprite, config); + + call.arg(JSON.stringify(config)); + + } else { + + call.argLiteral(sprite.animationKey); + } + + args.statements.push(call); + } + }); + } + + public static buildPlayConfig(sprite: Sprite, config: Phaser.Types.Animations.PlayAnimationConfig) { + + for (const prop of [ + SpriteComponent.animationKey, + SpriteComponent.animationFrameRate, + SpriteComponent.animationDelay, + SpriteComponent.animationRepeat, + SpriteComponent.animationRepeatDelay, + SpriteComponent.animationYoyo, + SpriteComponent.animationShowBeforeDelay, + SpriteComponent.animationShowOnStart, + SpriteComponent.animationHideOnComplete, + SpriteComponent.animationStartFrame, + SpriteComponent.animationTimeScale + ]) { + + colibri.core.json.write(config, prop.codeName, prop.getValue(sprite), prop.defValue); + } + } + } +} \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/SpriteEditorSupport.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/SpriteEditorSupport.ts index 56311c348..b456c0219 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/SpriteEditorSupport.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/SpriteEditorSupport.ts @@ -6,6 +6,8 @@ namespace phasereditor2d.scene.ui.sceneobjects { constructor(obj: Sprite, scene: Scene) { super(SpriteExtension.getInstance(), obj, scene); + + this.addComponent(new SpriteComponent(obj)); } } } \ No newline at end of file diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/SpriteExtension.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/SpriteExtension.ts index b7c690ab5..aefb022df 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/SpriteExtension.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/sprite/SpriteExtension.ts @@ -17,12 +17,45 @@ namespace phasereditor2d.scene.ui.sceneobjects { }); } - getCodeDOMBuilder(): GameObjectCodeDOMBuilder { + override getCodeDOMBuilder(): GameObjectCodeDOMBuilder { return new BaseImageCodeDOMBuilder("sprite"); } - protected newObject(scene: Scene, x: number, y: number, key?: string, frame?: string | number): ISceneGameObject { + override acceptsDropData(data: any): boolean { + + if (data instanceof pack.core.AnimationConfigInPackItem) { + + return data.getFrames().length > 0; + } + + return super.acceptsDropData(data); + } + + override createSceneObjectWithAsset(args: ICreateWithAssetArgs): ISceneGameObject { + + const animConfig = args.asset as pack.core.AnimationConfigInPackItem; + + const frames = animConfig.getFrames(); + + const frame = frames[0]; + + const args2: ICreateWithAssetArgs = { + ...args, + asset: frame.getTextureFrame() + } + + const sprite = super.createSceneObjectWithAsset(args2) as Sprite; + + sprite.getEditorSupport().setLabel(animConfig.getKey()); + + sprite.animationPlayMethod = AnimationPlayMethod.PLAY; + sprite.animationKey = animConfig.getKey(); + + return sprite; + } + + protected override newObject(scene: Scene, x: number, y: number, key?: string, frame?: string | number): ISceneGameObject { return new Sprite(scene, x, y, key || null, frame); } diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/texture/TextureSelectionDialog.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/texture/TextureSelectionDialog.ts index db3415e6b..803c9cc10 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/texture/TextureSelectionDialog.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/texture/TextureSelectionDialog.ts @@ -8,7 +8,8 @@ namespace phasereditor2d.scene.ui.sceneobjects { pack.core.IMAGE_TYPE, pack.core.SVG_TYPE, pack.core.ATLAS_TYPE, - pack.core.SPRITESHEET_TYPE + pack.core.SPRITESHEET_TYPE, + pack.core.ASEPRITE_TYPE ]; export class TextureSelectionDialog extends controls.dialogs.ViewerDialog { @@ -73,7 +74,19 @@ namespace phasereditor2d.scene.ui.sceneobjects { viewer.setLabelProvider(new pack.ui.viewers.AssetPackLabelProvider()); viewer.setTreeRenderer(new pack.ui.viewers.AssetPackTreeViewerRenderer(viewer, false)); - viewer.setCellRendererProvider(new pack.ui.viewers.AssetPackCellRendererProvider("grid")); + + viewer.setCellRendererProvider(new class extends pack.ui.viewers.AssetPackCellRendererProvider { + + getCellRenderer(element: any): controls.viewers.ICellRenderer { + + if (element instanceof pack.core.AnimationConfigInPackItem) { + + return new pack.ui.viewers.AnimationConfigCellRenderer("square"); + } + + return super.getCellRenderer(element); + } + }("grid")); viewer.setContentProvider(new (class extends ui.blocks.SceneEditorBlocksContentProvider { @@ -81,6 +94,17 @@ namespace phasereditor2d.scene.ui.sceneobjects { return input; } + + getChildren(parent: any): any[] { + + if (parent instanceof pack.core.AsepriteAssetPackItem) { + + return parent.getFrames(); + } + + return super.getChildren(parent); + } + })(this._editor, () => this._editor.getPackFinder().getPacks())); viewer.setCellSize(64, true); diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/tilemap/TilemapLayerCodeDOMBuilder.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/tilemap/TilemapLayerCodeDOMBuilder.ts index 0318d5d3e..634fbde86 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/tilemap/TilemapLayerCodeDOMBuilder.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/tilemap/TilemapLayerCodeDOMBuilder.ts @@ -29,6 +29,7 @@ namespace phasereditor2d.scene.ui.sceneobjects { call.arg(tilesetArray); call.argInt(tilemapLayer.x); call.argInt(tilemapLayer.y); + call.setNonNullAssertion(true); return call; } diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/tilemap/TilemapLayerEditorSupport.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/tilemap/TilemapLayerEditorSupport.ts index 54c12a4fa..2c9f5634e 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/tilemap/TilemapLayerEditorSupport.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/tilemap/TilemapLayerEditorSupport.ts @@ -15,7 +15,7 @@ namespace phasereditor2d.scene.ui.sceneobjects { this.addComponent( new TransformComponent(obj as unknown as ITransformLikeObject), - new VisibleComponent(obj as unknown as IVisibleLikeObject), + new VisibleComponent(obj as unknown as IVisibleLikeObject) ); this.setLabel(obj.layer.name); diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/AbstractAssetKeyPropertyType.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/AbstractAssetKeyPropertyType.ts index 26257d98f..23b9c4c79 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/AbstractAssetKeyPropertyType.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/AbstractAssetKeyPropertyType.ts @@ -94,7 +94,7 @@ namespace phasereditor2d.scene.ui.sceneobjects { if (element instanceof pack.core.AnimationConfigInPackItem) { - return new pack.ui.viewers.AnimationConfigCellRenderer(this._finder); + return new pack.ui.viewers.AnimationConfigCellRenderer(); } return super.getCellRenderer(element); @@ -125,7 +125,7 @@ namespace phasereditor2d.scene.ui.sceneobjects { return parent.getFrames(); } - if (parent instanceof pack.core.AnimationsAssetPackItem) { + if (parent instanceof pack.core.BaseAnimationsAssetPackItem) { return parent.getAnimations(); } diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/AbstractDialogPropertyType.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/AbstractDialogPropertyType.ts index e64147273..7406a1ef7 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/AbstractDialogPropertyType.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/AbstractDialogPropertyType.ts @@ -35,7 +35,7 @@ namespace phasereditor2d.scene.ui.sceneobjects { } createInspectorPropertyEditor( - section: SceneGameObjectSection, parent: HTMLElement, userProp: UserProperty, lockIcon: boolean): void { + section: SceneGameObjectSection, parent: HTMLElement, userProp: UserProperty, lockIcon: boolean, previewAction?: () => void): void { const prop = userProp.getComponentProperty(); @@ -47,7 +47,7 @@ namespace phasereditor2d.scene.ui.sceneobjects { const label = section.createLabel(parent, prop.label, PhaserHelp(prop.tooltip)); label.style.gridColumn = "2"; - const comp = this.createEditorComp(); + const comp = this.createEditorComp(Boolean(previewAction)); parent.appendChild(comp); const text = section.createStringField(comp, prop); @@ -72,13 +72,21 @@ namespace phasereditor2d.scene.ui.sceneobjects { }); comp.appendChild(buttonElement); + + if (previewAction) { + + section.createButton(comp, resources.getIcon(resources.ICON_PLAY), () => { + + previewAction(); + }); + } } - private createEditorComp() { + private createEditorComp(withPreviewButton = false) { const comp = document.createElement("div"); comp.style.display = "grid"; - comp.style.gridTemplateColumns = "1fr auto"; + comp.style.gridTemplateColumns = withPreviewButton ? "1fr auto auto" : "1fr auto"; comp.style.gap = "5px"; comp.style.alignItems = "center"; @@ -188,14 +196,13 @@ namespace phasereditor2d.scene.ui.sceneobjects { } } - createEditorElement(getValue: () => any, setValue: (value: any) => void): IPropertyEditor { + createEditorElement(getValue: () => any, setValue: (value: any) => void, previewAction?: () => void): IPropertyEditor { + + const comp = this.createEditorComp(Boolean(previewAction)); - const comp = this.createEditorComp(); + const formBuilder = new controls.properties.FormBuilder(); - const inputElement = document.createElement("input"); - comp.appendChild(inputElement); - inputElement.type = "text"; - inputElement.classList.add("formText"); + const inputElement = formBuilder.createText(comp, false); inputElement.addEventListener("change", e => { @@ -215,6 +222,16 @@ namespace phasereditor2d.scene.ui.sceneobjects { this.updateIcon(iconControl, value); }; + if (previewAction) { + + formBuilder.createButton(comp, resources.getIcon(resources.ICON_PLAY), () => { + + console.log("here"); + + previewAction(); + }); + } + return { element: comp, update diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/AnimationKeyPropertyType.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/AnimationKeyPropertyType.ts index 12bd4d0ed..b142f976f 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/AnimationKeyPropertyType.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/AnimationKeyPropertyType.ts @@ -16,29 +16,24 @@ namespace phasereditor2d.scene.ui.sceneobjects { protected getIcon(finder: pack.core.PackFinder, value: string): controls.IImage { + return AnimationKeyPropertyType.getAnimationIcon(finder, value); + } + + static getAnimationIcon(finder: pack.core.PackFinder, value: string): controls.IImage { + const animation = finder.getPacks() .flatMap(pack => pack.getItems()) - .filter(item => item instanceof pack.core.AnimationsAssetPackItem) + .filter(item => item instanceof pack.core.BaseAnimationsAssetPackItem) - .flatMap((item: pack.core.AnimationsAssetPackItem) => item.getAnimations()) + .flatMap((item: pack.core.BaseAnimationsAssetPackItem) => item.getAnimations()) .find(anim => anim.getKey() === value); if (animation) { - const frames = animation.getFrames(); - - if (frames.length > 0) { - - const frame = frames[Math.floor(frames.length / 2)]; - - if (frame) { - - return finder.getAssetPackItemImage(frame.getTextureKey(), frame.getFrameKey()); - } - } + return animation.getPreviewImageAsset(); } return null; @@ -52,6 +47,64 @@ namespace phasereditor2d.scene.ui.sceneobjects { return viewer; } + + createInspectorPropertyEditor(section: SceneGameObjectSection, parent: HTMLElement, userProp: UserProperty, lockIcon: boolean): void { + + super.createInspectorPropertyEditor(section, parent, userProp, lockIcon, async () => { + + const finder = new pack.core.PackFinder(); + + await finder.preload(); + + const values = section.getSelection() + .map(o => userProp.getComponentProperty().getValue(o)); + + const key = section.flatValues_StringOneOrNothing( + values); + + const anim = finder.findAnimationByKey(key); + + if (anim) { + + const dlg = new AnimationPreviewDialog(anim.getParent(), { + key + }); + + dlg.create(); + + } else { + + alert("Animation key not found."); + } + }); + } + + createEditorElement(getValue: () => any, setValue: (value: any) => void): IPropertyEditor { + + return super.createEditorElement(getValue, setValue, async () => { + + const finder = new pack.core.PackFinder(); + + await finder.preload(); + + const key = getValue() as string; + + const anim = finder.findAnimationByKey(key); + + if (anim) { + + const dlg = new AnimationPreviewDialog(anim.getParent(), { + key + }); + + dlg.create(); + + } else { + + alert("Animation key not found."); + } + }); + } } class AnimationKeyContentProvider implements controls.viewers.ITreeContentProvider { @@ -64,9 +117,9 @@ namespace phasereditor2d.scene.ui.sceneobjects { .flatMap(pack => pack.getItems()) - .filter(item => item instanceof pack.core.AnimationsAssetPackItem) + .filter(item => item instanceof pack.core.BaseAnimationsAssetPackItem) - .flatMap((item: pack.core.AnimationsAssetPackItem) => item.getAnimations()); + .flatMap((item: pack.core.BaseAnimationsAssetPackItem) => item.getAnimations()); } getChildren(parent: any): any[] { diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/EventPropertyType.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/EventPropertyType.ts index 36c9debec..9a16002f3 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/EventPropertyType.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/EventPropertyType.ts @@ -64,11 +64,8 @@ namespace phasereditor2d.scene.ui.sceneobjects { protected async createViewer() { - const finder = new pack.core.PackFinder(); - await finder.preload(); - const viewer = new controls.viewers.TreeViewer("phasereditor2d.scene.editor.EventPropertyType.Dialog"); - viewer.setCellRendererProvider(new EventCellRendererProvider(finder)); + viewer.setCellRendererProvider(new EventCellRendererProvider()); viewer.setLabelProvider(new EventLabelProvider()); viewer.setStyledLabelProvider(new EventPropertyStyleLabelProvider()); viewer.setContentProvider(new controls.viewers.ArrayTreeContentProvider()); @@ -103,8 +100,8 @@ namespace phasereditor2d.scene.ui.sceneobjects { await packFinder.preload(); const animEvents = packFinder - .getAssets(i => i instanceof pack.core.AnimationsAssetPackItem) - .map(i => i as pack.core.AnimationsAssetPackItem) + .getAssets(i => i instanceof pack.core.BaseAnimationsAssetPackItem) + .map(i => i as pack.core.BaseAnimationsAssetPackItem) .flatMap(i => i.getAnimations()) .map(anim => new AnimationEventItem(`animationcomplete-${anim.getKey()}`, anim)); @@ -257,7 +254,7 @@ namespace phasereditor2d.scene.ui.sceneobjects { class EventCellRendererProvider implements controls.viewers.ICellRendererProvider { - constructor(private _finder: pack.core.PackFinder) { + constructor() { } @@ -265,7 +262,7 @@ namespace phasereditor2d.scene.ui.sceneobjects { if (element instanceof AnimationEventItem) { - return new AnimationEventCellRenderer(this._finder); + return new AnimationEventCellRenderer(); } else if (element instanceof SkeletonEventItem) { diff --git a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/TextureConfigPropertyType.ts b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/TextureConfigPropertyType.ts index 613aee117..fb5e3fa8c 100644 --- a/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/TextureConfigPropertyType.ts +++ b/source/editor/plugins/phasereditor2d.scene/src/ui/sceneobjects/userProperties/TextureConfigPropertyType.ts @@ -92,7 +92,7 @@ namespace phasereditor2d.scene.ui.sceneobjects { const finder = new pack.core.PackFinder(); await finder.preload(); - + const viewer = await super.createViewer(); viewer.setContentProvider(new TextureContentProvider(finder)); viewer.setTreeRenderer(new pack.ui.viewers.AssetPackTreeViewerRenderer(viewer, false)); @@ -114,6 +114,7 @@ namespace phasereditor2d.scene.ui.sceneobjects { pack.core.IMAGE_TYPE, pack.core.SVG_TYPE, pack.core.ATLAS_TYPE, + pack.core.ASEPRITE_TYPE, pack.core.SPRITESHEET_TYPE]; } @@ -132,7 +133,8 @@ namespace phasereditor2d.scene.ui.sceneobjects { return this.getItems(parent); } - if (parent instanceof pack.core.ImageFrameContainerAssetPackItem) { + if (parent instanceof pack.core.ImageFrameContainerAssetPackItem + || parent instanceof pack.core.AsepriteAssetPackItem) { if (!(parent instanceof pack.core.ImageAssetPackItem)) { diff --git a/source/editor/product.json b/source/editor/product.json index f92235f0f..ef6973ed9 100644 --- a/source/editor/product.json +++ b/source/editor/product.json @@ -1,4 +1,4 @@ { "title": "Phaser Editor 2D", - "version": "3.63.0" + "version": "3.64.0" } \ No newline at end of file