Sign in to follow this  
  • entries
    8
  • comments
    35
  • views
    16185

Interlude - Concept of an Application Manager

Sign in to follow this  
Buckeye

1545 views

Years ago, back when I was gainfully employed, I took a management class as part of my employer's "career enhancement" plan. It completely changed the way I thought (and still think) about how an organization can (and should) be run.

The concept is that the staff of a company ( or a division of the company, or any subgroup down to the project or team level ) is an inverted pyramid - not with the leaders at the top** of a pyramid, but with the workers at the top. Managment was viewed as support for the workers, providing them with any and all resources they needed to get work done.

** The illustration shown has a big red X through it because it shows a team leader being carried by the workers. No, no, no. A team leader should be providing support for the workers.

Admittedly, for that concept to work, the workers are dedicated to working in the best interest of the customer, producing efficiently and economically what the customer wants.

A Program's User is the Customer, and the Customer is Always Right



Extending the concept to a user-driven computer program such as an editor, the current edit mode is provided with resources by the application manager to do whatever the user demands. The user interfaces with the current edit mode, just as a customer in a store talks directly with the clerk, not with the store manager. The current edit mode manipulates the mesh in any way it can, in response to the user's commands. If the user wants to do something the current mode can't provide, the current mode tells the application manager to switch to the edit mode the user has requested.

That results in the top-down approach to Windows message handling described in my previous blog entry.

I.e.,


editor_messaging.png


At each step along the way (the message procedures), the user's input is the priority, and each object (the current mode instance, the base mode instance, etc.) examines the user's requests. For those requests which the current mode recognizes, all the resources the program provides are available to or generated for that mode to accomplish what it must. If the current mode can't respond (or, rather, doesn't respond) to the request, the user's request is passed on to the next object in the chain. Each object in the chain either responds to the input, or passes it on. Eventually some object responds to the user's input. N.B., that response may be to create an object (i.e., change modes) that can do what the user wants.

Imagine a customer in a store talking to a clerk whose name-tag says "I sell shoes." After looking at shoes, the customer says: "I want to look at socks." The smiling clerk silently ignores the request, but the store manager is listening to the conversation. In the blink of an eye, the manager puts a new clerk behind the counter. That clerk's name-tag changes to "I sell socks" and the display case changes from shoes to socks.

The Windows API window procedure is (essentially) an event-driver, in which events occur through menu selection, key-strokes and mouse manipulations by the user. The architecture that I'm experimenting with, rather than immediately responding to those events through a set of OnSomeEvent routines, instead calls a set of specialized routines that can most likely handle the user's input at the current moment (the current mode.) The current mode routine then examines the input and (potentially) responds. If that set of routines doesn't respond, the system replaces that set with a set of routines that does respond.

I'm definitely not claiming that this architecture is better (or worse) than event-driven programming. Likely due to my own inadequacy, event-driven code I've done previously ended up with switch statements and conditional blocks to determine what specific routines to invoke. Those specific routines often had to further determine current conditions to behave properly.

Adapting L. Spiro's gamestate architecture for an editing environment in this way is proving interesting, primarily the "feature" of the approach that, when a new mode is to be set, the current state is actually deleted, and the new mode which is created, by its own initialization, provides known conditions for its own routines. For me, that provides both discipline (what must a mode do before it's destroyed?), and freedom (don't worry what the previous mode did).
Sign in to follow this  


5 Comments


Recommended Comments

lol, I came here expecting a post about people management, realized halfway through that the rest of it was actually about UI architecture. :D

Interesting, though. I've been working on a modeler of my own (called V2, haha.. as in 2D vector)... it's a quick'n'dirty HTML5 app, using the bloated JQuery UI libs which I was never fond of, but it gets the job done. Gives me more freedom than C++; it's not even strictly OO... but like L. Spiro my goal is clean separation of state. +1 for not using constructors/destructors, especially in C++. (I picked up on that from @EDI who also has a lot to say on this subject.)

 

My edit modes don't fit neatly into Spiro's architecture... for example I can select layers > draw/edit > position skeleton, then hit ESC to return to draw/edit. It's like a mode stack, but only 2-3 deep, totally ad-hoc. And I can imagine having multiple active modes, and so on - if my goal was to make a great editor, not just enough to build my game. :)

 

Anyway, enough rambling. I'll have to think about your main premise "a manager is there to protect modes from distractions" and see if it leads me to some kind of epiphany. Thanks for posting.

Share this comment


Link to comment
I came here expecting a post about people management ...


Doh! Sorry about that. Maybe I ought to change the title to clarify the subject better. Maybe the "Program's User ..." phrase instead.

 

Re: stacked/multiple active edit modes - if I want to keep my edit modes completely independent and avoid a stack of edit modes, I will end up with a whole boatload of modes. I.e., each mode is designed to assume/configure the current state of the data during Init. So, a mode such as rotate-group-of-vertices will be distinct from translate-group-of-vertices. In some previous editors I had more generalized modes like a "vertex edit mode," and, within that code, kept track of whether the user was translating, rotating, etc. Likely due to my own organizational inadequacy, it just became a mess of switch statements and if-then-else chains. And the Undo/Redo stacks were a nightmare.

 

The appeal of L. Spiro's state concept (for me, anyway) is that each mode is actually deleted from memory before the next mode starts. Every mode starts out with the same data state (well, edited, of course), known graphics state, etc. From a coding standpoint, that is very compelling when creating a new mode.

 

then hit ESC to return to draw/edit. It's like a mode stack

 

I'm thinking similar to Blender's edit mode switching with Tab. I would look at the user hitting ESC to be (just) a command to change modes, depending on the current mode. Admittedly, there may be circumstances when the user wants to go back-and-forth between two modes. I haven't gotten there yet, but with a context menu concept, e.g., the response to ESC in Mode_PostionSkeleton could be to tell the app manager to set the next mode to Mode_DrawEdit. As long as the user knows the response to a keystroke in the current mode, it's all good.

 

I'm intentionally trying to avoid a hierarchy (or stack) of modes, but rather coding a programmed response to the user in a particular mode. E.g., if the user instead pressed "V," Mode_PositionSkeleton would ignore it, the app manager would note the request, tell Mode_PositionSkeleton to destroy itself, and set Mode_EditVertices.

Re: Init/Destroy vs. ctor/dtor - absolutely! It gives a class a chance to say "I CAN'T INITIALIZE!"

 

"a manager is there to protect modes from distractions"


Interesting interpretation! Have to give that some thought from a concept standpoint. I'm currently heading more toward "The architecture doesn't allow distractions," and the app manager's role is just to provide resources to the modes, and handle any user commands the mode doesn't handle.

 

 

Thanks for posting.

 

 

Right back atcha'!

Share this comment


Link to comment

"A boatload of modes" - yep, I have about 10 so far, 20 by the time I implement translate/rotate/scale at 3 levels, plus skeleton editing.

 

I suppose it's feasible to delete and recreate modes when switching back and forth. I see the appeal. Anything that needs to be preserved between modes, can be stored in the model's permanent or runtime state.

 

Undo/Redo, yep, that's high on my wish list. Not having even 1 step is freakin' annoying! Figured I'd eventually force all state changes to go through an API that I can log and replay from a snapshot. That *could* be independent of modes, but it's all about state management...

Share this comment


Link to comment

Yeah, that state separation works well. World/object state, editor state (selected objects & vertexes), and the current mode's state -- nothing else. Some modes switch back to the previous mode when done. No mode stack, no mode state preserved when another mode is active. That fits what I see as a user.

Share this comment


Link to comment
editor state (selected objects & vertexes)

 

 

For me, it works better if I consider object selections as part of the object's state - selected vertices / faces / edges / bones, etc. That data has to be stored somewhere - it may as well be with the object is applies to. EDIT: that data affects how it's rendered, and how it behaves.
 

 

Some modes switch back to the previous mode when done. No mode stack, ...

 

 

Yes. Don't know if you intended it, but the phrasing is spot on - the current mode, either with user input, or by its code, determines the next mode. When the loop detects that a "next mode" has been set, the previous mode is deleted, the new mode created, and the new mode becomes the primary interface with the user. E.g., the model-loading mode conducts the file open dialog, loads/creates the model (or not if the user cancels), and sets (e.g.) object-editing mode as the next mode.

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now