brybott
Visitor
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
01-28-2016
04:06 PM
sending info from scene graph to main thread
I understand that to pass information from a scene graph node, I can set observeField with the field name and a message port to listen on. What I don't understand is how to assign the same message port in observeField that I am listening on in the roSGScreen's event loop. If I create the message port in the main thread so I can set it to the roSGScreen, how can I send it into the scene graph's thread so it can be set on observeField? Below is the basic code I'm working with:
Main:
Scene Graph:
The end result is once the scene graph is loaded, if the user presses "ok", the square should turn from green to blue.
The issue is, unsurprisingly, sceneGraphPort is uninitialized in the scene graph thread. Any advice how to set the port in the scene graph thread, that I'm listening to in the main thread? Or am I thinking about this all wrong? Did I miss something in the documentation that explains how to do this?
Main:
'create the screen graph component and set it up with a message port
screen = CreateObject("roSGScreen")
sceneGraphPort = CreateObject("roMessagePort")
screen.SetMessagePort(sceneGraphPort)
'set the xml component by name, that will be displayed on the screen
screen.createScene("appScene")
'display the scene on the screen
screen.show()
'listen for any events associated with the scene
while true
msg = wait(0, sceneGraphPort)
if type(msg) = "roSGScreenEvent"
if msg.isScreenClosed()
return
end if
else if type(msg) = "roSGNodeEvent"
print "node "; msg.getNode()
print "field name "; msg.getField()
print "data "; msg.data()
end if
end while
Scene Graph:
<?xml version="1.0" encoding="utf-8" ?>
<component name="appScene" extends="Scene" >
<script type="text/brightscript" >
<![CDATA[
sub init()
print "-----------STARTING GRAPH SCENE-----------"
m.leftRectangle = m.top.findNode("leftRectangle")
m.leftRectangle.observeField("color", sceneGraphPort)
m.top.setFocus(true)
end sub
function onKeyEvent(key as String, press as Boolean) as Boolean
handled = false
if press then
if (key = "OK")
m.leftRectangle.color = "0x0000FFFF"
handled = true
end if
end if
return handled
end function
]]>
</script>
<children>
<Rectangle
id="leftRectangle"
width="300"
height="300"
color="0xFF0000FF"
translation="[100,100]" />
</children>
</component>
The end result is once the scene graph is loaded, if the user presses "ok", the square should turn from green to blue.
The issue is, unsurprisingly, sceneGraphPort is uninitialized in the scene graph thread. Any advice how to set the port in the scene graph thread, that I'm listening to in the main thread? Or am I thinking about this all wrong? Did I miss something in the documentation that explains how to do this?
6 REPLIES 6

TheEndless
Channel Surfer
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
01-29-2016
08:33 AM
Re: sending info from scene graph to main thread
When observing a field in the SceneGraph thread, you don't specify a port or listen for roSGNode events. Those are strictly for listening from the main BrightScript thread. If you're trying to observe "color" inside the SceneGraph thread, use the version of observeField() that takes a field name and the name of the function that handles the event. And, of course, make sure you have a function with that name in the defined in the Scene.
My Channels: http://roku.permanence.com - Twitter: @TheEndlessDev
Instant Watch Browser (NetflixIWB), Aquarium Screensaver (AQUARIUM), Clever Clocks Screensaver (CLEVERCLOCKS), iTunes Podcasts (ITPC), My Channels (MYCHANNELS)
Instant Watch Browser (NetflixIWB), Aquarium Screensaver (AQUARIUM), Clever Clocks Screensaver (CLEVERCLOCKS), iTunes Podcasts (ITPC), My Channels (MYCHANNELS)
brybott
Visitor
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
01-29-2016
10:12 AM
Re: sending info from scene graph to main thread
Thank you for taking the time to respond TheEndless.
I'm actually trying to observe for a change to the color field in the main thread.
In a general sense, I'm trying to understand how to send information between the main thread and the scene graph thread, if it's possible (though the docs seem to imply that it's possible).
If I were to set up observeField() in the main thread, as I understand it, I would need to call that from an SGNode in the main thread. Ok, but that means I need to create the node in the main thread, which means it doesn't exist in the scene graph thread, so I'm still not able to listen for events that occur in the scene graph thread while in the main thread's event loop.
If you're trying to observe "color" inside the SceneGraph thread...
I'm actually trying to observe for a change to the color field in the main thread.
In a general sense, I'm trying to understand how to send information between the main thread and the scene graph thread, if it's possible (though the docs seem to imply that it's possible).
If I were to set up observeField() in the main thread, as I understand it, I would need to call that from an SGNode in the main thread. Ok, but that means I need to create the node in the main thread, which means it doesn't exist in the scene graph thread, so I'm still not able to listen for events that occur in the scene graph thread while in the main thread's event loop.

TheEndless
Channel Surfer
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
01-29-2016
11:14 AM
Re: sending info from scene graph to main thread
All messages should automatically be sent to the main BrightScript thread, if you've registered as an observer (they all use the same port). If the field you're setting is on a component instead of on the scene, then you may need to either search for that component to observe the field, or marshal it through the scene via a second custom field that you can easily observe from the main thread.
My Channels: http://roku.permanence.com - Twitter: @TheEndlessDev
Instant Watch Browser (NetflixIWB), Aquarium Screensaver (AQUARIUM), Clever Clocks Screensaver (CLEVERCLOCKS), iTunes Podcasts (ITPC), My Channels (MYCHANNELS)
Instant Watch Browser (NetflixIWB), Aquarium Screensaver (AQUARIUM), Clever Clocks Screensaver (CLEVERCLOCKS), iTunes Podcasts (ITPC), My Channels (MYCHANNELS)
brybott
Visitor
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-01-2016
02:29 PM
Re: sending info from scene graph to main thread
Well, it took a bunch experimentation, but I figured out how to send information from the main thread to the scene graph thread. Thanks to TheEndless for dropping some bread crumbs and leading me in the right direction. I've posted the following basic example, in case it might help someone else.
Main:
Scene Graph:
The key is to set the observeField() in the main thread after you call show() on the roSGScreen and before you enter the event loop for the roSGScreen. Additionally you have to observe field based on the relationship to the scene you've created and sent to the roSGScreen.createScene method.
Main:
sub Main()
showChannelSGScreen()
end sub
sub showChannelSGScreen()
screen = CreateObject("roSGScreen")
m.port = CreateObject("roMessagePort")
screen.setMessagePort(m.port)
scene = screen.CreateScene("appScene")
screen.show()
scene.findNode("leftRectangle").observeField("width", m.port)
while(true)
msg = wait(0, m.port)
msgType = type(msg)
if msgType = "roSGScreenEvent"
if msg.isScreenClosed() then return
else if msgType = "roSGNodeEvent"
print "node "; msg.getNode()
print "field name "; msg.getField()
print "data "; msg.getData()
scene.findNode(msg.getNode()).height = 400
end if
end while
end sub
Scene Graph:
<?xml version="1.0" encoding="utf-8" ?>
<component name="appScene" extends="Scene">
<script type="text/brightscript" >
<![CDATA[
sub init()
print "-----------STARTING SCENE GRAPH-----------"
m.leftRectangle = m.top.findNode("leftRectangle")
m.leftRectangle.observeField("color", "someFunction")
m.leftRectangle.observeField("width", "someOtherFunction")
m.top.setFocus(true)
end sub
sub someFunction()
print "color was changed"
end sub
sub someOtherFunction()
print "width was changed"
end sub
function onKeyEvent(key as String, press as Boolean) as Boolean
handled = false
if press then
if (key = "OK")
m.leftRectangle.setField("color", "0x0000FFFF")
m.leftRectangle.setField("width", 350)
handled = true
end if
end if
return handled
end function
]]>
</script>
<children>
<Rectangle
id="leftRectangle"
width="300"
height="300"
color="0xFF0000FF"
translation="[100,100]" />
</children>
</component>
The key is to set the observeField() in the main thread after you call show() on the roSGScreen and before you enter the event loop for the roSGScreen. Additionally you have to observe field based on the relationship to the scene you've created and sent to the roSGScreen.createScene method.
rynop
Visitor
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-11-2016
01:30 PM
Re: sending info from scene graph to main thread
You my friend, are the man! Thanks for following up, this helped me SO much. Docs are not clear (from what I can find) on this crucial topic of sending messages from Render thread to main thread and vice versa. Thanks again!

jasondixon
Visitor
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
12-08-2016
09:01 AM
Re: sending info from scene graph to main thread
This was perfect. Thank you so much for posting your solution. Was banging my head on this for longer than I'd like to admit. Thanks again so much.