LUADOC - Farming Simulator 17

Printable Version

Script v1.4.4.0

Engine v7.0.0.2

Foundation Reference

AnimatedVehicle

Description
Class for all AnimatedVehicles
Functions

prerequisitesPresent

Description
Checks if all prerequisite specializations are loaded
Definition
prerequisitesPresent(table specializations)
Arguments
tablespecializationsspecializations
Return Values
booleanhasPrerequisitetrue if all prerequisite specializations are loaded
Code
20function AnimatedVehicle.prerequisitesPresent(specializations)
21 return true;
22end;

preLoad

Description
Called before loading
Definition
preLoad(table savegame)
Arguments
tablesavegamesavegame
Code
27function AnimatedVehicle:preLoad(savegame)
28 self.loadSpeedRotatingPartFromXML = Utils.overwrittenFunction(self.loadSpeedRotatingPartFromXML, AnimatedVehicle.loadSpeedRotatingPartFromXML);
29 self.loadWorkAreaFromXML = Utils.overwrittenFunction(self.loadWorkAreaFromXML, AnimatedVehicle.loadWorkAreaFromXML);
30end

load

Description
Called on loading
Definition
load(table savegame)
Arguments
tablesavegamesavegame
Code
35function AnimatedVehicle:load(savegame)
36
37 self.playAnimation = SpecializationUtil.callSpecializationsFunction("playAnimation");
38 self.stopAnimation = SpecializationUtil.callSpecializationsFunction("stopAnimation");
39 self.setRealAnimationTime = SpecializationUtil.callSpecializationsFunction("setRealAnimationTime");
40 self.setAnimationTime = SpecializationUtil.callSpecializationsFunction("setAnimationTime");
41 self.setAnimationStopTime = SpecializationUtil.callSpecializationsFunction("setAnimationStopTime");
42 self.setAnimationSpeed = SpecializationUtil.callSpecializationsFunction("setAnimationSpeed");
43 self.getIsAnimationPlaying = AnimatedVehicle.getIsAnimationPlaying;
44 self.getRealAnimationTime = AnimatedVehicle.getRealAnimationTime;
45 self.getAnimationTime = AnimatedVehicle.getAnimationTime;
46 self.getAnimationDuration = AnimatedVehicle.getAnimationDuration;
47
48 self.resetAnimationValues = AnimatedVehicle.resetAnimationValues;
49 self.resetAnimationPartValues = AnimatedVehicle.resetAnimationPartValues;
50 self.getIsSpeedRotatingPartActive = Utils.overwrittenFunction(self.getIsSpeedRotatingPartActive, AnimatedVehicle.getIsSpeedRotatingPartActive);
51 self.getIsWorkAreaActive = Utils.overwrittenFunction(self.getIsWorkAreaActive, AnimatedVehicle.getIsWorkAreaActive);
52
53 self.animations = {};
54
55 local i=0;
56 while true do
57 local key = string.format("vehicle.animations.animation(%d)", i);
58 if not hasXMLProperty(self.xmlFile, key) then
59 break;
60 end;
61
62 local name = getXMLString(self.xmlFile, key.."#name");
63 if name ~= nil then
64 local animation = {};
65 animation.name = name;
66 animation.parts = {};
67 animation.currentTime = 0;
68 animation.currentSpeed = 1;
69 animation.looping = Utils.getNoNil(getXMLBool(self.xmlFile, key .. "#looping"), false);
70
71 local partI = 0;
72 while true do
73 local partKey = key..string.format(".part(%d)", partI);
74 if not hasXMLProperty(self.xmlFile, partKey) then
75 break;
76 end;
77
78 local node = Utils.indexToObject(self.components, getXMLString(self.xmlFile, partKey.."#node"));
79 local startTime = getXMLFloat(self.xmlFile, partKey.."#startTime");
80 local duration = getXMLFloat(self.xmlFile, partKey.."#duration");
81 local endTime = getXMLFloat(self.xmlFile, partKey.."#endTime");
82 local direction = Utils.sign(Utils.getNoNil(getXMLInt(self.xmlFile, partKey.."#direction"), 0));
83 local startRot = Utils.getRadiansFromString(getXMLString(self.xmlFile, partKey.."#startRot"), 3);
84 local endRot = Utils.getRadiansFromString(getXMLString(self.xmlFile, partKey.."#endRot"), 3);
85 local startTrans = Utils.getVectorNFromString(getXMLString(self.xmlFile, partKey.."#startTrans"), 3);
86 local endTrans = Utils.getVectorNFromString(getXMLString(self.xmlFile, partKey.."#endTrans"), 3);
87 local startScale = Utils.getVectorNFromString(getXMLString(self.xmlFile, partKey.."#startScale"), 3);
88 local endScale = Utils.getVectorNFromString(getXMLString(self.xmlFile, partKey.."#endScale"), 3);
89 local visibility = getXMLBool(self.xmlFile, partKey.."#visibility");
90 local componentJointIndex = getXMLInt(self.xmlFile, partKey.."#componentJointIndex");
91 local componentJoint;
92 if componentJointIndex ~= nil then
93 componentJoint = self.componentJoints[componentJointIndex+1];
94 end
95 local startRotLimit = Utils.getRadiansFromString(getXMLString(self.xmlFile, partKey.."#startRotLimit"), 3);
96 local startRotMinLimit = Utils.getRadiansFromString(getXMLString(self.xmlFile, partKey.."#startRotMinLimit"), 3);
97 local startRotMaxLimit = Utils.getRadiansFromString(getXMLString(self.xmlFile, partKey.."#startRotMaxLimit"), 3);
98 if startRotLimit ~= nil then
99 startRotMinLimit = {};
100 startRotMaxLimit = {};
101 for i=1,3 do
102 startRotMinLimit[i] = -startRotLimit[i];
103 startRotMaxLimit[i] = startRotLimit[i];
104 end
105 end
106 local endRotLimit = Utils.getRadiansFromString(getXMLString(self.xmlFile, partKey.."#endRotLimit"), 3);
107 local endRotMinLimit = Utils.getRadiansFromString(getXMLString(self.xmlFile, partKey.."#endRotMinLimit"), 3);
108 local endRotMaxLimit = Utils.getRadiansFromString(getXMLString(self.xmlFile, partKey.."#endRotMaxLimit"), 3);
109 if endRotLimit ~= nil then
110 endRotMinLimit = {};
111 endRotMaxLimit = {};
112 for i=1,3 do
113 endRotMinLimit[i] = -endRotLimit[i];
114 endRotMaxLimit[i] = endRotLimit[i];
115 end
116 end
117
118 local startTransLimit = Utils.getVectorNFromString(getXMLString(self.xmlFile, partKey.."#startTransLimit"), 3);
119 local startTransMinLimit = Utils.getVectorNFromString(getXMLString(self.xmlFile, partKey.."#startTransMinLimit"), 3);
120 local startTransMaxLimit = Utils.getVectorNFromString(getXMLString(self.xmlFile, partKey.."#startTransMaxLimit"), 3);
121 if startTransLimit ~= nil then
122 startTransMinLimit = {};
123 startTransMaxLimit = {};
124 for i=1,3 do
125 startTransMinLimit[i] = -startTransLimit[i];
126 startTransMaxLimit[i] = startTransLimit[i];
127 end
128 end
129 local endTransLimit = Utils.getVectorNFromString(getXMLString(self.xmlFile, partKey.."#endTransLimit"), 3);
130 local endTransMinLimit = Utils.getVectorNFromString(getXMLString(self.xmlFile, partKey.."#endTransMinLimit"), 3);
131 local endTransMaxLimit = Utils.getVectorNFromString(getXMLString(self.xmlFile, partKey.."#endTransMaxLimit"), 3);
132 if endTransLimit ~= nil then
133 endTransMinLimit = {};
134 endTransMaxLimit = {};
135 for i=1,3 do
136 endTransMinLimit[i] = -endTransLimit[i];
137 endTransMaxLimit[i] = endTransLimit[i];
138 end
139 end
140
141 local shaderParameter = getXMLString(self.xmlFile, partKey.."#shaderParameter");
142 local shaderStartValues = Utils.getVectorNFromString(getXMLString(self.xmlFile, partKey.."#shaderStartValues"), 4);
143 local shaderEndValues = Utils.getVectorNFromString(getXMLString(self.xmlFile, partKey.."#shaderEndValues"), 4);
144
145 if startTime ~= nil and (duration ~= nil or endTime ~= nil) and
146 ( (node ~= nil and (endRot ~= nil or endTrans ~= nil or endScale ~= nil or visibility ~= nil)) or
147 (componentJoint ~= nil and ((endRotMinLimit ~= nil and endRotMaxLimit ~= nil) or (endTransMinLimit ~= nil and endTransMaxLimit ~= nil))) or
148 (node ~= nil and shaderParameter ~= nil and (shaderStartValues ~= nil and shaderEndValues ~= nil))
149 )
150 then
151 if endTime ~= nil then
152 duration = endTime - startTime;
153 end;
154 local part = {};
155 part.node = node;
156 part.startTime = startTime*1000;
157 part.duration = duration*1000;
158 part.direction = direction;
159 if node ~= nil then
160 if endRot ~= nil then
161 part.startRot = startRot;
162 part.endRot = endRot;
163 end;
164 if endTrans ~= nil then
165 part.startTrans = startTrans;
166 part.endTrans = endTrans;
167 end;
168 if endScale ~= nil then
169 part.startScale = startScale;
170 part.endScale = endScale;
171 end;
172
173 if shaderParameter ~= nil and shaderEndValues ~= nil and shaderStartValues ~= nil then
174 part.shaderParameter = shaderParameter;
175 part.shaderStartValues = shaderStartValues;
176 part.shaderEndValues = shaderEndValues;
177 end
178
179 part.visibility = visibility;
180 end
181 if self.isServer then
182 if componentJoint ~= nil then
183 if endRotMinLimit ~= nil then
184 part.componentJoint = componentJoint;
185 part.startRotMinLimit = startRotMinLimit;
186 part.startRotMaxLimit = startRotMaxLimit;
187 part.endRotMinLimit = endRotMinLimit;
188 part.endRotMaxLimit = endRotMaxLimit;
189 end
190 if endTransMinLimit ~= nil then
191 part.componentJoint = componentJoint;
192 part.startTransMinLimit = startTransMinLimit;
193 part.startTransMaxLimit = startTransMaxLimit;
194 part.endTransMinLimit = endTransMinLimit;
195 part.endTransMaxLimit = endTransMaxLimit;
196 end
197 end
198 end
199 table.insert(animation.parts, part);
200 end;
201 partI = partI + 1;
202 end;
203
204 -- sort parts by start/end time
205 animation.partsReverse = {};
206 for _, part in ipairs(animation.parts) do
207 table.insert(animation.partsReverse, part);
208 end;
209 table.sort(animation.parts, AnimatedVehicle.animPartSorter);
210 table.sort(animation.partsReverse, AnimatedVehicle.animPartSorterReverse);
211
212 AnimatedVehicle.initializeParts(self, animation);
213
214 animation.currentPartIndex = 1;
215 animation.duration = 0;
216 for _, part in ipairs(animation.parts) do
217 animation.duration = math.max(animation.duration, part.startTime + part.duration);
218 end;
219
220 self.animations[name] = animation;
221 end;
222
223 i = i+1;
224 end;
225
226 self.activeAnimations = {};
227end;

initializeParts

Description
Initialize parts of animation
Definition
initializeParts(table animation)
Arguments
tableanimationanimation
Code
232function AnimatedVehicle.initializeParts(self, animation)
233 local numParts = table.getn(animation.parts);
234
235 for i=1, numParts do
236 local part = animation.parts[i];
237
238 -- find the next rot part
239 if part.endRot ~= nil then
240 for j=i+1, numParts do
241 local part2 = animation.parts[j];
242 if part.node == part2.node and part2.endRot ~= nil then
243 if part.startTime + part.duration > part2.startTime+0.001 then
244 print("Warning: overlapping rotation parts for node "..getName(part.node).." in " .. animation.name.. " "..self.configFileName);
245 end
246 part.nextRotPart = part2;
247 part2.prevRotPart = part;
248 if part2.startRot == nil then
249 part2.startRot = {part.endRot[1], part.endRot[2], part.endRot[3]};
250 end
251 break;
252 end
253 end
254 end
255
256 -- find the next trans part
257 if part.endTrans ~= nil then
258 for j=i+1, numParts do
259 local part2 = animation.parts[j];
260 if part.node == part2.node and part2.endTrans ~= nil then
261 if part.startTime + part.duration > part2.startTime+0.001 then
262 print("Warning: overlapping translation parts for node "..getName(part.node).." in " .. animation.name.. " "..self.configFileName);
263 end
264 part.nextTransPart = part2;
265 part2.prevTransPart = part;
266 if part2.startTrans == nil then
267 part2.startTrans = {part.endTrans[1], part.endTrans[2], part.endTrans[3]};
268 end
269 break;
270 end
271 end
272 end
273
274 -- find the next scale part
275 if part.endScale ~= nil then
276 for j=i+1, numParts do
277 local part2 = animation.parts[j];
278 if part.node == part2.node and part2.endScale ~= nil then
279 if part.startTime + part.duration > part2.startTime+0.001 then
280 print("Warning: overlapping scale parts for node "..getName(part.node).." in " .. animation.name.. " "..self.configFileName);
281 end
282 part.nextScalePart = part2;
283 part2.prevScalePart = part;
284 if part2.startScale == nil then
285 part2.startScale = {part.endScale[1], part.endScale[2], part.endScale[3]};
286 end
287 break;
288 end
289 end
290 end
291
292 -- find the next shader part
293 if part.shaderEndValues ~= nil then
294 for j=i+1, numParts do
295 local part2 = animation.parts[j];
296 if part.node == part2.node and part2.shaderEndValues ~= nil then
297 if part.startTime + part.duration > part2.startTime+0.001 then
298 print("Warning: overlapping shaderParameter parts for node "..getName(part.node).." in " .. animation.name.. " "..self.configFileName);
299 end
300 part.nextShaderPart = part2;
301 part2.prevShaderPart = part;
302 if part2.shaderStartValues == nil then
303 part2.shaderStartValues = {part.shaderEndValues[1], part.shaderEndValues[2], part.shaderEndValues[3], part.shaderEndValues[4]};
304 end
305 break;
306 end
307 end
308 end
309
310 if self.isServer then
311 -- find the next joint rot limit part
312 if part.endRotMinLimit ~= nil then
313 for j=i+1, numParts do
314 local part2 = animation.parts[j];
315 if part.componentJoint == part2.componentJoint and (part2.endRotMinLimit ~= nil and part2.endRotMaxLimit ~= nil) then
316 if part.startTime + part.duration > part2.startTime+0.001 then
317 print("Warning: overlapping joint rot limit parts for component joint "..getName(part.componentJoint.jointNode).." in " .. animation.name.. " "..self.configFileName);
318 end
319 part.nextRotLimitPart = part2;
320 part2.prevRotLimitPart = part;
321 if part2.startRotMinLimit == nil then
322 part2.startRotMinLimit = {part.endRotMinLimit[1], part.endRotMinLimit[2], part.endRotMinLimit[3]};
323 end
324 if part2.startRotMaxLimit == nil then
325 part2.startRotMaxLimit = {part.endRotMaxLimit[1], part.endRotMaxLimit[2], part.endRotMaxLimit[3]};
326 end
327 break;
328 end
329 end
330 end
331
332 -- find the next joint trans limit part
333 if part.endTransMinLimit ~= nil then
334 for j=i+1, numParts do
335 local part2 = animation.parts[j];
336 if part.componentJoint == part2.componentJoint and (part2.endTransMinLimit ~= nil and part2.endTransMaxLimit ~= nil) then
337 if part.startTime + part.duration > part2.startTime+0.001 then
338 print("Warning: overlapping joint trans limit parts for component joint "..getName(part.componentJoint.jointNode).." in " .. animation.name.. " "..self.configFileName);
339 end
340 part.nextTransLimitPart = part2;
341 part2.prevTransLimitPart = part;
342 if part2.startTransMinLimit == nil then
343 part2.startTransMinLimit = {part.endTransMinLimit[1], part.endTransMinLimit[2], part.endTransMinLimit[3]};
344 end
345 if part2.startTransMaxLimit == nil then
346 part2.startTransMaxLimit = {part.endTransMaxLimit[1], part.endTransMaxLimit[2], part.endTransMaxLimit[3]};
347 end
348 break;
349 end
350 end
351 end
352 end
353 end
354
355 -- default start values to the value stored in the i3d (if not set by the end value of the previous part)
356 for i=1, numParts do
357 local part = animation.parts[i];
358 if part.endRot ~= nil and part.startRot == nil then
359 local x,y,z = getRotation(part.node);
360 part.startRot = {x,y,z};
361 end
362 if part.endTrans ~= nil and part.startTrans == nil then
363 local x,y,z = getTranslation(part.node);
364 part.startTrans = {x,y,z};
365 end;
366 if part.endScale ~= nil and part.startScale == nil then
367 local x,y,z = getScale(part.node);
368 part.startScale = {x,y,z};
369 end;
370 if self.isServer then
371 if part.endRotMinLimit ~= nil and part.startRotMinLimit == nil then
372 local rotLimit = part.componentJoint.rotMinLimit;
373 part.startRotMinLimit = {rotLimit[1], rotLimit[2], rotLimit[3]};
374 end
375 if part.endRotMaxLimit ~= nil and part.startRotMaxLimit == nil then
376 local rotLimit = part.componentJoint.rotLimit;
377 part.startRotMaxLimit = {rotLimit[1], rotLimit[2], rotLimit[3]};
378 end
379 if part.endTransMinLimit ~= nil and part.startTransMinLimit == nil then
380 local transLimit = part.componentJoint.transMinLimit;
381 part.startTransMinLimit = {transLimit[1], transLimit[2], transLimit[3]};
382 end
383 if part.endTransMaxLimit ~= nil and part.startTransMaxLimit == nil then
384 local transLimit = part.componentJoint.transLimit;
385 part.startTransMaxLimit = {transLimit[1], transLimit[2], transLimit[3]};
386 end
387 end
388 end
389end

update

Description
Called on update
Definition
update(float dt)
Arguments
floatdttime since last call in ms
Code
415function AnimatedVehicle:update(dt)
416 AnimatedVehicle.updateAnimations(self, dt)
417end;

playAnimation

Description
Play animation
Definition
playAnimation(string name, float speed, float animTime, boolean noEventSend)
Arguments
stringnamename of animation
floatspeedspeed
floatanimTimestart time
booleannoEventSendno event send
Code
443function AnimatedVehicle:playAnimation(name, speed, animTime, noEventSend)
444 local animation = self.animations[name];
445 if animation ~= nil then
446 if speed == nil then
447 speed = animation.currentSpeed;
448 end;
449 if animTime == nil then
450 if self:getIsAnimationPlaying(name) then
451 animTime = self:getAnimationTime(name);
452 elseif speed > 0 then
453 animTime = 0;
454 else
455 animTime = 1;
456 end;
457 end;
458 if noEventSend == nil or noEventSend == false then
459 if g_server ~= nil then
460 g_server:broadcastEvent(AnimatedVehicleStartEvent:new(self, name, speed, animTime), nil, nil, self);
461 else
462 g_client:getServerConnection():sendEvent(AnimatedVehicleStartEvent:new(self, name, speed, animTime));
463 end;
464 end;
465
466 self.activeAnimations[name] = animation;
467 animation.currentSpeed = speed;
468 animation.currentTime = animTime*animation.duration;
469 self:resetAnimationValues(animation);
470 end;
471end;

stopAnimation

Description
Stop animation
Definition
stopAnimation(string name, boolean noEventSend)
Arguments
stringnamename of animation
booleannoEventSendno event send
Code
477function AnimatedVehicle:stopAnimation(name, noEventSend)
478 if noEventSend == nil or noEventSend == false then
479 if g_server ~= nil then
480 g_server:broadcastEvent(AnimatedVehicleStopEvent:new(self, name), nil, nil, self);
481 else
482 g_client:getServerConnection():sendEvent(AnimatedVehicleStopEvent:new(self, name));
483 end;
484 end
485 local animation = self.animations[name];
486 if animation ~= nil then
487 animation.stopTime = nil;
488 end;
489 self.activeAnimations[name] = nil;
490end;

getIsAnimationPlaying

Description
Returns true if animation is playing
Definition
getIsAnimationPlaying(string name)
Arguments
stringnamename of animation
Return Values
booleanisPlayinganimation is playing
Code
496function AnimatedVehicle:getIsAnimationPlaying(name)
497 return self.activeAnimations[name] ~= nil;
498end;

getRealAnimationTime

Description
Returns real animation time
Definition
getRealAnimationTime(string name)
Arguments
stringnamename of animation
Return Values
floatanimTimereal animation time in ms
Code
504function AnimatedVehicle:getRealAnimationTime(name)
505 local animation = self.animations[name];
506 if animation ~= nil then
507 return animation.currentTime;
508 end;
509 return 0;
510end;

setRealAnimationTime

Description
Set animation real time
Definition
setRealAnimationTime(string name, float animTime, boolean update)
Arguments
stringnamename of animation
floatanimTimereal animation time in ms
booleanupdateupdate animation
Code
517function AnimatedVehicle:setRealAnimationTime(name, animTime, update)
518 local animation = self.animations[name];
519 if animation ~= nil then
520 if update == nil or update then
521 local currentSpeed = animation.currentSpeed;
522 animation.currentSpeed = 1;
523 if animation.currentTime > animTime then
524 animation.currentSpeed = -1;
525 end;
526
527 self:resetAnimationValues(animation);
528
529 local dtToUse, _ = AnimatedVehicle.updateAnimationCurrentTime(self, animation, 99999999, animTime);
530 AnimatedVehicle.updateAnimation(self, animation, dtToUse, false);
531 animation.currentSpeed = currentSpeed;
532 else
533 animation.currentTime = animTime;
534 end
535 end;
536end;

getAnimationTime

Description
Returns animation time
Definition
getAnimationTime(string name)
Arguments
stringnamename of animation
Return Values
floatanimTimeanimation time [0..1]
Code
542function AnimatedVehicle:getAnimationTime(name)
543 local animation = self.animations[name];
544 if animation ~= nil then
545 return animation.currentTime/animation.duration;
546 end;
547 return 0;
548end;

setAnimationTime

Description
Set animation time
Definition
setAnimationTime(string name, float animTime, boolean update)
Arguments
stringnamename of animation
floatanimTimeanimation time [0..1]
booleanupdateupdate animation
Code
555function AnimatedVehicle:setAnimationTime(name, animTime, update)
556 local animation = self.animations[name];
557 if animation ~= nil then
558 self:setRealAnimationTime(name, animTime*animation.duration, update);
559 end;
560end;

getAnimationDuration

Description
Returns duration of animation
Definition
getAnimationDuration(string name)
Arguments
stringnamename of animation
Return Values
floatdurationduration in ms
Code
566function AnimatedVehicle:getAnimationDuration(name)
567 local animation = self.animations[name];
568 if animation ~= nil then
569 return animation.duration;
570 end;
571 return 1;
572end;

setAnimationSpeed

Description
Sets speed of animation
Definition
setAnimationSpeed(string name, float speed)
Arguments
stringnamename of animation
floatspeedspeed
Code
578function AnimatedVehicle:setAnimationSpeed(name, speed)
579 local animation = self.animations[name];
580 if animation ~= nil then
581 local speedReversed = false;
582 if (animation.currentSpeed > 0) ~= (speed > 0) then
583 speedReversed = true;
584 end;
585 animation.currentSpeed = speed;
586 if self:getIsAnimationPlaying(name) and speedReversed then
587 self:resetAnimationValues(animation);
588 end;
589 end;
590end;

setAnimationStopTime

Description
Sets animation stop time
Definition
setAnimationStopTime(string name, float stopTime)
Arguments
stringnamename of animation
floatstopTimestop time [0..1]
Code
596function AnimatedVehicle:setAnimationStopTime(name, stopTime)
597 local animation = self.animations[name];
598 if animation ~= nil then
599 animation.stopTime = stopTime*animation.duration;
600 end;
601end;

resetAnimationValues

Description
Resets animation values
Definition
resetAnimationValues(table animation)
Arguments
tableanimationanimation
Code
606function AnimatedVehicle:resetAnimationValues(animation)
607 AnimatedVehicle.findCurrentPartIndex(animation);
608 for _, part in ipairs(animation.parts) do
609 self:resetAnimationPartValues(part);
610 end;
611end

resetAnimationPartValues

Description
Resets animation part
Definition
resetAnimationPartValues(table part)
Arguments
tablepartpart to reset
Code
616function AnimatedVehicle:resetAnimationPartValues(part)
617 part.curRot = nil;
618 part.speedRot = nil;
619 part.curTrans = nil;
620 part.speedTrans = nil;
621 part.curScale = nil;
622 part.speedScale = nil;
623 part.curVisibility = nil;
624 part.curRotMinLimit = nil;
625 part.curRotMaxLimit = nil;
626 part.speedRotLimit = nil;
627 part.curTransMinLimit = nil;
628 part.curTransMaxLimit = nil;
629 part.speedTransLimit = nil;
630 part.shaderCurValues = nil;
631end;

loadSpeedRotatingPartFromXML

Description
Loads speed rotating parts from xml
Definition
loadSpeedRotatingPartFromXML(table speedRotatingPart, integer fileId, string key)
Arguments
tablespeedRotatingPartspeedRotatingPart
integerfileIdxml file id
stringkeykey
Code
638function AnimatedVehicle:loadSpeedRotatingPartFromXML(superFunc, speedRotatingPart, xmlFile, key)
639 if superFunc ~= nil then
640 if not superFunc(self, speedRotatingPart, xmlFile, key) then
641 return false;
642 end
643 end
644
645 speedRotatingPart.animName = getXMLString(xmlFile, key.."#animName");
646 speedRotatingPart.animOuterRange = Utils.getNoNil(getXMLBool(xmlFile, key.."#animOuterRange"), false);
647 speedRotatingPart.animMinLimit = Utils.getNoNil(getXMLFloat(xmlFile, key.."#animMinLimit"), 0);
648 speedRotatingPart.animMaxLimit = Utils.getNoNil(getXMLFloat(xmlFile, key.."#animMaxLimit"), 1);
649 return true;
650end

getIsSpeedRotatingPartActive

Description
Returns true if speed rotating part is active
Definition
getIsSpeedRotatingPartActive(table speedRotatingPart)
Arguments
tablespeedRotatingPartspeedRotatingPart
Return Values
booleanisActivespeed rotating part is active
Code
656function AnimatedVehicle:getIsSpeedRotatingPartActive(superFunc, speedRotatingPart)
657 if speedRotatingPart.animName ~= nil then
658 local animTime = self:getAnimationTime(speedRotatingPart.animName);
659 if speedRotatingPart.animOuterRange then
660 if animTime > speedRotatingPart.animMinLimit or animTime < speedRotatingPart.animMaxLimit then
661 return false;
662 end
663 else
664 if animTime > speedRotatingPart.animMaxLimit or animTime < speedRotatingPart.animMinLimit then
665 return false;
666 end
667 end;
668 end;
669
670 if superFunc ~= nil then
671 return superFunc(self, speedRotatingPart);
672 end
673 return true;
674end;

loadWorkAreaFromXML

Description
Loads work areas from xml
Definition
loadWorkAreaFromXML(table workArea, integer fileId, string key)
Arguments
tableworkAreaworkArea
integerfileIdxml file id
stringkeykey
Code
681function AnimatedVehicle:loadWorkAreaFromXML(superFunc, workArea, xmlFile, key)
682 workArea.animName = getXMLString(xmlFile, key.."#animName");
683 workArea.animMinLimit = Utils.getNoNil(getXMLFloat(xmlFile, key.."#animMinLimit"), 0);
684 workArea.animMaxLimit = Utils.getNoNil(getXMLFloat(xmlFile, key.."#animMaxLimit"), 1);
685
686 if superFunc ~= nil then
687 return superFunc(self, workArea, xmlFile, key);
688 end;
689 return true;
690end;

getIsWorkAreaActive

Description
Returns true if work area is active
Definition
getIsWorkAreaActive(table workArea)
Arguments
tableworkAreaworkArea
Return Values
booleanisActivework area is active
Code
696function AnimatedVehicle:getIsWorkAreaActive(superFunc, workArea)
697 if workArea.animName ~= nil then
698 local animTime = self:getAnimationTime(workArea.animName);
699 if animTime > workArea.animMaxLimit or animTime < workArea.animMinLimit then
700 return false;
701 end
702 end;
703
704 if superFunc ~= nil then
705 return superFunc(self, workArea);
706 end
707 return true;
708end;

animPartSorter

Description
Returns true if anim parts are in the right order
Definition
animPartSorter(table a, table b)
Arguments
tableapart a to check
tablebpart b to check
Return Values
booleanrightOrderreturns true if parts are in right order
Code
715function AnimatedVehicle.animPartSorter(a, b)
716 if a.startTime < b.startTime then
717 return true;
718 elseif a.startTime == b.startTime then
719 return a.duration < b.duration;
720 end;
721 return false;
722end;

animPartSorterReverse

Description
Returns true if anim parts are in the reverse right order
Definition
animPartSorterReverse(table a, table b)
Arguments
tableapart a to check
tablebpart b to check
Return Values
booleanrightOrderreturns true if parts are in reverse right order
Code
729function AnimatedVehicle.animPartSorterReverse(a, b)
730 local endTimeA = a.startTime+a.duration;
731 local endTimeB = b.startTime+b.duration;
732 if endTimeA > endTimeB then
733 return true;
734 elseif endTimeA == endTimeB then
735 return a.startTime > b.startTime;
736 end;
737 return false;
738end;

getMovedLimitedValue

Description
Returns moved limited value
Definition
getMovedLimitedValue(float currentValue, float destValue, float speed, float dt)
Arguments
floatcurrentValuecurrent value
floatdestValuedest value
floatspeedspeed
floatdttime since last call in ms
Return Values
floatretlimited value
Code
747function AnimatedVehicle.getMovedLimitedValue(currentValue, destValue, speed, dt)
748 local limitF = math.min;
749 -- we are moving towards -inf, we need to check for the maximum
750 if destValue < currentValue then
751 limitF = math.max;
752 elseif destValue == currentValue then
753 return currentValue;
754 end;
755 local ret = limitF(currentValue + speed * dt, destValue);
756 return ret;
757end;

setMovedLimitedValues3

Description
Sets moved limited values (3)
Definition
setMovedLimitedValues3(table currentValues, table destValues, table speeds, float dt)
Arguments
tablecurrentValuescurrent values
tabledestValuesdest values
tablespeedsspeeds
floatdttime since last call in ms
Code
765function AnimatedVehicle.setMovedLimitedValues3(currentValues, destValues, speeds, dt)
766 local hasChanged = false;
767 for i=1,3 do
768 local newValue = AnimatedVehicle.getMovedLimitedValue(currentValues[i], destValues[i], speeds[i], dt);
769 if currentValues[i] ~= newValue then
770 hasChanged = true;
771 currentValues[i] = newValue;
772 end;
773 end;
774 return hasChanged;
775end;

setMovedLimitedValues4

Description
Sets moved limited values (4)
Definition
setMovedLimitedValues4(table currentValues, table destValues, table speeds, float dt)
Arguments
tablecurrentValuescurrent values
tabledestValuesdest values
tablespeedsspeeds
floatdttime since last call in ms
Code
783function AnimatedVehicle.setMovedLimitedValues4(currentValues, destValues, speeds, dt)
784 local hasChanged = false;
785 for i=1,4 do
786 local newValue = AnimatedVehicle.getMovedLimitedValue(currentValues[i], destValues[i], speeds[i], dt);
787 if currentValues[i] ~= newValue then
788 hasChanged = true;
789 currentValues[i] = newValue;
790 end;
791 end;
792 return hasChanged;
793end;

findCurrentPartIndex

Description
Find current playing part
Definition
findCurrentPartIndex(table animation)
Arguments
tableanimationanimation
Return Values
integerindexof current playing part
Code
799function AnimatedVehicle.findCurrentPartIndex(animation)
800 if animation.currentSpeed > 0 then
801 -- find the first part that is being played at the current time
802 animation.currentPartIndex = table.getn(animation.parts)+1;
803 for i, part in ipairs(animation.parts) do
804 if part.startTime+part.duration >= animation.currentTime then
805 animation.currentPartIndex = i;
806 break;
807 end;
808 end;
809 else
810 -- find the last part that is being played at the current time (the first in partsReverse)
811 animation.currentPartIndex = table.getn(animation.partsReverse)+1;
812 for i, part in ipairs(animation.partsReverse) do
813 if part.startTime <= animation.currentTime then
814 animation.currentPartIndex = i;
815 break;
816 end;
817 end;
818 end;
819end;

getDurationToEndOfPart

Description
Returns duration to the end of current part
Definition
getDurationToEndOfPart(table part, table anim)
Arguments
tablepartpart
tableanimanimation
Return Values
floatdurationduration to end of current part
Code
826function AnimatedVehicle.getDurationToEndOfPart(part, anim)
827 if anim.currentSpeed > 0 then
828 return part.startTime+part.duration - anim.currentTime;
829 else
830 return anim.currentTime - part.startTime;
831 end
832end

getNextPartIsPlaying

Description
Get next part is playing
Definition
getNextPartIsPlaying(table nextPart, table prevPart, table anim, boolean default)
Arguments
tablenextPartnext part
tableprevPartprevious part
tableanimanimation
booleandefaultdefault value
Return Values
booleanisPlayingnext part is playing
Code
841function AnimatedVehicle.getNextPartIsPlaying(nextPart, prevPart, anim, default)
842 if anim.currentSpeed > 0 then
843 if nextPart ~= nil then
844 return nextPart.startTime > anim.currentTime;
845 end
846 else
847 if prevPart ~= nil then
848 return prevPart.startTime + prevPart.duration < anim.currentTime;
849 end
850 end
851 return default;
852end

updateAnimations

Description
Update animations
Definition
updateAnimations(float dt)
Arguments
floatdttime since last call in ms
Code
857function AnimatedVehicle.updateAnimations(self, dt)
858 for _, anim in pairs(self.activeAnimations) do
859 local dtToUse, stopAnim = AnimatedVehicle.updateAnimationCurrentTime(self, anim, dt, anim.stopTime);
860 AnimatedVehicle.updateAnimation(self, anim, dtToUse, stopAnim);
861 end
862end

updateAnimationByName

Description
Update animation by name
Definition
updateAnimationByName(string animName, float dt)
Arguments
stringanimNamename of animation to update
floatdttime since last call in ms
Code
868function AnimatedVehicle.updateAnimationByName(self, animName, dt)
869 local anim = self.animations[animName];
870 if anim ~= nil then
871 local dtToUse, stopAnim = AnimatedVehicle.updateAnimationCurrentTime(self, anim, dt, anim.stopTime);
872 AnimatedVehicle.updateAnimation(self, anim, dtToUse, stopAnim);
873 end
874end

updateAnimationCurrentTime

Description
Update current animation time
Definition
updateAnimationCurrentTime(table anim, float dt, float stopTime)
Arguments
tableanimanimation
floatdttime since last call in ms
floatstopTimestop time
Return Values
floatdtToUsedt to use
booleanstopAnimationstop animation
Code
883function AnimatedVehicle.updateAnimationCurrentTime(self, anim, dt, stopTime)
884 anim.currentTime = anim.currentTime + dt*anim.currentSpeed;
885
886 local absSpeed = math.abs(anim.currentSpeed);
887 local dtToUse = dt*absSpeed;
888 local stopAnim = false;
889 if stopTime ~= nil then
890 if anim.currentSpeed > 0 then
891 if stopTime <= anim.currentTime then
892 dtToUse = dtToUse-(anim.currentTime-stopTime);
893 anim.currentTime = stopTime;
894 stopAnim = true;
895 end;
896 else
897 if stopTime >= anim.currentTime then
898 dtToUse = dtToUse-(stopTime-anim.currentTime);
899 anim.currentTime = stopTime;
900 stopAnim = true;
901 end;
902 end;
903 end;
904 return dtToUse, stopAnim;
905end

updateAnimation

Description
Update animation
Definition
updateAnimation(table anim, float dtToUse, boolean stopAnimation)
Arguments
tableanimanimation
floatdtToUsedt to use
booleanstopAnimationstop animation
Code
912function AnimatedVehicle.updateAnimation(self, anim, dtToUse, stopAnim)
913 local name = anim.name;
914
915 local numParts = table.getn(anim.parts)
916 local parts = anim.parts;
917 if anim.currentSpeed < 0 then
918 parts = anim.partsReverse;
919 end;
920
921 if dtToUse > 0 then
922 local hasChanged = false;
923 local nothingToChangeYet = false;
924 for partI=anim.currentPartIndex, numParts do
925 local part = parts[partI];
926
927 if part.direction == 0 or ((part.direction > 0) == (anim.currentSpeed >= 0)) then
928 local durationToEnd = AnimatedVehicle.getDurationToEndOfPart(part, anim);
929
930 -- is this part not playing yet?
931 if durationToEnd > part.duration then
932 nothingToChangeYet = true;
933 break;
934 end
935
936 durationToEnd = durationToEnd+dtToUse;
937
938 local hasPartChanged = false;
939 -- update the part
940 if part.startRot ~= nil and (durationToEnd > 0 or AnimatedVehicle.getNextPartIsPlaying(part.nextRotPart, part.prevRotPart, anim, true)) then
941 local destRot = part.endRot;
942 if anim.currentSpeed < 0 then
943 destRot = part.startRot;
944 end;
945 if part.curRot == nil then
946 local x,y,z = getRotation(part.node);
947 part.curRot = {x,y,z};
948 local invDuration = 1.0/math.max(durationToEnd, 0.001);
949 part.speedRot = {(destRot[1]-x)*invDuration, (destRot[2]-y)*invDuration, (destRot[3]-z)*invDuration};
950 end;
951 if AnimatedVehicle.setMovedLimitedValues3(part.curRot, destRot, part.speedRot, dtToUse) then
952 setRotation(part.node, part.curRot[1], part.curRot[2], part.curRot[3]);
953 hasPartChanged = true;
954 end;
955 end;
956 if part.startTrans ~= nil and (durationToEnd > 0 or AnimatedVehicle.getNextPartIsPlaying(part.nextTransPart, part.prevTransPart, anim, true)) then
957 local destTrans = part.endTrans;
958 if anim.currentSpeed < 0 then
959 destTrans = part.startTrans;
960 end;
961 if part.curTrans == nil then
962 local x,y,z = getTranslation(part.node);
963 part.curTrans = {x,y,z};
964 local invDuration = 1.0/math.max(durationToEnd, 0.001);
965 part.speedTrans = {(destTrans[1]-x)*invDuration, (destTrans[2]-y)*invDuration, (destTrans[3]-z)*invDuration};
966 end;
967 if AnimatedVehicle.setMovedLimitedValues3(part.curTrans, destTrans, part.speedTrans, dtToUse) then
968 setTranslation(part.node, part.curTrans[1], part.curTrans[2], part.curTrans[3]);
969 hasPartChanged = true;
970 end;
971 end;
972 if part.startScale ~= nil and (durationToEnd > 0 or AnimatedVehicle.getNextPartIsPlaying(part.nextScalePart, part.prevScalePart, anim, true)) then
973 local destScale = part.endScale;
974 if anim.currentSpeed < 0 then
975 destScale = part.startScale;
976 end;
977 if part.curScale == nil then
978 local x,y,z = getScale(part.node);
979 part.curScale = {x,y,z};
980 local invDuration = 1.0/math.max(durationToEnd, 0.001);
981 part.speedScale = {(destScale[1]-x)*invDuration, (destScale[2]-y)*invDuration, (destScale[3]-z)*invDuration};
982 end;
983 if AnimatedVehicle.setMovedLimitedValues3(part.curScale, destScale, part.speedScale, dtToUse) then
984 setScale(part.node, part.curScale[1], part.curScale[2], part.curScale[3]);
985 hasPartChanged = true;
986 end;
987 end;
988 if part.shaderParameter ~= nil and (durationToEnd > 0 or AnimatedVehicle.getNextPartIsPlaying(part.nextShaderPart, part.prevShaderPart, anim, true)) then
989 local destValues = part.shaderEndValues;
990 if anim.currentSpeed < 0 then
991 destValues = part.shaderStartValues;
992 end
993 if part.shaderCurValues == nil then
994 local x,y,z,w = getShaderParameter(part.node, part.shaderParameter);
995 part.shaderCurValues = {x,y,z,w};
996 local invDuration = 1.0 / math.max(durationToEnd, 0.001);
997 part.speedShader = {(destValues[1]-x)*invDuration, (destValues[2]-y)*invDuration, (destValues[3]-z)*invDuration, (destValues[4]-w)*invDuration};
998 end
999 if AnimatedVehicle.setMovedLimitedValues4(part.shaderCurValues, destValues, part.speedShader, dtToUse) then
1000 setShaderParameter(part.node, part.shaderParameter, part.shaderCurValues[1], part.shaderCurValues[2], part.shaderCurValues[3], part.shaderCurValues[4], false);
1001 hasPartChanged = true;
1002 end
1003 end
1004 if part.visibility ~= nil then
1005 if part.curVisibility == nil then
1006 part.curVisibility = getVisibility(part.node);
1007 end;
1008 if part.visibility ~= part.curVisibility then
1009 part.curVisibility = part.visibility;
1010 setVisibility(part.node, part.visibility);
1011 hasPartChanged = true;
1012 end;
1013 end;
1014
1015 if self.isServer then
1016 if part.startRotMinLimit ~= nil and (durationToEnd > 0 or AnimatedVehicle.getNextPartIsPlaying(part.nextRotLimitPart, part.prevRotLimitPart, anim, true)) then
1017 local destRotMinLimit = part.endRotMinLimit;
1018 local destRotMaxLimit = part.endRotMaxLimit;
1019 if anim.currentSpeed < 0 then
1020 destRotMinLimit = part.startRotMinLimit;
1021 destRotMaxLimit = part.startRotMaxLimit;
1022 end;
1023 if part.curRotMinLimit == nil then
1024 local x,y,z = unpack(part.componentJoint.rotMinLimit);
1025 part.curRotMinLimit = {x,y,z};
1026 local invDuration = 1.0/math.max(durationToEnd, 0.001);
1027 part.speedRotMinLimit = {(destRotMinLimit[1]-x)*invDuration, (destRotMinLimit[2]-y)*invDuration, (destRotMinLimit[3]-z)*invDuration};
1028 end;
1029 if part.curRotMaxLimit == nil then
1030 local x,y,z = unpack(part.componentJoint.rotLimit);
1031 part.curRotMaxLimit = {x,y,z};
1032 local invDuration = 1.0/math.max(durationToEnd, 0.001);
1033 part.speedRotMaxLimit = {(destRotMaxLimit[1]-x)*invDuration, (destRotMaxLimit[2]-y)*invDuration, (destRotMaxLimit[3]-z)*invDuration};
1034 end;
1035 for i=1, 3 do
1036 local newRotMinLimit = AnimatedVehicle.getMovedLimitedValue(part.curRotMinLimit[i], destRotMinLimit[i], part.speedRotMinLimit[i], dtToUse);
1037 local newRotMaxLimit = AnimatedVehicle.getMovedLimitedValue(part.curRotMaxLimit[i], destRotMaxLimit[i], part.speedRotMaxLimit[i], dtToUse);
1038 if newRotMinLimit ~= part.curRotMinLimit[i] or newRotMaxLimit ~= part.curRotMaxLimit[i] then
1039 part.curRotMinLimit[i] = newRotMinLimit;
1040 part.curRotMaxLimit[i] = newRotMaxLimit;
1041 self:setComponentJointRotLimit(part.componentJoint, i, newRotMinLimit, newRotMaxLimit);
1042 hasPartChanged = true;
1043 end
1044 end;
1045 end;
1046 if part.startTransMinLimit ~= nil and (durationToEnd > 0 or AnimatedVehicle.getNextPartIsPlaying(part.nextTransLimitPart, part.prevTransLimitPart, anim, true)) then
1047 local destTransMinLimit = part.endTransMinLimit;
1048 local destTransMaxLimit = part.endTransMaxLimit;
1049 if anim.currentSpeed < 0 then
1050 destTransMinLimit = part.startTransMinLimit;
1051 destTransMaxLimit = part.startTransMaxLimit;
1052 end;
1053 if part.curTransMinLimit == nil then
1054 local x,y,z = unpack(part.componentJoint.transMinLimit);
1055 part.curTransMinLimit = {x,y,z};
1056 local invDuration = 1.0/math.max(durationToEnd, 0.001);
1057 part.speedTransMinLimit = {(destTransMinLimit[1]-x)*invDuration, (destTransMinLimit[2]-y)*invDuration, (destTransMinLimit[3]-z)*invDuration};
1058 end;
1059 if part.curTransMaxLimit == nil then
1060 local x,y,z = unpack(part.componentJoint.transLimit);
1061 part.curTransMaxLimit = {x,y,z};
1062 local invDuration = 1.0/math.max(durationToEnd, 0.001);
1063 part.speedTransMaxLimit = {(destTransMaxLimit[1]-x)*invDuration, (destTransMaxLimit[2]-y)*invDuration, (destTransMaxLimit[3]-z)*invDuration};
1064 end;
1065 for i=1, 3 do
1066 local newTransMinLimit = AnimatedVehicle.getMovedLimitedValue(part.curTransMinLimit[i], destTransMinLimit[i], part.speedTransMinLimit[i], dtToUse);
1067 local newTransMaxLimit = AnimatedVehicle.getMovedLimitedValue(part.curTransMaxLimit[i], destTransMaxLimit[i], part.speedTransMaxLimit[i], dtToUse);
1068 if newTransMinLimit ~= part.curTransMinLimit[i] or newTransMaxLimit ~= part.curTransMaxLimit[i] then
1069 part.curTransMinLimit[i] = newTransMinLimit;
1070 part.curTransMaxLimit[i] = newTransMaxLimit;
1071 self:setComponentJointTransLimit(part.componentJoint, i, newTransMinLimit, newTransMaxLimit);
1072 hasPartChanged = true;
1073 end
1074 end
1075 end
1076 end
1077
1078 if hasPartChanged then
1079 if self.setMovingToolDirty ~= nil then
1080 self:setMovingToolDirty(part.node);
1081 end
1082 hasChanged = true;
1083 end
1084 end
1085
1086 if partI == anim.currentPartIndex then
1087 -- is this part finished?
1088 if (anim.currentSpeed > 0 and part.startTime + part.duration < anim.currentTime) or
1089 (anim.currentSpeed <= 0 and part.startTime > anim.currentTime)
1090 then
1091 self:resetAnimationPartValues(part);
1092 --print("finished: "..anim.currentPartIndex);
1093 anim.currentPartIndex = anim.currentPartIndex+1;
1094 end
1095 end
1096 end;
1097 if not nothingToChangeYet and not hasChanged and anim.currentPartIndex >= numParts then
1098 -- end the animation
1099 if anim.currentSpeed > 0 then
1100 anim.currentTime = anim.duration;
1101 else
1102 anim.currentTime = 0;
1103 end
1104 stopAnim = true;
1105 end;
1106 end;
1107 if stopAnim or anim.currentPartIndex > numParts or anim.currentPartIndex < 1 then
1108 if not stopAnim then
1109 if anim.currentSpeed > 0 then
1110 anim.currentTime = anim.duration;
1111 else
1112 anim.currentTime = 0;
1113 end
1114 end
1115 anim.currentTime = math.min(math.max(anim.currentTime, 0), anim.duration);
1116 anim.stopTime = nil;
1117 self.activeAnimations[name] = nil;
1118
1119 if anim.looping then
1120 -- restart animation
1121 self:setAnimationTime(anim.name, math.abs((anim.duration-anim.currentTime) - 1), true);
1122 self:playAnimation(anim.name, anim.currentSpeed, nil, true);
1123 end;
1124 end;
1125end;