Last of the level editor rewrite

Published January 11, 2007
Advertisement


By late today or tomorrow, the major surgery on the level editor will be done. I'm sure there will be other usability tweaks over time, but I have only 3 out of the dozen or so tabs to do - the vertex, decals and atmosphere tabs.

Over the past couple of days I put in a limited form of Undo, and last night I put in auto-save. I also cleaned up the facet editing so you can't rename or delete important facets, like the 'name' facet.

The undo was an interesting problem. The classic way to do it is to have a command struct that contains enough information to undo itself. On every undoable command, you create one of these and store in some sort of container. When the user hits undo, you roll back the command using the saved undo information.

Of course, depending on how the code works, the amount of data needed to undo some commands can be huge - for instance, selecting the whole level and snapping the verts to a grid could require saving out basically the whole level geometry before the operation.

What I decided was that I would allow undo of rotation, placement and scaling of objects only, not creation/deletion, facet changes or any triangle or vertex geometry manipulation.

Each time the user goes into a modification mode or hits buttons that affect an object's matrix, I go through the selected objects and take snapshots of their matrix, and push it unto a per-object vector of past matrices.

When the user cancels the operation, or does Ctrl-Z later on, it just does a pop_back() on the history vector. With this particular method, the undo buffers are per-object, rather than app-wide, so you can individually undo changes, which I'm sure has its ups and downs.

It works well, but I'm extending it to support re-do also.

I'm also revamping the controls. Since I had so much trouble with the .net controls, I ended up using a bunch of keyboard shortcuts for things that should have been done with the mouse, so I've made a toolbar for manipulating movable objects where you click on a toolbar button, hold down the mouse button, and then the cursor disappears and you can manipulate the selected objects. Much better than the old method which kept the cursor visible, which would cause it to go offscreen, or over a control, etc.

I also added back in dirty handling, so it knows when you've changed something, and also added a new autosave feature. This saves your current name.lvl file as name.bak every minute or so ( configurable ). You can load .bak files just like .lvl files to go back to a saved version.

In other news, I've been a bit sick, but due to all my hoops playing, I'm able to sort of ride out most cold/flu type stuff pretty well. I ended up playing hoops during my break on jury duty on Tuesday. When I came back to the court, they ended up dismissing our case, so I didn't have to give my sob story after all!
Previous Entry Almost There...
Next Entry More options
0 likes 3 comments

Comments

Ravuya
Those object parameters are rather clever -- are those per-polygon, per-mesh, per-object, or per-entity? I assume it's implemented with a hash map internally.
January 11, 2007 01:54 PM
SimmerD
The 'facet' parameters are for every EditorObject, which means just about everything except static vertices and triangles, so you can attach properites to Triggers, Portals, AntiPortals, Cells, Rooms, Meshes, Entities, Decals and Sound Sources.

This way you can support things in your game that your editor doesn't directly know about, like I have a 'particle_type' facet that if found, puts a particle system where the object's bounding box is, so you usually put these on a trigger box.

You can also tag meshes with facets to effect the nearby navmesh. This way you can make a certain area ( like a railing near a ledge ) automatically keep AIs away from it.

At a certain point, you want the ability to filter out or create certain objects, so then you need a separate object category instead of using facets. For instance, I ended up adding Rooms, which originally were just a Trigger whose 'room' facet == true.

The facets are stored per-object in a std::map< std::wstring, Facet >.
January 11, 2007 04:34 PM
Ravuya
Yeah, that's why I figured you were doing it -- I'm looking for a relatively flexible properties system for entities in my editor and was considering something like your idea, but wasn't sure how much it would cost me to implement.

I assume if you're using it for something as performance critical as static geometry, that it must be fast enough to not really notice.
January 12, 2007 01:08 AM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement

Latest Entries

1.2 Almost ready...

1118 views

Sound Paths

1335 views

Stately Progress

1137 views

State Lines

1287 views

Pulsing

870 views

Return to The Ship!

1011 views

Cameras &amp; Boxes

1128 views
Advertisement