Elysian Shadows

The Toolkit is Born!

Many applications let the user search, view, and edit individual items that belong to a data set. The data might be held in files or accessed form a database or a  network server. A simple approach to this would be to populate your widgets with the entire contents of a data set; the users would perform all their searches and edits on the data held in the widget, and at some point the changes would be written back to the data source. Although simple to understand and use, this approach doesn't scale very well to large data sets and doesn't lend itself to situations where we want to display the same data set in two or more different widgets.

A popular approach to this is MVC, "Model-view-controller." In the MVC approach, the model represents the data set and is responsible for both fetching the data that is needed for viewing and saving back any changes. Each type of data set has its own model, but the API that the models provide to the views is uniform regardless of the underlying data set. The view presents the data to the user. With any large set, only a limited amount of data will be visible at any one time, so that is the only data that the view asks for. The controller mediates between the user and the view, converting user actions into requests to navigate or edit data, which the view then transmits to the model as necessary. 

Now, bear with me for a minute and keep in mind the idea of a "model-view-controller." 

A problem I always found particularly annoying was keeping track of form "states" before it is submitted. When a form is typically "submitted" it goes through a "validation step" where it's processed for correct input, completeness, buffer overflows, etc. Then, if successful, the form proceeds to place all of its data into a data set, then close itself. However, if you've got a dynamic form that changes shape for some reason...It doesn't hit that "validation" step until after you've hit submit, and it doesn't actually save the data out until afterwards. 

Consider my old itemset dialog for a minute. I can edit "concrete" or "abstract" items here...All in the same window. The idea was to click an item, and its stats all populate the fields. Change values...Then click another item and change its values. Sounds simple enough....

But this image represents a problem! Lets say that you type in some bullshit into a field, change some values...And it hasn't yet been "verified." So I really can't "save it" just yet. 

Then somebody clicks over to another item...Then wants to switch back and continue editing. Well...None of the previous data was "submitted" or verified. 

So I needed to create some way to keep track of the current "state." What if they made a bunch of changes....Then just "X" out of the dialog, not wanting to keep any? That's perfectly fine, so long as all the changes weren't actually reflected in the dataset, only in the actual "view" they were just looking at. Closing that "view" just discarded all of the data, and since you didn't hit "Ok," all the fuckups you just made have no effect on your project!

You should by now be realizing how a MVC model would tie in...But if not, continue to bear with me as I explain a great feature Falco and i wanted in the editor, and proceed to kill 3 birds with one stone. 

Well, we thought it would be pretty kickass to have a "Project View" sidepanel. In some of the screenshots you've seen already, there's a panel on the left that says "Project." The idea is to have any number of "projects" open at a time, each with any number of "levels," each with their own set of "areas." The sidepanel would provide "drag and drop" functionality for editing your project, and help the ultimate user to understand the way things are structured. 

A really cool thing that we could do with this is allow artists so simply drag tilesheets (of any size, multiples of 32) into a "tiles" folder in the "sidepanel" and it will automatically integrate itself into the project and level, and automatically update the "512x512" sheet the engine loads. Or you can drag a .map from your desktop into your project folder, or a .npc, or a .lua. 

The files in the "Project Panel" represent a real filetree how it will look if you were to save it on your system. And some of those files are files that the user of the editor will have no bussiness touching at all--namely, the ones output by the editor to be read-in by the engine. The goal is to make the 512x512 sheet be one of those things the user never touches--the editor outputs all of your "tiles" in that manner to be read in by the engine. All files being read by the engine are pretty much in binary and unreadable. These are the things that my editor "generate" and "output" for the engine...And they're still represented in the side panel.

So here's the thing. The actual "editor" and its main user interface represent the "current state" almost the same as an "un-submitted form" from the example above does. The sidepanel won't "reflect" that state until it's ready to do so. This is almost the same concept of an IDE representing an asterisk by the filename of the .cpp you're editing before you save and compile it. So files that you've "changed" in the editor but have not yet "submitted" (by saving, or changing "files") will be drawn in red. When you "submit" them, what actually happens is that the editor takes the nice "map" that you're staring at made of art, tiles, etc, and generates an up-to-date "output" (.txt) for the engine.  So your .map file will usually be out of date.[b] If you lay a single tile, the .map on your harddrive reflects different changes than what you're staring at on your screen. That .map is being drawn in your side panel, yet may be different still and more up-to-date than that on your harddrive.[/b] But the user's staring at the "most up to date" version on his screen where he's actually clicking and laying shit. If he fucks things up, he can double click on the .map in his tree view to "load it," thereby loosing all current changes. Or, if he hasn't yet "saved" his project to the harddrive via ctrl-S, he can right click that same .map and click "refresh" to have one exactly consistent with the harddrive, then double click that one to dump all of their modern changes and revert back to whatever is on the harddrive.

Here's an image that'll hopefully explain it a little better....

So if I employ this setup correctly, it should provide an experience for the user waaaayyy ahead of what it's always been. The goal is to get something feeling like Unity's environment--nice and polished. And, at the same time, by doing this, I'm effectively using the MVC model and setting the foundations for editor "states" and the functionality for being able to auto-save and recover from a crash. I think that this is the way to go...And, if we don't like the user interface, that's very easily fixed.

Now, I've got to start somewhere....So I began drafting some objects I'm going to create to begin my framework. This is what I have thus far:

The key thing to note is the idea of my "current level." That's essentially the editor's current state. Then there's a corresponding "levelData" object that becomes populated with changes at keytimes in the editor. When you save or load, you are simply syncing everything--first you replace all of the data in levelData with the crap in Current level, then overwrite whatever was on the harddrive with the contents of "levelData." The reverse would also be true. 

Also notice the major differences between the "data" and "current." Current litterally has a QT "scene" for "viewing" and a bunch of objects that have functionality for "on mouse over," "click", etc. The "data" doesn't need all of this extra shit--it's just a 2d array. So yes, switching "levels" would require a small loadtime whilest it swaps the data in its levelData with whats in your current "view," then populates the view with the data in the new level's dataset. But this is not true for "areas" as they all reside in memory at once--so "tabbing over" to another map is no loaddtime. Only switching "levels" (meaning, tilesets and stuff).

Lemme know what you think. Falco should be posting shortly about our talk earlier with integration, and we'll begin to braindump where it'll fit into the editor's new design.

Any ideas, suggestions, comments, w/e are welcome. I'll try to keep this moderately updates so that if anybody feels the urg to helpout with the editor, it's atleast closely the same as what's in the repositories. 

Thanks!

Discussion Topic

Falco Girgis
Falco Girgis is the founder and lead software architect of the Elysian Shadows project. He was previously employed in the telecom industry before taking a chance on Kickstarter and quitting his job to live the dream. He is currently pursuing his masters in Computer Engineering with a focus on GPU architecture.