[Bf-committers] Thoughts on transform code rewrite - attention Theeth

Ton Roosendaal bf-committers@blender.org
Thu, 20 May 2004 11:43:57 +0200


Just separating the transform in a per-mode or per-object type won't  
help really... too much code then needs to be maintained double.
It is also important to at least try to provide the most uniform  
possible access to each transform mode, also from user point of view.  
There's a lot of overlap in code, and only few exceptions. Like for  
bones, manipulating skeletons efficiently could be just a separate  
piece of code.

Another aspect is for example extrusion of faces, which should be  
possible based on direction of normals of the faces. And don't forget  
Python hooks!

The function pointer idea could assist yes in helping design of clearly  
separated and small functions to do the transform, but I still miss the  
big picture and a clear set of functional targets what to achieve. A  
reconstruction of code should at least give same performance and  
functionality, and open up easier access to improve and add  

I've also written a short summary of what I expect from it... there's a  
*lot* of work todo here, but we shouldn't be afraid of targeting at  
something thats truely an improvement.

Below copied my version of what we could do:

(reaction to Theeths transform proposal, mail from March 11)

I would like to see added some way to have Python playing with it. And  
of course, enabling the much wanted 'transform 3d widget'  
That would mean: the system has to become event based, and not with a  
sub-loop anymore.

 From event based perspective it could be like:
(note; constraint here means user input like X-axis constraint)

Start Transformer engine
|- Parsing the mode
|- Initialising Trans_Constraint with mode arguments (if needed)
|- Running all the pre-transform code (trans init, centre, ...)
|- maybe: some callback to verify if data operated on is still valid
|- end with: setting up some 'transform handler' which can be called  
from event loops

Handle Transformer
|- mouse input
|- keyboard input
|- constraint
|- etc

Close Transformer
|- after trans code

None of these three chunks will have subloops. The old 'transform()'  
function then can just still have a subloop calling the 'handler', but  
python and a 3D widget then can use it as event based system.

To look at is:
- where does 'transformer' data reside, in a Blender SpaceWindow, in a  
- what if 2 transformers operate simulteneously (could work!)

And also... the methods how IpoKey currently works with it is very  


On Wednesday, May 19, 2004, at 01:27 Europe/Amsterdam,  
jeremy@marzhillstudios.com wrote:

> On 18 May 2004 at 13:26, Chris McFarlen wrote:
>> I have been in this function recently too and it truly is a monster!   
>> I think my idea parallels Jeremy's, it
>> may just add a little detail (or too much :) ).
>> In my opinion transform() should be table driven, where each  
>> transform mode has
>> an entry in the table with three function pointers.  One function  
>> gets called
>> when transform() is called and the mode is looked up, another every
>> loop iteration, and the last when a key is pressed that is not a key  
>> handled
>> by transform directly (i.e. escape, MMB, x, y, z). (or maybe always  
>> called after
>> those keys change the state)
> A table would be another way of branching out to the various modes.
> The standard method for Blender right now is a case statement. By the
> way when I say mode I don't mean translation/rotation/scale. I mean
> PoseMode, EditMode, ObjectMode and so on. The
> translation/rotation/scale modes could further branch out from these
> Each of the pose edit and object modes have different requirements
> for transformations.
>> Each function is passed a transform state struct that has the current  
>> info.  Something
>> like:
>> struct TransformState
>> {
>>     int mode;  // 'g', 'G', 's', or ...
>>     int xnow;
>>     int ynow;
>>     int xlast;
>>     int ylast;
>>     // axis constraints
>>     // whatever else is important to all modes
>>     union {
>>         struct {
>>             // mode 's' specific stuff
>>         } s;
>>         struct {
>>            // mode 'g' specific stuff
>>         } g;
>>         ...
>>     } m;
>> };
>> struct TransformEntry
>> {
>>     int    mode;
>>     void (*init)(TransformState *);
>>     void (*loop)(TransformState *);
>>     void (*key)(int k, TransformState *);
>> };
>> TranformEntry modes[] = {
>>   {  's', transform_s_init, transform_s_loop, transform_s_key },
>>   ...
>> };
>> Then transform itself becomes: (rough pseudocode, no error checking)
>> void transform(int mode)
>> {
>>     TransformEntry *te = lookup_transform_entry(tolower(mode));
>>     TransformState  ts;
>>     //initialize ts
>>     ts.mode = mode;
>>     ...
>>     te->init(&ts);
>>     while (!breakout) {
>>          read mouse
>>          if (we moved the cursor) {
>>             update state
>>             te->loop(&ts);
>>             redraw
>>          }
>>          while (qtest()) {
>>               Check key, maybe break the loop, update state
>>               te->key(&ts);
>>          }
>>     }
>>     check for escape, undo etc.
>> }
> I'm not sure we need new structs for transformation data. Especially
> since the data for objects differs from the data for bones. And there
> may be other differences too. Basically we just need to hold future
> transformation data to test against a constraint before we apply it.
>> This provides a good clean separation.  You could even add to the  
>> lookup table at runtime
>> if for some reason that became desireable.  If you don't like the  
>> table idea, you
>> could have a switch at the beginning of transform() that assigns the  
>> functions to function pointers.
>> Chris
> _______________________________________________
> Bf-committers mailing list
> Bf-committers@blender.org
> http://www.blender.org/mailman/listinfo/bf-committers
Ton Roosendaal  Blender Foundation ton@blender.org