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

Chris McFarlen bf-committers@blender.org
Tue, 18 May 2004 13:26:23 -0500


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)

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.
}

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

On Tuesday 18 May 2004 14:44, jeremy@marzhillstudios.com wrote:
> Hiya
> 
> Been poking around the transform code for a while now and the 
> constraint code too. And had a few thoughts. I don't know where you 
> folks plan to take the code and theeth is pretty busy right now so I 
> can't get ahold of him. Maybe hell be able to see this :-)
> 
> transform(int mode) 
> 	this function is enormous and unweildy to work in. I know the plan 
> is to rewrite it so no criticism here. I just though I would offer 
> some thoughts on the direction that might be taken. I think we still 
> need a single entrypoint for transforms. However once we get there 
> packing all the action in that one function gets clunky real fast. I 
> propose branching out from transform to mode specific code. Have a 
> posemode transform function, an edit mode transform function and so 
> on and so forth I think it would make tracking down the code blocks 
> you need for a particular feature a lot easier. Transform would still 
> handle setting up any environment stuff that is shared by all the 
> modes. and of course there might be some operations on data that is 
> common between modes also. Those could be put in functions all the 
> modes could use. if we keep the mode entrypoints in the transform 
> function separate though we avoid any problems down the road when one 
> mode suddenly needs special treatment.
> 
> Constraints:
> 	the way they get evaluated now is rather hard to work with. I spent 
> days tracking down when constraints get evaluated for bones in 
> transform() finally managed to find a way to make sure it gets 
> evaluated at least once after the tranform is finished. Ideally 
> though we need a way to evaluate during the transform. That way the 
> user gets realtime feedback while working on the object or bone. How 
> to do that most efficiently I'm not totally sure. I was thinking 
> though that if before making a change to any transform data we tested 
> against a constraint then that would be workable. you could do that 
> by having the evaluate constraint functions return a boolean value 
> instead of actually changing the object's data. A failed the 
> constraint test value means don't perform the transform.
> This would also avoid any problems with people trying to figure out 
> how to modify object data properly. if only transform and object 
> creation handle the actual data modification and creation we have 
> less possibility for programmer errors later on.
> Anyway hope maybe this sparks some ideas on transform and 
> constraints. 
> 
> At it's current state the constraint system is really not useful for 
> animating armatures. We really need to fix that.
> 
> Jeremy Wall
> _______________________________________________
> Bf-committers mailing list
> Bf-committers@blender.org
> http://www.blender.org/mailman/listinfo/bf-committers
> 
>