First off, Merry Christmas to all of you. Hope you are enjoying some time off for the holidays.
The parser is behaving to expectation, which is great, considering I told you all that it would do everything short of walk on water. However, there are still two problems I see in ENIGMA that I fear will go uncorrected until they bite someone in the ass; I am going to address both of them and one personal problem here.
If you are a developer, try to pay a little attention. At least to the first two.Problem 1:
The extension system is subtly broken.
I don't know if anyone noticed this (I think HaRRi has stumbled upon it?), but the extension system is not as modular as it was designed to be due to issues with uninformed sideways casting. The compiler handles all the casting; the linker is not involved. Thus, extensions think
they are the only class that enigma::object_locals inherits virtually. Issue is, they are not. Thus, since alarms are first alphabetically, they're the only extension which will work.
Contrary to popular belief, extensions were designed to facilitate adding "heavy" functions as opposed to "groups of two or more" functions. By "heavy," I mean functions that have weighty dependency that might drive someone who is interested in disk and memory efficiency to drop us a complaint about it. Maybe someone doesn't need a 16 integer array in each object (talking of alarms). Maybe it really bothers someone that their objects all need a path_index variable, as well as position and time variables for their path. The point is, extensions make it so they can remove the entire system from their game, including the local variables that weigh down their objects.
To clarify, the issue is simply that when they need alarms and paths, both extensions assume that their bytes are the first in the structure, and one of them must logically be wrong. The fix is simply to do the casting from within the engine file (which is informed as to what each extension looks like and which extensions are being included). The detriment? We have data misread and life is hard.
Presently, you access the current instance (ENIGMA's equivalent of this
) using a global. There are actually a few problems with doing this:
- Casting that global to a virtual ancestor doesn't always work (as discussed above)
- Only one object can be this per running game per femtosecond
- All code has to be aware of any access boundaries associated with having only one object being this at a time
By the last one, I mean loops such as with() need to be extremely cautious about the length of time for which they change the current instance pointer. So far, this has only really entailed being careful to set it back at the end of the loop. It also, again, destroys any hope for threading anything to do with instances.The solution:
I am turning the instance addressing system on its ear.
The solution is actually pretty simple. We dump the globals that represent the current instances/iterators (namely, [snip]ENIGMA_global_instance[/snip] and [snip]instance_event_iterator[/snip]) and we replace them with a parameter given to ENIGMA functions which modify the current instance.
So basically, instead of this function:
void motion_set(int dir, double newspeed)
enigma::object_graphics* const inst = ((enigma::object_graphics*)enigma::instance_event_iterator->inst);
We have this function:
void motion_set(enigma::object_graphics* enigma_this, int dir, double newspeed)
So, not a huge difference, but enough that it will
mean some chaos.
If you are worried about the parameter, don't be. That's where the new parser comes in. I have not added this yet, as the pretty printer is not written. I want everyone on board with this idea before I ship it.
This idea has been up on the proposals board for some time; we're just finally to a point where I think I'll have the free time to deal with it. I will put everything up in the ENIGMA-JDI branch before I begin the migration. I'll make a new newspost to let you know the time has come to tackle it and do regression testing, when I'm ready for the change myself.
Again, the benefits are a fixed extension system, the option of threading, and a more stable instance addressing system.
As for the central iterator list (the list of active iterators to be conscious of when deleting shit), I am still happy with it. Though I may refactor it slightly to maintain links in the list correctly instead of moving deleted iterators back (in case an iterator is reused which is expecting one type of object and instead finds another type by mistake). For now, it should be fine.Problem 2:
The Platform-Graphics bridge is ill-conceived and horrible.
The engine directory structure gives the impression that you can use OpenGL or DirectX as your library on Windows. Presently, this isn't the case, as both systems require the window to be initialized in a special way. You may be familiar with WGL and GLX; they are, respectively, the Windows GL interface and the GL-X11 interface. Code for these monsters is found right in the Platforms folder—So far we've avoided possible issues using preprocessors, but these hurt compile time and are in general unattractive.
It's been a clusterfuck so far, because we're dealing with three entities in the Platforms folder instead of one:
- Platform-dependent code for all manner of things, including grabbing executable name and working with directories
- Window system code; the code that creates and manipulates windows
- Platform-specific Graphics code, eg, WGL/GLX
It's messy to separate those three items, which is why we have issues.Solution:
Create a new folder of bridge systems.
I don't care where in SHELL this folder is created, but it needs to contain folders such as Win32-OpenGL, Win32-DirectX, X11-OpenGL, etc, for each valid pairing of Window System - Graphics System.
We may also want to separate out the window system code and put it with the widget system code. This is leading to minor technicalities on Linux: The window is governed by raw X11, while the widgets are governed by GTK+. It hasn't led to any problems, but it has the potential to do so—especially on pairings in the future (eg, if some poor bastard tries to write QT widgets).
Since much of the code in the Win32/ folder was written by me when I was 16, it may be a good idea to comb over it again, anyway. If this can serve as an excuse to do so, go ahead and let it.Personal Problem
: I return to school after two weeks.
I have 14 days of freedom before I return to school, and I already need to start making preparations for that. Depending on how I tackle this semester, it may be even more work than the last. The good news? Two things: (1) the course which will generate the most work? It's on game design
. That's right, the thing we've all been doing since we were 12. (2) I am taking five courses instead of six, and one of them is philosophy. For those of you who have not taken a college philosophy course, they are an easy, effortless, and even fun A if you have an open mind and don't mind some discussion.
The bad news: The game I design has to use Ogre (or Unity or XNA—Not even considering the latter, not wanting the former since I use Linux)
, which I have never used before.
The other good news: I intend to deal with this gracefully by writing an Ogre extension for ENIGMA. If I have to deal with Ogre, this project may as well benefit from it.
Now you are all up to speed. In summary, brace for impact.