Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
Nathan Lam committed Feb 15, 2017
2 parents c68b6ac + f2a2578 commit 8016549
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@ install:

script:
- busted

branches:
only:
- master
84 changes: 84 additions & 0 deletions scene.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ local function min_bounds(x, y, half_width, half_height)
return x - half_width, y - half_height
end

local function insert_all(src, dest)
for _, value in ipairs(src) do
table.insert(dest, value)
end
end

--[[
A node representing a local transform.
--]]
Expand All @@ -36,6 +42,7 @@ function node:init(params)
self.halfw = (params and params.halfw) or 0
self.halfh = (params and params.halfh) or 0
self._id = (params and params.id) or nil
self.listeners = {}
end

-- Adds id to id tables of all ancestors
Expand Down Expand Up @@ -187,6 +194,83 @@ function node:calc_bounds()
end
end

function node:on(event_type, listener)
self.listeners[event_type] = self.listeners[event_type] or {}
table.insert(self.listeners[event_type], listener)
return listener
end

function node:off(event_type, listener)
if listener == nil then
self.listeners[event_type] = nil
else
local pos = nil
for i, value in ipairs(self.listeners[event_type]) do
if value == listener then
pos = i
break
end
end

if pos ~= nil then
table.remove(self.listeners[event_type], pos)
end
end
end

-- Sends event to current node only
function node:fire(event_type, ...)
for _, listener in ipairs(self.listeners[event_type]) do
local stopLocal, stopGlobal = listener(...)
if stopGlobal then
return false
elseif stopLocal then
break
end
end

return true
end

-- Sends event to root
function node:emit(event_type, ...)
if not self:fire(event_type, ...) then
return
end

if self.parent then
self.parent:emit(event_type, ...)
end
end

-- Sends event to descendents
function node:broadcast(event_type, ...)
if not self:fire(event_type, ...) then
return
end

if not self.children then
return
end

-- Breadth first traversal of scene tree
local queue = {}
local qpos = 1
insert_all(self.children, queue)
while qpos <= #queue do
local next = queue[qpos]
if not next:fire(event_type, ...) then
return
end

if next.children then
insert_all(next.children, queue)
end

qpos = qpos + 1
end
end

scene.node = node

-----------------------------------------------
Expand Down
74 changes: 74 additions & 0 deletions spec/event_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
local scene = require('scene')

local describe = require('busted').describe
local it = require('busted').it

describe("event listeners", function()
it("can be attached to nodes", function()
local node = scene.node()
node:on("test", function(obj)
obj.test_value = true
end)

local event = {test_value=false}
node:fire("test", event)
assert.is_true(event.test_value)
end)

it("can be removed", function()
local node = scene.node()
local listener = node:on("test", function()
print("will be removed")
end)

assert.is_equal(#node.listeners["test"], 1)
node:off("test", listener)
assert.is_equal(#node.listeners["test"], 0)
end)

it("can be emitted", function()
local node1 = scene.node()
local node2 = scene.node()
local node3 = scene.node()

node1:attach(node2)
node2:attach(node3)

local listener = node1:on("test", function(obj)
obj.test_value = obj.test_value + 1
end)
node2:on("test", listener)
node3:on("test", listener)

local test_obj = {test_value=0}
node3:emit("test", test_obj)

assert.is_equal(test_obj.test_value, 3)
end)

it("can be broadcasted", function()
local node1 = scene.node{id="1"}
local node2 = scene.node{id="2"}
local node3 = scene.node{id="3"}

node1:attach(node2)
node1:attach(node3)

node1:on("test", function(obj)
table.insert(obj.received, node1)
end)
node2:on("test", function(obj)
table.insert(obj.received, node2)
end)
node3:on("test", function(obj)
table.insert(obj.received, node3)
end)

local test_obj = {received={}}
node1:broadcast("test", test_obj)

assert.is_equal(test_obj.received[1], node1)
assert.is_equal(test_obj.received[2], node2)
assert.is_equal(test_obj.received[3], node3)
end)
end)

0 comments on commit 8016549

Please sign in to comment.