125 | function SpeedRotatingParts:update(dt) |
126 | if self:getIsActive() then |
127 | for _, speedRotatingPart in pairs(self.speedRotatingParts) do |
128 | local isActive = self:getIsSpeedRotatingPartActive(speedRotatingPart); |
129 | if isActive or (speedRotatingPart.lastSpeed ~= 0 and not speedRotatingPart.stopIfNotActive) then |
130 | local speed = speedRotatingPart.lastSpeed; |
131 | local dir = speedRotatingPart.lastDir; |
132 | if isActive then |
133 | if speedRotatingPart.wheel ~= nil then |
134 | local x,_,_ = getRotation(speedRotatingPart.wheel.driveNode); |
135 | local deltaRot = x-speedRotatingPart.lastWheelXRot; |
136 | speed = math.abs(deltaRot); |
137 | dir = Utils.sign(deltaRot); |
138 | speedRotatingPart.lastWheelXRot = x; |
139 | elseif speedRotatingPart.speedReferenceNode ~= nil then |
140 | local newX, newY, newZ = getWorldTranslation(speedRotatingPart.speedReferenceNode); |
141 | if speedRotatingPart.lastPosition == nil then |
142 | speedRotatingPart.lastPosition = {newX, newY, newZ}; |
143 | end; |
144 | |
145 | local dx, dy, dz = worldDirectionToLocal(speedRotatingPart.speedReferenceNode, newX-speedRotatingPart.lastPosition[1], newY-speedRotatingPart.lastPosition[2], newZ-speedRotatingPart.lastPosition[3]); |
146 | speed = Utils.vector3Length(dx, dy, dz); |
147 | |
148 | if dz > 0.001 then |
149 | dir = 1; |
150 | elseif dz < -0.001 then |
151 | dir = -1; |
152 | else |
153 | dir = 0; |
154 | end; |
155 | |
156 | speedRotatingPart.lastPosition[1], speedRotatingPart.lastPosition[2], speedRotatingPart.lastPosition[3] = newX, newY, newZ; |
157 | else |
158 | speed = self.lastSpeedReal * dt; |
159 | dir = self.movingDirection; |
160 | end; |
161 | speedRotatingPart.brakeForce = speed * dt/speedRotatingPart.fadeOutTime; |
162 | else |
163 | speed = math.max(speed - speedRotatingPart.brakeForce, 0); |
164 | end; |
165 | |
166 | speedRotatingPart.lastSpeed = speed; |
167 | speedRotatingPart.lastDir = dir; |
168 | if speedRotatingPart.updateXDrive then |
169 | speedRotatingPart.xDrive = speedRotatingPart.xDrive + speed * dir * self:getSpeedRotatingPartDirection(speedRotatingPart) * speedRotatingPart.wheelScale |
170 | end |
171 | |
172 | if speedRotatingPart.versatileYRot then |
173 | if self.isServer and self:getLastSpeed(true) > speedRotatingPart.activationSpeed then |
174 | local posX, posY, posZ = localToLocal(speedRotatingPart.repr, speedRotatingPart.componentNode, 0,0,0); |
175 | speedRotatingPart.steeringAngle = Utils.getVersatileRotation(speedRotatingPart.repr, speedRotatingPart.componentNode, dt, posX, posY, posZ, speedRotatingPart.steeringAngle, speedRotatingPart.minYRot, speedRotatingPart.maxYRot); |
176 | if math.abs(speedRotatingPart.steeringAngleSent-speedRotatingPart.steeringAngle) > 0.1 then |
177 | speedRotatingPart.steeringAngleSent = speedRotatingPart.steeringAngle; |
178 | self:raiseDirtyFlags(self.speedRotatingPartsDirtyFlag); |
179 | end; |
180 | end; |
181 | else |
182 | if speedRotatingPart.componentNode ~= nil and speedRotatingPart.dirRefNode ~= nil and not speedRotatingPart.alignDirection then |
183 | speedRotatingPart.steeringAngle = Utils.getYRotationBetweenNodes(speedRotatingPart.componentNode, speedRotatingPart.dirRefNode); |
184 | local _,yTrans,_ = localToLocal(speedRotatingPart.driveNode, speedRotatingPart.wheel.driveNode, 0, 0, 0); |
185 | setTranslation(speedRotatingPart.driveNode, 0, yTrans, 0); |
186 | end; |
187 | |
188 | if speedRotatingPart.dirRefNode ~= nil and speedRotatingPart.alignDirection then |
189 | local upX, upY, upZ = localDirectionToWorld(speedRotatingPart.dirFrameNode, 0, 1, 0); |
190 | local dirX, dirY, dirZ = localDirectionToWorld(speedRotatingPart.dirRefNode, 0, 0, 1); |
191 | Utils.setWorldDirection(speedRotatingPart.repr, dirX, dirY, dirZ, upX, upY, upZ, 2); |
192 | if speedRotatingPart.wheel ~= nil and speedRotatingPart.useWheelReprTranslation then |
193 | local _,yTrans,_ = localToLocal(speedRotatingPart.wheel.driveNode, getParent(speedRotatingPart.repr), 0,0,0); |
194 | setTranslation(speedRotatingPart.repr, 0, yTrans, 0); |
195 | end; |
196 | end; |
197 | end; |
198 | |
199 | if speedRotatingPart.driveNode ~= nil then |
200 | if speedRotatingPart.repr == speedRotatingPart.driveNode then |
201 | setRotation(speedRotatingPart.repr, speedRotatingPart.xDrive, speedRotatingPart.steeringAngle, 0); |
202 | else |
203 | if not speedRotatingPart.alignDirection then |
204 | setRotation(speedRotatingPart.repr, 0, speedRotatingPart.steeringAngle, 0); |
205 | end; |
206 | setRotation(speedRotatingPart.driveNode, speedRotatingPart.xDrive, 0, 0); |
207 | end; |
208 | end; |
209 | |
210 | if speedRotatingPart.shaderNode ~= nil then |
211 | if speedRotatingPart.useShaderRotation then |
212 | setShaderParameter(speedRotatingPart.shaderNode, "offsetUV", 0, 0, speedRotatingPart.xDrive, 0, false); |
213 | else |
214 | local pos = (speedRotatingPart.xDrive % math.pi) / (2*math.pi); -- normalize rotation |
215 | setShaderParameter(speedRotatingPart.shaderNode, "offsetUV", pos*speedRotatingPart.scrollScale[1], pos*speedRotatingPart.scrollScale[2], 0, 0, false); |
216 | end; |
217 | end; |
218 | end; |
219 | end; |
220 | end; |
221 | end; |
235 | function SpeedRotatingParts:loadSpeedRotatingPartFromXML(superFunc, speedRotatingPart, xmlFile, key) |
236 | if superFunc ~= nil then |
237 | if not superFunc(self, speedRotatingPart, xmlFile, key) then |
238 | return false; |
239 | end; |
240 | end; |
241 | speedRotatingPart.repr = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#index")); |
242 | speedRotatingPart.shaderNode = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#shaderNode")); |
243 | if speedRotatingPart.shaderNode ~= nil then |
244 | speedRotatingPart.useShaderRotation = Utils.getNoNil(getXMLBool(xmlFile, key.."#useRotation"), true); |
245 | local scale = Utils.getNoNil(getXMLString(xmlFile, key.."#scrollScale"), "1 0"); |
246 | speedRotatingPart.scrollScale = Utils.getVectorNFromString(scale, 2); |
247 | end; |
248 | |
249 | if speedRotatingPart.repr == nil and speedRotatingPart.shaderNode == nil then |
250 | print("Warning: Invalid speedrotationpart '"..tostring(getXMLString(xmlFile, key.."#index")).."'! in '"..self.configFileName.."'"); |
251 | return false; |
252 | end; |
253 | speedRotatingPart.driveNode = Utils.getNoNil(Utils.indexToObject(self.components, getXMLString(xmlFile, key .. "#driveNode")), speedRotatingPart.repr); |
254 | |
255 | local componentIndex = getXMLInt(xmlFile, key.."#refComponentIndex"); |
256 | if componentIndex ~= nil and self.components[componentIndex] ~= nil then |
257 | speedRotatingPart.componentNode = self.components[componentIndex].node; |
258 | else |
259 | local node = Utils.getNoNil(speedRotatingPart.driveNode, speedRotatingPart.shaderNode) |
260 | speedRotatingPart.componentNode = self:getParentComponent(node); |
261 | end; |
262 | |
263 | |
264 | speedRotatingPart.xDrive = 0; |
265 | local wheelIndex = getXMLInt(xmlFile, key.."#wheelIndex"); |
266 | if wheelIndex ~= nil then |
267 | local wheel = self.wheels[wheelIndex + 1]; |
268 | if wheel == nil then |
269 | print("SpeedRotatingParts: Invalid wheel index ("..tostring(wheelIndex)..")"); |
270 | return false; |
271 | end; |
272 | speedRotatingPart.wheel = wheel; |
273 | speedRotatingPart.lastWheelXRot = 0; |
274 | end; |
275 | speedRotatingPart.dirRefNode = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#dirRefNode")); |
276 | speedRotatingPart.dirFrameNode = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#dirFrameNode")); |
277 | speedRotatingPart.alignDirection = Utils.getNoNil(getXMLBool(xmlFile, key .. "#alignDirection"), false); |
278 | speedRotatingPart.useWheelReprTranslation = Utils.getNoNil(getXMLBool(xmlFile, key .. "#useWheelReprTranslation"), true); |
279 | speedRotatingPart.updateXDrive = Utils.getNoNil(getXMLBool(xmlFile, key .. "#updateXDrive"), true); |
280 | |
281 | speedRotatingPart.versatileYRot = Utils.getNoNil(getXMLBool(xmlFile, key .. "#versatileYRot"), false); |
282 | if speedRotatingPart.versatileYRot and speedRotatingPart.repr == nil then |
283 | print("Warning: Versatile speedrotationpart does not support shaderNodes in '"..self.configFileName.."'"); |
284 | return false; |
285 | end; |
286 | |
287 | local minYRot = getXMLFloat(xmlFile, key .. "#minYRot"); |
288 | if minYRot ~= nil then |
289 | speedRotatingPart.minYRot = math.rad(minYRot); |
290 | end; |
291 | local maxYRot = getXMLFloat(xmlFile, key .. "#maxYRot"); |
292 | if maxYRot ~= nil then |
293 | speedRotatingPart.maxYRot = math.rad(maxYRot); |
294 | end; |
295 | speedRotatingPart.steeringAngle = 0; |
296 | speedRotatingPart.steeringAngleSent = 0; |
297 | |
298 | speedRotatingPart.wheelScale = getXMLFloat(xmlFile, key .. "#wheelScale"); |
299 | if speedRotatingPart.wheelScale == nil then |
300 | local baseRadius = 1.0; |
301 | local radius = 1.0; |
302 | if speedRotatingPart.wheel ~= nil then |
303 | baseRadius = speedRotatingPart.wheel.radius; |
304 | radius = speedRotatingPart.wheel.radius; |
305 | end; |
306 | speedRotatingPart.wheelScale = baseRadius / Utils.getNoNil(getXMLFloat(xmlFile, key.."#radius"), radius); |
307 | end; |
308 | |
309 | speedRotatingPart.wheelScaleBackup = speedRotatingPart.wheelScale; |
310 | |
311 | speedRotatingPart.onlyActiveWhenLowered = Utils.getNoNil(getXMLBool(xmlFile, key .. "#onlyActiveWhenLowered"), false); |
312 | speedRotatingPart.stopIfNotActive = Utils.getNoNil(getXMLBool(xmlFile, key .. "#stopIfNotActive"), false); |
313 | speedRotatingPart.fadeOutTime = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#fadeOutTime"), 3) * 1000 |
314 | speedRotatingPart.activationSpeed = Utils.getNoNil(getXMLFloat(xmlFile, key .. "#activationSpeed"), 1); |
315 | speedRotatingPart.speedReferenceNode = Utils.indexToObject(self.components, getXMLString(xmlFile, key.."#speedReferenceNode")); |
316 | if speedRotatingPart.speedReferenceNode ~= nil and speedRotatingPart.speedReferenceNode == speedRotatingPart.driveNode then |
317 | print("Warning: Ignoring speedRotationPart '"..key.."' because speedReferenceNode is identical with driveNode in '"..self.configFileName.."'. Need to be different!") |
318 | return false |
319 | end |
320 | speedRotatingPart.lastSpeed = 0; |
321 | speedRotatingPart.lastDir = 1; |
322 | |
323 | return true; |
324 | end; |