LUADOC - Farming Simulator 19

Script v1.7.1.0

Engine v1.7.1.0

Foundation Reference

AnimatedVehicle

Description
Specialization adding support for (keyframe)animations to vehicles
Functions

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
809function AnimatedVehicle.animPartSorter(a, b)
810 if a.startTime < b.startTime then
811 return true
812 elseif a.startTime == b.startTime then
813 return a.duration < b.duration
814 end
815 return false
816end

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
823function AnimatedVehicle.animPartSorterReverse(a, b)
824 local endTimeA = a.startTime + a.duration
825 local endTimeB = b.startTime + b.duration
826 if endTimeA > endTimeB then
827 return true
828 elseif endTimeA == endTimeB then
829 return a.startTime > b.startTime
830 end
831 return false
832end

findCurrentPartIndex

Description
Find current playing part
Definition
findCurrentPartIndex(table animation)
Arguments
tableanimationanimation
Return Values
integerindexof current playing part
Code
893function AnimatedVehicle.findCurrentPartIndex(animation)
894 if animation.currentSpeed > 0 then
895 -- find the first part that is being played at the current time
896 animation.currentPartIndex = table.getn(animation.parts)+1
897 for i, part in ipairs(animation.parts) do
898 if part.startTime+part.duration >= animation.currentTime then
899 animation.currentPartIndex = i
900 break
901 end
902 end
903 else
904 -- find the last part that is being played at the current time (the first in partsReverse)
905 animation.currentPartIndex = table.getn(animation.partsReverse)+1
906 for i, part in ipairs(animation.partsReverse) do
907 if part.startTime <= animation.currentTime then
908 animation.currentPartIndex = i
909 break
910 end
911 end
912 end
913end

getAnimationDuration

Description
Returns duration of animation
Definition
getAnimationDuration(string name)
Arguments
stringnamename of animation
Return Values
floatdurationduration in ms
Code
625function AnimatedVehicle:getAnimationDuration(name)
626 local spec = self.spec_animatedVehicle
627
628 local animation = spec.animations[name]
629 if animation ~= nil then
630 return animation.duration
631 end
632 return 1
633end

getAnimationExists

Description
Returns true if animation exits
Definition
getAnimationExists(string name)
Arguments
stringnamename of animation
Return Values
booleanexistsanimation axists
Code
531function AnimatedVehicle:getAnimationExists(name)
532 local spec = self.spec_animatedVehicle
533
534 return spec.animations[name] ~= nil
535end

getAnimationTime

Description
Returns animation time
Definition
getAnimationTime(string name)
Arguments
stringnamename of animation
Return Values
floatanimTimeanimation time [0..1]
Code
593function AnimatedVehicle:getAnimationTime(name)
594 local spec = self.spec_animatedVehicle
595
596 local animation = spec.animations[name]
597 if animation ~= nil then
598 return animation.currentTime/animation.duration
599 end
600 return 0
601end

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
920function AnimatedVehicle.getDurationToEndOfPart(part, anim)
921 if anim.currentSpeed > 0 then
922 return part.startTime+part.duration - anim.currentTime
923 else
924 return anim.currentTime - part.startTime
925 end
926end

getIsAnimationPlaying

Description
Returns true if animation is playing
Definition
getIsAnimationPlaying(string name)
Arguments
stringnamename of animation
Return Values
booleanisPlayinganimation is playing
Code
541function AnimatedVehicle:getIsAnimationPlaying(name)
542 local spec = self.spec_animatedVehicle
543
544 return spec.activeAnimations[name] ~= nil
545end

getIsSpeedRotatingPartActive

Description
Definition
getIsSpeedRotatingPartActive()
Code
716function AnimatedVehicle:getIsSpeedRotatingPartActive(superFunc, speedRotatingPart)
717 if speedRotatingPart.animName ~= nil then
718 local animTime = self:getAnimationTime(speedRotatingPart.animName)
719 if speedRotatingPart.animOuterRange then
720 if animTime > speedRotatingPart.animMinLimit or animTime < speedRotatingPart.animMaxLimit then
721 return false
722 end
723 else
724 if animTime > speedRotatingPart.animMaxLimit or animTime < speedRotatingPart.animMinLimit then
725 return false
726 end
727 end
728 end
729
730 return superFunc(self, speedRotatingPart)
731end

getIsWorkAreaActive

Description
Definition
getIsWorkAreaActive()
Code
745function AnimatedVehicle:getIsWorkAreaActive(superFunc, workArea)
746 if workArea.animName ~= nil then
747 local animTime = self:getAnimationTime(workArea.animName)
748 if animTime > workArea.animMaxLimit or animTime < workArea.animMinLimit then
749 return false
750 end
751 end
752
753 return superFunc(self, workArea)
754end

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
841function AnimatedVehicle.getMovedLimitedValue(currentValue, destValue, speed, dt)
842 local limitF = math.min
843 -- we are moving towards -inf, we need to check for the maximum
844 if destValue < currentValue then
845 limitF = math.max
846 elseif destValue == currentValue then
847 return currentValue
848 end
849 local ret = limitF(currentValue + speed * dt, destValue)
850 return ret
851end

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
935function AnimatedVehicle.getNextPartIsPlaying(nextPart, prevPart, anim, default)
936 if anim.currentSpeed > 0 then
937 if nextPart ~= nil then
938 return nextPart.startTime > anim.currentTime
939 end
940 else
941 if prevPart ~= nil then
942 return prevPart.startTime + prevPart.duration < anim.currentTime
943 end
944 end
945 return default
946end

getNumOfActiveAnimations

Description
Definition
getNumOfActiveAnimations()
Code
1328function AnimatedVehicle:getNumOfActiveAnimations()
1329 return self.spec_animatedVehicle.numActiveAnimations
1330end

getRealAnimationTime

Description
Returns real animation time
Definition
getRealAnimationTime(string name)
Arguments
stringnamename of animation
Return Values
floatanimTimereal animation time in ms
Code
551function AnimatedVehicle:getRealAnimationTime(name)
552 local spec = self.spec_animatedVehicle
553
554 local animation = spec.animations[name]
555 if animation ~= nil then
556 return animation.currentTime
557 end
558 return 0
559end

initializeAnimationPart

Description
Initialize part of animation
Definition
initializeAnimationPart(table part)
Arguments
tablepartpart
Code
381function AnimatedVehicle:initializeAnimationPart(animation, part, i, numParts)
382 -- rot, trans, scale
383 AnimatedVehicle.initializeAnimationPartAttribute(self, animation, part, i, numParts, "nextRotPart", "prevRotPart", "startRot", "endRot", "rotation")
384 AnimatedVehicle.initializeAnimationPartAttribute(self, animation, part, i, numParts, "nextTransPart", "prevTransPart", "startTrans", "endTrans", "translation")
385 AnimatedVehicle.initializeAnimationPartAttribute(self, animation, part, i, numParts, "nextScalePart", "prevScalePart", "startScale", "endScale", "scale")
386
387 --shader params
388 AnimatedVehicle.initializeAnimationPartAttribute(self, animation, part, i, numParts, "nextShaderPart", "prevShaderPart", "shaderStartValues", "shaderEndValues", "shaderParameter")
389
390 -- animation clips
391 AnimatedVehicle.initializeAnimationPartAttribute(self, animation, part, i, numParts, "nextClipPart", "prevClipPart", "clipStartTime", "clipEndTime", "animation clip")
392
393 -- dependent animations
394 AnimatedVehicle.initializeAnimationPartAttribute(self, animation, part, i, numParts, "nextDependentAnimPart", "prevDependentAnimPart", "dependentAnimStartTime", "dependentAnimEndTime", "dependent animation", nil, nil, "dependentAnim")
395
396 if self.isServer then
397 -- joint limits
398 AnimatedVehicle.initializeAnimationPartAttribute(self, animation, part, i, numParts, "nextRotLimitPart", "prevRotLimitPart", "startRotMinLimit", "endRotMinLimit", "joint rot limit", "startRotMaxLimit", "endRotMaxLimit", "componentJoint")
399 AnimatedVehicle.initializeAnimationPartAttribute(self, animation, part, i, numParts, "nextTransLimitPart", "prevTransLimitPart", "startTransMinLimit", "startTransMinLimit", "joint trans limit", "startTransMaxLimit", "endTransMaxLimit", "componentJoint")
400 end
401end

initializeAnimationPartAttribute

Description
Definition
initializeAnimationPartAttribute()
Code
758function AnimatedVehicle.initializeAnimationPartAttribute(self, animation, part, i, numParts, nextName, prevName, startName, endName, warningName, startName2, endName2, additionalCompareParam)
759 -- find next part, check for overlapping, enter dependencies and set default start value if not already set
760 if part[endName] ~= nil then
761 for j=i+1, numParts do
762 local part2 = animation.parts[j]
763
764 local additionalCompare = true
765 if additionalCompareParam ~= nil then
766 if part[additionalCompareParam] ~= part2[additionalCompareParam] then
767 additionalCompare = false
768 end
769 end
770
771 -- check if the animations use the same range, if not they cannot collide
772 local sameRequiredRange = true
773 if part.requiredAnimation ~= nil then
774 if part.requiredAnimation == part2.requiredAnimation then
775 for n, v in ipairs(part.requiredAnimationRange) do
776 if part2.requiredAnimationRange[n] ~= v then
777 sameRequiredRange = false
778 end
779 end
780 end
781 end
782
783 if part.direction == part2.direction and part.node == part2.node and part2[endName] ~= nil and additionalCompare and sameRequiredRange then
784 if part.direction == part2.direction and part.startTime + part.duration > part2.startTime+0.001 then
785 g_logManager:xmlWarning(self.configFileName, "Overlapping %s parts for node '%s' in animation '%s'", warningName, getName(part.node), animation.name)
786 end
787 part[nextName] = part2
788 part2[prevName] = part
789 if part2[startName] == nil then
790 part2[startName] = {unpack(part[endName])}
791 end
792 if startName2 ~= nil and endName2 ~= nil then
793 if part2[startName2] == nil then
794 part2[startName2] = {unpack(part[endName2])}
795 end
796 end
797
798 break
799 end
800 end
801 end
802end

initializeAnimationParts

Description
Initialize parts of animation
Definition
initializeAnimationParts(table animation)
Arguments
tableanimationanimation
Code
366function AnimatedVehicle:initializeAnimationParts(animation)
367 local numParts = table.getn(animation.parts)
368
369 for i, part in ipairs(animation.parts) do
370 self:initializeAnimationPart(animation, part, i, numParts)
371 end
372
373 for i, part in ipairs(animation.parts) do
374 self:postInitializeAnimationPart(animation, part, i, numParts)
375 end
376end

loadAnimation

Description
Definition
loadAnimation()
Code
143function AnimatedVehicle:loadAnimation(xmlFile, key, animation)
144
145 local name = getXMLString(xmlFile, key.."#name")
146 if name ~= nil then
147 animation.name = name
148 animation.parts = {}
149 animation.currentTime = 0
150 animation.currentSpeed = 1
151 animation.looping = Utils.getNoNil(getXMLBool(xmlFile, key .. "#looping"), false)
152 animation.resetOnStart = Utils.getNoNil(getXMLBool(xmlFile, key .. "#resetOnStart"), true)
153
154 local partI = 0
155 while true do
156 local partKey = key..string.format(".part(%d)", partI)
157 if not hasXMLProperty(xmlFile, partKey) then
158 break
159 end
160
161 local animationPart = {}
162 if self:loadAnimationPart(xmlFile, partKey, animationPart) then
163 table.insert(animation.parts, animationPart)
164 end
165 partI = partI + 1
166 end
167
168 -- sort parts by start/end time
169 animation.partsReverse = {}
170 for _, part in ipairs(animation.parts) do
171 table.insert(animation.partsReverse, part)
172 end
173 table.sort(animation.parts, AnimatedVehicle.animPartSorter)
174 table.sort(animation.partsReverse, AnimatedVehicle.animPartSorterReverse)
175
176 self:initializeAnimationParts(animation)
177
178 animation.currentPartIndex = 1
179 animation.duration = 0
180 for _, part in ipairs(animation.parts) do
181 animation.duration = math.max(animation.duration, part.startTime + part.duration)
182 end
183
184 if self.isClient then
185 animation.sample = g_soundManager:loadSampleFromXML(self.xmlFile, key, "sound", self.baseDirectory, self.components, 0, AudioGroup.VEHICLE, self.i3dMappings, self)
186 end
187
188 return true
189 end
190
191 return false
192end

loadAnimationPart

Description
Definition
loadAnimationPart()
Code
196function AnimatedVehicle:loadAnimationPart(xmlFile, partKey, part)
197 local node = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, partKey.."#node"), self.i3dMappings)
198 local startTime = getXMLFloat(xmlFile, partKey.."#startTime")
199 local duration = getXMLFloat(xmlFile, partKey.."#duration")
200 local endTime = getXMLFloat(xmlFile, partKey.."#endTime")
201 local direction = MathUtil.sign(Utils.getNoNil(getXMLInt(xmlFile, partKey.."#direction"), 0))
202 local startRot = StringUtil.getRadiansFromString(getXMLString(xmlFile, partKey.."#startRot"), 3)
203 local endRot = StringUtil.getRadiansFromString(getXMLString(xmlFile, partKey.."#endRot"), 3)
204 local startTrans = StringUtil.getVectorNFromString(getXMLString(xmlFile, partKey.."#startTrans"), 3)
205 local endTrans = StringUtil.getVectorNFromString(getXMLString(xmlFile, partKey.."#endTrans"), 3)
206 local startScale = StringUtil.getVectorNFromString(getXMLString(xmlFile, partKey.."#startScale"), 3)
207 local endScale = StringUtil.getVectorNFromString(getXMLString(xmlFile, partKey.."#endScale"), 3)
208 local visibility = getXMLBool(xmlFile, partKey.."#visibility")
209 local componentJointIndex = getXMLInt(xmlFile, partKey.."#componentJointIndex")
210
211 local requiredAnimation = getXMLString(xmlFile, partKey.."#requiredAnimation")
212 local requiredAnimationRange = StringUtil.getVectorNFromString(getXMLString(xmlFile, partKey.."#requiredAnimationRange"), 2)
213
214 if componentJointIndex ~= nil and componentJointIndex < 1 then
215 g_logManager:warning("Invalid componentJointIndex for animation part '%s'. Indexing starts with 1!", partKey)
216 componentJointIndex = nil
217 end
218
219 local componentJoint
220 if componentJointIndex ~= nil then
221 componentJoint = self.componentJoints[componentJointIndex]
222 end
223 local startRotLimit = StringUtil.getRadiansFromString(getXMLString(xmlFile, partKey.."#startRotLimit"), 3)
224 local startRotMinLimit = StringUtil.getRadiansFromString(getXMLString(xmlFile, partKey.."#startRotMinLimit"), 3)
225 local startRotMaxLimit = StringUtil.getRadiansFromString(getXMLString(xmlFile, partKey.."#startRotMaxLimit"), 3)
226 if startRotLimit ~= nil then
227 startRotMinLimit = {}
228 startRotMaxLimit = {}
229 for i=1,3 do
230 startRotMinLimit[i] = -startRotLimit[i]
231 startRotMaxLimit[i] = startRotLimit[i]
232 end
233 end
234 local endRotLimit = StringUtil.getRadiansFromString(getXMLString(xmlFile, partKey.."#endRotLimit"), 3)
235 local endRotMinLimit = StringUtil.getRadiansFromString(getXMLString(xmlFile, partKey.."#endRotMinLimit"), 3)
236 local endRotMaxLimit = StringUtil.getRadiansFromString(getXMLString(xmlFile, partKey.."#endRotMaxLimit"), 3)
237 if endRotLimit ~= nil then
238 endRotMinLimit = {}
239 endRotMaxLimit = {}
240 for i=1,3 do
241 endRotMinLimit[i] = -endRotLimit[i]
242 endRotMaxLimit[i] = endRotLimit[i]
243 end
244 end
245
246 local startTransLimit = StringUtil.getVectorNFromString(getXMLString(xmlFile, partKey.."#startTransLimit"), 3)
247 local startTransMinLimit = StringUtil.getVectorNFromString(getXMLString(xmlFile, partKey.."#startTransMinLimit"), 3)
248 local startTransMaxLimit = StringUtil.getVectorNFromString(getXMLString(xmlFile, partKey.."#startTransMaxLimit"), 3)
249 if startTransLimit ~= nil then
250 startTransMinLimit = {}
251 startTransMaxLimit = {}
252 for i=1,3 do
253 startTransMinLimit[i] = -startTransLimit[i]
254 startTransMaxLimit[i] = startTransLimit[i]
255 end
256 end
257 local endTransLimit = StringUtil.getVectorNFromString(getXMLString(xmlFile, partKey.."#endTransLimit"), 3)
258 local endTransMinLimit = StringUtil.getVectorNFromString(getXMLString(xmlFile, partKey.."#endTransMinLimit"), 3)
259 local endTransMaxLimit = StringUtil.getVectorNFromString(getXMLString(xmlFile, partKey.."#endTransMaxLimit"), 3)
260 if endTransLimit ~= nil then
261 endTransMinLimit = {}
262 endTransMaxLimit = {}
263 for i=1,3 do
264 endTransMinLimit[i] = -endTransLimit[i]
265 endTransMaxLimit[i] = endTransLimit[i]
266 end
267 end
268
269 local shaderParameter = getXMLString(xmlFile, partKey.."#shaderParameter")
270 local shaderStartValues = StringUtil.getVectorNFromString(getXMLString(xmlFile, partKey.."#shaderStartValues"), 4)
271 local shaderEndValues = StringUtil.getVectorNFromString(getXMLString(xmlFile, partKey.."#shaderEndValues"), 4)
272
273 local animationClip = getXMLString(xmlFile, partKey.."#animationClip")
274 local clipStartTime = getXMLFloat(xmlFile, partKey.."#clipStartTime")
275 local clipEndTime = getXMLFloat(xmlFile, partKey.."#clipEndTime")
276
277 local dependentAnim = getXMLString(xmlFile, partKey.."#dependentAnimation")
278 local dependentAnimStartTime = getXMLFloat(xmlFile, partKey.."#dependentAnimationStartTime")
279 local dependentAnimEndTime = getXMLFloat(xmlFile, partKey.."#dependentAnimationEndTime")
280
281 local hasTiming = startTime ~= nil and (duration ~= nil or endTime ~= nil)
282-- local hasBasics = node ~= nil and (endRot ~= nil or endTrans ~= nil or endScale ~= nil or visibility ~= nil)
283-- local hasJointLimits = componentJoint ~= nil and ((endRotMinLimit ~= nil and endRotMaxLimit ~= nil) or (endTransMinLimit ~= nil and endTransMaxLimit ~= nil))
284-- local hasShaderParameters = node ~= nil and shaderParameter ~= nil and (shaderStartValues ~= nil and shaderEndValues ~= nil)
285-- local hasAnimationClip = node ~= nil and animationClip ~= nil and (clipStartTime ~= nil and clipEndTime ~= nil)
286
287 if hasTiming then
288 if endTime ~= nil then
289 duration = endTime - startTime
290 end
291 part.node = node
292 part.startTime = startTime*1000
293 part.duration = duration*1000
294 part.direction = direction
295 part.requiredAnimation = requiredAnimation
296 part.requiredAnimationRange = requiredAnimationRange
297 if node ~= nil then
298 if endRot ~= nil then
299 part.startRot = startRot
300 part.endRot = endRot
301 end
302 if endTrans ~= nil then
303 part.startTrans = startTrans
304 part.endTrans = endTrans
305 end
306 if endScale ~= nil then
307 part.startScale = startScale
308 part.endScale = endScale
309 end
310
311 if shaderParameter ~= nil and shaderEndValues ~= nil and shaderStartValues ~= nil then
312 if getHasClassId(node, ClassIds.SHAPE) and getHasShaderParameter(node, shaderParameter) then
313 part.shaderParameter = shaderParameter
314 part.shaderStartValues = shaderStartValues
315 part.shaderEndValues = shaderEndValues
316 else
317 g_logManager:warning("Node '%s' has no shaderParameter '%s' for animation part '%s'!", getName(node), shaderParameter, partKey)
318 end
319 end
320
321 if animationClip ~= nil and clipStartTime ~= nil and clipEndTime ~= nil then
322 part.animationClip = animationClip
323 part.animationCharSet = getAnimCharacterSet(node);
324 part.animationClipIndex = getAnimClipIndex(part.animationCharSet, animationClip);
325 part.clipStartTime = clipStartTime
326 part.clipEndTime = clipEndTime
327 end
328
329 part.visibility = visibility
330 end
331
332 if dependentAnim ~= nil and dependentAnimStartTime ~= nil and dependentAnimEndTime ~= nil then
333 part.dependentAnim = dependentAnim
334 part.dependentAnimStartTime = dependentAnimStartTime
335 part.dependentAnimEndTime = dependentAnimEndTime
336 end
337
338 if self.isServer then
339 if componentJoint ~= nil then
340 if endRotMinLimit ~= nil then
341 part.componentJoint = componentJoint
342 part.startRotMinLimit = startRotMinLimit
343 part.startRotMaxLimit = startRotMaxLimit
344 part.endRotMinLimit = endRotMinLimit
345 part.endRotMaxLimit = endRotMaxLimit
346 end
347 if endTransMinLimit ~= nil then
348 part.componentJoint = componentJoint
349 part.startTransMinLimit = startTransMinLimit
350 part.startTransMaxLimit = startTransMaxLimit
351 part.endTransMinLimit = endTransMinLimit
352 part.endTransMaxLimit = endTransMaxLimit
353 end
354 end
355 end
356
357 return true
358 end
359
360 return false
361end

loadSpeedRotatingPartFromXML

Description
Definition
loadSpeedRotatingPartFromXML()
Code
702function AnimatedVehicle:loadSpeedRotatingPartFromXML(superFunc, speedRotatingPart, xmlFile, key)
703 if not superFunc(self, speedRotatingPart, xmlFile, key) then
704 return false
705 end
706
707 speedRotatingPart.animName = getXMLString(xmlFile, key.."#animName")
708 speedRotatingPart.animOuterRange = Utils.getNoNil(getXMLBool(xmlFile, key.."#animOuterRange"), false)
709 speedRotatingPart.animMinLimit = Utils.getNoNil(getXMLFloat(xmlFile, key.."#animMinLimit"), 0)
710 speedRotatingPart.animMaxLimit = Utils.getNoNil(getXMLFloat(xmlFile, key.."#animMaxLimit"), 1)
711 return true
712end

loadWorkAreaFromXML

Description
Definition
loadWorkAreaFromXML()
Code
735function AnimatedVehicle:loadWorkAreaFromXML(superFunc, workArea, xmlFile, key)
736 workArea.animName = getXMLString(xmlFile, key.."#animName")
737 workArea.animMinLimit = Utils.getNoNil(getXMLFloat(xmlFile, key.."#animMinLimit"), 0)
738 workArea.animMaxLimit = Utils.getNoNil(getXMLFloat(xmlFile, key.."#animMaxLimit"), 1)
739
740 return superFunc(self, workArea, xmlFile, key)
741end

onDelete

Description
Called on deleting
Definition
onDelete()
Code
119function AnimatedVehicle:onDelete()
120 local spec = self.spec_animatedVehicle
121 for name, animation in pairs(spec.animations) do
122 if self.isClient then
123 g_soundManager:deleteSample(animation.sample)
124 end
125 end
126end

onLoad

Description
Called on loading
Definition
onLoad(table savegame)
Arguments
tablesavegamesavegame
Code
79function AnimatedVehicle:onLoad(savegame)
80 local spec = self.spec_animatedVehicle
81
82 spec.animations = {}
83
84 local i = 0
85 while true do
86 local key = string.format("vehicle.animations.animation(%d)", i)
87 if not hasXMLProperty(self.xmlFile, key) then
88 break
89 end
90
91 local animation = {}
92
93 if self:loadAnimation(self.xmlFile, key, animation) then
94 spec.animations[animation.name] = animation
95 end
96
97 i = i + 1
98 end
99
100 spec.activeAnimations = {}
101 spec.numActiveAnimations = 0
102end

onPostLoad

Description
Called after loading
Definition
onPostLoad(table savegame)
Arguments
tablesavegamesavegame
Code
107function AnimatedVehicle:onPostLoad(savegame)
108 local spec = self.spec_animatedVehicle
109 for name, animation in pairs(spec.animations) do
110 if animation.resetOnStart then
111 self:playAnimation(name, -1, nil, true)
112 AnimatedVehicle.updateAnimationByName(self, name, 9999999, false)
113 end
114 end
115end

onUpdate

Description
Called on update
Definition
onUpdate(float dt, boolean isActiveForInput, boolean isSelected)
Arguments
floatdttime since last call in ms
booleanisActiveForInputtrue if vehicle is active for input
booleanisSelectedtrue if vehicle is selected
Code
133function AnimatedVehicle:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
134 AnimatedVehicle.updateAnimations(self, dt)
135
136 if self.spec_animatedVehicle.numActiveAnimations > 0 then
137 self:raiseActive()
138 end
139end

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
446function AnimatedVehicle:playAnimation(name, speed, animTime, noEventSend)
447 local spec = self.spec_animatedVehicle
448
449 local animation = spec.animations[name]
450 if animation ~= nil then
451 SpecializationUtil.raiseEvent(self, "onPlayAnimation", name)
452
453 if speed == nil then
454 speed = animation.currentSpeed
455 end
456
457 -- skip animation if speed is not set or 0 to allow skipping animations per xml speed attribute set to 0
458 if speed == nil or speed == 0 then
459 return
460 end
461
462 if animTime == nil then
463 if self:getIsAnimationPlaying(name) then
464 animTime = self:getAnimationTime(name)
465 elseif speed > 0 then
466 animTime = 0
467 else
468 animTime = 1
469 end
470 end
471 if noEventSend == nil or noEventSend == false then
472 if g_server ~= nil then
473 g_server:broadcastEvent(AnimatedVehicleStartEvent:new(self, name, speed, animTime), nil, nil, self)
474 else
475 g_client:getServerConnection():sendEvent(AnimatedVehicleStartEvent:new(self, name, speed, animTime))
476 end
477 end
478
479 if spec.activeAnimations[name] == nil then
480 spec.activeAnimations[name] = animation
481 spec.numActiveAnimations = spec.numActiveAnimations + 1
482 SpecializationUtil.raiseEvent(self, "onStartAnimation", name)
483 end
484 animation.currentSpeed = speed
485 animation.currentTime = animTime*animation.duration
486 self:resetAnimationValues(animation)
487
488 if self.isClient then
489 g_soundManager:playSample(animation.sample)
490 end
491
492 self:raiseActive()
493 end
494end

postInitializeAnimationPart

Description
Post Initialize part of animation (normally used to set default start value if not set by the end value of the previous part)
Definition
postInitializeAnimationPart(table part)
Arguments
tablepartpart
Code
406function AnimatedVehicle:postInitializeAnimationPart(animation, part, i, numParts)
407 if part.endRot ~= nil and part.startRot == nil then
408 local x,y,z = getRotation(part.node)
409 part.startRot = {x,y,z}
410 end
411 if part.endTrans ~= nil and part.startTrans == nil then
412 local x,y,z = getTranslation(part.node)
413 part.startTrans = {x,y,z}
414 end
415 if part.endScale ~= nil and part.startScale == nil then
416 local x,y,z = getScale(part.node)
417 part.startScale = {x,y,z}
418 end
419 if self.isServer then
420 if part.endRotMinLimit ~= nil and part.startRotMinLimit == nil then
421 local rotLimit = part.componentJoint.rotMinLimit
422 part.startRotMinLimit = {rotLimit[1], rotLimit[2], rotLimit[3]}
423 end
424 if part.endRotMaxLimit ~= nil and part.startRotMaxLimit == nil then
425 local rotLimit = part.componentJoint.rotLimit
426 part.startRotMaxLimit = {rotLimit[1], rotLimit[2], rotLimit[3]}
427 end
428 if part.endTransMinLimit ~= nil and part.startTransMinLimit == nil then
429 local transLimit = part.componentJoint.transMinLimit
430 part.startTransMinLimit = {transLimit[1], transLimit[2], transLimit[3]}
431 end
432 if part.endTransMaxLimit ~= nil and part.startTransMaxLimit == nil then
433 local transLimit = part.componentJoint.transLimit
434 part.startTransMaxLimit = {transLimit[1], transLimit[2], transLimit[3]}
435 end
436 end
437end

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

registerEventListeners

Description
Definition
registerEventListeners()
Code
69function AnimatedVehicle.registerEventListeners(vehicleType)
70 SpecializationUtil.registerEventListener(vehicleType, "onLoad", AnimatedVehicle)
71 SpecializationUtil.registerEventListener(vehicleType, "onPostLoad", AnimatedVehicle)
72 SpecializationUtil.registerEventListener(vehicleType, "onDelete", AnimatedVehicle)
73 SpecializationUtil.registerEventListener(vehicleType, "onUpdate", AnimatedVehicle)
74end

registerEvents

Description
Definition
registerEvents()
Code
26function AnimatedVehicle.registerEvents(vehicleType)
27 SpecializationUtil.registerEvent(vehicleType, "onPlayAnimation")
28 SpecializationUtil.registerEvent(vehicleType, "onStartAnimation")
29 SpecializationUtil.registerEvent(vehicleType, "onFinishAnimation")
30 SpecializationUtil.registerEvent(vehicleType, "onStopAnimation")
31end

registerFunctions

Description
Definition
registerFunctions()
Code
35function AnimatedVehicle.registerFunctions(vehicleType)
36 SpecializationUtil.registerFunction(vehicleType, "loadAnimation", AnimatedVehicle.loadAnimation)
37 SpecializationUtil.registerFunction(vehicleType, "loadAnimationPart", AnimatedVehicle.loadAnimationPart)
38 SpecializationUtil.registerFunction(vehicleType, "initializeAnimationParts", AnimatedVehicle.initializeAnimationParts)
39 SpecializationUtil.registerFunction(vehicleType, "initializeAnimationPart", AnimatedVehicle.initializeAnimationPart)
40 SpecializationUtil.registerFunction(vehicleType, "postInitializeAnimationPart", AnimatedVehicle.postInitializeAnimationPart)
41 SpecializationUtil.registerFunction(vehicleType, "playAnimation", AnimatedVehicle.playAnimation)
42 SpecializationUtil.registerFunction(vehicleType, "stopAnimation", AnimatedVehicle.stopAnimation)
43 SpecializationUtil.registerFunction(vehicleType, "getAnimationExists", AnimatedVehicle.getAnimationExists)
44 SpecializationUtil.registerFunction(vehicleType, "getIsAnimationPlaying", AnimatedVehicle.getIsAnimationPlaying)
45 SpecializationUtil.registerFunction(vehicleType, "getRealAnimationTime", AnimatedVehicle.getRealAnimationTime)
46 SpecializationUtil.registerFunction(vehicleType, "setRealAnimationTime", AnimatedVehicle.setRealAnimationTime)
47 SpecializationUtil.registerFunction(vehicleType, "getAnimationTime", AnimatedVehicle.getAnimationTime)
48 SpecializationUtil.registerFunction(vehicleType, "setAnimationTime", AnimatedVehicle.setAnimationTime)
49 SpecializationUtil.registerFunction(vehicleType, "getAnimationDuration", AnimatedVehicle.getAnimationDuration)
50 SpecializationUtil.registerFunction(vehicleType, "setAnimationSpeed", AnimatedVehicle.setAnimationSpeed)
51 SpecializationUtil.registerFunction(vehicleType, "setAnimationStopTime", AnimatedVehicle.setAnimationStopTime)
52 SpecializationUtil.registerFunction(vehicleType, "resetAnimationValues", AnimatedVehicle.resetAnimationValues)
53 SpecializationUtil.registerFunction(vehicleType, "resetAnimationPartValues", AnimatedVehicle.resetAnimationPartValues)
54 SpecializationUtil.registerFunction(vehicleType, "updateAnimationPart", AnimatedVehicle.updateAnimationPart)
55 SpecializationUtil.registerFunction(vehicleType, "getNumOfActiveAnimations", AnimatedVehicle.getNumOfActiveAnimations)
56end

registerOverwrittenFunctions

Description
Definition
registerOverwrittenFunctions()
Code
60function AnimatedVehicle.registerOverwrittenFunctions(vehicleType)
61 SpecializationUtil.registerOverwrittenFunction(vehicleType, "loadSpeedRotatingPartFromXML", AnimatedVehicle.loadSpeedRotatingPartFromXML)
62 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsSpeedRotatingPartActive", AnimatedVehicle.getIsSpeedRotatingPartActive)
63 SpecializationUtil.registerOverwrittenFunction(vehicleType, "loadWorkAreaFromXML", AnimatedVehicle.loadWorkAreaFromXML)
64 SpecializationUtil.registerOverwrittenFunction(vehicleType, "getIsWorkAreaActive", AnimatedVehicle.getIsWorkAreaActive)
65end

resetAnimationPartValues

Description
Resets animation part
Definition
resetAnimationPartValues(table part)
Arguments
tablepartpart to reset
Code
681function AnimatedVehicle:resetAnimationPartValues(part)
682 part.curRot = nil
683 part.speedRot = nil
684 part.curTrans = nil
685 part.speedTrans = nil
686 part.curScale = nil
687 part.speedScale = nil
688 part.curVisibility = nil
689 part.curRotMinLimit = nil
690 part.curRotMaxLimit = nil
691 part.speedRotLimit = nil
692 part.curTransMinLimit = nil
693 part.curTransMaxLimit = nil
694 part.speedTransLimit = nil
695 part.shaderCurValues = nil
696 part.curClipTime = nil
697 part.curDependentAnimTime = nil
698end

resetAnimationValues

Description
Resets animation values
Definition
resetAnimationValues(table animation)
Arguments
tableanimationanimation
Code
671function AnimatedVehicle:resetAnimationValues(animation)
672 AnimatedVehicle.findCurrentPartIndex(animation)
673 for _, part in ipairs(animation.parts) do
674 self:resetAnimationPartValues(part)
675 end
676end

setAnimationSpeed

Description
Sets speed of animation
Definition
setAnimationSpeed(string name, float speed)
Arguments
stringnamename of animation
floatspeedspeed
Code
639function AnimatedVehicle:setAnimationSpeed(name, speed)
640 local spec = self.spec_animatedVehicle
641
642 local animation = spec.animations[name]
643 if animation ~= nil then
644 local speedReversed = false
645 if (animation.currentSpeed > 0) ~= (speed > 0) then
646 speedReversed = true
647 end
648 animation.currentSpeed = speed
649 if self:getIsAnimationPlaying(name) and speedReversed then
650 self:resetAnimationValues(animation)
651 end
652 end
653end

setAnimationStopTime

Description
Sets animation stop time
Definition
setAnimationStopTime(string name, float stopTime)
Arguments
stringnamename of animation
floatstopTimestop time [0..1]
Code
659function AnimatedVehicle:setAnimationStopTime(name, stopTime)
660 local spec = self.spec_animatedVehicle
661
662 local animation = spec.animations[name]
663 if animation ~= nil then
664 animation.stopTime = stopTime*animation.duration
665 end
666end

setAnimationTime

Description
Set animation time
Definition
setAnimationTime(string name, float animTime, boolean update)
Arguments
stringnamename of animation
floatanimTimeanimation time [0..1]
booleanupdateupdate animation
Code
608function AnimatedVehicle:setAnimationTime(name, animTime, update)
609 local spec = self.spec_animatedVehicle
610
611 if spec.animations == nil then
612 printCallstack()
613 end
614
615 local animation = spec.animations[name]
616 if animation ~= nil then
617 self:setRealAnimationTime(name, animTime*animation.duration, update)
618 end
619end

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
859function AnimatedVehicle.setMovedLimitedValues3(currentValues, destValues, speeds, dt)
860 local hasChanged = false
861 for i=1,3 do
862 local newValue = AnimatedVehicle.getMovedLimitedValue(currentValues[i], destValues[i], speeds[i], dt)
863 if currentValues[i] ~= newValue then
864 hasChanged = true
865 currentValues[i] = newValue
866 end
867 end
868 return hasChanged
869end

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
877function AnimatedVehicle.setMovedLimitedValues4(currentValues, destValues, speeds, dt)
878 local hasChanged = false
879 for i=1,4 do
880 local newValue = AnimatedVehicle.getMovedLimitedValue(currentValues[i], destValues[i], speeds[i], dt)
881 if currentValues[i] ~= newValue then
882 hasChanged = true
883 currentValues[i] = newValue
884 end
885 end
886 return hasChanged
887end

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
566function AnimatedVehicle:setRealAnimationTime(name, animTime, update)
567 local spec = self.spec_animatedVehicle
568
569 local animation = spec.animations[name]
570 if animation ~= nil then
571 if update == nil or update then
572 local currentSpeed = animation.currentSpeed
573 animation.currentSpeed = 1
574 if animation.currentTime > animTime then
575 animation.currentSpeed = -1
576 end
577
578 self:resetAnimationValues(animation)
579
580 local dtToUse, _ = AnimatedVehicle.updateAnimationCurrentTime(self, animation, 99999999, animTime)
581 AnimatedVehicle.updateAnimation(self, animation, dtToUse, false)
582 animation.currentSpeed = currentSpeed
583 else
584 animation.currentTime = animTime
585 end
586 end
587end

stopAnimation

Description
Stop animation
Definition
stopAnimation(string name, boolean noEventSend)
Arguments
stringnamename of animation
booleannoEventSendno event send
Code
500function AnimatedVehicle:stopAnimation(name, noEventSend)
501 local spec = self.spec_animatedVehicle
502
503 if noEventSend == nil or noEventSend == false then
504 if g_server ~= nil then
505 g_server:broadcastEvent(AnimatedVehicleStopEvent:new(self, name), nil, nil, self)
506 else
507 g_client:getServerConnection():sendEvent(AnimatedVehicleStopEvent:new(self, name))
508 end
509 end
510 local animation = spec.animations[name]
511 if animation ~= nil then
512 SpecializationUtil.raiseEvent(self, "onStopAnimation", name)
513 animation.stopTime = nil
514
515 if self.isClient then
516 g_soundManager:stopSample(animation.sample)
517 end
518 end
519
520 if spec.activeAnimations[name] ~= nil then
521 spec.numActiveAnimations = spec.numActiveAnimations - 1
522 spec.activeAnimations[name] = nil
523 SpecializationUtil.raiseEvent(self, "onFinishAnimation", name)
524 end
525end

updateAnimation

Description
Update animation
Definition
updateAnimation(table anim, float dtToUse, boolean stopAnimation)
Arguments
tableanimanimation
floatdtToUsedt to use
booleanstopAnimationstop animation
Code
1010function AnimatedVehicle.updateAnimation(self, anim, dtToUse, stopAnim, allowRestart)
1011 local spec = self.spec_animatedVehicle
1012
1013 local numParts = table.getn(anim.parts)
1014 local parts = anim.parts
1015 if anim.currentSpeed < 0 then
1016 parts = anim.partsReverse
1017 end
1018
1019 if dtToUse > 0 then
1020 local hasChanged = false
1021 local nothingToChangeYet = false
1022 for partI=anim.currentPartIndex, numParts do
1023 local part = parts[partI]
1024
1025 local isInRange = true
1026 if part.requiredAnimation ~= nil then
1027 local time = self:getAnimationTime(part.requiredAnimation)
1028 if time < part.requiredAnimationRange[1] or time > part.requiredAnimationRange[2] then
1029 isInRange = false
1030 end
1031 end
1032
1033 if (part.direction == 0 or ((part.direction > 0) == (anim.currentSpeed >= 0))) and isInRange then
1034 local durationToEnd = AnimatedVehicle.getDurationToEndOfPart(part, anim)
1035
1036 -- is this part not playing yet?
1037 if durationToEnd > part.duration then
1038 nothingToChangeYet = true
1039 break
1040 end
1041
1042 local realDt = dtToUse
1043
1044 if anim.currentSpeed > 0 then
1045 local startT = anim.currentTime-dtToUse
1046 if startT < part.startTime then
1047 realDt = dtToUse - part.startTime + startT
1048 end
1049 else
1050 local startT = anim.currentTime+dtToUse
1051 local endTime = part.startTime + part.duration
1052 if startT > endTime then
1053 realDt = dtToUse - (startT - endTime)
1054 end
1055 end
1056
1057 durationToEnd = durationToEnd+realDt
1058
1059 if self:updateAnimationPart(anim, part, durationToEnd, dtToUse, realDt) then
1060 if self.setMovingToolDirty ~= nil then
1061 self:setMovingToolDirty(part.node)
1062 end
1063 hasChanged = true
1064 end
1065 end
1066
1067 if partI == anim.currentPartIndex then
1068 -- is this part finished?
1069 if (anim.currentSpeed > 0 and part.startTime + part.duration < anim.currentTime) or
1070 (anim.currentSpeed <= 0 and part.startTime > anim.currentTime)
1071 then
1072 self:resetAnimationPartValues(part)
1073 anim.currentPartIndex = anim.currentPartIndex+1
1074 end
1075 end
1076 end
1077 if not nothingToChangeYet and not hasChanged and anim.currentPartIndex >= numParts then
1078 -- end the animation
1079 if anim.currentSpeed > 0 then
1080 anim.currentTime = anim.duration
1081 else
1082 anim.currentTime = 0
1083 end
1084 stopAnim = true
1085 end
1086 end
1087 if stopAnim or anim.currentPartIndex > numParts or anim.currentPartIndex < 1 then
1088 if not stopAnim then
1089 if anim.currentSpeed > 0 then
1090 anim.currentTime = anim.duration
1091 else
1092 anim.currentTime = 0
1093 end
1094 end
1095 anim.currentTime = math.min(math.max(anim.currentTime, 0), anim.duration)
1096 anim.stopTime = nil
1097 if spec.activeAnimations[anim.name] ~= nil then
1098 spec.numActiveAnimations = spec.numActiveAnimations - 1
1099
1100 if self.isClient then
1101 g_soundManager:stopSample(spec.activeAnimations[anim.name].sample)
1102 end
1103
1104 spec.activeAnimations[anim.name] = nil
1105 SpecializationUtil.raiseEvent(self, "onFinishAnimation", anim.name)
1106 end
1107
1108 if allowRestart == nil or allowRestart then
1109 if anim.looping then
1110 -- restart animation
1111 self:setAnimationTime(anim.name, math.abs((anim.currentTime/anim.duration) - 1), true)
1112 self:playAnimation(anim.name, anim.currentSpeed, nil, true)
1113 end
1114 end
1115 end
1116end

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
964function AnimatedVehicle.updateAnimationByName(self, animName, dt, allowRestart)
965 local spec = self.spec_animatedVehicle
966
967 local anim = spec.animations[animName]
968 if anim ~= nil then
969 local dtToUse, stopAnim = AnimatedVehicle.updateAnimationCurrentTime(self, anim, dt, anim.stopTime)
970 AnimatedVehicle.updateAnimation(self, anim, dtToUse, stopAnim, allowRestart)
971 end
972end

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
981function AnimatedVehicle.updateAnimationCurrentTime(self, anim, dt, stopTime)
982 anim.currentTime = anim.currentTime + dt*anim.currentSpeed
983
984 local absSpeed = math.abs(anim.currentSpeed)
985 local dtToUse = dt*absSpeed
986 local stopAnim = false
987 if stopTime ~= nil then
988 if anim.currentSpeed > 0 then
989 if stopTime <= anim.currentTime then
990 dtToUse = dtToUse-(anim.currentTime-stopTime)
991 anim.currentTime = stopTime
992 stopAnim = true
993 end
994 else
995 if stopTime >= anim.currentTime then
996 dtToUse = dtToUse-(stopTime-anim.currentTime)
997 anim.currentTime = stopTime
998 stopAnim = true
999 end
1000 end
1001 end
1002 return dtToUse, stopAnim
1003end

updateAnimationPart

Description
Update animation part
Definition
updateAnimationPart(table anim, table part, float durationToEnd, float dtToUse, float realDt)
Arguments
tableanimanimation
tablepartpart
floatdurationToEndduration to end
floatdtToUsedt to use
floatrealDtreal dt
Code
1125function AnimatedVehicle:updateAnimationPart(animation, part, durationToEnd, dtToUse, realDt)
1126 local hasPartChanged = false
1127 if part.startRot ~= nil and (durationToEnd > 0 or AnimatedVehicle.getNextPartIsPlaying(part.nextRotPart, part.prevRotPart, animation, true)) then
1128 local destRot = part.endRot
1129 if animation.currentSpeed < 0 then
1130 destRot = part.startRot
1131 end
1132 if part.curRot == nil then
1133 local x,y,z = getRotation(part.node)
1134 part.curRot = {x,y,z}
1135 local invDuration = 1.0/math.max(durationToEnd, 0.001)
1136 part.speedRot = {(destRot[1]-x)*invDuration, (destRot[2]-y)*invDuration, (destRot[3]-z)*invDuration}
1137 end
1138 if AnimatedVehicle.setMovedLimitedValues3(part.curRot, destRot, part.speedRot, realDt) then
1139 setRotation(part.node, part.curRot[1], part.curRot[2], part.curRot[3])
1140 hasPartChanged = true
1141 end
1142 end
1143 if part.startTrans ~= nil and (durationToEnd > 0 or AnimatedVehicle.getNextPartIsPlaying(part.nextTransPart, part.prevTransPart, animation, true)) then
1144 local destTrans = part.endTrans
1145 if animation.currentSpeed < 0 then
1146 destTrans = part.startTrans
1147 end
1148 if part.curTrans == nil then
1149 local x,y,z = getTranslation(part.node)
1150 part.curTrans = {x,y,z}
1151 local invDuration = 1.0/math.max(durationToEnd, 0.001)
1152 part.speedTrans = {(destTrans[1]-x)*invDuration, (destTrans[2]-y)*invDuration, (destTrans[3]-z)*invDuration}
1153 end
1154 if AnimatedVehicle.setMovedLimitedValues3(part.curTrans, destTrans, part.speedTrans, realDt) then
1155 setTranslation(part.node, part.curTrans[1], part.curTrans[2], part.curTrans[3])
1156 hasPartChanged = true
1157 end
1158 end
1159 if part.startScale ~= nil and (durationToEnd > 0 or AnimatedVehicle.getNextPartIsPlaying(part.nextScalePart, part.prevScalePart, animation, true)) then
1160 local destScale = part.endScale
1161 if animation.currentSpeed < 0 then
1162 destScale = part.startScale
1163 end
1164 if part.curScale == nil then
1165 local x,y,z = getScale(part.node)
1166 part.curScale = {x,y,z}
1167 local invDuration = 1.0/math.max(durationToEnd, 0.001)
1168 part.speedScale = {(destScale[1]-x)*invDuration, (destScale[2]-y)*invDuration, (destScale[3]-z)*invDuration}
1169 end
1170 if AnimatedVehicle.setMovedLimitedValues3(part.curScale, destScale, part.speedScale, realDt) then
1171 setScale(part.node, part.curScale[1], part.curScale[2], part.curScale[3])
1172 hasPartChanged = true
1173 end
1174 end
1175 if part.shaderParameter ~= nil and (durationToEnd > 0 or AnimatedVehicle.getNextPartIsPlaying(part.nextShaderPart, part.prevShaderPart, animation, true)) then
1176 local destValues = part.shaderEndValues
1177 if animation.currentSpeed < 0 then
1178 destValues = part.shaderStartValues
1179 end
1180 if part.shaderCurValues == nil then
1181 local x,y,z,w = getShaderParameter(part.node, part.shaderParameter)
1182 part.shaderCurValues = {x,y,z,w}
1183 local invDuration = 1.0 / math.max(durationToEnd, 0.001)
1184 part.speedShader = {(destValues[1]-x)*invDuration, (destValues[2]-y)*invDuration, (destValues[3]-z)*invDuration, (destValues[4]-w)*invDuration}
1185 end
1186 if AnimatedVehicle.setMovedLimitedValues4(part.shaderCurValues, destValues, part.speedShader, realDt) then
1187 setShaderParameter(part.node, part.shaderParameter, part.shaderCurValues[1], part.shaderCurValues[2], part.shaderCurValues[3], part.shaderCurValues[4], false)
1188 hasPartChanged = true
1189 end
1190 end
1191
1192 if part.animationClip ~= nil and (durationToEnd > 0 or AnimatedVehicle.getNextPartIsPlaying(part.nextClipPart, part.prevClipPart, animation, true)) then
1193 local destValue = part.clipEndTime
1194 if animation.currentSpeed < 0 then
1195 destValue = part.clipStartTime
1196 end
1197 local forceUpdate = false
1198 if part.curClipTime == nil then
1199 local oldClipIndex = getAnimTrackAssignedClip(part.animationCharSet, 0)
1200 clearAnimTrackClip(part.animationCharSet, 0);
1201 assignAnimTrackClip(part.animationCharSet, 0, part.animationClipIndex);
1202
1203 part.curClipTime = part.clipStartTime
1204 if oldClipIndex == part.animationClipIndex then
1205 part.curClipTime = getAnimTrackTime(part.animationCharSet, 0)
1206 end
1207
1208 local invDuration = 1.0 / math.max(durationToEnd, 0.001)
1209 part.speedClip = (destValue-part.curClipTime)*invDuration
1210 forceUpdate = true
1211 end
1212 local newTime = AnimatedVehicle.getMovedLimitedValue(part.curClipTime, destValue, part.speedClip, realDt)
1213 if newTime ~= part.curClipTime or forceUpdate then
1214 part.curClipTime = newTime
1215
1216 enableAnimTrack(part.animationCharSet, 0);
1217 setAnimTrackTime(part.animationCharSet, 0, newTime, true);
1218 disableAnimTrack(part.animationCharSet, 0);
1219
1220 hasPartChanged = true
1221 end
1222 end
1223
1224 if part.visibility ~= nil then
1225 if part.curVisibility == nil then
1226 part.curVisibility = getVisibility(part.node)
1227 end
1228 if part.visibility ~= part.curVisibility then
1229 part.curVisibility = part.visibility
1230 setVisibility(part.node, part.visibility)
1231 hasPartChanged = true
1232 end
1233 end
1234
1235 if part.dependentAnim ~= nil and (durationToEnd > 0 or AnimatedVehicle.getNextPartIsPlaying(part.nextDependentAnimPart, part.prevDependentAnimPart, animation, true)) then
1236 if self:getAnimationExists(part.dependentAnim) then
1237 local destValue = part.dependentAnimEndTime
1238 if animation.currentSpeed < 0 then
1239 destValue = part.dependentAnimStartTime
1240 end
1241 local forceUpdate = false
1242 if part.curDependentAnimTime == nil then
1243 part.curDependentAnimTime = self:getAnimationTime(part.dependentAnim)
1244
1245 local invDuration = 1.0 / math.max(durationToEnd, 0.001)
1246 part.speedDependentAnim = (destValue-part.curDependentAnimTime)*invDuration
1247 forceUpdate = true
1248 end
1249 local newTime = AnimatedVehicle.getMovedLimitedValue(part.curDependentAnimTime, destValue, part.speedDependentAnim, realDt)
1250 if newTime ~= part.curDependentAnimTime or forceUpdate then
1251 part.curDependentAnimTime = newTime
1252 self:setAnimationTime(part.dependentAnim, newTime, true)
1253 hasPartChanged = true
1254 end
1255 else
1256 g_logManager:xmlWarning(self.configFileName, "Unable to find dependent animation '%s'", part.dependentAnim)
1257 end
1258 end
1259
1260 if self.isServer then
1261 if part.startRotMinLimit ~= nil and (durationToEnd > 0 or AnimatedVehicle.getNextPartIsPlaying(part.nextRotLimitPart, part.prevRotLimitPart, animation, true)) then
1262 local destRotMinLimit = part.endRotMinLimit
1263 local destRotMaxLimit = part.endRotMaxLimit
1264 if animation.currentSpeed < 0 then
1265 destRotMinLimit = part.startRotMinLimit
1266 destRotMaxLimit = part.startRotMaxLimit
1267 end
1268 if part.curRotMinLimit == nil then
1269 local x,y,z = unpack(part.componentJoint.rotMinLimit)
1270 part.curRotMinLimit = {x,y,z}
1271 local invDuration = 1.0/math.max(durationToEnd, 0.001)
1272 part.speedRotMinLimit = {(destRotMinLimit[1]-x)*invDuration, (destRotMinLimit[2]-y)*invDuration, (destRotMinLimit[3]-z)*invDuration}
1273 end
1274 if part.curRotMaxLimit == nil then
1275 local x,y,z = unpack(part.componentJoint.rotLimit)
1276 part.curRotMaxLimit = {x,y,z}
1277 local invDuration = 1.0/math.max(durationToEnd, 0.001)
1278 part.speedRotMaxLimit = {(destRotMaxLimit[1]-x)*invDuration, (destRotMaxLimit[2]-y)*invDuration, (destRotMaxLimit[3]-z)*invDuration}
1279 end
1280 for i=1, 3 do
1281 local newRotMinLimit = AnimatedVehicle.getMovedLimitedValue(part.curRotMinLimit[i], destRotMinLimit[i], part.speedRotMinLimit[i], realDt)
1282 local newRotMaxLimit = AnimatedVehicle.getMovedLimitedValue(part.curRotMaxLimit[i], destRotMaxLimit[i], part.speedRotMaxLimit[i], realDt)
1283 if newRotMinLimit ~= part.curRotMinLimit[i] or newRotMaxLimit ~= part.curRotMaxLimit[i] then
1284 part.curRotMinLimit[i] = newRotMinLimit
1285 part.curRotMaxLimit[i] = newRotMaxLimit
1286 self:setComponentJointRotLimit(part.componentJoint, i, newRotMinLimit, newRotMaxLimit)
1287 hasPartChanged = true
1288 end
1289 end
1290 end
1291 if part.startTransMinLimit ~= nil and (durationToEnd > 0 or AnimatedVehicle.getNextPartIsPlaying(part.nextTransLimitPart, part.prevTransLimitPart, animation, true)) then
1292 local destTransMinLimit = part.endTransMinLimit
1293 local destTransMaxLimit = part.endTransMaxLimit
1294 if animation.currentSpeed < 0 then
1295 destTransMinLimit = part.startTransMinLimit
1296 destTransMaxLimit = part.startTransMaxLimit
1297 end
1298 if part.curTransMinLimit == nil then
1299 local x,y,z = unpack(part.componentJoint.transMinLimit)
1300 part.curTransMinLimit = {x,y,z}
1301 local invDuration = 1.0/math.max(durationToEnd, 0.001)
1302 part.speedTransMinLimit = {(destTransMinLimit[1]-x)*invDuration, (destTransMinLimit[2]-y)*invDuration, (destTransMinLimit[3]-z)*invDuration}
1303 end
1304 if part.curTransMaxLimit == nil then
1305 local x,y,z = unpack(part.componentJoint.transLimit)
1306 part.curTransMaxLimit = {x,y,z}
1307 local invDuration = 1.0/math.max(durationToEnd, 0.001)
1308 part.speedTransMaxLimit = {(destTransMaxLimit[1]-x)*invDuration, (destTransMaxLimit[2]-y)*invDuration, (destTransMaxLimit[3]-z)*invDuration}
1309 end
1310 for i=1, 3 do
1311 local newTransMinLimit = AnimatedVehicle.getMovedLimitedValue(part.curTransMinLimit[i], destTransMinLimit[i], part.speedTransMinLimit[i], realDt)
1312 local newTransMaxLimit = AnimatedVehicle.getMovedLimitedValue(part.curTransMaxLimit[i], destTransMaxLimit[i], part.speedTransMaxLimit[i], realDt)
1313 if newTransMinLimit ~= part.curTransMinLimit[i] or newTransMaxLimit ~= part.curTransMaxLimit[i] then
1314 part.curTransMinLimit[i] = newTransMinLimit
1315 part.curTransMaxLimit[i] = newTransMaxLimit
1316 self:setComponentJointTransLimit(part.componentJoint, i, newTransMinLimit, newTransMaxLimit)
1317 hasPartChanged = true
1318 end
1319 end
1320 end
1321 end
1322
1323 return hasPartChanged
1324end

updateAnimations

Description
Update animations
Definition
updateAnimations(float dt)
Arguments
floatdttime since last call in ms
Code
951function AnimatedVehicle.updateAnimations(self, dt, allowRestart)
952 local spec = self.spec_animatedVehicle
953
954 for _, anim in pairs(spec.activeAnimations) do
955 local dtToUse, stopAnim = AnimatedVehicle.updateAnimationCurrentTime(self, anim, dt, anim.stopTime)
956 AnimatedVehicle.updateAnimation(self, anim, dtToUse, stopAnim, allowRestart)
957 end
958end