318 | function ConnectionHoseManager:adapterI3DFileLoaded(i3dNode, failedReason, args) |
319 | local hoseType = args.hoseType |
320 | local adapterName = args.adapterName |
321 | local xmlFile = args.xmlFile |
322 | local adapterKey = args.adapterKey |
323 | |
324 | if i3dNode ~= nil and i3dNode ~= 0 then |
325 | local node = xmlFile:getValue(adapterKey .. "#node", nil, i3dNode) |
326 | local hoseReferenceNode = getChildAt(node, 0) |
327 | unlink(node) |
328 | |
329 | local detachedNode = xmlFile:getValue(adapterKey .. "#detachedNode", nil, i3dNode) |
330 | if detachedNode ~= nil then |
331 | unlink(detachedNode) |
332 | end |
333 | |
334 | if hoseReferenceNode ~= 0 then |
335 | local entry = {} |
336 | entry.node = node |
337 | entry.detachedNode = detachedNode |
338 | entry.hoseReferenceNode = hoseReferenceNode |
339 | hoseType.adapters[adapterName:upper()] = entry |
340 | else |
341 | print(string.format("Warning: Missing hose reference node as child from adapter '%s' in connection type '%s'", adapterName, hoseType.name)) |
342 | end |
343 | |
344 | delete(i3dNode) |
345 | end |
346 | |
347 | xmlFile.references = xmlFile.references - 1 |
348 | if xmlFile.references == 0 then |
349 | self.xmlFiles[xmlFile] = nil |
350 | xmlFile:delete() |
351 | end |
352 | end |
268 | function ConnectionHoseManager:basicHoseI3DFileLoaded(i3dNode, failedReason, args) |
269 | local xmlFile = args.xmlFile |
270 | local hoseKey = args.hoseKey |
271 | |
272 | if i3dNode ~= nil and i3dNode ~= 0 then |
273 | local node = xmlFile:getValue(hoseKey .. "#node", nil, i3dNode) |
274 | if node ~= nil then |
275 | unlink(node) |
276 | local entry = {} |
277 | entry.node = node |
278 | entry.startStraightening = xmlFile:getValue(hoseKey.."#startStraightening", 2) |
279 | entry.endStraightening = xmlFile:getValue(hoseKey.."#endStraightening", 2) |
280 | entry.minCenterPointAngle = xmlFile:getValue(hoseKey.."#minCenterPointAngle", 90) |
281 | |
282 | local length = xmlFile:getValue(hoseKey.."#length") |
283 | if length == nil then |
284 | print(string.format("Warning: Missing length attribute in '%s'", hoseKey)) |
285 | end |
286 | |
287 | local realLength = xmlFile:getValue(hoseKey.."#realLength") |
288 | if realLength == nil then |
289 | print(string.format("Warning: Missing realLength attribute in '%s'", hoseKey)) |
290 | end |
291 | |
292 | local diameter = xmlFile:getValue(hoseKey.."#diameter") |
293 | if diameter == nil then |
294 | print(string.format("Warning: Missing diameter attribute in '%s'", hoseKey)) |
295 | end |
296 | |
297 | if length ~= nil and realLength ~= nil and diameter ~= nil then |
298 | entry.length = length |
299 | entry.realLength = realLength |
300 | entry.diameter = diameter |
301 | table.insert(self.basicHoses, entry) |
302 | end |
303 | end |
304 | |
305 | delete(i3dNode) |
306 | end |
307 | |
308 | xmlFile.references = xmlFile.references - 1 |
309 | if xmlFile.references == 0 then |
310 | self.xmlFiles[xmlFile] = nil |
311 | xmlFile:delete() |
312 | end |
313 | end |
582 | function ConnectionHoseManager:getClonedBasicHose(length, diameter) |
583 | -- look for the most exact diameter we can get |
584 | local minDiameterDiff = math.huge |
585 | local closestDiameter = math.huge |
586 | for _, hose in pairs(self.basicHoses) do |
587 | local diff = math.abs(hose.diameter-diameter) |
588 | if minDiameterDiff > diff then |
589 | minDiameterDiff = diff |
590 | closestDiameter = hose.diameter |
591 | end |
592 | end |
593 | |
594 | -- get all hoses with that diameter |
595 | local foundHoses = {} |
596 | for _, hose in pairs(self.basicHoses) do |
597 | local diff = math.abs(hose.diameter-closestDiameter) |
598 | if diff <= 0.0001 then |
599 | table.insert(foundHoses, hose) |
600 | end |
601 | end |
602 | |
603 | --look for the hose with the most exact length |
604 | local minLengthDiff = math.huge |
605 | local foundHose |
606 | for _, hose in pairs(foundHoses) do |
607 | local diff = math.abs(hose.length-length) |
608 | if minLengthDiff > diff then |
609 | minLengthDiff = diff |
610 | foundHose = hose |
611 | end |
612 | end |
613 | |
614 | if foundHose ~= nil then |
615 | return clone(foundHose.node, true), foundHose.realLength, foundHose.startStraightening, foundHose.endStraightening, foundHose.minCenterPointAngle, closestDiameter |
616 | end |
617 | end |
536 | function ConnectionHoseManager:getClonedHoseNode(typeName, hoseName, length, diameter, color, customEnvironment) |
537 | local hoseType = self:getHoseTypeByName(typeName, customEnvironment) |
538 | if hoseType ~= nil then |
539 | local material = self:getHoseMaterialByName(hoseType, hoseName, customEnvironment) |
540 | if material ~= nil then |
541 | local hoseNodeClone, realLength, startStraightening, endStraightening, minCenterPointAngle, closestDiameter = self:getClonedBasicHose(length, diameter) |
542 | if hoseNodeClone ~= nil then |
543 | local mat = getMaterial(material.materialNode, 0) |
544 | setMaterial(hoseNodeClone, mat, 0) |
545 | |
546 | if color ~= nil or material.defaultColor ~= nil then |
547 | for i=1, 8 do |
548 | local parameter = string.format("colorMat%d", i-1) |
549 | if getHasShaderParameter(hoseNodeClone, parameter) then |
550 | local r, g, b, _ = unpack(color or material.defaultColor) |
551 | local _, _, _, w = getShaderParameter(hoseNodeClone, parameter) |
552 | setShaderParameter(hoseNodeClone, parameter, r, g, b, w, false) |
553 | end |
554 | end |
555 | end |
556 | |
557 | local _, _, z, w = getShaderParameter(hoseNodeClone, "lengthAndDiameter") |
558 | setShaderParameter(hoseNodeClone, "lengthAndDiameter", realLength, diameter/closestDiameter, z, w, false) |
559 | |
560 | local scaleFactorX, scaleFactorY = 1, 1 |
561 | if material.uvScale ~= nil then |
562 | scaleFactorX, scaleFactorY = material.uvScale[1], material.uvScale[2] |
563 | end |
564 | |
565 | local y |
566 | _, y, z, w = getShaderParameter(hoseNodeClone, "uvScale") |
567 | setShaderParameter(hoseNodeClone, "uvScale", length/realLength*scaleFactorX, y*scaleFactorY, z, w, false) |
568 | |
569 | if material.uvOffset ~= nil then |
570 | _, _, z, w = getShaderParameter(hoseNodeClone, "offsetUV") |
571 | setShaderParameter(hoseNodeClone, "offsetUV", material.uvOffset[1], material.uvOffset[2], z, w, false) |
572 | end |
573 | |
574 | return hoseNodeClone, startStraightening, endStraightening, minCenterPointAngle |
575 | end |
576 | end |
577 | end |
578 | end |
621 | function ConnectionHoseManager:linkSocketToNode(socketName, node, customEnvironment, socketColor) |
622 | local socket = self:getSocketByName(socketName, customEnvironment) |
623 | if socket ~= nil and node ~= nil then |
624 | local linkedSocket = {} |
625 | linkedSocket.node = clone(socket.node, true) |
626 | |
627 | linkedSocket.referenceNode = I3DUtil.indexToObject(linkedSocket.node, socket.referenceNode) |
628 | |
629 | linkedSocket.caps = {} |
630 | for _, cap in ipairs(socket.caps) do |
631 | local clonedCap = {} |
632 | for i, v in pairs(cap) do |
633 | clonedCap[i] = v |
634 | end |
635 | |
636 | clonedCap.node = I3DUtil.indexToObject(linkedSocket.node, clonedCap.node) |
637 | table.insert(linkedSocket.caps, clonedCap) |
638 | end |
639 | |
640 | if socket.shaderParameterColor ~= nil and socketColor ~= nil and #socketColor >= 3 then |
641 | I3DUtil.setShaderParameterRec(linkedSocket.node, socket.shaderParameterColor, socketColor[1], socketColor[2], socketColor[3], nil) |
642 | end |
643 | |
644 | link(node, linkedSocket.node) |
645 | self:closeSocket(linkedSocket) |
646 | |
647 | return linkedSocket |
648 | end |
649 | end |
108 | function ConnectionHoseManager:loadConnectionHosesFromXML(xmlFilename, customEnvironment, baseDirectory) |
109 | Logging.info("Loading ConnectionHoses from '%s'", xmlFilename) |
110 | |
111 | local xmlFile = XMLFile.load("TempHoses", xmlFilename, ConnectionHoseManager.xmlSchema) |
112 | if xmlFile ~= nil then |
113 | self.xmlFiles[xmlFile] = true |
114 | xmlFile.references = 1 |
115 | --load basic hoses |
116 | local i = 0 |
117 | while true do |
118 | local hoseKey = string.format("connectionHoses.basicHoses.basicHose(%d)", i) |
119 | if not xmlFile:hasProperty(hoseKey) then |
120 | break |
121 | end |
122 | |
123 | local filename = xmlFile:getValue(hoseKey.."#filename") |
124 | if filename ~= nil then |
125 | xmlFile.references = xmlFile.references + 1 |
126 | filename = Utils.getFilename(filename, baseDirectory) |
127 | |
128 | local arguments = { |
129 | xmlFile = xmlFile, |
130 | hoseKey = hoseKey |
131 | } |
132 | local sharedLoadRequestId = g_i3DManager:loadSharedI3DFileAsync(filename, false, false, self.basicHoseI3DFileLoaded, self, arguments) |
133 | table.insert(self.sharedLoadRequestIds, sharedLoadRequestId) |
134 | end |
135 | |
136 | i = i + 1 |
137 | end |
138 | |
139 | --load hose types |
140 | i = 0 |
141 | while true do |
142 | local key = string.format("connectionHoses.connectionHoseTypes.connectionHoseType(%d)", i) |
143 | if not xmlFile:hasProperty(key) then |
144 | break |
145 | end |
146 | |
147 | local name = xmlFile:getValue(key.."#name") |
148 | if name ~= nil then |
149 | local hoseType |
150 | if self.typeByName[name:upper()] ~= nil then |
151 | hoseType = self.typeByName[name:upper()] |
152 | else |
153 | if customEnvironment ~= nil then |
154 | name = customEnvironment .. "." .. name |
155 | end |
156 | |
157 | hoseType = {} |
158 | hoseType.name = name |
159 | hoseType.adapters = {} |
160 | hoseType.hoses = {} |
161 | |
162 | self.typeByName[name:upper()] = hoseType |
163 | end |
164 | |
165 | local j = 0 |
166 | while true do |
167 | local adapterKey = string.format("%s.adapter(%d)", key, j) |
168 | if not xmlFile:hasProperty(adapterKey) then |
169 | break |
170 | end |
171 | |
172 | local adapterName = xmlFile:getValue(adapterKey.."#name", "DEFAULT") |
173 | if customEnvironment ~= nil then |
174 | adapterName = customEnvironment .. "." .. adapterName |
175 | end |
176 | |
177 | local filename = xmlFile:getValue(adapterKey.."#filename") |
178 | if filename ~= nil then |
179 | xmlFile.references = xmlFile.references + 1 |
180 | filename = Utils.getFilename(filename, baseDirectory) |
181 | |
182 | local arguments = { |
183 | hoseType = hoseType, |
184 | adapterName = adapterName, |
185 | xmlFile = xmlFile, |
186 | adapterKey = adapterKey |
187 | } |
188 | local sharedLoadRequestId = g_i3DManager:loadSharedI3DFileAsync(filename, false, false, self.adapterI3DFileLoaded, self, arguments) |
189 | table.insert(self.sharedLoadRequestIds, sharedLoadRequestId) |
190 | end |
191 | j = j + 1 |
192 | end |
193 | |
194 | hoseType.hoses = {} |
195 | j = 0 |
196 | while true do |
197 | local hoseKey = string.format("%s.material(%d)", key, j) |
198 | if not xmlFile:hasProperty(hoseKey) then |
199 | break |
200 | end |
201 | |
202 | local hoseName = xmlFile:getValue(hoseKey.."#name", "DEFAULT") |
203 | if customEnvironment ~= nil then |
204 | hoseName = customEnvironment .. "." .. hoseName |
205 | end |
206 | |
207 | local filename = xmlFile:getValue(hoseKey.."#filename") |
208 | if filename ~= nil then |
209 | xmlFile.references = xmlFile.references + 1 |
210 | filename = Utils.getFilename(filename, baseDirectory) |
211 | |
212 | local arguments = { |
213 | hoseType = hoseType, |
214 | hoseName = hoseName, |
215 | xmlFile = xmlFile, |
216 | hoseKey = hoseKey |
217 | } |
218 | local sharedLoadRequestId = g_i3DManager:loadSharedI3DFileAsync(filename, false, false, self.materialI3DFileLoaded, self, arguments) |
219 | table.insert(self.sharedLoadRequestIds, sharedLoadRequestId) |
220 | end |
221 | j = j + 1 |
222 | end |
223 | end |
224 | |
225 | i = i + 1 |
226 | end |
227 | |
228 | --load basic hoses |
229 | i = 0 |
230 | while true do |
231 | local socketKey = string.format("connectionHoses.sockets.socket(%d)", i) |
232 | if not xmlFile:hasProperty(socketKey) then |
233 | break |
234 | end |
235 | |
236 | local name = xmlFile:getValue(socketKey.."#name") |
237 | if customEnvironment ~= nil then |
238 | name = customEnvironment .. "." .. name |
239 | end |
240 | |
241 | local filename = xmlFile:getValue(socketKey.."#filename") |
242 | if name ~= nil and filename ~= nil then |
243 | xmlFile.references = xmlFile.references + 1 |
244 | filename = Utils.getFilename(filename, baseDirectory) |
245 | |
246 | local arguments = { |
247 | name = name, |
248 | xmlFile = xmlFile, |
249 | socketKey = socketKey |
250 | } |
251 | local sharedLoadRequestId = g_i3DManager:loadSharedI3DFileAsync(filename, false, false, self.socketI3DFileLoaded, self, arguments) |
252 | table.insert(self.sharedLoadRequestIds, sharedLoadRequestId) |
253 | end |
254 | i = i + 1 |
255 | end |
256 | |
257 | xmlFile.references = xmlFile.references - 1 |
258 | if xmlFile.references == 0 then |
259 | self.xmlFiles[xmlFile] = nil |
260 | xmlFile:delete() |
261 | end |
262 | end |
263 | end |
357 | function ConnectionHoseManager:materialI3DFileLoaded(i3dNode, failedReason, args) |
358 | local hoseType = args.hoseType |
359 | local hoseName = args.hoseName |
360 | local xmlFile = args.xmlFile |
361 | local hoseKey = args.hoseKey |
362 | |
363 | if i3dNode ~= nil and i3dNode ~= 0 then |
364 | local materialNode = xmlFile:getValue(hoseKey .. "#materialNode", nil, i3dNode) |
365 | unlink(materialNode) |
366 | if materialNode ~= nil then |
367 | local entry = {} |
368 | entry.materialNode = materialNode |
369 | entry.defaultColor = xmlFile:getValue(hoseKey .. "#defaultColor", nil, true) |
370 | entry.uvOffset = xmlFile:getValue(hoseKey .. "#uvOffset", nil, true) |
371 | entry.uvScale = xmlFile:getValue(hoseKey .. "#uvScale", nil, true) |
372 | |
373 | hoseType.hoses[hoseName:upper()] = entry |
374 | end |
375 | |
376 | delete(i3dNode) |
377 | end |
378 | |
379 | xmlFile.references = xmlFile.references - 1 |
380 | if xmlFile.references == 0 then |
381 | self.xmlFiles[xmlFile] = nil |
382 | xmlFile:delete() |
383 | end |
384 | end |
695 | function ConnectionHoseManager:registerXMLPaths(schema) |
696 | schema:register(XMLValueType.STRING, "connectionHoses.basicHoses.basicHose(?)#filename", "I3d filename") |
697 | schema:register(XMLValueType.NODE_INDEX, "connectionHoses.basicHoses.basicHose(?)#node", "Path to hose node") |
698 | schema:register(XMLValueType.FLOAT, "connectionHoses.basicHoses.basicHose(?)#startStraightening", "Straightening factor on start side", 2) |
699 | schema:register(XMLValueType.FLOAT, "connectionHoses.basicHoses.basicHose(?)#endStraightening", "Straightening factor on end side", 2) |
700 | schema:register(XMLValueType.ANGLE, "connectionHoses.basicHoses.basicHose(?)#minCenterPointAngle", "Min. bending angle at the center of the hose", 90) |
701 | schema:register(XMLValueType.FLOAT, "connectionHoses.basicHoses.basicHose(?)#length", "Reference length of hose") |
702 | schema:register(XMLValueType.FLOAT, "connectionHoses.basicHoses.basicHose(?)#realLength", "Real length of hose in i3d") |
703 | schema:register(XMLValueType.FLOAT, "connectionHoses.basicHoses.basicHose(?)#diameter", "Diameter of hose") |
704 | |
705 | schema:register(XMLValueType.STRING, "connectionHoses.connectionHoseTypes.connectionHoseType(?)#name", "Name of type") |
706 | schema:register(XMLValueType.STRING, "connectionHoses.connectionHoseTypes.connectionHoseType(?).adapter(?)#name", "Name of adapter") |
707 | schema:register(XMLValueType.STRING, "connectionHoses.connectionHoseTypes.connectionHoseType(?).adapter(?)#filename", "Path to i3d file") |
708 | schema:register(XMLValueType.NODE_INDEX, "connectionHoses.connectionHoseTypes.connectionHoseType(?).adapter(?)#node", "Adapter node in i3d file") |
709 | schema:register(XMLValueType.NODE_INDEX, "connectionHoses.connectionHoseTypes.connectionHoseType(?).adapter(?)#detachedNode", "Detached adapter node in i3d file") |
710 | |
711 | schema:register(XMLValueType.STRING, "connectionHoses.connectionHoseTypes.connectionHoseType(?).material(?)#name", "Name of material") |
712 | schema:register(XMLValueType.STRING, "connectionHoses.connectionHoseTypes.connectionHoseType(?).material(?)#filename", "Path to i3d file") |
713 | schema:register(XMLValueType.NODE_INDEX, "connectionHoses.connectionHoseTypes.connectionHoseType(?).material(?)#materialNode", "Material node in i3d file") |
714 | schema:register(XMLValueType.VECTOR_4, "connectionHoses.connectionHoseTypes.connectionHoseType(?).material(?)#defaultColor", "Default color") |
715 | schema:register(XMLValueType.VECTOR_2, "connectionHoses.connectionHoseTypes.connectionHoseType(?).material(?)#uvOffset", "UV offset") |
716 | schema:register(XMLValueType.VECTOR_2, "connectionHoses.connectionHoseTypes.connectionHoseType(?).material(?)#uvScale", "UV scale") |
717 | |
718 | schema:register(XMLValueType.STRING, "connectionHoses.sockets.socket(?)#name", "Socket name") |
719 | schema:register(XMLValueType.STRING, "connectionHoses.sockets.socket(?)#filename", "Path to i3d file") |
720 | schema:register(XMLValueType.NODE_INDEX, "connectionHoses.sockets.socket(?)#node", "Socket node in i3d") |
721 | schema:register(XMLValueType.STRING, "connectionHoses.sockets.socket(?)#referenceNode", "Index of reference node inside socket") |
722 | schema:register(XMLValueType.STRING, "connectionHoses.sockets.socket(?)#shaderParameterColor", "Name of coloring shader parameter") |
723 | schema:register(XMLValueType.STRING, "connectionHoses.sockets.socket(?).cap(?)#node", "Index of cap node inside socket") |
724 | schema:register(XMLValueType.VECTOR_ROT, "connectionHoses.sockets.socket(?).cap(?)#openedRotation", "Opened rotation") |
725 | schema:register(XMLValueType.VECTOR_ROT, "connectionHoses.sockets.socket(?).cap(?)#closedRotation", "Closed rotation") |
726 | schema:register(XMLValueType.BOOL, "connectionHoses.sockets.socket(?).cap(?)#openedVisibility", "Opened visibility", true) |
727 | schema:register(XMLValueType.BOOL, "connectionHoses.sockets.socket(?).cap(?)#closedVisibility", "Closed visibility", true) |
728 | end |
389 | function ConnectionHoseManager:socketI3DFileLoaded(i3dNode, failedReason, args) |
390 | local name = args.name |
391 | local xmlFile = args.xmlFile |
392 | local socketKey = args.socketKey |
393 | |
394 | if i3dNode ~= nil and i3dNode ~= 0 then |
395 | local node = xmlFile:getValue(socketKey .. "#node", nil, i3dNode) |
396 | |
397 | if node ~= nil then |
398 | unlink(node) |
399 | local entry = {} |
400 | entry.node = node |
401 | |
402 | entry.referenceNode = xmlFile:getValue(socketKey .. "#referenceNode") |
403 | entry.shaderParameterColor = xmlFile:getValue(socketKey .. "#shaderParameterColor") |
404 | |
405 | entry.caps = {} |
406 | |
407 | local j = 0 |
408 | while true do |
409 | local capKey = string.format(socketKey .. ".cap(%d)", j) |
410 | if not xmlFile:hasProperty(capKey) then |
411 | break |
412 | end |
413 | |
414 | local cap = {} |
415 | cap.node = xmlFile:getValue(capKey .. "#node") |
416 | if cap.node ~= nil then |
417 | cap.openedRotation = xmlFile:getValue(capKey .. "#openedRotation", nil, true) |
418 | cap.closedRotation = xmlFile:getValue(capKey .. "#closedRotation", nil, true) |
419 | cap.openedVisibility = xmlFile:getValue(capKey .. "#openedVisibility", true) |
420 | cap.closedVisibility = xmlFile:getValue(capKey .. "#closedVisibility", true) |
421 | |
422 | table.insert(entry.caps, cap) |
423 | end |
424 | |
425 | j = j + 1 |
426 | end |
427 | |
428 | if self.sockets[name:upper()] == nil then |
429 | self.sockets[name:upper()] = entry |
430 | else |
431 | Logging.xmlError(xmlFile, "Socket '%s' already exists", name) |
432 | end |
433 | end |
434 | |
435 | delete(i3dNode) |
436 | end |
437 | |
438 | xmlFile.references = xmlFile.references - 1 |
439 | if xmlFile.references == 0 then |
440 | self.xmlFiles[xmlFile] = nil |
441 | xmlFile:delete() |
442 | end |
443 | end |
62 | function ConnectionHoseManager:unloadMapData() |
63 | for _, entry in ipairs(self.basicHoses) do |
64 | delete(entry.node) |
65 | end |
66 | for _, hoseType in pairs(self.typeByName) do |
67 | for _, adapter in pairs(hoseType.adapters) do |
68 | delete(adapter.node) |
69 | delete(adapter.detachedNode) |
70 | end |
71 | for _, hose in pairs(hoseType.hoses) do |
72 | delete(hose.materialNode) |
73 | end |
74 | end |
75 | for _, entry in pairs(self.sockets) do |
76 | delete(entry.node) |
77 | end |
78 | |
79 | for i=1, #self.sharedLoadRequestIds do |
80 | local sharedLoadRequestId = self.sharedLoadRequestIds[i] |
81 | g_i3DManager:releaseSharedI3DFile(sharedLoadRequestId) |
82 | end |
83 | |
84 | for xmlFile, _ in pairs(self.xmlFiles) do |
85 | self.xmlFiles[xmlFile] = nil |
86 | xmlFile:delete() |
87 | end |
88 | |
89 | ConnectionHoseManager:superClass().unloadMapData(self) |
90 | end |