Add some internal docs for the particle system and sprite engine
authorAlan Alpert <alan.alpert@nokia.com>
Tue, 17 Jan 2012 10:52:35 +0000 (20:52 +1000)
committerQt by Nokia <qt-info@nokia.com>
Mon, 23 Jan 2012 06:38:34 +0000 (07:38 +0100)
They're both large internal structures with extensive logic. Should have
at least a basic attempt at documentation (beyond inline comments).

Change-Id: I7d48ebf821fa759c11fa35889dbff8971644d23e
Reviewed-by: Martin Jones <martin.jones@nokia.com>
src/quick/items/qquickspriteengine.cpp
src/quick/particles/qquickparticlesystem.cpp

index 495957f..38be93f 100644 (file)
 
 QT_BEGIN_NAMESPACE
 
+/*
+    \internal Stochastic/Sprite engine implementation docs
+
+    Nomenclature: 'thing' refers to an instance of a running sprite or state. It could be renamed.
+    States and Transitions are referred to in the state machine sense here, NOT in the QML sense.
+
+    The Stochastic State engine takes states with stochastic state transitions defined and transitions them.
+    When a state is started, it's added to a list of pending updates sorted by their time they want to update.
+    An external driver calls the update function with an elapsed time, which becomes the new time offset.
+    The pending update stack is popped until all entries are past the current time, which simulates all intervening time.
+
+    The Sprite Engine subclass has two major differences. Firstly all states are sprites (and there's a new vector with them
+    cast to sprite). Secondly, it chops up images and states to fit a texture friendly format.
+    Before the Sprite Engine starts running, its user requests a texture assembled from all the sprite images. This
+    texture is made by pasting the sprites into one image, with one sprite animation per row (in the future it is planned to have
+    arbitrary X/Y start ends, but they will still be assembled and recorded here and still have to be contiguous lines).
+    This cut-up allows the users to calcuate frame positions with a texture percentage width and elapsed time.
+    It also means that large sprites cover multiple lines to fit inside the texture memory limit (which is a square).
+
+    Large sprites covering multiple lines breaks this simple interface for the users, so each line is treated as a pseudostate
+    and it's mostly hidden from the spriteengine users (except that they'll get advanced signals where the state is the same
+    but the visual parameters changed). These are not real states because that would get very complex with bindings. Instead,
+    when sprite attributes are requested from a sprite that has multiple pseudostates, it returns the values for the psuedostate
+    it is in. State advancement is intercepted and hollow for pseudostates, except the last one. The last one transitions as the
+    state normally does.
+*/
+
 /* TODO:
    make sharable?
    solve the state data initialization/transfer issue so as to not need to make friends
@@ -337,6 +364,7 @@ QImage QQuickSpriteEngine::assembledImage()
     return image;
 }
 
+//TODO: Add a reset() function, for completeness in the case of a SpriteEngine being restarted from 0
 void QQuickStochasticEngine::setCount(int c)
 {
     m_things.resize(c);
index 47aa4be..924a2d0 100644 (file)
 QT_BEGIN_NAMESPACE
 //###Switch to define later, for now user-friendly (no compilation) debugging is worth it
 DEFINE_BOOL_CONFIG_OPTION(qmlParticlesDebug, QML_PARTICLES_DEBUG)
+
+
+/* \internal ParticleSystem internals documentation
+
+   Affectors, Painters, Emitters and Groups all register themselves on construction as a callback
+   from their setSystem (or componentComplete if they have a system from a parent).
+
+   Particle data is stored by group, They have a group index (used by the particle system almost
+   everywhere) and a global index (used by the Stochastic state engine powering stochastic group
+   transitions). Each group has a recycling list/heap that stores the particle data.
+
+   The recycling list/heap is a heap of particle data sorted by when they're expected to die. If
+   they die prematurely then they are marked as reusable (and will probably still be alive when
+   they exit the heap). If they have their life extended, then they aren't dead when expected.
+   If this happens, they go back in the heap with the new estimate. If they have died on schedule,
+   then the indexes are marked as reusable. If no indexes are reusable when new particles are
+   requested, then the list is extended. This relatively complex datastructure is because memory
+   allocation and deallocation on this scale proved to be a significant performance cost. In order
+   to reuse the indexes validly (even when particles can have their life extended or cut short
+   dynamically, or particle counts grow) this seemed to be the most efficient option for keeping
+   track of which indices could be reused.
+
+   When a new particle is emitted, the emitter gets a new datum from the group (through the
+   system), and sets properties on it. Then it's passed back to the group briefly so that it can
+   now guess when the particle will die. Then the painters get a change to initialize properties
+   as well, since particle data includes shared data from painters as well as logical particle
+   data.
+
+   Every animation advance, the simulation advances by running all emitters for the elapsed
+   duration, then running all affectors, then telling all particle painters to update changed
+   particles. The ParticlePainter superclass stores these changes, and they are implemented
+   when the painter is called to paint in the render thread.
+
+   Particle group changes move the particle from one group to another by killing the old particle
+   and then creating a new one with the same data in the new group.
+
+   Note that currently groups only grow. Given that data is stored in vectors, it is non-trivial
+   to pluck out the unused indexes when the count goes down. Given the dynamic nature of the
+   system, it is difficult to tell if those unused data instances will be used again. Still,
+   some form of garbage collection is on the long term plan.
+*/
+
 /*!
     \qmlclass ParticleSystem QQuickParticleSystem
     \inqmlmodule QtQuick.Particles 2