Elysian Shadows

AssetIO Integration, Zoom, and Rotation

To review, the idea behind the AssetIO was to share a code base between the engine and editor so that there would be no "synchronization" required--the asset saving/loading are the exact same implementation in both. One of the problems with this is that assets in the Engine are deeply coupled with .libGyro (which contains various rendering, math, and other abstract implementations for different hardware) whereas the Editor is written in QT, which has its own drawing/animation framework. One possible solution was to simply create/utilize a QT version of .libGyro, as QT easily supports OGL integration...But, as you can imagine, that was not our number one option.

So what we ended up doing is a pretty neat way of abstracting away all of the assets into an almost data-only form, leaving only the functions for self-loading/saving. Then, the engine and editor can simply inherit from or encapsulate these abstract implementations. And when I say "we," I obviously mean Gyro--he's the one who implemented all of this with esGamma; my job was only to encapsulate/inherit from these abstract things and wrap when necessary! :P

Now, I obviously was not going to halt the development of the editor while ESGamma was underway, and vice-versa... So we utilizing the different repositories to handle our separate code-bases. What this means is that the ESToolkit's project file will actually be pointing to the Engine's source folder in the repository.

The actual .pro file for Toolkit looks like this:

# ------------------------------------------------- # Project created by QtCreator 2010-03-06T14:23:27 # ------------------------------------------------- QT += opengl TARGET = ESToolkit TEMPLATE = app INCLUDEPATH += ../../Engine/trunk/ESGamma/editorAsset/include      ../../Engine/trunk/ESGamma/libGyro/include SOURCES += main.cpp      estoolkit.cpp      projectmanager.cpp      projectdata.cpp      modifiablelevel.cpp      tilemanager.cpp      newprojectdialog.cpp      project.cpp      level.cpp      area.cpp      scenetile.cpp      sceneview.cpp      visualtile.cpp      ../../Engine/trunk/ESGamma/editorAsset/source/entity.cpp      ../../Engine/trunk/ESGamma/editorAsset/source/editor_sprite.cpp      ../../Engine/trunk/ESGamma/editorAsset/source/editor_level.cpp      ../../Engine/trunk/ESGamma/editorAsset/source/editor_collidable.cpp      ../../Engine/trunk/ESGamma/editorAsset/source/editor_area.cpp      ../../Engine/trunk/ESGamma/editorAsset/source/component.cpp      ../../Engine/trunk/ESGamma/libGyro/source/rect.cpp      ../../Engine/trunk/ESGamma/editorAsset/source/asset.cpp HEADERS += estoolkit.h      projectmanager.h      projectdata.h      modifiablelevel.h      tilemanager.h      newprojectdialog.h      project.h      level.h      area.h      scenetile.h      sceneview.h      visualtile.h      ../../Engine/trunk/ESGamma/editorAsset/include/tile.h      ../../Engine/trunk/ESGamma/editorAsset/include/object.h      ../../Engine/trunk/ESGamma/editorAsset/include/entity.h      ../../Engine/trunk/ESGamma/editorAsset/include/editor_sprite.h      ../../Engine/trunk/ESGamma/editorAsset/include/editor_level.h      ../../Engine/trunk/ESGamma/editorAsset/include/editor_collidable.h      ../../Engine/trunk/ESGamma/editorAsset/include/editor_area.h      ../../Engine/trunk/ESGamma/editorAsset/include/component.h      ../../Engine/trunk/ESGamma/editorAsset/include/asset.h      asset_platform.h FORMS += estoolkit.ui      newprojectdialog.ui 

If you'll note, all of the AssetIO dependencies are linked via relative paths (ex     ../../Engine/trunk/ESGamma/editorAsset/include/asset.h ), so before you can compile the toolkit, you need to be sure to update BOTH the editor and Engine repository, and that the two folders are in the same directory. I'd recommend setting up your repository folders somewhat how I have mine, in the above screenshot. But to each his own! :P

So now if you ever decide to take a look at the Toolkit's code, you'll see something like this from QT Creator:

One thing to note is the asset_platform.h (selected file in picture). All this is responsible for is defining a pre-compiler flag stating that we're compiling the Toolkit rather than engine. The rest is handled by Falco's hardcore coding skills--I'm sure he'll give you guys a more indepth look at how it works in the Gamma topic! ;p

For those of you who've actually been following the design diagrams of the toolkit and my small updates allow me to continue by explaining how exactly I utilize his assetIO in the editor:

Each of my data classes utilize a "has-a" relationship with their AssetIO counterpart. So, in the editor, I have a "Project," "Level," and "Area" class, each containing lists to eachother and other data required for organizing them internally in the toolkit, such as "name," different QObjects, and Toolkit enums. So, without AssetIO, there is no actual "data" being stored in my "area" class other than stuff to determine where it is in terms of the Toolkit's internal organiztion--there is no actual map data, npc, entities, etc. So my "Area" has-a "elysian::EditorArea," which is the data and save/load functions from assetIO. In addition to this, I have given my "Area" functions for swapping data to and from this "elysian::EditorArea." For example, I have a "toScene" and "fromScene" function in "Area." 'toScene' simply takes all of the data that is read from "elysian:EditorArea" and generates an actual "QScene" based on the values in tileArray and objectArray. 'fromScene' would do the exact opposite--it tears appart the actual QScene that the user has been modifying, and stores all the data into a 2d array in "elysian::EditorArea," which can then save itself to the harddrive.

Another small change I've made to the original design diagram that you should probably take note of:

The modifiableLevel class is no longer being utilized. I soon found that it was necessary, and simply gave the QScene it contained to each Area. Now my Areas all have their own QScene, which defaults to null and is only set when you use "projectManager" to call "open level," at which time the projectManager proceeds to call Scene creation functions on all of the Areas in the specified level. 

Currently I still have it in my project, but that will likely changed with the next update.

Now, with all of the talk about our AssetIO integration, I guess now would be the time to mention our debugging scheme.

Currently, if you look through the code, you'll find that I haven't put much thought into my error tracking system. Usually I hardcode some kind of descriptive error, then pop a modular dialog box. Well, this is a pretty poor method as you cannot "log" these error, and you cannot be expected to bother the user with less severe ones. Also, this may lead to multiple errors being reported at times where the user requires only one notifications. 

For example, lets say the the user tries to load a project. One of his levels is fucked, and missing the tilesheet.png. Using my (old) shit method, if my function "loadProject" is looping through all of the levels and calling load on them individually, then the individual "load" function for the level with the missing .png will return an error. This obviously will fuck up the loading of the entire project, so the projectLoad itself will return en error as well. Because of these error dependencies, it's necessary to take a step back and create an error logging system to handle this type of scenerio.

Luckily, Gyro's assetIO all use their own error tracking system, so I really didn't need to bother with that kind of thing...Until I realized that I need a way to display the error log to the user. Well, after some discussion with Gyro, we agreed on a pretty cool system that he went off to implement. Now, I can (and will) actually wire the AssetIO's error tracking system into the entire toolkit. It's a nifty way to only display to the user critical errors, and at that time also display the less critical ones. I will probably post more on the subject at a later time, after I'm able to make the changes necessary to fully utilize this system.

Now, lets take a small step back from all of the shared code/functionality, and take a look at the shit I've done in the actual editor!

Last time you fellas saw it, the "New Project Dialog" was done, but the 'done' button wasn't. Meaning, the dialog box itself was done, but the actual work it does (creating a new project) was not. Now, I've fixed this. When you hit "done," the dialog box will work correctly. It will generate a level of the given dimensions and name, load the given tilesheet into memory, and even display your level. This is because I have finally finished all of the backend code required for this to work.

However, there is not yet much you can do on the front end. I have not yet finished implementing the tile placement and selection system. So your new map will simply display a bunch of blank tiles (tile #0) that you cannot modify...Not very exciting (yet)! =(

Here's an a image that shows the tasks I've drawn up for myself whilest devving this weekend. The check marks show things that I'm done with. The Blue is design, the red is development, and the green is glam/features. This picture was taken verrrry late saturday night, so it's not fully up to date. I got slightly out of order in my workflow that what is displayed there...

So I've actually finished step #7, parts of step 9, and, obviously am working hard at number 8! If you'll notice, that leaves me only steps 5 & 6...Which sounds like would be most of the work, but the truth is, the majority is done! Now that the backend is done, implementing 5&6 should be a breeze! I was actually hoping to get them both done before making this post so that you guys could actually USE the editor...But I didn't quite have enough time this weekend, and felt that I should make this long overdue post anyway.

So, lets take a quick look at #7, the great feature of the weekend!

So yes. Everything on the backend is working, and to prove this, I've managed to utilize AssetIO's load and load the level "Cave2" from inside of the "Project" repository. Below is the level being draw, with rotation.

And here's scale as well:

Right now, to scale, you just hold control and scroll the mouse wheel. To rotate, hold control and move the mouse left or right (only dependent on the mouse's z movement). To reset the transformation, click the ugly button that says "Reset Transformtion" on the toolbar! (obviously, this will be prettier in the future! XD)

Well, alrighty! Wish I could post more, but I've been at it for an hour and half already...So be checking back up on this topic every few days for the post where I announce I've finished steps 5 & 6. To finish those (which shouldn't take too much time, provided that I'm able to dev this week) would be to have a working Toolkit back and ready to be distributed to you guys! My apologies for not quite having it this weekend...But I hope you do realize how astounding this progress is, especially the integrated code base!

Thanks for reading and feel free to ask any questions, comments, etc

Also, I've been meaning for a long time to give a much more detailed explanation of Gyro's component based design philosophy. Live-Dimension, be looking in the ESGamma topic over the next few days for an answer to your question. I've tried typing a response twice now--once on my ipad, which I accidentally shutdown, and once at work, where I again shutdown!. >.<

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.