diff --git a/projects/nat-archive-tool/src/nat/ArchiveController.kiss b/projects/nat-archive-tool/src/nat/ArchiveController.kiss index 2a4c11fc..e7e945a8 100644 --- a/projects/nat-archive-tool/src/nat/ArchiveController.kiss +++ b/projects/nat-archive-tool/src/nat/ArchiveController.kiss @@ -162,6 +162,10 @@ (archive.addSystem (new ImageAttachmentSystem)) (archive.addSystem (new KeyShortcutSystem this)) (archive.addSystem (new DLSystem)) + (whenLet [ps (ui.playgroundSystem)] + (archive.addSystem ps) + // TODO allow saving a different default playground + (ps.switchPlaygroundKey "Playground-MAIN")) // Just for testing: // (archive.addSystem (new AttachmentSystem ["jpg" "jpeg" "png"] ->[archive e files] ~files)) diff --git a/projects/nat-archive-tool/src/nat/ArchiveUI.hx b/projects/nat-archive-tool/src/nat/ArchiveUI.hx index 884aab9f..84f457f6 100644 --- a/projects/nat-archive-tool/src/nat/ArchiveUI.hx +++ b/projects/nat-archive-tool/src/nat/ArchiveUI.hx @@ -3,6 +3,7 @@ package nat; import nat.Entry; import nat.ArchiveController; import kiss_tools.KeyShortcutHandler; +import nat.systems.PlaygroundSystem; interface ArchiveUI { /** @@ -15,6 +16,11 @@ interface ArchiveUI { */ var shortcutHandler(default, null):Null>; + /** + * A PlaygroundSystem that will display interactible entry representations + */ + function playgroundSystem():Null; + /** * Prompt the user to enter text */ diff --git a/projects/nat-archive-tool/src/nat/components/Position.hx b/projects/nat-archive-tool/src/nat/components/Position.hx new file mode 100644 index 00000000..63c85e6e --- /dev/null +++ b/projects/nat-archive-tool/src/nat/components/Position.hx @@ -0,0 +1,3 @@ +package nat.components; + +typedef Position = {x:Float, y:Float, z:Float}; \ No newline at end of file diff --git a/projects/nat-archive-tool/src/nat/components/Positions.hx b/projects/nat-archive-tool/src/nat/components/Positions.hx index 1984a96b..2f6e671c 100644 --- a/projects/nat-archive-tool/src/nat/components/Positions.hx +++ b/projects/nat-archive-tool/src/nat/components/Positions.hx @@ -1,6 +1,7 @@ package nat.components; + /** * Entries can have multiple positions in different UIs/folders/whatever. */ -typedef Positions = Map; +typedef Positions = Map; diff --git a/projects/nat-archive-tool/src/nat/systems/PlaygroundSystem.hx b/projects/nat-archive-tool/src/nat/systems/PlaygroundSystem.hx new file mode 100644 index 00000000..2def8309 --- /dev/null +++ b/projects/nat-archive-tool/src/nat/systems/PlaygroundSystem.hx @@ -0,0 +1,15 @@ +package nat.systems; + +import kiss.Prelude; +import kiss.List; +import nat.System; +import nat.components.Position; + +typedef PlaygroundEntryProcessor = (Archive, Entry, Position, ?ArchiveUI) -> Dynamic; // Whatever value is returned will be dropped, but this is easier than requiring ->:Void + +/** + * Base class for Systems that process Entries in a playground view and displays them in an interactive form + * (EntrySpriteSystem, for example) + */ +@:build(kiss.Kiss.build()) +class PlaygroundSystem extends System {} diff --git a/projects/nat-archive-tool/src/nat/systems/PlaygroundSystem.kiss b/projects/nat-archive-tool/src/nat/systems/PlaygroundSystem.kiss new file mode 100644 index 00000000..ccf7f4f4 --- /dev/null +++ b/projects/nat-archive-tool/src/nat/systems/PlaygroundSystem.kiss @@ -0,0 +1,37 @@ +(load "../Lib.kiss") + +(prop &mut :String _playgroundKey "") +(method :String getPlaygroundKey [] _playgroundKey) + +(defNew [&prop :ArchiveUI ui + :EntryChecker canProcess + &prop :PlaygroundEntryProcessor processor] + + (super + ->[archive e] + (and (tagsMatch e "!(or done hidden)") (canProcess archive e)) + ->[archive e &opt ui] + { + (when !(hasComponent e Positions) + (addComponent archive e Positions (new Map))) + (withWritableComponents archive e [positions Positions] + (when !(positions.exists _playgroundKey) + // TODO do a playground check before giving a default position. + (dictSet positions _playgroundKey (defaultPosition e)))) + (let [pos (dictGet (readComponent e Positions) _playgroundKey)] + (processor archive e pos ui)) + })) + +(method switchPlaygroundKey [key] + (when _playgroundKey + (clear)) + (set _playgroundKey key) + (process ui.controller.archive ui)) + +(method clear []) + +(method &override :Void process [:Archive archive &opt :ArchiveUI ui] + (when _playgroundKey (super.process archive ui))) + +(method defaultPosition [:Entry e] + (object x 0.0 y 0.0 z 0.0)) \ No newline at end of file diff --git a/projects/nat-flixel-desktop-playground/source/EntrySprite.hx b/projects/nat-flixel-desktop-playground/source/EntrySprite.hx index e68a2d1a..50439030 100644 --- a/projects/nat-flixel-desktop-playground/source/EntrySprite.hx +++ b/projects/nat-flixel-desktop-playground/source/EntrySprite.hx @@ -9,7 +9,7 @@ import nat.Archive; import nat.ArchiveController; import nat.BoolExpInterp; import nat.components.Images; -import nat.components.Positions; +import nat.components.Position; import nat.components.Scale; using kiss_flixel.CameraTools; diff --git a/projects/nat-flixel-desktop-playground/source/EntrySprite.kiss b/projects/nat-flixel-desktop-playground/source/EntrySprite.kiss index 7bbc10de..76cd5281 100644 --- a/projects/nat-flixel-desktop-playground/source/EntrySprite.kiss +++ b/projects/nat-flixel-desktop-playground/source/EntrySprite.kiss @@ -2,14 +2,14 @@ (defNew [&prop :EntrySpriteSystem system &prop :String positionKey + &prop :Position position &prop :Archive archive &prop :Entry e &prop :ArchiveController controller] [&mut :Bool selected false] (let [images (readComponent e Images)] - (whenLet [(objectWith x y z) (dictGet (readComponent e Positions) positionKey)] - (super x y)) + (super position.x position.y) (.onComplete (BitmapData.loadFromFile (joinPath archive.archiveDir "files" (nth images.imageFiles images.pinnedImageIndex))) ->bitmapData { (loadGraphic bitmapData) diff --git a/projects/nat-flixel-desktop-playground/source/EntrySpriteDepthSystem.kiss b/projects/nat-flixel-desktop-playground/source/EntrySpriteDepthSystem.kiss index d7084cfe..c87bac31 100644 --- a/projects/nat-flixel-desktop-playground/source/EntrySpriteDepthSystem.kiss +++ b/projects/nat-flixel-desktop-playground/source/EntrySpriteDepthSystem.kiss @@ -1,7 +1,7 @@ (loadFrom "nat-archive-tool" "src/nat/Lib.kiss") (method z [:Entry e] - .z (dictGet (readComponent e Positions) spriteSystem.positionKey)) + .z (dictGet (readComponent e Positions) (spriteSystem.getPlaygroundKey))) (method :Array collectOverlapping [:EntrySprite s &opt :Array overlapping] (unless overlapping (set overlapping [])) @@ -21,7 +21,7 @@ !(= 0 (z e))) ->[archive e &opt ui] (let [:Array inOrder - ~(sortBy + (sortBy (collectOverlapping (dictGet spriteSystem.sprites e.id)) ->s (- (z s.e)))] // Looping twice avoids having to splice() the group diff --git a/projects/nat-flixel-desktop-playground/source/EntrySpriteSystem.hx b/projects/nat-flixel-desktop-playground/source/EntrySpriteSystem.hx index adebab9f..666b41fb 100644 --- a/projects/nat-flixel-desktop-playground/source/EntrySpriteSystem.hx +++ b/projects/nat-flixel-desktop-playground/source/EntrySpriteSystem.hx @@ -5,7 +5,9 @@ import kiss.List; import nat.System; import nat.BoolExpInterp; import nat.ArchiveController; +import nat.ArchiveUI; import nat.components.Positions; +import nat.systems.PlaygroundSystem; @:build(kiss.Kiss.build()) -class EntrySpriteSystem extends System {} +class EntrySpriteSystem extends PlaygroundSystem {} diff --git a/projects/nat-flixel-desktop-playground/source/EntrySpriteSystem.kiss b/projects/nat-flixel-desktop-playground/source/EntrySpriteSystem.kiss index ae5ee84c..74924e26 100644 --- a/projects/nat-flixel-desktop-playground/source/EntrySpriteSystem.kiss +++ b/projects/nat-flixel-desktop-playground/source/EntrySpriteSystem.kiss @@ -2,21 +2,19 @@ (prop :Map sprites (new Map)) -(defNew [:String tagFilterString - &prop :String positionKey - :PlayState playState +// TODO this can also handle text sprites, and instead of saving out the text bitmap, +// just make the FlxText every time at runtime -- so PinNextImage won't be needed +// when the media tag is added + +(defNew [:PlayState playState &prop :ArchiveController controller] (super + playState ->[archive e] - ?(and (tagsMatch e tagFilterString) (hasComponent e Images)) - ->[archive e &opt ui] + ?(hasComponent e Images) + ->[archive e pos &opt ui] (unless (sprites.exists e.id) - (when !(hasComponent e Positions) - (addComponent archive e Positions (new Map))) - (withWritableComponents archive e [positions Positions] - (when !(positions.exists positionKey) - (dictSet positions positionKey (object x 0.0 y 0.0 z 0.0)))) - (let [sprite (new EntrySprite this positionKey archive e controller)] + (let [sprite (new EntrySprite this _playgroundKey pos archive e controller)] (playState.entryGroup.add sprite) (dictSet sprites e.id sprite)))) @@ -29,5 +27,7 @@ (controller.DeSelectEntry e) })) +// TODO override process to z-sort all sprites after making them + (method getSelectedSprites [] (filter (for e (controller.getSelectedEntries) (dictGet sprites e.id)))) \ No newline at end of file diff --git a/projects/nat-flixel-desktop-playground/source/PlayState.hx b/projects/nat-flixel-desktop-playground/source/PlayState.hx index 43986b76..0ac30b09 100644 --- a/projects/nat-flixel-desktop-playground/source/PlayState.hx +++ b/projects/nat-flixel-desktop-playground/source/PlayState.hx @@ -21,6 +21,7 @@ using StringTools; using kiss_flixel.CameraTools; import kiss_tools.KeyShortcutHandler; import kiss_tools.FlxKeyShortcutHandler; +import nat.systems.PlaygroundSystem; @:build(kiss.Kiss.build()) class PlayState extends FlxState implements ArchiveUI {} diff --git a/projects/nat-flixel-desktop-playground/source/PlayState.kiss b/projects/nat-flixel-desktop-playground/source/PlayState.kiss index b3b83cba..2aba17c0 100644 --- a/projects/nat-flixel-desktop-playground/source/PlayState.kiss +++ b/projects/nat-flixel-desktop-playground/source/PlayState.kiss @@ -2,6 +2,13 @@ // TODO handleChanges() will need to kill every changed Entry's sprite and make a new one +// make interactible sprites for entries that have images + +(prop &mut :EntrySpriteSystem spriteSystem) + +(method :PlaygroundSystem playgroundSystem [] + (set spriteSystem (new EntrySpriteSystem this controller))) + (method &override :Void create [] (super.create) @@ -91,14 +98,6 @@ // make text-only sprites for entries that have no images: (archive.addSystem (new TextSpriteSystem)) - // make interactible sprites for entries that have images - - // TODO allow configuring the tags at runtime and erasing/re-creating sprites later - // TODO allow using other position keys and erasing/re-creating sprites later - (prop &mut :EntrySpriteSystem spriteSystem) - (set spriteSystem (new EntrySpriteSystem "!done" "Playground-MAIN" this controller)) - (archive.addSystem spriteSystem) - (prop &mut :EntrySpriteDepthSystem spriteDepthSystem) (set spriteDepthSystem (new EntrySpriteDepthSystem this spriteSystem)) (archive.addSystem spriteDepthSystem) @@ -148,7 +147,7 @@ (FlxG.camera.updateScrollWheelZoom elapsed 1) // Don't check keys that can be used in shortcuts outside this block: - (unless sh.currentMap + (unless (or sh.currentMap (and textInput textInput.hasFocus)) (when FlxG.keys.justPressed.SEMICOLON (sh.start) (return)) @@ -156,10 +155,10 @@ (doFor e (controller.getSelectedEntries) (when FlxG.keys.justPressed.MINUS (withWritableComponents archive e [positions Positions] - (-= .z (dictGet positions spriteSystem.positionKey) 1))) + (-= .z (dictGet positions (spriteSystem.getPlaygroundKey)) 1))) (when FlxG.keys.justPressed.PLUS (withWritableComponents archive e [positions Positions] - (+= .z (dictGet positions spriteSystem.positionKey) 1)))) + (+= .z (dictGet positions (spriteSystem.getPlaygroundKey)) 1)))) // don't move the ui camera before ui has been placed -- new UI elements could appear offscreen (when (> uiGroup.length 0)