Finally I've got a big chunk of time to program my personal projects.
The last several months I was spending my mental state at work( we finally released Phoenix FD 3.0 ) and then at home trying (or wasting my time) to come up with a grand plan for a level editor that does everything: C++ code reloading, undo/redo, serialization, edit while play, and is implemented as simple as possible. This basically burned me out and I gave that plan up for a few months.
I had 10 vacation days left for this year (this is how it works in my country, every year we have ~20 paid vacation days), so i took them and started coding my level editor with refreshed mind.
So here is a screen shot of what I manged to code for a few days.
So basically this is a "Skeleton" of a 3d "editor:, meaning that it is general purpose and can be reused for different context. The architecture consists of:
- "EditorInstance" is the structure that holds the whole data for the scene. Everything from nodes, per node type properties, selected nodes ect.
- "EditorView" is the stricture that manages displaying and accepting input for editing the scene via a "viewport". This does not include the GUI, it is only the viewport and input that is related to it (like clicking inside of it to modify the scene).
- A GUI that just reads the data that is stored in "EditorInstance" and displays it (in my case the Parameter editor, the Outline, the buttons, ect.)
I KNOW that call the "Scene editor" and editor is pretty dumb but this is how it is named in the code. I will changed in the future, but I cannot come up with anything, so any ideas are welcome.
My initial plan for level editing was to use Maya and hotlink it with the game in order to reload levels (Maya has a sockets API), but I backed up form the idea, as I do not want to get tied to any version of a 3rd party software, as there are many many restrictions (the C++ compiler version for example, Maya and 3ds Max are usually lagging behind the MSVC C++ runtime versions), and I'm highly interested in that subject.
So the way that I plan to use that editor is to basically to import the the edited scene in the game, load what is needed and play it.
I really wanted to have "one structure" per object type that is used for both game and editing levels in order to reduce to code complexity and make everything to just work,
but as I think out it "what you edit is not what you play", while editing there is a lot of helper data that is needed just for editing and I didn't wanted to tray my game with such thing.
I gave up on the "edit while play" for the same reason.
the editor currently supports:
- Creating new nodes
- Creating parameters/attributes for the nodes on the fly
- Duplicate and Delete nodes.
- Custom and auto generated UI for the nodes
- Tool to manipulate the scene. For example there is tool to move/rotate/scale nodes, control the camera. So in theory in the future making a tool for terrain editing shouldn't be that hard(not that I've planned to add).
- Multiple viewports(not tested, but should work).
The things that I'm going to focus next few days (if I have time as a few family holidays are coming) are:
- Serialization (this should be pretty easy)
- Undo/Redo. I do not plan to use the command pattern. I will try to serialize the scene to something on every significant change. I think it wont be that slow and I will be less code and more stable.
- Animated parameters, not sure how needed that is, it is there, but not tested, and there is no interface for it.
Additionally Im trying to avoid callbacks as much as possible. Maya for example is full of callbacks and implementing a little bit more complex feature gets really hard sometimes as there are a ton of callbacks and a ton of context switches. Instead I use something called "dirty index" For example.
In Maya when an attribute was changed you can get(if you subscribe to) a callback that say "this attribute was changed. In my editor Every attribute (well no every currently one per node) has an "dirty index", so when I change the value of an attribute, I increment the "dirtyIndex" for that value, so anyone who is interested in that attribute can check if the dirty value was changed by comparing it to internally stored one from the last update. This currently works really well and save me a lot of typing and loosing my mind on callbacks and call orders.
Wow that was kind of long by my standard. I'm happy to hear any suggestions, experience with such things (as there isn't much on that subject on the web), and I'm open to questions ^_^