Feedback

Please leave feedback and comments. I am always interested to hear how people get on using these LScripts!

Wednesday 24 September 2014

LScript - Motion_Slider


LScript (Layout) to make desk draws and filling cabinets move dynamically in relation to being in an earthquake, it ended up being one of my most used scripts, making objects slide from one place to another fixed along an axis such as a sliding mechanism inside of an office desk draw or the slider a keyboard rests upon. It reacts dynamically as its parents object moves and is baked to curves. Use Master_MotionBaker script to bake motions. *Master_MotionBaker compatible.

Changes

  • *Motion Baking implemented for quicker playback and network baking
  • Gizmo implemented to improve setting up
  • Added Lock / Unlock
  • Bake feature can now be used via Master_MotionBaker
  • Fixed Threshold bug
  • Fixed judder resulting from an equation flipping in unexpected circumstance
  • Replaced stabilizer with Damping

Compatible with Newtek LightWave 9.6 and above.

// LScript Item Animation - www.StephenCulley.co.uk
//
// web   address: http://www.stephenculley.co.uk
// email address: email@stephenculley.co.uk

/*  
    LScript Item Animation - Slider

    Motion_Slider.ls
      
*/

@version 2.2
@warnings
@script motion
@name *Slider

    // Title
    sTitle = "*Slider";

    // Version
    sVersion = "v1.0";

    // Item
    Item = nil;

    // Constant
    Scene; // Scene()

    // Variable
    aChannel = @"X","Y","Z"@;
    iChannel = 1; // Channel
    iIteration = 0; // Iteration
    vnGravity = <0.0,-1.0,0.0>; // Gravity

    // Envelope
    envDamping; // Damping
    envFriction; // Friction
    envMass; // Mass
    envMax; // Max
    envMin; // Min
    envMotionBaker; // Motion Baker
    envParentMotion; // Parent Motion
    envRandom; // Random
    envThreshold; // Threshold

    // Cache
    aCache;

        // [1] = i Frame
        // [2] = n time
        // [3] = n Position
        // [4] = n Momentum -
        // [5] = n Momentum +
        // [6] = v Parent World Position
        // [7] = n Parent Momentum +/-

    // Motion Baker   
    bMotionBakerLocked = false; // Locked
    bMotionBakerParent = false; // Parent
    iMotionBakerState = 2; // State

            // 1 = Disabled
            // 2 = Reset
            // 3 = Write
            // 4 = Read

    // Requester
    bRequesterUpdate = false; // Update
    iRequesterFrame = -1; // Frame

    ctrl_d0,ctrl_d1,ctrl_d1e,ctrl_d2v,ctrl_d2,ctrl_d2e,ctrl_d3v,ctrl_d3,ctrl_d3e,ctrl_d4,ctrl_d4e,
    ctrl_d5,ctrl_d5e,ctrl_d6,ctrl_d6e,ctrl_d7,ctrl_d7e,ctrl_d8,ctrl_d8e,ctrl_d9,ctrl_d10,ctrl_d11; // Dynamics
    ctrl_mb,ctrl_mbe,ctrl_mbl; // Motion Baker

/*   
---------------------------------------------------------------------------------------------------
                                                                                            CREATE
---------------------------------------------------------------------------------------------------
*/

create: obj
{
    // Item
    Item = obj;

    // Constant
    Scene = Scene();

    // Description
    setdesc(sTitle + " - Channel " + aChannel[iChannel]);

    // Envelope
    envDamping = Envelope("Damping (" + sTitle + ")",CHAN_NUMBER,Item.name); // Damping
    envDamping.persist(false);
    envDamping.createKey(0,0.8);
    envFriction = Envelope("Friction (" + sTitle + ")",CHAN_NUMBER,Item.name); // Friction
    envFriction.persist(false);
    envFriction.createKey(0,0.25);
    envMass = Envelope("Mass (" + sTitle + ")",CHAN_NUMBER,Item.name); // Mass
    envMass.persist(false);
    envMass.createKey(0,0.05);
    envMax = Envelope("Max (" + sTitle + ")",CHAN_NUMBER,Item.name); // Max
    envMax.persist(false);
    envMax.createKey(0,1.0);    
    envMin = Envelope("Min (" + sTitle + ")",CHAN_NUMBER,Item.name); // Min
    envMin.persist(false);
    envMin.createKey(0,-1.0);
    envMotionBaker = Envelope("Motion Baker (" + sTitle + ")",CHAN_NUMBER,Item.name); // Motion Baker
    envMotionBaker.persist(false);
    envParentMotion = Envelope("Parent Motion (" + sTitle + ")",CHAN_NUMBER,Item.name); // Parent Motion
    envParentMotion.persist(false);
    envParentMotion.createKey(0,1.0);
    envRandom = Envelope("Random (" + sTitle + ")",CHAN_NUMBER,Item.name); // Random
    envRandom.persist(false);
    envRandom.createKey(0,0.0);
    envThreshold = Envelope("Threshold (" + sTitle + ")",CHAN_NUMBER,Item.name); // Threshold
    envThreshold.persist(false);
    envThreshold.createKey(0,9.8);

    // Cache
    aCache[1] = -1; // Frame
    aCache[2] = 0.0; // Time
    aCache[3] = 0.0; // Position
    aCache[4] = 0.0; // Momentum -
    aCache[5] = 0.0; // Momentum +
    aCache[6] = <0.0,0.0,0.0>; // Parent World Position
    aCache[7] = 0.0; // Parent Momentum

    // Comring
    comringattach("*MotionBaker","comring_motionbaker"); // Comring *MotionBaker
}

/*   
---------------------------------------------------------------------------------------------------
                                                                                           DESTROY
---------------------------------------------------------------------------------------------------
*/

destroy
{
    // Comring
    comringdetach("*MotionBaker"); // Comring *MotionBaker
}

/*   
---------------------------------------------------------------------------------------------------
                                                                                           COMRING
---------------------------------------------------------------------------------------------------
*/

comring_motionbaker: event,data
{

    // Parent
    ParentItem = Item.parent;
    iParent = 1;
    while(ParentItem != nil)
        {
        iParent++;
        ParentItem = ParentItem.parent;
        }

    if(event != 0 && event != iParent)
        {
        return;
        }

    sMessage = comringdecode(@"s:200"@,data);

    if(strlower(sMessage) == "lock") // Lock
        {
        bMotionBakerLocked = true;
        }
    if(strlower(sMessage) == "unlock") // Unlock
        {
        bMotionBakerLocked = false;
        }
    if(strlower(sMessage) == "disable" && !bMotionBakerLocked) // Disable
        {
        iMotionBakerState = 1;
        }
    if(strlower(sMessage) == "reset" && !bMotionBakerLocked) // Reset 
        {
        iMotionBakerState = 2;       
        }
    if(strlower(sMessage) == "write" && !bMotionBakerLocked) // Write
        {
        iMotionBakerState = 3;        
        }
    if(strlower(sMessage) == "read" && !bMotionBakerLocked) // Read
        {
        iMotionBakerState = 4;
        }
    if(strlower(sMessage) == "parent" && !bMotionBakerLocked) // Parent
        {
        bMotionBakerParent = true;
        }
    if(strlower(sMessage) == "bake" && !bMotionBakerLocked) // Bake
        {
        motionbaker_bake(); // Bake
        iMotionBakerState = 1; // Disable
        bMotionBakerLocked = true; // Lock
        }

    // Requester
    if(reqisopen())
        {
        bRequesterUpdate = true; // Update
        setvalue(ctrl_mb,iMotionBakerState); // Motion Baker State
        setvalue(ctrl_mbl,bMotionBakerLocked); // Motion Baker Locked
        bRequesterUpdate = false; // Update
        }
}


/*   
---------------------------------------------------------------------------------------------------
                                                                                              BAKE
---------------------------------------------------------------------------------------------------
*/

motionbaker_bake
{
    if(iChannel == 1){envChannel = Envelope("Position.X",CHAN_NUMBER,Item.name);} // X 
    if(iChannel == 2){envChannel = Envelope("Position.Y",CHAN_NUMBER,Item.name);} // Y 
    if(iChannel == 3){envChannel = Envelope("Position.Z",CHAN_NUMBER,Item.name);} // Z 

    if(envChannel != nil)
      {
      for(frame = Scene().previewstart;frame <= Scene().previewend; frame++)
        {
        time = (1 / Scene().fps) * frame;
        iKey = envChannel.keyExists(time);
        if(iKey == nil)
            {envChannel.createKey(time, envMotionBaker.value(time));}
        else
            {envChannel.setKeyValue(iKey,envMotionBaker.value(time));}
        }  
      }

    info(Item.name + " baked"); // Info
    Refresh(); // Refresh
}

/*   
---------------------------------------------------------------------------------------------------
                                                                                           PROCESS
---------------------------------------------------------------------------------------------------
*/

process: ma, frame, time
{

/*   
-------------------------------------------------------------------------------
                                                                          Item
-------------------------------------------------------------------------------
*/

    // Parent Item
    ParentItem = Item.parent;

// ---------------------------------------------------------------------- end -

/*   
-------------------------------------------------------------------------------
                                                                     Requester
-------------------------------------------------------------------------------
*/

    if(reqisopen() && iRequesterFrame != frame)
        {
        bRequesterUpdate = true; // Update       

        setvalue(ctrl_d1,envFriction.value(Scene.currenttime)); // Friction
        setvalue(ctrl_d2,envMin.value(Scene.currenttime)); // Min
        setvalue(ctrl_d3,envMax.value(Scene.currenttime)); // Max
        setvalue(ctrl_d4,envMass.value(Scene.currenttime)); // Mass
        setvalue(ctrl_d5,envRandom.value(Scene.currenttime)); // Random
        setvalue(ctrl_d6,envDamping.value(Scene.currenttime)); // Damping
        setvalue(ctrl_d7,envParentMotion.value(Scene.currenttime)); // Parent Motion
        setvalue(ctrl_d8,envThreshold.value(Scene.currenttime)); // Threshold (m/s)

        iRequesterFrame = frame; // Frame
        bRequesterUpdate = false; // Update
        }

// ---------------------------------------------------------------------- end -

/*   
-------------------------------------------------------------------------------
                                                                     Iteration
-------------------------------------------------------------------------------
*/

    // Iteration
    iIteration++;
    if(aCache[1] <> frame)
        {
        iIteration = 1;
        }

// ---------------------------------------------------------------------- end -

/*   
-------------------------------------------------------------------------------
                                                         Motion Baker Disabled
-------------------------------------------------------------------------------
*/

    if(iMotionBakerState == 1)
        {
        return;
        }

// ---------------------------------------------------------------------- end -

/*    
-------------------------------------------------------------------------------
                                                           Motion Baker Parent
-------------------------------------------------------------------------------
*/
    if(bMotionBakerParent)
        {
        // Parent
        ParentItem = Item.parent;
        iParent = 1;
        while(ParentItem != nil)
            {
            iParent++;
            ParentItem = ParentItem.parent;
            }
        sMessage = "*parent";
        cMessage = comringencode(@"s:200"@,sMessage);
        comringmsg("*MotionBaker",iParent,cMessage);
        bMotionBakerParent = false;
        }

// ---------------------------------------------------------------------- end -

/*    
-------------------------------------------------------------------------------
                                                            Motion Baker Reset
-------------------------------------------------------------------------------
*/

    if(iMotionBakerState == 2)
        {
        aCache[1] = frame; // Frame
        aCache[2] = time; // Time
        if(iChannel == 1) aCache[3] = clip(envMin.value(time),envMax.value(time),ma.get(POSITION,time).x); // X Channel
        if(iChannel == 2) aCache[3] = clip(envMin.value(time),envMax.value(time),ma.get(POSITION,time).y); // Y Channel
        if(iChannel == 3) aCache[3] = clip(envMin.value(time),envMax.value(time),ma.get(POSITION,time).z); // Z Channel
        aCache[4] = 0.0; // Momentum -
        aCache[5] = 0.0; // Momentum +
        if(ParentItem != nil){aCache[6] = ParentItem.getWorldPosition(time);} else {aCache[6] = <0.0,0.0,0.0>;} // Parent World Position
        aCache[7] = 0.0; // Parent Momentum

        // Motion Baker Write
        iKey = envMotionBaker.keyExists((1 / Scene.fps) * frame);
        if(iKey == nil)
            {envMotionBaker.createKey((1 / Scene.fps) * frame, aCache[3]);}
        else
            {envMotionBaker.setKeyValue(iKey,aCache[3]);}
    
        // Motion Baker State
        iMotionBakerState = 3; // Motion Baker Write
        if(reqisopen())
            {
            bRequesterUpdate = true; // Update
            setvalue(ctrl_mb,iMotionBakerState); // Motion Baker
            bRequesterUpdate = false; // Update
            }
        }

// ---------------------------------------------------------------------- end -

/*
-------------------------------------------------------------------------------
                                                             Motion Baker Read
-------------------------------------------------------------------------------
*/

    if(iMotionBakerState == 3 && iIteration > 1) // Write
        {
        vPosition = ma.get(POSITION,time); // Position

        if(iChannel == 1) vPosition.x = aCache[3]; // X Channel
        if(iChannel == 2) vPosition.y = aCache[3]; // Y Channel
        if(iChannel == 3) vPosition.z = aCache[3]; // Z Channel

        ma.set(POSITION,vPosition);

        return;
        }  

    if(iMotionBakerState == 4) // Read
        {
        vPosition = ma.get(POSITION,time); // Position

        if(iChannel == 1) vPosition.x = envMotionBaker.value(time); // X Channel
        if(iChannel == 2) vPosition.y = envMotionBaker.value(time); // Y Channel
        if(iChannel == 3) vPosition.z = envMotionBaker.value(time); // Z Channel

        ma.set(POSITION,vPosition);

        return;
        }

// ---------------------------------------------------------------------- end -

/*
-------------------------------------------------------------------------------
                                                                       Process
-------------------------------------------------------------------------------
*/

    // Variable
    nDamping = 1.0 - clip(0.0,1.0,envDamping.value(time)); // Damping
    nMass = envMass.value(time); // Mass
    nMax = envMax.value(time);
    nMin = envMin.value(time);
    nPosition = 0.0; // Position
    nParentMotion = clip(0,1,envParentMotion.value(time)); // Parent Motion
    nRandom = 1.0 - (randu() * clip(0.0,1.0,envRandom.value(time))); // Random
    nThreshold = (1 / Scene().fps) * abs(envThreshold.value(time)); // Threshold
    vWorldPosition = ma.get(WPOSITION,time); // World Position
    vPosition = ma.get(POSITION,time); // Position
    vnRight = normalize3D(Item.getRight(time));
    vnUp = normalize3D(Item.getUp(time));
    vnForward = normalize3D(Item.getForward(time));

    // Angle Motion
    if(iChannel == 1) nAngleDot = dotproduct3D(normalize3D(vnGravity),vnRight); // X Channel
    if(iChannel == 2) nAngleDot = dotproduct3D(normalize3D(vnGravity),vnUp); // Y Channel
    if(iChannel == 3) nAngleDot = dotproduct3D(normalize3D(vnGravity),vnForward); // Z Channel

    nFriction = 1.0 - clip(0.0,1.0,envFriction.value(time)); // Friction
    if(nFriction < 1.0) nFriction = linear1D(nFriction,1.0,abs(pow(nAngleDot,3))); // Friction

    if(nAngleDot < 0.0)
        {
        // -
        nMomentumN = (nMass * nAngleDot * nRandom * nFriction) + aCache[4];
        nMomentumP = aCache[5] * nFriction * nDamping;
        }
    else
        {
        // +
        nMomentumP = (nMass * nAngleDot * nRandom * nFriction) + aCache[5];
        nMomentumN = aCache[4] * nFriction * nDamping;
        }

    // Parent Motion
    if(ParentItem != nil && nParentMotion > 0.0)
        {
        vParentWorldPosition = ParentItem.getWorldPosition(time);
        nParentMotionDistance = distance3D(aCache[6],vParentWorldPosition);
        vnParentMotionDirection = normalize3D(aCache[6] - vParentWorldPosition);
        if(iChannel == 1) nParentDot = dotproduct3D(vnParentMotionDirection,vnRight); // X Channel
        if(iChannel == 2) nParentDot = dotproduct3D(vnParentMotionDirection,vnUp); // Y Channel
        if(iChannel == 3) nParentDot = dotproduct3D(vnParentMotionDirection,vnForward); // Z Channel
        nParentMoment = nParentMotionDistance * nParentDot * nParentMotion;
        nParentMomentum = aCache[7] * nFriction;
        if(nParentDot > 0.0 && nParentMomentum < nParentMoment)
            {
            nParentMomentum = (nParentMotionDistance * (1 - nFriction) * nParentDot * nRandom) + (aCache[7] * nFriction);
            if(nParentMomentum > nParentMoment) nParentMomentum = nParentMoment;
            }
        else
        if(nParentDot < 0.0 && nParentMomentum > nParentMoment)
            {
            nParentMomentum = (nParentMotionDistance * (1 - nFriction) * nParentDot * nRandom) + (aCache[7] * nFriction);
            if(nParentMomentum < nParentMoment) nParentMomentum = nParentMoment;
            }
        nParentMomentum *= nParentMotion;
        }
    else
        {
        vParentWorldPosition = <0.0,0.0,0.0>; // Parent World Position
        nParentMoment = 0.0;            
        nParentMomentum = aCache[7] * nFriction;
        }

    // Threshold (m/s)
    if(nMomentumN < -nThreshold) nMomentumN = -nThreshold;
    if(nMomentumP > nThreshold) nMomentumP = nThreshold;
    if(nParentMomentum < -nThreshold) nParentMomentum = -nThreshold;
    if(nParentMomentum > nThreshold) nParentMomentum = nThreshold;

    // Position
    nPosition = aCache[3] + nMomentumP + nMomentumN - nParentMomentum + nParentMoment; // Compound Position

    if(nPosition <= nMin)
        {
        nPosition = nMin;
        nMomentumP = -nMomentumN * nDamping;
        nMomentumN = 0.0;
        }

    if(nPosition >= nMax)
        {
        nPosition = nMax;
        nMomentumN = -nMomentumP * nDamping;
        nMomentumP = 0.0;
        }

    if(iChannel == 1) vPosition.x = nPosition; // X Channel
    if(iChannel == 2) vPosition.y = nPosition; // Y Channel
    if(iChannel == 3) vPosition.z = nPosition; // Z Channel

// ---------------------------------------------------------------------- end -

/*
-------------------------------------------------------------------------------
                                                                            MA
-------------------------------------------------------------------------------
*/

    ma.set(POSITION,vPosition);

// ---------------------------------------------------------------------- end -

/*
-------------------------------------------------------------------------------
                                                            Motion Baker Write
-------------------------------------------------------------------------------
*/ 

    iKey = envMotionBaker.keyExists((1 / Scene.fps) * frame);
    if(iKey == nil)
        {envMotionBaker.createKey((1 / Scene.fps) * frame, nPosition);}
    else
        {envMotionBaker.setKeyValue(iKey,nPosition);}

// ---------------------------------------------------------------------- end -

/*
-------------------------------------------------------------------------------
                                                                         Cache
-------------------------------------------------------------------------------
*/

    aCache[1] = frame; // Frame
    aCache[2] = time; // Time
    aCache[3] = nPosition; // Position
    aCache[4] = nMomentumN; // Momentum -
    aCache[5] = nMomentumP; // Momentum +
    aCache[6] = vParentWorldPosition; // Parent World Position
    aCache[7] = nParentMomentum; // Parent Momentum

// ---------------------------------------------------------------------- end -

}

// CLIP

clip: min,max,n
{
    if(n < min) n = min;
    if(n > max) n = max;
    return(n);
}

// MAP RANGE

maprange01: n1,n2,i

{    
    if(n2-n1 == 0.0){return(0.0);}
  else
    {return((1/(n2-n1)) * (i-n1));}
}

// INTERPOLATION

linear1D: n1,n2,i // i = interpolation point (0-1)
{
    return(n1 * (1 - i) + n2 * i);     
}

cosine1D: n1,n2,i // i = interpolation point (0-1)
{
    i2 = (1 - cos(i * 3.1415926535)) * 0.5;
    return(n1 * (1 - i2) + n2 * i2);     
}

bicubic1D: n1,n2,n3,n4,i // i = interpolation point (0-1)
{
    i2 = i * i;
    n_01 = n4 - n3 - n1 + n2;
    n_02 = n1 - n2 - n_01;
    n_03 = n3 - n1;
    n_04 = n2;
    return(n_01 * i * i2 + n_02 * i2 + n_03 * i + n_04);
}

// VECTOR 3D

crossproduct3D: v1,v2 // v
{
    // Vector
    return();
}

distance3D: v1, v2 // n
{
    // Vector
    return(sqrt(((v2.x - v1.x) * (v2.x - v1.x)) +
                ((v2.y - v1.y) * (v2.y - v1.y)) + 
                ((v2.z - v1.z) * (v2.z - v1.z))));
}

dotproduct3D: v1,v2 // n
{
    // Vector
    return(v1.x * v2.x + v1.y * v2.y + v1.z * v2.z);
}

lineplanedistance3D: v1,vn1,v2,vn2 // n
{
    // Vector - v1 v2 is Vector / vn1 vn2 is Vector Normal
    nNumerator = dotproduct3D(vn2,v1) + dotproduct3D(-v2,vn2);
    nDenomimator = dotproduct3D(vn2,vn1);
    if(nDenomimator <> 0.0){return(-(nNumerator / nDenomimator));} else{return(0.0);}
}

lineplaneintersect3D: v1,vn1,v2,vn2 // a[1] b (true / false)
                                    // a[2] n (distance)
                                    // a[3] v (vector)
{
    // Vector - v1 v2 is Vector / vn1 vn2 is Vector Normal
    nNumerator = dotproduct3D(vn2,v1) + dotproduct3D(-v2,vn2);
    nDenomimator = dotproduct3D(vn2,vn1);
    if(nDenomimator <> 0.0){nDistance =  -(nNumerator / nDenomimator);} else{ nDistance = 0.0;}
    if(nDistance >= 0.0){a[1] = true;}else{a[1] = false;} // True / False
    a[2] = nDistance; // Distance
    a[3] = v1 + (vn1 * nDistance); // Vector
    return(a);
}

pointplane3D: v1,v2,vn2 // v
{
    // Vector - v1 is Vector / v2 is Vector on Plane / vn2 is Vector Normal on Plane
    return(v1 + (dotproduct3D(vn2,v2) - dotproduct3D(vn2,v1)) * vn2);
}

normal3D: v1,v2 // vn
{
    // Vector
    return();
}

magnitude3D: v // n
{
    // Vector
    return(sqrt((v.x * v.x) + (v.y * v.y) + (v.z * v.z)));
}

normalize3D: v // v
{
    // Vector normalize to 0 - 1
    nMagnitude = magnitude3D(v);
    if(nMagnitude <> 0) nMagnitude = 1 / nMagnitude;
    return(v * nMagnitude);
}

/*   
---------------------------------------------------------------------------------------------------
                                                                                              LOAD
---------------------------------------------------------------------------------------------------
*/

load: what,io
{
    if(what == SCENEMODE)   // processing an ASCII scene file
    {
        if(io.read().asStr() == sTitle + " " + sVersion)
            {
            iChannel = io.read().asInt(); // Channel
            vnGravity = ; // Gravity

            // Motion Baker
            bMotionBakerLocked = io.read().asInt(); // Motion Baker Locked
            iMotionBakerState = io.read().asInt(); // Motion Baker State

            // Envelope
            envDamping.load(); // Damping
            envFriction.load(); // Friction
            envMass.load(); // Mass
            envMax.load(); // Max
            envMin.load(); // Min
            envMotionBaker.load(); // Motion Baker
            envParentMotion.load(); // Parent Motion
            envRandom.load(); // Random
            envThreshold.load(); // Threshold (m/s)

            // Description
            setdesc(sTitle + " - Channel " + aChannel[iChannel]);
            }
        else
            {
            info(sTitle + " - Error");
            }
    }
}

/*   
---------------------------------------------------------------------------------------------------
                                                                                              SAVE
---------------------------------------------------------------------------------------------------
*/

save: what,io
{
    if(what == SCENEMODE)
    {
        // Header
        io.writeln(sTitle + " " + sVersion);

        io.writeln(iChannel); // Channel
        io.writeln(vnGravity.x); // Gravity X
        io.writeln(vnGravity.y); // Gravity Y
        io.writeln(vnGravity.z); // Gravity Z
       
        // Motion Baker
        io.writeln(bMotionBakerLocked); // Motion Baker Locked
        io.writeln(iMotionBakerState); // Motion Baker State

        // Envelope
        envDamping.save(); // Damping
        envFriction.save(); // Friction
        envMass.save(); // Mass
        envMax.save(); // Max
        envMin.save(); // Min
        envMotionBaker.save(); // Motion Baker
        envParentMotion.save(); // Parent Motion
        envRandom.save(); // Random
        envThreshold.save(); // Threshold (m/s)
    }
}

/*   
---------------------------------------------------------------------------------------------------
                                                                                           OPTIONS
---------------------------------------------------------------------------------------------------
*/

options
{
    if(reqisopen())
        {
        reqend();
        return;
        }

    // Variable
    iVar = 0;

    reqbegin(sTitle + " " + sVersion);
    reqsize(300,307);

    ctrl_tab = ctltab("Dynamics","*Motion Baker","Developer");

    // Dynamics
    ctrl_d0 = ctlchoice("Channel",iChannel,@"X","Y","Z"@);
    ctrl_d1 = ctlpercent("Friction",envFriction.value(Scene.currenttime)); // Friction
    ctrl_d1e = ctlbutton("E",20,"button_d1e"); // Button
    ctrl_d2v = ctlminislider(" ",iVar,-100,100);
    ctrl_d2 = ctldistance("Min",envMin.value(Scene.currenttime)); // Min
    ctrl_d2e = ctlbutton("E",20,"button_d2e"); // Button
    ctrl_d3v = ctlminislider(" ",iVar,-100,100);
    ctrl_d3 = ctldistance("Max",envMax.value(Scene.currenttime)); // Max
    ctrl_d3e = ctlbutton("E",20,"button_d3e"); // Button
    ctrl_d4 = ctlnumber("Mass",envMass.value(Scene.currenttime)); // Mass
    ctrl_d4e = ctlbutton("E",20,"button_d4e"); // Button
    ctrl_d5 = ctlpercent("Random",envRandom.value(Scene.currenttime)); // Random
    ctrl_d5e = ctlbutton("E",20,"button_d5e"); // Button
    ctrl_d6 = ctlpercent("Damping",envDamping.value(Scene.currenttime)); // Damping
    ctrl_d6e = ctlbutton("E",20,"button_d6e"); // Button
    ctrl_d7 = ctlpercent("Parent Motion",envParentMotion.value(Scene.currenttime)); // Parent Motion
    ctrl_d7e = ctlbutton("E",20,"button_d7e"); // Button
    ctrl_d8 = ctldistance("Threshold (m/s)",envThreshold.value(Scene.currenttime)); // Threshold (m/s)
    ctrl_d8e = ctlbutton("E",20,"button_d8e"); // Button
    ctrl_d9 = ctlnumber("Gravity X",vnGravity.x); // Gravity X
    ctrl_d10 = ctlnumber("Y",vnGravity.y); // Gravity Y
    ctrl_d11 = ctlnumber("Z",vnGravity.z); // Gravity Z

    ctlposition(ctrl_d0,36,32,212,20,100); // Channel
    ctlposition(ctrl_d1,36,54,212,20,100); // Friction
    ctlposition(ctrl_d1e,272,54,20,20); // Friction Button
    ctlposition(ctrl_d2v,238,76,10,20); // Min
    ctlposition(ctrl_d2,36,76,212,20,100);
    ctlposition(ctrl_d2e,272,76,20,20); // Min Button
    ctlposition(ctrl_d3v,238,98,10,20); // Max
    ctlposition(ctrl_d3,36,98,212,20,100);
    ctlposition(ctrl_d3e,272,98,20,20); // Max Button
    ctlposition(ctrl_d4,36,120,212,20,100); // Mass
    ctlposition(ctrl_d4e,272,120,20,20); // Mass Button
    ctlposition(ctrl_d5,36,142,212,20,100); // Random
    ctlposition(ctrl_d5e,272,142,20,20); // Random Button
    ctlposition(ctrl_d6,36,164,212,20,100); // Damping
    ctlposition(ctrl_d6e,272,164,20,20); // Damping Button
    ctlposition(ctrl_d7,36,186,212,20,100); // Parent Motion
    ctlposition(ctrl_d7e,272,186,20,20); // Parent Motion Button
    ctlposition(ctrl_d8,36,208,212,20,100); // Threshold (m/s)
    ctlposition(ctrl_d8e,272,208,20,20); // Threshold Button
    ctlposition(ctrl_d9,36,230,212,20,100); // Gravity X
    ctlposition(ctrl_d10,36,252,212,20,100); // Gravity Y
    ctlposition(ctrl_d11,36,274,212,20,100); // GRavity Z

    ctlpage(1,ctrl_d0,ctrl_d1,ctrl_d1e,ctrl_d2v,ctrl_d2,ctrl_d2e,ctrl_d3v,ctrl_d3,ctrl_d3e,
              ctrl_d4,ctrl_d4e,ctrl_d5,ctrl_d5e,ctrl_d6,ctrl_d6e,ctrl_d7,ctrl_d7e,ctrl_d8,ctrl_d8e,ctrl_d9,ctrl_d10,ctrl_d11); // Dynamics

    // Motion Baker
    ctrl_mb = ctlchoice("State",iMotionBakerState,@"Disable","Reset","Write","Read"@); // Choice
    ctrl_mbe = ctlbutton("E",20,"button_mbe"); // Button
    ctrl_mbl = ctlcheckbox("Lock",bMotionBakerLocked); // Checkbox
    ctlposition(ctrl_mb,10,32,260,20,60); // Choice
    ctlposition(ctrl_mbe,272,32,20,20); // Button
    ctlposition(ctrl_mbl,220,58,72,20); // Checkbox
    ctlpage(2,ctrl_mb,ctrl_mbe,ctrl_mbl);

    // Developer
    ctrl_dev = ctltext("","developer: Stephen Culley","http://www.stephenculley.co.uk");
    ctlposition(ctrl_dev,10,267,280,20,100);
    ctlpage(3,ctrl_dev);

    // Refresh
    ctlrefresh(ctrl_d0,"refresh_d0"); // Channel
    ctlrefresh(ctrl_d1,"refresh_d1"); // Friction
    ctlrefresh(ctrl_d2v,"refresh_d2v"); // Min
    ctlrefresh(ctrl_d2,"refresh_d2");
    ctlrefresh(ctrl_d3v,"refresh_d3v"); // Max
    ctlrefresh(ctrl_d3,"refresh_d3");
    ctlrefresh(ctrl_d4,"refresh_d4"); // Mass
    ctlrefresh(ctrl_d5,"refresh_d5"); // Random
    ctlrefresh(ctrl_d6,"refresh_d6"); // Damping
    ctlrefresh(ctrl_d7,"refresh_d7"); // Parent Motion
    ctlrefresh(ctrl_d8,"refresh_d8"); // Threshold (m/s)
    ctlrefresh(ctrl_d9,"refresh_d9"); // Gravity X
    ctlrefresh(ctrl_d10,"refresh_d10"); // Gravity Y
    ctlrefresh(ctrl_d11,"refresh_d11"); // Gravity Z
    ctlrefresh(ctrl_mb,"refresh_mb"); // Motion Baker State
    ctlrefresh(ctrl_mbl,"refresh_mbl"); // Motion Baker Locked
    reqopen();
}

refresh_d0:value // Channel
{
    iChannel = value;
    setdesc(sTitle + " - Channel " + aChannel[iChannel]);
}

refresh_d1:value // Friction
{
    if(bRequesterUpdate) return; // Requester Update
    setvalue(ctrl_d1,clip(0.0,1.0,value));
    iKey = envFriction.keyExists(Scene.currenttime);
    if(iKey == nil)
        {envFriction.createKey(Scene.currenttime,clip(0.0,1.0,value));}
    else
        {envFriction.setKeyValue(iKey,clip(0.0,1.0,value));}
}

button_d1e // Friction
{
    envFriction.edit();
}

refresh_d2v:value // Min
{
    setvalue(ctrl_d2,clip(-999.0,envMax.value(Scene.currenttime),envMin.value(Scene.currenttime) + value *.001));
    setvalue(ctrl_d2v,0);
}

refresh_d2:value // Min
{
    if(bRequesterUpdate) return; // Requester Update
    setvalue(ctrl_d2,clip(-9999999999.0,envMax.value(Scene.currenttime),value));
    iKey = envMin.keyExists(Scene.currenttime);
    if(iKey == nil)
        {envMin.createKey(Scene.currenttime,clip(-9999999999.0,envMax.value(Scene.currenttime),value));}
    else
        {envMin.setKeyValue(iKey,clip(-9999999999.0,envMax.value(Scene.currenttime),value));}
}

button_d2e // Min
{
    envMin.edit();
}

refresh_d3v:value // Max
{
    setvalue(ctrl_d3,clip(envMin.value(Scene.currenttime),9999999999.0,envMax.value(Scene.currenttime) + value *.001));
    setvalue(ctrl_d3v,0);
}

refresh_d3:value // Max
{
    if(bRequesterUpdate) return; // Requester Update
    setvalue(ctrl_d3,clip(envMin.value(Scene.currenttime),9999999999.0,value));
    iKey = envMax.keyExists(Scene.currenttime);
    if(iKey == nil)
        {envMax.createKey(Scene.currenttime,clip(envMin.value(Scene.currenttime),9999999999.0,value));}
    else
        {envMax.setKeyValue(iKey,clip(envMin.value(Scene.currenttime),9999999999.0,value));}
}

button_d3e // Max
{
    envMax.edit();
}

refresh_d4:value // Mass
{
    if(bRequesterUpdate) return; // Requester Update
    setvalue(ctrl_d4,max(0.0,value));
    iKey = envMass.keyExists(Scene.currenttime);
    if(iKey == nil)
        {envMass.createKey(Scene.currenttime,max(0.0,value));}
    else
        {envMass.setKeyValue(iKey,max(0.0,value));}
}

button_d4e // Mass
{
    envMass.edit();
}

refresh_d5:value // Random
{
    if(bRequesterUpdate) return; // Requester Update
    setvalue(ctrl_d5,clip(0.0,1.0,value));
    iKey = envRandom.keyExists(Scene.currenttime);
    if(iKey == nil)
        {envRandom.createKey(Scene.currenttime,max(0.0,value));}
    else
        {envRandom.setKeyValue(iKey,clip(0.0,1.0,value));}
}

button_d5e // Random
{
    envRandom.edit();
}

refresh_d6:value // Damping
{
    if(bRequesterUpdate) return; // Requester Update
    setvalue(ctrl_d6,clip(0.0,1.0,value));
    iKey = envDamping.keyExists(Scene.currenttime);
    if(iKey == nil)
        {envDamping.createKey(Scene.currenttime,max(0.0,value));}
    else
        {envDamping.setKeyValue(iKey,clip(0.0,1.0,value));}
}

button_d6e // Damping
{
    envDamping.edit();
}

refresh_d7:value // Parent Motion
{
    if(bRequesterUpdate) return; // Requester Update
    setvalue(ctrl_d7,clip(0.0,1.0,value));
    iKey = envParentMotion.keyExists(Scene.currenttime);
    if(iKey == nil)
        {envParentMotion.createKey(Scene.currenttime,clip(0.0,1.0,value));}
    else
        {envParentMotion.setKeyValue(iKey,clip(0.0,1.0,value));}
}

button_d7e // Parent Motion
{
    envParentMotion.edit();
}

refresh_d8:value // Threshold (m/s)
{
    if(bRequesterUpdate) return; // Requester Update
    setvalue(ctrl_d8,max(0.0,value));
    iKey = envThreshold.keyExists(Scene.currenttime);
    if(iKey == nil)
        {envThreshold.createKey(Scene.currenttime,max(0.0,value));}
    else
        {envThreshold.setKeyValue(iKey,max(0.0,value));}
}

button_d8e // Threshold (m/s)
{
    envThreshold.edit();
}

refresh_d9:value // Gravity X
{
    vnGravity.x = value;
}

refresh_d10:value // Gravity Y
{
    vnGravity.y = value;
}

refresh_d11:value // Gravity Z
{
    vnGravity.z = value;
}

refresh_mb: value // Motion Baker State
{
    if(bRequesterUpdate) return; // Requester Update
    iMotionBakerState = value;
}

button_mbe // Motion Baker Envelope
{
    envMotionBaker.edit();
}

refresh_mbl: value // Motion Baker Locked
{
    if(bRequesterUpdate) return; // Requester Update
    bMotionBakerLocked = value;
}

/*   
---------------------------------------------------------------------------------------------------
                                                                                             GIZMO
---------------------------------------------------------------------------------------------------
*/

gizmodraw: coa
{
    if(!reqisopen()) return;

    nTimeOffset = -0.0001;

    vPosition = Item.getPosition(Scene.currenttime + nTimeOffset); // Position
    vWorldPosition = Item.getWorldPosition(Scene.currenttime + nTimeOffset); // World Position
    vScaling = Item.getScaling(Scene.currenttime + nTimeOffset); // Scaling
    vnRight = normalize3D(Item.getRight(Scene.currenttime + nTimeOffset));
    vnUp = normalize3D(Item.getUp(Scene.currenttime + nTimeOffset));
    vnForward = normalize3D(Item.getForward(Scene.currenttime + nTimeOffset));
    nMin = envMin.value(Scene.currenttime + nTimeOffset);
    nMax = envMax.value(Scene.currenttime + nTimeOffset);

    if(iChannel == 1) // X
        {
        nMin *= vScaling.x;
        nMax *= vScaling.x;
        nStabilizer *= vScaling.x;    
        vMin = vWorldPosition + (vnRight * (nMin - vPosition.x));
        vMax = vWorldPosition + (vnRight * (nMax - vPosition.x));
        coa.setColor(0.78,0.0,0.0,1.0);
        coa.setPattern("dash");
        coa.drawLine(vMin,vMax,"world");     
        }

    if(iChannel == 2) // Y
        {
        nMin *= vScaling.y;
        nMax *= vScaling.y;
        vMin = vWorldPosition + (vnUp * (nMin - vPosition.y));
        vMax = vWorldPosition + (vnUp * (nMax - vPosition.y));
        coa.setColor(0.0,0.78,0.0,1.0);
        coa.setPattern("dash");
        coa.drawLine(vMin,vMax,"world");     
        }

    if(iChannel == 3) // Z
        {
        nMin *= vScaling.z;
        nMax *= vScaling.z;
        vMin = vWorldPosition + (vnForward * (nMin - vPosition.z));
        vMax = vWorldPosition + (vnForward * (nMax - vPosition.z));
        coa.setColor(0.0,0.0,0.78,1.0);
        coa.setPattern("dash");
        coa.drawLine(vMin,vMax,"world");     
        }
}

gizmodown: te
{
}

gizmomove: te
{
}

gizmoup: te
{
}

gizmodirty
{
}
All scripts available at my Google Drive at
https://drive.google.com/open?id=1cR_q2GVUAJHumic1-A3eXV16acQnVTWs

No comments:

Post a Comment