chrisgregan
9 years ago
93 changed files with 27980 additions and 4 deletions
@ -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: |
@ -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: |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 0319726c027694d388d69066da479b61 |
||||||
|
timeCreated: 1457363324 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: f739410aaa44d4fbca15e7fee5842e50 |
||||||
|
timeCreated: 1457362432 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: ad95753a2eeea4611980e3a03ebd8826 |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1455555043 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 479e25ea74c6e467f80ffa29bb049e0d |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1454938226 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 |
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: d189f86f383a341ac8dcfe22cb6309a1 |
||||||
|
timeCreated: 1458919194 |
||||||
|
licenseType: Free |
||||||
|
TextScriptImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 |
||||||
|
|
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 05e8903e53b464591b902273f0a3cf3d |
||||||
|
timeCreated: 1456487108 |
||||||
|
licenseType: Free |
||||||
|
TextScriptImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 94ca1ff98b1a144009c9c9d9977fbe95 |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1456135684 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 |
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: e0c2b90c058ff43f4a56a266d4fa721b |
||||||
|
timeCreated: 1455234100 |
||||||
|
licenseType: Free |
||||||
|
NativeFormatImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 |
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: c356764ac08ce4af2806a601a4f1e6e9 |
||||||
|
timeCreated: 1456135721 |
||||||
|
licenseType: Free |
||||||
|
NativeFormatImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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 |
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 49031c561e16d4fcf91c12153f8e0b25 |
||||||
|
timeCreated: 1455036757 |
||||||
|
licenseType: Free |
||||||
|
NativeFormatImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: faeb3c27132254942b6ffd5acf46da3a |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1454683902 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 2f151bb1b31334ecea7f682307a2d687 |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1454428088 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 62435b27e6a904bd99a8ce6e38f05445 |
||||||
|
timeCreated: 1455233914 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 1b3ef64b6145248f6b3d106f09bace3a |
||||||
|
timeCreated: 1455050970 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 28e6892c983f34f42a3d6d03b5d199e7 |
||||||
|
timeCreated: 1455233798 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 88272117b50644b24a3f22cadef823ae |
||||||
|
timeCreated: 1455875727 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 4cc8a659e950044b69d7c62696c36962 |
||||||
|
timeCreated: 1455049978 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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; } |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 446caeace65234baaacd52095d24f101 |
||||||
|
timeCreated: 1455233789 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: a9e5b64ab37dc4141963a6285c4000ee |
||||||
|
timeCreated: 1455918227 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: ba19c26c1ba7243d2b57ebc4329cc7c6 |
||||||
|
timeCreated: 1454343267 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: b370c105afb8a4e32bb641b7f6c6048c |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1454683923 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: e8ec7018e2e8c474e8ae39737a286c0a |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1456312519 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 71f455683d4ba4405b8dbba457159620 |
||||||
|
timeCreated: 1456398214 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: d3cdbb71635f4406baec64f33d24514f |
||||||
|
timeCreated: 1456230091 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: becdb52a4ba7c476d89008442adfc3ef |
||||||
|
timeCreated: 1458920418 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 483efc3d00eeb41e99e9472ecf3c3bd4 |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1454345352 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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. |
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 77bed9ffa87904128bf91eb0d73bd35e |
||||||
|
timeCreated: 1455193522 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
Binary file not shown.
@ -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: |
Binary file not shown.
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: af73bc91714a54f6a9e72ca6770987d8 |
||||||
|
timeCreated: 1456222253 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
Binary file not shown.
@ -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: |
Binary file not shown.
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 45b1b1eac93b04a4a8d6ec29d4803aa9 |
||||||
|
timeCreated: 1454345352 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 894a26d5d6ca04417aef855d8dfefaf0 |
||||||
|
timeCreated: 1454345354 |
||||||
|
licenseType: Free |
||||||
|
TextScriptImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
Binary file not shown.
@ -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: |
Binary file not shown.
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: f5996939cde6945dbaa205884e73d770 |
||||||
|
timeCreated: 1455193522 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
Binary file not shown.
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 4375c8dc0d3dd47a782783697a009e01 |
||||||
|
timeCreated: 1456222253 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: bf214384dd01b4f59a0569536329c190 |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1455049414 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 12a405989c9fd46e3924b54166aa0e4c |
||||||
|
timeCreated: 1454589006 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 8ab8afbfde36d4bc4ac6615dba9b64f9 |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1458925240 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: b8cbda23563c24ee493cae4e639ed67e |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1456153619 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: cadf03bc0402c437fafc9762bfb14663 |
||||||
|
timeCreated: 1456153613 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 3f657bc2681724af29e56b16b97d9ed1 |
||||||
|
timeCreated: 1455270559 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 49de283ddba5a4377a7a78f199f82d7e |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1455889299 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 33a4676250b33487eb5c027888e492a7 |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1455889308 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
local M = {} |
||||||
|
|
||||||
|
M.hello = |
||||||
|
{ |
||||||
|
en = "Hi there", |
||||||
|
fr = "Bonjour" |
||||||
|
} |
||||||
|
|
||||||
|
return M; |
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 9900570d789fa4b29957e4b897af9e3b |
||||||
|
timeCreated: 1455889334 |
||||||
|
licenseType: Free |
||||||
|
TextScriptImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
Binary file not shown.
@ -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: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 29e05612baa3440c9966497e70e5f03c |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1456417871 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -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} |
@ -0,0 +1,8 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 97a4dac23b6bb49888243026c50076a9 |
||||||
|
timeCreated: 1456417879 |
||||||
|
licenseType: Free |
||||||
|
NativeFormatImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: ecd214168ef7d46948192ac5b15df61c |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1456418449 |
||||||
|
licenseType: Free |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
After Width: | Height: | Size: 4.2 KiB |
@ -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…
Reference in new issue