1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
local function indexOf(table, value) for i, v in ipairs(table) do if v == value then return i end end return -1 end
local observableStack = {} function observableStack.push(callback) table.insert(observableStack, callback) end function observableStack.pop() table.remove(observableStack, #observableStack) end function observableStack.current() return observableStack[#observableStack]; end
local observables = {}
local observableValues = {}
local observableCallbacks = {}
local function hasObservable(caller, key) if key then return observables[caller] and indexOf(observables[caller], key) > 0 end return observables[caller] ~= nil end
local function callbackObservable(caller, key, value) if observableCallbacks[caller][key] then for _, func in ipairs(observableCallbacks[caller][key]) do func() end end end
local function setAndCallObservable(caller, key, value) observableValues[caller][key] = value callbackObservable(caller, key) end
local function addObservable(caller, key, value) if hasObservable(caller, key) then return end if not value then value = caller[key]; end caller[key] = nil if not observables[caller] then observables[caller] = {} observableValues[caller] = {} observableCallbacks[caller] = {} end table.insert(observables[caller], key) observableValues[caller][key] = value if not observableCallbacks[caller][key] then observableCallbacks[caller][key] = {} end end
local function getObservableValue(caller, key) return observableValues[caller][key] end
local function newDisposer(callback) return function() for _, caller in pairs(observableCallbacks) do for _, key in pairs(caller) do local index = indexOf(key, callback); while index > 0 do table.remove(key, index); index = indexOf(key, callback); end end end end end
function observable(caller, key, value) if not hasObservable(caller) then setmetatable(caller, { __newindex = function(c, k, v) if hasObservable(c, k) then if not (getObservableValue(c, k) == v) then setAndCallObservable(c, k, v) end else rawset(c, k, v) end end, __index = function(caller, key) if hasObservable(caller, key) then local callback = observableStack.current() if callback then if indexOf(observableCallbacks[caller][key], callback) <= 0 then table.insert(observableCallbacks[caller][key], callback) end end return getObservableValue(caller, key) end end }) end addObservable(caller, key, value) end
function autorun(func) if nil then local function f() observableStack.push(f); func(); observableStack.pop(); end f() return newDisposer(f); end observableStack.push(func); func() observableStack.pop(); return newDisposer(func); end
|