Script v1.7.1.0
- AI
- Animals
- Contracts
- Debug
- Economy
- Effects
- Events
- Farms
- GUI
- Handtools
- I3d
- Materials
- Misc
- Objects
- Placeables
- Player
- Shop
- Sounds
- Specializations
- AIConveyorBelt
- AIImplement
- AIVehicle
- AnimatedVehicle
- ArticulatedAxis
- Attachable
- AttacherJointControl
- AttacherJoints
- BaleGrab
- BaleLoader
- Baler
- BaleWrapper
- BaseMaterial
- BunkerSiloCompacter
- BunkerSiloInteractor
- BuyableBale
- CCTDrivable
- Combine
- ConnectionHoses
- ConveyorBelt
- Cover
- CrabSteering
- Crawlers
- Cultivator
- Cutter
- Cylindered
- CylinderedFoldable
- Dashboard
- Dischargeable
- Drivable
- DynamicallyLoadedParts
- DynamicMountAttacher
- Enterable
- FertilizingCultivator
- FertilizingSowingMachine
- FillTriggerVehicle
- FillUnit
- FillVolume
- Foldable
- FoliageBending
- ForageWagon
- FrontloaderAttacher
- FruitPreparer
- GroundAdjustedNodes
- GroundReference
- Honk
- HookLiftContainer
- HookLiftTrailer
- IKChains
- JigglingParts
- Leveler
- Lights
- LivestockTrailer
- Locomotive
- LogGrab
- ManureBarrel
- MixerWagon
- Motorized
- Mountable
- Mower
- Pickup
- Pipe
- Plow
- PowerConsumer
- PowerTakeOffs
- RandomlyMovingParts
- ReceivingHopper
- ReverseDriving
- Rideable
- RidgeMarker
- Roller
- Ropes
- SemiTrailerFront
- Shovel
- SlopeCompensation
- SmartAttach
- SowingMachine
- SpeedRotatingParts
- SplineVehicle
- Sprayer
- StrawBlower
- StumpCutter
- Suspensions
- Tedder
- TensionBeltObject
- TensionBelts
- TipOccluder
- Trailer
- TreePlanter
- TreeSaw
- TurnOnVehicle
- Washable
- WaterTrailer
- Wearable
- Weeder
- Wheels
- Windrower
- Wipers
- WoodCrusher
- WoodHarvester
- WorkArea
- WorkMode
- WorkParticles
- Triggers
- Utils
- Vehicles
- Weather
Engine v1.7.1.0
- AI
- Animation
- Camera
- Entity
- Fillplanes
- General
- I3D
- Input
- Lighting
- Math
- Network
- Node
- Overlays
- Particle System
- Physics
- Rendering
- Scenegraph
- Shape
- Sound
- Spline
- String
- Terrain Detail
- Text Rendering
- Tire Track
- XML
- general
Foundation Reference
AnimatedVehicle
DescriptionSpecialization adding support for (keyframe)animations to vehiclesFunctions
- animPartSorter
- animPartSorterReverse
- findCurrentPartIndex
- getAnimationDuration
- getAnimationExists
- getAnimationTime
- getDurationToEndOfPart
- getIsAnimationPlaying
- getIsSpeedRotatingPartActive
- getIsWorkAreaActive
- getMovedLimitedValue
- getNextPartIsPlaying
- getNumOfActiveAnimations
- getRealAnimationTime
- initializeAnimationPart
- initializeAnimationPartAttribute
- initializeAnimationParts
- loadAnimation
- loadAnimationPart
- loadSpeedRotatingPartFromXML
- loadWorkAreaFromXML
- onDelete
- onLoad
- onPostLoad
- onUpdate
- playAnimation
- postInitializeAnimationPart
- prerequisitesPresent
- registerEventListeners
- registerEvents
- registerFunctions
- registerOverwrittenFunctions
- resetAnimationPartValues
- resetAnimationValues
- setAnimationSpeed
- setAnimationStopTime
- setAnimationTime
- setMovedLimitedValues3
- setMovedLimitedValues4
- setRealAnimationTime
- stopAnimation
- updateAnimation
- updateAnimationByName
- updateAnimationCurrentTime
- updateAnimationPart
- updateAnimations
animPartSorter
DescriptionReturns true if anim parts are in the right orderDefinition
animPartSorter(table a, table b)Arguments
table | a | part a to check |
table | b | part b to check |
boolean | rightOrder | returns true if parts are in right order |
809 | function 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 |
816 | end |
animPartSorterReverse
DescriptionReturns true if anim parts are in the reverse right orderDefinition
animPartSorterReverse(table a, table b)Arguments
table | a | part a to check |
table | b | part b to check |
boolean | rightOrder | returns true if parts are in reverse right order |
823 | function 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 |
832 | end |
findCurrentPartIndex
DescriptionFind current playing partDefinition
findCurrentPartIndex(table animation)Arguments
table | animation | animation |
integer | index | of current playing part |
893 | function 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 |
913 | end |
getAnimationDuration
DescriptionReturns duration of animationDefinition
getAnimationDuration(string name)Arguments
string | name | name of animation |
float | duration | duration in ms |
625 | function 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 |
633 | end |
getAnimationExists
DescriptionReturns true if animation exitsDefinition
getAnimationExists(string name)Arguments
string | name | name of animation |
boolean | exists | animation axists |
531 | function AnimatedVehicle:getAnimationExists(name) |
532 | local spec = self.spec_animatedVehicle |
533 | |
534 | return spec.animations[name] ~= nil |
535 | end |
getAnimationTime
DescriptionReturns animation timeDefinition
getAnimationTime(string name)Arguments
string | name | name of animation |
float | animTime | animation time [0..1] |
593 | function 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 |
601 | end |
getDurationToEndOfPart
DescriptionReturns duration to the end of current partDefinition
getDurationToEndOfPart(table part, table anim)Arguments
table | part | part |
table | anim | animation |
float | duration | duration to end of current part |
920 | function 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 |
926 | end |
getIsAnimationPlaying
DescriptionReturns true if animation is playingDefinition
getIsAnimationPlaying(string name)Arguments
string | name | name of animation |
boolean | isPlaying | animation is playing |
541 | function AnimatedVehicle:getIsAnimationPlaying(name) |
542 | local spec = self.spec_animatedVehicle |
543 | |
544 | return spec.activeAnimations[name] ~= nil |
545 | end |
getIsSpeedRotatingPartActive
DescriptionDefinitiongetIsSpeedRotatingPartActive()Code
716 | function 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) |
731 | end |
getIsWorkAreaActive
DescriptionDefinitiongetIsWorkAreaActive()Code
745 | function 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) |
754 | end |
getMovedLimitedValue
DescriptionReturns moved limited valueDefinition
getMovedLimitedValue(float currentValue, float destValue, float speed, float dt)Arguments
float | currentValue | current value |
float | destValue | dest value |
float | speed | speed |
float | dt | time since last call in ms |
float | ret | limited value |
841 | function 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 |
851 | end |
getNextPartIsPlaying
DescriptionGet next part is playingDefinition
getNextPartIsPlaying(table nextPart, table prevPart, table anim, boolean default)Arguments
table | nextPart | next part |
table | prevPart | previous part |
table | anim | animation |
boolean | default | default value |
boolean | isPlaying | next part is playing |
935 | function 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 |
946 | end |
getNumOfActiveAnimations
DescriptionDefinitiongetNumOfActiveAnimations()Code
1328 | function AnimatedVehicle:getNumOfActiveAnimations() |
1329 | return self.spec_animatedVehicle.numActiveAnimations |
1330 | end |
getRealAnimationTime
DescriptionReturns real animation timeDefinition
getRealAnimationTime(string name)Arguments
string | name | name of animation |
float | animTime | real animation time in ms |
551 | function 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 |
559 | end |
initializeAnimationPart
DescriptionInitialize part of animationDefinition
initializeAnimationPart(table part)Arguments
table | part | part |
381 | function 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 |
401 | end |
initializeAnimationPartAttribute
DescriptionDefinitioninitializeAnimationPartAttribute()Code
758 | function 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 |
802 | end |
initializeAnimationParts
DescriptionInitialize parts of animationDefinition
initializeAnimationParts(table animation)Arguments
table | animation | animation |
366 | function 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 |
376 | end |
loadAnimation
DescriptionDefinitionloadAnimation()Code
143 | function 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 |
192 | end |
loadAnimationPart
DescriptionDefinitionloadAnimationPart()Code
196 | function 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 |
361 | end |
loadSpeedRotatingPartFromXML
DescriptionDefinitionloadSpeedRotatingPartFromXML()Code
702 | function 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 |
712 | end |
loadWorkAreaFromXML
DescriptionDefinitionloadWorkAreaFromXML()Code
735 | function 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) |
741 | end |
onDelete
DescriptionCalled on deletingDefinition
onDelete()Code
119 | function 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 |
126 | end |
onLoad
DescriptionCalled on loadingDefinition
onLoad(table savegame)Arguments
table | savegame | savegame |
79 | function 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 |
102 | end |
onPostLoad
DescriptionCalled after loadingDefinition
onPostLoad(table savegame)Arguments
table | savegame | savegame |
107 | function 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 |
115 | end |
onUpdate
DescriptionCalled on updateDefinition
onUpdate(float dt, boolean isActiveForInput, boolean isSelected)Arguments
float | dt | time since last call in ms |
boolean | isActiveForInput | true if vehicle is active for input |
boolean | isSelected | true if vehicle is selected |
133 | function 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 |
139 | end |
playAnimation
DescriptionPlay animationDefinition
playAnimation(string name, float speed, float animTime, boolean noEventSend)Arguments
string | name | name of animation |
float | speed | speed |
float | animTime | start time |
boolean | noEventSend | no event send |
446 | function 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 |
494 | end |
postInitializeAnimationPart
DescriptionPost 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
table | part | part |
406 | function 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 |
437 | end |
prerequisitesPresent
DescriptionChecks if all prerequisite specializations are loadedDefinition
prerequisitesPresent(table specializations)Arguments
table | specializations | specializations |
boolean | hasPrerequisite | true if all prerequisite specializations are loaded |
20 | function AnimatedVehicle.prerequisitesPresent(specializations) |
21 | return true |
22 | end |
registerEventListeners
DescriptionDefinitionregisterEventListeners()Code
69 | function 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) |
74 | end |
registerEvents
DescriptionDefinitionregisterEvents()Code
26 | function AnimatedVehicle.registerEvents(vehicleType) |
27 | SpecializationUtil.registerEvent(vehicleType, "onPlayAnimation") |
28 | SpecializationUtil.registerEvent(vehicleType, "onStartAnimation") |
29 | SpecializationUtil.registerEvent(vehicleType, "onFinishAnimation") |
30 | SpecializationUtil.registerEvent(vehicleType, "onStopAnimation") |
31 | end |
registerFunctions
DescriptionDefinitionregisterFunctions()Code
35 | function 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) |
56 | end |
registerOverwrittenFunctions
DescriptionDefinitionregisterOverwrittenFunctions()Code
60 | function 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) |
65 | end |
resetAnimationPartValues
DescriptionResets animation partDefinition
resetAnimationPartValues(table part)Arguments
table | part | part to reset |
681 | function 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 |
698 | end |
resetAnimationValues
DescriptionResets animation valuesDefinition
resetAnimationValues(table animation)Arguments
table | animation | animation |
671 | function AnimatedVehicle:resetAnimationValues(animation) |
672 | AnimatedVehicle.findCurrentPartIndex(animation) |
673 | for _, part in ipairs(animation.parts) do |
674 | self:resetAnimationPartValues(part) |
675 | end |
676 | end |
setAnimationSpeed
DescriptionSets speed of animationDefinition
setAnimationSpeed(string name, float speed)Arguments
string | name | name of animation |
float | speed | speed |
639 | function 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 |
653 | end |
setAnimationStopTime
DescriptionSets animation stop timeDefinition
setAnimationStopTime(string name, float stopTime)Arguments
string | name | name of animation |
float | stopTime | stop time [0..1] |
659 | function 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 |
666 | end |
setAnimationTime
DescriptionSet animation timeDefinition
setAnimationTime(string name, float animTime, boolean update)Arguments
string | name | name of animation |
float | animTime | animation time [0..1] |
boolean | update | update animation |
608 | function 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 |
619 | end |
setMovedLimitedValues3
DescriptionSets moved limited values (3)Definition
setMovedLimitedValues3(table currentValues, table destValues, table speeds, float dt)Arguments
table | currentValues | current values |
table | destValues | dest values |
table | speeds | speeds |
float | dt | time since last call in ms |
859 | function 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 |
869 | end |
setMovedLimitedValues4
DescriptionSets moved limited values (4)Definition
setMovedLimitedValues4(table currentValues, table destValues, table speeds, float dt)Arguments
table | currentValues | current values |
table | destValues | dest values |
table | speeds | speeds |
float | dt | time since last call in ms |
877 | function 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 |
887 | end |
setRealAnimationTime
DescriptionSet animation real timeDefinition
setRealAnimationTime(string name, float animTime, boolean update)Arguments
string | name | name of animation |
float | animTime | real animation time in ms |
boolean | update | update animation |
566 | function 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 |
587 | end |
stopAnimation
DescriptionStop animationDefinition
stopAnimation(string name, boolean noEventSend)Arguments
string | name | name of animation |
boolean | noEventSend | no event send |
500 | function 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 |
525 | end |
updateAnimation
DescriptionUpdate animationDefinition
updateAnimation(table anim, float dtToUse, boolean stopAnimation)Arguments
table | anim | animation |
float | dtToUse | dt to use |
boolean | stopAnimation | stop animation |
1010 | function 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 |
1116 | end |
updateAnimationByName
DescriptionUpdate animation by nameDefinition
updateAnimationByName(string animName, float dt)Arguments
string | animName | name of animation to update |
float | dt | time since last call in ms |
964 | function 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 |
972 | end |
updateAnimationCurrentTime
DescriptionUpdate current animation timeDefinition
updateAnimationCurrentTime(table anim, float dt, float stopTime)Arguments
table | anim | animation |
float | dt | time since last call in ms |
float | stopTime | stop time |
float | dtToUse | dt to use |
boolean | stopAnimation | stop animation |
981 | function 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 |
1003 | end |
updateAnimationPart
DescriptionUpdate animation partDefinition
updateAnimationPart(table anim, table part, float durationToEnd, float dtToUse, float realDt)Arguments
table | anim | animation |
table | part | part |
float | durationToEnd | duration to end |
float | dtToUse | dt to use |
float | realDt | real dt |
1125 | function 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 |
1324 | end |
updateAnimations
DescriptionUpdate animationsDefinition
updateAnimations(float dt)Arguments
float | dt | time since last call in ms |
951 | function 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 |
958 | end |