In trying to roll my own Modal pop-up menu, I quickly ( it’s all relative! )
learned that I can’t have a Modal anything! My app needs to keep doing
stuff even when menus and such are on screen awaiting user input.
So, in using getMessagePort() to hijack my main event loop, it crossed my
mind that I could send other “doEvent()/Update()” functions as parameters
into my Fake-Modal Menu of Awesomeness.
Q: As much as the possibility of this working is intriguing, how often is
such a construct put into action? Is this a standard way of doing such
a thing? If not, why have a getMessagePort() at all?
Follow-up Q: Are easing animations typically modal as well? Who here has
implemented non-modal transition animations?
“dev42” wrote:
In trying to roll my own Modal pop-up menu, I quickly ( it’s all relative! )
learned that I can’t have a Modal anything! My app needs to keep doing
stuff even when menus and such are on screen awaiting user input.
So, in using getMessagePort() to hijack my main event loop, it crossed my
mind that I could send other “doEvent()/Update()” functions as parameters
into my Fake-Modal Menu of Awesomeness.
Q: As much as the possibility of this working is intriguing, how often is
such a construct put into action? Is this a standard way of doing such
a thing? If not, why have a getMessagePort() at all?
Follow-up Q: Are easing animations typically modal as well? Who here has
implemented non-modal transition animations?
“NewManLiving” wrote:
just pass control to a message loop in your modal dialog. Use getmessage instead of wait or waitmessage
could you expound on this a bit? What exactly do you mean by “pass control”? :oops: :?:
When you create your dialog you first draw it and then go into another message loop. But you do not use wait. Instead you use getmessage which returns immediately if there’s no button pressed. it just returns invalid. So if you have to keep processing something you can continue until you notice some valid input. Of course what you are doing should not block the message queue either. If You have to block the queue then you don’t even need a loop. What is it that you are trying to do?
“NewManLiving” wrote:
What is it that you are trying to do?
Code better? That really isn’t a joke! I’ve apparently coded myself into a corner. I’ve been working on a game loop “framework” that I could use in the future and not just on the app I’m currently working on. One “feature” of this framework was that I allowed more than one object to process button events. Not only that, but some objects, depending on which button was pressed, could pass which button was pressed on to the next object in the list… or not.
To facilitate all of this, I started accumulating a bunch of boolean flags: .isVisible, .hasFocus, .isModal
Now I’m not saying I was completely wrong ( why would any programmer ever say that?! ), but I’m starting to see that I really was over-complicating things.
“NewManLiving” wrote:
another message loop
That’s just it. I only had one loop. This is new territory for me. I’m currently working through the 7 Stages of Learning to Program Better ( aka Programming Grief ). I initially posted when at the first stage, Shock & Denial. I won’t go into the other stages as I don’t want to cause anybody undue stress revisiting their past programming learning journeys.
“NewManLiving” wrote:
What is it that you are trying to do?
Topically? errr to learn if implementing more than one event loop is the way to go.
“NewManLiving” wrote:
What is it that you are trying to do?
Code better? That really isn’t a joke! I’ve apparently coded myself into a corner. I’ve been working on a game loop “framework” that I could use in the future and not just on the app I’m currently working on. One “feature” of this framework was that I allowed more than one object to process button events. Not only that, but some objects, depending on which button was pressed, could pass which button was pressed on to the next object in the list… or not.
To facilitate all of this, I started accumulating a bunch of boolean flags: .isVisible, .hasFocus, .isModal
Now I’m not saying I was completely wrong ( why would any programmer ever say that?! ), but I’m starting to see that I really was over-complicating things.
“NewManLiving” wrote:
another message loop
That’s just it. I only had one loop. This is new territory for me. I’m currently working through the 7 Stages of Learning to Program Better ( aka Programming Grief ). I initially posted when at the first stage, Shock & Denial. I won’t go into the other stages as I don’t want to cause anybody undue stress revisiting their past programming learning journeys.
“NewManLiving” wrote:
What is it that you are trying to do?
Topically? errr to learn if implementing more than one event loop is the way to go.
We only use 1 run-loop in our app. The key is to arrange components in a hierarchy and allow them to register with their parents as event receivers. Whenever an event is pulled out of the message port in the main loop, send it to the root component. Each component then either handles the event, or forwards it to it’s children, who can also handle, or forward it. Here’s some pseudo code:
Disclaimer This was all typed directly into the forum… It might not compile/run, but should demonstrate the concept
' -----------------------------------------------
' Entry: Main
function main() as Void
runloop = runloopCreate()
' Create a button
button = buttonCreate()
button.setText("Click Me!") ' setText not included in example
' Add button
runloop.getRoot().addChild(button)
' Execute
runloop.run()
end function
' -----------------------------------------------
' Class: Component
function componentCreate() as Object
return {
handleEvent : _component_handleEvent
handleOrForwardEvent: _component_handleOrForwardEvent
_children : []
addChild : function(component as Object) as Object: m._children.push(component): end function
}
end function
function _component_handleOrForwardEvent(event as Object) as Boolean
handled = m.handleEvent(event)
' We did not handle the event, maybe our children will?
if not handled
for i = 0 to m._children.count() - 1
handled = m._children[i].handleOrForwardEvent(event)
if handled then exit for
end for
end if
return handled
end function
function _component_handleEvent(event as Object) as Boolean
return false ' No handling of events at this level
end function
' -----------------------------------------------
' Class: Button
function buttonCreate() as Object
this = componentCreate()
' Override function handleEvent
this.handleEvent = _button_handleEvent
this.performClick = _button_performClick
return this
end function
function _button_handleEvent(event as Object) as Boolean
buttonCodes = bslUniversalControlCodes()
if event.getInt() = buttonCodes.button_select_pressed
m.performOnClick()
return true ' We handled this event
end if
return false ' We didn't handle this event -- it should be passed to others who may wish to handle it
end function
function _button_performClick() as Void
?"Button was clicked!"
end function
' -----------------------------------------------------------------------------
' Run Loop
function runloopCreate() as Object
return {
_exited : false
_root : componentCreate()
run : _runloop_run
getRoot: function() as Object: return m._root: end function
}
end function
function _runloop_run() as Void
while not m._exited
event = m._messagePort.getMessage()
if event <> invalid then m._root.handleOrForwardEvent(event)
' ... snip other run-loop stuff like drawing ...
end while
end function
I need to go over your framework 42 more times, but I’m starting to see similarity in what I’ve done.
( Is it common to create a framework and then become fuzzy on how it works? :oops: )
But that’s part of the reason for the thread. I have a working menu that is non-modal, but it isn’t quite the same as a roMessageDialog in look-n-feel. Thus the attempt to initially use and now attempt to roll my own. I am reconsidering this and wondering if it wouldn’t be easier to try to spiffy up what I already have working, but due to some “genius” reasoning on my part, my_menu and my_textbox are tightly integrated. Saved time / code before, more discomfort today.
“dev42” wrote: Is it common to create a framework and then become fuzzy on how it works? :oops:
In short, yes. That’s why separation of concerns and good documentation is critical to good architecture. If you have undocumented assumptions or dependencies, chances are in 8 months you’ll forget about them.
“dev42” wrote:
Saved time / code before, more discomfort today.
I try to revisit work done a few weeks back, see if my documentation is clear to me, and if not, refigure what I’ve done (since it’s not THAT old I can get “back into it” pretty quick), and improve my notes accordingly.
The following are off thread topic, but relate to the issues I’m having. Maybe I need a state machine? Or at the very least, more “finite” and less “unknown” situations?!
State - Game Programming Patterns/Design Patterns Revisited
“Rek” wrote:
Sounds like time for a refactor!
In a twisted way of looking at all this, I am! Just took a long way to get… here.
“Komag” wrote:
I try to revisit work done a few weeks back, see if my documentation is clear to me, and if not, refigure what I’ve done (since it’s not THAT old I can get “back into it” pretty quick), and improve my notes accordingly.
Awesome advice. I have a ton of “to do” notes. Better documentation would be helpful. Interestingly, I have a comment at the very top of each doEvent() func something that gives the impression that I intended to have only one function process events at any given time, but I haven’t done it that way!
Also, I’ve never been a fan of flow-charting, but I’m thinking I REALLY need to get over it and sketch out what’s supposed to be happening in order to have a way to compare what I think my code is doing and how I’ve implemented it. The same for what I’m debating with using multiple event loops with getMessagePort().
update:
Naming convention may be my NEMESIS! My current doEvent() functions process button presses, but in my attempt to make a new SuperMenu, I confused this with what would be called when a component was selected/executed… ~ onClick.
Built in roku components aren’t modal. facepalm They can be, but don’t have to be! I’d still need to send in whatever functions need to be called regularly to be called in the new event loop…
Here’s a different way of saying what I was initially asking:
“an anonymous genius” wrote:
U want to know whether you should have a kind of hierarchy with the event loop where one loop takes precedence over another. Or should the main loop be mutating like a plugin for each game state. When the modal dialog comes up it changes the game state that changes the event handlers. Personally i would try to keep the event handlers for the input pluggable, like your state machine idea. To me, i think of the input hardware as constant, so that should be one thing. And then when the game changes, the behavior triggered by the input naturally changes. So that would be your state transition in your state machine. But you may want to do the opposite. … Maybe the roku system favors the hierarchical looping. Sometimes may want to avoid fighting the framework too much.
Sounds like maybe you want a stack of components instead of a hierarchy. I was thinking more about a generic UI system like android’s where different components on the screen can react to events (i.e. buttons, text boxes, etc.). But if you’re trying to achieve something more like a pause screen in a game, it might make more sense to design your system as a stack of “GameStates”.
With that approach, you would only pass events and things like physics ticks to the top-most “active” GameState. So, initially you have a single GameState in the stack (main menu), then the user presses “Start Single Player”. At this point, you would create a new “SinglePlayerGameState” and push it onto the stack; making it the new “active” GameState. The MainMenuGameState would still be in the stack, but essentially idle (you may want to release resources used by idle states – depends on your needs). Finally, if the SinglePlayerGameState receives an event that it interprets as a “pause” command, it will create a PauseGameState and push that onto the stack, making the SinglePlayerGameState idle as well. All you have to do then is pop states off the stack to go “back”.
“Rek” wrote:
Sounds like maybe you want a stack of components instead of a hierarchy.
stacks FTW. Well, at least in theory. I haven’t gotten that far. In “refactoring” / “making new code” mode.
Here’s what I think I understand ( yes, I re-read that 3x to make sure I had it right ), Menu’s and sub-menu’s will be on one Stack, but their components ( buttons etc ) will be Lists ( one per Menu ).
Since I haven’t yet gotten to the “Stack” phase of all this, I’m not sure how it’ll work on screen. It might be a simple situation where I treat the “SuperMenu of Awesomeness” Stack as both a Stack and a List. The reason for both would be to make sure everything is drawn that needs to be → “for each” → [ List ] and to send user input to the active sub-menu → .GetTail() → [ Stack ] … [ ifList also has .RemoveTail() ]
As for where I’m at right now, I’m still trying to find more descriptive names for things and where to put functionality. For example ( WARNING: this is not for the faint of heart. Sleep deprivation played a factor in this. Continue reading at your own risk I considered making onClick() → onClickAndExit() that would return a Boolean if the component closed the current sub-menu. Thankfully, I came to a better / clearer solution which was to simply have a Boolean flag “exitOnClick” in the component and check that instead. It added a line of code in the event loop dag-nab it! But it is much clearer. [ of course, now that I’ve typed all this out, I start to re-consider and think “exitAfterClick” or “closeDialogAfterClick” would be better names! ]
I also have some Q’s about “global” vars or accessing variables of different objects from within a menu, but I’ll save them for later.
The further I go down this rabbit hole, the more I wish I’d just use the built in SDK UI elements and bend them to my will.