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

bf-committers@blender.org bf-committers@blender.org
Tue, 18 May 2004 18:27:18 -0500


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