LUADOC - Farming Simulator 19

Script v1.7.1.0

Engine v1.7.1.0

Foundation Reference

ConnectionHoses

Description
Specialization for loading materials from a vehicle config xml and applying them to given nodes
Functions

addHoseTargetNodes

Description
Definition
addHoseTargetNodes()
Code
447function ConnectionHoses:addHoseTargetNodes(xmlFile, key)
448 local spec = self.spec_connectionHoses
449
450 local i = 0
451 while true do
452 local targetKey = string.format("%s(%d)", key, i)
453 if not hasXMLProperty(xmlFile, targetKey) then
454 break
455 end
456 local entry = {}
457 if self:loadHoseTargetNode(xmlFile, targetKey, entry) then
458 table.insert(spec.targetNodes, entry)
459 entry.index = #spec.targetNodes
460
461 if spec.targetNodesByType[entry.type] == nil then
462 spec.targetNodesByType[entry.type] = {}
463 end
464
465 table.insert(spec.targetNodesByType[entry.type], entry)
466 end
467 i = i + 1
468 end
469
470 -- return the index of the last added target
471 if i > 0 then
472 return #spec.targetNodes
473 end
474end

addHoseToDelayedMountings

Description
Definition
addHoseToDelayedMountings()
Code
976function ConnectionHoses:addHoseToDelayedMountings(sourceObject, sourceHose, targetObject, targetHose)
977 local spec = self.spec_connectionHoses
978
979 local toolConnectionHose = spec.targetNodeToToolConnection[targetHose.index]
980 if toolConnectionHose ~= nil and toolConnectionHose.delayedMounting == nil then
981 toolConnectionHose.delayedMounting = {sourceObject=sourceObject, sourceHose=sourceHose, targetObject=targetObject, targetHose=targetHose}
982
983 local rootVehicle = self:getRootVehicle()
984 rootVehicle:retryHoseSkipNodeConnections(true, sourceObject)
985 end
986end

connectHose

Description
Definition
connectHose()
Code
745function ConnectionHoses:connectHose(sourceHose, targetObject, targetHose, updateToolConnections)
746 local spec = self.spec_connectionHoses
747
748 local doConnect = false
749 if updateToolConnections ~= nil and not updateToolConnections then
750 doConnect = true
751 else
752 if targetObject:updateToolConnectionHose(self, sourceHose, targetObject, targetHose, true) then
753 doConnect = true
754 else
755 -- on tool connections we wait until both ends are connected to a tool and then we connect the hoses
756 targetObject:addHoseToDelayedMountings(self, sourceHose, targetObject, targetHose)
757 end
758 end
759
760 if doConnect then
761 targetHose.connectedObject = self
762 sourceHose.connectedObject = targetObject
763
764 sourceHose.targetHose = targetHose
765
766 local node, referenceNode
767 if sourceHose.adapterName ~= nil then
768 if sourceHose.adapterName ~= "NONE" then
769 node, referenceNode = g_connectionHoseManager:getClonedAdapterNode(targetHose.type, sourceHose.adapterName)
770 end
771 elseif targetHose.adapterName ~= "NONE" then
772 node, referenceNode = g_connectionHoseManager:getClonedAdapterNode(targetHose.type, targetHose.adapterName)
773 end
774
775 if node ~= nil then
776 link(g_connectionHoseManager:getSocketTarget(targetHose.socket, targetHose.node), node)
777 setTranslation(node, 0,0,0)
778 setRotation(node, 0,0,0)
779 targetObject:addAllSubWashableNodes(node)
780
781 targetHose.adapter.node = node
782 targetHose.adapter.refNode = referenceNode
783 targetHose.adapter.isLinked = true
784 end
785
786 sourceHose.targetNode = targetHose.adapter.refNode
787
788 setVisibility(sourceHose.hoseNode, true)
789 setShaderParameter(sourceHose.hoseNode, "cv0", 0, 0, -sourceHose.startStraightening, 1, false)
790 sourceHose.endStraightening = sourceHose.endStraighteningBase * targetHose.straighteningFactor
791
792 ObjectChangeUtil.setObjectChanges(targetHose.objectChanges, true)
793 ObjectChangeUtil.setObjectChanges(sourceHose.objectChanges, true)
794
795 g_connectionHoseManager:openSocket(targetHose.socket)
796
797 -- if we don't use a adapter to connect we use the dirt of the attacher vehicle to have a seamless transition
798 if targetHose.adapter == nil or targetHose.adapter.node == targetHose.adapter.refNode then
799 self:removeAllSubWashableNodes(sourceHose.hoseNode)
800 targetObject:addAllSubWashableNodes(sourceHose.hoseNode)
801 end
802
803 table.insert(spec.updateableHoses, sourceHose)
804 self:updateConnectionHose(sourceHose, 0)
805 end
806end

connectHosesToAttacherVehicle

Description
Definition
connectHosesToAttacherVehicle()
Code
1060function ConnectionHoses:connectHosesToAttacherVehicle(attacherVehicle, inputJointDescIndex, jointDescIndex, updateToolConnections, excludeVehicle)
1061 if attacherVehicle.getConnectionTarget ~= nil then
1062 local hoses = self:getConnectionHosesByInputAttacherJoint(inputJointDescIndex)
1063 for _, hose in ipairs(hoses) do
1064 if not self:getIsConnectionHoseUsed(hose) then
1065 local firstValidTarget, isSkipNode = attacherVehicle:getConnectionTarget(jointDescIndex, hose.type)
1066 if firstValidTarget ~= nil then
1067 if not isSkipNode then
1068 self:connectHose(hose, attacherVehicle, firstValidTarget, updateToolConnections)
1069 else
1070 self:connectHoseToSkipNode(hose, attacherVehicle, firstValidTarget)
1071 end
1072 end
1073 end
1074 end
1075
1076 --try to connect the hoses of attached implements, maybe the connection is now valid since we got another skip node
1077 self:retryHoseSkipNodeConnections(updateToolConnections, excludeVehicle)
1078 end
1079end

connectHoseToSkipNode

Description
Definition
connectHoseToSkipNode()
Code
990function ConnectionHoses:connectHoseToSkipNode(sourceHose, targetObject, skipNode, childHose, childVehicle)
991 local spec = self.spec_connectionHoses
992
993 skipNode.connectedObject = self
994 sourceHose.connectedObject = targetObject
995
996 sourceHose.targetHose = skipNode
997 sourceHose.targetNode = skipNode.node
998
999 setVisibility(sourceHose.hoseNode, true)
1000 setShaderParameter(sourceHose.hoseNode, "cv0", 0, 0, -sourceHose.startStraightening, 1, false)
1001
1002 ObjectChangeUtil.setObjectChanges(sourceHose.objectChanges, true)
1003
1004 self:addAllSubWashableNodes(sourceHose.hoseNode)
1005
1006 sourceHose.childVehicle = childVehicle
1007 sourceHose.childHose = childHose
1008
1009 if self.getAttacherVehicle ~= nil then
1010 local attacherVehicle1 = self:getAttacherVehicle()
1011 if attacherVehicle1.getAttacherVehicle ~= nil then
1012 local attacherVehicle2 = attacherVehicle1:getAttacherVehicle()
1013 if attacherVehicle2 ~= nil then
1014
1015 local attacherJointIndex = attacherVehicle2:getAttacherJointIndexFromObject(attacherVehicle1)
1016 local implement = attacherVehicle1:getImplementFromAttacherJointIndex(attacherJointIndex)
1017
1018 if implement.inputJointDescIndex == skipNode.inputAttacherJointIndex then
1019 local firstValidTarget, isSkipNode = attacherVehicle2:getConnectionTarget(attacherJointIndex, skipNode.type)
1020 if firstValidTarget ~= nil then
1021 local hose = attacherVehicle1:getClonedSkipHoseNode(sourceHose, skipNode)
1022 if not isSkipNode then
1023 attacherVehicle1:connectHose(hose, attacherVehicle2, firstValidTarget)
1024 else
1025 attacherVehicle1:connectHoseToSkipNode(hose, attacherVehicle2, firstValidTarget, sourceHose, attacherVehicle1)
1026 end
1027
1028 if skipNode.parentHose ~= nil then
1029 delete(skipNode.parentHose.hoseNode)
1030 end
1031 skipNode.parentVehicle = attacherVehicle1
1032 skipNode.parentHose = hose
1033
1034 sourceHose.parentVehicle = attacherVehicle1
1035 sourceHose.parentHose = hose
1036
1037 hose.childVehicle = self
1038 hose.childHose = sourceHose
1039 else
1040 --same hose is still active, just update the relations
1041 if skipNode.parentHose ~= nil then
1042 sourceHose.parentVehicle = skipNode.parentVehicle
1043 sourceHose.parentHose = skipNode.parentHose
1044
1045 sourceHose.parentHose.childVehicle = self
1046 sourceHose.parentHose.childHose = sourceHose
1047 end
1048 end
1049 end
1050 end
1051 end
1052 end
1053
1054 table.insert(spec.updateableHoses, sourceHose)
1055 self:updateConnectionHose(sourceHose, 0)
1056end

disconnectHose

Description
Definition
disconnectHose()
Code
810function ConnectionHoses:disconnectHose(hose)
811 local spec = self.spec_connectionHoses
812 local target = hose.targetHose
813 if target ~= nil then
814 hose.connectedObject:updateToolConnectionHose(self, hose, hose.connectedObject, target, false)
815
816 local hoseHasSkipNodeTarget = target.isSkipNode ~= nil and target.isSkipNode
817 local hoseIsFromSkipNodeTarget = hose.isClonedSkipNodeHose ~= nil and hose.isClonedSkipNodeHose
818 if hoseHasSkipNodeTarget or hoseIsFromSkipNodeTarget then
819 --remove all skip node connections recursively in both directions
820 if hose.parentVehicle ~= nil and hose.parentHose ~= nil then
821 hose.parentHose.childVehicle = nil
822 hose.parentHose.childHose = nil
823 hose.parentVehicle:disconnectHose(hose.parentHose)
824 end
825
826 if hose.childVehicle ~= nil and hose.childHose ~= nil then
827 hose.childHose.parentVehicle = nil
828 hose.childHose.parentHose = nil
829 hose.childVehicle:disconnectHose(hose.childHose)
830 end
831
832 setVisibility(hose.hoseNode, false)
833 target.parentHose = nil
834 else
835 if target.adapter.isLinked ~= nil and target.adapter.isLinked then
836 hose.connectedObject:removeAllSubWashableNodes(target.adapter.node)
837 delete(target.adapter.node)
838
839 target.adapter.node = target.node
840 target.adapter.refNode = target.node
841 target.adapter.isLinked = false
842 end
843
844 setVisibility(hose.hoseNode, false)
845 ObjectChangeUtil.setObjectChanges(target.objectChanges, false)
846 ObjectChangeUtil.setObjectChanges(hose.objectChanges, false)
847
848 g_connectionHoseManager:closeSocket(target.socket)
849 end
850
851 if target.adapter == nil or target.adapter.node == target.adapter.refNode then
852 hose.connectedObject:removeAllSubWashableNodes(hose.hoseNode)
853 self:addAllSubWashableNodes(hose.hoseNode)
854 end
855
856 target.connectedObject = nil
857 hose.connectedObject = nil
858 hose.targetHose = nil
859
860 ListUtil.removeElementFromList(spec.updateableHoses, hose)
861 end
862end

getCenterPointAngle

Description
Definition
getCenterPointAngle()
Code
339function ConnectionHoses:getCenterPointAngle(node, cX, cY, cZ, eX, eY, eZ, useWorldSpace)
340 local lengthStartToCenter = MathUtil.vector3Length(cX, cY, cZ)
341 local lengthCenterToEnd = math.abs(MathUtil.vector3Length(cX-eX, cY-eY, cZ-eZ))
342
343 local _, sY, _ = getWorldTranslation(node)
344 if useWorldSpace then
345 _, cY, _ = localToWorld(node, cX, cY, cZ)
346 _, eY, _ = localToWorld(node, eX, eY, eZ)
347 else
348 sY = 0
349 end
350
351 local lengthStartToCenter2 = sY-cY
352 local lengthCenterToEnd2 = eY-cY
353
354 local angle1 = math.acos(lengthStartToCenter2/lengthStartToCenter)
355 local angle2 = math.acos(lengthCenterToEnd2/lengthCenterToEnd)
356
357 return angle1, angle2
358end

getCenterPointAngleRegulation

Description
Definition
getCenterPointAngleRegulation()
Code
362function ConnectionHoses:getCenterPointAngleRegulation(node, cX, cY, cZ, eX, eY, eZ, angle1, angle2, targetAngle, useWorldSpace)
363 local sX, sY, sZ = getWorldTranslation(node)
364 if useWorldSpace then
365 cX, _, cZ = localToWorld(node, cX, cY, cZ)
366 eX, _, eZ = localToWorld(node, eX, eY, eZ)
367 else
368 sX, sY, sZ = 0, 0, 0
369 end
370
371 local startCenterLength = MathUtil.vector2Length(sX-cX, sZ-cZ)
372 local centerEndLength = MathUtil.vector2Length(eX-cX, eZ-cZ)
373
374 local pct = angle1/(angle1+angle2)
375 local alpha = math.pi * 0.5 - (pct * targetAngle)
376
377 local newY1 = math.tan(alpha) * startCenterLength
378 local newY2 = math.tan(alpha) * centerEndLength
379
380 local newY = (newY1 + newY2) / 2
381
382 if useWorldSpace then
383 return worldToLocal(node, cX, sY-newY, cZ)
384 else
385 return cX, sY-newY, cZ
386 end
387end

getClonedSkipHoseNode

Description
Definition
getClonedSkipHoseNode()
Code
613function ConnectionHoses:getClonedSkipHoseNode(sourceHose, skipNode)
614 local clonedHose = {}
615
616 clonedHose.isClonedSkipNodeHose = true
617
618 clonedHose.type = sourceHose.type
619 clonedHose.hoseType = sourceHose.hoseType
620 clonedHose.node = skipNode.node
621
622 clonedHose.component = self:getParentComponent(skipNode.node)
623 clonedHose.lastVelY = 0
624 clonedHose.lastVelZ = 0
625 clonedHose.dampingRange = 0.05
626 clonedHose.dampingFactor = 50
627
628 clonedHose.minDeltaYComponent = self:getParentComponent(skipNode.node)
629 clonedHose.minDeltaY = math.huge
630
631 clonedHose.length = skipNode.length or sourceHose.length
632 clonedHose.diameter = sourceHose.diameter
633 clonedHose.isTwoPointHose = skipNode.isTwoPointHose
634
635 clonedHose.color = sourceHose.color
636
637 local hose, startStraightening, endStraightening, minCenterPointAngle = g_connectionHoseManager:getClonedHoseNode(clonedHose.type, clonedHose.hoseType, clonedHose.length, clonedHose.diameter, clonedHose.color)
638
639 if hose ~= nil then
640 link(clonedHose.node, hose)
641 setTranslation(hose, 0, 0, 0)
642 setRotation(hose, 0, 0, 0)
643
644 clonedHose.hoseNode = hose
645 clonedHose.startStraightening = startStraightening
646 clonedHose.endStraightening = endStraightening
647 clonedHose.endStraighteningBase = endStraightening
648 clonedHose.minCenterPointAngle = minCenterPointAngle
649
650 setVisibility(clonedHose.hoseNode, false)
651 else
652 g_logManager:xmlWarning(self.configFileName, "Unable to find connection hose with length '%.2f' and diameter '%.2f' in '%s'", clonedHose.length, clonedHose.diameter, "skipHoseClone")
653 return false
654 end
655
656 clonedHose.objectChanges = {}
657
658 return clonedHose
659end

getConnectionHosesByInputAttacherJoint

Description
Definition
getConnectionHosesByInputAttacherJoint()
Code
733function ConnectionHoses:getConnectionHosesByInputAttacherJoint(inputJointDescIndex)
734 local spec = self.spec_connectionHoses
735
736 if spec.hoseNodesByInputAttacher[inputJointDescIndex] ~= nil then
737 return spec.hoseNodesByInputAttacher[inputJointDescIndex]
738 end
739
740 return {}
741end

getConnectionTarget

Description
Definition
getConnectionTarget()
Code
663function ConnectionHoses:getConnectionTarget(attacherJointIndex, type, excludeToolConnections)
664 local spec = self.spec_connectionHoses
665 if #spec.targetNodes == 0 and #spec.hoseSkipNodes == 0 then
666 return nil
667 end
668
669 local nodes = spec.targetNodesByType[type]
670 if nodes ~= nil then
671 for _, node in ipairs(nodes) do
672 if node.attacherJointIndices[attacherJointIndex] ~= nil then
673 if not self:getIsConnectionTargetUsed(node) then
674 local toolConnectionHose = spec.targetNodeToToolConnection[node.index]
675 if toolConnectionHose ~= nil and excludeToolConnections ~= nil and excludeToolConnections then
676 if toolConnectionHose.delayedMounting == nil then
677 return nil
678 end
679 end
680
681 return node, false
682 end
683 end
684 end
685 end
686
687 nodes = spec.hoseSkipNodeByType[type]
688 if nodes ~= nil then
689 for _, node in ipairs(nodes) do
690 if self:getIsSkipNodeAvailable(node) then
691 return node, true
692 end
693 end
694 end
695
696 return nil
697end

getIsConnectionHoseUsed

Description
Definition
getIsConnectionHoseUsed()
Code
707function ConnectionHoses:getIsConnectionHoseUsed(desc)
708 return desc.connectedObject ~= nil
709end

getIsConnectionTargetUsed

Description
Definition
getIsConnectionTargetUsed()
Code
701function ConnectionHoses:getIsConnectionTargetUsed(desc)
702 return desc.connectedObject ~= nil
703end

getIsSkipNodeAvailable

Description
Definition
getIsSkipNodeAvailable()
Code
713function ConnectionHoses:getIsSkipNodeAvailable(skipNode)
714 if self.getAttacherVehicle == nil then
715 return false
716 end
717
718 local attacherVehicle = self:getAttacherVehicle()
719 if attacherVehicle ~= nil then
720 local attacherJointIndex = attacherVehicle:getAttacherJointIndexFromObject(self)
721 local implement = attacherVehicle:getImplementFromAttacherJointIndex(attacherJointIndex)
722
723 if implement.inputJointDescIndex == skipNode.inputAttacherJointIndex then
724 return attacherVehicle:getConnectionTarget(attacherJointIndex, skipNode.type, true) ~= nil or skipNode.parentHose ~= nil
725 end
726 end
727
728 return false
729end

loadHoseNode

Description
Definition
loadHoseNode()
Code
524function ConnectionHoses:loadHoseNode(xmlFile, hoseKey, entry)
525 local inputAttacherJointIndices = {StringUtil.getVectorFromString(getXMLString(xmlFile, hoseKey .. "#inputAttacherJointIndices"))}
526 entry.inputAttacherJointIndices = {}
527 for _, v in ipairs(inputAttacherJointIndices) do
528 entry.inputAttacherJointIndices[v] = v
529 end
530
531 entry.type = getXMLString(xmlFile, hoseKey .. "#type")
532 if entry.type == nil then
533 g_logManager:xmlWarning(self.configFileName, "Missing type attribute in '%s'", hoseKey)
534 return false
535 end
536
537 entry.hoseType = Utils.getNoNil(getXMLString(xmlFile, hoseKey .. "#hoseType"), "DEFAULT")
538 entry.node = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, hoseKey .. "#node"), self.i3dMappings)
539 if entry.node == nil then
540 g_logManager:xmlWarning(self.configFileName, "Missing node for connection hose '%s'", hoseKey)
541 return false
542 end
543
544 entry.isTwoPointHose = Utils.getNoNil(getXMLBool(xmlFile, hoseKey .. "#isTwoPointHose"), false)
545 entry.isWorldSpaceHose = Utils.getNoNil(getXMLBool(xmlFile, hoseKey .. "#isWorldSpaceHose"), true)
546
547 entry.component = self:getParentComponent(entry.node)
548 entry.lastVelY = 0
549 entry.lastVelZ = 0
550 entry.dampingRange = Utils.getNoNil(getXMLFloat(xmlFile, hoseKey .. "#dampingRange"), 0.05)
551 entry.dampingFactor = Utils.getNoNil(getXMLFloat(xmlFile, hoseKey .. "#dampingFactor"), 50)
552
553 entry.length = Utils.getNoNil(getXMLFloat(xmlFile, hoseKey .. "#length"), 3)
554 entry.diameter = Utils.getNoNil(getXMLFloat(xmlFile, hoseKey .. "#diameter"), 0.02)
555 entry.straighteningFactor = Utils.getNoNil(getXMLFloat(xmlFile, hoseKey .. "#straighteningFactor"), 1)
556 entry.minCenterPointAngle = Utils.getNoNilRad(getXMLFloat(xmlFile, hoseKey .. "#minCenterPointAngle"), nil)
557
558 entry.minCenterPointOffset = StringUtil.getVectorNFromString(getXMLString(xmlFile, hoseKey .. "#minCenterPointOffset"), 3)
559 entry.maxCenterPointOffset = StringUtil.getVectorNFromString(getXMLString(xmlFile, hoseKey .. "#maxCenterPointOffset"), 3)
560
561 if entry.minCenterPointOffset ~= nil and entry.maxCenterPointOffset ~= nil then
562 for i=1, 3 do
563 if entry.minCenterPointOffset[i] == 0 then
564 entry.minCenterPointOffset[i] = -math.huge
565 end
566
567 if entry.maxCenterPointOffset[i] == 0 then
568 entry.maxCenterPointOffset[i] = math.huge
569 end
570 end
571 end
572
573 entry.minDeltaY = Utils.getNoNil(getXMLFloat(xmlFile, hoseKey .. "#minDeltaY"), math.huge)
574 entry.minDeltaYComponent = Utils.getNoNil(I3DUtil.indexToObject(self.components, getXMLString(xmlFile, hoseKey .. "#minDeltaYComponent"), self.i3dMappings), entry.component)
575
576 local colorValueStr = getXMLString(xmlFile, hoseKey.."#color")
577 entry.color = g_brandColorManager:getBrandColorByName(colorValueStr)
578 if entry.color == nil then
579 entry.color = StringUtil.getVectorNFromString(colorValueStr, 4)
580 end
581
582 local hose, startStraightening, endStraightening, minCenterPointAngle = g_connectionHoseManager:getClonedHoseNode(entry.type, entry.hoseType, entry.length, entry.diameter, entry.color)
583
584 if hose ~= nil then
585 link(entry.node, hose)
586 setTranslation(hose, 0, 0, 0)
587 setRotation(hose, 0, 0, 0)
588
589 entry.hoseNode = hose
590 entry.startStraightening = startStraightening * entry.straighteningFactor
591 entry.endStraightening = endStraightening
592 entry.endStraighteningBase = endStraightening
593 entry.minCenterPointAngle = entry.minCenterPointAngle or minCenterPointAngle
594
595 setVisibility(entry.hoseNode, false)
596 else
597 g_logManager:xmlWarning(self.configFileName, "Unable to find connection hose with length '%.2f' and diameter '%.2f' in '%s'", entry.length, entry.diameter, hoseKey)
598 return false
599 end
600
601 entry.adapterName = getXMLString(xmlFile, hoseKey .. "#adapterType")
602
603 entry.objectChanges = {}
604 ObjectChangeUtil.loadObjectChangeFromXML(self.xmlFile, hoseKey, entry.objectChanges, self.components, self)
605 ObjectChangeUtil.setObjectChanges(entry.objectChanges, false)
606
607 return true
608end

loadHoseSkipNode

Description
Definition
loadHoseSkipNode()
Code
391function ConnectionHoses:loadHoseSkipNode(xmlFile, targetKey, entry)
392 entry.node = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, targetKey .. "#node"), self.i3dMappings)
393
394 if entry.node == nil then
395 g_logManager:xmlWarning(self.configFileName, "Missing node for hose skip node '%s'", targetKey)
396 return false
397 end
398
399 entry.inputAttacherJointIndex = Utils.getNoNil(getXMLInt(xmlFile, targetKey .. "#inputAttacherJointIndex"), 1)
400 entry.attacherJointIndex = Utils.getNoNil(getXMLInt(xmlFile, targetKey .. "#attacherJointIndex"), 1)
401
402 entry.type = getXMLString(xmlFile, targetKey .. "#type")
403
404 if entry.type == nil then
405 g_logManager:xmlWarning(self.configFileName, "Missing type for hose skip node '%s'", targetKey)
406 return false
407 end
408
409 entry.length = getXMLFloat(xmlFile, targetKey .. "#length")
410 entry.isTwoPointHose = Utils.getNoNil(getXMLBool(xmlFile, targetKey .. "#isTwoPointHose"), false)
411
412 entry.isSkipNode = true
413
414 return true
415end

loadHoseTargetNode

Description
Definition
loadHoseTargetNode()
Code
478function ConnectionHoses:loadHoseTargetNode(xmlFile, targetKey, entry)
479 entry.node = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, targetKey .. "#node"), self.i3dMappings)
480
481 if entry.node == nil then
482 g_logManager:xmlWarning(self.configFileName, "Missing node for connection hose target '%s'", targetKey)
483 return false
484 end
485
486 local attacherJointIndices = {StringUtil.getVectorFromString(getXMLString(xmlFile, targetKey .. "#attacherJointIndices"))}
487 entry.attacherJointIndices = {}
488 for _, v in ipairs(attacherJointIndices) do
489 entry.attacherJointIndices[v] = v
490 end
491
492 entry.type = getXMLString(xmlFile, targetKey .. "#type")
493 entry.straighteningFactor = Utils.getNoNil(getXMLFloat(xmlFile, targetKey .. "#straighteningFactor"), 1)
494
495 local socketName = getXMLString(xmlFile, targetKey .. "#socket")
496 if socketName ~= nil then
497 entry.socket = g_connectionHoseManager:linkSocketToNode(socketName, entry.node)
498 end
499
500 if entry.type ~= nil then
501 entry.adapterName = Utils.getNoNil(getXMLString(xmlFile, targetKey .. "#adapterType"), "DEFAULT")
502
503 -- empty adapter with target node as reference
504 -- will be replaced with the real adapter on connecting
505 if entry.adapter == nil then
506 entry.adapter = {}
507 entry.adapter.node = entry.node
508 entry.adapter.refNode = entry.node
509 end
510
511 entry.objectChanges = {}
512 ObjectChangeUtil.loadObjectChangeFromXML(self.xmlFile, targetKey, entry.objectChanges, self.components, self)
513 ObjectChangeUtil.setObjectChanges(entry.objectChanges, false)
514 else
515 g_logManager:xmlWarning(self.configFileName, "Missing type for '%s'", targetKey)
516 return false
517 end
518
519 return true
520end

loadToolConnectorHoseNode

Description
Definition
loadToolConnectorHoseNode()
Code
419function ConnectionHoses:loadToolConnectorHoseNode(xmlFile, targetKey, entry)
420 local key = string.format("%s.startTarget", targetKey)
421 entry.startTargetNodeIndex = self:addHoseTargetNodes(xmlFile, key)
422
423 if entry.startTargetNodeIndex == nil then
424 g_logManager:xmlWarning(self.configFileName, "startTarget is missing for tool connection hose '%s'", targetKey)
425 return false
426 end
427
428 key = string.format("%s.endTarget", targetKey)
429 entry.endTargetNodeIndex = self:addHoseTargetNodes(xmlFile, key)
430
431 if entry.endTargetNodeIndex == nil then
432 g_logManager:xmlWarning(self.configFileName, "endTarget is missing for tool connection hose '%s'", targetKey)
433 return false
434 end
435
436 entry.mountingNode = I3DUtil.indexToObject(self.components, getXMLString(xmlFile, targetKey .. "#mountingNode"), self.i3dMappings)
437
438 if entry.mountingNode ~= nil then
439 setVisibility(entry.mountingNode, false)
440 end
441
442 return true
443end

onPostAttach

Description
Definition
onPostAttach()
Code
1099function ConnectionHoses:onPostAttach(attacherVehicle, inputJointDescIndex, jointDescIndex)
1100 self:connectHosesToAttacherVehicle(attacherVehicle, inputJointDescIndex, jointDescIndex)
1101end

onPreDetach

Description
Definition
onPreDetach()
Code
1105function ConnectionHoses:onPreDetach(attacherVehicle, implement)
1106 local spec = self.spec_connectionHoses
1107
1108 local hoses = self:getConnectionHosesByInputAttacherJoint(self:getActiveInputAttacherJointDescIndex())
1109 for _, hose in ipairs(hoses) do
1110 self:disconnectHose(hose)
1111 end
1112
1113 for _, hose in ipairs(spec.updateableHoses) do
1114 if hose.connectedObject == attacherVehicle then
1115 self:disconnectHose(hose)
1116 end
1117 end
1118
1119 -- remove delayed mounting if we detach the implement
1120 local attacherVehicleSpec = attacherVehicle.spec_connectionHoses
1121 if attacherVehicleSpec ~= nil then
1122 for _, toolConnector in pairs(attacherVehicleSpec.toolConnectorHoses) do
1123 if toolConnector.delayedMounting ~= nil then
1124 if toolConnector.delayedMounting.sourceObject == self then
1125 toolConnector.delayedMounting = nil
1126 end
1127 end
1128 end
1129 end
1130end

onUpdateInterpolation

Description
Definition
onUpdateInterpolation()
Code
171function ConnectionHoses:onUpdateInterpolation(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
172 if self.isClient then
173 local spec = self.spec_connectionHoses
174 for index, hose in ipairs(spec.updateableHoses) do
175 if self.updateLoopIndex == hose.connectedObject.updateLoopIndex then
176 self:updateConnectionHose(hose, index)
177 end
178 end
179
180 if self.getAttachedImplements ~= nil then
181 for _, implement in ipairs(self:getAttachedImplements()) do
182 if implement.object.updateAttachedConnectionHoses ~= nil then
183 implement.object:updateAttachedConnectionHoses(self)
184 end
185 end
186 end
187 end
188end

prerequisitesPresent

Description
Definition
prerequisitesPresent()
Code
15function ConnectionHoses.prerequisitesPresent(specializations)
16 return true
17end

registerEventListeners

Description
Definition
registerEventListeners()
Code
48function ConnectionHoses.registerEventListeners(vehicleType)
49 SpecializationUtil.registerEventListener(vehicleType, "onLoad", ConnectionHoses)
50 SpecializationUtil.registerEventListener(vehicleType, "onUpdateInterpolation", ConnectionHoses)
51 SpecializationUtil.registerEventListener(vehicleType, "onPostAttach", ConnectionHoses)
52 SpecializationUtil.registerEventListener(vehicleType, "onPreDetach", ConnectionHoses)
53end

registerFunctions

Description
Definition
registerFunctions()
Code
21function ConnectionHoses.registerFunctions(vehicleType)
22 SpecializationUtil.registerFunction(vehicleType, "updateAttachedConnectionHoses", ConnectionHoses.updateAttachedConnectionHoses)
23 SpecializationUtil.registerFunction(vehicleType, "updateConnectionHose", ConnectionHoses.updateConnectionHose)
24 SpecializationUtil.registerFunction(vehicleType, "getCenterPointAngle", ConnectionHoses.getCenterPointAngle)
25 SpecializationUtil.registerFunction(vehicleType, "getCenterPointAngleRegulation", ConnectionHoses.getCenterPointAngleRegulation)
26 SpecializationUtil.registerFunction(vehicleType, "loadHoseSkipNode", ConnectionHoses.loadHoseSkipNode)
27 SpecializationUtil.registerFunction(vehicleType, "loadToolConnectorHoseNode", ConnectionHoses.loadToolConnectorHoseNode)
28 SpecializationUtil.registerFunction(vehicleType, "addHoseTargetNodes", ConnectionHoses.addHoseTargetNodes)
29 SpecializationUtil.registerFunction(vehicleType, "loadHoseTargetNode", ConnectionHoses.loadHoseTargetNode)
30 SpecializationUtil.registerFunction(vehicleType, "loadHoseNode", ConnectionHoses.loadHoseNode)
31 SpecializationUtil.registerFunction(vehicleType, "getClonedSkipHoseNode", ConnectionHoses.getClonedSkipHoseNode)
32 SpecializationUtil.registerFunction(vehicleType, "getConnectionTarget", ConnectionHoses.getConnectionTarget)
33 SpecializationUtil.registerFunction(vehicleType, "getIsConnectionTargetUsed", ConnectionHoses.getIsConnectionTargetUsed)
34 SpecializationUtil.registerFunction(vehicleType, "getIsConnectionHoseUsed", ConnectionHoses.getIsConnectionHoseUsed)
35 SpecializationUtil.registerFunction(vehicleType, "getIsSkipNodeAvailable", ConnectionHoses.getIsSkipNodeAvailable)
36 SpecializationUtil.registerFunction(vehicleType, "getConnectionHosesByInputAttacherJoint", ConnectionHoses.getConnectionHosesByInputAttacherJoint)
37 SpecializationUtil.registerFunction(vehicleType, "connectHose", ConnectionHoses.connectHose)
38 SpecializationUtil.registerFunction(vehicleType, "disconnectHose", ConnectionHoses.disconnectHose)
39 SpecializationUtil.registerFunction(vehicleType, "updateToolConnectionHose", ConnectionHoses.updateToolConnectionHose)
40 SpecializationUtil.registerFunction(vehicleType, "addHoseToDelayedMountings", ConnectionHoses.addHoseToDelayedMountings)
41 SpecializationUtil.registerFunction(vehicleType, "connectHoseToSkipNode", ConnectionHoses.connectHoseToSkipNode)
42 SpecializationUtil.registerFunction(vehicleType, "connectHosesToAttacherVehicle", ConnectionHoses.connectHosesToAttacherVehicle)
43 SpecializationUtil.registerFunction(vehicleType, "retryHoseSkipNodeConnections", ConnectionHoses.retryHoseSkipNodeConnections)
44end

retryHoseSkipNodeConnections

Description
Definition
retryHoseSkipNodeConnections()
Code
1083function ConnectionHoses:retryHoseSkipNodeConnections(updateToolConnections, excludeVehicle)
1084 if self.getAttachedImplements ~= nil then
1085 local attachedImplements = self:getAttachedImplements()
1086 for _, implement in ipairs(attachedImplements) do
1087 local object = implement.object
1088 if object ~= excludeVehicle then
1089 if object.connectHosesToAttacherVehicle ~= nil then
1090 object:connectHosesToAttacherVehicle(self, implement.inputJointDescIndex, implement.jointDescIndex, updateToolConnections, excludeVehicle)
1091 end
1092 end
1093 end
1094 end
1095end

updateAttachedConnectionHoses

Description
Definition
updateAttachedConnectionHoses()
Code
192function ConnectionHoses:updateAttachedConnectionHoses(attacherVehicle)
193 if self.isClient then
194 local spec = self.spec_connectionHoses
195 for index, hose in ipairs(spec.updateableHoses) do
196 if hose.connectedObject == attacherVehicle then
197 if self.updateLoopIndex == hose.connectedObject.updateLoopIndex then
198 self:updateConnectionHose(hose, index)
199 end
200 end
201 end
202 end
203end

updateConnectionHose

Description
Definition
updateConnectionHose()
Code
207function ConnectionHoses:updateConnectionHose(hose, index)
208 -- determine control points for spline
209 local p0x, p0y, p0z = 0, 0, -hose.startStraightening
210 local p3x, p3y, p3z = localToLocal(hose.targetNode, hose.hoseNode, 0,0,0)
211 local p4x, p4y, p4z = localToLocal(hose.targetNode, hose.hoseNode, 0,0, hose.endStraightening)
212
213 -- default position of middle node
214 local p2x
215 local p2y
216 local p2z
217
218 if hose.isWorldSpaceHose then
219 local w1x, w1y, w1z = getWorldTranslation(hose.hoseNode)
220 local w2x, w2y, w2z = getWorldTranslation(hose.targetNode)
221
222 p2x = (w1x + w2x) / 2
223 p2y = (w1y + w2y) / 2
224 p2z = (w1z + w2z) / 2
225 else
226 p2x = p3x / 2
227 p2y = p3y / 2
228 p2z = p3z / 2
229 end
230
231 -- real distance between nodes
232 local d = MathUtil.vector3Length(p3x, p3y, p3z)
233
234 -- simple calculation of the center point -> low precicision, high performance
235 local lengthDifference = math.max(hose.length - d, 0)
236 p2y = p2y - math.max(lengthDifference, 0.04 * d)
237
238 if hose.isWorldSpaceHose then
239 if hose.minDeltaY ~= math.huge then
240 local x, y, z = worldToLocal(hose.minDeltaYComponent, p2x, p2y, p2z)
241 local _, yTarget, _ = localToLocal(hose.minDeltaYComponent, hose.hoseNode, 0, 0, 0)
242 p2x, p2y, p2z = localToWorld(hose.minDeltaYComponent, x, math.max(y, -yTarget+hose.minDeltaY), z)
243 end
244
245 p2x, p2y, p2z = worldToLocal(hose.hoseNode, p2x, p2y, p2z)
246 end
247
248 local angle1, angle2 = self:getCenterPointAngle(hose.hoseNode, p2x, p2y, p2z, p3x, p3y, p3z, hose.isWorldSpaceHose)
249 local centerPointAngle = angle1+angle2
250 if centerPointAngle < hose.minCenterPointAngle then
251 p2x, p2y, p2z = self:getCenterPointAngleRegulation(hose.hoseNode, p2x, p2y, p2z, p3x, p3y, p3z, angle1, angle2, hose.minCenterPointAngle, hose.isWorldSpaceHose)
252 end
253
254 if hose.minCenterPointOffset ~= nil and hose.maxCenterPointOffset ~= nil then
255 p2x = MathUtil.clamp(p2x, hose.minCenterPointOffset[1], hose.maxCenterPointOffset[1])
256 p2y = MathUtil.clamp(p2y, hose.minCenterPointOffset[2], hose.maxCenterPointOffset[2])
257 p2z = MathUtil.clamp(p2z, hose.minCenterPointOffset[3], hose.maxCenterPointOffset[3])
258 end
259
260 -- manipulate by parent component Y and Z velocity
261 local newX, newY, newZ = getWorldTranslation(hose.component)
262 if hose.lastComponentPosition == nil or hose.lastComponentVelocity == nil then
263 hose.lastComponentPosition = {newX, newY, newZ}
264 hose.lastComponentVelocity = {newX, newY, newZ}
265 end
266
267 local newVelX, newVelY, newVelZ = newX-hose.lastComponentPosition[1], newY-hose.lastComponentPosition[2], newZ-hose.lastComponentPosition[3]
268 hose.lastComponentPosition[1], hose.lastComponentPosition[2], hose.lastComponentPosition[3] = newX, newY, newZ
269
270 local velX, velY, velZ = newVelX-hose.lastComponentVelocity[1], newVelY-hose.lastComponentVelocity[2], newVelZ-hose.lastComponentVelocity[3]
271 hose.lastComponentVelocity[1], hose.lastComponentVelocity[2], hose.lastComponentVelocity[3] = newVelX, newVelY, newVelZ
272
273 local worldX, worldY, worldZ = getWorldTranslation(hose.hoseNode)
274 _, velY, velZ = worldToLocal(hose.hoseNode, worldX+velX, worldY+velY, worldZ+velZ)
275
276 velY = MathUtil.clamp(velY*-hose.dampingFactor, -hose.dampingRange, hose.dampingRange) * lengthDifference
277 velZ = MathUtil.clamp(velZ*-hose.dampingFactor, -hose.dampingRange, hose.dampingRange) * lengthDifference
278
279 velY = velY * 0.1 + hose.lastVelY * 0.9
280 velZ = velZ * 0.1 + hose.lastVelZ * 0.9
281
282 hose.lastVelY = velY
283 hose.lastVelZ = velZ
284
285 p2x, p2y, p2z = p2x, p2y+velY, p2z+velZ
286
287 -- on two point hoses we set the center point to 0 and the shader creates a two point catmull rom
288 if hose.isTwoPointHose then
289 p2x, p2y, p2z = 0, 0, 0
290 end
291
292 -- apply to shader
293 setShaderParameter(hose.hoseNode, "cv2", p2x, p2y, p2z, 0, false) -- center point
294 setShaderParameter(hose.hoseNode, "cv3", p3x, p3y, p3z, 0, false) -- target point
295 setShaderParameter(hose.hoseNode, "cv4", p4x, p4y, p4z, 1, false) -- straighter point
296
297 if VehicleDebug.state == VehicleDebug.DEBUG_ATTACHER_JOINTS then
298 if self:getIsActiveForInput() then
299 local realLength = MathUtil.vector3Length(p2x, p2y, p2z)
300 realLength = realLength + MathUtil.vector3Length(p2x-p3x, p2y-p3y, p2z-p3z)
301 renderText(0.5, 0.9-index*0.02, 0.0175, string.format("hose %s:", getName(hose.node)))
302 renderText(0.62, 0.9-index*0.02, 0.0175, string.format("directLength: %.2f configLength: %.2f realLength: %.2f angle: %.2f minAngle: %.2f", d, hose.length, realLength, math.deg(centerPointAngle), math.deg(hose.minCenterPointAngle)))
303
304 local x1,y1,z1 = localToWorld(hose.hoseNode, p0x, p0y, p0z)
305 local x2,y2,z2 = localToWorld(hose.hoseNode, 0, 0, 0)
306 drawDebugLine(x1,y1,z1, 1,0,0, x2,y2,z2, 0,1,0)
307
308 x1,y1,z1 = localToWorld(hose.hoseNode, 0, 0, 0)
309 x2,y2,z2 = localToWorld(hose.hoseNode, p2x, p2y, p2z)
310 drawDebugLine(x1,y1,z1, 1,0,0, x2,y2,z2, 0,1,0)
311
312 x1,y1,z1 = localToWorld(hose.hoseNode, p2x, p2y, p2z)
313 x2,y2,z2 = localToWorld(hose.hoseNode, p3x, p3y, p3z)
314 drawDebugLine(x1,y1,z1, 1,0,0, x2,y2,z2, 0,1,0)
315
316 x1,y1,z1 = localToWorld(hose.hoseNode, p3x, p3y, p3z)
317 x2,y2,z2 = localToWorld(hose.hoseNode, p4x, p4y, p4z)
318 drawDebugLine(x1,y1,z1, 1,0,0, x2,y2,z2, 0,1,0)
319
320 local x0,y0,z0 = localToWorld(hose.hoseNode, p0x, p0y, p0z)
321 x1,y1,z1 = localToWorld(hose.hoseNode, 0, 0, 0)
322 x2,y2,z2 = localToWorld(hose.hoseNode, p2x, p2y, p2z)
323 local x3,y3,z3 = localToWorld(hose.hoseNode, p3x, p3y, p3z)
324 local x4,y4,z4 = localToWorld(hose.hoseNode, p4x, p4y, p4z)
325 drawDebugPoint(x0,y0,z0, 1,0,0,1)
326 drawDebugPoint(x1,y1,z1, 1,0,0,1)
327 drawDebugPoint(x2,y2,z2, 1,0,0,1)
328 drawDebugPoint(x3,y3,z3, 1,0,0,1)
329 drawDebugPoint(x4,y4,z4, 1,0,0,1)
330
331 DebugUtil.drawDebugNode(hose.hoseNode)
332 DebugUtil.drawDebugNode(hose.targetNode)
333 end
334 end
335end

updateToolConnectionHose

Description
Definition
updateToolConnectionHose()
Code
866function ConnectionHoses:updateToolConnectionHose(sourceObject, sourceHose, targetObject, targetHose, visibility)
867 local spec = self.spec_connectionHoses
868
869 local toolConnectionHose = spec.targetNodeToToolConnection[targetHose.index]
870 if toolConnectionHose ~= nil then
871 local opositTargetIndex = toolConnectionHose.startTargetNodeIndex
872 if opositTargetIndex == targetHose.index then
873 opositTargetIndex = toolConnectionHose.endTargetNodeIndex
874 end
875 local opositTarget = spec.targetNodes[opositTargetIndex]
876
877 if opositTarget ~= nil then
878 if visibility and toolConnectionHose.delayedMounting ~= nil then
879 local differentSource = toolConnectionHose.delayedMounting.sourceObject ~= sourceObject -- with the retryHoseSkipNodeConnections functionallity it can happen that the object is the same
880 local sameType = toolConnectionHose.delayedMounting.sourceHose.type == sourceHose.type
881 if differentSource and sameType then
882 local x, y, z = localToLocal(targetHose.node, opositTarget.node, 0, 0, 0)
883 local length = MathUtil.vector3Length(x, y, z)
884
885 local hose, _, _, _ = g_connectionHoseManager:getClonedHoseNode(sourceHose.type, sourceHose.hoseType, length, sourceHose.diameter, sourceHose.color)
886
887 if hose ~= nil then
888 link(targetHose.node, hose)
889 setTranslation(hose, 0, 0, 0)
890
891 local dirX, dirY, dirZ = localToLocal(hose, opositTarget.node, 0, 0, 0)
892 setDirection(hose, dirX, dirY, dirZ, 0, 0, 1)
893
894 setShaderParameter(hose, "cv0", 0, 0, -dirZ*0.5, 0, false)
895 setShaderParameter(hose, "cv2", dirX*0.5+0.003, dirY*0.5, dirZ*0.5, 0, false) -- center point
896 setShaderParameter(hose, "cv3", dirX-0.003, dirY, dirZ, 0, false) -- target point
897 setShaderParameter(hose, "cv4", dirX-0.003, dirY, dirZ+dirZ*0.5, 0, false) -- end straightening point
898
899 local function setTargetNodeTranslation(hose)
900 if hose.originalNodeTranslation == nil then
901 hose.originalNodeTranslation = {getTranslation(hose.node)}
902 else
903 setTranslation(hose.node, unpack(hose.originalNodeTranslation))
904 end
905 local wx, wy, wz = localToWorld(hose.node, 0, sourceHose.diameter*0.5, 0)
906 local lx, ly, lz = worldToLocal(getParent(hose.node), wx, wy, wz)
907 setTranslation(hose.node, lx, ly, lz)
908 end
909
910 setTargetNodeTranslation(targetHose)
911 setTargetNodeTranslation(opositTarget)
912
913 self:addAllSubWashableNodes(hose)
914
915 toolConnectionHose.hoseNode = hose
916
917 if toolConnectionHose.mountingNode ~= nil then
918 setVisibility(toolConnectionHose.mountingNode, true)
919 end
920
921 -- connect the first attached hose to the tool connection
922 if toolConnectionHose.delayedMounting ~= nil then
923 toolConnectionHose.delayedUnmounting = {}
924 table.insert(toolConnectionHose.delayedUnmounting, toolConnectionHose.delayedMounting)
925 table.insert(toolConnectionHose.delayedUnmounting, {sourceObject=sourceObject, sourceHose=sourceHose, targetObject=targetObject, targetHose=targetHose})
926
927 local delayedHose = toolConnectionHose.delayedMounting
928 toolConnectionHose.delayedMounting = nil
929 delayedHose.sourceObject:connectHose(delayedHose.sourceHose, delayedHose.targetObject, delayedHose.targetHose, false)
930 delayedHose.sourceObject:retryHoseSkipNodeConnections(false)
931 end
932
933 return true
934 else
935 return false
936 end
937 end
938 else
939 if toolConnectionHose.hoseNode ~= nil then
940 self:removeWashableNode(toolConnectionHose.hoseNode)
941
942 delete(toolConnectionHose.hoseNode)
943 toolConnectionHose.hoseNode = nil
944
945 if toolConnectionHose.mountingNode ~= nil then
946 setVisibility(toolConnectionHose.mountingNode, false)
947 end
948
949 -- remove the second hose connection from the tool connection
950 -- but keep it as delayed mounting
951 -- if is hose from skip node, completly remove it (will be recreated depending on sub attached tool)
952 if toolConnectionHose.delayedUnmounting ~= nil then
953 for _, hose in ipairs(toolConnectionHose.delayedUnmounting) do
954 if sourceHose ~= hose.sourceHose then
955 hose.sourceObject:disconnectHose(hose.sourceHose)
956 if hose.sourceHose.isClonedSkipNodeHose == nil or not hose.sourceHose.isClonedSkipNodeHose then
957 toolConnectionHose.delayedMounting = hose
958 end
959 end
960 end
961
962 toolConnectionHose.delayedUnmounting = nil
963 end
964 end
965 end
966 end
967 else
968 return true
969 end
970
971 return false
972end