-
Notifications
You must be signed in to change notification settings - Fork 3
Documentation
This is the page that will have function descriptions. 'Bigger' examples and tutorials are going onto separate pages.
This section will describe the core modules. These provide basic functionality, useful APIs, and a majority of other modules use these as a dependency.
Provides a basic interface for logging. Uses either absolute time, or frame-based timestamps, and uses named logging components for better debugging.
Format:
Time [LEVEL] <Name>: Message
Examples:
133.37 [ERROR] <Global>: LOGGER TEST - IGNORE ME
133.37 [INFO] <Global>: Global log level is 3
Creates a named Logger instance. It will print output_log entries with its given name.
-- Params: name (string)
local myLogger = Logger("myModule") -- makes a new unique Logger instance
myLogger:changeName("newModule") -- changes the name of an already existing instance
Using log4j log levels, more on them here
Log levels in decreasing order, with their expected output, and log level after them:
local myLogger = Logger("myModule")
-- Log level 0: OFF
myLogger:exc("desc")
myLogger:exception("desc")
myLogger:fatal("desc")
-- 1.23 [FATAL] <Global>: Log level 1
myLogger:err("desc")
myLogger:error("desc")
-- 1.23 [ERROR] <Global>: Log level 2
myLogger:warn("desc")
myLogger:warning("desc")
-- 1.23 [WARN] <Global>: Log level 3
myLogger:log("desc")
myLogger:info("desc")
-- 1.23 [INFO] <Global>: Log level 4
myLogger:dbg("desc")
myLogger:debug("desc")
-- 1.23 [DEBUG] <Global>: Log level 5
myLogger:trace("desc", level)
-- 1.23 [TRACE] <Global>: Log level 7
-- If a level is specified, then log level '5+level'
You can disable logging of each instance separately.
local myLogger = new Logger("myModule")
myLogger:log("Enabed by default - you can see this")
myLogger:disable()
myLogger:log("You cannot see this")
myLogger:enable()
myLogger:log("You can see this again")
myLogger:toggle() -- Toggles on/off
myLogger:log("Off again")
myLogger:error("Log levels ERROR and above ignore the enabled state")
The events
module is the core of the framework. All the game's events are routed through here, with the possibility of custom events included.
The module has 2 main sections: the Event
and the EventHandler
.
An Event
is made up of 2 parts: the id
of the event, and the data
of the event. While the ID is stored in the central Events
table, the data is entirely event-specific, and can range from nil to a raw Track
table.
Callbacks can be added to the EventHandler
- whenever the specified type of event is thrown, the callback will be called. (note: you can bind classes to your callbacks)
Each callback added has an unique callbackID
- with that ID, it can be changed, disabled, or even removed.
This module does NOT use multithreading - every callback is executed in the order they were added in, even if they were disabled beforehand. Disabled callbacks are skipped.
Any extra EventHandlers, apart from EventHandler.instance
, will have their original events (from Events.INIT
to Events.SCORE
) forwarded from EventHandler.instance
. This is because there is no other way to capture those events.
A global EventHandler.instance
is provided, the default events are all routed through this one central instance. You have the option to create your own EventHandler
instance.
local myEventHandler = EventHandler()
(note: I will use EventHandler.instance
from now on, instead of a separate instance)
You can reset to default your EventHandler
, deleting every event and re-registering gameplay event forwardings.
EventHandler.instance:reset()
Callbacks can be added in 2 ways: as a standalone function, and with a class to bind to. The callback function needs to take only one parameter - the Event
object of the event.
Event IDs can be found in the Events
table.
-- Standalone function
local function myCallback(event)
Logger.Global:log(dump(ev))
end
local callbackID = EventHandler.instance:on(Events.INIT, myCallback)
Callbacks can also be bound to classes, if you wish to use object-oriented modules.
-- Create a function inside our class
function MyClass:onEvent(event)
self.logger:log(event.id)
end
-- Create an instance of our class
local myInstance = MyClass()
-- Bind our instance to our function
local callbackID2 = EventHandler.instance:on(Events.ALL, MyClass.onEvent, myInstance)
To remove a callback, you need its unique callbackID
. Only with this value can the event be removed.
EventHandler.instance:remove(callbackID)
EventHandler.instance:del(callbackID2) -- alias
Disabling an event only disables the callbacks - it does not remove the event itself, making it possible to re-enable each event.
EventHandler.instance:enable(id)
Eventhandler.instance:disable(id)
Eventhandler.instance:toggle(id)
You can also disable an event from inside the calback function by returning a non-falsey value (usually true
).
function callback(ev)
return true -- This event will not run again until re-enabled.
end
Events can be thrown using the Event
object. Each callback gets a separate copy of the same object.
-- Params:
local myEvent = Event(Events.INIT, {})
EventHandler.instance:throw(myEvent)
The tick
module is used to track our current position in the song as well as to provide accurate timing, taking into account pauses.
It contains two sub-modules: GameStates
and Tick
.
The former, GameStates
is used to track bigger sections of the loading and the game process - it tracks pauses, load segments, and pre- and post-song sections. This class is static - meaning there is only one global game state (because there is only one song playing currently).
It indicates that the song is currently in progress, by giving a 0x10
flag to the current GameState.
All the possible game states are stored in GameStates
, along with the current state.
-- Returns the current game state, can be cross-checked with GameStates
local currentGameState = GameStates.current
if currentGameState == GameStates.PRE_START then
Logger.Global:log("The song is about to start!")
end
-- Short-hand for checking for the paused flag.
local gameIsPaused = GameStates.isPaused()
The latter, Tick
, serves more precise timing purposes. It is recommended to use this module when syncing special effects and visuals with the song.
Tick
has two separate timers: RelativeTime
and AbsoluteTime
.
FRAME
events, when passed back by the game, have an 'elapsed time' parameter.
RelativeTime
uses the sum of this 'elapsed time' parameter, while AbsoluteTime
gets its timing value from the number of elapsed frames. (AbsoluteTime
runs based on the 90Hz refresh rate of the HTC VIVE.)
On computers with more frequent frame-drops (or more reprojected frames), this will cause significant discrepancy between the two times.
For static render updates, using AbsoluteTime
is recommended, while RelativeTime
is better for song-synchronized and timecoded visualizations.
Tick
, however accurate data it gets from current frames, is still very inaccurate. For more accurate timing, use the game's built-in GetMillisecondsSinceStartup()
function.
local myTick = Tick()
Instances of Tick
can be reset, just like any other non-static class.
myTick:reset()
You can get current times by these two functions:
local currentRelativeTime = Tick.instance:getRelativeTime() -- based on elapsed time
local currentAbsoluteTime = Tick.instance:getAbsoluteTime() -- based on frame count
The intervals
module is used mainly to run timed events and intervals. Its timing is entirely gameplay-based - meaning that if you pause the game, your timers will stop, unlike the Events.FRAME
event.
To help timing functions, this module takes the two Tick module timings.
Just like EventHandler
, callbacks are added to Intervals
the same way - once every timeout
seconds, your callback will be called.
The callback can be bound to a class for object-oriented purposes.
Each interval has a unique callbackID
- using this ID, the interval can be removed.
Callbacks can also remove themselves by returning a non-falsey value (typically true
). Timers can be created this way, only running once, and returning true
.
Intervals cannot temporarily be disabled, and they cannot use a timer other than Tick
- do not run high precision tasks with Intervals
, run them with GetMillisecondsSinceStartup()
and coroutines instead!
A global Intervals.instance
is provided. However, you can make your own if you wish.
local myIntervals = Intervals()
addInterval
takes 3 parameters:
-
timeout
to indicate their interval duration in seconds, -
isRelativeTime
to indicate the timing method, true for relative, false for absolute (default true), - the
callback
function. -
(optional) A 4th,
class
parameter is also provided to make function binding easier.
Callbacks are given no parameters, they are just called - to give them an extra parameter, use the bindFunc
utility.
local myTimeout = 3.5 -- seconds, not necessarily integers
local useRelativeTime = true
local function myCallback()
Logger.Global:log("My interval is called!")
end
local callbackID = Intervals.instance:addInterval(myTimeout, useRelativeTime, myCallback) -- a 4th parameter
Removing intervals can be done the same way as removing events - by passing the callback ID returned from adding the interval.
Intervals.instance:delInterval(callbackID)
Intervals.instance:del(callbackID2) -- alias
Intervals.instance:remove(callbackID3) -- alias
Intervals can also delete themselves by returning true
.
-- This interval would only run once - it will be removed as soon as it returns true.
-- This method is useful for creating timeouts.
local function myCallback()
return true
end
TODO.
Back to top
TODO.
Back to top
TODO.
Back to top
-
Home
- Getting started
-
List of mods
- Default mod
- Insane mod
- Documentation
- Licenses, credits and acknowledgements