A2Ded : Aspect2D auto-save transform + editing features

I found several topics about serialization in Panda :

But that’s not what I do here. (please correct anything I missed)
What I understand is, serialization means dumping the whole scenegraph under a node from memory to external storage, so that in the future it can be loaded as a whole piece as if created piece by piece at runtime. Just like loading models. This is the workflow of serializing nodes :

  1. run the script, let it build up the nodes, and at the given time, dump those nodes to disk
  2. the nodes’ builder part in the script must be eliminated (or commented out) to avoid duplication at future run-time
  3. create it’s loader script

While what I want is only to save/write to disk the transformation of particular nodes under aspect2d, kind of “save game”. I don’t mean to build a visual builder/editor. There is scene editor, but I’ve never used it to build 2d nodes.
All I want is the same standard workflow, but more flexible and (hopefully) intuitive. So my workflow is not changed at all, just need to be more careful, though.

  1. build up the nodes using script interface, mark which node whose transform must be saved to disk, using hardcoded tag for it’s unique node identity, which must stay the same forever
  2. anytime at run-time, I can move them around and scale them up/down, and dump the transform matrix to disk
  3. next, at future run-times, the transform matrix will be loaded from disk and automatically applied to the node

download :
A2DEditor.zip (last updated Jun 25, 2012)
test script (last updated 10/20/07)
put the test script at the same level with the A2DEditor directory.

A little guide to use it :
1. You must assign a unique ID to each node which need to be dynamically transformed at run-time. Call saveA2D and pass a hardcode unique random number, just close your eyes and hit some numbers. Sounds funny ??
2. Next, at run-time, you can enter edit session by pressing F5
3. In edit session, you can move & scale those marked nodes. They’re including Direct GUI and any geometry nodes. For geometry nodes, I use collision ray to select the geom, and then it’s parents will be displayed, so you can select exactly which node you want to edit. After selecting the node, press SPACE to enter edit mode, and there will be some info displayed following the mouse position to remind you about what you can do there.
4. After editing the nodes and keep the changes, you can leave edit session with 2 options : save/write the changes during that session to disk, or just discard them.

NEW 10/20/07 :
Aspect2D_EDITOR-UserGuide.htm (8.6 MB)

This is the internal of how it works :
1. The process walks through aspect2d scenegraph, searching for tagged nodes, even under not-tagged nodes.
2. Any node under a tagged node, if is not tagged already, will be tagged according to it’s parent’s tag.
Example : if the parent is tagged with “1234” number, the not-tagged children will be tagged with “1234-#”, which # means child’s index. It will be “1234-0”, “1234-1”, “1234-2”, and so on.
3. Important !! Just make sure to assign unique ID to each desired node, otherwise if two different nodes have the same ID, then they would share the same transform matrix.

Have fun !!

[EDIT] 4/24/07 :

  1. when start it at the first time (no file saved yet), “registering” the node (saveA2D) now stores the matrix to dictionary, instead of doing nothing. So discarding the changes (at the first time) works as expected.
  2. added keyboard control for walking through nodes list. Very handy for crowded geometry nodes.
  3. added the geometry node’s XZcoordinate output on the screen edges
  4. added thresholds for the XZcoordinate output, so that they won’t jump over screen edges
  5. better ortho behaviour
    and some minor changes.

[EDIT] 4/26/07 :

  1. CompassEffect issue fixed
  2. the collision now respects the smallest geom if there are several geoms lying on the same XZ plane (no longer using queue.sortEntries, now compares bounding spheres’ radii)
  3. the editing style now apllied to Direct GUI too. It’s no longer using MiddleMouseButton, and the standard Direct GUI editing is disabled, except for the nodes list GUI. So you can use any editing features on them, e.g. ortho lock and any future improvements (e.g. various snap option perhaps). This is achieved by creating a (frame tight) card for each Direct GUI object, so the collision can be done.
  4. added lockable feature of nodes list GUI, since the hover/off state of the mouse over those GUI regions is not reliable.
  5. the selected node is brought to a higher level render bin to reveal it, especially when it’s sort order is lower than any other objects, and then restored if other object is selected.
  6. no longer accepts “enter-" and "exit-” events of mouse watcher region to decide if the mouse is hovering/off the region. Now it’s done by collecting those region to a list and perform a simple check against each one. Simple but more reliable.
  7. more cleanup and comments

[EDIT] 4/28/07 :

  1. added various object snap : grid, origin (GeomNode or other node type are optional)
  2. added mouse position snap (before dragging object), so hopefully the offset of mouse-node can be acurate when dropping it relative to other snap target. But there is still inaccuracy, around .0063. Not sure where it comes from. [EDIT] : fixed. now 100% no loss.
  3. mouse offset now locked when dragging in ortho mode.

[EDIT] 4/29/07 :

  1. the real zoom is available, i.e. zoom using mouse position as focus.
  2. added bounding box corners snap.

[EDIT] 4/30/07 :

  1. more friendly user input. No longer using Shift key to indicate mouse position snap. Now clicking inside any marker means snap the mouse position, otherwise it uses the current offset. And dropping the object while the mouse is inside a marker means snap that point. So drag & drop mouse snap is now that easy.

[EDIT] 5/1/07 :

  1. added bounding box middle points snap
  2. added non-origin scale base, so it’s possible to scale with corner or middle point as base point. Works only for GeomNode and Direct GUI. Also possible to snap to grid when scaling.

[EDIT] 5/3/07 :

  1. the last selected node restored back to it’s render bin upon exit editing session.

[EDIT] 5/9/07 :

  1. added better mouse controlled camera movement. Using mouse in edit session doesn’t affect camera movement in 3d world.
  2. hidden objects displayed in edit session, and then re-hidden on exit
  3. render is now hidden when entering edit session, but the last frame is still there, rendered on the generated fullscreen card. Since render is hidden, all active intervals get paused when entering edit session, and then resumed.

[EDIT] 5/14/07 :

  1. intervals pause/resume issue fixed.
  2. render-capture-card’s render bin fixed

[EDIT] 5/17/07 :

  1. now you can refuse to save children under a node.
    You have 2 options :
  • to exclude ALL children, pass excludeChildren=1 to saveA2D method.
  • to exclude only specific children, pass children’ index list :
    Example : if you have a DirectScrolledList, you should NOT save the list frame, or else the list items would be stacked at the same position. So it would be excludeChildren=[2] to exclude the list frame.

Nice work! I tried your latest version. I got a message about a missing model: lilSmiley. Commenting the loading of this model out fixed it.

Sorry, I don’t know where it is on Linux install. I guess you can figure it out on your own.

[EDIT] 5/21/07 :

  1. bug fix : snap markers placement now correct for any GeomNodes structure.
  2. added undo & redo for both Select Mode and Edit Mode.
  3. no longer using lilSmiley model. Seems it’s not distributed on Linux.

Note that the lilsmiley model is properly named “lilsmiley.bam”, not “lilSmiley.bam”. On Windows, the incorrect case doesn’t matter, and the file will load anyway. Not so on Linux.


Oh, yes you’re right.

It’s not true. The problem is I always disable case sensitivity in my Config.prc : vfs-case-sensitive 0
and there had been typo in my head since long time ago. o my …
It’s fixed.

[EDIT] 5/30/07 :

  1. bug fix : the not-saved parent node now correctly ignored when creating the parents list
  2. bug fix : children exclusion
  3. added full collapsible/expandable aspect2d scenegraph tree, displayed using DirectScrolledFrame. But I don’t use the built-in slider bar because I dislike it’s jumping behaviour. So I created my own vertical slider, but without up/down buttons. I use Ctrl+MouseWheel instead to replace their function.

[EDIT] 6/1/07 :

  1. added hierarchy lines of aspect2d scenegraph tree

[EDIT] 6/2/07 :

  1. finally I found the 4 MB leaks during session switch. It’s the texture of renderCapture card. Each time render get captured, a brand new texture object will be created, and overwhelming texture pool in RAM. So it has to be released before removing the card.
  2. DirectScrolledFrame’s canvas hidden resistance fixed

[EDIT] 6/3/07 :

  1. added extension line of snap marker. Usage : snap to the marker first to enable it’s XZ extension line. So, by having 2 X&Z extension lines, you have an intersection point. Those lines are black&white dash lines, span from the snapped marker to the origin of the node (if not snapped at the start of transform), or to the mouse position (if snapped at the start of transform). To avoid building the lines again and again, I use very long line instances, and clip planes are used to cut the lines precisely.

[EDIT] 6/6/07 :

  1. simplified extension line’s clip plane placement
  2. added intersection point visualizer
  3. added RightMouseButton click to enable/disable snap marker’s extension lines. Usage : right click inside the marker.

[EDIT] 6/18/07 :

  1. extension line’s visibility logic fixed
  2. right click snap now ignores the extension lines
  3. now uses vertex color for many lines
  4. changed key for parentsList/A2Dscenegraph toggle
  5. clearer distinction of the currently edited node’s snap markers and the other nodes’

[EDIT] 6/20/07 :

  1. bug fix : the original active state of every DirectGUI now saved, and only the ones were active will be re-activated on exit
  2. now able to pan aspect2d too, using MMB

[EDIT] 6/21/07 :
cleaned up & tiny typo fixed

[UPDATE] 7/3/07 :
1. added nodesListGUI placement threshold
2. added node position and scale panel
Now it’s possible to :
[=] type-in the transform number
[=] copy a node’s position and/or scale and paste it (+XYZ filters) to other node, relative to “fake” render2d or to the parent. The XYZ filters only affect the PASTE process, while the COPY process copies the transform properties entirely. There are COPY & PASTE buttons, and of course you can use Ctrl+c and Ctrl+v as well.
It’s available both in Select Mode and Edit Mode, and fully undoable/redoable.
Empowered DirectEntry features :
[=] press Escape to cancel the input typing
[=] if the input value couldn’t be converted into float, ‘INVALID’ notification text would remind you to fix it
[=] clicking other DirectEntry box will force the current DirectEntry to accept the input, so if it’s invalid, you’d have to fix it, or simply cancel it
[=] clicking any DirectButton or DirectCheckButton while a DirectEntry is still in focus will automatically cancel the input and restore the original DirectEntry value
3. added enableEditSession option in init
4. other tiny improvements & cleaning up
5. bug fix : bad DirectButtonsNameList creation time
6. added jump to end of edit history
7. changed key for jump to beginning of edit history, now uses HOME and END to go back and forth.

[UPDATE] 7/23/07 :

  1. integrated the collidable non-rectangular polygonal button system :
  2. packed the previous empowered DirectEntry into a custom class :
    Features :
    [=] frame & text color distinction when in-focus
    [=] able to set the desired entry value type : string, float, integer
    [=] equipped with value validity check. It would run the given user command if the user enters invalid value type (inconvertible), and then force user to fix the value
    [=] able to keep the entry focus after running user valid-command
    [=] pressing Escape cancels the input and restore the previous value & color
  3. packed DirectButton and DirectCheckButton into custom classes :
    basically only to make them aware of the custom DirectEntry (myEntry class),
    so while there is an in-focus myEntry, and user presses any custom button,
    the in-focus myEntry’s value would be restored to it’s previous value, and
    the focus would be dropped.
    [EDIT] :
  4. myEntry : added a reminder of the expected value type if the input value invalid
  5. myEntry : added explanation about not to use ‘command’ keyword
  6. separated the extension classes into a module
    [EDIT] :
  7. bug fix : modules structure (now uses builtins)

[UPDATE] 9/11/07 :

  1. since v1.4.0, DirectGUI instance name is prefixed by the class name. Some code parts use instance name, so it wasn’t work as expected. Fixed by using instance attribute : guiId.
  2. integrated the latest update of polygonal button system

[UPDATE] 9/13/07 :
minor ignorable changes

[MAJOR UPDATE] 10/20/07 :

  1. added TAB and SHIFT+TAB to select dialog’s buttons
  2. added SPACE to execute button’s command
  3. localized AutoSaveAspect2d and SceneGraphItem into a separate module
  4. bugfix: it’s old stuff, I forgot to exclude the snap markers from contributing to the parent’s bounding box, resulting wrong bounds, it’s so obvious for node whose origin is usually far outside the geometry, e.g. OnscreenText.
  5. bugfix: it’s precision issue of snapping when scaling, which I used for decision making. I didn’t realized that there maybe numerical tiny difference (not zero), which at some point it yields huge scaling. I fixed it using 1e-6 threshold and no more problem.
  6. added non-origin scale-base for other-type nodes (other than geomnode or DirectGUIs classes), with 2 new markers (3 & 4 pointed-stars), which represent the node’s bounding box, automatically adjusted upon any child’s transform change. Added bounding box rectangle visualizer too.
  7. since the number of markers on the scene get bigger, rendering the marker geometry used to take a lot of time. Now I use point rendering (sprite texture) rather than geometry. Result : ~350% boost. Extra bonus : I can distinguish the currently edited node’s snap markers from the others better than before, since I use textures, so I can simply override it with additional pre-loaded textures.
  8. changed key for help, now uses F1
  9. added ability to set view focus on the selected node (it’s brought to screen center)


This is amazing.

Thanks, though I don’t use it often.

I missed something minor in the user guide, wonder why the order of the snap keys got scrambled. Also I missed some tiny explanation.

[MINOR UPDATE] 11/3/07 :

  1. no longer using mouse watcher regions to block the collision when the mouse is hovering on the properties panel. Now uses a very simple bounds check.
  2. the selected node’s bounding box now redrawed upon transform change.

[MINOR UPDATE] 11/24/07 :
bugfix : bounding box vis removal in applyHistorySelectMode

Hi ynjh,

I downloaded your examples, forgive me for my inexperience with panda3d I have been looking into it for about 3 days now. In my evaluation of it I was told that the GUI system is not up to par, but by looking at your example (on your website) I see you have some interesting GUI going on that I would love to have examples of.

I’ll be honest I have no idea what the point of your program is (nodes?), but I’m sure its useful to people that understand panda3d more then I do at the moment. But what I would love is for you to post some standalone examples of how you did some of that more complicated gui:

  • Scrollable treeview
  • scrollable listview

very impressive!



etc ? What else, mention them all.
I’ll do it this weekend.


Well I threw in etc, because I’ll be honest, when I looked at your program it was somewhat overwhelming. Lots of stuff going on there, but very impressive to be sure.

I just think the panda3d community could benefit if you could possibly take out pieces of your program and put them into individual runnable programs that we could use as examples.

What I would love to see personally is the scrollable treeview and most importantly a selectable scrollable listview. I also found your customized buttons to be impressive, the Yes/No/Cancel was very nice. I think you tried to share that one in another post but I could not download it when I tried.

What I’m trying to decide is if my current game will transfer well over to Panda3d, currently it is written in python using pyOpenGL, but pyOpenGL is not well developed so I’m looking for alternatives.

I managed to run your program and its very interesting. Is its purpose to modify the placement and size of 2D objects?

Thanks for replying,


haha…, yes, 4000 lines is quite overwhelming.
You couldn’t DL it ? I could be server downtime. Try again.

The selectable scrollable listview is simply DirectButtons parented to DirectScrolledFrame’s canvas.

Yes, that’s the point.
Actually, at the moment it’s still bound to whatever your window’s aspect ratio (relative to aspect2d, not render2d).

Done, it’s pulled out (but still need some improvement) :