I've made a minor change to the schedule. Implementation of dynamic graphics settings configuration was moved from week 1 (having too much work) to week 4 (having too little work). See the updated version in
the wiki.
A couple of design decisions/changes:
SampleEngine is now called SampleContext. It would be less confusing since OGRE itself is an engine, and more precise since its purpose is to provide a common, safe "context" for Samples.
The SamplePlugin class is no longer part of the framework (it will still be made for the browser). There are a couple of reasons for this. First of all, it contains no unique functionality. That is, it does absolutely nothing that a Sample doesn't do except for being where it is (in a plugin). Secondly, it should be completely up to the user to provide the SampleContext with Samples, and the SampleContext should be agnostic of the Samples' origins. So, the browser will be responsible for locating plugins containing Samples, extracting them, and giving them to the SampleContext.
The third design decision concerns cross-sample resource management. Originally, SampleContext only had to handle one scenario: switching from Sample A to Sample B, where A or B could be possibly null. But in order to leave room for the possibility of having multiple samples loaded in memory and being able to switch back and forth quickly between them (i.e. browser tabbing, adjacent areas in a game), it becomes inevitable to have more complicated loading scenarios...
Let's say we have Samples A and B loaded, and we want to unload Sample B and load Sample C instead. We can't just do it in order, because B and C could potentially share resources, in which case there will be redundant reloading of resources. We also shouldn't do it in reverse order (even if unloading B doesn't affect C), because after the first step the resources for both Samples will be loaded, but we never need to see them at the same time, so this is unnecessary stress on memory. The only solution is to unload B first
with the knowledge that C will be loaded immediately after, and not unloading its required resources. This was easy enough before, because we only needed to consider a maximum of two Samples: the current, and the next. Now, there can be any number of Samples, and we need to be able to load/unload any one of them
with maximum efficiency, without needing an overly large/complicated interface.
The problem here is that we can no longer just tell SampleContext "what to do", because that would involve making a complicated set of instructions that seems far removed from the simple job we need done. Instead, what we could do is just tell SampleContext
the end result we need, and hide away all the complexity. If you've ever used Ubuntu, chances are you've used the Synaptics package manager. If you have, you can probably guess what I'm about to propose...
The SampleContext will have a member class SampleContext::LoadJob. With a LoadJob, you can "mark" a Sample for loading or unloading, or "unmark" it. Basically, you're telling it which Samples you want loaded/unloaded
without providing an order. Here's a code example for the aforementioned scenario using LoadJob:
Code: Select all
SampleContext::LoadJob job;
job.markForLoading(sampleC);
job.markForUnloading(sampleB);
sampleContext->doLoadJob(job);
sampleContext->setActiveSample(sampleC);
Note that lines 2 and 3 can be switched and the effect would be the same. While this is certainly more complicated than the original "quick switch", this same level of complexity applies to
all possible scenarios, so overall, it makes the job easier. Plus, we get the feature we originally wanted. Besides, we could still make a "quick switch" wrapper method.
I know we agreed that tabbing is a little overkill for now, but I thought I should plan ahead for possible changes while I'm still laying out the foundations. A little extra work now is better than refactoring the whole darn thing later.
Please let me know what you think about these changes, guys. Thanks!