Files
kiss-vscode/projects/nat-flixel-desktop-playground/source/PlayState.kiss

219 lines
8.3 KiB
Plaintext

(loadFrom "nat-archive-tool" "src/nat/Lib.kiss")
(var TEXT_SIZE 16)
(prop &mut :EntrySpriteSystem spriteSystem)
(method :PlaygroundSystem playgroundSystem []
(set spriteSystem (new EntrySpriteSystem this controller)))
(prop :KeyShortcutHandler<Entry> shortcutHandler (new FlxKeyShortcutHandler<Entry>))
(method &override :Void create []
(super.create)
(FlxG.plugins.add (new FlxMouseControl))
(set FlxG.sound.muteKeys null)
(set FlxG.sound.volumeDownKeys null)
(set FlxG.sound.volumeUpKeys null)
// TODO find a better way to pass the archiveDir to a HaxeFlixel game
(let [archiveDir
(or (Sys.getEnv "NAT_DIR") (throw "NAT_DIR environment variable must be set"))
archive
(new Archive archiveDir)]
(set this.archive archive)
(set controller
(new ArchiveController
archive
this)))
(prop screenCamera (new FlxCamera 0 0 FlxG.width FlxG.height))
(prop &mut :SimpleWindow uiWindow (new SimpleWindow 0.8 0.8 true "escape"))
(set uiWindow.cameras [screenCamera])
(set uiWindow.keyboardEnabled false)
(prop :FlxTypedGroup<EntrySprite> entryGroup (new FlxTypedGroup<EntrySprite>))
(add entryGroup)
(prop debugLayer (new DebugLayer))
(set debugLayer.cameras [FlxG.camera])
(add debugLayer)
(FlxG.camera.calculateScrollBounds entryGroup SCROLL_BOUND_MARGIN))
(method :Void showPrefixMap [:Map<String,String> map]
(clearUI)
(doFor =>key thing map
(displayMessage "$key - $thing")))
(method :Void hidePrefixMap []
(clearUI))
(prop &mut :Bool confirmQuit false)
(defAlias &ident sh (cast shortcutHandler FlxKeyShortcutHandler<Dynamic>))
(method &override :Void update [:Float elapsed]
(super.update elapsed)
(when sh.currentMap
(sh.update))
(when (and FlxG.keys.justPressed.V FlxG.keys.pressed.CONTROL)
(when (and textInput textInput.hasFocus)
(whenLet [text (Clipboard.generalClipboard.getData ClipboardFormats.TEXT_FORMAT)]
(when (textInput.text.endsWith "v")
(set textInput.text (substr textInput.text 0 -1)))
(+= textInput.text text)
(set textInput.caretIndex textInput.text.length))))
(when FlxG.keys.justPressed.ESCAPE
(when sh.currentMap
(sh.cancel)))
(when FlxG.keys.justPressed.DELETE
(Sys.exit 0))
// Press ENTER to type a command to run
(when (and !textInput FlxG.keys.justPressed.ENTER)
(set confirmQuit false)
(typeCommand))
(when (and textInput !textInput.alive)
(set textInput null))
// Control the UI camera with WASD, and the playground camera with arrow keys:
(var KEYBOARD_SCROLL_SPEED 800)
(FlxG.camera.updateKeyControl
elapsed
KEYBOARD_SCROLL_SPEED
->{FlxG.keys.pressed.LEFT}
->{FlxG.keys.pressed.RIGHT}
->{FlxG.keys.pressed.UP}
->{FlxG.keys.pressed.DOWN})
(FlxG.camera.updateMouseBorderControl elapsed KEYBOARD_SCROLL_SPEED 0.01 screenCamera)
(FlxG.camera.updateScrollWheelZoom elapsed 1)
// Don't check keys that can be used in shortcuts outside this block:
(unless (or sh.currentMap (and textInput textInput.hasFocus))
(when FlxG.keys.justPressed.SEMICOLON
(set confirmQuit false)
(sh.start)
(return))
// +/- keys to change an entry's z
(doFor e (controller.getSelectedEntries)
(when FlxG.keys.justPressed.MINUS
(withWritableComponents archive e [positions Positions]
(-= .z (dictGet positions (spriteSystem.getPlaygroundKey)) 1)))
(when FlxG.keys.justPressed.PLUS
(withWritableComponents archive e [positions Positions]
(+= .z (dictGet positions (spriteSystem.getPlaygroundKey)) 1))))))
(method :Void typeCommand []
(enterText
"command to run:"
->commandName (controller.tryRunCommand commandName)
Math.POSITIVE_INFINITY))
(prop &mut :ArchiveController controller)
(prop &mut :Archive archive)
(prop &mut :FlxText textInputLabel null)
(prop &mut :FlxInputText textInput null)
(method :Void enterText [prompt resolve maxLength]
(displayMessage prompt)
(set textInput (new FlxInputText 0 0 FlxG.width "" TEXT_SIZE))
(set textInput.hasFocus true)
(set textInput.callback
->:Void [text action]
// Super weird that this check is necessary
(when textInput
(case [text action]
([text FlxInputText.ENTER_ACTION]
(clearUI)
(set textInput.callback null)
(set textInput null)
(resolve text))
//([_ FlxInputText.])
(otherwise {}))))
(uiWindow.addControl textInput))
(method :Void enterNumber [prompt resolve min max &opt inStepsOf]
(enterText prompt
->:Void [numberStr]
(let [number
(try (Std.parseFloat numberStr)
(catch [e]
(reportError "Not a number: $numberStr")
(return)))]
(resolve number))
Math.POSITIVE_INFINITY))
(method :Void chooseEntry [prompt :Archive archive resolve]
(entryGroup.forEach ->s
(set s.mousePressedCallback ->:Void [s _ _] {
(entryGroup.forEach ->s
(set s.mousePressedCallback ->:Void [_ _ _] null))
(resolve .e (cast s EntrySprite))
})))
(method :Void chooseEntries [prompt archive resolve min max]
(_chooseEntries prompt archive resolve min max []))
// TODO is it possible to resolve with less than max?
// TODO this version that just delegates to (chooseEntry) should be reusable, which is tricky because ArchiveUI is an interface
// It also needs a way to resolve with less than the maximum, which may be infinity
(method :Void _chooseEntries [prompt archive resolve min max :Array<Entry> collectedEntries]
(let [&mut :Void->Void chooseNextEntry
null
_chooseNextEntry
->:Void {(chooseEntry
prompt
archive
->:Void e {(collectedEntries.push e)
// If the maximum is reached, return it
(if (= (#if debug 1 max) collectedEntries.length)
(resolve collectedEntries)
// Otherwise, recurse
(chooseNextEntry))})}]
(set chooseNextEntry _chooseNextEntry)
(_chooseNextEntry)))
(var SCROLL_BOUND_MARGIN 2000)
(method handleChanges [:Archive archive :ChangeSet changeSet]
(doFor e changeSet
// Entries whose data changed to remove them from the sprite pool will already have been removed
// by refreshEntry()
(when (spriteSystem.entries.exists e.id)
// refresh the sprites for entries that changed data but still should have sprites
(when (spriteSystem.sprites.exists e.id)
(spriteSystem.onRemoveEntry archive e))
(spriteSystem.processEntry archive e)))
(FlxG.camera.calculateScrollBounds entryGroup SCROLL_BOUND_MARGIN))
(method :Void displayMessage [:String message]
(print message)
(uiWindow.makeText message)
(uiWindow.show))
(method :Void clearUI []
(uiWindow.clearControls)
(uiWindow.hide))
(method :Void reportError [:String error]
(print error)
(uiWindow.makeText error FlxColor.RED)
(uiWindow.show))
(method :Void onSelectionChanged [:Array<Entry> selectedEntries :Array<Entry> lastSelectedEntries]
(doFor e (selectedEntries.concat lastSelectedEntries)
(whenLet [sprite (dictGet spriteSystem.sprites e.id)]
(sprite.updateColor))))
(method :Option<Position> cursorPosition []
(let [pos (FlxG.mouse.getWorldPosition FlxG.camera)]
(Some (object x pos.x y pos.y z 0.0))))