Bitmap stacking GUI

All topics about ZGameEditor goes here.

Moderator: Moderators

Post Reply
User avatar
VilleK
Site Admin
Posts: 2277
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Bitmap stacking GUI

Post by VilleK »

Kattle PM'd me an idea of how to build a "stacking" gui (used in tools such as werkkzeug and tg) for building bitmaps. I post it here so that we can all discuss it.

Kattle wrote:

Ok: this is the pseudocode for the operator stacking. I have no idea of how one should create the GUI with a grid on which you can snap the operators you create. Plus, I will do some assumptions you can't rely on (ZGE components), mainly because my understanding of the ZGE codebase is very limited.

Basic idea is: the GUI element himself holds a struct that will be used for creating a tree.
The memory for the node is allocated when the GUI element is created.
Every node in the tree will contain the Producer choosen by the user.
This is the structure (C++ style) on which the GUI part should be based on:

Code: Select all

struct ComponentTree {
  TZComponent Producer
  ComponentTree * Child     //OR: something like "List of Childrens"
  ComponentTree * Sibling   //should be better instead of Childrens and Siblings
  
  void AddChild(ComponentTree * NewChild) //A function that adds a child to the node 
}

struct GUIOperator {     //Will contain infos about the operator displayed by the GUI
  rect Rectangule                         //used for representing position & extension
  ComponentTree * ContainedComponentTree  //Every operator holds a pointer to the TreeStruct
  /* stuff like caption or others*/
}

struct GUIOperatorList //just a common list that contains all the operators placed
                       //in their creation order.
CRITICAL POINT:
Not sure about this but we should be able to access the producer by something like:

GUIOperator->ContainedComponentTree.Producer

If we can't we are dead because rest of the code is useless :D
Plus I was wondering if we could use this for displaying and editing everything on the left bar like if the producer itself was selected.

After the user modify something (E.G: moves a rect) we follow this sequence:

Code: Select all

Loop with index i on the GUIOperatorList
    with GUIOperatorList[i]
        Clean the list of childrens
        Loop with index j on the GUIOperatorList                                      //For every component we find his childrens
            if GUIOperatorList[j].Rectangule is placed over GUIOperatorList[i].Rectangule   //We need very simple criteria
                GUIOperatorList[i]->ContainedComponentTree.AddChild(GUIOperatorList[j].ContainedComponentTree)
                  //we are creating one or more trees that in the end will represent 
                  //the operator stacking Upside-down (see picture)
            endif
        end Loop
        
        if no child was assigned, assign a default "NewBitmapProducer" as child
        //this is what I did using "blank texture" in the example
end Loop

//Now our trees are complete (in the sense that every linked node is represented in the tree)
//We proceed creating the list of producers from the tree

Loop with index i on the GUIOperatorList
    with GUIOperatorList[i]
        if GUIOperatorList[i]->ContainedComponentTree.Producer == "SaveAs"    //looks for operators that will create a bitmap.
                              
            Create a bitmap named as the same way the user wanted
            TZComponentList TempList
            ExploreTreeRecursively (GUIOperatorList[i].ContainedComponentTree->Child, TempList) //See description at bottom
            Remove the first element from TempList, since it will be a "NewBitmapProducer" which is not needed
            Assign the TempList to the Bitmap. This now cointains all the needed producers.
        endif
end Loop


//Idea is: Call the function recursively before adding the producer
//so we get the list of operations in the right order

ExploreTreeRecursively (ComponentTree *Tree, TZComponentList TempList) {
      if Tree->Child = NULL {
          TempList.Add(Tree->Producer)
          return
          }
      
      ExploreTreeRecursively (Tree->Child, TempList) //This will be called once for every
                                                     //child if the component is "Combine"
      
      TempList.Add(Tree->Producer)      //This will be called once for every
                                        //child if the component is "Combine"
      
}

FINAL CONSIDERATIONS:

Maybe the whole thing could be done without the "support tree" but I did not found a way to manage it in an easy way.
Plus, actual complexity should be O(n^2) which is not that bad.

The "NewBitmapProducer" should be added to the Producers actually ZGE has, but should be quite trivial ;)

When I say "if no child was assigned, assign a default "NewBitmapProducer" as child" there might be a fast way for doing it:
consider using the GUIOperatorList[0] as an always-present invisible GUI element that contains the "NewBitmapProducer" so you can link to it easily.
You just will jump it when it is needed by looping GUIOperatorList from 1 to n.

Some checks should be done: EG: "save" operators SHOULD NOT BE STACKED OVER SOMETHING ELSE or should be ignored within the ExploreTreeRecursively function, otherwise things will get messy.

Feel free to ask for clarifications since I do understand I might have been not so clear ;)
Attachments
ZStack2.gif
ZStack2.gif (35.1 KiB) Viewed 13714 times
User avatar
VilleK
Site Admin
Posts: 2277
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Post by VilleK »

Here are some comments I have on Kattle's suggestion:

The NewBitmapProducer-component is probably unnecessary. Instead we could introduce a "IgnorePrevious" property on producers that optionally works on the bitmap on the stack if it's present. Such as BitmapExpression and BitmapRect. If IgnorePrevious is set then the bitmaps on the stack are left unchanged and a new bitmap is always generated.

The editor should always show the stacks of all bitmaps in the project, not just the currently selected one. This is because you may work on all bitmaps at once, and save/load between them.

The editor should work two-way with the project-tree. If you add a bitmap or a producer to the editor it should immediately be added to the tree also.

The bitmap-component and the producers must save their gui position coords in the xml. If none are present (opening a old project) they should be defaulted to coordinates that do not overlap.

I'm not sure the exact flexibility of werkkzeug stacking is possible with the current architecture of zge bitmap producers. For instance: in wz you can add five bitmaps together, then combine the result with another bitmap. In zge the Add (combine) producer operates on exactly two bitmaps on the stack. It could be changed to add together all bitmaps currently on the stack, but that would empty the stack.

It would be quite a lot of work to add this functionality to ZGE, and maybe I don't consider it to be of the highest priority but now at least the thread is started so that we can discuss it for a future version of ZGE!
kattle87
Posts: 402
Joined: Wed Sep 26, 2007 9:06 am
Location: Italy

Post by kattle87 »

VilleK wrote: The editor should work two-way with the project-tree. If you add a bitmap or a producer to the editor it should immediately be added to the tree also.
Let's say: basic problem is from infix to postfix order. That's all! :)
The point is that we have to get them in infix somehow. And this brings the problem of creating the whole stacking GUI.
VilleK wrote: I'm not sure the exact flexibility of werkkzeug stacking is possible with the current architecture of zge bitmap producers. [...] In zge the Add (combine) producer operates on exactly two bitmaps on the stack. It could be changed to add together all bitmaps currently on the stack, but that would empty the stack.
just use Combine more then once and you are done ;) as I've done in my example.
VilleK wrote: maybe I don't consider it to be of the highest priority
me too... Let's say we might get more attention from the public ;)
In the fall of 1972 President Nixon announced that the rate of increase of inflation was decreasing. This was the first time a sitting president used the third derivative to advance his case for reelection.
-=Hugo Rossi=-
User avatar
VilleK
Site Admin
Posts: 2277
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Post by VilleK »

Perhaps it is time to give this a go now. I'm thinking that the quickest way to get something up and running is to use a gui similar to the Void texture editor (possibly even using some code from it). So I'll just make a quick attempt to see what kind of problems might surface in doing this. Will keep you posted on any progress or failure ;)
User avatar
VilleK
Site Admin
Posts: 2277
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Post by VilleK »

Here is a report on my progress so far.

See attached screenshot.

When you select a Bitmap-component in the project tree the texture editor will automatically appear and display the graph of producer components that the selected bitmap contains.

Every node in the graph is a bitmap producer. The text indicates the type of producer, "Blur" means BitmapBlur etc. The triangle on top represents the output of the producer. The circles at the bottom are the inputs.

You can edit the order in which the producers are executed by dragging the lines between the graph nodes. So you can either drag a line from the output-triangle to an input-circle, or the other way around.

You can add new producers by right-clicking and selecting "Add" from a popup-menu. You can also delete a producer by selecting "Delete".

Every time the graph is changed (links changed, or nodes added/deleted) the graph will automatically rearrange itself to display its updated state.

You can still edit bitmaps the old way by adding/deleting producers directly in the project tree, the graph will be updated automatically with your changes.

Limitations/bugs: The editor can only handle producer-components so it cannot display a graph of a bitmap containing logical components such as a Repeat-component. I'm also struggling a bit with producers that optionally takes a input image but also works without inputs, such as BitmapRect and BitmapExpression.

I'm still not sure where this feature is going. The editor is a bit confusing to use at first but after a bit of training I find it at least makes bitmap editing easier than before :) . Hopefully it will result in something you will appreciate also! And if it doesn't, at least the code was fun for me to write ;)

It is not quite ready for testing yet but I hope to update the beta during the weekend. Meanwhile I doing intermittent check-ins to the Subversion repository so the code is there if anyone is interested.
Attachments
current w.i.p. bitmap graph editor
current w.i.p. bitmap graph editor
TextureEditor.png (138.52 KiB) Viewed 13575 times
kattle87
Posts: 402
Joined: Wed Sep 26, 2007 9:06 am
Location: Italy

Post by kattle87 »

I have just one word:
A M A Z I N G
:D
It's really FAR BETTER LOOKING than I would expect!
Did you used lots of code from that pascal project we found?

And if you really had fun working at this, well, I am really really really happy about it :D

Now we have to decide if we are keeping it "reversed" (EG: from down to up) or just get it "from up to down" inverting the producers and the output positions :P
In the fall of 1972 President Nixon announced that the rate of increase of inflation was decreasing. This was the first time a sitting president used the third derivative to advance his case for reelection.
-=Hugo Rossi=-
User avatar
jph_wacheski
Posts: 1005
Joined: Sat Feb 16, 2008 8:10 pm
Location: Canada
Contact:

Post by jph_wacheski »

yeah, it looks great,. should do some to help in creating more complex procedural bitmaps,. the bottom up thing is fine, if it was easier to build, but top down is more standard,. I suppose. either way we will get used to it. but who cares about that,. you bunch of rebels,. LOL
iterationGAMES.com
kattle87
Posts: 402
Joined: Wed Sep 26, 2007 9:06 am
Location: Italy

Post by kattle87 »

First feedback:
-I would prefer not getting the last created producer to be automatically attached to the lower node... EG when I used this with combine it took me forever to set the arrows like I wanted to! :D
-What about a little larger bitmap preview? Or at least a sizeable one :P
However... Amazing job Ville!!! :D

PS: Always remember to do what you do at your pace =) don't rush!
In the fall of 1972 President Nixon announced that the rate of increase of inflation was decreasing. This was the first time a sitting president used the third derivative to advance his case for reelection.
-=Hugo Rossi=-
User avatar
VilleK
Site Admin
Posts: 2277
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Post by VilleK »

The graph is bottom-up pretty much by accident, I guess I'm used to seeing graphs in that direction like class-diagrams where the base-class is on top and the descendants below. It's not super-easy to turn it around so I'll keep it this way for now, but I can change it if you think it becomes too confusing to use.

Yeah, the code is fun to write and I was definitely helped by XProger's code for the texture-editor to his void-engine. In the end I did not use much code from it but it got me started quickly and in the right direction. So many thanks to XProgerfor making his code available!

The auto-linking of new nodes is a problem and I'll see what I can do to fix that.
User avatar
jph_wacheski
Posts: 1005
Joined: Sat Feb 16, 2008 8:10 pm
Location: Canada
Contact:

Post by jph_wacheski »

been working with this some more and it is very good now! I do think that with a double click anywere on the graph then THAT component should be previewed,. that way we can see what each element is contibuting, and when you want to see the resulting bitmap simply double click on the last (or top) node,. . or in the right click menu if there was a 'preview node' option and it opened a preview in another window that you could just close after you look at it,. if that is somehow easier to implement., just guessing here.
iterationGAMES.com
kattle87
Posts: 402
Joined: Wed Sep 26, 2007 9:06 am
Location: Italy

Post by kattle87 »

Ok! I've got a suggestion:
what about a button for rapid swap of the 2 inputs for the Combine component (or the brand new Distort component I've just finished coding)? ;)
The point is it's easy to accidentally swap the two inputs. I've noticed that if you move the left circle on the component away, the two inputs are swapped... not sure if it was intended or not :D
Maybe we should get another fast way to do such a thing? Or keep this "feature" and officialize it?
In the fall of 1972 President Nixon announced that the rate of increase of inflation was decreasing. This was the first time a sitting president used the third derivative to advance his case for reelection.
-=Hugo Rossi=-
User avatar
jph_wacheski
Posts: 1005
Joined: Sat Feb 16, 2008 8:10 pm
Location: Canada
Contact:

Post by jph_wacheski »

doesn't seem to make a difference with add but it do with subtract,. and perhaps any new methods it will matter the order,. yeah a simple button for 'swap inputs' would perhaps be more clear however now that you found an easy and already working way, simply documenting it is fine by me,. cuse I know now ;) gota lov occult knowlage eh? and for my suggestion above perhaps the node being previewed could highlight in some way,. colored border or title,. whatever.
iterationGAMES.com
Post Reply