You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
280 lines
7.4 KiB
280 lines
7.4 KiB
local inspect = require('inspect') |
|
|
|
-- Utility functions for working with Lua in Fungus |
|
local M = {} |
|
|
|
------------ |
|
-- Debugging |
|
------------ |
|
|
|
function M.inspect(v) |
|
print (inspect.inspect(v)) |
|
end |
|
|
|
------- |
|
-- Time |
|
------- |
|
|
|
-- Returns the absolute time |
|
-- Use this timing function to work correctly with the Lua Environment's timeScale property |
|
function M.gettime() |
|
return M.luautils.getTime() |
|
end |
|
|
|
-- Returns the delta time this frame |
|
-- Use this timing function to work correctly with the Lua Environment's timeScale property |
|
function M.getdeltatime() |
|
return M.luautils.getDeltaTime() |
|
end |
|
|
|
function M.settimescale(s) |
|
M.luautils.timeScale = s |
|
end |
|
|
|
------------- |
|
-- Coroutines |
|
------------- |
|
|
|
-- Waits for a number of seconds |
|
function M.wait(duration) |
|
local t = M.gettime() |
|
while (M.gettime() - t < duration) do |
|
coroutine.yield() |
|
end |
|
end |
|
|
|
-- Waits until the lamda function provided returns true, or the timeout expires. |
|
-- Returns true if the function succeeded, or false if the timeout expired |
|
-- |
|
function M.waitfor(fn, timeoutduration) |
|
local t = M.gettime() |
|
while (not fn()) do |
|
coroutine.yield() |
|
if (M.gettime() - t > timeoutduration) then |
|
return false |
|
end |
|
end |
|
return true |
|
end |
|
|
|
-- Starts a C# coroutine method |
|
function M.run(enumerator) |
|
-- If the parameter isn't an enumerator then CreateTask will fail |
|
local status, err = pcall( function() |
|
local task = M.luaenvironment.RunUnityCoroutine(enumerator) |
|
end) |
|
|
|
if (not status) then |
|
print(debug.traceback("Can't start a coroutine with a c# method that doesn't return IEnumerator", 2)) |
|
error(err) |
|
end |
|
end |
|
|
|
-- Starts a C# coroutine method and waits until it's finished |
|
function M.runwait(enumerator) |
|
-- If the parameter isn't an enumerator then CreateTask will fail |
|
local status, err = pcall( function() |
|
local task = M.luaenvironment.RunUnityCoroutine(enumerator) |
|
while (task != nil and task.Running) do |
|
coroutine.yield(); |
|
end |
|
end) |
|
|
|
if (not status) then |
|
print(debug.traceback("Can't start a coroutine with a c# method that doesn't return IEnumerator", 2)) |
|
error(err) |
|
end |
|
end |
|
|
|
--------------- |
|
-- String table |
|
--------------- |
|
|
|
-- Set active language for string table |
|
function M.setlanguage(languagecode) |
|
M.luautils.activeLanguage = languagecode |
|
end |
|
|
|
-- Get a named string from the string table |
|
function M.getstring(key) |
|
return M.luautils.GetString(key) |
|
end |
|
|
|
-- Substitutes variables and localisation strings into a piece of text |
|
-- e.g. v = 10, "Subbed value is [$v]" => "Subbed value is 10" |
|
function M.sub(text) |
|
return M.luautils.substitute(text) |
|
end |
|
|
|
-------------------------------------------------------------- |
|
-- Integration tests |
|
-- These functions require the Unity Test Tools to work. |
|
-------------------------------------------------------------- |
|
|
|
-- Checks if a condition is true (requires Unity Test Tools) |
|
-- Lua has a built in assert function, so we called this check to avoid conflicting. |
|
function M.check(c, reason) |
|
if (not c) then |
|
-- Output a traceback to help track down source |
|
error( debug.traceback("Assert failed", 2) ) |
|
end |
|
M.test.assert(c, reason) |
|
end |
|
|
|
-- Pass an integration test (requires Unity Test Tools) |
|
function M.pass() |
|
M.test.pass() |
|
end |
|
|
|
-- Fail an integration test (requires Unity Test Tools) |
|
function M.fail(reason) |
|
error( debug.traceback("Test failed", 2) ) |
|
M.test.fail(reason) |
|
end |
|
|
|
--------------------------------------------- |
|
-- All functions below require Fungus to work |
|
--------------------------------------------- |
|
|
|
------------- |
|
-- Say Dialog |
|
------------- |
|
|
|
-- Options for configuring Say Dialog behaviour |
|
M.sayoptions = {} |
|
M.sayoptions.saydialog = nil |
|
M.sayoptions.clearprevious = true |
|
M.sayoptions.waitforinput = true |
|
M.sayoptions.fadewhendone = true |
|
M.sayoptions.stopvoiceover = true |
|
|
|
-- Set the active saydialog to use with the say function |
|
function M.setsaydialog(saydialog) |
|
M.sayoptions.saydialog = saydialog |
|
end |
|
|
|
-- Gets the active say dialog, or creates one if none exists yet |
|
function M.getsaydialog() |
|
if (M.sayoptions.saydialog == nil) then |
|
local sd = M.luautils.spawn("SayDialog").GetComponent("SayDialog") |
|
M.setsaydialog(sd) |
|
end |
|
return M.sayoptions.saydialog |
|
end |
|
|
|
-- Set the active character on the Say Dialog |
|
-- character: A Fungus.Character component |
|
-- portrait: The name of a sprite in the character's portrait list |
|
function M.setcharacter(character, portrait) |
|
assert(character, "character must not be nil") |
|
local sd = M.getsaydialog() |
|
sd.SetCharacter(character) |
|
|
|
-- Do substitution on character name |
|
local subbed = M.sub(character.nameText) |
|
M.sayoptions.saydialog.SetCharacterName(subbed, character.nameColor) |
|
|
|
-- Try to set the portrait sprite |
|
if (portrait) then |
|
if (portrait == "") then |
|
M.sayoptions.saydialog.SetCharacterImage(nill) |
|
else |
|
for i,v in ipairs(character.portraits) do |
|
-- Use a case insensitive comparison |
|
if (string.lower(v.name) == string.lower(portrait)) then |
|
M.sayoptions.saydialog.SetCharacterImage(v) |
|
end |
|
end |
|
end |
|
end |
|
end |
|
|
|
-- Write text to the active Say Dialog |
|
-- text: A string to write to the say dialog |
|
-- voice: A voiceover audioclip to play |
|
function M.say(text, voiceclip) |
|
local sd = M.getsaydialog() |
|
|
|
-- Do variable substitution before displaying text |
|
local subbed = M.sub(text) |
|
local e = sd.SayInternal(subbed, M.sayoptions.clearprevious, M.sayoptions.waitforinput, M.sayoptions.fadewhendone, M.sayoptions.stopvoiceover, voiceclip) |
|
|
|
M.runwait(e) |
|
end |
|
|
|
-------------- |
|
-- Menu Dialog |
|
-------------- |
|
|
|
-- Options for configuring Menu Dialog behaviour |
|
M.menuoptions = {} |
|
|
|
-- Set the active menudialog to use with the menu function |
|
function M.setmenudialog(menudialog) |
|
M.menuoptions.menudialog = menudialog |
|
end |
|
|
|
-- Gets the active menu dialog, or creates one if none exists yet |
|
function M.getmenudialog() |
|
if (M.menuoptions.menudialog == nil) then |
|
local md = M.luautils.spawn("MenuDialog").GetComponent("MenuDialog") |
|
M.setmenudialog(md) |
|
end |
|
return M.menuoptions.menudialog |
|
end |
|
|
|
-- Display a menu button |
|
-- text: text to display on the button |
|
-- callback: function to call when this option is selected |
|
-- interactive (optional): if false, displays the option as disabled |
|
function M.menu(text, callback, interactive) |
|
local md = M.getmenudialog() |
|
|
|
-- Do variable substitution before displaying text |
|
local subbed = M.sub(text) |
|
md.AddOption(subbed, interactive or true, M.luaenvironment, callback) |
|
end |
|
|
|
-- Display a timer during which the player has to choose an option. |
|
-- duration: The length of time to display the timer. |
|
-- callback: Function to call if the timer expires before an option is selected. |
|
function M.menutimer(duration, callback) |
|
local md = M.getmenudialog() |
|
|
|
local e = md.ShowTimer(duration, M.luaenvironment, callback) |
|
M.runwait(e) |
|
end |
|
|
|
-- Clear all currently displayed menu options |
|
function M.clearmenu() |
|
assert(M.menuoptions.menudialog, "menudialog must not be nil") |
|
M.menuoptions.menudialog.Clear() |
|
end |
|
|
|
------------ |
|
-- Flowchart |
|
------------ |
|
|
|
-- Runs the specified Block in a Flowchart |
|
-- flowchart: The Fungus Flowchart containing the Block to run. |
|
-- blockname: The name of the Block to run. |
|
-- nowait: If false, will yield until the Block finishes execution. If true will continue immediately. |
|
function M.runblock(flowchart, blockname, nowait) |
|
assert(flowchart, "flowchart must not be nil") |
|
assert(blockname, "blockname must not be nil") |
|
local block = flowchart.FindBlock(blockname) |
|
if (not block) then |
|
error("Block " .. blockname .. " not found") |
|
return |
|
end |
|
|
|
local e = block.Execute(); |
|
|
|
if (nowait) then |
|
M.run( e ) |
|
else |
|
M.runwait( e ) |
|
end |
|
end |
|
|
|
return M |