From 7ad5c2d641f5049d3f3ed738bbe39cb91de6928d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Reuh=20Fildadut?= Date: Fri, 16 Sep 2022 20:07:53 +0900 Subject: [PATCH] Update and rebuild docs --- LICENSE | 2 +- docs/index.html | 9 +- docs/modules/asset.html | 5 +- docs/modules/ecs.html | 58 +- docs/modules/input.html | 706 ++++++++++++++++++++++ docs/modules/ldtk.html | 300 ++++++++- docs/modules/scene.html | 3 +- docs/modules/signal.html | 514 +++++++++++++--- docs/modules/timer.html | 3 +- docs/modules/ubiquitousse.html | 34 +- docs/modules/util.html | 3 +- docs/topics/LICENSE.html | 5 +- docs/topics/README.md.html | 22 +- ecs/ecs.lua | 425 +++++++------ gltf/draw.lua | 84 +++ gltf/gltf.lua | 15 + gltf/loader.lua | 389 ++++++++++++ ldtk/ldtk.lua | 1039 +++++++++++++++++--------------- signal/signal.lua | 359 ++++++----- 19 files changed, 3026 insertions(+), 949 deletions(-) create mode 100644 docs/modules/input.html create mode 100644 gltf/draw.lua create mode 100644 gltf/gltf.lua create mode 100644 gltf/loader.lua diff --git a/LICENSE b/LICENSE index f616df4..730dea1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2021 Étienne "Reuh" Fildadut +Copyright 2016-2022 Étienne "Reuh" Fildadut Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. diff --git a/docs/index.html b/docs/index.html index 294be24..cfac48e 100644 --- a/docs/index.html +++ b/docs/index.html @@ -35,6 +35,7 @@
  • ubiquitousse
  • asset
  • ecs
  • +
  • input
  • ldtk
  • scene
  • signal
  • @@ -71,6 +72,10 @@ ecs ECS (entity compenent system) library for Lua. + + input + Input management facilities. + ldtk LDtk level importer for Lua and drawing using LÖVE. @@ -81,7 +86,7 @@ signal - Signal management for Lua. + Simple signal / observer pattern implementation for Lua. timer @@ -108,7 +113,7 @@
    generated by LDoc 1.4.6 -Last updated 2021-12-27 17:22:39 +Last updated 2022-09-16 20:07:07
    diff --git a/docs/modules/asset.html b/docs/modules/asset.html index 44225ae..cac1531 100644 --- a/docs/modules/asset.html +++ b/docs/modules/asset.html @@ -43,6 +43,7 @@
  • ubiquitousse
  • asset
  • ecs
  • +
  • input
  • ldtk
  • scene
  • signal
  • @@ -67,6 +68,8 @@

    See the Asset:__call method for more details on how assets are loaded. Hopefully this will allow you to use asset which are more game-specific than “image” or “audio”.

    +

    TODO: async loading

    +

    No dependencies.

    Usage:

    + + + + +

    Parameters:

    + + +

    Returns:

    +
      + + Entity + the entity; nil if there is no such entity in the system +
    + + + +
    @@ -1683,7 +1729,7 @@ its sibling systems (i.e. completely stop the propagation of the event).
    generated by LDoc 1.4.6 -Last updated 2021-12-27 17:22:39 +Last updated 2022-09-16 20:07:07
    diff --git a/docs/modules/input.html b/docs/modules/input.html new file mode 100644 index 0000000..5256c33 --- /dev/null +++ b/docs/modules/input.html @@ -0,0 +1,706 @@ + + + + + Ubiquitousse reference + + + + +
    + +
    + +
    +
    +
    + + +
    + + + + + + +
    + +

    Module input

    +

    Input management facilities.

    +

    The module returns a single function, input.

    + +

    Requires ubiquitousse.signal.

    +

    Usage:

    +
      +
      TODO
      +
      +
    + + +

    Functions

    + + + + + +
    input ()Make a new input object.
    +

    Input objects

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Input.configInput configuration table.
    Input.childrenList and map of children inputs.
    Input.nameName of the input.
    Input.grabbedFalse if the input is currently not grabbed, a subinput otherwise.
    Input.grabbingFalse if the input is not a subinput, the input it grabbed otherwise.
    Input.eventInput event registry.
    Input:update ()Update the input and its children.
    Input:clone ()Create a new input object based on this input config data.
    Input:reload ()Relond the input config, and do the same for its children.
    Input:disable ()Disable the input and its children, preventing further updates and events.
    Input:onNextActiveSource (fn[, filter])Will call fn(source) on the next activated source (including sources not currently used by this input).
    Input:grab ()Grab the input and its children input and returns the new subinput.
    Input:release ()Release a subinput and its children.
    Input:neutralize ()Set the state of this input to a neutral position (i.e.
    Input:setJoystick (joystick)Set the joystick associated with this input.
    Input:getJoystick ()Returns the currently selected joystick.
    Input:down ()Returns true if the input is currently down.
    Input:pressed ()Returns true if the input has just been pressed.
    Input:released ()Returns true if the input has just been released.
    Input:value ()Returns the current value of the input.
    Input:delta ()Returns the delta value of the input since the last call to update.
    Input:pointer ()If there is a horizontal and vertical children inputs, this returns the horizontal value and the vertical value.
    Input:clamped ()Same as pointer, but normalize the returned vector, i.e.
    + +
    +
    + + +

    Functions

    + +
    +
    + + input () +
    +
    + Make a new input object. + t: input configuration table (optional) + + + + + + + + + + + +
    +
    +

    Input objects

    + +
    + Input methods. +
    +
    +
    + + Input.config +
    +
    + Input configuration table. + It can be used to recreate this input object later (by passing the table as an argument for the input constructor). + This table does not contain any userdata and should be easily serializable (e.g. to save custom input binding config). + This doesn’t include input state, grab state, the event registry and the selected joystick since they may change often during runtime. + Can be changed anytime, but you may need to call reload to apply changes. + + + + + + + + + + +

    Usage:

    +
      +
      player.config = {
      +  "key.a", "key.d - key.a", {"key.left + x", x=0.5}, -- list of input sources expressions
      +  jump = {...}, -- children input
      +  deadzone = 0.05, -- The deadzone for analog inputs (e.g. joystick axes): if the input absolute value is strictly below this, it will be considered as 0.
      +  threshold = 0.05 -- The pressed threshold: an input is considered down if above or equal to this value.
      +}
      +
    + +
    +
    + + Input.children +
    +
    + List and map of children inputs. + {[child1.name]=child1, [child2.name]=child2, child1, child2…} + + + + + + + + + + + +
    +
    + + Input.name +
    +
    + Name of the input. + Defined on children inputs only. + + + + + + + + + + + +
    +
    + + Input.grabbed +
    +
    + False if the input is currently not grabbed, a subinput otherwise. + This may be different between each subinput. + + + + + + + + + + + +
    +
    + + Input.grabbing +
    +
    + False if the input is not a subinput, the input it grabbed otherwise. + This may be different between each subinput. + + + + + + + + + + + +
    +
    + + Input.event +
    +
    + Input event registry. + The following events are available:

    + +
      +
    • "moved": called when the input value change, with arguments (new value, delta since last event)
    • +
    • "pressed": called when the input is pressed
    • +
    • "released": called when the input is released
    • +
    + + +

    For pointer inputs (have a “horizontal” and “vertical” children inputs) is also avaible:

    + +
      +
    • "pointer moved": called when the pointer position change, with arguments (new pointer x, new pointer y, delta x since last event, delta y since last event)
    • +
    + + +

    Each subinput has a different event registry. + + + + + + + + + + + +

    +
    + + Input:update () +
    +
    + Update the input and its children. + Should be called every frame, typically after you've done all your input handling + (otherwise pressed and released may never return true and delta might be wrong). + (Note: this should not be called on subinputs) + + + + + + + + + + + +
    +
    + + Input:clone () +
    +
    + Create a new input object based on this input config data. + + + + + + + + + + + +
    +
    + + Input:reload () +
    +
    + Relond the input config, and do the same for its children. + This will reenable the input if it was disabled using disable. + + + + + + + + + + + +
    +
    + + Input:disable () +
    +
    + Disable the input and its children, preventing further updates and events. + The input can be reenabled using reload. + + + + + + + + + + + +
    +
    + + Input:onNextActiveSource (fn[, filter]) +
    +
    + Will call fn(source) on the next activated source (including sources not currently used by this input). + Typically used to detect an input in your game input binding settings. + + + + + + +

    Parameters:

    +
      +
    • fn + function that will be called on the next activated source matching the filter +
    • +
    • filter + list of string patterns that sources must start with (example {"button", "key"} to only get buttons and key sources) + (optional) +
    • +
    + + + + + +
    +
    + + Input:grab () +
    +
    + Grab the input and its children input and returns the new subinput.

    + +

    A grabbed input will no longer update and instead pass all new update to the subinput. + This is typically used for contextual action or pause menus: by grabbing the player input, all the direct use of + this input in the game will stop (can’t move caracter, …) and instead you can use the subinput to handle input in the pause menu. + To stop grabbing an input, you will need to :release the subinput.

    + +

    This will also reset the input to a neutral state. The subinput will share everything with this input, except + grabbed, grabbing, event (a new event registry is created), and of course its current state. + + + + + + + + + + + +

    +
    + + Input:release () +
    +
    + Release a subinput and its children. + The parent grabbed input will be updated again. This subinput will be reset to a neutral position and won’t be updated further. + + + + + + + + + + + +
    +
    + + Input:neutralize () +
    +
    + Set the state of this input to a neutral position (i.e. value = 0). + + + + + + + + + + + +
    +
    + + Input:setJoystick (joystick) +
    +
    + Set the joystick associated with this input. + The input will ignore every other joystick. + Set joystick to nil to disable and get input from every connected joystick. + + + + + + +

    Parameters:

    +
      +
    • joystick + LÖVE jostick object to associate +
    • +
    + + + + + +
    +
    + + Input:getJoystick () +
    +
    + Returns the currently selected joystick. + + + + + + + + + + + +
    +
    + + Input:down () +
    +
    + Returns true if the input is currently down. + + + + + + + + + + + +
    +
    + + Input:pressed () +
    +
    + Returns true if the input has just been pressed. + + + + + + + + + + + +
    +
    + + Input:released () +
    +
    + Returns true if the input has just been released. + + + + + + + + + + + +
    +
    + + Input:value () +
    +
    + Returns the current value of the input. + + + + + + + + + + + +
    +
    + + Input:delta () +
    +
    + Returns the delta value of the input since the last call to update. + + + + + + + + + + + +
    +
    + + Input:pointer () +
    +
    + If there is a horizontal and vertical children inputs, this returns the horizontal value and the vertical value. + Typically used for movement/axes pairs (e.g. to get x,y of a stick or directional pad). + + + + + + + + + + + +
    +
    + + Input:clamped () +
    +
    + Same as pointer, but normalize the returned vector, i.e. “clamp” the returned x,y coordinates into a circle of radius 1. + Typically used to avoid faster movement on diagonals + (as if both horizontal and vertical values are 1, the pointer vector has √2 magnitude, higher than the 1 magnitude of a purely vertical or horizontal movement). + + + + + + + + + + + +
    +
    + + +
    +
    +
    +generated by LDoc 1.4.6 +Last updated 2022-09-16 20:07:07 +
    +
    + + diff --git a/docs/modules/ldtk.html b/docs/modules/ldtk.html index e91bcac..4ff7347 100644 --- a/docs/modules/ldtk.html +++ b/docs/modules/ldtk.html @@ -50,6 +50,7 @@
  • ubiquitousse
  • asset
  • ecs
  • +
  • input
  • ldtk
  • scene
  • signal
  • @@ -68,15 +69,22 @@

    Module ldtk

    LDtk level importer for Lua and drawing using LÖVE.

    -

    Support most LDtk features, and allow easy usage in LÖVE projects.

    +

    Support most LDtk features, and allow easy usage in LÖVE projects. + In particular, this mainly focus only on features and values that are useful for showing the final level – this does not try, for example, to expose + every internal identfiers or intermediates values that are only relevant for editing.

    + +

    Currently up-to-date with LDtk 1.1.3.

    Every unit is in pixel in the API unless written otherwise. Colors are reprsented as a table {r,g,b} where r,b,g in [0-1].

    This modules returns a single function, LDtk(path).

    -

    No mandatory dependency. - Optionally requires LÖVE love.graphics (drawing Image, SpriteBatch, Quad) for drawing only.

    +

    This modules requires json.lua; a copy of it is included with ubiquitousse in the lib directory for simplicity. + This module will first try to load a global module named json – so if you use the same json module in your project ubiquitousse will reuse it. + If it doesn’t find it, it will then try to load the copy included with ubiquitousse.

    + +

    Optionally requires LÖVE love.graphics (drawing Image, SpriteBatch, Quad), for drawing only.

    Usage:

    + + + + + +

    Returns:

    +
      + + SignalGroup + + +
    + + + +
    event
    -

    SignalRegistry which will be used to bind signals that need to be called on game engine event; other ubiquitousse modules may bind to this registry + SignalRegistry which will be used to bind signals that need to be called on LÖVE events; other ubiquitousse modules may bind to this registry if avaible.

    For example, every ubiquitousse module with a “update” function will bind it to the “update” signal in the registry; you can then call this signal on each game update to update every ubiquitousse module easily.

    -

    Provided signals:

    - - - +

    You will need to call registerEvents for the signal to be called on LÖVE callbacks automatically (otherwise you will have to emit the events + from the LÖVE callbacks manually).

    +

    List of signals available: “displayrotated”, “draw”, “load”, “lowmemory”, “quit”, “update”, + “directorydropped”, “filedropped”, “focus”, “mousefocus”, “resize”, “visible”, + “keypressed”, “keyreleased”, “textedited”, “textinput”, + “mousemoved”, “mousepressed”, “mousereleased”, “wheelmoved”, + “gamepadaxis”, “gamepadpressed”, “gamepadreleased”, + “joystickadded”, “joystickaxis”, “joystickhat”, “joystickpressed”, “joystickreleased”, “joystickremoved”, + “touchmoved”, “touchpressed”, “touchreleased”.

    Type:

    @@ -226,7 +324,28 @@

    Type:

    + + + + + + + + +
    +
    + + SignalRegistry.chained +
    +
    + List of registries chained to this registry. + + +

    Type:

    + @@ -239,10 +358,10 @@
    - SignalRegistry:bind (name, fn, ...) + SignalRegistry:bind (name, fn)
    - Bind one or several functions to a signal name. + Bind a function to a signal name. @@ -259,9 +378,34 @@ function the function to bind to the signal -
  • ... - function,... - other function to bind to the signal + + + + + + +
  • +
    + + SignalRegistry:has (name, fn) +
    +
    + Returns true if fn is bound to the signal. + + + + + + +

    Parameters:

    + @@ -272,10 +416,10 @@
    - SignalRegistry:unbind (name, fn, ...) + SignalRegistry:unbind (name, fn)
    - Unbind one or several functions to a signal name. + Unbind a function from a signal name. @@ -292,9 +436,34 @@ function the function to unbind to the signal -
  • ... - function,... - other function to unbind to the signal + + + + + + +
  • +
    + + SignalRegistry:unbindPattern (pat, fn) +
    +
    + Unbind a function from every signal whose name match the pattern. + + + + + + +

    Parameters:

    + @@ -304,8 +473,8 @@
    - - SignalRegistry:unbindAll (name) + + SignalRegistry:clear (name)
    Remove every bound function to a signal name. @@ -329,11 +498,11 @@
    - - SignalRegistry:replace (name, sourceFn, destFn) + + SignalRegistry:clearPattern (pat)
    - Replace a bound function with another function. + Remove every bound function to every signal whose name match the pattern. @@ -342,17 +511,9 @@

    Parameters:

    @@ -360,24 +521,6 @@ -
    -
    - - SignalRegistry:clear () -
    -
    - Remove every bound function to every signal. - - - - - - - - - - -
    @@ -406,6 +549,237 @@ + +
    + + SignalRegistry:emitPattern (pat, ...) +
    +
    + Emit to every signal whose name match the pattern. + + + + + + +

    Parameters:

    + + + + + + +
    +
    + + SignalRegistry:chain (registry) +
    +
    + Chain another regsitry to this registry. + I.e., after an event is emitted in this registry it will be automatically emitted in the other registry. + Several registries can be chained to a single registry. + + + + + + +

    Parameters:

    + + + + + + +
    +
    + + SignalRegistry:unchain (registry) +
    +
    + Unchain a specific registry from the registry chaining list. + Will error if the regsitry is not in the chaining list. + + + + + + +

    Parameters:

    + + + + + + +
    + +

    SignalGroup objects

    + +
    + Signal group.

    + +

    A SignalGroup is a list of (registry, signal name, function) triplets. + When the group is active, all of these triplets will bind the specified signal name to the specified function in the specified registry. + When the group is paused, all of these triplets are unbound.

    + +

    This can be used to maintain a list of signal bindings where every one should be either disabled or enabled at the same time. + For example you may maintain a signal group of signals you want to be emitted when your game is running, and disabled when the game is paused + (like inputs, update, simulation step, etc. signals). +

    +
    +
    + + SignalGroup.paused +
    +
    + Indicate if the signal group if currently paused or not. + + +

    Type:

    +
      + boolean +
    + + + + + + + + +
    +
    + + SignalGroup.binds +
    +
    + List of triplets in the group. + + +

    Type:

    +
      + { {registry, "signal name", function}, ... } +
    + + + + + + + + +
    +
    + + SignalGroup:bind (registry, name, fn) +
    +
    + Bind a function to a signal name in the given registry. + This handles binding the function on its own; you do not need to call SignalRegistry:bind manually. + If the group is paused, this will not bind the function immediately but only on the next time this group is resumed (as expected). + + + + + + +

    Parameters:

    +
      +
    • registry + SignalRegistry + to bind the signal in +
    • +
    • name + string + the name of the signal +
    • +
    • fn + function + the function to bind to the signal +
    • +
    + + + + + +
    +
    + + SignalGroup:clear () +
    +
    + Remove every bound triplet in the group. + + + + + + + + + + + +
    +
    + + SignalGroup:pause () +
    +
    + Pause the group. + The signals bound to this group will be disabled in their given registries. + + + + + + + + + + + +
    +
    + + SignalGroup:resume () +
    +
    + Resume the group. + The signals bound to this group will be enabled in their given registries. + + + + + + + + + + +
    @@ -414,7 +788,7 @@
    generated by LDoc 1.4.6 -Last updated 2021-12-27 17:22:39 +Last updated 2022-09-16 20:07:07
    diff --git a/docs/modules/timer.html b/docs/modules/timer.html index 7dbf0b1..9a33d7f 100644 --- a/docs/modules/timer.html +++ b/docs/modules/timer.html @@ -45,6 +45,7 @@
  • ubiquitousse
  • asset
  • ecs
  • +
  • input
  • ldtk
  • scene
  • signal
  • @@ -1153,7 +1154,7 @@
    generated by LDoc 1.4.6 -Last updated 2021-12-27 17:22:39 +Last updated 2022-09-16 20:07:07
    diff --git a/docs/modules/ubiquitousse.html b/docs/modules/ubiquitousse.html index 9753ba9..2d4b091 100644 --- a/docs/modules/ubiquitousse.html +++ b/docs/modules/ubiquitousse.html @@ -42,6 +42,7 @@
  • ubiquitousse
  • asset
  • ecs
  • +
  • input
  • ldtk
  • scene
  • signal
  • @@ -141,6 +142,10 @@ the repository to save you a few seconds.

    LDtk level import, if available. + gltf + glTF model import, if available. + + scene Scene management, if available. @@ -233,7 +238,7 @@ the repository to save you a few seconds.

    Input management, if available. - TODO: not currently generated with LDoc. + TODO: documentation not currently generated with LDoc. @@ -245,7 +250,7 @@ the repository to save you a few seconds.

    See also:

    @@ -271,6 +276,29 @@ the repository to save you a few seconds.

    +
    +
    + + gltf +
    +
    + glTF model import, if available. + TODO: documentation not currently generated with LDoc. + + + + + + + + + +

    See also:

    + + +
    @@ -367,7 +395,7 @@ the repository to save you a few seconds.

    generated by LDoc 1.4.6 -Last updated 2021-12-27 17:22:39 +Last updated 2022-09-16 20:07:07
    diff --git a/docs/modules/util.html b/docs/modules/util.html index 0979dd0..9414737 100644 --- a/docs/modules/util.html +++ b/docs/modules/util.html @@ -42,6 +42,7 @@
  • ubiquitousse
  • asset
  • ecs
  • +
  • input
  • ldtk
  • scene
  • signal
  • @@ -784,7 +785,7 @@
    generated by LDoc 1.4.6 -Last updated 2021-12-27 17:22:39 +Last updated 2022-09-16 20:07:07
    diff --git a/docs/topics/LICENSE.html b/docs/topics/LICENSE.html index a861be2..5c2811f 100644 --- a/docs/topics/LICENSE.html +++ b/docs/topics/LICENSE.html @@ -43,6 +43,7 @@
  • ubiquitousse
  • asset
  • ecs
  • +
  • input
  • ldtk
  • scene
  • signal
  • @@ -54,7 +55,7 @@
    - Copyright 2021 Étienne “Reuh” Fildadut

    + Copyright 2016-2022 Étienne “Reuh” Fildadut

    Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

    @@ -64,7 +65,7 @@
    generated by LDoc 1.4.6 -Last updated 2021-12-27 17:22:39 +Last updated 2022-09-16 20:07:07
    diff --git a/docs/topics/README.md.html b/docs/topics/README.md.html index 2553fcd..9784fa6 100644 --- a/docs/topics/README.md.html +++ b/docs/topics/README.md.html @@ -43,6 +43,7 @@
  • ubiquitousse
  • asset
  • ecs
  • +
  • input
  • ldtk
  • scene
  • signal
  • @@ -56,7 +57,22 @@

    ubiquitousse

    -

    Set of various libraries I use for game development, mainly with LÖVE. Nothing that hasn’t been done before, but these are tailored to what I need. They can be used independently too.

    +

    Set of various libraries I use for game development, mainly with LÖVE. Most of which has already been done before, but these are tailored to what I need. They can be used independently too (you should be able to only pick the directories of the libraries you need; some modules depends on each other though, see documentation for details).

    + +

    This provides, sorting the one with the fewest existing alterative as far as I know first:

    + + +

    You can find the documentation here or in the docs/ directory.

    @@ -64,14 +80,14 @@

    Whatever is currently on the master branch should be working and usable. Changelog, including breaking changes, are documented in commit messages.

    -

    Licensed under ISC (equivalent to MIT/Expat/Simplified BSD).

    +

    Licensed under ISC (equivalent to MIT/Expat/Simplified BSD). Have fun.

    generated by LDoc 1.4.6 -Last updated 2021-12-27 17:22:39 +Last updated 2022-09-16 20:07:07
    diff --git a/ecs/ecs.lua b/ecs/ecs.lua index 2e9b97e..620a502 100644 --- a/ecs/ecs.lua +++ b/ecs/ecs.lua @@ -289,206 +289,229 @@ end, -- ./ecs/ecs.can:604 ["iter"] = function(self) -- ./ecs/ecs.can:609 return nextEntity, { self["_first"] } -- ./ecs/ecs.can:610 end, -- ./ecs/ecs.can:610 -["clear"] = function(self) -- ./ecs/ecs.can:613 -for e in self:iter() do -- ./ecs/ecs.can:614 -self:remove(e) -- ./ecs/ecs.can:615 -end -- ./ecs/ecs.can:615 -for _, s in ipairs(self["systems"]) do -- ./ecs/ecs.can:617 -s:clear() -- ./ecs/ecs.can:618 -end -- ./ecs/ecs.can:618 -end, -- ./ecs/ecs.can:618 -["update"] = function(self, dt) -- ./ecs/ecs.can:625 -if self["active"] then -- ./ecs/ecs.can:626 -if self["interval"] then -- ./ecs/ecs.can:627 -self["_waited"] = self["_waited"] + (dt) -- ./ecs/ecs.can:628 -if self["_waited"] < self["interval"] then -- ./ecs/ecs.can:629 -return -- ./ecs/ecs.can:630 +["get"] = function(self, i) -- ./ecs/ecs.can:617 +local n = 1 -- ./ecs/ecs.can:618 +for e in self:iter() do -- ./ecs/ecs.can:619 +if n == i then -- ./ecs/ecs.can:620 +return e -- ./ecs/ecs.can:621 +end -- ./ecs/ecs.can:621 +n = n + (1) -- ./ecs/ecs.can:623 +end -- ./ecs/ecs.can:623 +return nil -- ./ecs/ecs.can:625 +end, -- ./ecs/ecs.can:625 +["clear"] = function(self) -- ./ecs/ecs.can:628 +for e in self:iter() do -- ./ecs/ecs.can:629 +self:remove(e) -- ./ecs/ecs.can:630 end -- ./ecs/ecs.can:630 -end -- ./ecs/ecs.can:630 -self:onUpdate(dt) -- ./ecs/ecs.can:633 -if self["process"] ~= system_mt["process"] then -- ./ecs/ecs.can:634 -for e in self:iter() do -- ./ecs/ecs.can:635 -self:process(e, e[self["component"]], dt) -- ./ecs/ecs.can:636 -end -- ./ecs/ecs.can:636 -end -- ./ecs/ecs.can:636 -for _, s in ipairs(self["systems"]) do -- ./ecs/ecs.can:639 -s:update(dt) -- ./ecs/ecs.can:640 -end -- ./ecs/ecs.can:640 -self:onUpdateEnd(dt) -- ./ecs/ecs.can:642 -if self["interval"] then -- ./ecs/ecs.can:643 -self["_waited"] = self["_waited"] - (self["interval"]) -- ./ecs/ecs.can:644 -end -- ./ecs/ecs.can:644 -end -- ./ecs/ecs.can:644 -end, -- ./ecs/ecs.can:644 -["draw"] = function(self) -- ./ecs/ecs.can:651 -if self["visible"] then -- ./ecs/ecs.can:652 -self:onDraw() -- ./ecs/ecs.can:653 -if self["render"] ~= system_mt["render"] then -- ./ecs/ecs.can:654 -for e in self:iter() do -- ./ecs/ecs.can:655 -self:render(e, e[self["component"]]) -- ./ecs/ecs.can:656 -end -- ./ecs/ecs.can:656 -end -- ./ecs/ecs.can:656 -for _, s in ipairs(self["systems"]) do -- ./ecs/ecs.can:659 -s:draw() -- ./ecs/ecs.can:660 -end -- ./ecs/ecs.can:660 -self:onDrawEnd() -- ./ecs/ecs.can:662 -end -- ./ecs/ecs.can:662 -end, -- ./ecs/ecs.can:662 -["callback"] = function(self, name, e, ...) -- ./ecs/ecs.can:675 -if self["_previous"][e] and self[name] then -- ./ecs/ecs.can:677 -self[name](self, e, e[self["component"]], ...) -- ./ecs/ecs.can:678 -end -- ./ecs/ecs.can:678 -if self["_previous"][e] then -- ./ecs/ecs.can:681 -for _, ss in ipairs(self["systems"]) do -- ./ecs/ecs.can:682 -ss:callback(name, e, ...) -- ./ecs/ecs.can:683 -end -- ./ecs/ecs.can:683 -end -- ./ecs/ecs.can:683 -end, -- ./ecs/ecs.can:683 -["emit"] = function(self, name, ...) -- ./ecs/ecs.can:708 -local status -- ./ecs/ecs.can:710 -if self[name] then -- ./ecs/ecs.can:711 -status = self[name](self, ...) -- ./ecs/ecs.can:712 -end -- ./ecs/ecs.can:712 -if status ~= "stop" and status ~= "capture" then -- ./ecs/ecs.can:715 -for _, s in ipairs(self["systems"]) do -- ./ecs/ecs.can:716 -status = s:emit(name, ...) -- ./ecs/ecs.can:717 -if status == "capture" then -- ./ecs/ecs.can:718 -break -- ./ecs/ecs.can:718 -end -- ./ecs/ecs.can:718 -end -- ./ecs/ecs.can:718 -end -- ./ecs/ecs.can:718 -return status -- ./ecs/ecs.can:721 -end, -- ./ecs/ecs.can:721 -["destroy"] = function(self) -- ./ecs/ecs.can:724 -recCallOnRemoveFromWorld(self["world"], { self }) -- ./ecs/ecs.can:725 -recDestroySystems({ ["systems"] = { self } }) -- ./ecs/ecs.can:726 -end -- ./ecs/ecs.can:726 -} -- ./ecs/ecs.can:726 -local alwaysTrue -- ./ecs/ecs.can:731 -alwaysTrue = function() -- ./ecs/ecs.can:731 -return true -- ./ecs/ecs.can:731 -end -- ./ecs/ecs.can:731 -local alwaysFalse -- ./ecs/ecs.can:732 -alwaysFalse = function() -- ./ecs/ecs.can:732 -return false -- ./ecs/ecs.can:732 -end -- ./ecs/ecs.can:732 -local recInstanciateSystems -- ./ecs/ecs.can:737 -recInstanciateSystems = function(world, systems) -- ./ecs/ecs.can:737 -local t -- ./ecs/ecs.can:738 -t = {} -- ./ecs/ecs.can:738 -for _, s in ipairs(systems) do -- ./ecs/ecs.can:739 -local system -- ./ecs/ecs.can:740 -system = setmetatable({ -- ./ecs/ecs.can:742 -["systems"] = recInstanciateSystems(world, s["systems"] or {}), -- ./ecs/ecs.can:743 -["world"] = world, -- ./ecs/ecs.can:744 -["w"] = world, -- ./ecs/ecs.can:745 -["s"] = world["s"], -- ./ecs/ecs.can:746 -["_previous"] = {} -- ./ecs/ecs.can:747 -}, { ["__index"] = function(self, k) -- ./ecs/ecs.can:749 -if s[k] ~= nil then -- ./ecs/ecs.can:750 -return s[k] -- ./ecs/ecs.can:751 -else -- ./ecs/ecs.can:751 -return system_mt[k] -- ./ecs/ecs.can:753 -end -- ./ecs/ecs.can:753 -end }) -- ./ecs/ecs.can:753 -if type(s["filter"]) == "string" then -- ./ecs/ecs.can:758 -system["filter"] = function(_, e) -- ./ecs/ecs.can:759 -return e[s["filter"]] ~= nil -- ./ecs/ecs.can:759 -end -- ./ecs/ecs.can:759 -elseif type(s["filter"]) == "table" then -- ./ecs/ecs.can:760 -system["filter"] = ecs["all"](unpack(s["filter"])) -- ./ecs/ecs.can:761 -elseif type(s["filter"]) == "boolean" then -- ./ecs/ecs.can:762 -if s["filter"] then -- ./ecs/ecs.can:763 -system["filter"] = alwaysTrue -- ./ecs/ecs.can:764 -else -- ./ecs/ecs.can:764 -system["filter"] = alwaysFalse -- ./ecs/ecs.can:766 -end -- ./ecs/ecs.can:766 -end -- ./ecs/ecs.can:766 -if not s["component"] and s["name"] then -- ./ecs/ecs.can:770 -s["component"] = s["name"] -- ./ecs/ecs.can:771 -end -- ./ecs/ecs.can:771 -table["insert"](t, system) -- ./ecs/ecs.can:774 -if s["name"] then -- ./ecs/ecs.can:775 -world["s"][s["name"]] = system -- ./ecs/ecs.can:776 -end -- ./ecs/ecs.can:776 -system:onInstance() -- ./ecs/ecs.can:778 -end -- ./ecs/ecs.can:778 -return t -- ./ecs/ecs.can:780 -end -- ./ecs/ecs.can:780 -local recCallOnAddToWorld -- ./ecs/ecs.can:783 -recCallOnAddToWorld = function(world, systems) -- ./ecs/ecs.can:783 -for _, s in ipairs(systems) do -- ./ecs/ecs.can:784 -recCallOnAddToWorld(world, s["systems"]) -- ./ecs/ecs.can:785 -s:onAddToWorld(world) -- ./ecs/ecs.can:786 +for _, s in ipairs(self["systems"]) do -- ./ecs/ecs.can:632 +s:clear() -- ./ecs/ecs.can:633 +end -- ./ecs/ecs.can:633 +end, -- ./ecs/ecs.can:633 +["update"] = function(self, dt) -- ./ecs/ecs.can:640 +if self["active"] then -- ./ecs/ecs.can:641 +if self["interval"] then -- ./ecs/ecs.can:642 +self["_waited"] = self["_waited"] + (dt) -- ./ecs/ecs.can:643 +if self["_waited"] < self["interval"] then -- ./ecs/ecs.can:644 +return -- ./ecs/ecs.can:645 +end -- ./ecs/ecs.can:645 +end -- ./ecs/ecs.can:645 +self:onUpdate(dt) -- ./ecs/ecs.can:648 +if self["process"] ~= system_mt["process"] then -- ./ecs/ecs.can:649 +for e in self:iter() do -- ./ecs/ecs.can:650 +self:process(e, e[self["component"]], dt) -- ./ecs/ecs.can:651 +end -- ./ecs/ecs.can:651 +end -- ./ecs/ecs.can:651 +for _, s in ipairs(self["systems"]) do -- ./ecs/ecs.can:654 +s:update(dt) -- ./ecs/ecs.can:655 +end -- ./ecs/ecs.can:655 +self:onUpdateEnd(dt) -- ./ecs/ecs.can:657 +if self["interval"] then -- ./ecs/ecs.can:658 +self["_waited"] = self["_waited"] - (self["interval"]) -- ./ecs/ecs.can:659 +end -- ./ecs/ecs.can:659 +end -- ./ecs/ecs.can:659 +end, -- ./ecs/ecs.can:659 +["draw"] = function(self) -- ./ecs/ecs.can:666 +if self["visible"] then -- ./ecs/ecs.can:667 +self:onDraw() -- ./ecs/ecs.can:668 +if self["render"] ~= system_mt["render"] then -- ./ecs/ecs.can:669 +for e in self:iter() do -- ./ecs/ecs.can:670 +self:render(e, e[self["component"]]) -- ./ecs/ecs.can:671 +end -- ./ecs/ecs.can:671 +end -- ./ecs/ecs.can:671 +for _, s in ipairs(self["systems"]) do -- ./ecs/ecs.can:674 +s:draw() -- ./ecs/ecs.can:675 +end -- ./ecs/ecs.can:675 +self:onDrawEnd() -- ./ecs/ecs.can:677 +end -- ./ecs/ecs.can:677 +end, -- ./ecs/ecs.can:677 +["callback"] = function(self, name, e, ...) -- ./ecs/ecs.can:690 +if self["_previous"][e] and self[name] then -- ./ecs/ecs.can:692 +self[name](self, e, e[self["component"]], ...) -- ./ecs/ecs.can:693 +end -- ./ecs/ecs.can:693 +if self["_previous"][e] then -- ./ecs/ecs.can:696 +for _, ss in ipairs(self["systems"]) do -- ./ecs/ecs.can:697 +ss:callback(name, e, ...) -- ./ecs/ecs.can:698 +end -- ./ecs/ecs.can:698 +end -- ./ecs/ecs.can:698 +end, -- ./ecs/ecs.can:698 +["emit"] = function(self, name, ...) -- ./ecs/ecs.can:723 +local status -- ./ecs/ecs.can:725 +if self[name] then -- ./ecs/ecs.can:726 +status = self[name](self, ...) -- ./ecs/ecs.can:727 +end -- ./ecs/ecs.can:727 +if status ~= "stop" and status ~= "capture" then -- ./ecs/ecs.can:730 +for _, s in ipairs(self["systems"]) do -- ./ecs/ecs.can:731 +status = s:emit(name, ...) -- ./ecs/ecs.can:732 +if status == "capture" then -- ./ecs/ecs.can:733 +break -- ./ecs/ecs.can:733 +end -- ./ecs/ecs.can:733 +end -- ./ecs/ecs.can:733 +end -- ./ecs/ecs.can:733 +return status -- ./ecs/ecs.can:736 +end, -- ./ecs/ecs.can:736 +["destroy"] = function(self) -- ./ecs/ecs.can:739 +recCallOnRemoveFromWorld(self["world"], { self }) -- ./ecs/ecs.can:740 +recDestroySystems({ ["systems"] = { self } }) -- ./ecs/ecs.can:741 +end -- ./ecs/ecs.can:741 +} -- ./ecs/ecs.can:741 +local alwaysTrue -- ./ecs/ecs.can:746 +alwaysTrue = function() -- ./ecs/ecs.can:746 +return true -- ./ecs/ecs.can:746 +end -- ./ecs/ecs.can:746 +local alwaysFalse -- ./ecs/ecs.can:747 +alwaysFalse = function() -- ./ecs/ecs.can:747 +return false -- ./ecs/ecs.can:747 +end -- ./ecs/ecs.can:747 +local recInstanciateSystems -- ./ecs/ecs.can:752 +recInstanciateSystems = function(world, systems) -- ./ecs/ecs.can:752 +local t -- ./ecs/ecs.can:753 +t = {} -- ./ecs/ecs.can:753 +for _, s in ipairs(systems) do -- ./ecs/ecs.can:754 +local system -- ./ecs/ecs.can:755 +system = setmetatable({ -- ./ecs/ecs.can:757 +["systems"] = recInstanciateSystems(world, s["systems"] or {}), -- ./ecs/ecs.can:758 +["world"] = world, -- ./ecs/ecs.can:759 +["w"] = world, -- ./ecs/ecs.can:760 +["s"] = world["s"], -- ./ecs/ecs.can:761 +["_previous"] = {} -- ./ecs/ecs.can:762 +}, { ["__index"] = function(self, k) -- ./ecs/ecs.can:764 +if s[k] ~= nil then -- ./ecs/ecs.can:765 +return s[k] -- ./ecs/ecs.can:766 +else -- ./ecs/ecs.can:766 +return system_mt[k] -- ./ecs/ecs.can:768 +end -- ./ecs/ecs.can:768 +end }) -- ./ecs/ecs.can:768 +if type(s["filter"]) == "string" then -- ./ecs/ecs.can:773 +system["filter"] = function(_, e) -- ./ecs/ecs.can:774 +return e[s["filter"]] ~= nil -- ./ecs/ecs.can:774 +end -- ./ecs/ecs.can:774 +elseif type(s["filter"]) == "table" then -- ./ecs/ecs.can:775 +system["filter"] = ecs["all"](unpack(s["filter"])) -- ./ecs/ecs.can:776 +elseif type(s["filter"]) == "boolean" then -- ./ecs/ecs.can:777 +if s["filter"] then -- ./ecs/ecs.can:778 +system["filter"] = alwaysTrue -- ./ecs/ecs.can:779 +else -- ./ecs/ecs.can:779 +system["filter"] = alwaysFalse -- ./ecs/ecs.can:781 +end -- ./ecs/ecs.can:781 +end -- ./ecs/ecs.can:781 +if not s["component"] and s["name"] then -- ./ecs/ecs.can:785 +s["component"] = s["name"] -- ./ecs/ecs.can:786 end -- ./ecs/ecs.can:786 -end -- ./ecs/ecs.can:786 -ecs = { -- ./ecs/ecs.can:792 -["world"] = function(...) -- ./ecs/ecs.can:797 -local world -- ./ecs/ecs.can:798 -world = setmetatable({ -- ./ecs/ecs.can:798 -["filter"] = ecs["all"](), -- ./ecs/ecs.can:799 -["s"] = {}, -- ./ecs/ecs.can:800 -["_previous"] = {} -- ./ecs/ecs.can:801 -}, { ["__index"] = system_mt }) -- ./ecs/ecs.can:802 -world["world"] = world -- ./ecs/ecs.can:803 -world["w"] = world -- ./ecs/ecs.can:804 -world["systems"] = recInstanciateSystems(world, { ... }) -- ./ecs/ecs.can:805 -recCallOnAddToWorld(world, world["systems"]) -- ./ecs/ecs.can:806 -return world -- ./ecs/ecs.can:807 -end, -- ./ecs/ecs.can:807 -["all"] = function(...) -- ./ecs/ecs.can:813 -if ... then -- ./ecs/ecs.can:814 -local l -- ./ecs/ecs.can:815 -l = { ... } -- ./ecs/ecs.can:815 -return function(s, e) -- ./ecs/ecs.can:816 -for _, k in ipairs(l) do -- ./ecs/ecs.can:817 -if e[k] == nil then -- ./ecs/ecs.can:818 -return false -- ./ecs/ecs.can:819 -end -- ./ecs/ecs.can:819 -end -- ./ecs/ecs.can:819 -return true -- ./ecs/ecs.can:822 -end -- ./ecs/ecs.can:822 -else -- ./ecs/ecs.can:822 -return alwaysTrue -- ./ecs/ecs.can:825 -end -- ./ecs/ecs.can:825 -end, -- ./ecs/ecs.can:825 -["any"] = function(...) -- ./ecs/ecs.can:832 -if ... then -- ./ecs/ecs.can:833 -local l -- ./ecs/ecs.can:834 -l = { ... } -- ./ecs/ecs.can:834 -return function(s, e) -- ./ecs/ecs.can:835 -for _, k in ipairs(l) do -- ./ecs/ecs.can:836 -if e[k] ~= nil then -- ./ecs/ecs.can:837 -return true -- ./ecs/ecs.can:838 -end -- ./ecs/ecs.can:838 -end -- ./ecs/ecs.can:838 -return false -- ./ecs/ecs.can:841 -end -- ./ecs/ecs.can:841 -else -- ./ecs/ecs.can:841 -return alwaysFalse -- ./ecs/ecs.can:844 -end -- ./ecs/ecs.can:844 -end, -- ./ecs/ecs.can:844 -["scene"] = function(name, systems, entities) -- ./ecs/ecs.can:854 -if systems == nil then systems = {} end -- ./ecs/ecs.can:854 -if entities == nil then entities = {} end -- ./ecs/ecs.can:854 -assert(scene, "ubiquitousse.scene unavailable") -- ./ecs/ecs.can:855 -local s -- ./ecs/ecs.can:856 -s = scene["new"](name) -- ./ecs/ecs.can:856 -local w -- ./ecs/ecs.can:857 -s["enter"] = function(self) -- ./ecs/ecs.can:859 -w = ecs["world"](unpack(systems)) -- ./ecs/ecs.can:860 -w:add(unpack(entities)) -- ./ecs/ecs.can:861 -end -- ./ecs/ecs.can:861 -s["exit"] = function(self) -- ./ecs/ecs.can:863 -w:destroy() -- ./ecs/ecs.can:864 -end -- ./ecs/ecs.can:864 -s["update"] = function(self, dt) -- ./ecs/ecs.can:866 -w:update(dt) -- ./ecs/ecs.can:867 -end -- ./ecs/ecs.can:867 -s["draw"] = function(self) -- ./ecs/ecs.can:869 -w:draw() -- ./ecs/ecs.can:870 -end -- ./ecs/ecs.can:870 -return s -- ./ecs/ecs.can:873 -end -- ./ecs/ecs.can:873 -} -- ./ecs/ecs.can:873 -return ecs -- ./ecs/ecs.can:877 +table["insert"](t, system) -- ./ecs/ecs.can:789 +if s["name"] then -- ./ecs/ecs.can:790 +world["s"][s["name"]] = system -- ./ecs/ecs.can:791 +end -- ./ecs/ecs.can:791 +system:onInstance() -- ./ecs/ecs.can:793 +end -- ./ecs/ecs.can:793 +return t -- ./ecs/ecs.can:795 +end -- ./ecs/ecs.can:795 +local recCallOnAddToWorld -- ./ecs/ecs.can:798 +recCallOnAddToWorld = function(world, systems) -- ./ecs/ecs.can:798 +for _, s in ipairs(systems) do -- ./ecs/ecs.can:799 +recCallOnAddToWorld(world, s["systems"]) -- ./ecs/ecs.can:800 +s:onAddToWorld(world) -- ./ecs/ecs.can:801 +end -- ./ecs/ecs.can:801 +end -- ./ecs/ecs.can:801 +ecs = { -- ./ecs/ecs.can:807 +["world"] = function(...) -- ./ecs/ecs.can:812 +local world -- ./ecs/ecs.can:813 +world = setmetatable({ -- ./ecs/ecs.can:813 +["filter"] = ecs["all"](), -- ./ecs/ecs.can:814 +["s"] = {}, -- ./ecs/ecs.can:815 +["_previous"] = {} -- ./ecs/ecs.can:816 +}, { ["__index"] = system_mt }) -- ./ecs/ecs.can:817 +world["world"] = world -- ./ecs/ecs.can:818 +world["w"] = world -- ./ecs/ecs.can:819 +world["systems"] = recInstanciateSystems(world, { ... }) -- ./ecs/ecs.can:820 +recCallOnAddToWorld(world, world["systems"]) -- ./ecs/ecs.can:821 +return world -- ./ecs/ecs.can:822 +end, -- ./ecs/ecs.can:822 +["all"] = function(...) -- ./ecs/ecs.can:828 +if ... then -- ./ecs/ecs.can:829 +local l -- ./ecs/ecs.can:830 +l = { ... } -- ./ecs/ecs.can:830 +return function(s, e) -- ./ecs/ecs.can:831 +for _, k in ipairs(l) do -- ./ecs/ecs.can:832 +if e[k] == nil then -- ./ecs/ecs.can:833 +return false -- ./ecs/ecs.can:834 +end -- ./ecs/ecs.can:834 +end -- ./ecs/ecs.can:834 +return true -- ./ecs/ecs.can:837 +end -- ./ecs/ecs.can:837 +else -- ./ecs/ecs.can:837 +return alwaysTrue -- ./ecs/ecs.can:840 +end -- ./ecs/ecs.can:840 +end, -- ./ecs/ecs.can:840 +["any"] = function(...) -- ./ecs/ecs.can:847 +if ... then -- ./ecs/ecs.can:848 +local l -- ./ecs/ecs.can:849 +l = { ... } -- ./ecs/ecs.can:849 +return function(s, e) -- ./ecs/ecs.can:850 +for _, k in ipairs(l) do -- ./ecs/ecs.can:851 +if e[k] ~= nil then -- ./ecs/ecs.can:852 +return true -- ./ecs/ecs.can:853 +end -- ./ecs/ecs.can:853 +end -- ./ecs/ecs.can:853 +return false -- ./ecs/ecs.can:856 +end -- ./ecs/ecs.can:856 +else -- ./ecs/ecs.can:856 +return alwaysFalse -- ./ecs/ecs.can:859 +end -- ./ecs/ecs.can:859 +end, -- ./ecs/ecs.can:859 +["scene"] = function(name, systems, entities) -- ./ecs/ecs.can:877 +if systems == nil then systems = {} end -- ./ecs/ecs.can:877 +if entities == nil then entities = {} end -- ./ecs/ecs.can:877 +assert(scene, "ubiquitousse.scene unavailable") -- ./ecs/ecs.can:878 +local s -- ./ecs/ecs.can:879 +s = scene["new"](name) -- ./ecs/ecs.can:879 +local w -- ./ecs/ecs.can:880 +s["enter"] = function(self) -- ./ecs/ecs.can:882 +local sys, ent = systems, entities -- ./ecs/ecs.can:883 +if type(systems) == "function" then -- ./ecs/ecs.can:884 +sys = { systems() } -- ./ecs/ecs.can:884 +end -- ./ecs/ecs.can:884 +if type(entities) == "function" then -- ./ecs/ecs.can:885 +ent = { entities() } -- ./ecs/ecs.can:885 +end -- ./ecs/ecs.can:885 +w = ecs["world"](unpack(sys)) -- ./ecs/ecs.can:886 +w:add(unpack(ent)) -- ./ecs/ecs.can:887 +end -- ./ecs/ecs.can:887 +s["exit"] = function(self) -- ./ecs/ecs.can:889 +w:destroy() -- ./ecs/ecs.can:890 +end -- ./ecs/ecs.can:890 +s["suspend"] = function(self) -- ./ecs/ecs.can:892 +w:emit("onSuspend") -- ./ecs/ecs.can:893 +end -- ./ecs/ecs.can:893 +s["resume"] = function(self) -- ./ecs/ecs.can:895 +w:emit("onResume") -- ./ecs/ecs.can:896 +end -- ./ecs/ecs.can:896 +s["update"] = function(self, dt) -- ./ecs/ecs.can:898 +w:update(dt) -- ./ecs/ecs.can:899 +end -- ./ecs/ecs.can:899 +s["draw"] = function(self) -- ./ecs/ecs.can:901 +w:draw() -- ./ecs/ecs.can:902 +end -- ./ecs/ecs.can:902 +return s -- ./ecs/ecs.can:905 +end -- ./ecs/ecs.can:905 +} -- ./ecs/ecs.can:905 +return ecs -- ./ecs/ecs.can:909 diff --git a/gltf/draw.lua b/gltf/draw.lua new file mode 100644 index 0000000..a2f9903 --- /dev/null +++ b/gltf/draw.lua @@ -0,0 +1,84 @@ +local whiteTexture -- ./gltf/draw.can:4 +whiteTexture = love["graphics"]["newCanvas"](2, 2) -- ./gltf/draw.can:4 +whiteTexture:renderTo(function() -- ./gltf/draw.can:5 +love["graphics"]["setColor"](1, 1, 1) -- ./gltf/draw.can:6 +love["graphics"]["rectangle"]("fill", 0, 0, 2, 2) -- ./gltf/draw.can:7 +end) -- ./gltf/draw.can:7 +local maybeSend -- ./gltf/draw.can:11 +maybeSend = function(s, name, val) -- ./gltf/draw.can:11 +if s:hasUniform(name) then -- ./gltf/draw.can:12 +s:send(name, val) -- ./gltf/draw.can:13 +end -- ./gltf/draw.can:13 +end -- ./gltf/draw.can:13 +local maybeSendTexture -- ./gltf/draw.can:16 +maybeSendTexture = function(s, name, tex) -- ./gltf/draw.can:16 +if s:hasUniform(name) then -- ./gltf/draw.can:17 +if tex then -- ./gltf/draw.can:18 +s:send(name, tex["index"]["image"]) -- ./gltf/draw.can:19 +else -- ./gltf/draw.can:19 +s:send(name, whiteTexture) -- ./gltf/draw.can:21 +end -- ./gltf/draw.can:21 +end -- ./gltf/draw.can:21 +end -- ./gltf/draw.can:21 +local applyMaterial -- ./gltf/draw.can:27 +applyMaterial = function(s, mat) -- ./gltf/draw.can:27 +maybeSend(s, "baseColorFactor", mat["pbrMetallicRoughness"]["baseColorFactor"]) -- ./gltf/draw.can:28 +maybeSendTexture(s, "baseColorTexture", mat["pbrMetallicRoughness"]["baseColorTexture"]) -- ./gltf/draw.can:29 +maybeSend(s, "metallicFactor", mat["pbrMetallicRoughness"]["metallicFactor"]) -- ./gltf/draw.can:30 +maybeSend(s, "roughnessFactor", mat["pbrMetallicRoughness"]["roughnessFactor"]) -- ./gltf/draw.can:31 +maybeSendTexture(s, "metallicRoughnessTexture", mat["pbrMetallicRoughness"]["metallicRoughnessTexture"]) -- ./gltf/draw.can:32 +maybeSendTexture(s, "normalTexture", mat["normalTexture"]) -- ./gltf/draw.can:33 +maybeSendTexture(s, "occlusionTexture", mat["occlusionTexture"]) -- ./gltf/draw.can:34 +if mat["occlusionTexture"] then -- ./gltf/draw.can:35 +maybeSend(s, "occlusionTextureStrength", mat["occlusionTexture"]["strength"]) -- ./gltf/draw.can:36 +else -- ./gltf/draw.can:36 +maybeSend(s, "occlusionTextureStrength", 1) -- ./gltf/draw.can:38 +end -- ./gltf/draw.can:38 +maybeSendTexture(s, "emissiveTexture", mat["emissiveTexture"]) -- ./gltf/draw.can:40 +if mat["emissiveTexture"] then -- ./gltf/draw.can:41 +maybeSend(s, "emissiveTextureScale", mat["emissiveTexture"]["scale"]) -- ./gltf/draw.can:42 +else -- ./gltf/draw.can:42 +maybeSend(s, "emissiveTextureScale", 1) -- ./gltf/draw.can:44 +end -- ./gltf/draw.can:44 +maybeSend(s, "emissiveFactor", mat["emissiveFactor"]) -- ./gltf/draw.can:46 +if mat["alphaMode"] == "BLEND" then -- ./gltf/draw.can:47 +love["graphics"]["setBlendMode"]("alpha") -- ./gltf/draw.can:48 +maybeSend(s, "alphaCutoff", 0) -- ./gltf/draw.can:49 +else -- ./gltf/draw.can:49 +love["graphics"]["setBlendMode"]("replace") -- ./gltf/draw.can:51 +maybeSend(s, "alphaCutoff", mat["alphaMode"] == "BLEND" and mat["alphaCutoff"] or 0) -- ./gltf/draw.can:52 +end -- ./gltf/draw.can:52 +if mat["doubleSided"] then -- ./gltf/draw.can:54 +love["graphics"]["setMeshCullMode"]("none") -- ./gltf/draw.can:55 +else -- ./gltf/draw.can:55 +love["graphics"]["setMeshCullMode"]("back") -- ./gltf/draw.can:57 +end -- ./gltf/draw.can:57 +end -- ./gltf/draw.can:57 +local drawNode -- ./gltf/draw.can:62 +drawNode = function(node, s) -- ./gltf/draw.can:62 +if node["mesh"] then -- ./gltf/draw.can:63 +s:send("modelMatrix", "column", node["matrix"]) -- ./gltf/draw.can:64 +for _, primitive in ipairs(node["mesh"]["primitives"]) do -- ./gltf/draw.can:65 +applyMaterial(s, primitive["material"]) -- ./gltf/draw.can:66 +love["graphics"]["draw"](primitive["mesh"]) -- ./gltf/draw.can:67 +end -- ./gltf/draw.can:67 +end -- ./gltf/draw.can:67 +for _, child in ipairs(node["children"]) do -- ./gltf/draw.can:70 +drawNode(child, s) -- ./gltf/draw.can:71 +end -- ./gltf/draw.can:71 +end -- ./gltf/draw.can:71 +local drawMainScene -- ./gltf/draw.can:77 +drawMainScene = function(gltf, s) -- ./gltf/draw.can:77 +love["graphics"]["push"]("all") -- ./gltf/draw.can:78 +love["graphics"]["setDepthMode"]("lequal", true) -- ./gltf/draw.can:79 +if s then -- ./gltf/draw.can:80 +love["graphics"]["setShader"](s) -- ./gltf/draw.can:81 +else -- ./gltf/draw.can:81 +s = love["graphics"]["getShader"]() -- ./gltf/draw.can:83 +end -- ./gltf/draw.can:83 +for _, node in ipairs(gltf["scene"]["nodes"]) do -- ./gltf/draw.can:85 +drawNode(node, s) -- ./gltf/draw.can:86 +end -- ./gltf/draw.can:86 +love["graphics"]["pop"]("all") -- ./gltf/draw.can:88 +end -- ./gltf/draw.can:88 +return drawMainScene -- ./gltf/draw.can:91 diff --git a/gltf/gltf.lua b/gltf/gltf.lua new file mode 100644 index 0000000..6465706 --- /dev/null +++ b/gltf/gltf.lua @@ -0,0 +1,15 @@ +local loader -- ./gltf/gltf.can:3 +loader = require((...):gsub("gltf$", "loader")) -- ./gltf/gltf.can:3 +local draw -- ./gltf/gltf.can:4 +draw = require((...):gsub("gltf$", "draw")) -- ./gltf/gltf.can:4 +local gltf_mt -- ./gltf/gltf.can:7 +gltf_mt = { -- ./gltf/gltf.can:7 +["gltf"] = nil, -- ./gltf/gltf.can:9 +["draw"] = function(self, shader) -- ./gltf/gltf.can:12 +draw(self["gltf"], shader) -- ./gltf/gltf.can:13 +end -- ./gltf/gltf.can:13 +} -- ./gltf/gltf.can:13 +gltf_mt["__index"] = gltf_mt -- ./gltf/gltf.can:16 +return function(path) -- ./gltf/gltf.can:19 +return setmetatable({ ["gltf"] = loader(path) }, gltf_mt) -- ./gltf/gltf.can:22 +end -- ./gltf/gltf.can:22 diff --git a/gltf/loader.lua b/gltf/loader.lua new file mode 100644 index 0000000..29447ab --- /dev/null +++ b/gltf/loader.lua @@ -0,0 +1,389 @@ +local json_decode -- ./gltf/loader.can:4 +do -- ./gltf/loader.can:6 +local r, json -- ./gltf/loader.can:6 +r, json = pcall(require, "json") -- ./gltf/loader.can:6 +if not r then -- ./gltf/loader.can:7 +json = require((...):gsub("gltf%.loader$", "lib.json")) -- ./gltf/loader.can:7 +end -- ./gltf/loader.can:7 +json_decode = json["decode"] -- ./gltf/loader.can:8 +end -- ./gltf/loader.can:8 +local cpml -- ./gltf/loader.can:11 +cpml = require("cpml") -- ./gltf/loader.can:11 +local mat4, vec3, quat -- ./gltf/loader.can:12 +mat4, vec3, quat = cpml["mat4"], cpml["vec3"], cpml["quat"] -- ./gltf/loader.can:12 +local dunpack -- ./gltf/loader.can:14 +dunpack = string["unpack"] or love["data"]["unpack"] -- ./gltf/loader.can:14 +local attributeName -- ./gltf/loader.can:17 +attributeName = { -- ./gltf/loader.can:17 +["POSITION"] = "VertexPosition", -- ./gltf/loader.can:18 +["NORMAL"] = "VertexNormal", -- ./gltf/loader.can:19 +["TANGENT"] = "VertexTangent", -- ./gltf/loader.can:20 +["TEXCOORD_0"] = "VertexTexCoord", -- ./gltf/loader.can:21 +["TEXCOORD_1"] = "VertexTexCoord1", -- ./gltf/loader.can:22 +["COLOR_0"] = "VertexColor", -- ./gltf/loader.can:23 +["JOINTS_0"] = "VertexJoints", -- ./gltf/loader.can:24 +["WEIGHTS_0"] = "VertexWeights" -- ./gltf/loader.can:25 +} -- ./gltf/loader.can:25 +local componentType -- ./gltf/loader.can:28 +componentType = { -- ./gltf/loader.can:28 +[5120] = "byte", -- ./gltf/loader.can:29 +[5121] = "unsigned byte", -- ./gltf/loader.can:30 +[5122] = "short", -- ./gltf/loader.can:31 +[5123] = "unsigned short", -- ./gltf/loader.can:32 +[5125] = "int", -- ./gltf/loader.can:33 +[5126] = "float" -- ./gltf/loader.can:34 +} -- ./gltf/loader.can:34 +local samplerEnum -- ./gltf/loader.can:37 +samplerEnum = { -- ./gltf/loader.can:37 +[9728] = "nearest", -- ./gltf/loader.can:38 +[9729] = "linear", -- ./gltf/loader.can:39 +[9984] = "nearest_mipmap_nearest", -- ./gltf/loader.can:40 +[9985] = "linear_mipmap_nearest", -- ./gltf/loader.can:41 +[9986] = "nearest_mipmap_linear", -- ./gltf/loader.can:42 +[9987] = "linear_mipmap_linear", -- ./gltf/loader.can:43 +[33071] = "clamp", -- ./gltf/loader.can:44 +[33648] = "mirroredrepeat", -- ./gltf/loader.can:45 +[10497] = "repeat" -- ./gltf/loader.can:46 +} -- ./gltf/loader.can:46 +local mode -- ./gltf/loader.can:49 +mode = { -- ./gltf/loader.can:49 +[0] = "points", -- ./gltf/loader.can:50 +[1] = "lines", -- ./gltf/loader.can:51 +[2] = "line_loop", -- ./gltf/loader.can:52 +[3] = "line_strip", -- ./gltf/loader.can:53 +[4] = "triangles", -- ./gltf/loader.can:54 +[5] = "strip", -- ./gltf/loader.can:55 +[6] = "fan" -- ./gltf/loader.can:56 +} -- ./gltf/loader.can:56 +local gltf -- ./gltf/loader.can:77 +gltf = function(path) -- ./gltf/loader.can:77 +local f -- ./gltf/loader.can:78 +f = assert(io["open"](path, "r")) -- ./gltf/loader.can:78 +local t -- ./gltf/loader.can:79 +t = json_decode(f:read("*a")) -- ./gltf/loader.can:79 +f:close() -- ./gltf/loader.can:80 +if t["asset"]["minVersion"] then -- ./gltf/loader.can:83 +local maj, min -- ./gltf/loader.can:84 +maj, min = t["asset"]["minVersion"]:match("^(%d+)%.(%d+)$") -- ./gltf/loader.can:84 +assert(maj == "2" and min == "0", ("asset require at least glTF version %s.%s but we only support 2.0"):format(maj, min)) -- ./gltf/loader.can:85 +else -- ./gltf/loader.can:85 +local maj, min -- ./gltf/loader.can:87 +maj, min = t["asset"]["version"]:match("^(%d+)%.(%d+)$") -- ./gltf/loader.can:87 +assert(maj == "2", ("asset require glTF version %s.%s but we only support 2.x"):format(maj, min)) -- ./gltf/loader.can:88 +end -- ./gltf/loader.can:88 +t["nodes"] = t["nodes"] or ({}) -- ./gltf/loader.can:92 +t["scenes"] = t["scenes"] or ({}) -- ./gltf/loader.can:93 +t["cameras"] = t["cameras"] or ({}) -- ./gltf/loader.can:94 +t["meshes"] = t["meshes"] or ({}) -- ./gltf/loader.can:95 +t["buffers"] = t["buffers"] or ({}) -- ./gltf/loader.can:96 +t["bufferViews"] = t["bufferViews"] or ({}) -- ./gltf/loader.can:97 +t["accessors"] = t["accessors"] or ({}) -- ./gltf/loader.can:98 +t["materials"] = t["materials"] or ({}) -- ./gltf/loader.can:99 +t["textures"] = t["textures"] or ({}) -- ./gltf/loader.can:100 +t["images"] = t["images"] or ({}) -- ./gltf/loader.can:101 +t["samplers"] = t["samplers"] or ({}) -- ./gltf/loader.can:102 +t["skins"] = t["skins"] or ({}) -- ./gltf/loader.can:103 +t["animations"] = t["animations"] or ({}) -- ./gltf/loader.can:104 +for _, scene in ipairs(t["scenes"]) do -- ./gltf/loader.can:107 +if scene["name"] then -- ./gltf/loader.can:108 +t["scenes"][scene["name"]] = scene -- ./gltf/loader.can:108 +end -- ./gltf/loader.can:108 +for i, node in ipairs(scene["nodes"]) do -- ./gltf/loader.can:109 +scene["nodes"][i] = t["nodes"][node + 1] -- ./gltf/loader.can:110 +if scene["nodes"][i]["name"] then -- ./gltf/loader.can:111 +scene["nodes"][scene["nodes"][i]["name"]] = scene["nodes"][i] -- ./gltf/loader.can:111 +end -- ./gltf/loader.can:111 +end -- ./gltf/loader.can:111 +end -- ./gltf/loader.can:111 +if t["scene"] then -- ./gltf/loader.can:116 +t["scene"] = t["scenes"][t["scene"] + 1] -- ./gltf/loader.can:117 +end -- ./gltf/loader.can:117 +for _, node in ipairs(t["nodes"]) do -- ./gltf/loader.can:121 +if node["name"] then -- ./gltf/loader.can:122 +t["nodes"][node["name"]] = node -- ./gltf/loader.can:122 +end -- ./gltf/loader.can:122 +node["children"] = node["children"] or ({}) -- ./gltf/loader.can:123 +for i, child in ipairs(node["children"]) do -- ./gltf/loader.can:124 +node["children"][i] = t["nodes"][child + 1] -- ./gltf/loader.can:125 +end -- ./gltf/loader.can:125 +if node["matrix"] then -- ./gltf/loader.can:127 +node["matrix"] = mat4(node["matrix"]) -- ./gltf/loader.can:128 +else -- ./gltf/loader.can:128 +node["translation"] = node["translation"] or ({ -- ./gltf/loader.can:130 +0, -- ./gltf/loader.can:130 +0, -- ./gltf/loader.can:130 +0 -- ./gltf/loader.can:130 +}) -- ./gltf/loader.can:130 +node["rotation"] = node["rotation"] or ({ -- ./gltf/loader.can:131 +0, -- ./gltf/loader.can:131 +0, -- ./gltf/loader.can:131 +0, -- ./gltf/loader.can:131 +1 -- ./gltf/loader.can:131 +}) -- ./gltf/loader.can:131 +node["scale"] = node["scale"] or ({ -- ./gltf/loader.can:132 +1, -- ./gltf/loader.can:132 +1, -- ./gltf/loader.can:132 +1 -- ./gltf/loader.can:132 +}) -- ./gltf/loader.can:132 +node["translation"] = vec3(node["translation"]) -- ./gltf/loader.can:134 +node["rotation"] = quat(node["rotation"]) -- ./gltf/loader.can:135 +node["scale"] = vec3(node["scale"]) -- ./gltf/loader.can:136 +node["matrix"] = mat4["identity"]() -- ./gltf/loader.can:139 +node["matrix"]:scale(node["matrix"], node["scale"]) -- ./gltf/loader.can:140 +node["matrix"]:mul(mat4["from_quaternion"](node["rotation"]), node["matrix"]) -- ./gltf/loader.can:141 +node["matrix"]:translate(node["matrix"], node["translation"]) -- ./gltf/loader.can:142 +end -- ./gltf/loader.can:142 +if node["mesh"] then -- ./gltf/loader.can:144 +node["mesh"] = t["meshes"][node["mesh"] + 1] -- ./gltf/loader.can:145 +end -- ./gltf/loader.can:145 +if node["camera"] then -- ./gltf/loader.can:147 +node["camera"] = t["cameras"][node["camera"] + 1] -- ./gltf/loader.can:148 +end -- ./gltf/loader.can:148 +end -- ./gltf/loader.can:148 +for i, buffer in ipairs(t["buffers"]) do -- ./gltf/loader.can:153 +if i == 1 and not buffer["uri"] then -- ./gltf/loader.can:154 +error("no support for glb-stored buffer") -- ./gltf/loader.can:155 +end -- ./gltf/loader.can:155 +if buffer["uri"]:match("data:") then -- ./gltf/loader.can:157 +local data = buffer["uri"]:match("^data:.-,(.*)$") -- ./gltf/loader.can:158 +if buffer["uri"]:match("^data:.-;base64,") then -- ./gltf/loader.can:159 +buffer["data"] = love["data"]["decode"]("string", "base64", data):sub(1, buffer["byteLength"] + 1) -- ./gltf/loader.can:160 +else -- ./gltf/loader.can:160 +buffer["data"] = data:gsub("%%(%x%x)", function(hex) -- ./gltf/loader.can:162 +return love["data"]["decode"]("string", "hex", hex) -- ./gltf/loader.can:163 +end):sub(1, buffer["byteLength"] + 1) -- ./gltf/loader.can:164 +end -- ./gltf/loader.can:164 +else -- ./gltf/loader.can:164 +local bf -- ./gltf/loader.can:167 +bf = assert(io["open"](buffer["uri"], "r"), ("can't find ressource %s"):format(buffer["uri"])) -- ./gltf/loader.can:167 +local s -- ./gltf/loader.can:168 +s = bf:read("*a") -- ./gltf/loader.can:168 +bf:close() -- ./gltf/loader.can:169 +buffer["data"] = s:sub(1, buffer["byteLength"] + 1) -- ./gltf/loader.can:170 +end -- ./gltf/loader.can:170 +end -- ./gltf/loader.can:170 +for _, view in ipairs(t["bufferViews"]) do -- ./gltf/loader.can:175 +view["buffer"] = t["buffers"][view["buffer"] + 1] -- ./gltf/loader.can:176 +view["byteOffset"] = view["byteOffset"] or (0) -- ./gltf/loader.can:177 +end -- ./gltf/loader.can:177 +for _, accessor in ipairs(t["accessors"]) do -- ./gltf/loader.can:182 +accessor["bufferView"] = t["bufferViews"][accessor["bufferView"] + 1] -- ./gltf/loader.can:183 +accessor["byteOffset"] = accessor["byteOffset"] or (0) -- ./gltf/loader.can:184 +local view -- ./gltf/loader.can:186 +view = accessor["bufferView"] -- ./gltf/loader.can:186 +local data -- ./gltf/loader.can:187 +data = view["buffer"]["data"] -- ./gltf/loader.can:187 +local fmt, size -- ./gltf/loader.can:190 +accessor["componentType"] = componentType[accessor["componentType"]] -- ./gltf/loader.can:191 +if accessor["componentType"] == "byte" then -- ./gltf/loader.can:192 +fmt, size = "b", 1 -- ./gltf/loader.can:193 +elseif accessor["componentType"] == "unsigned byte" then -- ./gltf/loader.can:194 +fmt, size = "B", 1 -- ./gltf/loader.can:195 +elseif accessor["componentType"] == "short" then -- ./gltf/loader.can:196 +fmt, size = "h", 2 -- ./gltf/loader.can:197 +elseif accessor["componentType"] == "unsigned short" then -- ./gltf/loader.can:198 +fmt, size = "H", 2 -- ./gltf/loader.can:199 +elseif accessor["componentType"] == "unsigned int" then -- ./gltf/loader.can:200 +fmt, size = "I4", 4 -- ./gltf/loader.can:201 +elseif accessor["componentType"] == "float" then -- ./gltf/loader.can:202 +fmt, size = "f", 4 -- ./gltf/loader.can:203 +end -- ./gltf/loader.can:203 +if accessor["type"] == "SCALAR" then -- ./gltf/loader.can:207 +accessor["components"], fmt = 1, fmt -- ./gltf/loader.can:208 +elseif accessor["type"] == "VEC2" then -- ./gltf/loader.can:209 +accessor["components"], fmt = 2, fmt:rep(2) -- ./gltf/loader.can:210 +elseif accessor["type"] == "VEC3" then -- ./gltf/loader.can:211 +accessor["components"], fmt = 3, fmt:rep(3) -- ./gltf/loader.can:212 +elseif accessor["type"] == "VEC4" then -- ./gltf/loader.can:213 +accessor["components"], fmt = 4, fmt:rep(4) -- ./gltf/loader.can:214 +elseif accessor["type"] == "MAT2" then -- ./gltf/loader.can:215 +accessor["components"] = 4 -- ./gltf/loader.can:216 +fmt = (fmt:rep(2) .. ("x"):rep(4 - (size * 2) % 4)):rep(2) -- ./gltf/loader.can:217 +elseif accessor["type"] == "MAT3" then -- ./gltf/loader.can:218 +accessor["components"] = 9 -- ./gltf/loader.can:219 +fmt = (fmt:rep(3) .. ("x"):rep(4 - (size * 3) % 4)):rep(3) -- ./gltf/loader.can:220 +elseif accessor["type"] == "MAT4" then -- ./gltf/loader.can:221 +accessor["components"] = 16 -- ./gltf/loader.can:222 +fmt = (fmt:rep(4) .. ("x"):rep(4 - (size * 4) % 4)):rep(4) -- ./gltf/loader.can:223 +end -- ./gltf/loader.can:223 +fmt = ("<") .. fmt -- ./gltf/loader.can:226 +accessor["data"] = {} -- ./gltf/loader.can:229 +local i -- ./gltf/loader.can:230 +i = view["byteOffset"] + 1 + accessor["byteOffset"] -- ./gltf/loader.can:230 +local stop -- ./gltf/loader.can:231 +stop = view["byteOffset"] + 1 + view["byteLength"] -- ./gltf/loader.can:231 +local count = 0 -- ./gltf/loader.can:232 +while i < stop and count < accessor["count"] do -- ./gltf/loader.can:233 +local d = { dunpack(fmt, data, i) } -- ./gltf/loader.can:234 +d[# d] = nil -- ./gltf/loader.can:235 +if accessor["components"] > 1 then -- ./gltf/loader.can:236 +table["insert"](accessor["data"], d) -- ./gltf/loader.can:237 +else -- ./gltf/loader.can:237 +table["insert"](accessor["data"], d[1]) -- ./gltf/loader.can:239 +end -- ./gltf/loader.can:239 +count = count + (1) -- ./gltf/loader.can:241 +i = i + (view["byteStride"] or (size * accessor["components"])) -- ./gltf/loader.can:242 +end -- ./gltf/loader.can:242 +end -- ./gltf/loader.can:242 +for _, image in ipairs(t["images"]) do -- ./gltf/loader.can:249 +if image["uri"] then -- ./gltf/loader.can:250 +image["image"] = love["graphics"]["newImage"](image["uri"]) -- ./gltf/loader.can:251 +else -- ./gltf/loader.can:251 +image["bufferView"] = t["bufferViews"][image["bufferView"] + 1] -- ./gltf/loader.can:253 +local view -- ./gltf/loader.can:255 +view = image["bufferView"] -- ./gltf/loader.can:255 +local data -- ./gltf/loader.can:256 +data = view["buffer"]["data"] -- ./gltf/loader.can:256 +image["data"] = love["image"]["newImageData"](love["data"]["newByteData"](data:sub(view["byteOffset"] + 1, view["byteOffset"] + view["byteLength"]))) -- ./gltf/loader.can:258 +end -- ./gltf/loader.can:258 +end -- ./gltf/loader.can:258 +for _, sampler in ipairs(t["samplers"]) do -- ./gltf/loader.can:262 +sampler["wrapS"] = sampler["wrapS"] or (10497) -- ./gltf/loader.can:263 +sampler["wrapT"] = sampler["wrapT"] or (10497) -- ./gltf/loader.can:264 +sampler["magFilter"] = samplerEnum[sampler["magFilter"]] -- ./gltf/loader.can:266 +sampler["minFilter"] = samplerEnum[sampler["minFilter"]] -- ./gltf/loader.can:267 +sampler["wrapS"] = samplerEnum[sampler["wrapS"]] -- ./gltf/loader.can:268 +sampler["wrapT"] = samplerEnum[sampler["wrapT"]] -- ./gltf/loader.can:269 +end -- ./gltf/loader.can:269 +for _, texture in ipairs(t["textures"]) do -- ./gltf/loader.can:272 +texture["source"] = t["images"][texture["source"] + 1] or {} -- ./gltf/loader.can:273 +texture["sampler"] = t["samplers"][texture["sampler"] + 1] -- ./gltf/loader.can:274 +local mag -- ./gltf/loader.can:276 +mag = texture["sampler"]["magFilter"] -- ./gltf/loader.can:276 +local min -- ./gltf/loader.can:277 +min = texture["sampler"]["minFilter"] -- ./gltf/loader.can:277 +local mip -- ./gltf/loader.can:278 +if min:match("_mipmap_") then -- ./gltf/loader.can:279 +min, mip = min:match("^(.*)_mipmap_(.*)$") -- ./gltf/loader.can:280 +end -- ./gltf/loader.can:280 +texture["image"] = love["graphics"]["newImage"](texture["source"]["data"], { ["mipmaps"] = not not mip }) -- ./gltf/loader.can:282 +texture["image"]:setFilter(min or "linear", mag) -- ./gltf/loader.can:283 +if mip then -- ./gltf/loader.can:284 +texture["image"]:setMipmapFilter(mip) -- ./gltf/loader.can:284 +end -- ./gltf/loader.can:284 +texture["image"]:setWrap(texture["sampler"]["wrapS"], texture["sampler"]["wrapT"]) -- ./gltf/loader.can:285 +end -- ./gltf/loader.can:285 +t["materials"][0] = { -- ./gltf/loader.can:289 +["pbrMetallicRoughness"] = { -- ./gltf/loader.can:290 +["baseColorFactor"] = { -- ./gltf/loader.can:291 +1, -- ./gltf/loader.can:291 +1, -- ./gltf/loader.can:291 +1, -- ./gltf/loader.can:291 +1 -- ./gltf/loader.can:291 +}, -- ./gltf/loader.can:291 +["metallicFactor"] = 1, -- ./gltf/loader.can:292 +["roughnessFactor"] = 1 -- ./gltf/loader.can:293 +}, -- ./gltf/loader.can:293 +["emissiveFactor"] = { -- ./gltf/loader.can:295 +0, -- ./gltf/loader.can:295 +0, -- ./gltf/loader.can:295 +0 -- ./gltf/loader.can:295 +}, -- ./gltf/loader.can:295 +["alphaMode"] = "OPAQUE", -- ./gltf/loader.can:296 +["alphaCutoff"] = .5, -- ./gltf/loader.can:297 +["doubleSided"] = false -- ./gltf/loader.can:298 +} -- ./gltf/loader.can:298 +for _, material in ipairs(t["materials"]) do -- ./gltf/loader.can:301 +material["pbrMetallicRoughness"] = material["pbrMetallicRoughness"] or ({}) -- ./gltf/loader.can:302 +material["pbrMetallicRoughness"]["baseColorFactor"] = material["pbrMetallicRoughness"]["baseColorFactor"] or ({ -- ./gltf/loader.can:303 +1, -- ./gltf/loader.can:303 +1, -- ./gltf/loader.can:303 +1, -- ./gltf/loader.can:303 +1 -- ./gltf/loader.can:303 +}) -- ./gltf/loader.can:303 +if material["pbrMetallicRoughness"]["baseColorTexture"] then -- ./gltf/loader.can:304 +material["pbrMetallicRoughness"]["baseColorTexture"]["index"] = t["textures"][material["pbrMetallicRoughness"]["baseColorTexture"]["index"] + 1] -- ./gltf/loader.can:305 +material["pbrMetallicRoughness"]["baseColorTexture"]["texCoord"] = material["pbrMetallicRoughness"]["baseColorTexture"]["texCoord"] or (0) -- ./gltf/loader.can:306 +end -- ./gltf/loader.can:306 +material["pbrMetallicRoughness"]["metallicFactor"] = material["pbrMetallicRoughness"]["metallicFactor"] or (1) -- ./gltf/loader.can:308 +material["pbrMetallicRoughness"]["roughnessFactor"] = material["pbrMetallicRoughness"]["roughnessFactor"] or (1) -- ./gltf/loader.can:309 +if material["pbrMetallicRoughness"]["metallicRoughnessTexture"] then -- ./gltf/loader.can:310 +material["pbrMetallicRoughness"]["metallicRoughnessTexture"]["index"] = t["textures"][material["pbrMetallicRoughness"]["metallicRoughnessTexture"]["index"] + 1] -- ./gltf/loader.can:311 +material["pbrMetallicRoughness"]["metallicRoughnessTexture"]["texCoord"] = material["pbrMetallicRoughness"]["metallicRoughnessTexture"]["texCoord"] or (0) -- ./gltf/loader.can:312 +end -- ./gltf/loader.can:312 +if material["normalTexture"] then -- ./gltf/loader.can:314 +material["normalTexture"]["index"] = t["textures"][material["normalTexture"]["index"] + 1] -- ./gltf/loader.can:315 +material["normalTexture"]["texCoord"] = material["normalTexture"]["texCoord"] or (0) -- ./gltf/loader.can:316 +material["normalTexture"]["scale"] = material["normalTexture"]["scale"] or (1) -- ./gltf/loader.can:317 +end -- ./gltf/loader.can:317 +if material["occlusionTexture"] then -- ./gltf/loader.can:319 +material["occlusionTexture"]["index"] = t["textures"][material["occlusionTexture"]["index"] + 1] -- ./gltf/loader.can:320 +material["occlusionTexture"]["texCoord"] = material["occlusionTexture"]["texCoord"] or (0) -- ./gltf/loader.can:321 +material["occlusionTexture"]["strength"] = material["occlusionTexture"]["strength"] or (1) -- ./gltf/loader.can:322 +end -- ./gltf/loader.can:322 +if material["emissiveTexture"] then -- ./gltf/loader.can:324 +material["emissiveTexture"]["index"] = t["textures"][material["emissiveTexture"]["index"] + 1] -- ./gltf/loader.can:325 +material["emissiveTexture"]["texCoord"] = material["emissiveTexture"]["texCoord"] or (0) -- ./gltf/loader.can:326 +end -- ./gltf/loader.can:326 +material["emissiveFactor"] = material["emissiveFactor"] or ({ -- ./gltf/loader.can:328 +0, -- ./gltf/loader.can:328 +0, -- ./gltf/loader.can:328 +0 -- ./gltf/loader.can:328 +}) -- ./gltf/loader.can:328 +material["alphaMode"] = material["alphaMode"] or ("OPAQUE") -- ./gltf/loader.can:329 +material["alphaCutoff"] = material["alphaCutoff"] or (.5) -- ./gltf/loader.can:330 +material["doubleSided"] = material["doubleSided"] or (false) -- ./gltf/loader.can:331 +end -- ./gltf/loader.can:331 +for _, mesh in ipairs(t["meshes"]) do -- ./gltf/loader.can:335 +for _, primitive in ipairs(mesh["primitives"]) do -- ./gltf/loader.can:336 +local vertexformat -- ./gltf/loader.can:337 +vertexformat = {} -- ./gltf/loader.can:337 +local vertices -- ./gltf/loader.can:338 +vertices = {} -- ./gltf/loader.can:338 +for n, v in pairs(primitive["attributes"]) do -- ./gltf/loader.can:339 +local accessor -- ./gltf/loader.can:340 +accessor = t["accessors"][v + 1] -- ./gltf/loader.can:340 +primitive["attributes"][n] = accessor -- ./gltf/loader.can:341 +table["insert"](vertexformat, { -- ./gltf/loader.can:342 +attributeName[n] or n, -- ./gltf/loader.can:342 +accessor["componentType"], -- ./gltf/loader.can:342 +accessor["components"] -- ./gltf/loader.can:342 +}) -- ./gltf/loader.can:342 +for i, x in ipairs(accessor["data"]) do -- ./gltf/loader.can:343 +local vertex -- ./gltf/loader.can:344 +vertex = vertices[i] -- ./gltf/loader.can:344 +if not vertex then -- ./gltf/loader.can:345 +table["insert"](vertices, i, {}) -- ./gltf/loader.can:346 +vertex = vertices[i] -- ./gltf/loader.can:347 +end -- ./gltf/loader.can:347 +for _, c in ipairs(x) do -- ./gltf/loader.can:349 +table["insert"](vertex, c) -- ./gltf/loader.can:350 +end -- ./gltf/loader.can:350 +end -- ./gltf/loader.can:350 +end -- ./gltf/loader.can:350 +if primitive["mode"] then -- ./gltf/loader.can:355 +primitive["mode"] = mode[primitive["mode"]] -- ./gltf/loader.can:356 +else -- ./gltf/loader.can:356 +primitive["mode"] = "triangles" -- ./gltf/loader.can:358 +end -- ./gltf/loader.can:358 +primitive["mesh"] = love["graphics"]["newMesh"](vertexformat, vertices, primitive["mode"]) -- ./gltf/loader.can:361 +if primitive["indices"] then -- ./gltf/loader.can:362 +primitive["indices"] = (function() -- ./gltf/loader.can:363 +local self = {} -- ./gltf/loader.can:363 +for _, i in ipairs(t["accessors"][primitive["indices"] + 1]["data"]) do -- ./gltf/loader.can:363 +self[#self+1] = i + 1 -- ./gltf/loader.can:363 +end -- ./gltf/loader.can:363 +return self -- ./gltf/loader.can:363 +end)() -- ./gltf/loader.can:363 +primitive["mesh"]:setVertexMap(primitive["indices"]) -- ./gltf/loader.can:364 +end -- ./gltf/loader.can:364 +primitive["material"] = t["materials"][(primitive["material"] or - 1) + 1] -- ./gltf/loader.can:367 +if primitive["material"]["pbrMetallicRoughness"]["baseColorTexture"] then -- ./gltf/loader.can:368 +primitive["mesh"]:setTexture(primitive["material"]["pbrMetallicRoughness"]["baseColorTexture"]["index"]["image"]) -- ./gltf/loader.can:369 +end -- ./gltf/loader.can:369 +end -- ./gltf/loader.can:369 +end -- ./gltf/loader.can:369 +for _, camera in ipairs(t["cameras"]) do -- ./gltf/loader.can:377 +if camera["name"] then -- ./gltf/loader.can:378 +t["cameras"][camera["name"]] = camera -- ./gltf/loader.can:378 +end -- ./gltf/loader.can:378 +if camera["type"] == "perspective" then -- ./gltf/loader.can:379 +camera["perspective"]["aspectRatio"] = camera["perspective"]["aspectRatio"] or (16 / 9) -- ./gltf/loader.can:380 +camera["matrix"] = mat4["from_perspective"](camera["perspective"]["yfov"], camera["perspective"]["aspectRatio"], camera["perspective"]["znear"], camera["perspective"]["zfar"]) -- ./gltf/loader.can:381 +elseif camera["type"] == "orthographic" then -- ./gltf/loader.can:382 +camera["matrix"] = mat4["from_ortho"](0, 0, camera["orthographic"]["xmag"], camera["orthographic"]["ymag"], camera["orthographic"]["znear"], camera["orthographic"]["zfar"]) -- ./gltf/loader.can:383 +end -- ./gltf/loader.can:383 +end -- ./gltf/loader.can:383 +return t -- ./gltf/loader.can:395 +end -- ./gltf/loader.can:395 +return gltf -- ./gltf/loader.can:398 diff --git a/ldtk/ldtk.lua b/ldtk/ldtk.lua index c5a0ceb..644513d 100644 --- a/ldtk/ldtk.lua +++ b/ldtk/ldtk.lua @@ -1,489 +1,550 @@ -local lg -- ./ldtk/ldtk.can:38 -lg = (love or {})["graphics"] -- ./ldtk/ldtk.can:38 -local newQuad -- ./ldtk/ldtk.can:39 -if lg then -- ./ldtk/ldtk.can:40 -newQuad = lg["newQuad"] -- ./ldtk/ldtk.can:41 -else -- ./ldtk/ldtk.can:41 -newQuad = function(x, y, w, h, image) -- ./ldtk/ldtk.can:43 -return { -- ./ldtk/ldtk.can:44 -x, -- ./ldtk/ldtk.can:44 -y, -- ./ldtk/ldtk.can:44 -w, -- ./ldtk/ldtk.can:44 -h -- ./ldtk/ldtk.can:44 -} -- ./ldtk/ldtk.can:44 -end -- ./ldtk/ldtk.can:44 -end -- ./ldtk/ldtk.can:44 -local json_decode -- ./ldtk/ldtk.can:49 -json_decode = require((...):gsub("ldtk$", "json"))["decode"] -- ./ldtk/ldtk.can:49 -local readJson -- ./ldtk/ldtk.can:50 -readJson = function(file) -- ./ldtk/ldtk.can:50 -local f -- ./ldtk/ldtk.can:51 -f = assert(io["open"](file, "r")) -- ./ldtk/ldtk.can:51 -local t = json_decode(f:read("*a")) -- ./ldtk/ldtk.can:52 -f:close() -- ./ldtk/ldtk.can:53 -return t -- ./ldtk/ldtk.can:54 -end -- ./ldtk/ldtk.can:54 -local parseColor -- ./ldtk/ldtk.can:58 -parseColor = function(str) -- ./ldtk/ldtk.can:58 -local r, g, b = str:match("^#(..)(..)(..)") -- ./ldtk/ldtk.can:59 -r, g, b = tonumber(r, 16), tonumber(g, 16), tonumber(b, 16) -- ./ldtk/ldtk.can:60 -return { -- ./ldtk/ldtk.can:61 -r / 255, -- ./ldtk/ldtk.can:61 -g / 255, -- ./ldtk/ldtk.can:61 -b / 255 -- ./ldtk/ldtk.can:61 -} -- ./ldtk/ldtk.can:61 -end -- ./ldtk/ldtk.can:61 -local white -- ./ldtk/ldtk.can:63 -white = { -- ./ldtk/ldtk.can:63 -1, -- ./ldtk/ldtk.can:63 -1, -- ./ldtk/ldtk.can:63 -1 -- ./ldtk/ldtk.can:63 -} -- ./ldtk/ldtk.can:63 -local toLua -- ./ldtk/ldtk.can:66 -toLua = function(type, val) -- ./ldtk/ldtk.can:66 -if val == nil then -- ./ldtk/ldtk.can:67 -return val -- ./ldtk/ldtk.can:67 -end -- ./ldtk/ldtk.can:67 -if type:match("^Array%<") then -- ./ldtk/ldtk.can:68 -local itype = type:match("^Array%<(.*)%>$") -- ./ldtk/ldtk.can:69 -for i, v in ipairs(val) do -- ./ldtk/ldtk.can:70 -val[i] = toLua(itype, v) -- ./ldtk/ldtk.can:71 -end -- ./ldtk/ldtk.can:71 -elseif type == "Color" then -- ./ldtk/ldtk.can:73 -return parseColor(val) -- ./ldtk/ldtk.can:74 -elseif type == "Point" then -- ./ldtk/ldtk.can:75 -return { -- ./ldtk/ldtk.can:76 -["x"] = val["cx"], -- ./ldtk/ldtk.can:76 -["y"] = val["cy"] -- ./ldtk/ldtk.can:76 -} -- ./ldtk/ldtk.can:76 -end -- ./ldtk/ldtk.can:76 -return val -- ./ldtk/ldtk.can:78 -end -- ./ldtk/ldtk.can:78 -local getFields -- ./ldtk/ldtk.can:80 -getFields = function(f) -- ./ldtk/ldtk.can:80 -local t = {} -- ./ldtk/ldtk.can:81 -for _, v in ipairs(f) do -- ./ldtk/ldtk.can:82 -t[v["__identifier"]] = toLua(v["__type"], v["__value"]) -- ./ldtk/ldtk.can:83 -end -- ./ldtk/ldtk.can:83 -return t -- ./ldtk/ldtk.can:85 -end -- ./ldtk/ldtk.can:85 -local tileset_mt -- ./ldtk/ldtk.can:88 -local make_cache -- ./ldtk/ldtk.can:91 -make_cache = function(new_fn) -- ./ldtk/ldtk.can:91 -return setmetatable({}, { -- ./ldtk/ldtk.can:92 -["__mode"] = "v", -- ./ldtk/ldtk.can:93 -["__call"] = function(cache, id) -- ./ldtk/ldtk.can:94 -if not cache[id] then -- ./ldtk/ldtk.can:95 -cache[id] = new_fn(id) -- ./ldtk/ldtk.can:96 -end -- ./ldtk/ldtk.can:96 -return cache[id] -- ./ldtk/ldtk.can:98 -end -- ./ldtk/ldtk.can:98 -}) -- ./ldtk/ldtk.can:98 -end -- ./ldtk/ldtk.can:98 -local cache -- ./ldtk/ldtk.can:102 -cache = { -- ./ldtk/ldtk.can:102 -["tileset"] = make_cache(function(tilesetDef) -- ./ldtk/ldtk.can:103 -return tileset_mt["_init"](tilesetDef) -- ./ldtk/ldtk.can:104 -end), -- ./ldtk/ldtk.can:104 -["image"] = make_cache(function(path) -- ./ldtk/ldtk.can:106 -if lg then -- ./ldtk/ldtk.can:107 -return lg["newImage"](path) -- ./ldtk/ldtk.can:108 -else -- ./ldtk/ldtk.can:108 -return path -- ./ldtk/ldtk.can:110 -end -- ./ldtk/ldtk.can:110 -end) -- ./ldtk/ldtk.can:110 -} -- ./ldtk/ldtk.can:110 -tileset_mt = { -- ./ldtk/ldtk.can:118 -["_newQuad"] = function(self, x, y, width, height) -- ./ldtk/ldtk.can:119 -return newQuad(x, y, width, height, self["image"]) -- ./ldtk/ldtk.can:120 -end, -- ./ldtk/ldtk.can:120 -["_getTileQuad"] = function(self, tileid, x, y, size) -- ./ldtk/ldtk.can:122 -if not self["_tileQuads"][tileid] then -- ./ldtk/ldtk.can:123 -self["_tileQuads"][tileid] = self:_newQuad(x, y, size, size) -- ./ldtk/ldtk.can:124 -end -- ./ldtk/ldtk.can:124 -return self["_tileQuads"][tileid] -- ./ldtk/ldtk.can:126 -end, -- ./ldtk/ldtk.can:126 -["_init"] = function(tilesetDef) -- ./ldtk/ldtk.can:128 -local t = { -- ./ldtk/ldtk.can:129 -["image"] = cache["image"](tilesetDef["path"]), -- ./ldtk/ldtk.can:132 -["_tileQuads"] = {} -- ./ldtk/ldtk.can:134 -} -- ./ldtk/ldtk.can:134 -return setmetatable(t, tileset_mt) -- ./ldtk/ldtk.can:136 -end -- ./ldtk/ldtk.can:136 -} -- ./ldtk/ldtk.can:136 -tileset_mt["__index"] = tileset_mt -- ./ldtk/ldtk.can:139 -local layer_mt -- ./ldtk/ldtk.can:146 -layer_mt = { -- ./ldtk/ldtk.can:146 -["draw"] = function(self, x, y) -- ./ldtk/ldtk.can:154 -if x == nil then x = 0 end -- ./ldtk/ldtk.can:154 -if y == nil then y = 0 end -- ./ldtk/ldtk.can:154 -if self["visible"] then -- ./ldtk/ldtk.can:155 -lg["push"]() -- ./ldtk/ldtk.can:156 -lg["translate"](x + self["x"], y + self["y"]) -- ./ldtk/ldtk.can:157 -if self["spritebatch"] then -- ./ldtk/ldtk.can:158 -lg["setColor"](1, 1, 1, self["opacity"]) -- ./ldtk/ldtk.can:159 -lg["draw"](self["spritebatch"]) -- ./ldtk/ldtk.can:160 -elseif self["intTiles"] then -- ./ldtk/ldtk.can:161 -for _, t in ipairs(self["intTiles"]) do -- ./ldtk/ldtk.can:162 -lg["setColor"](t["color"]) -- ./ldtk/ldtk.can:163 -lg["rectangle"]("fill", t["x"], t["y"], t["layer"]["gridSize"], t["layer"]["gridSize"]) -- ./ldtk/ldtk.can:164 -end -- ./ldtk/ldtk.can:164 -elseif self["entities"] then -- ./ldtk/ldtk.can:166 -for _, e in ipairs(self["entities"]) do -- ./ldtk/ldtk.can:167 -if e["draw"] then -- ./ldtk/ldtk.can:168 -e:draw() -- ./ldtk/ldtk.can:168 -end -- ./ldtk/ldtk.can:168 -end -- ./ldtk/ldtk.can:168 -end -- ./ldtk/ldtk.can:168 -lg["pop"]() -- ./ldtk/ldtk.can:171 -end -- ./ldtk/ldtk.can:171 -end, -- ./ldtk/ldtk.can:171 -["_unloadCallbacks"] = function(self, callbacks) -- ./ldtk/ldtk.can:175 -local onRemoveTile = callbacks["onRemoveTile"] -- ./ldtk/ldtk.can:176 -if self["tiles"] and onRemoveTile then -- ./ldtk/ldtk.can:177 -for _, t in ipairs(self["tiles"]) do -- ./ldtk/ldtk.can:178 -onRemoveTile(t) -- ./ldtk/ldtk.can:179 -end -- ./ldtk/ldtk.can:179 -end -- ./ldtk/ldtk.can:179 -local onRemoveIntTile = callbacks["onRemoveIntTile"] -- ./ldtk/ldtk.can:182 -if self["intTiles"] and onRemoveIntTile then -- ./ldtk/ldtk.can:183 -for _, t in ipairs(self["intTiles"]) do -- ./ldtk/ldtk.can:184 -onRemoveIntTile(t) -- ./ldtk/ldtk.can:185 -end -- ./ldtk/ldtk.can:185 -end -- ./ldtk/ldtk.can:185 -local onRemoveEntity = callbacks["onRemoveEntity"] -- ./ldtk/ldtk.can:188 -if self["entities"] and onRemoveEntity then -- ./ldtk/ldtk.can:189 -for _, e in ipairs(self["entities"]) do -- ./ldtk/ldtk.can:190 -onRemoveEntity(e) -- ./ldtk/ldtk.can:191 -end -- ./ldtk/ldtk.can:191 -end -- ./ldtk/ldtk.can:191 -end, -- ./ldtk/ldtk.can:191 -["_init"] = function(layer, level, order, callbacks) -- ./ldtk/ldtk.can:195 -local gridSize -- ./ldtk/ldtk.can:196 -gridSize = layer["__gridSize"] -- ./ldtk/ldtk.can:196 -local t -- ./ldtk/ldtk.can:197 -t = { -- ./ldtk/ldtk.can:197 -["level"] = level, -- ./ldtk/ldtk.can:200 -["identifier"] = layer["__identifier"], -- ./ldtk/ldtk.can:203 -["type"] = layer["__type"], -- ./ldtk/ldtk.can:206 -["visible"] = layer["visible"], -- ./ldtk/ldtk.can:209 -["opacity"] = layer["opacity"], -- ./ldtk/ldtk.can:212 -["order"] = order, -- ./ldtk/ldtk.can:215 -["x"] = layer["__pxTotalOffsetX"], -- ./ldtk/ldtk.can:218 -["y"] = layer["__pxTotalOffsetY"], -- ./ldtk/ldtk.can:221 -["gridSize"] = gridSize, -- ./ldtk/ldtk.can:224 -["gridWidth"] = layer["__cWid"], -- ./ldtk/ldtk.can:227 -["gridHeight"] = layer["__cHei"], -- ./ldtk/ldtk.can:230 -["entities"] = nil, -- ./ldtk/ldtk.can:233 -["tiles"] = nil, -- ./ldtk/ldtk.can:237 -["tileset"] = nil, -- ./ldtk/ldtk.can:241 -["spritebatch"] = nil, -- ./ldtk/ldtk.can:246 -["intTiles"] = nil -- ./ldtk/ldtk.can:250 -} -- ./ldtk/ldtk.can:250 -if layer["__tilesetDefUid"] then -- ./ldtk/ldtk.can:253 -t["tiles"] = {} -- ./ldtk/ldtk.can:254 -local tilesetData = level["project"]["_tilesetData"][layer["__tilesetDefUid"]] -- ./ldtk/ldtk.can:255 -t["tileset"] = cache["tileset"](tilesetData) -- ./ldtk/ldtk.can:256 -local tiles = layer["__type"] == "Tiles" and layer["gridTiles"] or layer["autoLayerTiles"] -- ./ldtk/ldtk.can:257 -local onAddTile = callbacks["onAddTile"] -- ./ldtk/ldtk.can:258 -if lg then -- ./ldtk/ldtk.can:259 -t["spritebatch"] = lg["newSpriteBatch"](t["tileset"]["image"]) -- ./ldtk/ldtk.can:259 -end -- ./ldtk/ldtk.can:259 -for _, tl in ipairs(tiles) do -- ./ldtk/ldtk.can:260 -local quad -- ./ldtk/ldtk.can:261 -quad = t["tileset"]:_getTileQuad(tl["t"], tl["src"][1], tl["src"][2], gridSize) -- ./ldtk/ldtk.can:261 -local sx, sy = 1, 1 -- ./ldtk/ldtk.can:262 -local x, y -- ./ldtk/ldtk.can:263 -x, y = tl["px"][1], tl["px"][2] -- ./ldtk/ldtk.can:263 -local tile -- ./ldtk/ldtk.can:271 -tile = { -- ./ldtk/ldtk.can:271 -["layer"] = t, -- ./ldtk/ldtk.can:274 -["x"] = x, -- ./ldtk/ldtk.can:277 -["y"] = y, -- ./ldtk/ldtk.can:280 -["flipX"] = false, -- ./ldtk/ldtk.can:283 -["flipY"] = false, -- ./ldtk/ldtk.can:286 -["tags"] = tilesetData[tl["t"]]["tags"], -- ./ldtk/ldtk.can:289 -["data"] = tilesetData[tl["t"]]["data"], -- ./ldtk/ldtk.can:292 -["quad"] = quad -- ./ldtk/ldtk.can:296 -} -- ./ldtk/ldtk.can:296 -if tl["f"] == 1 or tl["f"] == 3 then -- ./ldtk/ldtk.can:298 -sx = - 1 -- ./ldtk/ldtk.can:299 -x = x + (gridSize) -- ./ldtk/ldtk.can:300 -tile["flipX"] = true -- ./ldtk/ldtk.can:301 -end -- ./ldtk/ldtk.can:301 -if tl["f"] == 2 or tl["f"] == 3 then -- ./ldtk/ldtk.can:303 -sy = - 1 -- ./ldtk/ldtk.can:304 -y = y + (gridSize) -- ./ldtk/ldtk.can:305 -tile["flipY"] = true -- ./ldtk/ldtk.can:306 -end -- ./ldtk/ldtk.can:306 -if t["spritebatch"] then -- ./ldtk/ldtk.can:308 -t["spritebatch"]:add(quad, x, y, 0, sx, sy) -- ./ldtk/ldtk.can:308 -end -- ./ldtk/ldtk.can:308 -table["insert"](t["tiles"], tile) -- ./ldtk/ldtk.can:309 -if onAddTile then -- ./ldtk/ldtk.can:310 -onAddTile(tile) -- ./ldtk/ldtk.can:310 -end -- ./ldtk/ldtk.can:310 -end -- ./ldtk/ldtk.can:310 -elseif layer["__type"] == "IntGrid" then -- ./ldtk/ldtk.can:313 -t["intTiles"] = {} -- ./ldtk/ldtk.can:314 -local onAddIntTile = callbacks["onAddIntTile"] -- ./ldtk/ldtk.can:315 -local values = level["project"]["_layerDef"][layer["layerDefUid"]]["intGridValues"] -- ./ldtk/ldtk.can:316 -for i, tl in ipairs(layer["intGridCsv"]) do -- ./ldtk/ldtk.can:317 -if tl > 0 then -- ./ldtk/ldtk.can:318 -local y -- ./ldtk/ldtk.can:319 -y = math["floor"]((i - 1) / t["gridWidth"]) * gridSize -- ./ldtk/ldtk.can:319 -local x -- ./ldtk/ldtk.can:320 -x = ((i - 1) % t["gridWidth"]) * gridSize -- ./ldtk/ldtk.can:320 -local tile -- ./ldtk/ldtk.can:328 -tile = { -- ./ldtk/ldtk.can:328 -["layer"] = t, -- ./ldtk/ldtk.can:331 -["x"] = x, -- ./ldtk/ldtk.can:334 -["y"] = y, -- ./ldtk/ldtk.can:337 -["identifier"] = values[tl]["identifier"], -- ./ldtk/ldtk.can:340 -["value"] = tl, -- ./ldtk/ldtk.can:343 -["color"] = values[tl]["color"] -- ./ldtk/ldtk.can:346 -} -- ./ldtk/ldtk.can:346 -table["insert"](t["intTiles"], tile) -- ./ldtk/ldtk.can:348 -if onAddIntTile then -- ./ldtk/ldtk.can:349 -onAddIntTile(tile) -- ./ldtk/ldtk.can:349 -end -- ./ldtk/ldtk.can:349 -end -- ./ldtk/ldtk.can:349 -end -- ./ldtk/ldtk.can:349 -end -- ./ldtk/ldtk.can:349 -if layer["__type"] == "Entities" then -- ./ldtk/ldtk.can:354 -t["entities"] = {} -- ./ldtk/ldtk.can:355 -local onAddEntity = callbacks["onAddEntity"] -- ./ldtk/ldtk.can:356 -for _, e in ipairs(layer["entityInstances"]) do -- ./ldtk/ldtk.can:357 -local entityDef -- ./ldtk/ldtk.can:358 -entityDef = level["project"]["_entityData"][e["defUid"]] -- ./ldtk/ldtk.can:358 -local entity -- ./ldtk/ldtk.can:366 -entity = { -- ./ldtk/ldtk.can:366 -["layer"] = t, -- ./ldtk/ldtk.can:369 -["identifier"] = e["__identifier"], -- ./ldtk/ldtk.can:372 -["x"] = e["px"][1], -- ./ldtk/ldtk.can:375 -["y"] = e["px"][2], -- ./ldtk/ldtk.can:378 -["width"] = e["width"], -- ./ldtk/ldtk.can:381 -["height"] = e["height"], -- ./ldtk/ldtk.can:384 -["sx"] = e["width"] / entityDef["width"], -- ./ldtk/ldtk.can:387 -["sy"] = e["height"] / entityDef["height"], -- ./ldtk/ldtk.can:390 -["pivotX"] = e["__pivot"][1] * e["width"], -- ./ldtk/ldtk.can:393 -["pivotY"] = e["__pivot"][2] * e["height"], -- ./ldtk/ldtk.can:396 -["color"] = entityDef["color"], -- ./ldtk/ldtk.can:399 -["tile"] = nil, -- ./ldtk/ldtk.can:403 -["fields"] = getFields(e["fieldInstances"]), -- ./ldtk/ldtk.can:406 -["draw"] = function(self) -- ./ldtk/ldtk.can:412 -if self["tile"] then -- ./ldtk/ldtk.can:413 -local _, _, w, h -- ./ldtk/ldtk.can:414 -_, _, w, h = self["tile"]["quad"]:getViewport() -- ./ldtk/ldtk.can:414 -lg["setColor"](white) -- ./ldtk/ldtk.can:415 -lg["draw"](self["tile"]["tileset"]["image"], self["tile"]["quad"], self["x"] - self["pivotX"], self["y"] - self["pivotY"], 0, self["width"] / w, self["height"] / h) -- ./ldtk/ldtk.can:416 -else -- ./ldtk/ldtk.can:416 -lg["setColor"](self["color"]) -- ./ldtk/ldtk.can:418 -lg["rectangle"]("line", self["x"] - self["pivotX"], self["y"] - self["pivotY"], self["width"], self["height"]) -- ./ldtk/ldtk.can:419 -end -- ./ldtk/ldtk.can:419 -end -- ./ldtk/ldtk.can:419 -} -- ./ldtk/ldtk.can:419 -if e["__tile"] then -- ./ldtk/ldtk.can:423 -local tileset = cache["tileset"](level["project"]["_tilesetData"][e["__tile"]["tilesetUid"]]) -- ./ldtk/ldtk.can:424 -local srcRect = e["__tile"]["srcRect"] -- ./ldtk/ldtk.can:425 -local quad = tileset:_newQuad(srcRect[1], srcRect[2], srcRect[3], srcRect[4]) -- ./ldtk/ldtk.can:426 -entity["tile"] = { -- ./ldtk/ldtk.can:427 -["tileset"] = tileset, -- ./ldtk/ldtk.can:428 -["quad"] = quad -- ./ldtk/ldtk.can:429 -} -- ./ldtk/ldtk.can:429 -end -- ./ldtk/ldtk.can:429 -table["insert"](t["entities"], entity) -- ./ldtk/ldtk.can:432 -if onAddEntity then -- ./ldtk/ldtk.can:433 -onAddEntity(entity) -- ./ldtk/ldtk.can:433 -end -- ./ldtk/ldtk.can:433 -end -- ./ldtk/ldtk.can:433 -end -- ./ldtk/ldtk.can:433 -return setmetatable(t, layer_mt) -- ./ldtk/ldtk.can:436 -end -- ./ldtk/ldtk.can:436 -} -- ./ldtk/ldtk.can:436 -layer_mt["__index"] = layer_mt -- ./ldtk/ldtk.can:439 -local level_mt -- ./ldtk/ldtk.can:448 -level_mt = { -- ./ldtk/ldtk.can:448 -["draw"] = function(self, x, y) -- ./ldtk/ldtk.can:459 -if x == nil then x = 0 end -- ./ldtk/ldtk.can:459 -if y == nil then y = 0 end -- ./ldtk/ldtk.can:459 -assert(self["loaded"] == true, "level not loaded") -- ./ldtk/ldtk.can:460 -lg["push"]() -- ./ldtk/ldtk.can:461 -lg["translate"](x + self["x"], y + self["y"]) -- ./ldtk/ldtk.can:462 -self:drawBackground() -- ./ldtk/ldtk.can:463 -for _, l in ipairs(self["layers"]) do -- ./ldtk/ldtk.can:465 -l:draw() -- ./ldtk/ldtk.can:466 -end -- ./ldtk/ldtk.can:466 -lg["pop"]() -- ./ldtk/ldtk.can:468 -end, -- ./ldtk/ldtk.can:468 -["drawBackground"] = function(self, x, y) -- ./ldtk/ldtk.can:479 -if x == nil then x = 0 end -- ./ldtk/ldtk.can:479 -if y == nil then y = 0 end -- ./ldtk/ldtk.can:479 -assert(self["loaded"] == true, "level not loaded") -- ./ldtk/ldtk.can:480 -lg["setColor"](self["background"]["color"]) -- ./ldtk/ldtk.can:482 -lg["rectangle"]("fill", x, y, self["width"], self["height"]) -- ./ldtk/ldtk.can:483 -lg["setColor"](white) -- ./ldtk/ldtk.can:485 -local bgImage -- ./ldtk/ldtk.can:486 -bgImage = self["background"]["image"] -- ./ldtk/ldtk.can:486 -if bgImage then -- ./ldtk/ldtk.can:487 -lg["draw"](bgImage["image"], bgImage["quad"], x + bgImage["x"], y + bgImage["y"], 0, bgImage["sx"], bgImage["sy"]) -- ./ldtk/ldtk.can:488 -end -- ./ldtk/ldtk.can:488 -end, -- ./ldtk/ldtk.can:488 -["load"] = function(self, callbacks) -- ./ldtk/ldtk.can:506 -if callbacks == nil then callbacks = {} end -- ./ldtk/ldtk.can:506 -assert(self["loaded"] == false, "level already loaded") -- ./ldtk/ldtk.can:507 -if self["_json"]["bgRelPath"] then -- ./ldtk/ldtk.can:508 -local pos -- ./ldtk/ldtk.can:509 -pos = self["_json"]["__bgPos"] -- ./ldtk/ldtk.can:509 -local cropRect -- ./ldtk/ldtk.can:510 -cropRect = pos["cropRect"] -- ./ldtk/ldtk.can:510 -local image -- ./ldtk/ldtk.can:511 -image = cache["image"](self["project"]["_directory"] .. self["_json"]["bgRelPath"]) -- ./ldtk/ldtk.can:511 -self["background"]["image"] = { -- ./ldtk/ldtk.can:512 -["image"] = image, -- ./ldtk/ldtk.can:513 -["quad"] = newQuad(cropRect[1], cropRect[2], cropRect[3], cropRect[4], image), -- ./ldtk/ldtk.can:514 -["x"] = pos["topLeftPx"][1], -- ./ldtk/ldtk.can:515 -["y"] = pos["topLeftPx"][2], -- ./ldtk/ldtk.can:516 -["sx"] = pos["scale"][1], -- ./ldtk/ldtk.can:517 -["sy"] = pos["scale"][1] -- ./ldtk/ldtk.can:518 -} -- ./ldtk/ldtk.can:518 -end -- ./ldtk/ldtk.can:518 -local layerInstances -- ./ldtk/ldtk.can:521 -if self["_json"]["externalRelPath"] then -- ./ldtk/ldtk.can:522 -layerInstances = readJson(self["project"]["_directory"] .. self["_json"]["externalRelPath"])["layerInstances"] -- ./ldtk/ldtk.can:523 -else -- ./ldtk/ldtk.can:523 -layerInstances = self["_json"]["layerInstances"] -- ./ldtk/ldtk.can:525 -end -- ./ldtk/ldtk.can:525 -self["layers"] = {} -- ./ldtk/ldtk.can:527 -local onAddLayer -- ./ldtk/ldtk.can:528 -onAddLayer = callbacks["onAddLayer"] -- ./ldtk/ldtk.can:528 -for i = # layerInstances, 1, - 1 do -- ./ldtk/ldtk.can:529 -local layer = layer_mt["_init"](layerInstances[i], self, i, callbacks) -- ./ldtk/ldtk.can:530 -table["insert"](self["layers"], layer) -- ./ldtk/ldtk.can:531 -if onAddLayer then -- ./ldtk/ldtk.can:532 -onAddLayer(layer) -- ./ldtk/ldtk.can:532 -end -- ./ldtk/ldtk.can:532 -end -- ./ldtk/ldtk.can:532 -self["loaded"] = true -- ./ldtk/ldtk.can:534 -end, -- ./ldtk/ldtk.can:534 -["unload"] = function(self, callbacks) -- ./ldtk/ldtk.can:547 -if callbacks == nil then callbacks = {} end -- ./ldtk/ldtk.can:547 -assert(self["loaded"] == true, "level not loaded") -- ./ldtk/ldtk.can:548 -local onRemoveLayer -- ./ldtk/ldtk.can:549 -onRemoveLayer = callbacks["onRemoveLayer"] -- ./ldtk/ldtk.can:549 -for _, l in ipairs(self["layers"]) do -- ./ldtk/ldtk.can:550 -l:_unloadCallbacks(callbacks) -- ./ldtk/ldtk.can:551 -if onRemoveLayer then -- ./ldtk/ldtk.can:552 -onRemoveLayer(l) -- ./ldtk/ldtk.can:552 -end -- ./ldtk/ldtk.can:552 -end -- ./ldtk/ldtk.can:552 -self["loaded"] = false -- ./ldtk/ldtk.can:554 -self["background"]["image"] = nil -- ./ldtk/ldtk.can:555 -self["layers"] = nil -- ./ldtk/ldtk.can:556 -end, -- ./ldtk/ldtk.can:556 -["_init"] = function(level, project) -- ./ldtk/ldtk.can:559 -local t -- ./ldtk/ldtk.can:560 -t = { -- ./ldtk/ldtk.can:560 -["project"] = project, -- ./ldtk/ldtk.can:563 -["loaded"] = false, -- ./ldtk/ldtk.can:566 -["identifier"] = level["identifier"], -- ./ldtk/ldtk.can:569 -["x"] = level["worldX"], -- ./ldtk/ldtk.can:572 -["y"] = level["worldY"], -- ./ldtk/ldtk.can:575 -["width"] = level["pxWid"], -- ./ldtk/ldtk.can:578 -["height"] = level["pxHei"], -- ./ldtk/ldtk.can:581 -["fields"] = getFields(level["fieldInstances"]), -- ./ldtk/ldtk.can:584 -["layers"] = nil, -- ./ldtk/ldtk.can:587 -["background"] = { -- ./ldtk/ldtk.can:595 -["color"] = parseColor(level["__bgColor"]), -- ./ldtk/ldtk.can:596 -["image"] = nil -- ./ldtk/ldtk.can:597 -}, -- ./ldtk/ldtk.can:597 -["_json"] = level -- ./ldtk/ldtk.can:601 -} -- ./ldtk/ldtk.can:601 -return setmetatable(t, level_mt) -- ./ldtk/ldtk.can:603 -end -- ./ldtk/ldtk.can:603 -} -- ./ldtk/ldtk.can:603 -level_mt["__index"] = level_mt -- ./ldtk/ldtk.can:606 -local project_mt -- ./ldtk/ldtk.can:613 -project_mt = { ["_init"] = function(project, directory) -- ./ldtk/ldtk.can:614 -assert(project["jsonVersion"] == "0.9.3", ("the map was made with LDtk version %s but the importer is made for 0.9.3"):format(project["jsonVersion"])) -- ./ldtk/ldtk.can:615 -local t -- ./ldtk/ldtk.can:616 -t = { -- ./ldtk/ldtk.can:616 -["levels"] = nil, -- ./ldtk/ldtk.can:619 -["_directory"] = directory, -- ./ldtk/ldtk.can:622 -["_layerDef"] = nil, -- ./ldtk/ldtk.can:623 -["_tilesetData"] = nil, -- ./ldtk/ldtk.can:624 -["_entityData"] = nil -- ./ldtk/ldtk.can:625 -} -- ./ldtk/ldtk.can:625 -t["levels"] = (function() -- ./ldtk/ldtk.can:627 -local self = {} -- ./ldtk/ldtk.can:627 -for _, lvl in ipairs(project["levels"]) do -- ./ldtk/ldtk.can:628 -do -- ./ldtk/ldtk.can:629 -local __CAN_a = table.pack(level_mt["_init"](lvl, t)) -- ./ldtk/ldtk.can:629 -table.move(__CAN_a, 1, __CAN_a.n, #self+1, self) -- ./ldtk/ldtk.can:629 -end -- ./ldtk/ldtk.can:629 -end -- ./ldtk/ldtk.can:629 -return self -- ./ldtk/ldtk.can:629 -end)() -- ./ldtk/ldtk.can:629 -t["_tilesetData"] = (function() -- ./ldtk/ldtk.can:632 -local self = {} -- ./ldtk/ldtk.can:632 -for _, ts in ipairs(project["defs"]["tilesets"]) do -- ./ldtk/ldtk.can:633 -self[ts["uid"]] = { ["path"] = directory .. ts["relPath"] } -- ./ldtk/ldtk.can:635 -local tilesetData = self[ts["uid"]] -- ./ldtk/ldtk.can:637 -for gridx = 0, ts["__cWid"] - 1 do -- ./ldtk/ldtk.can:638 -for gridy = 0, ts["__cHei"] - 1 do -- ./ldtk/ldtk.can:639 -tilesetData[gridx + gridy * ts["__cWid"]] = { -- ./ldtk/ldtk.can:640 -["tags"] = {}, -- ./ldtk/ldtk.can:641 -["data"] = nil -- ./ldtk/ldtk.can:642 -} -- ./ldtk/ldtk.can:642 -end -- ./ldtk/ldtk.can:642 -end -- ./ldtk/ldtk.can:642 -for _, custom in ipairs(ts["customData"]) do -- ./ldtk/ldtk.can:646 -tilesetData[custom["tileId"]]["data"] = custom["data"] -- ./ldtk/ldtk.can:647 -end -- ./ldtk/ldtk.can:647 -for _, tag in ipairs(ts["enumTags"]) do -- ./ldtk/ldtk.can:649 -local value = tag["enumValueId"] -- ./ldtk/ldtk.can:650 -for _, tileId in ipairs(tag["tileIds"]) do -- ./ldtk/ldtk.can:651 -table["insert"](tilesetData[tileId]["tags"], value) -- ./ldtk/ldtk.can:652 -tilesetData[tileId]["tags"][value] = true -- ./ldtk/ldtk.can:653 -end -- ./ldtk/ldtk.can:653 -end -- ./ldtk/ldtk.can:653 -end -- ./ldtk/ldtk.can:653 -return self -- ./ldtk/ldtk.can:653 -end)() -- ./ldtk/ldtk.can:653 -t["_layerDef"] = (function() -- ./ldtk/ldtk.can:658 -local self = {} -- ./ldtk/ldtk.can:658 -for _, lay in ipairs(project["defs"]["layers"]) do -- ./ldtk/ldtk.can:659 -self[lay["uid"]] = { ["intGridValues"] = nil } -- ./ldtk/ldtk.can:661 -local layerDef = self[lay["uid"]] -- ./ldtk/ldtk.can:663 -if lay["__type"] == "IntGrid" then -- ./ldtk/ldtk.can:664 -layerDef["intGridValues"] = (function() -- ./ldtk/ldtk.can:665 -local self = {} -- ./ldtk/ldtk.can:665 -for _, v in ipairs(lay["intGridValues"]) do -- ./ldtk/ldtk.can:666 -self[v["value"]] = { -- ./ldtk/ldtk.can:667 -["color"] = parseColor(v["color"]), -- ./ldtk/ldtk.can:668 -["identifier"] = v["identifier"] -- ./ldtk/ldtk.can:669 -} -- ./ldtk/ldtk.can:669 -end -- ./ldtk/ldtk.can:669 -return self -- ./ldtk/ldtk.can:669 -end)() -- ./ldtk/ldtk.can:669 -end -- ./ldtk/ldtk.can:669 -end -- ./ldtk/ldtk.can:669 -return self -- ./ldtk/ldtk.can:669 -end)() -- ./ldtk/ldtk.can:669 -t["_entityData"] = (function() -- ./ldtk/ldtk.can:676 -local self = {} -- ./ldtk/ldtk.can:676 -for _, ent in ipairs(project["defs"]["entities"]) do -- ./ldtk/ldtk.can:677 -self[ent["uid"]] = { -- ./ldtk/ldtk.can:678 -["color"] = parseColor(ent["color"]), -- ./ldtk/ldtk.can:679 -["width"] = ent["width"], -- ./ldtk/ldtk.can:680 -["height"] = ent["height"] -- ./ldtk/ldtk.can:681 -} -- ./ldtk/ldtk.can:681 -end -- ./ldtk/ldtk.can:681 -return self -- ./ldtk/ldtk.can:681 -end)() -- ./ldtk/ldtk.can:681 -return setmetatable(t, project_mt) -- ./ldtk/ldtk.can:685 -end } -- ./ldtk/ldtk.can:685 -project_mt["__index"] = project_mt -- ./ldtk/ldtk.can:688 -return function(file) -- ./ldtk/ldtk.can:719 -return project_mt["_init"](readJson(file), file:match("^(.-)[^%/%\\]+$")) -- ./ldtk/ldtk.can:720 -end -- ./ldtk/ldtk.can:720 +local lg -- ./ldtk/ldtk.can:47 +lg = (love or {})["graphics"] -- ./ldtk/ldtk.can:47 +local newQuad -- ./ldtk/ldtk.can:48 +if lg then -- ./ldtk/ldtk.can:49 +newQuad = lg["newQuad"] -- ./ldtk/ldtk.can:50 +else -- ./ldtk/ldtk.can:50 +newQuad = function(x, y, w, h, image) -- ./ldtk/ldtk.can:52 +return { -- ./ldtk/ldtk.can:53 +x, -- ./ldtk/ldtk.can:53 +y, -- ./ldtk/ldtk.can:53 +w, -- ./ldtk/ldtk.can:53 +h -- ./ldtk/ldtk.can:53 +} -- ./ldtk/ldtk.can:53 +end -- ./ldtk/ldtk.can:53 +end -- ./ldtk/ldtk.can:53 +local cache -- ./ldtk/ldtk.can:57 +local json_decode -- ./ldtk/ldtk.can:60 +do -- ./ldtk/ldtk.can:62 +local r, json -- ./ldtk/ldtk.can:62 +r, json = pcall(require, "json") -- ./ldtk/ldtk.can:62 +if not r then -- ./ldtk/ldtk.can:63 +json = require((...):gsub("ldtk%.ldtk$", "lib.json")) -- ./ldtk/ldtk.can:63 +end -- ./ldtk/ldtk.can:63 +json_decode = json["decode"] -- ./ldtk/ldtk.can:64 +end -- ./ldtk/ldtk.can:64 +local readJson -- ./ldtk/ldtk.can:66 +readJson = function(file) -- ./ldtk/ldtk.can:66 +local f -- ./ldtk/ldtk.can:67 +f = assert(io["open"](file, "r")) -- ./ldtk/ldtk.can:67 +local t = json_decode(f:read("*a")) -- ./ldtk/ldtk.can:68 +f:close() -- ./ldtk/ldtk.can:69 +return t -- ./ldtk/ldtk.can:70 +end -- ./ldtk/ldtk.can:70 +local parseColor -- ./ldtk/ldtk.can:74 +parseColor = function(str) -- ./ldtk/ldtk.can:74 +local r, g, b = str:match("^#(..)(..)(..)") -- ./ldtk/ldtk.can:75 +r, g, b = tonumber(r, 16), tonumber(g, 16), tonumber(b, 16) -- ./ldtk/ldtk.can:76 +return { -- ./ldtk/ldtk.can:77 +r / 255, -- ./ldtk/ldtk.can:77 +g / 255, -- ./ldtk/ldtk.can:77 +b / 255 -- ./ldtk/ldtk.can:77 +} -- ./ldtk/ldtk.can:77 +end -- ./ldtk/ldtk.can:77 +local white -- ./ldtk/ldtk.can:79 +white = { -- ./ldtk/ldtk.can:79 +1, -- ./ldtk/ldtk.can:79 +1, -- ./ldtk/ldtk.can:79 +1 -- ./ldtk/ldtk.can:79 +} -- ./ldtk/ldtk.can:79 +local makeTilesetRect -- ./ldtk/ldtk.can:82 +makeTilesetRect = function(tilesetRect, project) -- ./ldtk/ldtk.can:82 +local tileset = cache["tileset"](project["_tilesetData"][tilesetRect["tilesetUid"]]) -- ./ldtk/ldtk.can:83 +local quad = tileset:_newQuad(tilesetRect["x"], tilesetRect["y"], tilesetRect["w"], tilesetRect["h"]) -- ./ldtk/ldtk.can:84 +return { -- ./ldtk/ldtk.can:85 +["tileset"] = tileset, -- ./ldtk/ldtk.can:86 +["quad"] = quad -- ./ldtk/ldtk.can:87 +} -- ./ldtk/ldtk.can:87 +end -- ./ldtk/ldtk.can:87 +local toLua -- ./ldtk/ldtk.can:92 +toLua = function(type, val, parent_entity) -- ./ldtk/ldtk.can:92 +if val == nil then -- ./ldtk/ldtk.can:93 +return val -- ./ldtk/ldtk.can:93 +end -- ./ldtk/ldtk.can:93 +if type:match("^Array%<") then -- ./ldtk/ldtk.can:94 +local itype = type:match("^Array%<(.*)%>$") -- ./ldtk/ldtk.can:95 +for i, v in ipairs(val) do -- ./ldtk/ldtk.can:96 +val[i] = toLua(itype, v, parent_entity) -- ./ldtk/ldtk.can:97 +end -- ./ldtk/ldtk.can:97 +elseif type == "Color" then -- ./ldtk/ldtk.can:99 +return parseColor(val) -- ./ldtk/ldtk.can:100 +elseif type == "Point" then -- ./ldtk/ldtk.can:101 +assert(parent_entity, "AFAIK, it's not possible to have a Point field in something that's not an entity") -- ./ldtk/ldtk.can:102 +return { -- ./ldtk/ldtk.can:103 +["x"] = val["cx"] * parent_entity["layer"]["gridSize"], -- ./ldtk/ldtk.can:104 +["y"] = val["cy"] * parent_entity["layer"]["gridSize"] -- ./ldtk/ldtk.can:105 +} -- ./ldtk/ldtk.can:105 +elseif type == "Tile" then -- ./ldtk/ldtk.can:107 +assert(parent_entity, "AFAIK, it's not possible to have a Tile field in something that's not an entity") -- ./ldtk/ldtk.can:108 +return makeTilesetRect(val, parent_entity["layer"]["level"]["project"]) -- ./ldtk/ldtk.can:109 +elseif type == "EntityRef" then -- ./ldtk/ldtk.can:110 +assert(parent_entity, "AFAIK, it's not possible to have an EntityRef field in something that's not an entity") -- ./ldtk/ldtk.can:111 +local entityRef = setmetatable({ -- ./ldtk/ldtk.can:112 +["level"] = parent_entity["layer"]["level"]["project"]["levels"][val["levelIid"]], -- ./ldtk/ldtk.can:113 +["layerIid"] = val["layerIid"], -- ./ldtk/ldtk.can:114 +["entityIid"] = val["entityIid"], -- ./ldtk/ldtk.can:115 +["entity"] = nil -- ./ldtk/ldtk.can:116 +}, { ["__index"] = function(self, k) -- ./ldtk/ldtk.can:118 +if self["level"]["loaded"] then -- ./ldtk/ldtk.can:119 +if k == "entity" then -- ./ldtk/ldtk.can:120 +self["entity"] = self["level"]["layers"][self["layerIid"]]["entities"][self["entityIid"]] -- ./ldtk/ldtk.can:121 +return self["entity"] -- ./ldtk/ldtk.can:122 +end -- ./ldtk/ldtk.can:122 +end -- ./ldtk/ldtk.can:122 +return nil -- ./ldtk/ldtk.can:125 +end }) -- ./ldtk/ldtk.can:125 +return entityRef -- ./ldtk/ldtk.can:128 +end -- ./ldtk/ldtk.can:128 +return val -- ./ldtk/ldtk.can:130 +end -- ./ldtk/ldtk.can:130 +local getFields -- ./ldtk/ldtk.can:132 +getFields = function(f, parent_entity) -- ./ldtk/ldtk.can:132 +local t = {} -- ./ldtk/ldtk.can:133 +for _, v in ipairs(f) do -- ./ldtk/ldtk.can:134 +t[v["__identifier"]] = toLua(v["__type"], v["__value"], parent_entity) -- ./ldtk/ldtk.can:135 +end -- ./ldtk/ldtk.can:135 +return t -- ./ldtk/ldtk.can:137 +end -- ./ldtk/ldtk.can:137 +local tileset_mt -- ./ldtk/ldtk.can:140 +local make_cache -- ./ldtk/ldtk.can:143 +make_cache = function(new_fn) -- ./ldtk/ldtk.can:143 +return setmetatable({}, { -- ./ldtk/ldtk.can:144 +["__mode"] = "v", -- ./ldtk/ldtk.can:145 +["__call"] = function(cache, id) -- ./ldtk/ldtk.can:146 +if not cache[id] then -- ./ldtk/ldtk.can:147 +cache[id] = new_fn(id) -- ./ldtk/ldtk.can:148 +end -- ./ldtk/ldtk.can:148 +return cache[id] -- ./ldtk/ldtk.can:150 +end -- ./ldtk/ldtk.can:150 +}) -- ./ldtk/ldtk.can:150 +end -- ./ldtk/ldtk.can:150 +cache = { -- ./ldtk/ldtk.can:154 +["tileset"] = make_cache(function(tilesetDef) -- ./ldtk/ldtk.can:155 +return tileset_mt["_init"](tilesetDef) -- ./ldtk/ldtk.can:156 +end), -- ./ldtk/ldtk.can:156 +["image"] = make_cache(function(path) -- ./ldtk/ldtk.can:158 +if lg then -- ./ldtk/ldtk.can:159 +return lg["newImage"](path) -- ./ldtk/ldtk.can:160 +else -- ./ldtk/ldtk.can:160 +return path -- ./ldtk/ldtk.can:162 +end -- ./ldtk/ldtk.can:162 +end) -- ./ldtk/ldtk.can:162 +} -- ./ldtk/ldtk.can:162 +tileset_mt = { -- ./ldtk/ldtk.can:170 +["_newQuad"] = function(self, x, y, width, height) -- ./ldtk/ldtk.can:171 +return newQuad(x, y, width, height, self["image"]) -- ./ldtk/ldtk.can:172 +end, -- ./ldtk/ldtk.can:172 +["_getTileQuad"] = function(self, tileid, x, y, size) -- ./ldtk/ldtk.can:174 +if not self["_tileQuads"][tileid] then -- ./ldtk/ldtk.can:175 +self["_tileQuads"][tileid] = self:_newQuad(x, y, size, size) -- ./ldtk/ldtk.can:176 +end -- ./ldtk/ldtk.can:176 +return self["_tileQuads"][tileid] -- ./ldtk/ldtk.can:178 +end, -- ./ldtk/ldtk.can:178 +["_init"] = function(tilesetDef) -- ./ldtk/ldtk.can:180 +assert(not tilesetDef["embedAtlas"], "cannot load a tileset that use an internal LDtk atlas image, please use external tileset images") -- ./ldtk/ldtk.can:181 +assert(tilesetDef["path"], "cannot load a tileset that has no image associated") -- ./ldtk/ldtk.can:182 +local t = { -- ./ldtk/ldtk.can:183 +["image"] = cache["image"](tilesetDef["path"]), -- ./ldtk/ldtk.can:186 +["tags"] = tilesetDef["tags"], -- ./ldtk/ldtk.can:190 +["_tileQuads"] = {} -- ./ldtk/ldtk.can:192 +} -- ./ldtk/ldtk.can:192 +return setmetatable(t, tileset_mt) -- ./ldtk/ldtk.can:194 +end -- ./ldtk/ldtk.can:194 +} -- ./ldtk/ldtk.can:194 +tileset_mt["__index"] = tileset_mt -- ./ldtk/ldtk.can:197 +local layer_mt -- ./ldtk/ldtk.can:204 +layer_mt = { -- ./ldtk/ldtk.can:204 +["draw"] = function(self, x, y) -- ./ldtk/ldtk.can:212 +if x == nil then x = 0 end -- ./ldtk/ldtk.can:212 +if y == nil then y = 0 end -- ./ldtk/ldtk.can:212 +if self["visible"] then -- ./ldtk/ldtk.can:213 +lg["push"]() -- ./ldtk/ldtk.can:214 +lg["translate"](x + self["x"], y + self["y"]) -- ./ldtk/ldtk.can:215 +if self["spritebatch"] then -- ./ldtk/ldtk.can:216 +lg["setColor"](1, 1, 1, self["opacity"]) -- ./ldtk/ldtk.can:217 +lg["draw"](self["spritebatch"]) -- ./ldtk/ldtk.can:218 +elseif self["intTiles"] then -- ./ldtk/ldtk.can:219 +for _, t in ipairs(self["intTiles"]) do -- ./ldtk/ldtk.can:220 +lg["setColor"](t["color"]) -- ./ldtk/ldtk.can:221 +lg["rectangle"]("fill", t["x"], t["y"], t["layer"]["gridSize"], t["layer"]["gridSize"]) -- ./ldtk/ldtk.can:222 +end -- ./ldtk/ldtk.can:222 +elseif self["entities"] then -- ./ldtk/ldtk.can:224 +for _, e in ipairs(self["entities"]) do -- ./ldtk/ldtk.can:225 +if e["draw"] then -- ./ldtk/ldtk.can:226 +e:draw() -- ./ldtk/ldtk.can:226 +end -- ./ldtk/ldtk.can:226 +end -- ./ldtk/ldtk.can:226 +end -- ./ldtk/ldtk.can:226 +lg["pop"]() -- ./ldtk/ldtk.can:229 +end -- ./ldtk/ldtk.can:229 +end, -- ./ldtk/ldtk.can:229 +["_unloadCallbacks"] = function(self, callbacks) -- ./ldtk/ldtk.can:233 +local onRemoveTile = callbacks["onRemoveTile"] -- ./ldtk/ldtk.can:234 +if self["tiles"] and onRemoveTile then -- ./ldtk/ldtk.can:235 +for _, t in ipairs(self["tiles"]) do -- ./ldtk/ldtk.can:236 +onRemoveTile(t) -- ./ldtk/ldtk.can:237 +end -- ./ldtk/ldtk.can:237 +end -- ./ldtk/ldtk.can:237 +local onRemoveIntTile = callbacks["onRemoveIntTile"] -- ./ldtk/ldtk.can:240 +if self["intTiles"] and onRemoveIntTile then -- ./ldtk/ldtk.can:241 +for _, t in ipairs(self["intTiles"]) do -- ./ldtk/ldtk.can:242 +onRemoveIntTile(t) -- ./ldtk/ldtk.can:243 +end -- ./ldtk/ldtk.can:243 +end -- ./ldtk/ldtk.can:243 +local onRemoveEntity = callbacks["onRemoveEntity"] -- ./ldtk/ldtk.can:246 +if self["entities"] and onRemoveEntity then -- ./ldtk/ldtk.can:247 +for _, e in ipairs(self["entities"]) do -- ./ldtk/ldtk.can:248 +onRemoveEntity(e) -- ./ldtk/ldtk.can:249 +end -- ./ldtk/ldtk.can:249 +end -- ./ldtk/ldtk.can:249 +end, -- ./ldtk/ldtk.can:249 +["_init"] = function(layer, level, order, callbacks) -- ./ldtk/ldtk.can:253 +local layerDef = level["project"]["_layerDef"][layer["layerDefUid"]] -- ./ldtk/ldtk.can:254 +local gridSize -- ./ldtk/ldtk.can:255 +gridSize = layer["__gridSize"] -- ./ldtk/ldtk.can:255 +local t -- ./ldtk/ldtk.can:256 +t = { -- ./ldtk/ldtk.can:256 +["level"] = level, -- ./ldtk/ldtk.can:259 +["iid"] = layer["iid"], -- ./ldtk/ldtk.can:262 +["identifier"] = layer["__identifier"], -- ./ldtk/ldtk.can:265 +["type"] = layer["__type"], -- ./ldtk/ldtk.can:268 +["visible"] = layer["visible"], -- ./ldtk/ldtk.can:271 +["opacity"] = layer["opacity"], -- ./ldtk/ldtk.can:274 +["order"] = order, -- ./ldtk/ldtk.can:277 +["x"] = layer["__pxTotalOffsetX"], -- ./ldtk/ldtk.can:280 +["y"] = layer["__pxTotalOffsetY"], -- ./ldtk/ldtk.can:283 +["gridSize"] = gridSize, -- ./ldtk/ldtk.can:286 +["gridWidth"] = layer["__cWid"], -- ./ldtk/ldtk.can:289 +["gridHeight"] = layer["__cHei"], -- ./ldtk/ldtk.can:292 +["parallaxFactorX"] = layerDef["parallaxFactorX"], -- ./ldtk/ldtk.can:295 +["parallaxFactorY"] = layerDef["parallaxFactorY"], -- ./ldtk/ldtk.can:298 +["parallaxScaling"] = layerDef["parallaxScaling"], -- ./ldtk/ldtk.can:301 +["entities"] = nil, -- ./ldtk/ldtk.can:305 +["tiles"] = nil, -- ./ldtk/ldtk.can:309 +["tileset"] = nil, -- ./ldtk/ldtk.can:313 +["spritebatch"] = nil, -- ./ldtk/ldtk.can:318 +["intTiles"] = nil -- ./ldtk/ldtk.can:322 +} -- ./ldtk/ldtk.can:322 +if layer["__tilesetDefUid"] then -- ./ldtk/ldtk.can:325 +t["tiles"] = {} -- ./ldtk/ldtk.can:326 +local tilesetData = level["project"]["_tilesetData"][layer["__tilesetDefUid"]] -- ./ldtk/ldtk.can:327 +t["tileset"] = cache["tileset"](tilesetData) -- ./ldtk/ldtk.can:328 +local tiles = layer["__type"] == "Tiles" and layer["gridTiles"] or layer["autoLayerTiles"] -- ./ldtk/ldtk.can:329 +local onAddTile = callbacks["onAddTile"] -- ./ldtk/ldtk.can:330 +if lg then -- ./ldtk/ldtk.can:331 +t["spritebatch"] = lg["newSpriteBatch"](t["tileset"]["image"]) -- ./ldtk/ldtk.can:331 +end -- ./ldtk/ldtk.can:331 +for _, tl in ipairs(tiles) do -- ./ldtk/ldtk.can:332 +local quad -- ./ldtk/ldtk.can:333 +quad = t["tileset"]:_getTileQuad(tl["t"], tl["src"][1], tl["src"][2], gridSize) -- ./ldtk/ldtk.can:333 +local sx, sy = 1, 1 -- ./ldtk/ldtk.can:334 +local x, y -- ./ldtk/ldtk.can:335 +x, y = tl["px"][1], tl["px"][2] -- ./ldtk/ldtk.can:335 +local tile -- ./ldtk/ldtk.can:343 +tile = { -- ./ldtk/ldtk.can:343 +["layer"] = t, -- ./ldtk/ldtk.can:346 +["x"] = x, -- ./ldtk/ldtk.can:349 +["y"] = y, -- ./ldtk/ldtk.can:352 +["flipX"] = false, -- ./ldtk/ldtk.can:355 +["flipY"] = false, -- ./ldtk/ldtk.can:358 +["tags"] = tilesetData[tl["t"]]["enumTags"], -- ./ldtk/ldtk.can:361 +["data"] = tilesetData[tl["t"]]["data"], -- ./ldtk/ldtk.can:364 +["quad"] = quad -- ./ldtk/ldtk.can:368 +} -- ./ldtk/ldtk.can:368 +if tl["f"] == 1 or tl["f"] == 3 then -- ./ldtk/ldtk.can:370 +sx = - 1 -- ./ldtk/ldtk.can:371 +x = x + (gridSize) -- ./ldtk/ldtk.can:372 +tile["flipX"] = true -- ./ldtk/ldtk.can:373 +end -- ./ldtk/ldtk.can:373 +if tl["f"] == 2 or tl["f"] == 3 then -- ./ldtk/ldtk.can:375 +sy = - 1 -- ./ldtk/ldtk.can:376 +y = y + (gridSize) -- ./ldtk/ldtk.can:377 +tile["flipY"] = true -- ./ldtk/ldtk.can:378 +end -- ./ldtk/ldtk.can:378 +if t["spritebatch"] then -- ./ldtk/ldtk.can:380 +t["spritebatch"]:add(quad, x, y, 0, sx, sy) -- ./ldtk/ldtk.can:380 +end -- ./ldtk/ldtk.can:380 +table["insert"](t["tiles"], tile) -- ./ldtk/ldtk.can:381 +if onAddTile then -- ./ldtk/ldtk.can:382 +onAddTile(tile) -- ./ldtk/ldtk.can:382 +end -- ./ldtk/ldtk.can:382 +end -- ./ldtk/ldtk.can:382 +elseif layer["__type"] == "IntGrid" then -- ./ldtk/ldtk.can:385 +t["intTiles"] = {} -- ./ldtk/ldtk.can:386 +local onAddIntTile = callbacks["onAddIntTile"] -- ./ldtk/ldtk.can:387 +local values = layerDef["intGridValues"] -- ./ldtk/ldtk.can:388 +for i, tl in ipairs(layer["intGridCsv"]) do -- ./ldtk/ldtk.can:389 +if tl > 0 then -- ./ldtk/ldtk.can:390 +local y -- ./ldtk/ldtk.can:391 +y = math["floor"]((i - 1) / t["gridWidth"]) * gridSize -- ./ldtk/ldtk.can:391 +local x -- ./ldtk/ldtk.can:392 +x = ((i - 1) % t["gridWidth"]) * gridSize -- ./ldtk/ldtk.can:392 +local tile -- ./ldtk/ldtk.can:400 +tile = { -- ./ldtk/ldtk.can:400 +["layer"] = t, -- ./ldtk/ldtk.can:403 +["x"] = x, -- ./ldtk/ldtk.can:406 +["y"] = y, -- ./ldtk/ldtk.can:409 +["identifier"] = values[tl]["identifier"], -- ./ldtk/ldtk.can:412 +["value"] = tl, -- ./ldtk/ldtk.can:415 +["color"] = values[tl]["color"] -- ./ldtk/ldtk.can:418 +} -- ./ldtk/ldtk.can:418 +table["insert"](t["intTiles"], tile) -- ./ldtk/ldtk.can:420 +if onAddIntTile then -- ./ldtk/ldtk.can:421 +onAddIntTile(tile) -- ./ldtk/ldtk.can:421 +end -- ./ldtk/ldtk.can:421 +end -- ./ldtk/ldtk.can:421 +end -- ./ldtk/ldtk.can:421 +end -- ./ldtk/ldtk.can:421 +if layer["__type"] == "Entities" then -- ./ldtk/ldtk.can:426 +t["entities"] = {} -- ./ldtk/ldtk.can:427 +local onAddEntity = callbacks["onAddEntity"] -- ./ldtk/ldtk.can:428 +for _, e in ipairs(layer["entityInstances"]) do -- ./ldtk/ldtk.can:429 +local entityDef -- ./ldtk/ldtk.can:430 +entityDef = level["project"]["_entityData"][e["defUid"]] -- ./ldtk/ldtk.can:430 +local entity -- ./ldtk/ldtk.can:438 +entity = { -- ./ldtk/ldtk.can:438 +["layer"] = t, -- ./ldtk/ldtk.can:441 +["iid"] = e["iid"], -- ./ldtk/ldtk.can:444 +["identifier"] = e["__identifier"], -- ./ldtk/ldtk.can:447 +["x"] = e["px"][1], -- ./ldtk/ldtk.can:450 +["y"] = e["px"][2], -- ./ldtk/ldtk.can:453 +["width"] = e["width"], -- ./ldtk/ldtk.can:456 +["height"] = e["height"], -- ./ldtk/ldtk.can:459 +["sx"] = e["width"] / entityDef["width"], -- ./ldtk/ldtk.can:462 +["sy"] = e["height"] / entityDef["height"], -- ./ldtk/ldtk.can:465 +["pivotX"] = e["__pivot"][1] * e["width"], -- ./ldtk/ldtk.can:468 +["pivotY"] = e["__pivot"][2] * e["height"], -- ./ldtk/ldtk.can:471 +["color"] = parseColor(e["__smartColor"]), -- ./ldtk/ldtk.can:474 +["tile"] = nil, -- ./ldtk/ldtk.can:478 +["tags"] = e["__tags"], -- ./ldtk/ldtk.can:481 +["fields"] = nil, -- ./ldtk/ldtk.can:484 +["draw"] = function(self) -- ./ldtk/ldtk.can:490 +if self["tile"] then -- ./ldtk/ldtk.can:491 +local _, _, w, h -- ./ldtk/ldtk.can:492 +_, _, w, h = self["tile"]["quad"]:getViewport() -- ./ldtk/ldtk.can:492 +lg["setColor"](white) -- ./ldtk/ldtk.can:493 +lg["draw"](self["tile"]["tileset"]["image"], self["tile"]["quad"], self["x"] - self["pivotX"], self["y"] - self["pivotY"], 0, self["width"] / w, self["height"] / h) -- ./ldtk/ldtk.can:494 +else -- ./ldtk/ldtk.can:494 +lg["setColor"](self["color"]) -- ./ldtk/ldtk.can:496 +lg["rectangle"]("line", self["x"] - self["pivotX"], self["y"] - self["pivotY"], self["width"], self["height"]) -- ./ldtk/ldtk.can:497 +end -- ./ldtk/ldtk.can:497 +end -- ./ldtk/ldtk.can:497 +} -- ./ldtk/ldtk.can:497 +if e["__tile"] then -- ./ldtk/ldtk.can:501 +entity["tile"] = makeTilesetRect(e["__tile"], level["project"]) -- ./ldtk/ldtk.can:502 +end -- ./ldtk/ldtk.can:502 +for _, tag in ipairs(entity["tags"]) do -- ./ldtk/ldtk.can:504 +entity["tags"][tag] = true -- ./ldtk/ldtk.can:505 +end -- ./ldtk/ldtk.can:505 +entity["fields"] = getFields(e["fieldInstances"], entity) -- ./ldtk/ldtk.can:507 +t["entities"][entity["iid"]] = entity -- ./ldtk/ldtk.can:508 +table["insert"](t["entities"], entity) -- ./ldtk/ldtk.can:509 +if onAddEntity then -- ./ldtk/ldtk.can:510 +onAddEntity(entity) -- ./ldtk/ldtk.can:510 +end -- ./ldtk/ldtk.can:510 +end -- ./ldtk/ldtk.can:510 +end -- ./ldtk/ldtk.can:510 +return setmetatable(t, layer_mt) -- ./ldtk/ldtk.can:513 +end -- ./ldtk/ldtk.can:513 +} -- ./ldtk/ldtk.can:513 +layer_mt["__index"] = layer_mt -- ./ldtk/ldtk.can:516 +local level_mt -- ./ldtk/ldtk.can:525 +level_mt = { -- ./ldtk/ldtk.can:525 +["draw"] = function(self, x, y) -- ./ldtk/ldtk.can:536 +if x == nil then x = 0 end -- ./ldtk/ldtk.can:536 +if y == nil then y = 0 end -- ./ldtk/ldtk.can:536 +assert(self["loaded"] == true, "level not loaded") -- ./ldtk/ldtk.can:537 +lg["push"]() -- ./ldtk/ldtk.can:538 +lg["translate"](x + self["x"], y + self["y"]) -- ./ldtk/ldtk.can:539 +self:drawBackground() -- ./ldtk/ldtk.can:540 +for _, l in ipairs(self["layers"]) do -- ./ldtk/ldtk.can:542 +l:draw() -- ./ldtk/ldtk.can:543 +end -- ./ldtk/ldtk.can:543 +lg["pop"]() -- ./ldtk/ldtk.can:545 +end, -- ./ldtk/ldtk.can:545 +["drawBackground"] = function(self, x, y) -- ./ldtk/ldtk.can:556 +if x == nil then x = 0 end -- ./ldtk/ldtk.can:556 +if y == nil then y = 0 end -- ./ldtk/ldtk.can:556 +assert(self["loaded"] == true, "level not loaded") -- ./ldtk/ldtk.can:557 +lg["setColor"](self["background"]["color"]) -- ./ldtk/ldtk.can:559 +lg["rectangle"]("fill", x, y, self["width"], self["height"]) -- ./ldtk/ldtk.can:560 +lg["setColor"](white) -- ./ldtk/ldtk.can:562 +local bgImage -- ./ldtk/ldtk.can:563 +bgImage = self["background"]["image"] -- ./ldtk/ldtk.can:563 +if bgImage then -- ./ldtk/ldtk.can:564 +lg["draw"](bgImage["image"], bgImage["quad"], x + bgImage["x"], y + bgImage["y"], 0, bgImage["sx"], bgImage["sy"]) -- ./ldtk/ldtk.can:565 +end -- ./ldtk/ldtk.can:565 +end, -- ./ldtk/ldtk.can:565 +["load"] = function(self, callbacks) -- ./ldtk/ldtk.can:583 +if callbacks == nil then callbacks = {} end -- ./ldtk/ldtk.can:583 +assert(self["loaded"] == false, "level already loaded") -- ./ldtk/ldtk.can:584 +if self["_json"]["bgRelPath"] then -- ./ldtk/ldtk.can:585 +local pos -- ./ldtk/ldtk.can:586 +pos = self["_json"]["__bgPos"] -- ./ldtk/ldtk.can:586 +local cropRect -- ./ldtk/ldtk.can:587 +cropRect = pos["cropRect"] -- ./ldtk/ldtk.can:587 +local image -- ./ldtk/ldtk.can:588 +image = cache["image"](self["project"]["_directory"] .. self["_json"]["bgRelPath"]) -- ./ldtk/ldtk.can:588 +self["background"]["image"] = { -- ./ldtk/ldtk.can:589 +["image"] = image, -- ./ldtk/ldtk.can:590 +["quad"] = newQuad(cropRect[1], cropRect[2], cropRect[3], cropRect[4], image), -- ./ldtk/ldtk.can:591 +["x"] = pos["topLeftPx"][1], -- ./ldtk/ldtk.can:592 +["y"] = pos["topLeftPx"][2], -- ./ldtk/ldtk.can:593 +["sx"] = pos["scale"][1], -- ./ldtk/ldtk.can:594 +["sy"] = pos["scale"][1] -- ./ldtk/ldtk.can:595 +} -- ./ldtk/ldtk.can:595 +end -- ./ldtk/ldtk.can:595 +local layerInstances -- ./ldtk/ldtk.can:598 +if self["_json"]["externalRelPath"] then -- ./ldtk/ldtk.can:599 +layerInstances = readJson(self["project"]["_directory"] .. self["_json"]["externalRelPath"])["layerInstances"] -- ./ldtk/ldtk.can:600 +else -- ./ldtk/ldtk.can:600 +layerInstances = self["_json"]["layerInstances"] -- ./ldtk/ldtk.can:602 +end -- ./ldtk/ldtk.can:602 +self["layers"] = {} -- ./ldtk/ldtk.can:604 +local onAddLayer -- ./ldtk/ldtk.can:605 +onAddLayer = callbacks["onAddLayer"] -- ./ldtk/ldtk.can:605 +for i = # layerInstances, 1, - 1 do -- ./ldtk/ldtk.can:606 +local layer = layer_mt["_init"](layerInstances[i], self, i, callbacks) -- ./ldtk/ldtk.can:607 +self["layers"][layer["iid"]] = layer -- ./ldtk/ldtk.can:608 +table["insert"](self["layers"], layer) -- ./ldtk/ldtk.can:609 +if onAddLayer then -- ./ldtk/ldtk.can:610 +onAddLayer(layer) -- ./ldtk/ldtk.can:610 +end -- ./ldtk/ldtk.can:610 +end -- ./ldtk/ldtk.can:610 +self["loaded"] = true -- ./ldtk/ldtk.can:612 +end, -- ./ldtk/ldtk.can:612 +["unload"] = function(self, callbacks) -- ./ldtk/ldtk.can:625 +if callbacks == nil then callbacks = {} end -- ./ldtk/ldtk.can:625 +assert(self["loaded"] == true, "level not loaded") -- ./ldtk/ldtk.can:626 +local onRemoveLayer -- ./ldtk/ldtk.can:627 +onRemoveLayer = callbacks["onRemoveLayer"] -- ./ldtk/ldtk.can:627 +for _, l in ipairs(self["layers"]) do -- ./ldtk/ldtk.can:628 +l:_unloadCallbacks(callbacks) -- ./ldtk/ldtk.can:629 +if onRemoveLayer then -- ./ldtk/ldtk.can:630 +onRemoveLayer(l) -- ./ldtk/ldtk.can:630 +end -- ./ldtk/ldtk.can:630 +end -- ./ldtk/ldtk.can:630 +self["loaded"] = false -- ./ldtk/ldtk.can:632 +self["background"]["image"] = nil -- ./ldtk/ldtk.can:633 +self["layers"] = nil -- ./ldtk/ldtk.can:634 +end, -- ./ldtk/ldtk.can:634 +["_init"] = function(level, project) -- ./ldtk/ldtk.can:637 +local t -- ./ldtk/ldtk.can:638 +t = { -- ./ldtk/ldtk.can:638 +["project"] = project, -- ./ldtk/ldtk.can:641 +["loaded"] = false, -- ./ldtk/ldtk.can:644 +["iid"] = level["iid"], -- ./ldtk/ldtk.can:647 +["identifier"] = level["identifier"], -- ./ldtk/ldtk.can:650 +["depth"] = level["worldDepth"], -- ./ldtk/ldtk.can:653 +["x"] = level["worldX"], -- ./ldtk/ldtk.can:657 +["y"] = level["worldY"], -- ./ldtk/ldtk.can:661 +["width"] = level["pxWid"], -- ./ldtk/ldtk.can:664 +["height"] = level["pxHei"], -- ./ldtk/ldtk.can:667 +["fields"] = getFields(level["fieldInstances"]), -- ./ldtk/ldtk.can:670 +["layers"] = nil, -- ./ldtk/ldtk.can:674 +["background"] = { -- ./ldtk/ldtk.can:682 +["color"] = parseColor(level["__bgColor"]), -- ./ldtk/ldtk.can:683 +["image"] = nil -- ./ldtk/ldtk.can:684 +}, -- ./ldtk/ldtk.can:684 +["_json"] = level -- ./ldtk/ldtk.can:688 +} -- ./ldtk/ldtk.can:688 +return setmetatable(t, level_mt) -- ./ldtk/ldtk.can:690 +end -- ./ldtk/ldtk.can:690 +} -- ./ldtk/ldtk.can:690 +level_mt["__index"] = level_mt -- ./ldtk/ldtk.can:693 +local project_mt -- ./ldtk/ldtk.can:700 +project_mt = { ["_init"] = function(project, directory) -- ./ldtk/ldtk.can:701 +assert(project["jsonVersion"]:match("^1%.1%."), ("the map was made with LDtk version %s but the importer is made for 1.1.3"):format(project["jsonVersion"])) -- ./ldtk/ldtk.can:702 +local t -- ./ldtk/ldtk.can:703 +t = { -- ./ldtk/ldtk.can:703 +["levels"] = nil, -- ./ldtk/ldtk.can:707 +["_directory"] = directory, -- ./ldtk/ldtk.can:710 +["_layerDef"] = nil, -- ./ldtk/ldtk.can:711 +["_tilesetData"] = nil, -- ./ldtk/ldtk.can:712 +["_entityData"] = nil -- ./ldtk/ldtk.can:713 +} -- ./ldtk/ldtk.can:713 +t["levels"] = (function() -- ./ldtk/ldtk.can:715 +local self = {} -- ./ldtk/ldtk.can:715 +for _, lvl in ipairs(project["levels"]) do -- ./ldtk/ldtk.can:716 +local level = level_mt["_init"](lvl, t) -- ./ldtk/ldtk.can:717 +self[lvl["iid"]] = level -- ./ldtk/ldtk.can:718 +self[#self+1] = level -- ./ldtk/ldtk.can:719 +end -- ./ldtk/ldtk.can:719 +return self -- ./ldtk/ldtk.can:719 +end)() -- ./ldtk/ldtk.can:719 +t["_tilesetData"] = (function() -- ./ldtk/ldtk.can:722 +local self = {} -- ./ldtk/ldtk.can:722 +for _, ts in ipairs(project["defs"]["tilesets"]) do -- ./ldtk/ldtk.can:723 +self[ts["uid"]] = { ["tags"] = ts["tags"] } -- ./ldtk/ldtk.can:725 +if ts["relPath"] then -- ./ldtk/ldtk.can:727 +self[ts["uid"]]["path"] = directory .. ts["relPath"] -- ./ldtk/ldtk.can:728 +elseif ts["embedAtlas"] then -- ./ldtk/ldtk.can:729 +self[ts["uid"]]["embedAtlas"] = true -- ./ldtk/ldtk.can:730 +end -- ./ldtk/ldtk.can:730 +for _, tag in ipairs(ts["tags"]) do -- ./ldtk/ldtk.can:732 +self[ts["uid"]]["tags"][tag] = true -- ./ldtk/ldtk.can:733 +end -- ./ldtk/ldtk.can:733 +local tilesetData = self[ts["uid"]] -- ./ldtk/ldtk.can:735 +for gridx = 0, ts["__cWid"] - 1 do -- ./ldtk/ldtk.can:736 +for gridy = 0, ts["__cHei"] - 1 do -- ./ldtk/ldtk.can:737 +tilesetData[gridx + gridy * ts["__cWid"]] = { -- ./ldtk/ldtk.can:738 +["enumTags"] = {}, -- ./ldtk/ldtk.can:739 +["data"] = nil -- ./ldtk/ldtk.can:740 +} -- ./ldtk/ldtk.can:740 +end -- ./ldtk/ldtk.can:740 +end -- ./ldtk/ldtk.can:740 +for _, custom in ipairs(ts["customData"]) do -- ./ldtk/ldtk.can:744 +tilesetData[custom["tileId"]]["data"] = custom["data"] -- ./ldtk/ldtk.can:745 +end -- ./ldtk/ldtk.can:745 +for _, tag in ipairs(ts["enumTags"]) do -- ./ldtk/ldtk.can:747 +local value = tag["enumValueId"] -- ./ldtk/ldtk.can:748 +for _, tileId in ipairs(tag["tileIds"]) do -- ./ldtk/ldtk.can:749 +table["insert"](tilesetData[tileId]["enumTags"], value) -- ./ldtk/ldtk.can:750 +tilesetData[tileId]["enumTags"][value] = true -- ./ldtk/ldtk.can:751 +end -- ./ldtk/ldtk.can:751 +end -- ./ldtk/ldtk.can:751 +end -- ./ldtk/ldtk.can:751 +return self -- ./ldtk/ldtk.can:751 +end)() -- ./ldtk/ldtk.can:751 +t["_layerDef"] = (function() -- ./ldtk/ldtk.can:756 +local self = {} -- ./ldtk/ldtk.can:756 +for _, lay in ipairs(project["defs"]["layers"]) do -- ./ldtk/ldtk.can:757 +self[lay["uid"]] = { -- ./ldtk/ldtk.can:758 +["intGridValues"] = nil, -- ./ldtk/ldtk.can:759 +["parallaxFactorX"] = lay["parallaxFactorX"], -- ./ldtk/ldtk.can:760 +["parallaxFactorY"] = lay["parallaxFactorY"], -- ./ldtk/ldtk.can:761 +["parallaxScaling"] = lay["parallaxScaling"] -- ./ldtk/ldtk.can:762 +} -- ./ldtk/ldtk.can:762 +local layerDef = self[lay["uid"]] -- ./ldtk/ldtk.can:764 +if lay["__type"] == "IntGrid" then -- ./ldtk/ldtk.can:765 +layerDef["intGridValues"] = (function() -- ./ldtk/ldtk.can:766 +local self = {} -- ./ldtk/ldtk.can:766 +for _, v in ipairs(lay["intGridValues"]) do -- ./ldtk/ldtk.can:767 +self[v["value"]] = { -- ./ldtk/ldtk.can:768 +["color"] = parseColor(v["color"]), -- ./ldtk/ldtk.can:769 +["identifier"] = v["identifier"] -- ./ldtk/ldtk.can:770 +} -- ./ldtk/ldtk.can:770 +end -- ./ldtk/ldtk.can:770 +return self -- ./ldtk/ldtk.can:770 +end)() -- ./ldtk/ldtk.can:770 +end -- ./ldtk/ldtk.can:770 +end -- ./ldtk/ldtk.can:770 +return self -- ./ldtk/ldtk.can:770 +end)() -- ./ldtk/ldtk.can:770 +t["_entityData"] = (function() -- ./ldtk/ldtk.can:777 +local self = {} -- ./ldtk/ldtk.can:777 +for _, ent in ipairs(project["defs"]["entities"]) do -- ./ldtk/ldtk.can:778 +self[ent["uid"]] = { -- ./ldtk/ldtk.can:779 +["width"] = ent["width"], -- ./ldtk/ldtk.can:780 +["height"] = ent["height"], -- ./ldtk/ldtk.can:781 +["nineSliceBorders"] = # ent["nineSliceBorders"] > 0 and ent["nineSliceBorders"] or nil -- ./ldtk/ldtk.can:782 +} -- ./ldtk/ldtk.can:782 +end -- ./ldtk/ldtk.can:782 +return self -- ./ldtk/ldtk.can:782 +end)() -- ./ldtk/ldtk.can:782 +return setmetatable(t, project_mt) -- ./ldtk/ldtk.can:786 +end } -- ./ldtk/ldtk.can:786 +project_mt["__index"] = project_mt -- ./ldtk/ldtk.can:789 +return function(file) -- ./ldtk/ldtk.can:822 +return project_mt["_init"](readJson(file), file:match("^(.-)[^%/%\\]+$")) -- ./ldtk/ldtk.can:823 +end -- ./ldtk/ldtk.can:823 diff --git a/signal/signal.lua b/signal/signal.lua index 540e20e..96cc85b 100644 --- a/signal/signal.lua +++ b/signal/signal.lua @@ -1,143 +1,226 @@ -local registry_mt -- ./signal/signal.can:13 -registry_mt = { -- ./signal/signal.can:13 -["signals"] = {}, -- ./signal/signal.can:16 -["bind"] = function(self, name, fn, ...) -- ./signal/signal.can:22 -if not self["signals"][name] then -- ./signal/signal.can:23 -self["signals"][name] = {} -- ./signal/signal.can:24 -end -- ./signal/signal.can:24 -table["insert"](self["signals"][name], fn) -- ./signal/signal.can:26 -if ... then -- ./signal/signal.can:27 -self:bind(name, ...) -- ./signal/signal.can:28 -end -- ./signal/signal.can:28 -end, -- ./signal/signal.can:28 -["unbind"] = function(self, name, fn, ...) -- ./signal/signal.can:36 -if not self["signals"][name] then -- ./signal/signal.can:37 -return -- ./signal/signal.can:38 -end -- ./signal/signal.can:38 -for i = # self["signals"][name], 1, - 1 do -- ./signal/signal.can:40 -if self["signals"][name] == fn then -- ./signal/signal.can:41 -table["remove"](self["signals"][name], i) -- ./signal/signal.can:42 -end -- ./signal/signal.can:42 -end -- ./signal/signal.can:42 -if ... then -- ./signal/signal.can:45 -self:unbind(name, ...) -- ./signal/signal.can:46 -end -- ./signal/signal.can:46 -end, -- ./signal/signal.can:46 -["unbindAll"] = function(self, name) -- ./signal/signal.can:52 -self["signals"][name] = nil -- ./signal/signal.can:53 -end, -- ./signal/signal.can:53 -["replace"] = function(self, name, sourceFn, destFn) -- ./signal/signal.can:60 +local signal -- ./signal/signal.can:30 +local registry_mt -- ./signal/signal.can:36 +registry_mt = { -- ./signal/signal.can:36 +["signals"] = {}, -- ./signal/signal.can:39 +["chained"] = {}, -- ./signal/signal.can:43 +["bind"] = function(self, name, fn) -- ./signal/signal.can:48 +assert(not self:has(name, fn), ("function %s already bound to signal %s"):format(fn, name)) -- ./signal/signal.can:49 +if not self["signals"][name] then -- ./signal/signal.can:50 +self["signals"][name] = {} -- ./signal/signal.can:51 +end -- ./signal/signal.can:51 +table["insert"](self["signals"][name], fn) -- ./signal/signal.can:53 +return self -- ./signal/signal.can:54 +end, -- ./signal/signal.can:54 +["has"] = function(self, name, fn) -- ./signal/signal.can:60 if not self["signals"][name] then -- ./signal/signal.can:61 -self["signals"][name] = {} -- ./signal/signal.can:62 +return false -- ./signal/signal.can:62 end -- ./signal/signal.can:62 -for i, fn in ipairs(self["signals"][name]) do -- ./signal/signal.can:64 -if fn == sourceFn then -- ./signal/signal.can:65 -self["signals"][name][i] = destFn -- ./signal/signal.can:66 -break -- ./signal/signal.can:67 -end -- ./signal/signal.can:67 -end -- ./signal/signal.can:67 -end, -- ./signal/signal.can:67 -["clear"] = function(self) -- ./signal/signal.can:73 -self["signals"] = {} -- ./signal/signal.can:74 -end, -- ./signal/signal.can:74 -["emit"] = function(self, name, ...) -- ./signal/signal.can:80 -if self["signals"][name] then -- ./signal/signal.can:81 -for _, fn in ipairs(self["signals"][name]) do -- ./signal/signal.can:82 -fn(...) -- ./signal/signal.can:83 +for _, f in ipairs(self["signals"][name]) do -- ./signal/signal.can:64 +if f == fn then -- ./signal/signal.can:65 +return true -- ./signal/signal.can:66 +end -- ./signal/signal.can:66 +end -- ./signal/signal.can:66 +return false -- ./signal/signal.can:69 +end, -- ./signal/signal.can:69 +["unbind"] = function(self, name, fn) -- ./signal/signal.can:75 +if not self["signals"][name] then -- ./signal/signal.can:76 +self["signals"][name] = {} -- ./signal/signal.can:77 +end -- ./signal/signal.can:77 +for i = # self["signals"][name], 1, - 1 do -- ./signal/signal.can:79 +local f = self["signals"][name][i] -- ./signal/signal.can:80 +if f == fn then -- ./signal/signal.can:81 +table["remove"](self["signals"][name], i) -- ./signal/signal.can:82 +return self -- ./signal/signal.can:83 end -- ./signal/signal.can:83 end -- ./signal/signal.can:83 -end -- ./signal/signal.can:83 -} -- ./signal/signal.can:83 -registry_mt["__index"] = registry_mt -- ./signal/signal.can:88 -local signal -- ./signal/signal.can:96 -signal = { -- ./signal/signal.can:96 -["new"] = function() -- ./signal/signal.can:99 -return setmetatable({ ["signals"] = {} }, registry_mt) -- ./signal/signal.can:100 -end, -- ./signal/signal.can:100 -["signals"] = {}, -- ./signal/signal.can:104 -["bind"] = function(...) -- ./signal/signal.can:105 -return registry_mt["bind"](signal, ...) -- ./signal/signal.can:106 -end, -- ./signal/signal.can:106 -["unbind"] = function(...) -- ./signal/signal.can:108 -return registry_mt["unbind"](signal, ...) -- ./signal/signal.can:109 -end, -- ./signal/signal.can:109 -["unbindAll"] = function(...) -- ./signal/signal.can:111 -return registry_mt["unbindAll"](signal, ...) -- ./signal/signal.can:112 -end, -- ./signal/signal.can:112 -["replace"] = function(...) -- ./signal/signal.can:114 -return registry_mt["replace"](signal, ...) -- ./signal/signal.can:115 -end, -- ./signal/signal.can:115 -["clear"] = function(...) -- ./signal/signal.can:117 -return registry_mt["clear"](signal, ...) -- ./signal/signal.can:118 +error(("function %s not bound to signal %s"):format(fn, name)) -- ./signal/signal.can:86 +end, -- ./signal/signal.can:86 +["unbindPattern"] = function(self, pat, fn) -- ./signal/signal.can:91 +return self:_patternize("unbind", pat, fn) -- ./signal/signal.can:92 +end, -- ./signal/signal.can:92 +["clear"] = function(self, name) -- ./signal/signal.can:97 +self["signals"][name] = nil -- ./signal/signal.can:98 +end, -- ./signal/signal.can:98 +["clearPattern"] = function(self, pat) -- ./signal/signal.can:102 +return self:_patternize("clear", pat) -- ./signal/signal.can:103 +end, -- ./signal/signal.can:103 +["emit"] = function(self, name, ...) -- ./signal/signal.can:109 +if self["signals"][name] then -- ./signal/signal.can:110 +for _, fn in ipairs(self["signals"][name]) do -- ./signal/signal.can:111 +fn(...) -- ./signal/signal.can:112 +end -- ./signal/signal.can:112 +end -- ./signal/signal.can:112 +for _, c in ipairs(self["chained"]) do -- ./signal/signal.can:115 +c:emit(name, ...) -- ./signal/signal.can:116 +end -- ./signal/signal.can:116 +return self -- ./signal/signal.can:118 end, -- ./signal/signal.can:118 -["emit"] = function(...) -- ./signal/signal.can:120 -return registry_mt["emit"](signal, ...) -- ./signal/signal.can:121 -end, -- ./signal/signal.can:121 -["event"] = nil, -- ./signal/signal.can:136 -["registerEvents"] = function() -- ./signal/signal.can:141 -local callbacks = { -- ./signal/signal.can:142 -"displayrotated", -- ./signal/signal.can:143 -"draw", -- ./signal/signal.can:143 -"load", -- ./signal/signal.can:143 -"lowmemory", -- ./signal/signal.can:143 -"quit", -- ./signal/signal.can:143 -"update", -- ./signal/signal.can:143 -"directorydropped", -- ./signal/signal.can:144 -"filedropped", -- ./signal/signal.can:144 -"focus", -- ./signal/signal.can:144 -"mousefocus", -- ./signal/signal.can:144 -"resize", -- ./signal/signal.can:144 -"visible", -- ./signal/signal.can:144 -"keypressed", -- ./signal/signal.can:145 -"keyreleased", -- ./signal/signal.can:145 -"textedited", -- ./signal/signal.can:145 -"textinput", -- ./signal/signal.can:145 -"mousemoved", -- ./signal/signal.can:146 -"mousepressed", -- ./signal/signal.can:146 -"mousereleased", -- ./signal/signal.can:146 -"wheelmoved", -- ./signal/signal.can:146 -"gamepadaxis", -- ./signal/signal.can:147 -"gamepadpressed", -- ./signal/signal.can:147 -"gamepadreleased", -- ./signal/signal.can:147 -"joystickadded", -- ./signal/signal.can:148 -"joystickaxis", -- ./signal/signal.can:148 -"joystickhat", -- ./signal/signal.can:148 -"joystickpressed", -- ./signal/signal.can:148 -"joystickreleased", -- ./signal/signal.can:148 -"joystickremoved", -- ./signal/signal.can:148 -"touchmoved", -- ./signal/signal.can:149 -"touchpressed", -- ./signal/signal.can:149 -"touchreleased" -- ./signal/signal.can:149 -} -- ./signal/signal.can:149 -local event = signal["event"] -- ./signal/signal.can:151 -for _, callback in ipairs(callbacks) do -- ./signal/signal.can:152 -if callback == "update" then -- ./signal/signal.can:153 -if love[callback] then -- ./signal/signal.can:154 -local old = love[callback] -- ./signal/signal.can:155 -love[callback] = function(dt) -- ./signal/signal.can:156 -old(dt) -- ./signal/signal.can:157 -event:emit(callback, dt) -- ./signal/signal.can:158 -end -- ./signal/signal.can:158 -else -- ./signal/signal.can:158 -love[callback] = function(dt) -- ./signal/signal.can:161 -event:emit(callback, dt) -- ./signal/signal.can:162 -end -- ./signal/signal.can:162 -end -- ./signal/signal.can:162 -else -- ./signal/signal.can:162 -if love[callback] then -- ./signal/signal.can:166 -local old = love[callback] -- ./signal/signal.can:167 -love[callback] = function(...) -- ./signal/signal.can:168 -old(...) -- ./signal/signal.can:169 -event:emit(callback, ...) -- ./signal/signal.can:170 -end -- ./signal/signal.can:170 -else -- ./signal/signal.can:170 -love[callback] = function(...) -- ./signal/signal.can:173 -event:emit(callback, ...) -- ./signal/signal.can:174 -end -- ./signal/signal.can:174 -end -- ./signal/signal.can:174 -end -- ./signal/signal.can:174 -end -- ./signal/signal.can:174 -end -- ./signal/signal.can:174 -} -- ./signal/signal.can:174 -signal["event"] = signal["new"]() -- ./signal/signal.can:182 -return signal -- ./signal/signal.can:184 +["emitPattern"] = function(self, pat, ...) -- ./signal/signal.can:123 +return self:_patternize("emit", pat, ...) -- ./signal/signal.can:124 +end, -- ./signal/signal.can:124 +["chain"] = function(self, registry) -- ./signal/signal.can:131 +if not registry then -- ./signal/signal.can:132 +registry = signal["new"]() -- ./signal/signal.can:133 +end -- ./signal/signal.can:133 +table["insert"](self["chained"], registry) -- ./signal/signal.can:135 +return registry -- ./signal/signal.can:136 +end, -- ./signal/signal.can:136 +["unchain"] = function(self, registry) -- ./signal/signal.can:141 +for i = # self["chained"], 1, - 1 do -- ./signal/signal.can:142 +if self["chained"][i] == registry then -- ./signal/signal.can:143 +table["remove"](self["chained"], i) -- ./signal/signal.can:144 +return self -- ./signal/signal.can:145 +end -- ./signal/signal.can:145 +end -- ./signal/signal.can:145 +error("the givent registry is not chained with this registry") -- ./signal/signal.can:148 +end, -- ./signal/signal.can:148 +["_patternize"] = function(self, method, pat, ...) -- ./signal/signal.can:151 +for name in pairs(self["signals"]) do -- ./signal/signal.can:152 +if name:match(pat) then -- ./signal/signal.can:153 +self[method](self, name, ...) -- ./signal/signal.can:154 +end -- ./signal/signal.can:154 +end -- ./signal/signal.can:154 +end -- ./signal/signal.can:154 +} -- ./signal/signal.can:154 +registry_mt["__index"] = registry_mt -- ./signal/signal.can:159 +local group_mt -- ./signal/signal.can:172 +group_mt = { -- ./signal/signal.can:172 +["paused"] = false, -- ./signal/signal.can:175 +["binds"] = {}, -- ./signal/signal.can:179 +["bind"] = function(self, registry, name, fn) -- ./signal/signal.can:187 +table["insert"](self["binds"], { -- ./signal/signal.can:188 +registry, -- ./signal/signal.can:188 +name, -- ./signal/signal.can:188 +fn -- ./signal/signal.can:188 +}) -- ./signal/signal.can:188 +if not self["paused"] then -- ./signal/signal.can:189 +registry:bind(name, fn) -- ./signal/signal.can:189 +end -- ./signal/signal.can:189 +end, -- ./signal/signal.can:189 +["clear"] = function(self) -- ./signal/signal.can:193 +if not self["paused"] then -- ./signal/signal.can:194 +for _, b in ipairs(self["binds"]) do -- ./signal/signal.can:195 +b[1]:unbind(b[2], b[3]) -- ./signal/signal.can:196 +end -- ./signal/signal.can:196 +end -- ./signal/signal.can:196 +self["binds"] = {} -- ./signal/signal.can:199 +end, -- ./signal/signal.can:199 +["pause"] = function(self) -- ./signal/signal.can:204 +assert(not self["paused"], "event group is already paused") -- ./signal/signal.can:205 +self["paused"] = true -- ./signal/signal.can:206 +for _, b in ipairs(self["binds"]) do -- ./signal/signal.can:207 +b[1]:unbind(b[2], b[3]) -- ./signal/signal.can:208 +end -- ./signal/signal.can:208 +end, -- ./signal/signal.can:208 +["resume"] = function(self) -- ./signal/signal.can:214 +assert(self["paused"], "event group is not paused") -- ./signal/signal.can:215 +self["paused"] = false -- ./signal/signal.can:216 +for _, b in ipairs(self["binds"]) do -- ./signal/signal.can:217 +b[1]:bind(b[2], b[3]) -- ./signal/signal.can:218 +end -- ./signal/signal.can:218 +end -- ./signal/signal.can:218 +} -- ./signal/signal.can:218 +group_mt["__index"] = group_mt -- ./signal/signal.can:222 +signal = { -- ./signal/signal.can:228 +["new"] = function() -- ./signal/signal.can:231 +return setmetatable({ -- ./signal/signal.can:232 +["signals"] = {}, -- ./signal/signal.can:232 +["chained"] = {} -- ./signal/signal.can:232 +}, registry_mt) -- ./signal/signal.can:232 +end, -- ./signal/signal.can:232 +["group"] = function() -- ./signal/signal.can:237 +return setmetatable({ ["binds"] = {} }, group_mt) -- ./signal/signal.can:238 +end, -- ./signal/signal.can:238 +["signals"] = {}, -- ./signal/signal.can:242 +["bind"] = function(...) -- ./signal/signal.can:243 +return registry_mt["bind"](signal, ...) -- ./signal/signal.can:244 +end, -- ./signal/signal.can:244 +["has"] = function(...) -- ./signal/signal.can:246 +return registry_mt["has"](signal, ...) -- ./signal/signal.can:247 +end, -- ./signal/signal.can:247 +["unbind"] = function(...) -- ./signal/signal.can:249 +return registry_mt["unbind"](signal, ...) -- ./signal/signal.can:250 +end, -- ./signal/signal.can:250 +["unbindPattern"] = function(...) -- ./signal/signal.can:252 +return registry_mt["unbindPattern"](signal, ...) -- ./signal/signal.can:253 +end, -- ./signal/signal.can:253 +["clear"] = function(...) -- ./signal/signal.can:255 +return registry_mt["clear"](signal, ...) -- ./signal/signal.can:256 +end, -- ./signal/signal.can:256 +["clearPattern"] = function(...) -- ./signal/signal.can:258 +return registry_mt["clearPattern"](signal, ...) -- ./signal/signal.can:259 +end, -- ./signal/signal.can:259 +["emit"] = function(...) -- ./signal/signal.can:261 +return registry_mt["emit"](signal, ...) -- ./signal/signal.can:262 +end, -- ./signal/signal.can:262 +["emitPattern"] = function(...) -- ./signal/signal.can:264 +return registry_mt["emitPattern"](signal, ...) -- ./signal/signal.can:265 +end, -- ./signal/signal.can:265 +["event"] = nil, -- ./signal/signal.can:286 +["registerEvents"] = function() -- ./signal/signal.can:291 +local callbacks = { -- ./signal/signal.can:292 +"displayrotated", -- ./signal/signal.can:293 +"draw", -- ./signal/signal.can:293 +"load", -- ./signal/signal.can:293 +"lowmemory", -- ./signal/signal.can:293 +"quit", -- ./signal/signal.can:293 +"update", -- ./signal/signal.can:293 +"directorydropped", -- ./signal/signal.can:294 +"filedropped", -- ./signal/signal.can:294 +"focus", -- ./signal/signal.can:294 +"mousefocus", -- ./signal/signal.can:294 +"resize", -- ./signal/signal.can:294 +"visible", -- ./signal/signal.can:294 +"keypressed", -- ./signal/signal.can:295 +"keyreleased", -- ./signal/signal.can:295 +"textedited", -- ./signal/signal.can:295 +"textinput", -- ./signal/signal.can:295 +"mousemoved", -- ./signal/signal.can:296 +"mousepressed", -- ./signal/signal.can:296 +"mousereleased", -- ./signal/signal.can:296 +"wheelmoved", -- ./signal/signal.can:296 +"gamepadaxis", -- ./signal/signal.can:297 +"gamepadpressed", -- ./signal/signal.can:297 +"gamepadreleased", -- ./signal/signal.can:297 +"joystickadded", -- ./signal/signal.can:298 +"joystickaxis", -- ./signal/signal.can:298 +"joystickhat", -- ./signal/signal.can:298 +"joystickpressed", -- ./signal/signal.can:298 +"joystickreleased", -- ./signal/signal.can:298 +"joystickremoved", -- ./signal/signal.can:298 +"touchmoved", -- ./signal/signal.can:299 +"touchpressed", -- ./signal/signal.can:299 +"touchreleased" -- ./signal/signal.can:299 +} -- ./signal/signal.can:299 +local event = signal["event"] -- ./signal/signal.can:301 +for _, callback in ipairs(callbacks) do -- ./signal/signal.can:302 +if callback == "update" then -- ./signal/signal.can:303 +if love[callback] then -- ./signal/signal.can:304 +local old = love[callback] -- ./signal/signal.can:305 +love[callback] = function(dt) -- ./signal/signal.can:306 +old(dt) -- ./signal/signal.can:307 +event:emit(callback, dt) -- ./signal/signal.can:308 +end -- ./signal/signal.can:308 +else -- ./signal/signal.can:308 +love[callback] = function(dt) -- ./signal/signal.can:311 +event:emit(callback, dt) -- ./signal/signal.can:312 +end -- ./signal/signal.can:312 +end -- ./signal/signal.can:312 +else -- ./signal/signal.can:312 +if love[callback] then -- ./signal/signal.can:316 +local old = love[callback] -- ./signal/signal.can:317 +love[callback] = function(...) -- ./signal/signal.can:318 +old(...) -- ./signal/signal.can:319 +event:emit(callback, ...) -- ./signal/signal.can:320 +end -- ./signal/signal.can:320 +else -- ./signal/signal.can:320 +love[callback] = function(...) -- ./signal/signal.can:323 +event:emit(callback, ...) -- ./signal/signal.can:324 +end -- ./signal/signal.can:324 +end -- ./signal/signal.can:324 +end -- ./signal/signal.can:324 +end -- ./signal/signal.can:324 +end -- ./signal/signal.can:324 +} -- ./signal/signal.can:324 +signal["event"] = signal["new"]() -- ./signal/signal.can:332 +return signal -- ./signal/signal.can:334