Recursive message passing in a collection (SOLVED)

Hi,
I want to recursively update all of the things within a collection so that their “team” setting is accurate.

For example
coreseg.go

go.property("team", 0)

function init(self)
	print("team is", self.team)
	msg.post(".", hash("update_team"), { team = self.team })
end

segment.go

function on_message(self, message_id, message, sender)
	if message_id == hash("update_team") then
		local tint = vmath.vector4(0, self.team/2, self.team/5, 1) -- just placeholder
		go.set("#sprite", "tint", tint)
	end
end

main.script

function init(self)
	msg.post(".", "acquire_input_focus")
	msg.post("@render:", "use_fixed_fit_projection", { near = -1, far = 1 })
	
	local rot = vmath.quat_rotation_z(0)
	
	local props1 = {}
	props1[hash("/core")] = { team = 1 }

	local props2 = {}
	props2[hash("/core")] = { team = 2 }

	collectionfactory.create("#hestiafactory", vmath.vector3(200,200,0), rot, props1)
	collectionfactory.create("#hestiafactory", vmath.vector3(300,300,0), rot, props2)
end

The hierarchy of the object being created by #hestiafactory looks like this:

But I’m only getting the message on the “core” node – I also want to see it on “segment11”, and “segment12”, “segment13” … etc however many segments I add automatically.

I sort of assumed that this was the core use-case of the message passing system.

Well… I was approaching this entirely wrong. I think the documentation for Defold’s message passing system could do with some better ‘prompts’ about how to achieve certain patterns.

For example, I was approaching the problem from the idea that the parent should try and update all of its children. That was pretty futile because the most elegant way in Defold (it’s beautiful, btw) is for the children to just post to the parent and get a response sent directly to them. For example:

segment.go

function init(self)
	msg.post("core", hash("seg_created"))
end

function final(self)
	msg.post("core", hash("seg_destroyed"))
end

function update(self, dt)
	-- Add update code here
	-- Remove this function if not needed
end

function on_message(self, message_id, message, sender)
	if message_id == hash("set_team") then
		self.team = message.team
	elseif message_id == hash("set_tint") then
		go.set("#sprite", "tint", message.tint)
	end
end

coreseg.go

go.property("team", 0)

function init(self)
	-- Add initialization code here
	-- Remove this function if not needed
	print("team is", self.team)
end

function final(self)
	-- Add finalization code here
	-- Remove this function if not needed
end

function update(self, dt)
	-- Add update code here
	-- Remove this function if not needed
end

function on_message(self, message_id, message, sender)
	if message_id == hash("seg_created") then
		msg.post(sender, hash("set_team"), { team = self.team })
		msg.post(sender, hash("set_tint"), { tint = mk_segment_tint(self.team) })
	end
end

function mk_segment_tint(team)
	--local mag = math.random(0.8, 1)
	--local intensity = vmath.vector4(mag, mag, mag, 1)
	
	if team == 0 then
		return vmath.vector4(1, 1, 1, 1)
	elseif team == 1 then
		return vmath.vector4(1, 0, 1, 1)
	else
		return vmath.vector4(1, 1, 0, 1)
	end
end

This is pretty amazing because it handles arbitrary arrangements and depths of segments, but it’s only a few lines of code.

Now that I am more aware of the msg.post(sender, ...) pattern, this pretty much cleans up any concerns that I had with Defolds way of doing things.

1 Like

Message passing is for one-to-one messages. No broadcast out of the box, but easy to build using a Lua module if needed (broadcast.lua and docs).

Yes, it’s quite useful to have access to the sender to be able to “reply” if needed.

1 Like