201 | function Crawlers:loadCrawlerFromConfigFile(crawler, xmlFilename, linkNode, isLeft) |
202 | xmlFilename = Utils.getFilename(xmlFilename, self.baseDirectory) |
203 | local xmlFile = loadXMLFile("TempConfig", xmlFilename) |
204 | if xmlFile ~= nil then |
205 | local filename = getXMLString(xmlFile, "crawler.file#name") |
206 | if filename ~= nil then |
207 | crawler.filename = filename |
208 | local i3dNode = g_i3DManager:loadSharedI3DFile(filename, self.baseDirectory, false, false, false) |
209 | if i3dNode ~= 0 then |
210 | local key = (isLeft and "leftNode") or "rightNode" |
211 | crawler.loadedCrawler = I3DUtil.indexToObject(i3dNode, getXMLString(xmlFile, "crawler.file#"..key)) |
212 | link(linkNode, crawler.loadedCrawler) |
213 | delete(i3dNode) |
214 | else |
215 | g_logManager:xmlWarning(self.configFileName, "Failed to find crawler in i3d file '%s'", filename, xmlFilename) |
216 | return false |
217 | end |
218 | else |
219 | g_logManager:xmlWarning(self.configFileName, "Failed to open crawler i3d file '%s' in '%s'", filename, xmlFilename) |
220 | return false |
221 | end |
222 | |
223 | crawler.scrollerNodes = {} |
224 | local j = 0 |
225 | while true do |
226 | local key = string.format("crawler.scrollerNodes.scrollerNode(%d)", j) |
227 | if not hasXMLProperty(xmlFile, key) then |
228 | break |
229 | end |
230 | |
231 | local entry = {} |
232 | entry.node = I3DUtil.indexToObject(crawler.loadedCrawler, getXMLString(xmlFile, key.."#node")) |
233 | if entry.node ~= nil then |
234 | entry.scrollSpeed = Utils.getNoNil(getXMLFloat(xmlFile, key.."#scrollSpeed"), 1) |
235 | entry.scrollLength = Utils.getNoNil(getXMLFloat(xmlFile, key.."#scrollLength"), 1) |
236 | entry.shaderParameterName = Utils.getNoNil(getXMLString(xmlFile, key.."#shaderParameterName"), "offsetUV") |
237 | entry.shaderParameterComponent = Utils.getNoNil(getXMLInt(xmlFile, key.."#shaderParameterComponent"), 1) |
238 | entry.scrollPosition = 0 |
239 | |
240 | if crawler.trackWidth ~= 1 then |
241 | if Utils.getNoNil(getXMLBool(xmlFile, key.."#isTrackPart"), true) then |
242 | setScale(entry.node, crawler.trackWidth, 1, 1) |
243 | end |
244 | end |
245 | |
246 | table.insert(crawler.scrollerNodes, entry) |
247 | end |
248 | j = j + 1 |
249 | end |
250 | |
251 | crawler.rotatingParts = {} |
252 | j = 0 |
253 | while true do |
254 | local key = string.format("crawler.rotatingParts.rotatingPart(%d)", j) |
255 | if not hasXMLProperty(xmlFile, key) then |
256 | break |
257 | end |
258 | |
259 | local entry = {} |
260 | entry.node = I3DUtil.indexToObject(crawler.loadedCrawler, getXMLString(xmlFile, key.."#node")) |
261 | if entry.node ~= nil then |
262 | entry.radius = getXMLFloat(xmlFile, key.."#radius") |
263 | entry.speedScale = getXMLFloat(xmlFile, key.."#speedScale") |
264 | if entry.speedScale == nil and entry.radius ~= nil then |
265 | entry.speedScale = 1.0 / entry.radius |
266 | end |
267 | |
268 | table.insert(crawler.rotatingParts, entry) |
269 | end |
270 | |
271 | j = j + 1 |
272 | end |
273 | |
274 | local applyColor = function(name, color) |
275 | j = 0 |
276 | while true do |
277 | local key = string.format("crawler.%s.%s(%d)", name.."s", name, j) |
278 | if not hasXMLProperty(xmlFile, key) then |
279 | break |
280 | end |
281 | |
282 | local node = I3DUtil.indexToObject(crawler.loadedCrawler, getXMLString(xmlFile, key.."#node")) |
283 | if node ~= nil then |
284 | local shaderParameter = getXMLString(xmlFile, key.."#shaderParameter") |
285 | if getHasShaderParameter(node, shaderParameter) then |
286 | local r, g, b, mat = unpack(color) |
287 | if mat == nil then |
288 | _, _, _, mat = getShaderParameter(node, shaderParameter) |
289 | end |
290 | I3DUtil.setShaderParameterRec(node, shaderParameter, r, g, b, mat, true) |
291 | else |
292 | g_logManager:xmlWarning(self.configFileName, "Missing shaderParameter '%s' on object '%s' in %s", shaderParameter, getName(node), key) |
293 | end |
294 | end |
295 | |
296 | j = j + 1 |
297 | end |
298 | end |
299 | |
300 | local rimColor = Utils.getNoNil(ConfigurationUtil.getColorByConfigId(self, "rimColor", self.configurations["rimColor"]), self.spec_wheels.rimColor) |
301 | if rimColor ~= nil then |
302 | crawler.rimColorNodes = applyColor("rimColorNode", rimColor) |
303 | end |
304 | |
305 | crawler.objectChanges = {} |
306 | ObjectChangeUtil.loadObjectChangeFromXML(xmlFile, "crawler", crawler.objectChanges, crawler.loadedCrawler, self) |
307 | ObjectChangeUtil.setObjectChanges(crawler.objectChanges, true) |
308 | |
309 | delete(xmlFile) |
310 | return true |
311 | end |
312 | |
313 | g_logManager:xmlWarning(self.configFileName, "Failed to open crawler config file '%s'", xmlFilename) |
314 | return false |
315 | end |
146 | function Crawlers:loadCrawlerFromXML(xmlFile, key, crawler) |
147 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, key.."#crawlerIndex", "Moved to external crawler config file") -- FS17 to FS19 |
148 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, key.."#length", "Moved to external crawler config file") -- FS17 to FS19 |
149 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, key.."#shaderParameterComponent", "Moved to external crawler config file") -- FS17 to FS19 |
150 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, key.."#shaderParameterName", "Moved to external crawler config file") -- FS17 to FS19 |
151 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, key.."#scrollLength", "Moved to external crawler config file") -- FS17 to FS19 |
152 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, key.."#scrollSpeed", "Moved to external crawler config file") -- FS17 to FS19 |
153 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, key.."#index", "Moved to external crawler config file") -- FS17 to FS19 |
154 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, key..".rotatingPart", "Moved to external crawler config file") -- FS17 to FS19 |
155 | |
156 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, key.."#linkIndex", key.."#linkNode") -- FS17 to FS19 |
157 | local linkNode = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, key.."#linkNode"), self.i3dMappings) |
158 | if linkNode == nil then |
159 | g_logManager:xmlWarning(self.configFileName, "Missing link node for crawler '%s'", key) |
160 | return false |
161 | end |
162 | |
163 | local isLeft = Utils.getNoNil(getXMLBool(xmlFile, key .. "#isLeft"), false) |
164 | crawler.trackWidth = Utils.getNoNil(getXMLFloat(xmlFile, key.."#trackWidth"), 1) |
165 | |
166 | local filename = getXMLString(xmlFile, key .. "#filename") |
167 | if not self:loadCrawlerFromConfigFile(crawler, filename, linkNode, isLeft) then |
168 | return false |
169 | end |
170 | |
171 | local offset = StringUtil.getVectorNFromString(getXMLString(xmlFile, key .. "#offset"), 3) |
172 | if offset ~= nil then |
173 | setTranslation(crawler.loadedCrawler, unpack(offset)) |
174 | end |
175 | |
176 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, key.."#speedRefWheel", key.."#wheelIndex") -- FS17 to FS19 |
177 | local wheelIndex = getXMLInt(xmlFile, key.."#wheelIndex") |
178 | if wheelIndex ~= nil then |
179 | local wheels = self:getWheels() |
180 | if wheels[wheelIndex] ~= nil then |
181 | crawler.wheel = wheels[wheelIndex] |
182 | if not crawler.wheel.isSynchronized then |
183 | g_logManager:xmlWarning(self.configFileName, "Wheel for crawler '%s' in not synchronized! It won't rotate on the client side.", key) |
184 | end |
185 | end |
186 | end |
187 | |
188 | XMLUtil.checkDeprecatedXMLElements(self.xmlFile, self.configFileName, key.."#speedRefNode", key.."#speedReferenceNode") -- FS17 to FS19 |
189 | crawler.speedReferenceNode = Utils.getNoNil(I3DUtil.indexToObject(self.components, getXMLString(xmlFile, key.."#speedReferenceNode"), self.i3dMappings), linkNode) |
190 | crawler.movedDistance = 0 |
191 | |
192 | crawler.fieldDirtMultiplier = Utils.getNoNil(getXMLInt(xmlFile, key.."#fieldDirtMultiplier"), 75) |
193 | crawler.streetDirtMultiplier = Utils.getNoNil(getXMLInt(xmlFile, key.."#streetDirtMultiplier"), -150) |
194 | crawler.minDirtPercentage = Utils.getNoNil(getXMLInt(xmlFile, key.."#minDirtPercentage"), 0.35) |
195 | |
196 | return true |
197 | end |
85 | function Crawlers:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected) |
86 | local spec = self.spec_crawlers |
87 | for _, crawler in pairs(spec.crawlers) do |
88 | crawler.movedDistance = 0 |
89 | |
90 | if crawler.wheel ~= nil then |
91 | local newX, _, _ = getRotation(crawler.wheel.driveNode) |
92 | if crawler.lastRotation == nil then |
93 | crawler.lastRotation = newX |
94 | end |
95 | |
96 | if newX - crawler.lastRotation < -math.pi then |
97 | crawler.lastRotation = crawler.lastRotation - 2*math.pi |
98 | elseif newX - crawler.lastRotation > math.pi then |
99 | crawler.lastRotation = crawler.lastRotation + 2*math.pi |
100 | end |
101 | |
102 | crawler.movedDistance = crawler.wheel.radius * (newX-crawler.lastRotation) |
103 | crawler.lastRotation = newX |
104 | else |
105 | local newX, newY, newZ = getWorldTranslation(crawler.speedReferenceNode) |
106 | if crawler.lastPosition == nil then |
107 | crawler.lastPosition = {newX, newY, newZ} |
108 | end |
109 | local dx, dy, dz = worldDirectionToLocal(crawler.speedReferenceNode, newX-crawler.lastPosition[1], newY-crawler.lastPosition[2], newZ-crawler.lastPosition[3]) |
110 | local movingDirection = 0 |
111 | if dz > 0.0001 then |
112 | movingDirection = 1 |
113 | elseif dz < -0.0001 then |
114 | movingDirection = -1 |
115 | end |
116 | crawler.movedDistance = MathUtil.vector3Length(dx, dy, dz) * movingDirection |
117 | crawler.lastPosition[1] = newX |
118 | crawler.lastPosition[2] = newY |
119 | crawler.lastPosition[3] = newZ |
120 | end |
121 | |
122 | for _, scrollerNode in pairs(crawler.scrollerNodes) do |
123 | scrollerNode.scrollPosition = (scrollerNode.scrollPosition + crawler.movedDistance*scrollerNode.scrollSpeed) % scrollerNode.scrollLength |
124 | if scrollerNode.shaderParameterComponent == 1 then |
125 | setShaderParameter(scrollerNode.node, scrollerNode.shaderParameterName, scrollerNode.scrollPosition,0,0,0, false) |
126 | else |
127 | setShaderParameter(scrollerNode.node, scrollerNode.shaderParameterName, 0,scrollerNode.scrollPosition,0,0, false) |
128 | end |
129 | end |
130 | |
131 | for _, rotatingPart in pairs(crawler.rotatingParts) do |
132 | if crawler.wheel ~= nil and rotatingPart.speedScale == nil then |
133 | -- rotate the part exactly like the wheel |
134 | local newX, _, _ = getRotation(crawler.wheel.driveNode) |
135 | setRotation(rotatingPart.node, newX, 0, 0) |
136 | elseif rotatingPart.speedScale ~= nil then |
137 | rotate(rotatingPart.node, rotatingPart.speedScale * crawler.movedDistance, 0, 0) |
138 | end |
139 | end |
140 | end |
141 | end |