Пример #1
0
        public static AttachNodeSim New(PartSim partSim, String newId, AttachNode.NodeType newNodeType)
        {
            AttachNodeSim nodeSim = pool.Borrow();

            nodeSim.attachedPartSim = partSim;
            nodeSim.nodeType        = newNodeType;
            nodeSim.id = newId;

            return(nodeSim);
        }
Пример #2
0
        public AttachedPartInfo(AnimatedAttachment animatedAttachment, Part attachedPart)
        {
            this.animatedAttachment = animatedAttachment;
            this.attachedPart       = attachedPart;

            AttachNode.NodeType nodeType = AttachNode.NodeType.Stack;
            if (attachedPart && attachedPart.srfAttachNode.attachedPart)
            {
                nodeType = AttachNode.NodeType.Surface;
            }
            this.nodeType = nodeType;
        }
Пример #3
0
        internal void Load(int index, ConfigNode root)
        {
            ConfigNode attachNodeInfo = root.GetNode("ATTACH_NODE_INFO", index);

            if (attachNodeInfo == null)
            {
                printf("Failed to find ATTACH_NODE_INFO!");
                return;
            }

            loaded = true;

            if (!attachNodeInfo.HasNode("POS_ROT"))
            {
                printf("Failed to find POS_ROT!");
                return;
            }

            //string attachedPartName = attachNodeInfo.GetValue("attachedPart");
            string colliderName = attachNodeInfo.GetValue("colliderName");

            Collider[] colliders = animatedAttachment.part.GetPartColliders();

            foreach (Collider collider in colliders)
            {
                if (collider.name == colliderName)
                {
                    this.collider = collider;
                }
            }

            nodeType = (AttachNode.NodeType)Enum.Parse(typeof(AttachNode.NodeType), attachNodeInfo.GetValue("nodeType"));

            if (attachedPartOffset == null)
            {
                attachedPartOffset = new PosRot();
            }

            attachedPartOffset.Load(attachNodeInfo, "offset");
        }
Пример #4
0
        public void UpdateAttachments(State flightState, bool debug, bool debugPeriodic)
        {
            // If the is no actual part attached to the attach node, then we can bail out.
            // Part attachedPart = GetAttachedPart();

            if (debugPeriodic)
            {
                printf("UA: %s %s %s %s",
                       attachedPart != null ? attachedPart.name : null,
                       nodeType,
                       stackAttachNode != null ? stackAttachNode.id : "null",
                       stackAttachNode != null ? stackAttachNode.attachedPartId.ToString() : "null");
            }

            // We don't want to mess with the joint attaching this part to its parent.
            // Also, take of the special case where they are both null, otherwise we
            // will incorrectly get a match between them, resulting in loss of function
            // if the animated part is the root part.
            if ((attachedPart == animatedAttachment.part.parent) &&
                (attachedPart != null))
            {
                if (debugPeriodic)
                {
                    printf("Skipping parent");
                }

                return;
            }

            switch (nodeType)
            {
            case AttachNode.NodeType.Surface:
                if (collider == null)
                {
                    SetCollider();

                    if (debug)
                    {
                        printf("Setting collider to %s",
                               collider.name);
                    }
                }
                break;

            case AttachNode.NodeType.Stack:
                if (stackAttachNode == null)
                {
                    stackAttachNode = animatedAttachment.part.FindAttachNodeByPart(attachedPart);

                    // Sometimes life throws lemons at you, like when the user actvated attachments in flight
                    if (stackAttachNode == null)
                    {
                        // Try again as surface attached
                        nodeType = AttachNode.NodeType.Surface;
                        return;
                    }

                    if (debug)
                    {
                        printf("Setting attach node to %s",
                               stackAttachNode.id);
                    }
                }
                break;
            }

            Transform referenceTransform = GetReferenceTransform();

            // If this attach node is defined in the cfg, then bail out now, it will not be movable
            if (referenceTransform == null)
            {
                if (debugPeriodic)
                {
                    printf("Skipping cfg based node: %s", stackAttachNode.id);
                }
                return;
            }

            // Get the position and rotation of the node transform relative to the part.
            // The nodeTransform itself will only contain its positions and rotation
            // relative to the immediate parent in the model
            PosRot referencePosRot = PosRot.GetPosRot(referenceTransform, animatedAttachment.part);

            // We can't animate decoupling shrouds
            if (referencePosRot == null)
            {
                if (debugPeriodic)
                {
                    printf("Skipping decoupler shroud");
                }
                return;
            }

            bool active = animatedAttachment.activated;

            if (EditorLogic.fetch && (EditorLogic.fetch.EditorConstructionMode != ConstructionMode.Place))
            {
                active = false;
            }

            // Take note of newly attached parts, including at initial ship load
            if (attachedPart == null || !active)
            {
                if (debugPeriodic)
                {
                    if (attachedPart == null)
                    {
                        printf("No part attached");
                    }
                }

                attachedPartOffset = null;
                return;
            }

            if (attachedPartOffset == null || attachedPartOriginal == null)
            {
                // Get attached part position relative to this part
                PosRot localPosRot = new PosRot();

                Transform parent = attachedPart.transform.parent;

                // Let the engine calculate the local position instead of doing the calculation ourselves..
                attachedPart.transform.parent = animatedAttachment.part.transform;
                localPosRot.position          = attachedPart.transform.localPosition;
                localPosRot.rotation          = attachedPart.transform.localRotation;
                attachedPart.transform.parent = parent;

                // We could do parenting trick for this too, but seems we loose the scaling
                if (attachedPartOffset == null)
                {
                    printf("Recording attachedPartOffset");

                    attachedPartOffset = new PosRot();

                    attachedPartOffset.rotation =
                        referencePosRot.rotation.Inverse() *
                        localPosRot.rotation;

                    attachedPartOffset.position =
                        referencePosRot.rotation.Inverse() *
                        (localPosRot.position -
                         referencePosRot.position);
                }

                if (attachedPartOriginal == null)
                {
                    printf("Recording attachedPartOriginal");

                    attachedPartOriginal          = new PosRot();
                    attachedPartOriginal.rotation = localPosRot.rotation;
                }
            }

            // Calculate the attached parts position in the frame of reference of this part
            PosRot attachedPartPosRot = new PosRot
            {
                rotation = referencePosRot.rotation * attachedPartOffset.rotation,
                position = referencePosRot.position + referencePosRot.rotation * attachedPartOffset.position
            };

            /* A sub part can either be connected directly by their transform having a parent transform,
             * or be connected through a joint. In the first case, the sub part will directly move with
             * their parent as their position is in in the reference frame of the parent local space.
             * In the latter case, the sub part lacks a parent transform, and the position is in the vessel
             * space instead, and parts are held together by forces working through the joints.
             * The first case occurs in two situations. In the VAB editor, all parts are connected by
             * parent transforms. And, during flight, a physicsless part will also be connected to the parent
             * this way - for example some science parts.
             * Joints are used for normal physics based parts during flight.
             */

            if (attachedPart.transform.parent != null)
            {
                // If a parent was found, we will just update the position of the part directly since no physics is involved
                attachedPart.transform.localRotation = attachedPartPosRot.rotation;
                attachedPart.transform.localPosition = attachedPartPosRot.position;

                if (debugPeriodic)
                {
                    printf("Updated pos without physics");
                }

                // There is nothing more to do, so bail out
                return;
            }

            // In the editor, while changing action groups, the parent will be null for some reason.
            // We can catch that here by making sure there exists a joint
            if (attachedPart.attachJoint == null)
            {
                if (debugPeriodic)
                {
                    printf("No attach joint found");
                }
                return;
            }

            // Things get tricker if the parts are connected by joints. We need to setup the joint
            // to apply forces to the sub part.
            ConfigurableJoint joint = attachedPart.attachJoint.Joint;

            // It is not possible to change values of a JointDrive after creation, so we must create a
            // new one and apply it to the joint. Seems we can't only create it at startup either.
            switch (joint.name)
            {
            case "AnimatedAttachment":
                if (joint.xMotion != ConfigurableJointMotion.Free && flightState == State.STARTED)
                {
                    animatedAttachment.initJointDrive = true;
                }
                break;

            case "MechanicsToolkit":
                break;

            default:
                animatedAttachment.initJointDrive = true;
                break;
            }

            if (animatedAttachment.initJointDrive)
            {
                animatedAttachment.initJointDrive = false;
                joint.name = "AnimatedAttachment";

                jointDrive = new JointDrive();
                printf("Creating a new drive mode. Previous: %s, %s, %s, %s, %s",
                       joint.name,
                       joint.xDrive.positionSpring,
                       animatedAttachment.part.name,
                       animatedAttachment.part.started,
                       joint.angularXMotion);

                /*
                 * printf(string.Format("maximumForce: {0}", animatedAttachment.maximumForce));
                 * printf(string.Format("positionDamper: {0}", animatedAttachment.positionDamper));
                 * printf(string.Format("positionSpring: {0}", animatedAttachment.positionSpring));
                 */

                // The joint will not respond to changes to targetRotation/Position in locked mode,
                // so change it to free in all directions
                joint.xMotion        = ConfigurableJointMotion.Free;
                joint.yMotion        = ConfigurableJointMotion.Free;
                joint.zMotion        = ConfigurableJointMotion.Free;
                joint.angularXMotion = ConfigurableJointMotion.Free;
                joint.angularYMotion = ConfigurableJointMotion.Free;
                joint.angularZMotion = ConfigurableJointMotion.Free;

                // Create a new joint with settings from the cfg file or user selection
                jointDrive.maximumForce   = animatedAttachment.maximumForce;
                jointDrive.positionDamper = animatedAttachment.positionDamper;
                jointDrive.positionSpring = animatedAttachment.positionSpring;

                // Same drive in all directions.. is there benefits of separating them?
                joint.angularXDrive  = jointDrive;
                joint.angularYZDrive = jointDrive;
                joint.xDrive         = jointDrive;
                joint.yDrive         = jointDrive;
                joint.zDrive         = jointDrive;
                //}
                if (debug)
                {
                    printf("%s", joint);
                }
            }

            if (debug)
            {
                printf("%s", attachedPartPosRot);
            }
            if (debug)
            {
                printf("%s", attachedPartOriginal);
            }

            // Update the joint.targetRotation using this convenience function, since the joint
            // reference frame has weird axes. Arguments are current and original rotation.
            joint.SetTargetRotationLocal(
                attachedPartPosRot.rotation,
                attachedPartOriginal.rotation);

            /* Move the attached part by updating the connectedAnchor instead of the joint.targetPosition.
             * This is easier since the anchor is in the reference frame of this part, and we already have the
             * position in that reference frame. It also makes sense from the view that since it really is the
             * attachment point of the attached part that is moving. There might be benefits of using the targetPosition
             * though, and should be possible to calculate it fairly easily if needed.
             */
            joint.connectedAnchor = referencePosRot.position;

            // Make sure the target position is zero
            joint.targetPosition = Vector3.zero;

            // This scaling and rotation is to convert to joint space... maybe?
            // Determined by random tinkering and is magical as far as I am concerned
            joint.anchor = attachedPartOffset.rotation.Inverse() *
                           Vector3.Scale(
                new Vector3(-1, -1, -1),
                attachedPartOffset.position);

            if (debugPeriodic)
            {
                printf("%s; %s; %s -> %s; %s -> %s; %s",
                       referencePosRot,
                       attachedPartPosRot,
                       attachedPartOffset,
                       attachedPartOriginal.rotation.eulerAngles,
                       joint.targetRotation.eulerAngles,
                       joint.anchor,
                       joint.connectedAnchor
                       );
            }

            // Debug info
            if (debug)
            {
                // Show debug vectors for the child part
                if (axisJoint == null)
                {
                    axisJoint = new AxisInfo(joint.transform);
                }

                if (lineAnchor == null)
                {
                    lineAnchor = new LineInfo(animatedAttachment.part.transform, Color.cyan);
                }
                lineAnchor.Update(Vector3.zero, joint.connectedAnchor);

                if (lineNodeToPart == null)
                {
                    lineNodeToPart = new LineInfo(animatedAttachment.part.transform, Color.magenta);
                }
                lineNodeToPart.Update(
                    referencePosRot.position,
                    attachedPartPosRot.position);
            }
            else
            {
                if (axisJoint != null)
                {
                    axisJoint = null;
                }
            }

            // Debug info
            if (debug)
            {
                // Show debug vectors for the attachNodes
                if (orientationAttachNode == null)
                {
                    orientationAttachNode = new OrientationInfo(animatedAttachment.part.transform, referencePosRot.position, referencePosRot.position + attachedPartOffset.orientation);
                }

                if (stackAttachNode != null)
                {
                    orientationAttachNode.Update(referencePosRot.position, referencePosRot.position + stackAttachNode.orientation);
                }
            }
            else
            {
                if (orientationAttachNode != null)
                {
                    orientationAttachNode = null;
                }
            }
        }
Пример #5
0
 public AttachNodeSim(PartSim partSim, String newId, AttachNode.NodeType newNodeType)
 {
     attachedPartSim = partSim;
     nodeType = newNodeType;
     id = newId;
 }
Пример #6
0
 public AttachNodeSim(PartSim partSim, String newId, AttachNode.NodeType newNodeType)
 {
     attachedPartSim = partSim;
     nodeType        = newNodeType;
     id = newId;
 }