Sign in to follow this  
  • entries
    235
  • comments
    509
  • views
    171993

Last of the level editor rewrite

Sign in to follow this  
SimmerD

111 views



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!
Sign in to follow this  


3 Comments


Recommended Comments

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.

Share this comment


Link to comment
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 >.

Share this comment


Link to comment
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.

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