Browse Source

Initial implementation of FungusScript Lua scripting

master
chrisgregan 9 years ago
parent
commit
56cd4b213c
  1. 4
      Assets/Fungus/FungusScript.meta
  2. 4
      Assets/Fungus/FungusScript/ExampleScenes.meta
  3. 3011
      Assets/Fungus/FungusScript/ExampleScenes/Narrative.unity
  4. 8
      Assets/Fungus/FungusScript/ExampleScenes/Narrative.unity.meta
  5. 1659
      Assets/Fungus/FungusScript/ExampleScenes/Trigger.unity
  6. 8
      Assets/Fungus/FungusScript/ExampleScenes/Trigger.unity.meta
  7. 9
      Assets/Fungus/FungusScript/Resources.meta
  8. 9
      Assets/Fungus/FungusScript/Resources/Lua.meta
  9. 258
      Assets/Fungus/FungusScript/Resources/Lua/fungus.txt
  10. 8
      Assets/Fungus/FungusScript/Resources/Lua/fungus.txt.meta
  11. 331
      Assets/Fungus/FungusScript/Resources/Lua/inspect.txt
  12. 8
      Assets/Fungus/FungusScript/Resources/Lua/inspect.txt.meta
  13. 9
      Assets/Fungus/FungusScript/Resources/Prefabs.meta
  14. 55
      Assets/Fungus/FungusScript/Resources/Prefabs/FungusBindings.prefab
  15. 8
      Assets/Fungus/FungusScript/Resources/Prefabs/FungusBindings.prefab.meta
  16. 65
      Assets/Fungus/FungusScript/Resources/Prefabs/FungusInvoke.prefab
  17. 8
      Assets/Fungus/FungusScript/Resources/Prefabs/FungusInvoke.prefab.meta
  18. 56
      Assets/Fungus/FungusScript/Resources/Prefabs/FungusScript.prefab
  19. 8
      Assets/Fungus/FungusScript/Resources/Prefabs/FungusScript.prefab.meta
  20. 9
      Assets/Fungus/FungusScript/Scripts.meta
  21. 9
      Assets/Fungus/FungusScript/Scripts/Editor.meta
  22. 81
      Assets/Fungus/FungusScript/Scripts/Editor/DropDownControl.cs
  23. 12
      Assets/Fungus/FungusScript/Scripts/Editor/DropDownControl.cs.meta
  24. 455
      Assets/Fungus/FungusScript/Scripts/Editor/FungusBindingsEditor.cs
  25. 12
      Assets/Fungus/FungusScript/Scripts/Editor/FungusBindingsEditor.cs.meta
  26. 197
      Assets/Fungus/FungusScript/Scripts/Editor/FungusInvokeEditor.cs
  27. 12
      Assets/Fungus/FungusScript/Scripts/Editor/FungusInvokeEditor.cs.meta
  28. 89
      Assets/Fungus/FungusScript/Scripts/Editor/MenuItems.cs
  29. 12
      Assets/Fungus/FungusScript/Scripts/Editor/MenuItems.cs.meta
  30. 153
      Assets/Fungus/FungusScript/Scripts/FungusBindings.cs
  31. 12
      Assets/Fungus/FungusScript/Scripts/FungusBindings.cs.meta
  32. 359
      Assets/Fungus/FungusScript/Scripts/FungusInvoke.cs
  33. 12
      Assets/Fungus/FungusScript/Scripts/FungusInvoke.cs.meta
  34. 110
      Assets/Fungus/FungusScript/Scripts/FungusPrefs.cs
  35. 12
      Assets/Fungus/FungusScript/Scripts/FungusPrefs.cs.meta
  36. 527
      Assets/Fungus/FungusScript/Scripts/FungusScript.cs
  37. 12
      Assets/Fungus/FungusScript/Scripts/FungusScript.cs.meta
  38. 9
      Assets/Fungus/FungusScript/Thirdparty.meta
  39. 9
      Assets/Fungus/FungusScript/Thirdparty/FungusExtensions.meta
  40. 155
      Assets/Fungus/FungusScript/Thirdparty/FungusExtensions/ExecuteLua.cs
  41. 12
      Assets/Fungus/FungusScript/Thirdparty/FungusExtensions/ExecuteLua.cs.meta
  42. 97
      Assets/Fungus/FungusScript/Thirdparty/FungusExtensions/FungusScriptExtensions.cs
  43. 12
      Assets/Fungus/FungusScript/Thirdparty/FungusExtensions/FungusScriptExtensions.cs.meta
  44. 40
      Assets/Fungus/FungusScript/Thirdparty/FungusExtensions/RegisterFungusTypes.cs
  45. 12
      Assets/Fungus/FungusScript/Thirdparty/FungusExtensions/RegisterFungusTypes.cs.meta
  46. 9
      Assets/Fungus/FungusScript/Thirdparty/MoonSharp.meta
  47. 36
      Assets/Fungus/FungusScript/Thirdparty/MoonSharp/LICENSE
  48. 8
      Assets/Fungus/FungusScript/Thirdparty/MoonSharp/LICENSE.meta
  49. BIN
      Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Hardwire.dll
  50. 24
      Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Hardwire.dll.meta
  51. BIN
      Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Hardwire.pdb
  52. 8
      Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Hardwire.pdb.meta
  53. BIN
      Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Interpreter.dll
  54. 24
      Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Interpreter.dll.meta
  55. BIN
      Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Interpreter.pdb
  56. 8
      Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Interpreter.pdb.meta
  57. 7750
      Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Interpreter.xml
  58. 8
      Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Interpreter.xml.meta
  59. BIN
      Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.RemoteDebugger.dll
  60. 24
      Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.RemoteDebugger.dll.meta
  61. BIN
      Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.RemoteDebugger.pdb
  62. 8
      Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.RemoteDebugger.pdb.meta
  63. BIN
      Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.pdb
  64. 8
      Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.pdb.meta
  65. 9
      Assets/Fungus/FungusScript/Thirdparty/TaskManager.meta
  66. 214
      Assets/Fungus/FungusScript/Thirdparty/TaskManager/TaskManager.cs
  67. 12
      Assets/Fungus/FungusScript/Thirdparty/TaskManager/TaskManager.cs.meta
  68. 9
      Assets/FungusExamples/FungusScript.meta
  69. 9
      Assets/Tests/FungusScript.meta
  70. 9861
      Assets/Tests/FungusScript/FungusTests.unity
  71. 8
      Assets/Tests/FungusScript/FungusTests.unity.meta
  72. 1704
      Assets/Tests/FungusScript/ScriptingTests.unity
  73. 8
      Assets/Tests/FungusScript/ScriptingTests.unity.meta
  74. 9
      Assets/Tests/Resources.meta
  75. 9
      Assets/Tests/Resources/Lua.meta
  76. 9
      Assets/Tests/Resources/Lua/teststringtable.txt
  77. 8
      Assets/Tests/Resources/Lua/teststringtable.txt.meta
  78. 0
      Assets/Tests/TestAssets/Animation/TestAnim.anim
  79. 0
      Assets/Tests/TestAssets/Animation/TestAnim.anim.meta
  80. 0
      Assets/Tests/TestAssets/Animation/TestAnim.unity
  81. 0
      Assets/Tests/TestAssets/Animation/TestAnim.unity.meta
  82. 0
      Assets/Tests/TestAssets/Animation/TestSprite.controller
  83. 0
      Assets/Tests/TestAssets/Animation/TestSprite.controller.meta
  84. 0
      Assets/Tests/TestAssets/Audio/AudioTests.unity
  85. 0
      Assets/Tests/TestAssets/Audio/AudioTests.unity.meta
  86. BIN
      Assets/Tests/TestAssets/Audio/voiceover.ogg
  87. 22
      Assets/Tests/TestAssets/Audio/voiceover.ogg.meta
  88. 9
      Assets/Tests/TestAssets/Material.meta
  89. 138
      Assets/Tests/TestAssets/Material/TestMaterial.mat
  90. 8
      Assets/Tests/TestAssets/Material/TestMaterial.mat.meta
  91. 9
      Assets/Tests/TestAssets/Texture.meta
  92. BIN
      Assets/Tests/TestAssets/Texture/MousePointer.png
  93. 57
      Assets/Tests/TestAssets/Texture/MousePointer.png.meta

4
Assets/Tests/Animation.meta → Assets/Fungus/FungusScript.meta

@ -1,7 +1,7 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 281dd8265cd4c4d00b1c5ad04f2e6b5a guid: 6fb32c987f2084f71b3394b6efb57ccf
folderAsset: yes folderAsset: yes
timeCreated: 1458814154 timeCreated: 1455641608
licenseType: Free licenseType: Free
DefaultImporter: DefaultImporter:
userData: userData:

4
Assets/Tests/Audio.meta → Assets/Fungus/FungusScript/ExampleScenes.meta

@ -1,7 +1,7 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 7b5a2e9e9c22f479480e7cf72064bffa guid: b08784ce29a474b758098629a00fb6c4
folderAsset: yes folderAsset: yes
timeCreated: 1439214867 timeCreated: 1454684130
licenseType: Free licenseType: Free
DefaultImporter: DefaultImporter:
userData: userData:

3011
Assets/Fungus/FungusScript/ExampleScenes/Narrative.unity

File diff suppressed because it is too large Load Diff

8
Assets/Fungus/FungusScript/ExampleScenes/Narrative.unity.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0319726c027694d388d69066da479b61
timeCreated: 1457363324
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

1659
Assets/Fungus/FungusScript/ExampleScenes/Trigger.unity

File diff suppressed because it is too large Load Diff

8
Assets/Fungus/FungusScript/ExampleScenes/Trigger.unity.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f739410aaa44d4fbca15e7fee5842e50
timeCreated: 1457362432
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Fungus/FungusScript/Resources.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: ad95753a2eeea4611980e3a03ebd8826
folderAsset: yes
timeCreated: 1455555043
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Fungus/FungusScript/Resources/Lua.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 479e25ea74c6e467f80ffa29bb049e0d
folderAsset: yes
timeCreated: 1454938226
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

258
Assets/Fungus/FungusScript/Resources/Lua/fungus.txt

@ -0,0 +1,258 @@
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 FungusScript timeScale property
function M.time()
return unity.fungusscript.getTime()
end
-- Returns the delta time this frame
-- Use this timing function to work correctly with the FungusScript timeScale property
function M.deltatime()
return unity.fungusscript.getDeltaTime()
end
-------------
-- Coroutines
-------------
-- Waits for a number of seconds
function M.wait(duration)
local t = M.time()
while (M.time() - 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.time()
while (not fn()) do
coroutine.yield()
if (M.time() - 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 = unity.fungusscript.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 = unity.fungusscript.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)
unity.fungusscript.activeLanguage = languageCode
end
-- Get a named string from the string table
function M.getstring(key)
return unity.fungusscript.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 unity.fungusscript.substitute(text)
end
--------------------
-- Integration tests
--------------------
-- Assert a condition is true (requires Unity Test Tools)
function M.assert(c, reason)
if (not c) then
-- Output a traceback to help track down source
error( debug.traceback("Assert failed", 2) )
end
unity.test.assert(c, reason)
end
-- Pass an integration test (requires Unity Test Tools)
function M.pass()
unity.test.pass()
end
-- Fail an integration test (requires Unity Test Tools)
function M.fail(reason)
error( debug.traceback("Test failed", 2) )
unity.test.fail(reason)
end
---------------
-- Fungus Prefs
---------------
-- prefs is a handy short alias to the real fungusprefs
M.prefs = unity.fungusprefs
-------------
-- 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
-- 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")
assert(M.sayoptions.saydialog, "saydialog must not be nil")
M.sayoptions.saydialog.SetCharacter(character)
-- Do substitution on character name
local subbed = fungus.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)
assert(M.sayoptions.saydialog, "saydialog must not be nil")
-- Do variable substitution before displaying text
local subbed = fungus.sub(text)
local e = M.sayoptions.saydialog.SayInternal(subbed, M.sayoptions.clearprevious, M.sayoptions.waitforinput, M.sayoptions.fadewhendone, M.sayoptions.stopvoiceover, voiceclip)
fungus.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
-- 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)
assert(M.menuoptions.menudialog, "menudialog must not be nil")
-- Do variable substitution before displaying text
local subbed = fungus.sub(text)
M.menuoptions.menudialog.AddOption(subbed, interactive or true, unity.fungusscript, 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)
assert(M.menuoptions.menudialog, "menudialog must not be nil")
local e = M.menuoptions.menudialog.ShowTimer(duration, unity.fungusscript, callback)
fungus.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

8
Assets/Fungus/FungusScript/Resources/Lua/fungus.txt.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d189f86f383a341ac8dcfe22cb6309a1
timeCreated: 1458919194
licenseType: Free
TextScriptImporter:
userData:
assetBundleName:
assetBundleVariant:

331
Assets/Fungus/FungusScript/Resources/Lua/inspect.txt

@ -0,0 +1,331 @@
local inspect ={
_VERSION = 'inspect.lua 3.0.2',
_URL = 'http://github.com/kikito/inspect.lua',
_DESCRIPTION = 'human-readable representations of tables',
_LICENSE = [[
MIT LICENSE
Copyright (c) 2013 Enrique García Cota
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
}
inspect.KEY = setmetatable({}, {__tostring = function() return 'inspect.KEY' end})
inspect.METATABLE = setmetatable({}, {__tostring = function() return 'inspect.METATABLE' end})
-- returns the length of a table, ignoring __len (if it exists)
local rawlen = _G.rawlen or function(t) return #t end
-- Apostrophizes the string if it has quotes, but not aphostrophes
-- Otherwise, it returns a regular quoted string
local function smartQuote(str)
if str:match('"') and not str:match("'") then
return "'" .. str .. "'"
end
return '"' .. str:gsub('"', '\\"') .. '"'
end
local controlCharsTranslation = {
["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n",
["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v"
}
local function escape(str)
local result = str:gsub("\\", "\\\\"):gsub("(%c)", controlCharsTranslation)
return result
end
local function isIdentifier(str)
return type(str) == 'string' and str:match( "^[_%a][_%a%d]*$" )
end
local function isSequenceKey(k, length)
return type(k) == 'number'
and 1 <= k
and k <= length
and math.floor(k) == k
end
local defaultTypeOrders = {
['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4,
['function'] = 5, ['userdata'] = 6, ['thread'] = 7
}
local function sortKeys(a, b)
local ta, tb = type(a), type(b)
-- strings and numbers are sorted numerically/alphabetically
if ta == tb and (ta == 'string' or ta == 'number') then return a < b end
local dta, dtb = defaultTypeOrders[ta], defaultTypeOrders[tb]
-- Two default types are compared according to the defaultTypeOrders table
if dta and dtb then return defaultTypeOrders[ta] < defaultTypeOrders[tb]
elseif dta then return true -- default types before custom ones
elseif dtb then return false -- custom types after default ones
end
-- custom types are sorted out alphabetically
return ta < tb
end
local function getNonSequentialKeys(t)
local keys, length = {}, rawlen(t)
for k,_ in pairs(t) do
if not isSequenceKey(k, length) then table.insert(keys, k) end
end
table.sort(keys, sortKeys)
return keys
end
local function getToStringResultSafely(t, mt)
local __tostring = type(mt) == 'table' and rawget(mt, '__tostring')
local str, ok
if type(__tostring) == 'function' then
ok, str = pcall(__tostring, t)
str = ok and str or 'error: ' .. tostring(str)
end
if type(str) == 'string' and #str > 0 then return str end
end
local maxIdsMetaTable = {
__index = function(self, typeName)
rawset(self, typeName, 0)
return 0
end
}
local idsMetaTable = {
__index = function (self, typeName)
local col = {}
rawset(self, typeName, col)
return col
end
}
local function countTableAppearances(t, tableAppearances)
tableAppearances = tableAppearances or {}
if type(t) == 'table' then
if not tableAppearances[t] then
tableAppearances[t] = 1
for k,v in pairs(t) do
countTableAppearances(k, tableAppearances)
countTableAppearances(v, tableAppearances)
end
countTableAppearances(getmetatable(t), tableAppearances)
else
tableAppearances[t] = tableAppearances[t] + 1
end
end
return tableAppearances
end
local copySequence = function(s)
local copy, len = {}, #s
for i=1, len do copy[i] = s[i] end
return copy, len
end
local function makePath(path, ...)
local keys = {...}
local newPath, len = copySequence(path)
for i=1, #keys do
newPath[len + i] = keys[i]
end
return newPath
end
local function processRecursive(process, item, path)
if item == nil then return nil end
local processed = process(item, path)
if type(processed) == 'table' then
local processedCopy = {}
local processedKey
for k,v in pairs(processed) do
processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY))
if processedKey ~= nil then
processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey))
end
end
local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE))
setmetatable(processedCopy, mt)
processed = processedCopy
end
return processed
end
-------------------------------------------------------------------
local Inspector = {}
local Inspector_mt = {__index = Inspector}
function Inspector:puts(...)
local args = {...}
local buffer = self.buffer
local len = #buffer
for i=1, #args do
len = len + 1
buffer[len] = tostring(args[i])
end
end
function Inspector:down(f)
self.level = self.level + 1
f()
self.level = self.level - 1
end
function Inspector:tabify()
self:puts(self.newline, string.rep(self.indent, self.level))
end
function Inspector:alreadyVisited(v)
return self.ids[type(v)][v] ~= nil
end
function Inspector:getId(v)
local tv = type(v)
local id = self.ids[tv][v]
if not id then
id = self.maxIds[tv] + 1
self.maxIds[tv] = id
self.ids[tv][v] = id
end
return id
end
function Inspector:putKey(k)
if isIdentifier(k) then return self:puts(k) end
self:puts("[")
self:putValue(k)
self:puts("]")
end
function Inspector:putTable(t)
if t == inspect.KEY or t == inspect.METATABLE then
self:puts(tostring(t))
elseif self:alreadyVisited(t) then
self:puts('<table ', self:getId(t), '>')
elseif self.level >= self.depth then
self:puts('{...}')
else
if self.tableAppearances[t] > 1 then self:puts('<', self:getId(t), '>') end
local nonSequentialKeys = getNonSequentialKeys(t)
local length = rawlen(t)
local mt = getmetatable(t)
local toStringResult = getToStringResultSafely(t, mt)
self:puts('{')
self:down(function()
if toStringResult then
self:puts(' -- ', escape(toStringResult))
if length >= 1 then self:tabify() end
end
local count = 0
for i=1, length do
if count > 0 then self:puts(',') end
self:puts(' ')
self:putValue(t[i])
count = count + 1
end
for _,k in ipairs(nonSequentialKeys) do
if count > 0 then self:puts(',') end
self:tabify()
self:putKey(k)
self:puts(' = ')
self:putValue(t[k])
count = count + 1
end
if mt then
if count > 0 then self:puts(',') end
self:tabify()
self:puts('<metatable> = ')
self:putValue(mt)
end
end)
if #nonSequentialKeys > 0 or mt then -- result is multi-lined. Justify closing }
self:tabify()
elseif length > 0 then -- array tables have one extra space before closing }
self:puts(' ')
end
self:puts('}')
end
end
function Inspector:putValue(v)
local tv = type(v)
if tv == 'string' then
self:puts(smartQuote(escape(v)))
elseif tv == 'number' or tv == 'boolean' or tv == 'nil' then
self:puts(tostring(v))
elseif tv == 'table' then
self:putTable(v)
else
self:puts('<',tv,' ',self:getId(v),'>')
end
end
-------------------------------------------------------------------
function inspect.inspect(root, options)
options = options or {}
local depth = options.depth or math.huge
local newline = options.newline or '\n'
local indent = options.indent or ' '
local process = options.process
if process then
root = processRecursive(process, root, {})
end
local inspector = setmetatable({
depth = depth,
buffer = {},
level = 0,
ids = setmetatable({}, idsMetaTable),
maxIds = setmetatable({}, maxIdsMetaTable),
newline = newline,
indent = indent,
tableAppearances = countTableAppearances(root)
}, Inspector_mt)
inspector:putValue(root)
return table.concat(inspector.buffer)
end
setmetatable(inspect, { __call = function(_, ...) return inspect.inspect(...) end })
return inspect

8
Assets/Fungus/FungusScript/Resources/Lua/inspect.txt.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 05e8903e53b464591b902273f0a3cf3d
timeCreated: 1456487108
licenseType: Free
TextScriptImporter:
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Fungus/FungusScript/Resources/Prefabs.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 94ca1ff98b1a144009c9c9d9977fbe95
folderAsset: yes
timeCreated: 1456135684
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

55
Assets/Fungus/FungusScript/Resources/Prefabs/FungusBindings.prefab

@ -0,0 +1,55 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &178698
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 4
m_Component:
- 4: {fileID: 403334}
- 114: {fileID: 11414792}
m_Layer: 0
m_Name: FungusBindings
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &403334
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 178698}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
--- !u!114 &11414792
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 178698}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4cc8a659e950044b69d7c62696c36962, type: 3}
m_Name:
m_EditorClassIdentifier:
tableName:
boundObjects: []
boundTypes: []
--- !u!1001 &100100000
Prefab:
m_ObjectHideFlags: 1
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications: []
m_RemovedComponents: []
m_ParentPrefab: {fileID: 0}
m_RootGameObject: {fileID: 178698}
m_IsPrefabParent: 1

8
Assets/Fungus/FungusScript/Resources/Prefabs/FungusBindings.prefab.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e0c2b90c058ff43f4a56a266d4fa721b
timeCreated: 1455234100
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

65
Assets/Fungus/FungusScript/Resources/Prefabs/FungusInvoke.prefab

@ -0,0 +1,65 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &139298
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 4
m_Component:
- 4: {fileID: 449874}
- 114: {fileID: 11472914}
m_Layer: 0
m_Name: FungusInvoke
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &449874
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 139298}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
--- !u!114 &11472914
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 139298}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 446caeace65234baaacd52095d24f101, type: 3}
m_Name:
m_EditorClassIdentifier:
executeAfterTime: 1
repeatExecuteTime: 1
repeatEveryTime: 1
executeAfterFrames: 1
repeatExecuteFrame: 1
repeatEveryFrame: 1
hasFailed: 0
executeMethods: 2
fungusScript: {fileID: 0}
luaFile: {fileID: 0}
luaScript:
runAsCoroutine: 1
useFungusModule: 1
--- !u!1001 &100100000
Prefab:
m_ObjectHideFlags: 1
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications: []
m_RemovedComponents: []
m_ParentPrefab: {fileID: 0}
m_RootGameObject: {fileID: 139298}
m_IsPrefabParent: 1

8
Assets/Fungus/FungusScript/Resources/Prefabs/FungusInvoke.prefab.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c356764ac08ce4af2806a601a4f1e6e9
timeCreated: 1456135721
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

56
Assets/Fungus/FungusScript/Resources/Prefabs/FungusScript.prefab

@ -0,0 +1,56 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &100640
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 4
m_Component:
- 4: {fileID: 495584}
- 114: {fileID: 11493126}
m_Layer: 0
m_Name: FungusScript
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &495584
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 100640}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
--- !u!114 &11493126
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 100640}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ba19c26c1ba7243d2b57ebc4329cc7c6, type: 3}
m_Name:
m_EditorClassIdentifier:
remoteDebugger: 0
stringTable: {fileID: 0}
activeLanguage: en
timeScale: -1
--- !u!1001 &100100000
Prefab:
m_ObjectHideFlags: 1
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications: []
m_RemovedComponents: []
m_ParentPrefab: {fileID: 0}
m_RootGameObject: {fileID: 100640}
m_IsPrefabParent: 1

8
Assets/Fungus/FungusScript/Resources/Prefabs/FungusScript.prefab.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 49031c561e16d4fcf91c12153f8e0b25
timeCreated: 1455036757
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Fungus/FungusScript/Scripts.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: faeb3c27132254942b6ffd5acf46da3a
folderAsset: yes
timeCreated: 1454683902
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Fungus/FungusScript/Scripts/Editor.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 2f151bb1b31334ecea7f682307a2d687
folderAsset: yes
timeCreated: 1454428088
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

81
Assets/Fungus/FungusScript/Scripts/Editor/DropDownControl.cs

@ -0,0 +1,81 @@
// Adapted from the Unity Test Tools project (MIT license)
// https://bitbucket.org/Unity-Technologies/unitytesttools/src/a30d562427e9/Assets/UnityTestTools/
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Fungus
{
[Serializable]
internal class DropDownControl<T>
{
private readonly GUILayoutOption[] m_ButtonLayoutOptions = { GUILayout.ExpandWidth(true) };
public Func<T, string> convertForButtonLabel = s => s.ToString();
public Func<T, string> convertForGUIContent = s => s.ToString();
public Func<T[], bool> ignoreConvertForGUIContent = t => t.Length <= 40;
public Action<T> printContextMenu = null;
public string tooltip = "";
private object m_SelectedValue;
public void Draw(T selected, T[] options, Action<T> onValueSelected)
{
Draw(null,
selected,
options,
onValueSelected);
}
public void Draw(string label, T selected, T[] options, Action<T> onValueSelected)
{
Draw(label, selected, () => options, onValueSelected);
}
public void Draw(string label, T selected, Func<T[]> loadOptions, Action<T> onValueSelected)
{
if (!string.IsNullOrEmpty(label))
EditorGUILayout.BeginHorizontal();
var guiContent = new GUIContent(label);
var labelSize = EditorStyles.label.CalcSize(guiContent);
if (!string.IsNullOrEmpty(label))
GUILayout.Label(label, EditorStyles.label, GUILayout.Width(labelSize.x));
if (GUILayout.Button(new GUIContent(convertForButtonLabel(selected), tooltip),
EditorStyles.popup, m_ButtonLayoutOptions))
{
if (Event.current.button == 0)
{
PrintMenu(loadOptions());
}
else if (printContextMenu != null && Event.current.button == 1)
printContextMenu(selected);
}
if (m_SelectedValue != null)
{
onValueSelected((T)m_SelectedValue);
m_SelectedValue = null;
}
if (!string.IsNullOrEmpty(label))
EditorGUILayout.EndHorizontal();
}
public void PrintMenu(T[] options)
{
var menu = new GenericMenu();
foreach (var s in options)
{
var localS = s;
menu.AddItem(new GUIContent((ignoreConvertForGUIContent(options) ? localS.ToString() : convertForGUIContent(localS))),
false,
() => { m_SelectedValue = localS; }
);
}
menu.ShowAsContext();
}
}
}

12
Assets/Fungus/FungusScript/Scripts/Editor/DropDownControl.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 62435b27e6a904bd99a8ce6e38f05445
timeCreated: 1455233914
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

455
Assets/Fungus/FungusScript/Scripts/Editor/FungusBindingsEditor.cs

@ -0,0 +1,455 @@
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Rotorz.ReorderableList;
using System.Linq;
using System.Reflection;
using System.IO;
namespace Fungus
{
[CustomEditor (typeof(FungusBindings))]
public class FungusBindingsEditor : Editor
{
protected ReorderableList boundObjectsList;
protected SerializedProperty tableNameProp;
protected SerializedProperty boundObjectsProp;
protected string bindingHelpItem = "";
protected string bindingHelpDetail = "";
protected virtual void OnEnable()
{
tableNameProp = serializedObject.FindProperty("tableName");
boundObjectsProp = serializedObject.FindProperty("boundObjects");
CreateBoundObjectsList();
}
protected void CreateBoundObjectsList()
{
boundObjectsList = new ReorderableList(serializedObject, boundObjectsProp, true, true, true, true);
boundObjectsList.drawElementCallback =
(Rect rect, int index, bool isActive, bool isFocused) => {
var element = boundObjectsList.serializedProperty.GetArrayElementAtIndex(index);
rect.y += 2;
float widthA = rect.width * 0.25f;
float widthB = rect.width * 0.75f * 0.5f;
float widthC = rect.width * 0.75f * 0.5f;
SerializedProperty keyProp = element.FindPropertyRelative("key");
SerializedProperty objectProp = element.FindPropertyRelative("obj");
EditorGUI.BeginChangeCheck();
EditorGUI.PropertyField(
new Rect(rect.x, rect.y, widthA - 5, EditorGUIUtility.singleLineHeight),
keyProp, GUIContent.none);
if (EditorGUI.EndChangeCheck())
{
// Force the key to be a valid Lua variable name
FungusBindings fungusBindings = target as FungusBindings;
keyProp.stringValue = GetUniqueKey(fungusBindings, keyProp.stringValue, index);
}
EditorGUI.BeginChangeCheck();
EditorGUI.PropertyField(
new Rect(rect.x + widthA, rect.y, widthB - 5, EditorGUIUtility.singleLineHeight),
objectProp, GUIContent.none);
if (EditorGUI.EndChangeCheck())
{
// Use the object name as the key
string keyName = objectProp.objectReferenceValue.name;
FungusBindings fungusBindings = target as FungusBindings;
element.FindPropertyRelative("key").stringValue = GetUniqueKey(fungusBindings, keyName.ToLower(), index);
}
if (objectProp.objectReferenceValue != null)
{
GameObject go = objectProp.objectReferenceValue as GameObject;
if (go != null)
{
SerializedProperty componentProp = element.FindPropertyRelative("component");
int selected = 0;
List<string> options = new List<string>();
options.Add("<GameObject>");
int count = 1;
Component[] componentList = go.GetComponents<Component>();
foreach (Component component in componentList)
{
if (componentProp.objectReferenceValue == component)
{
selected = count;
}
string componentName = component.GetType().ToString().Replace("UnityEngine.", "");
options.Add(componentName);
count++;
}
int i = EditorGUI.Popup(
new Rect(rect.x + widthA + widthB, rect.y, widthC, EditorGUIUtility.singleLineHeight),
selected,
options.ToArray());
if (i == 0)
{
componentProp.objectReferenceValue = null;
}
else
{
componentProp.objectReferenceValue = componentList[i - 1];
}
}
}
boundObjectsList.onAddCallback = (ReorderableList l) => {
// Add a new item. This copies last item in the list, so clear new items values.
boundObjectsProp.InsertArrayElementAtIndex(boundObjectsProp.arraySize);
SerializedProperty newItem = boundObjectsProp.GetArrayElementAtIndex(boundObjectsProp.arraySize - 1);
newItem.FindPropertyRelative("key").stringValue = "";
newItem.FindPropertyRelative("obj").objectReferenceValue = null;
newItem.FindPropertyRelative("component").objectReferenceValue = null;
};
};
boundObjectsList.drawHeaderCallback = (Rect rect) => {
float widthA = rect.width * 0.25f;
float widthB = rect.width * 0.75f * 0.5f;
float widthC = rect.width * 0.75f * 0.5f;
EditorGUI.LabelField(new Rect(rect.x+ 12, rect.y, widthA, EditorGUIUtility.singleLineHeight), "Key");
EditorGUI.LabelField(new Rect(rect.x + widthA + 12, rect.y, widthB, EditorGUIUtility.singleLineHeight), "Object");
EditorGUI.LabelField(new Rect(rect.x + widthA + widthB + 6, rect.y, widthC, EditorGUIUtility.singleLineHeight), "Component");
};
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(tableNameProp);
EditorGUILayout.LabelField("Object Bindings");
boundObjectsList.DoLayoutList();
EditorGUILayout.Space();
ShowBindingMemberInfo();
// Update the bound types on every tick to make sure they're up to date.
// This could be a bit heavy on performance if the bound object list is long, but
// I couldn't get it to work reliably by only updating when the list has changed.
// This only happens when inspecting a Fungus Bindings component so I think it'll be ok.
PopulateBoundTypes();
serializedObject.ApplyModifiedProperties();
}
protected virtual void ShowBindingMemberInfo()
{
List<string> items = new List<string>();
items.Add("<Select a binding member>");
List<string> details = new List<string>();
details.Add("");
FungusBindings fungusBindings = target as FungusBindings;
foreach (FungusBindings.BoundObject boundObject in fungusBindings.boundObjects)
{
UnityEngine.Object inspectObject = boundObject.obj;
if (boundObject.component != null)
{
inspectObject = boundObject.component;
}
// Ignore empty entries
if (inspectObject == null ||
boundObject.key.Length == 0)
{
continue;
}
// Show info for fields and properties
MemberInfo[] memberInfos = inspectObject.GetType().GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly);
foreach (MemberInfo memberInfo in memberInfos)
{
if (memberInfo.MemberType != MemberTypes.Field &&
memberInfo.MemberType != MemberTypes.Property)
{
continue;
}
string item = boundObject.key + "/" + memberInfo.Name;
items.Add(item);
string detail = "";
detail += "Binding Key: " + boundObject.key + "\n";
detail += "Bound Object: " + boundObject.obj.name + "\n";
if (boundObject.component != null)
{
detail += "Bound Component: " + boundObject.component.GetType() + "\n";
}
if (memberInfo.MemberType == MemberTypes.Field)
{
detail += "Field Name: " + memberInfo.Name + "\n";
detail += "Field Type: " + (memberInfo as FieldInfo).FieldType;
}
else if (memberInfo.MemberType == MemberTypes.Property)
{
detail += "Property Name: " + memberInfo.Name + "\n";
detail += "Property Type: " + (memberInfo as PropertyInfo).PropertyType;
}
details.Add(detail);
}
// Show info for methods
foreach (MemberInfo memberInfo in memberInfos)
{
if (memberInfo.MemberType != MemberTypes.Method)
{
continue;
}
MethodInfo methodInfo = memberInfo as MethodInfo;
if (methodInfo.IsGenericMethod)
{
continue;
}
// Build list of parameters
string param = "";
foreach (ParameterInfo pi in methodInfo.GetParameters() )
{
if (param == "")
{
param += pi.Name;
}
else
{
param += ", " + pi.Name;
}
}
param = "(" + param + ")";
string item = boundObject.key + "/" + methodInfo.Name + param;
items.Add(item);
string detail = "";
detail += "Binding Key: " + boundObject.key + "\n";
detail += "Bound Object: " + boundObject.obj.name + "\n";
if (boundObject.component != null)
{
detail += "Bound Component: " + boundObject.component.GetType() + "\n";
}
detail += "Method Name: " + methodInfo.Name + "\n";
foreach (ParameterInfo pi in methodInfo.GetParameters() )
{
detail += "Parameter: " + pi.Name + " (" + pi.ParameterType.ToString() + ")\n";
}
detail += "Return Type : " + methodInfo.ReturnType.ToString();
details.Add(detail);
}
}
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel(new GUIContent("Member Info", "Display member info for the selected binding"));
GUILayout.FlexibleSpace();
// Display the popup list of bound members
int selectedIndex = EditorGUILayout.Popup(0, items.ToArray());
if (selectedIndex > 0)
{
bindingHelpItem = items[selectedIndex].Replace("/", ".");
bindingHelpDetail = details[selectedIndex];
}
EditorGUILayout.EndHorizontal();
// Show help info for currently selected item
if (bindingHelpItem != "")
{
EditorGUILayout.HelpBox(bindingHelpDetail, MessageType.Info);
EditorGUILayout.PrefixLabel(new GUIContent("Lua Usage", "A copyable example of how this item could be used in a Lua script."));
GUIStyle textAreaStyle = EditorStyles.textField;
textAreaStyle.wordWrap = true;
EditorGUILayout.TextArea(bindingHelpItem, textAreaStyle, GUILayout.MinHeight(EditorGUIUtility.singleLineHeight * 3));
}
}
/// <summary>
/// Returns a new binding key that is guaranteed to be a valid Lua variable name and
/// not to clash with any existing binding in the list.
/// </summary>
protected virtual string GetUniqueKey(FungusBindings fungusBindings, string originalKey, int ignoreIndex = -1)
{
string baseKey = originalKey;
// Only letters and digits allowed
char[] arr = baseKey.Where(c => (char.IsLetterOrDigit(c) || c == '_')).ToArray();
baseKey = new string(arr);
// No leading digits allowed
baseKey = baseKey.TrimStart('0','1','2','3','4','5','6','7','8','9');
// No empty keys allowed
if (baseKey.Length == 0)
{
baseKey = "object";
}
// Build a hash of all keys currently in use
HashSet<string> keyhash = new HashSet<string>();
for (int i = 0; i < fungusBindings.boundObjects.Count; ++i)
{
if (i == ignoreIndex)
{
continue;
}
keyhash.Add(fungusBindings.boundObjects[i].key);
}
// Append a suffix to make the key unique
string key = baseKey;
int suffix = 0;
while (keyhash.Contains(key))
{
suffix++;
key = baseKey + suffix;
}
return key;
}
/// <summary>
/// Update the list of bound types on the FungusBindings object.
/// </summary>
protected virtual void PopulateBoundTypes()
{
FungusBindings fungusBindings = target as FungusBindings;
// Use a temp HashSet to store the list of types.
// The final list is stored as a list of type strings.
HashSet<System.Type> typeSet = new HashSet<System.Type>();
foreach (FungusBindings.BoundObject boundObject in fungusBindings.boundObjects)
{
if (boundObject.obj == null)
{
continue;
}
AddAllSubTypes(typeSet, boundObject.obj.GetType());
if (boundObject.component != null)
{
AddAllSubTypes(typeSet, boundObject.component.GetType());
}
}
// Store the final list of types in the fungusBindings object
SerializedProperty boundTypesProp = serializedObject.FindProperty("boundTypes");
boundTypesProp.ClearArray();
int index = 0;
foreach (System.Type t in typeSet)
{
boundTypesProp.InsertArrayElementAtIndex(index);
SerializedProperty element = boundTypesProp.GetArrayElementAtIndex(index);
element.stringValue = t.AssemblyQualifiedName;
index++;
}
}
/// <summary>
/// Adds the type to the set of types, and then uses reflection to add
/// all public fields, properties and methods to the set of types.
/// </summary>
protected virtual void AddAllSubTypes(HashSet<System.Type> typeSet, System.Type t)
{
AddSubType(typeSet, t);
MemberInfo[] memberInfos = t.GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly);
foreach (MemberInfo memberInfo in memberInfos)
{
if (memberInfo.MemberType == MemberTypes.Field)
{
FieldInfo fieldInfo = memberInfo as FieldInfo;
AddSubType(typeSet, fieldInfo.FieldType);
}
else if (memberInfo.MemberType == MemberTypes.Property)
{
PropertyInfo propertyInfo = memberInfo as PropertyInfo;
AddSubType(typeSet, propertyInfo.PropertyType);
}
else if (memberInfo.MemberType == MemberTypes.Method)
{
MethodInfo methodInfo = memberInfo as MethodInfo;
if (methodInfo.IsGenericMethod)
{
continue;
}
if (methodInfo.ReturnType != typeof(void))
{
AddSubType(typeSet, methodInfo.ReturnType);
}
foreach (ParameterInfo pi in methodInfo.GetParameters() )
{
AddSubType(typeSet, pi.ParameterType);
}
}
}
}
/// <summary>
/// Adds a single type to the type set.
/// IEnumerable and IEnumerator types are handled specially.
/// </summary>
protected virtual void AddSubType(HashSet<System.Type> typeSet, System.Type t)
{
// MoonSharp handles IEnumerator and IEnumerable types automatically, so just
// register the generic type used.
if (typeof(IEnumerable).IsAssignableFrom(t) ||
typeof(IEnumerator).IsAssignableFrom(t))
{
System.Type[] genericArguments = t.GetGenericArguments();
if (genericArguments.Count() == 1)
{
System.Type containedType = genericArguments[0];
// The generic type could itself be an IEnumerator or IEnumerable, so
// recursively check for this case.
AddSubType(typeSet, containedType);
}
}
else
{
// Non-IEnumerable/IEnumerator types will be registered.
typeSet.Add(t);
}
}
}
}

12
Assets/Fungus/FungusScript/Scripts/Editor/FungusBindingsEditor.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 1b3ef64b6145248f6b3d106f09bace3a
timeCreated: 1455050970
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

197
Assets/Fungus/FungusScript/Scripts/Editor/FungusInvokeEditor.cs

@ -0,0 +1,197 @@
// Adapted from the Unity Test Tools project (MIT license)
// https://bitbucket.org/Unity-Technologies/unitytesttools/src/a30d562427e9/Assets/UnityTestTools/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace Fungus
{
[CustomEditor(typeof(FungusInvoke))]
public class FungusInvokeEditor : Editor
{
private readonly DropDownControl<Type> m_ComparerDropDown = new DropDownControl<Type>();
#region GUI Contents
private readonly GUIContent m_GUIExecuteAfterTimeGuiContent = new GUIContent("Execute after (seconds)", "After how many seconds the script should be executed");
private readonly GUIContent m_GUIRepeatExecuteTimeGuiContent = new GUIContent("Repeat execute", "Should the execution be repeated.");
private readonly GUIContent m_GUIRepeatEveryTimeGuiContent = new GUIContent("Frequency of repetitions", "How often should the execution be done");
private readonly GUIContent m_GUIExecuteAfterFramesGuiContent = new GUIContent("Execute after (frames)", "After how many frames the script should be executed");
private readonly GUIContent m_GUIRepeatExecuteFrameGuiContent = new GUIContent("Repeat execution", "Should the execution be repeated.");
#endregion
protected SerializedProperty fungusScriptProp;
protected SerializedProperty runAsCoroutineProp;
protected SerializedProperty luaFileProp;
protected SerializedProperty luaScriptProp;
protected SerializedProperty useFungusModuleProp;
protected List<TextAsset> luaFiles = new List<TextAsset>();
public FungusInvokeEditor()
{
m_ComparerDropDown.convertForButtonLabel = type => type.Name;
m_ComparerDropDown.convertForGUIContent = type => type.Name;
m_ComparerDropDown.ignoreConvertForGUIContent = types => false;
m_ComparerDropDown.tooltip = "Comparer that will be used to compare values and determine the result of assertion.";
}
public virtual void OnEnable()
{
fungusScriptProp = serializedObject.FindProperty("fungusScript");
runAsCoroutineProp = serializedObject.FindProperty("runAsCoroutine");
luaFileProp = serializedObject.FindProperty("luaFile");
luaScriptProp = serializedObject.FindProperty("luaScript");
useFungusModuleProp = serializedObject.FindProperty("useFungusModule");
// Make a note of all Lua files in the project resources
object[] result = Resources.LoadAll("Lua", typeof(TextAsset));
luaFiles.Clear();
foreach (object res in result)
{
TextAsset ta = res as TextAsset;
// Ignore the built-in modules as you'll never want to execute these
if (ta == null ||
ta.name == "fungus" ||
ta.name == "inspect")
{
continue;
}
luaFiles.Add(ta);
}
}
public override void OnInspectorGUI()
{
var fungusInvoke = (FungusInvoke)target;
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel(new GUIContent("On Event"));
fungusInvoke.executeMethods = (FungusInvoke.ExecuteMethod)EditorGUILayout.EnumMaskField(fungusInvoke.executeMethods,
EditorStyles.popup,
GUILayout.ExpandWidth(false));
EditorGUILayout.EndHorizontal();
if (fungusInvoke.IsExecuteMethodSelected(FungusInvoke.ExecuteMethod.AfterPeriodOfTime))
{
DrawOptionsForAfterPeriodOfTime(fungusInvoke);
}
if (fungusInvoke.IsExecuteMethodSelected(FungusInvoke.ExecuteMethod.Update))
{
DrawOptionsForOnUpdate(fungusInvoke);
}
if (Application.isPlaying)
{
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button(new GUIContent("Execute Now", "Execute the Lua script immediately.")))
{
fungusInvoke.Execute();
}
GUILayout.FlexibleSpace();
EditorGUILayout.EndHorizontal();
}
serializedObject.Update();
EditorGUILayout.PropertyField(fungusScriptProp);
EditorGUILayout.PropertyField(runAsCoroutineProp);
EditorGUILayout.PropertyField(useFungusModuleProp);
int selected = 0;
List<GUIContent> options = new List<GUIContent>();
options.Add(new GUIContent("<Lua Script>"));
int index = 1;
if (luaFiles != null)
{
foreach (TextAsset textAsset in luaFiles)
{
options.Add(new GUIContent(textAsset.name));
if (luaFileProp.objectReferenceValue == textAsset)
{
selected = index;
}
index++;
}
}
selected = EditorGUILayout.Popup(new GUIContent("Execute Lua", "Lua file or script to execute."), selected, options.ToArray());
if (selected == 0)
{
luaFileProp.objectReferenceValue = null;
}
else
{
luaFileProp.objectReferenceValue = luaFiles[selected - 1];
}
if (luaFileProp.objectReferenceValue == null)
{
EditorGUILayout.PropertyField(luaScriptProp);
}
else
{
EditorGUILayout.BeginHorizontal();
GUILayout.FlexibleSpace();
if (GUILayout.Button(new GUIContent("Open in Editor", "Open this Lua file in the external text editor.")))
{
string path = AssetDatabase.GetAssetPath(luaFileProp.objectReferenceValue);
UnityEditorInternal.InternalEditorUtility.OpenFileAtLineExternal(path, 0);
}
GUILayout.FlexibleSpace();
EditorGUILayout.EndHorizontal();
}
serializedObject.ApplyModifiedProperties();
}
private void DrawOptionsForAfterPeriodOfTime(FungusInvoke script)
{
EditorGUILayout.Space();
script.executeAfterTime = EditorGUILayout.FloatField(m_GUIExecuteAfterTimeGuiContent,
script.executeAfterTime);
if (script.executeAfterTime < 0)
script.executeAfterTime = 0;
script.repeatExecuteTime = EditorGUILayout.Toggle(m_GUIRepeatExecuteTimeGuiContent,
script.repeatExecuteTime);
if (script.repeatExecuteTime)
{
script.repeatEveryTime = EditorGUILayout.FloatField(m_GUIRepeatEveryTimeGuiContent,
script.repeatEveryTime);
if (script.repeatEveryTime < 0)
script.repeatEveryTime = 0;
}
}
private void DrawOptionsForOnUpdate(FungusInvoke script)
{
EditorGUILayout.Space();
script.executeAfterFrames = EditorGUILayout.IntField(m_GUIExecuteAfterFramesGuiContent,
script.executeAfterFrames);
if (script.executeAfterFrames < 1)
script.executeAfterFrames = 1;
script.repeatExecuteFrame = EditorGUILayout.Toggle(m_GUIRepeatExecuteFrameGuiContent,
script.repeatExecuteFrame);
if (script.repeatExecuteFrame)
{
script.repeatEveryFrame = EditorGUILayout.IntField(m_GUIRepeatEveryTimeGuiContent,
script.repeatEveryFrame);
if (script.repeatEveryFrame < 1)
script.repeatEveryFrame = 1;
}
}
}
}

12
Assets/Fungus/FungusScript/Scripts/Editor/FungusInvokeEditor.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 28e6892c983f34f42a3d6d03b5d199e7
timeCreated: 1455233798
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

89
Assets/Fungus/FungusScript/Scripts/Editor/MenuItems.cs

@ -0,0 +1,89 @@
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Collections;
namespace Fungus
{
public class MenuItems
{
[MenuItem("Tools/Fungus/Create/Fungus Script", false, 2000)]
static void CreateFungusScript()
{
SpawnPrefab("Prefabs/FungusScript", false);
}
[MenuItem("Tools/Fungus/Create/Fungus Bindings", false, 2001)]
static void CreateFungusBindings()
{
SpawnPrefab("Prefabs/FungusBindings", false);
}
[MenuItem("Tools/Fungus/Create/Fungus Invoke", false, 2002)]
static void CreateFungusInvoke()
{
SpawnPrefab("Prefabs/FungusInvoke", false);
}
[MenuItem("Tools/Fungus/Create/Lua File", false, 2100)]
static void CreateLuaFile()
{
string path = EditorUtility.SaveFilePanelInProject("Create Lua File", "script.txt", "txt", "Please select a file name for the new Lua script. Note: Lua files in Unity use the .txt extension.");
if(path.Length == 0)
{
return;
}
File.WriteAllText(path, "");
AssetDatabase.Refresh();
Object asset = AssetDatabase.LoadAssetAtPath<Object>(path);
if (asset != null)
{
EditorUtility.FocusProjectWindow();
EditorGUIUtility.PingObject(asset);
}
}
/// <summary>
/// Spawns a prefab in the scene based on it's filename in a Resources folder in the project.
/// If centerInScene is true then the object will be placed centered in the view window with z = 0.
/// If centerInScene is false the the object will be placed at (0,0,0)
/// </summary>
public static GameObject SpawnPrefab(string prefabName, bool centerInScene)
{
GameObject prefab = Resources.Load<GameObject>(prefabName);
if (prefab == null)
{
return null;
}
GameObject go = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
PrefabUtility.DisconnectPrefabInstance(go);
if (centerInScene)
{
SceneView view = SceneView.lastActiveSceneView;
if (view != null)
{
Camera sceneCam = view.camera;
Vector3 pos = sceneCam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, 10f));
pos.z = 0f;
go.transform.position = pos;
}
}
else
{
go.transform.position = Vector3.zero;
}
Selection.activeGameObject = go;
Undo.RegisterCreatedObjectUndo(go, "Create Object");
return go;
}
}
}

12
Assets/Fungus/FungusScript/Scripts/Editor/MenuItems.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 88272117b50644b24a3f22cadef823ae
timeCreated: 1455875727
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

153
Assets/Fungus/FungusScript/Scripts/FungusBindings.cs

@ -0,0 +1,153 @@
using UnityEngine;
using System;
using System.Reflection;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using MoonSharp.Interpreter;
namespace Fungus
{
/// <summary>
/// Component which manages a list of bound objects to be accessed in Lua scripts.
/// </summary>
[ExecuteInEditMode]
public class FungusBindings : MonoBehaviour
{
/// <summary>
/// Represents a single Unity object (+ optional component) bound to a string key.
/// </summary>
[Serializable]
public class BoundObject
{
public string key;
public UnityEngine.Object obj;
public Component component;
}
/// <summary>
/// Name of global table variable to store bindings in. If left blank then each binding will be added as a global variable.
/// </summary>
[Tooltip("Name of global table variable to store bindings in. If left blank then each binding will be added as a global variable.")]
public string tableName = "";
/// <summary>
/// The list of Unity objects to be bound for access in Lua.
/// </summary>
[Tooltip("The list of Unity objects to be bound to make them accessible in Lua script.")]
public List<BoundObject> boundObjects = new List<BoundObject>();
/// <summary>
/// The complete list of types used by the currently bound objects.
/// This includes the bound object types themselves, plus all the other types they use in public properties, fields and methods.
/// </summary>
[HideInInspector]
public List<string> boundTypes = new List<string>();
/// <summary>
/// Always ensure there is at least one row in the bound objects list.
/// </summary>
protected virtual void Update()
{
// Add in a single empty line at start
if (boundObjects.Count == 0)
{
boundObjects.Add(null);
}
}
/// <summary>
/// Add all declared bindings to the globals table.
/// </summary>
public virtual void AddBindings(Table globals)
{
Table bindingsTable = null;
if (tableName == "")
{
// Add directly to globals table
bindingsTable = globals;
}
else
{
DynValue res = globals.Get(tableName);
if (res.Type == DataType.Table)
{
// Add to an existing table
bindingsTable = res.Table;
}
else
{
// Create a new table
bindingsTable = new Table(globals.OwnerScript);
globals[tableName] = bindingsTable;
}
}
if (bindingsTable == null)
{
Debug.LogError("Bindings table must not be null");
}
RegisterBoundTypes();
for (int i = 0; i < boundObjects.Count; ++i)
{
// Ignore empty keys
string key = boundObjects[i].key;
if (key == null ||
key == "")
{
continue;
}
// Check for keys used multiple times
if (bindingsTable.Get(key).Type != DataType.Nil)
{
Debug.LogWarning("An item already exists with the same key as binding '" + key + "'. This binding will be ignored.");
continue;
}
// Ignore bindings with no object set
GameObject go = boundObjects[i].obj as GameObject;
if (go != null)
{
// Register as gameobject / components
Component component = boundObjects[i].component;
if (component == null)
{
// Bind the key to the gameobject
bindingsTable[key] = go;
}
else
{
// Bind the key to the component
bindingsTable[key] = component;
}
}
else
{
// Register as other UnityEngine.Object type
bindingsTable[key] = boundObjects[i].obj;
}
}
}
/// <summary>
/// Registers the list of bound types with MoonSharp.
/// </summary>
protected virtual void RegisterBoundTypes()
{
foreach (string typeName in boundTypes)
{
System.Type t = System.Type.GetType(typeName);
if (t != null &&
!UserData.IsTypeRegistered(t))
{
UserData.RegisterType(t);
}
}
}
}
}

12
Assets/Fungus/FungusScript/Scripts/FungusBindings.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 4cc8a659e950044b69d7c62696c36962
timeCreated: 1455049978
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

359
Assets/Fungus/FungusScript/Scripts/FungusInvoke.cs

@ -0,0 +1,359 @@
// Adapted from the Unity Test Tools project (MIT license)
// https://bitbucket.org/Unity-Technologies/unitytesttools/src/a30d562427e9/Assets/UnityTestTools/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using UnityEngine;
using Debug = UnityEngine.Debug;
using Object = UnityEngine.Object;
namespace Fungus
{
[Serializable]
public class FungusInvoke : MonoBehaviour, IFungusInvokeConfigurator
{
[Flags]
public enum ExecuteMethod
{
AfterPeriodOfTime = 1 << 0,
Start = 1 << 1,
Update = 1 << 2,
FixedUpdate = 1 << 3,
LateUpdate = 1 << 4,
OnDestroy = 1 << 5,
OnEnable = 1 << 6,
OnDisable = 1 << 7,
OnControllerColliderHit = 1 << 8,
OnParticleCollision = 1 << 9,
OnJointBreak = 1 << 10,
OnBecameInvisible = 1 << 11,
OnBecameVisible = 1 << 12,
OnTriggerEnter = 1 << 13,
OnTriggerExit = 1 << 14,
OnTriggerStay = 1 << 15,
OnCollisionEnter = 1 << 16,
OnCollisionExit = 1 << 17,
OnCollisionStay = 1 << 18,
OnTriggerEnter2D = 1 << 19,
OnTriggerExit2D = 1 << 20,
OnTriggerStay2D = 1 << 21,
OnCollisionEnter2D = 1 << 22,
OnCollisionExit2D = 1 << 23,
OnCollisionStay2D = 1 << 24,
}
[SerializeField] public float executeAfterTime = 1f;
[SerializeField] public bool repeatExecuteTime = true;
[SerializeField] public float repeatEveryTime = 1f;
[SerializeField] public int executeAfterFrames = 1;
[SerializeField] public bool repeatExecuteFrame = true;
[SerializeField] public int repeatEveryFrame = 1;
[SerializeField] public bool hasFailed;
[SerializeField] public ExecuteMethod executeMethods = ExecuteMethod.Start;
/// <summary>
/// The Lua script environment to use when executing.
/// </summary>
[Tooltip("The Lua script environment to use when executing.")]
public FungusScript fungusScript;
/// <summary>
/// Lua script file to execute.
/// </summary>
[Tooltip("Lua script file to execute.")]
public TextAsset luaFile;
/// <summary>
/// Lua script to execute.
/// </summary>
[Tooltip("Lua script to execute.")]
[TextArea(5, 50)]
public string luaScript = "";
/// <summary>
/// Run the script as a Lua coroutine so execution can be yielded for asynchronous operations.
/// </summary>
[Tooltip("Run the script as a Lua coroutine so execution can be yielded for asynchronous operations.")]
public bool runAsCoroutine = true;
/// <summary>
/// Require the fungus Lua module at the start of the script. Equivalent to 'local fungus = require('fungus')
/// </summary>
[Tooltip("Require the fungus Lua module at the start of the script. Equivalent to 'local fungus = require('fungus')")]
public bool useFungusModule = true;
private int m_ExecuteOnFrame;
protected string friendlyName = "";
// Recursively build the full hierarchy path to this game object
private static string GetPath(Transform current)
{
if (current.parent == null)
{
return current.name;
}
return GetPath(current.parent) + "." + current.name;
}
public void Start()
{
// If no FungusScript has been explicitly set then try to get one in the scene
if (fungusScript == null)
{
fungusScript = GetComponentInParent<FungusScript>();
}
if (fungusScript == null)
{
fungusScript = GameObject.FindObjectOfType<FungusScript>();
}
// Cache a descriptive name to use in Lua error messages
friendlyName = GetPath(transform) + ".FungusInvoke";
Execute(ExecuteMethod.Start);
if (IsExecuteMethodSelected(ExecuteMethod.AfterPeriodOfTime))
{
StartCoroutine(ExecutePeriodically());
}
if (IsExecuteMethodSelected(ExecuteMethod.Update))
{
m_ExecuteOnFrame = Time.frameCount + executeAfterFrames;
}
}
public IEnumerator ExecutePeriodically()
{
yield return new WaitForSeconds(executeAfterTime);
Execute(ExecuteMethod.AfterPeriodOfTime);
while (repeatExecuteTime)
{
yield return new WaitForSeconds(repeatEveryTime);
Execute(ExecuteMethod.AfterPeriodOfTime);
}
}
public bool ShouldExecuteOnFrame()
{
if (Time.frameCount > m_ExecuteOnFrame)
{
if (repeatExecuteFrame)
m_ExecuteOnFrame += repeatEveryFrame;
else
m_ExecuteOnFrame = Int32.MaxValue;
return true;
}
return false;
}
public void OnDisable()
{
Execute(ExecuteMethod.OnDisable);
}
public void OnEnable()
{
Execute(ExecuteMethod.OnEnable);
}
public void OnDestroy()
{
Execute(ExecuteMethod.OnDestroy);
}
public void Update()
{
if (IsExecuteMethodSelected(ExecuteMethod.Update) && ShouldExecuteOnFrame())
{
Execute(ExecuteMethod.Update);
}
}
public void FixedUpdate()
{
Execute(ExecuteMethod.FixedUpdate);
}
public void LateUpdate()
{
Execute(ExecuteMethod.LateUpdate);
}
public void OnControllerColliderHit()
{
Execute(ExecuteMethod.OnControllerColliderHit);
}
public void OnParticleCollision()
{
Execute(ExecuteMethod.OnParticleCollision);
}
public void OnJointBreak()
{
Execute(ExecuteMethod.OnJointBreak);
}
public void OnBecameInvisible()
{
Execute(ExecuteMethod.OnBecameInvisible);
}
public void OnBecameVisible()
{
Execute(ExecuteMethod.OnBecameVisible);
}
public void OnTriggerEnter()
{
Execute(ExecuteMethod.OnTriggerEnter);
}
public void OnTriggerExit()
{
Execute(ExecuteMethod.OnTriggerExit);
}
public void OnTriggerStay()
{
Execute(ExecuteMethod.OnTriggerStay);
}
public void OnCollisionEnter()
{
Execute(ExecuteMethod.OnCollisionEnter);
}
public void OnCollisionExit()
{
Execute(ExecuteMethod.OnCollisionExit);
}
public void OnCollisionStay()
{
Execute(ExecuteMethod.OnCollisionStay);
}
public void OnTriggerEnter2D()
{
Execute(ExecuteMethod.OnTriggerEnter2D);
}
public void OnTriggerExit2D()
{
Execute(ExecuteMethod.OnTriggerExit2D);
}
public void OnTriggerStay2D()
{
Execute(ExecuteMethod.OnTriggerStay2D);
}
public void OnCollisionEnter2D()
{
Execute(ExecuteMethod.OnCollisionEnter2D);
}
public void OnCollisionExit2D()
{
Execute(ExecuteMethod.OnCollisionExit2D);
}
public void OnCollisionStay2D()
{
Execute(ExecuteMethod.OnCollisionStay2D);
}
private void Execute(ExecuteMethod executeMethod)
{
if (IsExecuteMethodSelected(executeMethod))
{
Execute();
}
}
public bool IsExecuteMethodSelected(ExecuteMethod method)
{
return method == (executeMethods & method);
}
/// <summary>
/// Execute the Lua script immediately.
/// This is the function to call if you want to trigger execution from an external script.
/// </summary>
public virtual void Execute()
{
if (fungusScript == null)
{
Debug.LogWarning("No FungusScript selected");
}
else
{
string s = "";
if (useFungusModule)
{
s = "fungus = require('fungus')\n";
}
if (luaFile != null)
{
s += luaFile.text;
}
else if (luaScript.Length > 0)
{
s += luaScript;
}
fungusScript.DoLuaString(s, friendlyName, runAsCoroutine);
}
}
#region AssertionComponentConfigurator
public int UpdateExecuteStartOnFrame { set { executeAfterFrames = value; } }
public int UpdateExecuteRepeatFrequency { set { repeatEveryFrame = value; } }
public bool UpdateExecuteRepeat { set { repeatExecuteFrame = value; } }
public float TimeExecuteStartAfter { set { executeAfterTime = value; } }
public float TimeExecuteRepeatFrequency { set { repeatEveryTime = value; } }
public bool TimeExecuteRepeat { set { repeatExecuteTime = value; } }
public FungusInvoke Component { get { return this; } }
#endregion
}
public interface IFungusInvokeConfigurator
{
/// <summary>
/// If the assertion is evaluated in Update, after how many frame should the evaluation start. Defult is 1 (first frame)
/// </summary>
int UpdateExecuteStartOnFrame { set; }
/// <summary>
/// If the assertion is evaluated in Update and UpdateExecuteRepeat is true, how many frame should pass between evaluations
/// </summary>
int UpdateExecuteRepeatFrequency { set; }
/// <summary>
/// If the assertion is evaluated in Update, should the evaluation be repeated after UpdateExecuteRepeatFrequency frames
/// </summary>
bool UpdateExecuteRepeat { set; }
/// <summary>
/// If the assertion is evaluated after a period of time, after how many seconds the first evaluation should be done
/// </summary>
float TimeExecuteStartAfter { set; }
/// <summary>
/// If the assertion is evaluated after a period of time and TimeExecuteRepeat is true, after how many seconds should the next evaluation happen
/// </summary>
float TimeExecuteRepeatFrequency { set; }
/// <summary>
/// If the assertion is evaluated after a period, should the evaluation happen again after TimeExecuteRepeatFrequency seconds
/// </summary>
bool TimeExecuteRepeat { set; }
FungusInvoke Component { get; }
}
}

12
Assets/Fungus/FungusScript/Scripts/FungusInvoke.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 446caeace65234baaacd52095d24f101
timeCreated: 1455233789
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

110
Assets/Fungus/FungusScript/Scripts/FungusPrefs.cs

@ -0,0 +1,110 @@
using UnityEngine;
using System.Collections;
namespace Fungus
{
/// <summary>
/// Wrapper class for PlayerPrefs that adds the concept of multiple save slots.
/// Save slots allow you to store multiple player save profiles.
/// </summary>
public class FungusPrefs
{
/// <summary>
/// Deletes all saved values for all slots.
/// </summary>
public static void DeleteAll()
{
PlayerPrefs.DeleteAll();
}
/// <summary>
/// Removes key and its value from this save slot.
/// </summary>
public static void DeleteKey(int slot, string key)
{
string slotKey = GetSlotKey(slot, key);
PlayerPrefs.DeleteKey(slotKey);
}
/// <summary>
/// Returns the float value associated with this key in this save slot, it it exists.
/// </summary>
public static float GetFloat(int slot, string key, float defaultValue = 0f)
{
string slotKey = GetSlotKey(slot, key);
return PlayerPrefs.GetFloat(slotKey, defaultValue);
}
/// <summary>
/// Returns the int value associated with this key in this save slot, it it exists.
/// </summary>
public static int GetInt(int slot, string key, int defaultValue = 0)
{
string slotKey = GetSlotKey(slot, key);
return PlayerPrefs.GetInt(slotKey, defaultValue);
}
/// <summary>
/// Returns the string value associated with this key in this save slot, it it exists.
/// </summary>
public static string GetString(int slot, string key, string defaultValue = "")
{
string slotKey = GetSlotKey(slot, key);
return PlayerPrefs.GetString(slotKey, defaultValue);
}
/// <summary>
/// Returns true if the key exists in this save slot.
/// </summary>
public static bool HasKey(int slot, string key)
{
string slotKey = GetSlotKey(slot, key);
return PlayerPrefs.HasKey(slotKey);
}
/// <summary>
/// Writes all modified prefences to disk.
/// </summary>
public static void Save()
{
PlayerPrefs.Save();
}
/// <summary>
/// Sets the value of the preference identified by key for this save slot.
/// </summary>
public static void SetFloat(int slot, string key, float value)
{
string slotKey = GetSlotKey(slot, key);
PlayerPrefs.SetFloat(slotKey, value);
}
/// <summary>
/// Sets the value of the preference identified by key for this save slot.
/// </summary>
public static void SetInt(int slot, string key, int value)
{
string slotKey = GetSlotKey(slot, key);
PlayerPrefs.SetInt(slotKey, value);
}
/// <summary>
/// Sets the value of the preference identified by key for this save slot.
/// </summary>
public static void SetString(int slot, string key, string value)
{
string slotKey = GetSlotKey(slot, key);
PlayerPrefs.SetString(slotKey, value);
}
/// <summary>
/// Returns the combined key used to identify a key within a save slot.
/// </summary>
private static string GetSlotKey(int slot, string key)
{
return slot.ToString() + ":" + key;
}
}
}

12
Assets/Fungus/FungusScript/Scripts/FungusPrefs.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a9e5b64ab37dc4141963a6285c4000ee
timeCreated: 1455918227
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

527
Assets/Fungus/FungusScript/Scripts/FungusScript.cs

@ -0,0 +1,527 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
using System.Linq;
using System.Diagnostics;
using System.Text.RegularExpressions;
using MoonSharp.Interpreter;
using MoonSharp.Interpreter.Interop;
using MoonSharp.Interpreter.Loaders;
using MoonSharp.RemoteDebugger;
namespace Fungus
{
public class FungusScript : MonoBehaviour
{
/// <summary>
/// Custom file loader for MoonSharp that loads in all Lua scripts in the project.
/// Scripts must be placed in a Resources/Lua directory.
/// </summary>
protected class FungusScriptLoader : ScriptLoaderBase
{
// Give the script loader access to the list of accessible Lua Modules.
private IEnumerable<TextAsset> luaScripts;
public FungusScriptLoader(IEnumerable<TextAsset> luaScripts)
{
this.luaScripts = luaScripts;
}
/// <summary>
// Bypasses the standard path resolution logic for require.
/// </summary>
protected override string ResolveModuleName(string modname, string[] paths)
{
return modname;
}
public override object LoadFile(string file, Table globalContext)
{
foreach (TextAsset luaScript in luaScripts)
{
// Case insensitive string compare to allow standard Lua naming conventions in code
if (String.Compare(luaScript.name, file, true) == 0)
{
return luaScript.text;
}
}
return "";
}
public override bool ScriptFileExists(string name)
{
foreach (TextAsset luaScript in luaScripts)
{
// Case insensitive string compare to allow standard Lua naming conventions in code
if (String.Compare(luaScript.name, name, true) == 0)
{
return true;
}
}
return false;
}
}
protected Script interpreter;
/// <summary>
/// Returns the MoonSharp interpreter instance used to run Lua code.
/// </summary>
public Script Interpreter { get { return interpreter; } }
/// <summary>
/// Launches the remote Lua debugger in your browser and breaks execution at the first executed Lua command.
/// </summary>
[Tooltip("Launches the remote Lua debugger in your browser and breaks execution at the first executed Lua command.")]
public bool remoteDebugger = false;
/// <summary>
/// Lua script file which defines the global string table used for localisation.
/// </summary>
[Tooltip("Lua script file which defines the global string table used for localisation.")]
public TextAsset stringTable;
/// <summary>
/// The currently selected language in the string table. Affects variable substitution.
/// </summary>
[Tooltip("The currently selected language in the string table. Affects variable substitution.")]
public string activeLanguage = "en";
/// <summary>
/// Time scale factor to apply when running Lua scripts.
/// This allows pausing of a FungusScript by setting timescale to 0.
/// Use the GetTime() and GetDeltaTime() functions to get scaled time values.
/// If negative, then GetTime() and GetDeltaTime() return the same values as the standard Time class.
/// </summary>
[Tooltip("Time scale factor to apply when running Lua scripts. If negative then uses the same values as the standard Time class.")]
public float timeScale = -1f;
/// <summary>
/// Instance of remote debugging service when debugging option is enabled.
/// </summary>
protected RemoteDebuggerService remoteDebuggerService;
/// <summary>
/// Flag used to avoid startup dependency issues.
/// </summary>
protected bool initialised = false;
/// <summary>
/// Cached referenence to the string table (if loaded).
/// </summary>
protected Table stringTableCached;
protected virtual void Start()
{
InitInterpreter();
}
/// <summary>
/// Initialise the Lua interpreter so we can start running Lua code.
/// </summary>
public virtual void InitInterpreter()
{
if (initialised)
{
return;
}
Script.DefaultOptions.DebugPrint = (s) => { UnityEngine.Debug.Log(s); };
// In some use cases (e.g. downloadable Lua files) some Lua modules can pose a potential security risk.
// You can restrict which core lua modules are available here if needed.
// See the MoonSharp documentation for details.
interpreter = new Script(CoreModules.Preset_Complete);
RegisterLuaScriptFiles();
RegisterCLRTypes();
RegisterFungus();
RegisterCLRClassObjects();
RegisterBindings();
LoadStringTable();
if (remoteDebugger)
{
ActivateRemoteDebugger(interpreter);
}
initialised = true;
}
/// <summary>
/// Register all Lua files in the project so they can be accessed at runtime.
/// </summary>
protected virtual void RegisterLuaScriptFiles()
{
object[] result = Resources.LoadAll("Lua", typeof(TextAsset));
interpreter.Options.ScriptLoader = new FungusScriptLoader(result.OfType<TextAsset>());
}
/// <summary>
/// Registers a commonly used subset of Unity types for Lua interop.
/// To register more types externally to this class, register them in the Awake method of any
/// monobehavior in your scene.
/// </summary>
protected virtual void RegisterCLRTypes()
{
// Core types needed by FungusScript
UserData.RegisterType<GameObject>();
UserData.RegisterType<Component>();
UserData.RegisterType<MonoBehaviour>();
UserData.RegisterType<ScriptableObject>();
UserData.RegisterType<IEnumerator>();
UserData.RegisterType<UnityEngine.Coroutine>();
UserData.RegisterType<Task>();
// Monobehaviors and other Unity.Objects
UserData.RegisterType<FungusScript>();
UserData.RegisterType<Transform>();
UserData.RegisterType<RectTransform>();
UserData.RegisterType<Material>();
UserData.RegisterType<Texture>();
UserData.RegisterType<Sprite>();
UserData.RegisterType<AudioClip>();
UserData.RegisterType<AudioSource>();
// Value types
UserData.RegisterType<Vector2>();
UserData.RegisterType<Vector3>();
UserData.RegisterType<Rect>();
UserData.RegisterType<Quaternion>();
UserData.RegisterType<Color>();
UserData.RegisterType<Time>();
UserData.RegisterType<FungusPrefs>();
}
/// <summary>
/// Registers the most common types used by Fungus.
/// </summary>
protected virtual void RegisterFungus()
{
RegisterFungusTypes.Register();
}
/// <summary>
/// Registers a commonly used subset of Unity class objects for Lua interop.
/// To register more class objects externally to this class, register them in the Awake method of any
/// monobehavior in your scene.
/// </summary>
protected virtual void RegisterCLRClassObjects()
{
// Add the CLR class objects to a global unity table
Table unityTable = new Table(interpreter);
interpreter.Globals["unity"] = unityTable;
// Instances of these types can be created in Lua using e.g. c = unity.color.__new()
unityTable["vector2"] = typeof(Vector2);
unityTable["vector3"] = typeof(Vector3);
unityTable["rect"] = typeof(Rect);
unityTable["quaternion"] = typeof(Quaternion);
unityTable["color"] = typeof(Color);
// Static classes
unityTable["time"] = UserData.CreateStatic(typeof(Time));
unityTable["fungusprefs"] = UserData.CreateStatic(typeof(FungusPrefs));
// This FungusScript object
unityTable["fungusscript"] = this;
// Provide access to the Unity Test Tools (if available).
Type testType = Type.GetType("IntegrationTest");
if (testType != null)
{
UserData.RegisterType(testType);
unityTable["test"] = UserData.CreateStatic(testType);
}
// Example of how to register an enum
// UserData.RegisterType<MyClass.MyEnum>();
// interpreter.Globals.Set("MyEnum", UserData.CreateStatic<MyClass.MyEnum>());
}
/// <summary>
/// Binds all gameobjects and components defined in FungusBinding objects to the global scene table.
/// </summary>
protected virtual void RegisterBindings()
{
FungusBindings[] bindings = GameObject.FindObjectsOfType<FungusBindings>();
foreach (FungusBindings binding in bindings)
{
binding.AddBindings(interpreter.Globals);
}
}
/// <summary>
/// Loads the global string table used for localisation.
/// </summary>
protected virtual void LoadStringTable()
{
if (stringTable != null)
{
try
{
DynValue stringTableRes = interpreter.DoString(stringTable.text);
if (stringTableRes.Type == DataType.Table)
{
stringTableCached = stringTableRes.Table;
interpreter.Globals["stringtable"] = stringTableCached;
}
}
catch (ScriptRuntimeException ex)
{
UnityEngine.Debug.LogError("Lua runtime error: " + ex.DecoratedMessage);
}
catch (InterpreterException ex)
{
UnityEngine.Debug.LogError(ex.DecoratedMessage);
}
}
}
/// <summary>
/// Returns a string from the string table for this key.
/// The string returned depends on the active language.
/// </summary>
public virtual string GetString(string key)
{
if (stringTableCached != null)
{
// Match against string table and active language
DynValue stringTableVar = stringTableCached.Get(key);
if (stringTableVar.Type == DataType.Table)
{
DynValue languageEntry = stringTableVar.Table.Get(activeLanguage);
if (languageEntry.Type == DataType.String)
{
return languageEntry.String;
}
}
}
return "";
}
/// <summary>
/// Substitutes specially formatted tokens in the text with global variables and string table values.
/// The string table value used depends on the currently loaded string table and active language.
/// </summary>
public virtual string Substitute(string text)
{
string subbedText = text;
// Instantiate the regular expression object.
Regex r = new Regex("\\[\\$.*?\\]");
// Match the regular expression pattern against a text string.
var results = r.Matches(text);
foreach (Match match in results)
{
string key = match.Value.Substring(2, match.Value.Length - 3);
if (stringTableCached != null)
{
// Match against string table and active language
DynValue stringTableVar = stringTableCached.Get(key);
if (stringTableVar.Type == DataType.Table)
{
DynValue languageEntry = stringTableVar.Table.Get(activeLanguage);
if (languageEntry.Type == DataType.String)
{
subbedText = subbedText.Replace(match.Value, languageEntry.String);
}
continue;
}
}
// Match against global variables
DynValue globalVar = interpreter.Globals.Get(key);
if (globalVar.Type != DataType.Nil)
{
subbedText = subbedText.Replace(match.Value, globalVar.ToPrintString());
continue;
}
}
return subbedText;
}
/// <summary>
/// Returns the time since level load, multiplied by timeScale.
/// If timeScale is negative then returns the same as Time.timeSinceLevelLoaded.
/// </summary>
public float GetTime()
{
if (timeScale < 0f)
{
return Time.timeSinceLevelLoad;
}
else
{
return Time.unscaledTime * timeScale;
}
}
/// <summary>
/// Returns the delta time this frame, multiplied by timeScale.
/// If timeScale is negative then returns the same as Time.deltaTime.
/// </summary>
public float GetDeltaTime()
{
if (timeScale < 0f)
{
return Time.deltaTime;
}
else
{
return Time.deltaTime * timeScale;
}
}
/// <summary>
/// Load and run a string containing Lua script. May be run as a coroutine.
/// <param name="luaString">The Lua code to be run.</param>
/// <param name="friendlyName">A descriptive name to be used in error reports.</param>
/// <param name="runAsCoroutine">Run the Lua code as a coroutine to support asynchronous operations.</param>
/// <param name="onComplete">Method to callback when the Lua code finishes exection. Supports return parameters.</param>
/// </summary>
public void DoLuaString(string luaString, string friendlyName, bool runAsCoroutine, Action<DynValue> onComplete = null)
{
InitInterpreter();
// Load the Lua script
DynValue res = null;
try
{
res = interpreter.LoadString(luaString, null, friendlyName);
}
catch (InterpreterException ex)
{
UnityEngine.Debug.LogError(ex.DecoratedMessage + "\n" + luaString);
}
if (res == null)
{
if (onComplete != null)
{
onComplete(null);
}
return;
}
// Execute the Lua script
if (runAsCoroutine)
{
StartCoroutine(RunLuaCoroutineInternal(res.Function, luaString, onComplete));
}
else
{
DynValue returnValue = null;
try
{
returnValue = res.Function.Call();
}
catch (InterpreterException ex)
{
UnityEngine.Debug.LogError(ex.DecoratedMessage + "\n" + luaString);
}
if (onComplete != null)
{
onComplete(returnValue);
}
}
}
/// <summary>
/// Starts a Unity coroutine which updates a Lua coroutine each frame.
/// <param name="closure">A MoonSharp closure object representing a function.</param>
/// <param name="debugInfo">Debug text to display if an exception occurs (usually the Lua code that is being executed).</param>
/// <param name="onComplete">A delegate method that is called when the coroutine completes. Includes return parameter.</param>
/// </summary>
public void RunLuaCoroutine(Closure closure, string debugInfo, Action<DynValue> onComplete = null)
{
StartCoroutine(RunLuaCoroutineInternal(closure, debugInfo, onComplete));
}
/// <summary>
/// A Unity coroutine method which updates a Lua coroutine each frame.
/// <param name="closure">A MoonSharp closure object representing a function.</param>
/// <param name="debugInfo">Debug text to display if an exception occurs (usually the Lua code that is being executed).</param>
/// <param name="onComplete">A delegate method that is called when the coroutine completes. Includes return parameter.</param>
/// </summary>
protected IEnumerator RunLuaCoroutineInternal(Closure closure, string debugInfo, Action<DynValue> onComplete = null)
{
DynValue co = interpreter.CreateCoroutine(closure);
DynValue returnValue = null;
while (co.Coroutine.State != CoroutineState.Dead)
{
try
{
returnValue = co.Coroutine.Resume();
}
catch (InterpreterException ex)
{
UnityEngine.Debug.LogError(ex.DecoratedMessage + "\n" + debugInfo);
}
yield return null;
}
if (onComplete != null)
{
onComplete(returnValue);
}
}
/// <summary>
/// Start a Unity coroutine from a Lua call.
/// </summary>
public Task RunUnityCoroutine(IEnumerator coroutine)
{
if (coroutine == null)
{
return null;
}
// We use the Task class so we can poll the coroutine to check if it has finished.
// Standard Unity coroutines don't support this check.
return new Task(RunUnityCoroutineImpl(coroutine));
}
/// <summary>
/// Starts a standard Unity coroutine.
/// The coroutine is managed by the FungusScript monobehavior, so you can call StopAllCoroutines to
/// stop all active coroutines later.
/// </summary>
protected virtual IEnumerator RunUnityCoroutineImpl(IEnumerator coroutine)
{
if (coroutine == null)
{
UnityEngine.Debug.LogWarning("Coroutine must not be null");
yield break;
}
yield return StartCoroutine(coroutine);
}
protected virtual void ActivateRemoteDebugger(Script script)
{
if (remoteDebuggerService == null)
{
remoteDebuggerService = new RemoteDebuggerService();
// the last boolean is to specify if the script is free to run
// after attachment, defaults to false
remoteDebuggerService.Attach(script, gameObject.name, false);
}
// start the web-browser at the correct url. Replace this or just
// pass the url to the user in some way.
Process.Start(remoteDebuggerService.HttpUrlStringLocalHost);
}
}
}

12
Assets/Fungus/FungusScript/Scripts/FungusScript.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: ba19c26c1ba7243d2b57ebc4329cc7c6
timeCreated: 1454343267
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Fungus/FungusScript/Thirdparty.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: b370c105afb8a4e32bb641b7f6c6048c
folderAsset: yes
timeCreated: 1454683923
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Fungus/FungusScript/Thirdparty/FungusExtensions.meta vendored

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: e8ec7018e2e8c474e8ae39737a286c0a
folderAsset: yes
timeCreated: 1456312519
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

155
Assets/Fungus/FungusScript/Thirdparty/FungusExtensions/ExecuteLua.cs vendored

@ -0,0 +1,155 @@
using UnityEngine;
using System.Collections;
using Fungus;
using MoonSharp.Interpreter;
namespace Fungus
{
[CommandInfo("FungusScript",
"Execute Lua",
"Executes a Lua code chunk using a FungusScript object.")]
public class ExecuteLua : Command
{
[Tooltip("FungusScript to use to execute this Lua script")]
public FungusScript fungusScript;
[TextArea(10,100)]
[Tooltip("Lua script to execute. Use {$VarName} to insert a Flowchart variable in the Lua script.")]
public string luaScript;
/// <summary>
/// Require the fungus Lua module at the start of the script. Equivalent to 'local fungus = require('fungus')
/// </summary>
[Tooltip("Require the fungus Lua module at the start of the script. Equivalent to 'local fungus = require('fungus')")]
public bool useFungusModule = true;
[Tooltip("Execute this Lua script as a Lua coroutine")]
public bool runAsCoroutine = true;
[Tooltip("Pause command execution until the Lua script has finished execution")]
public bool waitUntilFinished = true;
[Tooltip("A Flowchart variable to store the returned value in.")]
[VariableProperty()]
public Variable returnVariable;
protected string friendlyName = "";
protected virtual void Start()
{
// Cache a descriptive name to use in Lua error messages
friendlyName = gameObject.name + "." + parentBlock.blockName + "." + "ExecuteLua #" + commandIndex.ToString();
}
public override void OnEnter()
{
if (fungusScript == null)
{
Debug.LogWarning("No FungusScript object selected");
Continue();
return;
}
string s = "";
if (useFungusModule)
{
s = "fungus = require('fungus')\n";
}
string subbed = s + GetFlowchart().SubstituteVariables(luaScript);
fungusScript.DoLuaString(subbed, friendlyName, runAsCoroutine, (returnValue) => {
StoreReturnVariable(returnValue);
if (waitUntilFinished)
{
Continue();
}
});
if (!waitUntilFinished)
{
Continue();
}
}
protected virtual void StoreReturnVariable(DynValue returnValue)
{
if (returnVariable == null || returnValue == null)
{
return;
}
// Store the return value in a Fungus Variable
System.Type variableType = returnVariable.GetType();
if (variableType == typeof(BooleanVariable) && returnValue.Type == DataType.Boolean)
{
(returnVariable as BooleanVariable).value = returnValue.Boolean;
}
else if (variableType == typeof(IntegerVariable) && returnValue.Type == DataType.Number)
{
(returnVariable as IntegerVariable).value = (int)returnValue.Number;
}
else if (variableType == typeof(FloatVariable) && returnValue.Type == DataType.Number)
{
(returnVariable as FloatVariable).value = (float)returnValue.Number;
}
else if (variableType == typeof(StringVariable) && returnValue.Type == DataType.String)
{
(returnVariable as StringVariable).value = returnValue.String;
}
else if (variableType == typeof(ColorVariable) && returnValue.Type == DataType.UserData)
{
(returnVariable as ColorVariable).value = returnValue.CheckUserDataType<Color>("ExecuteLua.StoreReturnVariable");
}
else if (variableType == typeof(GameObjectVariable) && returnValue.Type == DataType.UserData)
{
(returnVariable as GameObjectVariable).value = returnValue.CheckUserDataType<GameObject>("ExecuteLua.StoreReturnVariable");
}
else if (variableType == typeof(MaterialVariable) && returnValue.Type == DataType.UserData)
{
(returnVariable as MaterialVariable).value = returnValue.CheckUserDataType<Material>("ExecuteLua.StoreReturnVariable");
}
else if (variableType == typeof(ObjectVariable) && returnValue.Type == DataType.UserData)
{
(returnVariable as ObjectVariable).value = returnValue.CheckUserDataType<Object>("ExecuteLua.StoreReturnVariable");
}
else if (variableType == typeof(SpriteVariable) && returnValue.Type == DataType.UserData)
{
(returnVariable as SpriteVariable).value = returnValue.CheckUserDataType<Sprite>("ExecuteLua.StoreReturnVariable");
}
else if (variableType == typeof(TextureVariable) && returnValue.Type == DataType.UserData)
{
(returnVariable as TextureVariable).value = returnValue.CheckUserDataType<Texture>("ExecuteLua.StoreReturnVariable");
}
else if (variableType == typeof(Vector2Variable) && returnValue.Type == DataType.UserData)
{
(returnVariable as Vector2Variable).value = returnValue.CheckUserDataType<Vector2>("ExecuteLua.StoreReturnVariable");
}
else if (variableType == typeof(Vector3Variable) && returnValue.Type == DataType.UserData)
{
(returnVariable as Vector3Variable).value = returnValue.CheckUserDataType<Vector3>("ExecuteLua.StoreReturnVariable");
}
else
{
Debug.LogError("Failed to convert " + returnValue.Type.ToLuaTypeString() + " return type to " + variableType.ToString());
}
}
public override string GetSummary()
{
if (fungusScript == null)
{
return "Error: No FungusScript object selected";
}
return luaScript;
}
public override Color GetButtonColor()
{
return new Color32(235, 191, 217, 255);
}
}
}

12
Assets/Fungus/FungusScript/Thirdparty/FungusExtensions/ExecuteLua.cs.meta vendored

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 71f455683d4ba4405b8dbba457159620
timeCreated: 1456398214
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

97
Assets/Fungus/FungusScript/Thirdparty/FungusExtensions/FungusScriptExtensions.cs vendored

@ -0,0 +1,97 @@
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using Fungus;
using MoonSharp.Interpreter;
namespace Fungus
{
public static class FungusScriptExtensions
{
/// <summary>
/// Extension for MenuDialog that allows AddOption to call a Lua function when an option is selected.
/// </summary>
public static bool AddOption(this MenuDialog menuDialog, string text, bool interactable, FungusScript fungusScript, Closure callBack)
{
bool addedOption = false;
foreach (Button button in menuDialog.cachedButtons)
{
if (!button.gameObject.activeSelf)
{
button.gameObject.SetActive(true);
button.interactable = interactable;
Text textComponent = button.GetComponentInChildren<Text>();
if (textComponent != null)
{
textComponent.text = text;
}
button.onClick.AddListener(delegate {
menuDialog.StopAllCoroutines(); // Stop timeout
menuDialog.Clear();
menuDialog.HideSayDialog();
menuDialog.gameObject.SetActive(false);
if (callBack != null)
{
fungusScript.RunLuaCoroutine(callBack, text);
}
});
addedOption = true;
break;
}
}
return addedOption;
}
/// <summary>
/// Extension for MenuDialog that allows ShowTimer to call a Lua function when the timer expires.
/// </summary>
public static IEnumerator ShowTimer(this MenuDialog menuDialog, float duration, FungusScript fungusScript, Closure callBack)
{
if (menuDialog.cachedSlider == null ||
duration <= 0f)
{
yield break;
}
menuDialog.cachedSlider.gameObject.SetActive(true);
menuDialog.StopAllCoroutines();
float elapsedTime = 0;
Slider timeoutSlider = menuDialog.GetComponentInChildren<Slider>();
while (elapsedTime < duration)
{
if (timeoutSlider != null)
{
float t = 1f - elapsedTime / duration;
timeoutSlider.value = t;
}
elapsedTime += Time.deltaTime;
yield return null;
}
menuDialog.Clear();
menuDialog.gameObject.SetActive(false);
menuDialog.HideSayDialog();
if (callBack != null)
{
fungusScript.RunLuaCoroutine(callBack, "menutimer");
}
}
}
}

12
Assets/Fungus/FungusScript/Thirdparty/FungusExtensions/FungusScriptExtensions.cs.meta vendored

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: d3cdbb71635f4406baec64f33d24514f
timeCreated: 1456230091
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

40
Assets/Fungus/FungusScript/Thirdparty/FungusExtensions/RegisterFungusTypes.cs vendored

@ -0,0 +1,40 @@
using UnityEngine;
using System.Collections;
using MoonSharp.Interpreter;
using Fungus;
namespace Fungus
{
public class RegisterFungusTypes
{
/// <summary>
/// Extension for FungusScript that registers all types used by Fungus.
/// </summary>
public static void Register()
{
UserData.RegisterType<Flowchart>();
UserData.RegisterType<Block>();
UserData.RegisterType<Variable>();
UserData.RegisterType<BooleanVariable>();
UserData.RegisterType<ColorVariable>();
UserData.RegisterType<FloatVariable>();
UserData.RegisterType<GameObjectVariable>();
UserData.RegisterType<IntegerVariable>();
UserData.RegisterType<MaterialVariable>();
UserData.RegisterType<ObjectVariable>();
UserData.RegisterType<SpriteVariable>();
UserData.RegisterType<StringVariable>();
UserData.RegisterType<TextureVariable>();
UserData.RegisterType<Vector2Variable>();
UserData.RegisterType<Vector3Variable>();
UserData.RegisterType<AnimatorVariable>();
UserData.RegisterType<AudioSourceVariable>();
UserData.RegisterType<TransformVariable>();
// Extension types
UserData.RegisterExtensionType(typeof(FungusScriptExtensions));
}
}
}

12
Assets/Fungus/FungusScript/Thirdparty/FungusExtensions/RegisterFungusTypes.cs.meta vendored

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: becdb52a4ba7c476d89008442adfc3ef
timeCreated: 1458920418
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Fungus/FungusScript/Thirdparty/MoonSharp.meta vendored

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 483efc3d00eeb41e99e9472ecf3c3bd4
folderAsset: yes
timeCreated: 1454345352
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

36
Assets/Fungus/FungusScript/Thirdparty/MoonSharp/LICENSE vendored

@ -0,0 +1,36 @@
Copyright (c) 2014, Marco Mastropaolo
All rights reserved.
Parts of the string library are based on the KopiLua project (https://github.com/NLua/KopiLua)
Copyright (c) 2012 LoDC
Debugger icons are from the Eclipse project (https://www.eclipse.org/).
Copyright of The Eclipse Foundation
The MoonSharp icon is (c) Isaac, 2014-2015
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

8
Assets/Fungus/FungusScript/Thirdparty/MoonSharp/LICENSE.meta vendored

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 77bed9ffa87904128bf91eb0d73bd35e
timeCreated: 1455193522
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Hardwire.dll vendored

Binary file not shown.

24
Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Hardwire.dll.meta vendored

@ -0,0 +1,24 @@
fileFormatVersion: 2
guid: 39a7bcc4c4db443cc85a13a12555c9f7
timeCreated: 1456222254
licenseType: Free
PluginImporter:
serializedVersion: 1
iconMap: {}
executionOrder: {}
isPreloaded: 0
platformData:
Any:
enabled: 1
settings: {}
Editor:
enabled: 0
settings:
DefaultValueInitialized: true
WindowsStoreApps:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Hardwire.pdb vendored

Binary file not shown.

8
Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Hardwire.pdb.meta vendored

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: af73bc91714a54f6a9e72ca6770987d8
timeCreated: 1456222253
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Interpreter.dll vendored

Binary file not shown.

24
Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Interpreter.dll.meta vendored

@ -0,0 +1,24 @@
fileFormatVersion: 2
guid: 2d32648e4d82e4c3e837a7ad11352ac0
timeCreated: 1454345354
licenseType: Free
PluginImporter:
serializedVersion: 1
iconMap: {}
executionOrder: {}
isPreloaded: 0
platformData:
Any:
enabled: 1
settings: {}
Editor:
enabled: 0
settings:
DefaultValueInitialized: true
WindowsStoreApps:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Interpreter.pdb vendored

Binary file not shown.

8
Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Interpreter.pdb.meta vendored

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 45b1b1eac93b04a4a8d6ec29d4803aa9
timeCreated: 1454345352
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

7750
Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Interpreter.xml vendored

File diff suppressed because it is too large Load Diff

8
Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.Interpreter.xml.meta vendored

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 894a26d5d6ca04417aef855d8dfefaf0
timeCreated: 1454345354
licenseType: Free
TextScriptImporter:
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.RemoteDebugger.dll vendored

Binary file not shown.

24
Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.RemoteDebugger.dll.meta vendored

@ -0,0 +1,24 @@
fileFormatVersion: 2
guid: c3effdd4e9d074bcbb90e8773303ad3b
timeCreated: 1455193529
licenseType: Free
PluginImporter:
serializedVersion: 1
iconMap: {}
executionOrder: {}
isPreloaded: 0
platformData:
Any:
enabled: 1
settings: {}
Editor:
enabled: 0
settings:
DefaultValueInitialized: true
WindowsStoreApps:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.RemoteDebugger.pdb vendored

Binary file not shown.

8
Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.RemoteDebugger.pdb.meta vendored

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f5996939cde6945dbaa205884e73d770
timeCreated: 1455193522
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.pdb vendored

Binary file not shown.

8
Assets/Fungus/FungusScript/Thirdparty/MoonSharp/MoonSharp.pdb.meta vendored

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4375c8dc0d3dd47a782783697a009e01
timeCreated: 1456222253
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Fungus/FungusScript/Thirdparty/TaskManager.meta vendored

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: bf214384dd01b4f59a0569536329c190
folderAsset: yes
timeCreated: 1455049414
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

214
Assets/Fungus/FungusScript/Thirdparty/TaskManager/TaskManager.cs vendored

@ -0,0 +1,214 @@
/// TaskManager.cs
/// Copyright (c) 2011, Ken Rockot <k-e-n-@-REMOVE-CAPS-AND-HYPHENS-oz.gs>. All rights reserved.
/// Everyone is granted non-exclusive license to do anything at all with this code.
///
/// This is a new coroutine interface for Unity.
///
/// The motivation for this is twofold:
///
/// 1. The existing coroutine API provides no means of stopping specific
/// coroutines; StopCoroutine only takes a string argument, and it stops
/// all coroutines started with that same string; there is no way to stop
/// coroutines which were started directly from an enumerator. This is
/// not robust enough and is also probably pretty inefficient.
///
/// 2. StartCoroutine and friends are MonoBehaviour methods. This means
/// that in order to start a coroutine, a user typically must have some
/// component reference handy. There are legitimate cases where such a
/// constraint is inconvenient. This implementation hides that
/// constraint from the user.
///
/// Example usage:
///
/// ----------------------------------------------------------------------------
/// IEnumerator MyAwesomeTask()
/// {
/// while(true) {
/// Debug.Log("Logcat iz in ur consolez, spammin u wif messagez.");
/// yield return null;
//// }
/// }
///
/// IEnumerator TaskKiller(float delay, Task t)
/// {
/// yield return new WaitForSeconds(delay);
/// t.Stop();
/// }
///
/// void SomeCodeThatCouldBeAnywhereInTheUniverse()
/// {
/// Task spam = new Task(MyAwesomeTask());
/// new Task(TaskKiller(5, spam));
/// }
/// ----------------------------------------------------------------------------
///
/// When SomeCodeThatCouldBeAnywhereInTheUniverse is called, the debug console
/// will be spammed with annoying messages for 5 seconds.
///
/// Simple, really. There is no need to initialize or even refer to TaskManager.
/// When the first Task is created in an application, a "TaskManager" GameObject
/// will automatically be added to the scene root with the TaskManager component
/// attached. This component will be responsible for dispatching all coroutines
/// behind the scenes.
///
/// Task also provides an event that is triggered when the coroutine exits.
using UnityEngine;
using System.Collections;
/// A Task object represents a coroutine. Tasks can be started, paused, and stopped.
/// It is an error to attempt to start a task that has been stopped or which has
/// naturally terminated.
public class Task
{
/// Returns true if and only if the coroutine is running. Paused tasks
/// are considered to be running.
public bool Running {
get {
return task.Running;
}
}
/// Returns true if and only if the coroutine is currently paused.
public bool Paused {
get {
return task.Paused;
}
}
/// Delegate for termination subscribers. manual is true if and only if
/// the coroutine was stopped with an explicit call to Stop().
public delegate void FinishedHandler(bool manual);
/// Termination event. Triggered when the coroutine completes execution.
public event FinishedHandler Finished;
/// Creates a new Task object for the given coroutine.
///
/// If autoStart is true (default) the task is automatically started
/// upon construction.
public Task(IEnumerator c, bool autoStart = true)
{
task = TaskManager.CreateTask(c);
task.Finished += TaskFinished;
if(autoStart)
Start();
}
/// Begins execution of the coroutine
public void Start()
{
task.Start();
}
/// Discontinues execution of the coroutine at its next yield.
public void Stop()
{
task.Stop();
}
public void Pause()
{
task.Pause();
}
public void Unpause()
{
task.Unpause();
}
void TaskFinished(bool manual)
{
FinishedHandler handler = Finished;
if(handler != null)
handler(manual);
}
TaskManager.TaskState task;
}
class TaskManager : MonoBehaviour
{
public class TaskState
{
public bool Running {
get {
return running;
}
}
public bool Paused {
get {
return paused;
}
}
public delegate void FinishedHandler(bool manual);
public event FinishedHandler Finished;
IEnumerator coroutine;
bool running;
bool paused;
bool stopped;
public TaskState(IEnumerator c)
{
coroutine = c;
}
public void Pause()
{
paused = true;
}
public void Unpause()
{
paused = false;
}
public void Start()
{
running = true;
singleton.StartCoroutine(CallWrapper());
}
public void Stop()
{
stopped = true;
running = false;
}
IEnumerator CallWrapper()
{
yield return null;
IEnumerator e = coroutine;
while(running) {
if(paused)
yield return null;
else {
if(e != null && e.MoveNext()) {
yield return e.Current;
}
else {
running = false;
}
}
}
FinishedHandler handler = Finished;
if(handler != null)
handler(stopped);
}
}
static TaskManager singleton;
public static TaskState CreateTask(IEnumerator coroutine)
{
if(singleton == null) {
GameObject go = new GameObject("TaskManager");
singleton = go.AddComponent<TaskManager>();
}
return new TaskState(coroutine);
}
}

12
Assets/Fungus/FungusScript/Thirdparty/TaskManager/TaskManager.cs.meta vendored

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 12a405989c9fd46e3924b54166aa0e4c
timeCreated: 1454589006
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

9
Assets/FungusExamples/FungusScript.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 8ab8afbfde36d4bc4ac6615dba9b64f9
folderAsset: yes
timeCreated: 1458925240
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Tests/FungusScript.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: b8cbda23563c24ee493cae4e639ed67e
folderAsset: yes
timeCreated: 1456153619
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9861
Assets/Tests/FungusScript/FungusTests.unity

File diff suppressed because it is too large Load Diff

8
Assets/Tests/FungusScript/FungusTests.unity.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cadf03bc0402c437fafc9762bfb14663
timeCreated: 1456153613
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

1704
Assets/Tests/FungusScript/ScriptingTests.unity

File diff suppressed because it is too large Load Diff

8
Assets/Tests/FungusScript/ScriptingTests.unity.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3f657bc2681724af29e56b16b97d9ed1
timeCreated: 1455270559
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Tests/Resources.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 49de283ddba5a4377a7a78f199f82d7e
folderAsset: yes
timeCreated: 1455889299
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Tests/Resources/Lua.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 33a4676250b33487eb5c027888e492a7
folderAsset: yes
timeCreated: 1455889308
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Tests/Resources/Lua/teststringtable.txt

@ -0,0 +1,9 @@
local M = {}
M.hello =
{
en = "Hi there",
fr = "Bonjour"
}
return M;

8
Assets/Tests/Resources/Lua/teststringtable.txt.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9900570d789fa4b29957e4b897af9e3b
timeCreated: 1455889334
licenseType: Free
TextScriptImporter:
userData:
assetBundleName:
assetBundleVariant:

0
Assets/Tests/Animation/TestAnim.anim → Assets/Tests/TestAssets/Animation/TestAnim.anim

0
Assets/Tests/Animation/TestAnim.anim.meta → Assets/Tests/TestAssets/Animation/TestAnim.anim.meta

0
Assets/Tests/Animation/TestAnim.unity → Assets/Tests/TestAssets/Animation/TestAnim.unity

0
Assets/Tests/Animation/TestAnim.unity.meta → Assets/Tests/TestAssets/Animation/TestAnim.unity.meta

0
Assets/Tests/Animation/TestSprite.controller → Assets/Tests/TestAssets/Animation/TestSprite.controller

0
Assets/Tests/Animation/TestSprite.controller.meta → Assets/Tests/TestAssets/Animation/TestSprite.controller.meta

0
Assets/Tests/Audio/AudioTests.unity → Assets/Tests/TestAssets/Audio/AudioTests.unity

0
Assets/Tests/Audio/AudioTests.unity.meta → Assets/Tests/TestAssets/Audio/AudioTests.unity.meta

BIN
Assets/Tests/TestAssets/Audio/voiceover.ogg

Binary file not shown.

22
Assets/Tests/TestAssets/Audio/voiceover.ogg.meta

@ -0,0 +1,22 @@
fileFormatVersion: 2
guid: d2ab1fbe555d44e9e870311657856bdc
timeCreated: 1456156794
licenseType: Free
AudioImporter:
serializedVersion: 6
defaultSettings:
loadType: 0
sampleRateSetting: 0
sampleRateOverride: 44100
compressionFormat: 1
quality: 1
conversionMode: 0
platformSettingOverrides: {}
forceToMono: 0
normalize: 1
preloadAudioData: 1
loadInBackground: 0
3D: 1
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Tests/TestAssets/Material.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 29e05612baa3440c9966497e70e5f03c
folderAsset: yes
timeCreated: 1456417871
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

138
Assets/Tests/TestAssets/Material/TestMaterial.mat

@ -0,0 +1,138 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: TestMaterial
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords:
m_LightmapFlags: 5
m_CustomRenderQueue: -1
stringTagMap: {}
m_SavedProperties:
serializedVersion: 2
m_TexEnvs:
data:
first:
name: _MainTex
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
data:
first:
name: _BumpMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
data:
first:
name: _DetailNormalMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
data:
first:
name: _ParallaxMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
data:
first:
name: _OcclusionMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
data:
first:
name: _EmissionMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
data:
first:
name: _DetailMask
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
data:
first:
name: _DetailAlbedoMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
data:
first:
name: _MetallicGlossMap
second:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
data:
first:
name: _SrcBlend
second: 1
data:
first:
name: _DstBlend
second: 0
data:
first:
name: _Cutoff
second: 0.5
data:
first:
name: _Parallax
second: 0.02
data:
first:
name: _ZWrite
second: 1
data:
first:
name: _Glossiness
second: 0.5
data:
first:
name: _BumpScale
second: 1
data:
first:
name: _OcclusionStrength
second: 1
data:
first:
name: _DetailNormalMapScale
second: 1
data:
first:
name: _UVSec
second: 0
data:
first:
name: _Mode
second: 0
data:
first:
name: _Metallic
second: 0
m_Colors:
data:
first:
name: _EmissionColor
second: {r: 0, g: 0, b: 0, a: 1}
data:
first:
name: _Color
second: {r: 1, g: 1, b: 1, a: 1}

8
Assets/Tests/TestAssets/Material/TestMaterial.mat.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 97a4dac23b6bb49888243026c50076a9
timeCreated: 1456417879
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

9
Assets/Tests/TestAssets/Texture.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: ecd214168ef7d46948192ac5b15df61c
folderAsset: yes
timeCreated: 1456418449
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/Tests/TestAssets/Texture/MousePointer.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

57
Assets/Tests/TestAssets/Texture/MousePointer.png.meta

@ -0,0 +1,57 @@
fileFormatVersion: 2
guid: efe8aa62cc87f4b70b9272e4e8e06668
timeCreated: 1456418478
licenseType: Free
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 1
linearTexture: 0
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
cubemapConvolution: 0
cubemapConvolutionSteps: 8
cubemapConvolutionExponent: 1.5
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 2048
textureSettings:
filterMode: -1
aniso: 16
mipBias: -1
wrapMode: 1
nPOTScale: 1
lightmap: 0
rGBM: 0
compressionQuality: 50
allowsAlphaSplitting: 0
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 0
textureType: 0
buildTargetSettings: []
spriteSheet:
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:
Loading…
Cancel
Save