LScript (Layout) to make an object rotate around its axle dynamically on collision with a plane. Objects to be used must be designed to rotate around there pivot on its B Axis. This then allows key control over any other axis.
.
// LScript Item Animation - www.StephenCulley.co.uk
//
// web address: http://www.stephenculley.co.uk
// email address: email@stephenculley.co.uk
/*
LScript Item Animation - Wheel & Axle v1.0
Motion_Wheel&Axle.ls
*/
@version 2.2
@warnings
@script motion
@name *Wheel & Axle
// Title
sTitle = "*Wheel & Axle";
// Version
sVersion = "v1.0";
// Items
Item = nil; // Item
GroundItem = nil; // Item
GroundItemName = "nil"; // Item
// Constant
Scene; // Scene()
// Variable
bAcceleratorInvert = false; // Accelerator Invert
iIteration = 0; // Iteration
nLength = 1.0; // Length
// Samples [1..5]
aSample; // Array of Wheel Edge Samples World Position
// [1] [1] = b Enable/Disable
// [1] [2] = n Offset from center
// [1] [3] = n Radius
// [1] [4] = v World Position
// [1] [5] = v Ground World Position
// [1] [6] = n Distance to Ground
// Envelope
envAccelerator; // Accelerator
envBrake; // Brake
envDamping; // Damping
envFriction; // Friction
envMotionBaker; // Motion Baker
envRoughness; // Roughness
// Cache
aCache;
// [1] = i Frame
// [2] = n time
// [3] = v World Position
// [4] = n Rotation
// [5] = n Momentum
// Motion Baker
bMotionBakerLocked = false; // Locked
bMotionBakerParent = false; // Parent
iMotionBakerState = 2; // State
// 1 = Disabled
// 2 = Reset
// 3 = Write
// 4 = Read
// Requester
bRequesterUpdate; // Update
iRequesterFrame; // Frame
// Gizmo
aCirclePoints; // Array of Points of Circle
ctrl_d0,ctrl_d0i,ctrl_d1,ctrl_d2,ctrl_d3,ctrl_d4; // Dynamics
ctrl_pl,ctrl_pls,ctrl_p0,ctrl_p1,ctrl_p1e,ctrl_p1o,ctrl_p1r,ctrl_p2,ctrl_p2e,ctrl_p2o,ctrl_p2r,
ctrl_p3,ctrl_p3e,ctrl_p3o,ctrl_p3r,ctrl_p4,ctrl_p4e,ctrl_p4o,ctrl_p4r,ctrl_p5,ctrl_p5e,ctrl_p5o,ctrl_p5r,
ctrl_p6,ctrl_p6e,ctrl_p6o,ctrl_p6r,ctrl_p7,ctrl_p7e,ctrl_p7o,ctrl_p7r,ctrl_p8,ctrl_p8e,ctrl_p8o,ctrl_p8r,
ctrl_p9,ctrl_p9e,ctrl_p9o,ctrl_p9r; // Profile
ctrl_mb,ctrl_mbe,ctrl_mbl; // Motion Baker
/*
---------------------------------------------------------------------------------------------------
CREATE
---------------------------------------------------------------------------------------------------
*/
create : id
{
// Description
setdesc(sTitle);
// Items
Item = id; // Item
// Constant
Scene = Scene();
// Envelope
envAccelerator = Envelope("Accelerator (Wheel&Axle)",CHAN_NUMBER,id.name);
envAccelerator.persist(false);
envAccelerator.createKey(0,0.0);
envBrake = Envelope("Brake (Wheel&Axle)",CHAN_NUMBER,id.name);
envBrake.persist(false);
envBrake.createKey(0,0.0);
envDamping = Envelope("Damping (Wheel&Axle)",CHAN_NUMBER,id.name);
envDamping.persist(false);
envDamping.createKey(0,0.05);
envFriction = Envelope("Friction (Wheel&Axle)",CHAN_NUMBER,id.name);
envFriction.persist(false);
envFriction.createKey(0,1.0);
envMotionBaker = Envelope("Motion Baker (Wheel&Axle)",CHAN_NUMBER,id.name); // Motion Baker
envMotionBaker.persist(false);
envRoughness = Envelope("Roughness (Wheel&Axle)",CHAN_NUMBER,id.name);
envRoughness.persist(false);
envRoughness.createKey(0,0.0);
// Cache
aCache[1] = -1; // Frame
aCache[2] = 0.0; // Time
aCache[3] = <0.0,0.0,0.0>; // World Position
aCache[4] = 0.0; // Rotation
aCache[5] = 0.0; // Momentum
// Requester
bRequesterUpdate = false; // Update
iRequesterFrame = -1; // Frame
// Comring
comringattach("*MotionBaker","comring_motionbaker"); // Comring *MotionBaker
// Variable
nRadius = 1.0; // Radius
if(id.genus == 1 && id.null == false) // Automatic
{
// Bounding Box
aBoundingBox = Item.position(getlayernumber(Item));
// Length
nLength = aBoundingBox[2].z - aBoundingBox[1].z;
// Radius
nRadius = 0.0;
if(abs(aBoundingBox[1].x) > nRadius){nRadius = abs(aBoundingBox[1].x);}
if(abs(aBoundingBox[1].y) > nRadius){nRadius = abs(aBoundingBox[1].y);}
if(abs(aBoundingBox[2].x) > nRadius){nRadius = abs(aBoundingBox[2].x);}
if(abs(aBoundingBox[2].y) > nRadius){nRadius = abs(aBoundingBox[2].y);}
}
// Sample - 1
aSample[1][1] = true; // b Enable/Disable
aSample[1][2] = -0.5; // n Offset
aSample[1][3] = nRadius; // n Radius
aSample[1][4] = <0.0,0.0,0.0>; // v World Position
aSample[1][5] = <0.0,0.0,0.0>; // v Ground World Position
aSample[1][6] = 0.0; // n Distance to Ground
// Sample - 2
aSample[2][1] = false; // b Enable/Disable
aSample[2][2] = -0.375; // n Offset
aSample[2][3] = nRadius; // n Radius
aSample[2][4] = <0.0,0.0,0.0>; // v World Position
aSample[2][5] = <0.0,0.0,0.0>; // v Ground World Position
aSample[2][6] = 0.0; // n Distance to Ground
// Sample - 3
aSample[3][1] = false; // b Enable/Disable
aSample[3][2] = -0.25; // n Offset
aSample[3][3] = nRadius; // n Radius
aSample[3][4] = <0.0,0.0,0.0>; // v World Position
aSample[3][5] = <0.0,0.0,0.0>; // v Ground World Position
aSample[3][6] = 0.0; // n Distance to Ground
// Sample - 4
aSample[4][1] = false; // b Enable/Disable
aSample[4][2] = -0.125; // n Offset
aSample[4][3] = nRadius; // n Radius
aSample[4][4] = <0.0,0.0,0.0>; // v World Position
aSample[4][5] = <0.0,0.0,0.0>; // v Ground World Position
aSample[4][6] = 0.0; // n Distance to Ground
// Sample - 5
aSample[5][1] = true; // b Enable/Disable
aSample[5][2] = 0.0; // n Offset
aSample[5][3] = nRadius; // n Radius
aSample[5][4] = <0.0,0.0,0.0>; // v World Position
aSample[5][5] = <0.0,0.0,0.0>; // v Ground World Position
aSample[5][6] = 0.0; // n Distance to Ground
// Sample - 6
aSample[6][1] = false; // b Enable/Disable
aSample[6][2] = 0.125; // n Offset
aSample[6][3] = nRadius; // n Radius
aSample[6][4] = <0.0,0.0,0.0>; // v World Position
aSample[6][5] = <0.0,0.0,0.0>; // v Ground World Position
aSample[6][6] = 0.0; // n Distance to Ground
// Sample - 7
aSample[7][1] = false; // b Enable/Disable
aSample[7][2] = 0.25; // n Offset
aSample[7][3] = nRadius; // n Radius
aSample[7][4] = <0.0,0.0,0.0>; // v World Position
aSample[7][5] = <0.0,0.0,0.0>; // v Ground World Position
aSample[7][6] = 0.0; // n Distance to Ground
// Sample - 8
aSample[8][1] = false; // b Enable/Disable
aSample[8][2] = 0.375; // n Offset
aSample[8][3] = nRadius; // n Radius
aSample[8][4] = <0.0,0.0,0.0>; // v World Position
aSample[8][5] = <0.0,0.0,0.0>; // v Ground World Position
aSample[8][6] = 0.0; // n Distance to Ground
// Sample - 9
aSample[9][1] = true; // b Enable/Disable
aSample[9][2] = 0.5; // n Offset
aSample[9][3] = nRadius; // n Radius
aSample[9][4] = <0.0,0.0,0.0>; // v World Position
aSample[9][5] = <0.0,0.0,0.0>; // v Ground World Position
aSample[9][6] = 0.0; // n Distance to Ground
// Gizmo
nDegree = 0;
for(d = 0; d <= 32; d++)
{
vPoint = ;
aCirclePoints[d + 1] = vPoint; // Store vertex
nDegree += 360 / 32; // Add Division
}
aCirclePoints[33] = aCirclePoints[1]; // Add copy of first point
}
/*
---------------------------------------------------------------------------------------------------
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
{
envChannel = Envelope("Rotation.B",CHAN_NUMBER,Item.name); // B
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) * (3.1415926535 / 180));}
else
{envChannel.setKeyValue(iKey,envMotionBaker.value(time) * (3.1415926535 / 180));}
}
}
info(Item.name + " baked"); // Info
Refresh(); // Refresh
}
/*
---------------------------------------------------------------------------------------------------
PROCESS
---------------------------------------------------------------------------------------------------
*/
process: ma, frame, time
{
/*
-------------------------------------------------------------------------------
Item
-------------------------------------------------------------------------------
*/
// Ground Item
if(GroundItemName != "nil") {GroundItem = Mesh(GroundItemName); GroundItemName = "nil";}
// ---------------------------------------------------------------------- end -
/*
-------------------------------------------------------------------------------
Requester
-------------------------------------------------------------------------------
*/
if(reqisopen() && iRequesterFrame != frame)
{
bRequesterUpdate = true; // Update
setvalue(ctrl_d0,envAccelerator.value(Scene.currenttime)); // Accelerator
setvalue(ctrl_d1,envBrake.value(Scene.currenttime)); // Brake
setvalue(ctrl_d2,envDamping.value(Scene.currenttime)); // Damping
setvalue(ctrl_d3,envFriction.value(Scene.currenttime)); // Friction
setvalue(ctrl_d4,envRoughness.value(Scene.currenttime)); // Roughness
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)
{
nAxleMomentum = 0.0; // Momentum
aCache[1] = frame; // Frame
aCache[2] = time; // Time
aCache[3] = ma.get(WPOSITION,time); // World Position
aCache[4] = ma.get(ROTATION,time).z; // Rotation
aCache[5] = 0.0; // Momentum
// Motion Baker Write
iKey = envMotionBaker.keyExists((1 / Scene.fps) * frame);
if(iKey == nil)
{envMotionBaker.createKey((1 / Scene.fps) * frame, aCache[4]);}
else
{envMotionBaker.setKeyValue(iKey,aCache[4]);}
// 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
{
vRotation = ma.get(ROTATION,time); // Rotation
vRotation.z = aCache[4]; // B Channel
ma.set(ROTATION,vRotation);
return;
}
if(iMotionBakerState == 4) // Read
{
vRotation = ma.get(ROTATION,time); // Rotation
vRotation.z = envMotionBaker.value(time); // B Channel
ma.set(ROTATION,vRotation);
return;
}
// ---------------------------------------------------------------------- end -
/*
-------------------------------------------------------------------------------
Process
-------------------------------------------------------------------------------
*/
// Variable
nCircumference = 0.0; // Circumference
nDiameter = 0.0; // Diameter
nDistanceToGround = 999999999999999.0; // Distance to ground
nDistanceDegree = 0.0; // Distance per degree
nRadius = 0.0; // Radius
nRotation = 0.0; // Wheel Rotation
vWorldPosition = ma.get(WPOSITION,time); // World Position
vRotation = ma.get(ROTATION,time); // Rotation
vScaling = ma.get(SCALING,time); // Scaling
vNearest = <0.0,0.0,0.0>;
vGroundNearest = <0.0,0.0,0.0>;
vnRight = normalize3D(Item.getRight(time));
vnUp = normalize3D(Item.getUp(time));
vnForward = normalize3D(Item.getForward(time));
// Ground Item
if(GroundItem)
{
vGroundWorldPosition = GroundItem.getWorldPosition(time);
vnGround = normalize3D(GroundItem.getUp(time));
}
else
{
vGroundWorldPosition = <0.0,0.0,0.0>; // World Position
vnGround = <0.0,1.0,0.0>; // Up Vector
}
// Nearest Ground / Axle
vGroundNearest = pointplane3D(vWorldPosition,vGroundWorldPosition,vnGround);
vnToGround = normalize3D(vGroundNearest - vWorldPosition); // Vector Normal to Ground
vNearest = pointplane3D(vGroundNearest,vWorldPosition,vnForward);
vnToward = normalize3D(vWorldPosition - vNearest); // Vector Normal towards center
vnAway = normalize3D(vNearest - vWorldPosition); // Vector Normal away from center
// Samples
// [1] [1] = b Enable/Disable
// [1] [2] = n Offset from center
// [1] [3] = n Radius
// [1] [4] = v World Position
// [1] [5] = v Ground World Position
// [1] [6] = n Distance to Ground
for(s = 1; s <= 9; s++)
{
if(aSample[s][1])
{
aSample[s][4] = vWorldPosition + (vnAway * (aSample[s][3] * ((vScaling.x + vScaling.y) * 0.5))) + (vnForward * (nLength * aSample[s][2] * vScaling.z)); // v World Position
aIntersection = lineplaneintersect3D(aSample[s][4],vnToGround,vGroundWorldPosition,vnGround); // Intersection with ground
aSample[s][5] = aIntersection[3]; // v Ground World Position
aSample[s][6] = aIntersection[2]; // n Distance to Ground
if(aSample[s][6] < nDistanceToGround)
{
nRadius = aSample[s][3]; // n Radius
vNearest = aSample[s][4]; // v World Position
vGroundNearest = aSample[s][5]; // v Ground World Position
nDistanceToGround = aSample[s][6]; // n Distant to ground
nDiameter = 2 * nRadius; // Diameter
nCircumference = 3.1415926535 * nDiameter; // Circumference
if(nCircumference <> 0.0){nDistanceDegree = 360 / nCircumference;} else {nDistanceDegree = 0.0;} // Distance per degree
}
}
}
// Motion
nMotionDistance = distance3D(aCache[3],vWorldPosition); // Distance frame to frame
vnMotionDirection = normalize3D(aCache[3] - vWorldPosition); // Direction Vector
// Rotation
vnDirectionForwardCrossProduct = normalize3D(crossproduct3D(vnMotionDirection,vnForward));
vnForwardAlignCrossProduct = normalize3D(crossproduct3D(vnMotionDirection,vnDirectionForwardCrossProduct));
if(bAcceleratorInvert)
{
nAccelerator = -envAccelerator.value(time); // Accelerator
}
else
{
nAccelerator = envAccelerator.value(time); // Accelerator
}
nBrake = 1.0 - clip(0,1.0,envBrake.value(time)); // Brake
nDamping = 1.0 - clip(0,1.0,envDamping.value(time)); // Damping
nFriction = clip(0,1.0,envFriction.value(time)); // Friction
nSlip = abs(dotproduct3D(vnForwardAlignCrossProduct,vnForward)); // Slip
nVelocity = dotproduct3D(-vnDirectionForwardCrossProduct,vnGround); // Velocity
nRoughness = 1.0 - (randu() * clip(0,1.0,envRoughness.value(time))); // Roughness
// Moment
if(nDistanceToGround <= 0.0)
{
// in contact
nMomentum = maxmin(maxmin((nDistanceDegree * nMotionDistance * nVelocity * nSlip * (nFriction * (nRoughness * nFriction))),(aCache[5] * (nDamping * (1.0 - (nFriction * (nRoughness * nFriction)))))),nAccelerator) * nBrake;
}
else
{
// free wheel
nMomentum = maxmin(aCache[5] * nDamping,nAccelerator) * nBrake;
}
// Rotation
nRotation = aCache[4] + nMomentum; // Compound rotation
vRotation.z = nRotation; // Rotation
// ---------------------------------------------------------------------- end -
/*
-------------------------------------------------------------------------------
MA
-------------------------------------------------------------------------------
*/
ma.set(ROTATION,vRotation);
// ---------------------------------------------------------------------- end -
/*
-------------------------------------------------------------------------------
Motion Baker Write
-------------------------------------------------------------------------------
*/
iKey = envMotionBaker.keyExists((1 / Scene.fps) * frame);
if(iKey == nil)
{envMotionBaker.createKey((1 / Scene.fps) * frame, nRotation);}
else
{envMotionBaker.setKeyValue(iKey,nRotation);}
// ---------------------------------------------------------------------- end -
/*
-------------------------------------------------------------------------------
Cache
-------------------------------------------------------------------------------
*/
aCache[1] = frame; // Frame
aCache[2] = time; // Time
aCache[3] = vWorldPosition; // World Position
aCache[4] = nRotation; // Rotation
aCache[5] = nMomentum; // Momentum
// ---------------------------------------------------------------------- end -
}
// CLIP
clip: min,max,n
{
if(n < min) n = min;
if(n > max) n = max;
return(n);
}
// CONVERSIONS
DEGtoRAD: n // Degree to radian
{
return(n * (3.1415926535 / 180));
}
RADtoDEG: n // Radian to degree
{
return(n * (180 / 3.1415926535));
}
// MAP RANGE
maprange01: n1,n2,i
{
if(n2-n1 == 0.0){return(0.0);}
else
{return((1/(n2-n1)) * (i-n1));}
}
// MAX MIN
maxmin: n1,n2
{
if(n1 < 0.0 && n2 < 0.0){return(min(n1,n2));} // Min
else
if(n1 >= 0.0 && n2 >= 0.0){return(max(n1,n2));} // Max
else
{return(n1 + n2);}
}
// 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);
}
// ITEM
getlayernumber: item
{
if(item.totallayers == 1){return(1);}
sTokens = parse(":",item.name);
iLayer = 0;
if (strleft(sTokens[2],5)=="Layer")
{
iLayer = integer(sTokens[2]);
}
else
{
iTotal = item.totallayers;
for(i = 1; i <= iTotal; i++)
{
if(item.layerVisible(i) == 1)
{
if(item.layerName(i) == sTokens[2])
{
iLayer = i;
break;
}
}
else
{
iTotal++;
}
}
}
return iLayer;
}
/*
---------------------------------------------------------------------------------------------------
LOAD
---------------------------------------------------------------------------------------------------
*/
load: what,io
{
if(what == SCENEMODE) // processing an ASCII scene file
{
if(io.read().asStr() == sTitle + " " + sVersion)
{
bAcceleratorInvert = io.read().asInt(); // Accelerator Invert
nLength = io.read().asNum(); // Length
// Samples
for(s = 1; s <= 9; s++)
{
aSample[s][1] := io.read().asInt(); // b Enable/Disable
aSample[s][2] := io.read().asNum(); // n Offset
aSample[s][3] := io.read().asNum(); // n Radius
}
// Item
GroundItemName = io.read().asStr();
// Motion Baker
bMotionBakerLocked = io.read().asInt(); // Motion Baker Locked
iMotionBakerState = io.read().asInt(); // Motion Baker State
// Envelope
envAccelerator.load(); // Accelerator
envBrake.load(); // Brake
envDamping.load(); // Damping
envFriction.load(); // Friction
envMotionBaker.load(); // Motion Baker
envRoughness.load(); // Roughness
}
else
{
info(sTitle + " - Error");
}
}
}
/*
---------------------------------------------------------------------------------------------------
SAVE
---------------------------------------------------------------------------------------------------
*/
save: what,io
{
if(what == SCENEMODE)
{
// Header
io.writeln(sTitle + " " + sVersion);
io.writeln(bAcceleratorInvert); // Accelerator Invert
io.writeln(nLength); // Length
// Samples
for(s = 1; s <= 9; s++)
{
io.writeln(aSample[s][1]); // b Enable/Disable
io.writeln(aSample[s][2]); // n Offset
io.writeln(aSample[s][3]); // n Radius
}
// Item
if(GroundItem != nil)
{
io.writeln(string(GroundItem.name));
}
else
{
io.writeln("nil");
}
// Motion Baker
io.writeln(bMotionBakerLocked); // Motion Baker Locked
io.writeln(iMotionBakerState); // Motion Baker State
// Envelope
envAccelerator.save(); // Accelerator
envBrake.save(); // Brake
envDamping.save(); // Damping
envFriction.save(); // Friction
envMotionBaker.save(); // Motion Baker
envRoughness.save(); // Roughness
}
}
/*
---------------------------------------------------------------------------------------------------
OPTIONS
---------------------------------------------------------------------------------------------------
*/
options
{
if(reqisopen())
{
reqend();
return;
}
// Variable
iVar = 0;
reqbegin(sTitle + " " + sVersion + " - " + Item.name);
reqsize(300,390);
ctrl_tab = ctltab("Profile","Dynamics","*Motion Baker","Developer");
// Profile
ctrl_p0 = ctlinfo(298,100,"draw_profile"); // Profile Preview
ctrl_pb0 = ctlbutton("Reset",50,"button_reset"); // Button Reset
ctrl_pb1 = ctlbutton("Automatic",50,"button_automatic"); // Button Automatic
ctrl_pb2 = ctlbutton("Mirror 1..4 > 6..9",50,"button_mirror"); // Button Mirror
ctrl_pb3 = ctlbutton("S",20,"button_profile_save"); // Button Profile Save
ctrl_pb4 = ctlbutton("L",20,"button_profile_load"); // Button Profile Load
ctrl_pls = ctlminislider(" ",iVar,-100,100);
ctrl_pl = ctldistance("Length (Section Width)",nLength); // Length
ctrl_p1o = ctlminislider(" ",iVar,-100,100); // Sample 1
ctrl_p1r = ctlminislider(" ",iVar,-100,100);
ctrl_p1 = ctldistance("1) Radius",aSample[1][3]);
ctrl_p1e = ctlcheckbox("Enable",aSample[1][1]);
ctrl_p2o = ctlminislider(" ",iVar,-100,100); // Sample 2
ctrl_p2r = ctlminislider(" ",iVar,-100,100);
ctrl_p2 = ctldistance("2) Radius",aSample[2][3]);
ctrl_p2e = ctlcheckbox("Enable",aSample[2][1]);
ctrl_p3o = ctlminislider(" ",iVar,-100,100); // Sample 3
ctrl_p3r = ctlminislider(" ",iVar,-100,100);
ctrl_p3 = ctldistance("3) Radius",aSample[3][3]);
ctrl_p3e = ctlcheckbox("Enable",aSample[3][1]);
ctrl_p4o = ctlminislider(" ",iVar,-100,100); // Sample 4
ctrl_p4r = ctlminislider(" ",iVar,-100,100);
ctrl_p4 = ctldistance("4) Radius",aSample[4][3]);
ctrl_p4e = ctlcheckbox("Enable",aSample[4][1]);
ctrl_p5o = ctlminislider(" ",iVar,-100,100); // Sample 5
ctrl_p5r = ctlminislider(" ",iVar,-100,100);
ctrl_p5 = ctldistance("5) Radius",aSample[5][3]);
ctrl_p5e = ctlcheckbox("Enable",aSample[5][1]);
ctrl_p6o = ctlminislider(" ",iVar,-100,100); // Sample 6
ctrl_p6r = ctlminislider(" ",iVar,-100,100);
ctrl_p6 = ctldistance("6) Radius",aSample[6][3]);
ctrl_p6e = ctlcheckbox("Enable",aSample[6][1]);
ctrl_p7o = ctlminislider(" ",iVar,-100,100); // Sample 7
ctrl_p7r = ctlminislider(" ",iVar,-100,100);
ctrl_p7 = ctldistance("7) Radius",aSample[7][3]);
ctrl_p7e = ctlcheckbox("Enable",aSample[7][1]);
ctrl_p8o = ctlminislider(" ",iVar,-100,100); // Sample 8
ctrl_p8r = ctlminislider(" ",iVar,-100,100);
ctrl_p8 = ctldistance("8) Radius",aSample[8][3]);
ctrl_p8e = ctlcheckbox("Enable",aSample[8][1]);
ctrl_p9o = ctlminislider(" ",iVar,-100,100); // Sample 9
ctrl_p9r = ctlminislider(" ",iVar,-100,100);
ctrl_p9 = ctldistance("9) Radius",aSample[9][3]);
ctrl_p9e = ctlcheckbox("Enable",aSample[9][1]);
// Profile
ctlposition(ctrl_p0,1,28,299,100); // Profile Preview
ctlposition(ctrl_pb0,2,130,41,20); // Button Reset
ctlposition(ctrl_pb1,45,130,58,20); // Button Automatic
ctlposition(ctrl_pb2,105,130,90,20); // Button Mirror
ctlposition(ctrl_pb3,250,130,20,20); // Button Profile Save
ctlposition(ctrl_pb4,272,130,20,20); // Button Profile Load
ctlposition(ctrl_pls,260,162,10,20); // Length Slider
ctlposition(ctrl_pl,60,162,212,20,130); // Length
ctlposition(ctrl_p1o,188,184,10,20); // Sample 1
ctlposition(ctrl_p1r,168,184,10,20);
ctlposition(ctrl_p1,8,184,172,20);
ctlposition(ctrl_p1e,224,184,68,20);
ctlposition(ctrl_p2o,188,206,10,20); // Sample 2
ctlposition(ctrl_p2r,168,206,10,20);
ctlposition(ctrl_p2,8,206,172,20);
ctlposition(ctrl_p2e,224,206,68,20);
ctlposition(ctrl_p3o,188,228,10,20); // Sample 3
ctlposition(ctrl_p3r,168,228,10,20);
ctlposition(ctrl_p3,8,228,172,20);
ctlposition(ctrl_p3e,224,228,68,20);
ctlposition(ctrl_p4o,188,250,10,20); // Sample 4
ctlposition(ctrl_p4r,168,250,10,20);
ctlposition(ctrl_p4,8,250,172,20);
ctlposition(ctrl_p4e,224,250,68,20);
ctlposition(ctrl_p5o,188,272,10,20); // Sample 5
ctlposition(ctrl_p5r,168,272,10,20);
ctlposition(ctrl_p5,8,272,172,20);
ctlposition(ctrl_p5e,224,272,68,20);
ctlposition(ctrl_p6o,188,294,10,20); // Sample 6
ctlposition(ctrl_p6r,168,294,10,20);
ctlposition(ctrl_p6,8,294,172,20);
ctlposition(ctrl_p6e,224,294,68,20);
ctlposition(ctrl_p7o,188,316,10,20); // Sample 7
ctlposition(ctrl_p7r,168,316,10,20);
ctlposition(ctrl_p7,8,316,172,20);
ctlposition(ctrl_p7e,224,316,68,20);
ctlposition(ctrl_p8o,188,338,10,20); // Sample 8
ctlposition(ctrl_p8r,168,338,10,20);
ctlposition(ctrl_p8,8,338,172,20);
ctlposition(ctrl_p8e,224,338,68,20);
ctlposition(ctrl_p9o,188,360,10,20); // Sample 9
ctlposition(ctrl_p9r,168,360,10,20);
ctlposition(ctrl_p9,8,360,172,20);
ctlposition(ctrl_p9e,224,360,68,20);
ctlpage(1,ctrl_p0,ctrl_pb0,ctrl_pb1,ctrl_pb2,ctrl_pb3,ctrl_pb4,ctrl_pls,ctrl_pl,ctrl_p1r,ctrl_p1o,ctrl_p1e,ctrl_p1,ctrl_p1e,
ctrl_p2o,ctrl_p2r,ctrl_p2,ctrl_p2e,ctrl_p3o,ctrl_p3r,ctrl_p3,ctrl_p3e,ctrl_p4o,ctrl_p4r,ctrl_p4,ctrl_p4e,
ctrl_p5o,ctrl_p5r,ctrl_p5,ctrl_p5e,ctrl_p6o,ctrl_p6r,ctrl_p6,ctrl_p6e,ctrl_p7o,ctrl_p7r,ctrl_p7,ctrl_p7e,
ctrl_p8o,ctrl_p8r,ctrl_p8,ctrl_p8e,ctrl_p9o,ctrl_p9r,ctrl_p9,ctrl_p9e); // Profile
// Dynamics
ctrl_d0 = ctlangle("Accelerator",envAccelerator.value(Scene.currenttime)); // Accelerator
ctrl_d0i = ctlcheckbox("Invert",bAcceleratorInvert); // Accelerator Invert
ctrl_d0e = ctlbutton("E",20,"button_d0e"); // Button
ctrl_d1 = ctlpercent("Brake",envBrake.value(Scene.currenttime)); // Brake
ctrl_d1e = ctlbutton("E",20,"button_d1e"); // Button
ctrl_d2 = ctlpercent("Damping",envDamping.value(Scene.currenttime)); // Damping
ctrl_d2e = ctlbutton("E",20,"button_d2e"); // Button
ctrl_d3 = ctlpercent("Friction",envFriction.value(Scene.currenttime)); // Friction
ctrl_d3e = ctlbutton("E",20,"button_d3e"); // Button
ctrl_d4 = ctlpercent("Roughness",envRoughness.value(Scene.currenttime)); // Roughness
ctrl_d4e = ctlbutton("E",20,"button_d4e"); // Button
ctrl_d5 = ctlpopup("Preset", 1, @"Rubber - Tarmac",
"Rubber - Gravel",
"Rubber - Snow",
"Rubber - Ice",
"Rollerskate - Tarmac",
"Plastic - Plastic"@);
// Ground
ctrl_g0 = ctlsep();
ctrl_g1 = ctlmeshitems("Ground Item",GroundItem);
ctlposition(ctrl_d0,36,32,152,20,100); // Accelerator
ctlposition(ctrl_d0i,212,32,58,20); // Accelerator Invert
ctlposition(ctrl_d0e,272,32,20,20); // Accelerator Button
ctlposition(ctrl_d1,36,54,212,20,100); // Brake
ctlposition(ctrl_d1e,272,54,20,20); // Brake Button
ctlposition(ctrl_d2,36,76,212,20,100); // Damping
ctlposition(ctrl_d2e,272,76,20,20); // Damping Button
ctlposition(ctrl_d3,36,98,212,20,100); // Friction
ctlposition(ctrl_d3e,272,98,20,20); // Friction Button
ctlposition(ctrl_d4,36,120,212,20,100); // Roughness
ctlposition(ctrl_d4e,272,120,20,20); // Roughness Button
ctlposition(ctrl_d5,36,142,256,20,100); // Preset
ctlposition(ctrl_g0,0,174,300,4); // Seperator
ctlposition(ctrl_g1,36,188,256,20,100); // Ground Item
ctlpage(2,ctrl_d0,ctrl_d0i,ctrl_d0e,ctrl_d1,ctrl_d1e,ctrl_d2,ctrl_d2e,ctrl_d3,ctrl_d3e,ctrl_d4,ctrl_d4e,ctrl_d5,ctrl_g0,ctrl_g1); // 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(3,ctrl_mb,ctrl_mbe,ctrl_mbl);
// Developer
ctrl_dev = ctltext("","developer: Stephen Culley","http://www.stephenculley.co.uk");
ctlposition(ctrl_dev,10,350,280,20,100);
ctlpage(4,ctrl_dev);
// Refresh
ctlrefresh(ctrl_pl,"refresh_pl"); // Length
ctlrefresh(ctrl_pls,"refresh_pls"); // Length Slider
ctlrefresh(ctrl_p1,"refresh_p1"); // Radius
ctlrefresh(ctrl_p1r,"refresh_p1r"); // Radius Slider
ctlrefresh(ctrl_p1o,"refresh_p1o"); // Offset Slider
ctlrefresh(ctrl_p1e,"refresh_p1e"); // Enable
ctlrefresh(ctrl_p2,"refresh_p2"); // Radius
ctlrefresh(ctrl_p2r,"refresh_p2r"); // Radius Slider
ctlrefresh(ctrl_p2o,"refresh_p2o"); // Offset Slider
ctlrefresh(ctrl_p2e,"refresh_p2e"); // Enable
ctlrefresh(ctrl_p3,"refresh_p3"); // Radius
ctlrefresh(ctrl_p3r,"refresh_p3r"); // Radius Slider
ctlrefresh(ctrl_p3o,"refresh_p3o"); // Offset Slider
ctlrefresh(ctrl_p3e,"refresh_p3e"); // Enable
ctlrefresh(ctrl_p4,"refresh_p4"); // Radius
ctlrefresh(ctrl_p4r,"refresh_p4r"); // Radius Slider
ctlrefresh(ctrl_p4o,"refresh_p4o"); // Offset Slider
ctlrefresh(ctrl_p4e,"refresh_p4e"); // Enable
ctlrefresh(ctrl_p5,"refresh_p5"); // Radius
ctlrefresh(ctrl_p5r,"refresh_p5r"); // Radius Slider
ctlrefresh(ctrl_p5o,"refresh_p5o"); // Offset Slider
ctlrefresh(ctrl_p5e,"refresh_p5e"); // Enable
ctlrefresh(ctrl_p6,"refresh_p6"); // Radius
ctlrefresh(ctrl_p6r,"refresh_p6r"); // Radius Slider
ctlrefresh(ctrl_p6o,"refresh_p6o"); // Offset Slider
ctlrefresh(ctrl_p6e,"refresh_p6e"); // Enable
ctlrefresh(ctrl_p7,"refresh_p7"); // Radius
ctlrefresh(ctrl_p7r,"refresh_p7r"); // Radius Slider
ctlrefresh(ctrl_p7o,"refresh_p7o"); // Offset Slider
ctlrefresh(ctrl_p7e,"refresh_p7e"); // Enable
ctlrefresh(ctrl_p8,"refresh_p8"); // Radius
ctlrefresh(ctrl_p8r,"refresh_p8r"); // Radius Slider
ctlrefresh(ctrl_p8o,"refresh_p8o"); // Offset Slider
ctlrefresh(ctrl_p8e,"refresh_p8e"); // Enable
ctlrefresh(ctrl_p9,"refresh_p9"); // Radius
ctlrefresh(ctrl_p9r,"refresh_p9r"); // Radius Slider
ctlrefresh(ctrl_p9o,"refresh_p9o"); // Offset Slider
ctlrefresh(ctrl_p9e,"refresh_p9e"); // Enable
ctlrefresh(ctrl_d0,"refresh_d0"); // Accelerator
ctlrefresh(ctrl_d0i,"refresh_d0i"); // Accelerator Invert
ctlrefresh(ctrl_d1,"refresh_d1"); // Brake
ctlrefresh(ctrl_d2,"refresh_d2"); // Damping
ctlrefresh(ctrl_d3,"refresh_d3"); // Friction
ctlrefresh(ctrl_d4,"refresh_d4"); // Roughness
ctlrefresh(ctrl_d5,"refresh_d5"); // Preset
ctlrefresh(ctrl_g1,"refresh_g1"); // Ground Item
ctlrefresh(ctrl_mb,"refresh_mb"); // Motion Baker State
ctlrefresh(ctrl_mbl,"refresh_mbl"); // Motion Baker Locked
reqopen();
}
button_reset
{
bAcceleratorInvert = false; // Accelerator Invert
// Sample - 1
aSample[1][1] = true; // b Enable/Disable
aSample[1][2] = -0.5; // n Offset
aSample[1][3] = 1.0; // n Radius
// Sample - 2
aSample[2][1] = false; // b Enable/Disable
aSample[2][2] = -0.375; // n Offset
aSample[2][3] = 1.0; // n Radius
// Sample - 3
aSample[3][1] = false; // b Enable/Disable
aSample[3][2] = -0.25; // n Offset
aSample[3][3] = 1.0; // n Radius
// Sample - 4
aSample[4][1] = false; // b Enable/Disable
aSample[4][2] = -0.125; // n Offset
aSample[4][3] = 1.0; // n Radius
// Sample - 5
aSample[5][1] = true; // b Enable/Disable
aSample[5][2] = 0.0; // n Offset
aSample[5][3] = 1.0; // n Radius
// Sample - 6
aSample[6][1] = false; // b Enable/Disable
aSample[6][2] = 0.125; // n Offset
aSample[6][3] = 1.0; // n Radius
// Sample - 7
aSample[7][1] = false; // b Enable/Disable
aSample[7][2] = 0.25; // n Offset
aSample[7][3] = 1.0; // n Radius
// Sample - 8
aSample[8][1] = false; // b Enable/Disable
aSample[8][2] = 0.375; // n Offset
aSample[8][3] = 1.0; // n Radius
// Sample - 9
aSample[9][1] = true; // b Enable/Disable
aSample[9][2] = 0.5; // n Offset
aSample[9][3] = 1.0; // n Radius
setvalue(ctrl_pl,1.0); // Length
setvalue(ctrl_p1,aSample[1][3]); // Sample 1
setvalue(ctrl_p1e,aSample[1][1]);
setvalue(ctrl_p2,aSample[2][3]); // Sample 2
setvalue(ctrl_p2e,aSample[2][1]);
setvalue(ctrl_p3,aSample[3][3]); // Sample 3
setvalue(ctrl_p3e,aSample[3][1]);
setvalue(ctrl_p4,aSample[4][3]); // Sample 4
setvalue(ctrl_p4e,aSample[4][1]);
setvalue(ctrl_p5,aSample[5][3]); // Sample 5
setvalue(ctrl_p5e,aSample[5][1]);
setvalue(ctrl_p6,aSample[6][3]); // Sample 6
setvalue(ctrl_p6e,aSample[6][1]);
setvalue(ctrl_p7,aSample[7][3]); // Sample 7
setvalue(ctrl_p7e,aSample[7][1]);
setvalue(ctrl_p8,aSample[8][3]); // Sample 8
setvalue(ctrl_p8e,aSample[8][1]);
setvalue(ctrl_p9,aSample[9][3]); // Sample 9
setvalue(ctrl_p9e,aSample[9][1]);
// Motion Baker
iMotionBakerState = 3; // Write
// Envelope
while(envAccelerator.keyCount >= 1)
{
envAccelerator.deleteKey(envAccelerator.keys[1]);
}
envAccelerator.createKey(0,0.0);
setvalue(ctrl_d0,0.0); // Accelerator
setvalue(ctrl_d0i,0); // Accelerator Invert
while(envBrake.keyCount >= 1)
{
envBrake.deleteKey(envBrake.keys[1]);
}
envBrake.createKey(0,0.0);
setvalue(ctrl_d1,0.0); // Brake
while(envDamping.keyCount >= 1)
{
envDamping.deleteKey(envDamping.keys[1]);
}
envDamping.createKey(0,0.01);
setvalue(ctrl_d2,0.05); // Damping
while(envFriction.keyCount >= 1)
{
envFriction.deleteKey(envFriction.keys[1]);
}
envFriction.createKey(0,1.0);
setvalue(ctrl_d3,1.0); // Friction
while(envRoughness.keyCount >= 1)
{
envRoughness.deleteKey(envRoughness.keys[1]);
}
envRoughness.createKey(0,0.0);
setvalue(ctrl_d4,0.0); // Roughness
}
button_automatic
{
if(Item.genus != 1) // Check for Mesh
{
error("*Wheel & Axle - Must be attached to an object to use automatic.");
return;
}
if(Item.null == true) // Check for Null
{
error("*Wheel & Axle - Must be attached to an object to use automatic.");
return; // Check for Mesh
}
// Bounding Box
aBoundingBox = Item.position(getlayernumber(Item));
// Length
nLength = aBoundingBox[2].z - aBoundingBox[1].z;
// Radius
nRadius = 0.0;
if(abs(aBoundingBox[1].x) > nRadius){nRadius = abs(aBoundingBox[1].x);}
if(abs(aBoundingBox[1].y) > nRadius){nRadius = abs(aBoundingBox[1].y);}
if(abs(aBoundingBox[2].x) > nRadius){nRadius = abs(aBoundingBox[2].x);}
if(abs(aBoundingBox[2].y) > nRadius){nRadius = abs(aBoundingBox[2].y);}
// Sample - 1
aSample[1][1] = true; // b Enable/Disable
aSample[1][2] = -0.5; // n Offset
aSample[1][3] = nRadius; // n Radius
// Sample - 2
aSample[2][1] = false; // b Enable/Disable
aSample[2][2] = -0.375; // n Offset
aSample[2][3] = nRadius; // n Radius
// Sample - 3
aSample[3][1] = false; // b Enable/Disable
aSample[3][2] = -0.25; // n Offset
aSample[3][3] = nRadius; // n Radius
// Sample - 4
aSample[4][1] = false; // b Enable/Disable
aSample[4][2] = -0.125; // n Offset
aSample[4][3] = nRadius; // n Radius
// Sample - 5
aSample[5][1] = true; // b Enable/Disable
aSample[5][2] = 0.0; // n Offset
aSample[5][3] = nRadius; // n Radius
// Sample - 6
aSample[6][1] = false; // b Enable/Disable
aSample[6][2] = 0.125; // n Offset
aSample[6][3] = nRadius; // n Radius
// Sample - 7
aSample[7][1] = false; // b Enable/Disable
aSample[7][2] = 0.25; // n Offset
aSample[7][3] = nRadius; // n Radius
// Sample - 8
aSample[8][1] = false; // b Enable/Disable
aSample[8][2] = 0.375; // n Offset
aSample[8][3] = nRadius; // n Radius
// Sample - 9
aSample[9][1] = true; // b Enable/Disable
aSample[9][2] = 0.5; // n Offset
aSample[9][3] = nRadius; // n Radius
setvalue(ctrl_pl,nLength); // Length
setvalue(ctrl_p1,nRadius); // Sample 1
setvalue(ctrl_p1e,1);
setvalue(ctrl_p2,nRadius); // Sample 2
setvalue(ctrl_p2e,0);
setvalue(ctrl_p3,nRadius); // Sample 3
setvalue(ctrl_p3e,0);
setvalue(ctrl_p4,nRadius); // Sample 4
setvalue(ctrl_p4e,0);
setvalue(ctrl_p5,nRadius); // Sample 5
setvalue(ctrl_p5e,1);
setvalue(ctrl_p6,nRadius); // Sample 6
setvalue(ctrl_p6e,0);
setvalue(ctrl_p7,nRadius); // Sample 7
setvalue(ctrl_p7e,0);
setvalue(ctrl_p8,nRadius); // Sample 8
setvalue(ctrl_p8e,0);
setvalue(ctrl_p9,nRadius); // Sample 9
setvalue(ctrl_p9e,1);
}
button_mirror
{
// Sample - 1 to 9
aSample[9][1] = aSample[1][1]; // b Enable/Disable
aSample[9][2] = -aSample[1][2]; // n Offset
aSample[9][3] = aSample[1][3]; // n Radius
// Sample - 2 to 8
aSample[8][1] = aSample[2][1]; // b Enable/Disable
aSample[8][2] = -aSample[2][2]; // n Offset
aSample[8][3] = aSample[2][3]; // n Radius
// Sample - 3 to 7
aSample[7][1] = aSample[3][1]; // b Enable/Disable
aSample[7][2] = -aSample[3][2]; // n Offset
aSample[7][3] = aSample[3][3]; // n Radius
// Sample - 4 to 6
aSample[6][1] = aSample[4][1]; // b Enable/Disable
aSample[6][2] = -aSample[4][2]; // n Offset
aSample[6][3] = aSample[4][3]; // n Radius
// Sample - 5
aSample[5][2] = 0.0; // n Offset
setvalue(ctrl_p6,aSample[6][3]); // Sample 6
setvalue(ctrl_p6e,aSample[6][1]);
setvalue(ctrl_p7,aSample[7][3]); // Sample 7
setvalue(ctrl_p7e,aSample[7][1]);
setvalue(ctrl_p8,aSample[8][3]); // Sample 8
setvalue(ctrl_p8e,aSample[8][1]);
setvalue(ctrl_p9,aSample[9][3]); // Sample 9
setvalue(ctrl_p9e,aSample[9][1]);
}
button_profile_save
{
filename = getfile("Save Profile","*.prf",,0);
if(filename != nil)
{
if(filename == "") return;
if((file = File(filename,"w")) == nil) return;
file.writeln("*Wheel & Axle" + sVersion + " - Profile");
file.writeln(nLength); // Length
// Samples
for(s = 1; s <= 9; s++)
{
file.writeln(aSample[s][1]); // b Enable/Disable
file.writeln(aSample[s][2]); // n Offset
file.writeln(aSample[s][3]); // n Radius
}
file.close();
}
}
button_profile_load
{
filename = getfile("Load Profile","*.prf",,1);
if(filename != nil)
{
if(filename == "") return;
if((file = File(filename,"r")) == nil) return;
if(file.linecount())
{
line = file.read();
if(line == "*Wheel & Axle" + sVersion + " - Profile")
{
nLength = file.read().asNum(); // Length
// Samples
for(s = 1; s <= 9; s++)
{
aSample[s][1] = file.read().asInt(); // b Enable/Disable
aSample[s][2] = file.read().asNum(); // n Offset
aSample[s][3] = file.read().asNum(); // n Radius
}
setvalue(ctrl_pl,nLength); // Length
setvalue(ctrl_p1,aSample[1][3]); // Sample 1
setvalue(ctrl_p1e,aSample[1][1]);
setvalue(ctrl_p2,aSample[2][3]); // Sample 2
setvalue(ctrl_p2e,aSample[2][1]);
setvalue(ctrl_p3,aSample[3][3]); // Sample 3
setvalue(ctrl_p3e,aSample[3][1]);
setvalue(ctrl_p4,aSample[4][3]); // Sample 4
setvalue(ctrl_p4e,aSample[4][1]);
setvalue(ctrl_p5,aSample[5][3]); // Sample 5
setvalue(ctrl_p5e,aSample[5][1]);
setvalue(ctrl_p6,aSample[6][3]); // Sample 6
setvalue(ctrl_p6e,aSample[6][1]);
setvalue(ctrl_p7,aSample[7][3]); // Sample 7
setvalue(ctrl_p7e,aSample[7][1]);
setvalue(ctrl_p8,aSample[8][3]); // Sample 8
setvalue(ctrl_p8e,aSample[8][1]);
setvalue(ctrl_p9,aSample[9][3]); // Sample 9
setvalue(ctrl_p9e,aSample[9][1]);
}
}
file.close();
}
}
refresh_pls:value // Length Slider
{
setvalue(ctrl_pl,clip(0.0,9999999999,nLength + value *.001));
setvalue(ctrl_pls,0);
}
refresh_pl:value // Length
{
nLength = clip(0.0,9999999999,value);
setvalue(ctrl_pl,nLength);
}
refresh_p1:value // Sample 1
{
aSample[1][3] = clip(0.0,9999999999,value);
setvalue(ctrl_p1,aSample[1][3]);
requpdate(ctrl_p0); // Update
}
refresh_p1r:value // Sample 1
{
setvalue(ctrl_p1,clip(0.0,9999999999,aSample[1][3] + value *.001));
setvalue(ctrl_p1r,0);
}
refresh_p1o:value // Sample 1
{
aSample[1][2] = clip(-999.0,aSample[2][2] - 0.001,aSample[1][2] + value *.001);
setvalue(ctrl_p1o,0);
requpdate(ctrl_p0); // Update
}
refresh_p1e:value // Sample 1
{
aSample[1][1] = value;
requpdate(ctrl_p0); // Update
}
refresh_p2:value // Sample 2
{
aSample[2][3] = clip(0.0,9999999999,value);
setvalue(ctrl_p2,aSample[2][3]);
requpdate(ctrl_p0); // Update
}
refresh_p2r:value // Sample 2
{
setvalue(ctrl_p2,clip(0.0,9999999999,aSample[2][3] + value *.001));
setvalue(ctrl_p2r,0);
}
refresh_p2o:value // Sample 2
{
aSample[2][2] = clip(aSample[1][2] + 0.001,aSample[3][2] - 0.001,aSample[2][2] + value *.001);
setvalue(ctrl_p2o,0);
requpdate(ctrl_p0); // Update
}
refresh_p2e:value // Sample 2
{
aSample[2][1] = value;
requpdate(ctrl_p0); // Update
}
refresh_p3:value // Sample 3
{
aSample[3][3] = clip(0.0,9999999999,value);
setvalue(ctrl_p3,aSample[3][3]);
requpdate(ctrl_p0); // Update
}
refresh_p3r:value // Sample 3
{
setvalue(ctrl_p3,clip(0.0,9999999999,aSample[3][3] + value *.001));
setvalue(ctrl_p3r,0);
}
refresh_p3o:value // Sample 3
{
aSample[3][2] = clip(aSample[2][2] + 0.001,aSample[4][2] - 0.001,aSample[3][2] + value *.001);
setvalue(ctrl_p3o,0);
requpdate(ctrl_p0); // Update
}
refresh_p3e:value // Sample 3
{
aSample[3][1] = value;
requpdate(ctrl_p0); // Update
}
refresh_p4:value // Sample 4
{
aSample[4][3] = clip(0.0,9999999999,value);
setvalue(ctrl_p4,aSample[4][3]);
requpdate(ctrl_p0); // Update
}
refresh_p4r:value // Sample 4
{
setvalue(ctrl_p4,clip(0.0,9999999999,aSample[4][3] + value *.001));
setvalue(ctrl_p4r,0);
}
refresh_p4o:value // Sample 4
{
aSample[4][2] = clip(aSample[3][2] + 0.001,aSample[5][2] - 0.001,aSample[4][2] + value *.001);
setvalue(ctrl_p4o,0);
requpdate(ctrl_p0); // Update
}
refresh_p4e:value // Sample 4
{
aSample[4][1] = value;
requpdate(ctrl_p0); // Update
}
refresh_p5:value // Sample 5
{
aSample[5][3] = clip(0.0,9999999999,value);
setvalue(ctrl_p5,aSample[5][3]);
requpdate(ctrl_p0); // Update
}
refresh_p5r:value // Sample 5
{
setvalue(ctrl_p5,clip(0.0,9999999999,aSample[5][3] + value *.001));
setvalue(ctrl_p5r,0);
}
refresh_p5o:value // Sample 5
{
aSample[5][2] = clip(aSample[4][2] + 0.001,aSample[6][2] - 0.001,aSample[5][2] + value *.001);
setvalue(ctrl_p5o,0);
requpdate(ctrl_p0); // Update
}
refresh_p5e:value // Sample 5
{
aSample[5][1] = value;
requpdate(ctrl_p0); // Update
}
refresh_p6:value // Sample 6
{
aSample[6][3] = clip(0.0,9999999999,value);
setvalue(ctrl_p6,aSample[6][3]);
requpdate(ctrl_p0); // Update
}
refresh_p6r:value // Sample 6
{
setvalue(ctrl_p6,clip(0.0,9999999999,aSample[6][3] + value *.001));
setvalue(ctrl_p6r,0);
}
refresh_p6o:value // Sample 6
{
aSample[6][2] = clip(aSample[5][2] + 0.001,aSample[7][2] - 0.001,aSample[6][2] + value *.001);
setvalue(ctrl_p6o,0);
requpdate(ctrl_p0); // Update
}
refresh_p6e:value // Sample 6
{
aSample[6][1] = value;
requpdate(ctrl_p0); // Update
}
refresh_p7:value // Sample 7
{
aSample[7][3] = clip(0.0,9999999999,value);
setvalue(ctrl_p7,aSample[7][3]);
requpdate(ctrl_p0); // Update
}
refresh_p7r:value // Sample 7
{
setvalue(ctrl_p7,clip(0.0,9999999999,aSample[7][3] + value *.001));
setvalue(ctrl_p7r,0);
}
refresh_p7o:value // Sample 7
{
aSample[7][2] = clip(aSample[6][2] + 0.001,aSample[8][2] - 0.001,aSample[7][2] + value *.001);
setvalue(ctrl_p7o,0);
requpdate(ctrl_p0); // Update
}
refresh_p7e:value // Sample 7
{
aSample[7][1] = value;
requpdate(ctrl_p0); // Update
}
refresh_p8:value // Sample 8
{
aSample[8][3] = clip(0.0,9999999999,value);
setvalue(ctrl_p8,aSample[8][3]);
requpdate(ctrl_p0); // Update
}
refresh_p8r:value // Sample 8
{
setvalue(ctrl_p8,clip(0.0,9999999999,aSample[8][3] + value *.001));
setvalue(ctrl_p8r,0);
}
refresh_p8o:value // Sample 8
{
aSample[8][2] = clip(aSample[7][2] + 0.001,aSample[9][2] - 0.001,aSample[8][2] + value *.001);
setvalue(ctrl_p8o,0);
requpdate(ctrl_p0); // Update
}
refresh_p8e:value // Sample 8
{
aSample[8][1] = value;
requpdate(ctrl_p0); // Update
}
refresh_p9:value // Sample 9
{
aSample[9][3] = clip(0.0,9999999999,value);
setvalue(ctrl_p9,aSample[9][3]);
requpdate(ctrl_p0); // Update
}
refresh_p9r:value // Sample 9
{
setvalue(ctrl_p9,clip(0.0,9999999999,aSample[9][3] + value *.001));
setvalue(ctrl_p9r,0);
}
refresh_p9o:value // Sample 9
{
aSample[9][2] = clip(aSample[8][2] + 0.001,999.0,aSample[9][2] + value *.001);
setvalue(ctrl_p9o,0);
requpdate(ctrl_p0); // Update
}
refresh_p9e:value // Sample 9
{
aSample[9][1] = value;
requpdate(ctrl_p0); // Update
}
refresh_d0:value // Accelerator
{
if(bRequesterUpdate) return; // Requester Update
iKey = envAccelerator.keyExists(Scene.currenttime);
if(iKey == nil)
{envAccelerator.createKey(Scene.currenttime,value);}
else
{envAccelerator.setKeyValue(iKey,value);}
}
refresh_d0i:value // Accelerator Invert
{
bAcceleratorInvert = value; // Accelerator Invert
}
button_d0e // Accelerator
{
envAccelerator.edit();
}
refresh_d1:value // Brake
{
if(bRequesterUpdate) return; // Requester Update
setvalue(ctrl_d1,clip(0.0,1.0,value));
iKey = envBrake.keyExists(Scene.currenttime);
if(iKey == nil)
{envBrake.createKey(Scene.currenttime,clip(0.0,1.0,value));}
else
{envBrake.setKeyValue(iKey,clip(0.0,1.0,value));}
}
button_d1e // Brake
{
envBrake.edit();
}
refresh_d2:value // Damping
{
if(bRequesterUpdate) return; // Requester Update
setvalue(ctrl_d2,clip(0.0,1.0,value));
iKey = envDamping.keyExists(Scene.currenttime);
if(iKey == nil)
{envDamping.createKey(Scene.currenttime,clip(0.0,1.0,value));}
else
{envDamping.setKeyValue(iKey,clip(0.0,1.0,value));}
}
button_d2e // Damping
{
envDamping.edit();
}
refresh_d3:value // Friction
{
if(bRequesterUpdate) return; // Requester Update
setvalue(ctrl_d3,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_d3e // Friction
{
envFriction.edit();
}
refresh_d4:value // Roughness
{
if(bRequesterUpdate) return; // Requester Update
setvalue(ctrl_d4,clip(0.0,1.0,value));
iKey = envRoughness.keyExists(Scene.currenttime);
if(iKey == nil)
{envRoughness.createKey(Scene.currenttime,clip(0.0,1.0,value));}
else
{envRoughness.setKeyValue(iKey,clip(0.0,1.0,value));}
}
button_d4e // Roughness
{
envRoughness.edit();
}
refresh_d5:value
{
if(value == 1) // Rubber - Tarmac
{
setvalue(ctrl_d2,0.025); // Damping
setvalue(ctrl_d3,0.975); // Friction
setvalue(ctrl_d4,0.2); // Roughness
}
if(value == 2) // Rubber - Gravel
{
setvalue(ctrl_d2,0.025); // Damping
setvalue(ctrl_d3,0.9); // Friction
setvalue(ctrl_d4,0.5); // Roughness
}
if(value == 3) // Rubber - Snow
{
setvalue(ctrl_d2,0.025); // Damping
setvalue(ctrl_d3,0.75); // Friction
setvalue(ctrl_d4,0.1); // Roughness
}
if(value == 4) // Rubber - Ice
{
setvalue(ctrl_d2,0.025); // Damping
setvalue(ctrl_d3,0.5); // Friction
setvalue(ctrl_d4,0.1); // Roughness
}
if(value == 5) // Rollerskate - Tarmac
{
setvalue(ctrl_d2,0.005); // Damping
setvalue(ctrl_d3,0.975); // Friction
setvalue(ctrl_d4,0.2); // Roughness
}
if(value == 6) // Plastic - Plastic
{
setvalue(ctrl_d2,0.05); // Damping
setvalue(ctrl_d3,0.9); // Friction
setvalue(ctrl_d4,0.0); // Roughness
}
}
refresh_g1:value
{
GroundItem = 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;
}
draw_profile
{
// Background
drawbox(<127,127,127>,0,0,298,100);
// Border
drawline(<0,0,0>,0,0,297,0);
drawline(<0,0,0>,297,0,297,99);
drawline(<0,0,0>,297,99,0,99);
drawline(<0,0,0>,0,99,0,0);
// Variables
aXY = nil; // array of points enabled.
nMinX = 0.0; // Min X
nMaxX = 0.0; // Max X
nMaxY = 0.0001; // Max Y
// Min / Max
for(s = 1; s <= 9; s++)
{
if(aSample[s][2] < nMinX) nMinX = aSample[s][2]; // Min X
if(aSample[s][2] > nMaxX) nMaxX = aSample[s][2]; // Max X
if(aSample[s][3] > nMaxY && aSample[s][1]) nMaxY = aSample[s][3]; // Max Y
}
nYMultiplier = 1 / nMaxY;
// Draw 0
iX = (277 * maprange01(nMinX,nMaxX,0.0)) + 10; // X
drawline(<117,117,117>,iX,30,iX,68);
drawtext("- 0 0 +",<117,117,117>,iX - 15,43);
// Draw Samples (Disabled)
for(s = 1; s <= 9; s++)
{
if(aSample[s][1] == false)
{
iX = (277 * maprange01(nMinX,nMaxX,aSample[s][2])) + 10; // X
iY = clip(10,88,(90 * (nYMultiplier * aSample[s][3])) + 10); // Y
if(iY >= 20) drawline(<107,107,107>,iX,20,iX,iY);
drawtext(string(s),<107,107,107>,iX - 3,3);
}
}
// Draw Samples (Enabled)
iC = 1; // Count
for(s = 1; s <= 9; s++)
{
if(aSample[s][1])
{
iX = (277 * maprange01(nMinX,nMaxX,aSample[s][2])) + 10; // X
iY = clip(10,88,(90 * (nYMultiplier * aSample[s][3])) + 10); // Y
if(iY >= 20) drawline(<255,255,255>,iX,20,iX,iY);
drawtext(string(s),<255,255,255>,iX - 3,3);
// below used to draw profile preview
aXY[iC] = ;
iC++;
}
}
// Draw preview of enabled points
if(iC > 2)
{
for(s = 2; s <= sizeof(aXY); s++)
{
drawline(<200,200,200>,aXY[s - 1].x,aXY[s - 1].y,aXY[s].x,aXY[s].y);
}
}
}
// GIZMO
gizmodraw: coa
{
if(!reqisopen()) return;
nTimeOffset = -0.0001;
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));
// Scaling
if(vScaling.x != vScaling.y)
{
vScaling = <(vScaling.x + vScaling.y) * 0.5,(vScaling.x + vScaling.y) * 0.5,vScaling.z>;
}
// Draw Center
coa.setColor(0.0,0.0,0.78,1.0);
coa.setPattern("dash");
coa.drawLine(vWorldPosition + (vnForward * (nLength * 0.5) * vScaling.z),vWorldPosition + (-vnForward * (nLength * 0.5) * vScaling.z),"world");
// Draw Profile
coa.setPattern("solid");
for(s = 1; s <= 9; s++)
{
vCenter = vWorldPosition + (vnForward * aSample[s][2] * nLength * vScaling.z);
if(aSample[s][1])
{
coa.setColor(1.0,1.0,1.0,1.0);
coa.drawText(vCenter,s.asStr(),"world","center"); // Sample
for(p = 1; p < 33; p++)
{
vA = (vnRight * aCirclePoints[p].x * aSample[s][3] * vScaling.x) +
(vnUp * aCirclePoints[p].y * aSample[s][3] * vScaling.y) +
(vnForward * aCirclePoints[p].z * aSample[s][3] * vScaling.z) + vCenter;
vB = (vnRight * aCirclePoints[p + 1].x * aSample[s][3] * vScaling.x) +
(vnUp * aCirclePoints[p + 1].y * aSample[s][3] * vScaling.y) +
(vnForward * aCirclePoints[p + 1].z * aSample[s][3] * vScaling.z) + vCenter;
coa.drawLine(vA,vB,"world");
}
}
else
{
coa.setColor(0.4,0.4,0.4,1.0);
for(p = 1; p < 33; p++)
{
vA = (vnRight * aCirclePoints[p].x * aSample[s][3] * vScaling.x) +
(vnUp * aCirclePoints[p].y * aSample[s][3] * vScaling.y) +
(vnForward * aCirclePoints[p].z * aSample[s][3] * vScaling.z) + vCenter;
vB = (vnRight * aCirclePoints[p + 1].x * aSample[s][3] * vScaling.x) +
(vnUp * aCirclePoints[p + 1].y * aSample[s][3] * vScaling.y) +
(vnForward * aCirclePoints[p + 1].z * aSample[s][3] * vScaling.z) + vCenter;
coa.drawLine(vA,vB,"world");
}
}
}
}
gizmodown: te
{
}
gizmomove: te
{
}
gizmoup: te
{
}
gizmodirty
{
}