Ejemplo n.º 1
0
        void OnCollisionStay(Collision collisionInfo)
        {
            //if (collisionInfo.rigidbody != part.Rigidbody || !moduleAnimateGeneric)
            if (!moduleAnimateGeneric || !animationStopper)
            {
                return;
            }

            if (!moduleAnimateGeneric.IsMoving())
            {
                return;
            }

            foreach (ContactPoint contact in collisionInfo.contacts)
            {
                ColliderInfo thisColliderInfo = GetColliderInfo(contact.thisCollider);

                // Check if this is an internal collider moving in respect to the part,
                // or if it is a child part moving due to being animated by AnimatedAttachment
                if (thisColliderInfo.part == part)
                {
                    PosRot  currentPosRot = PosRot.GetPosRot(thisColliderInfo.collider.transform, part);
                    Vector3 movement      = currentPosRot.position - thisColliderInfo.posRot.position;
                    double  angle         = Quaternion.Angle(currentPosRot.rotation, thisColliderInfo.posRot.rotation);

                    thisColliderInfo.posRot = currentPosRot;

                    // Set a minimum level
                    if (movement.IsSmallerThan(0.1f) && angle < 0.1)
                    {
                        continue;
                    }

                    printf("Animation stopped by a collision between %s and %s (movement %s, angle %s)",
                           thisColliderInfo.collider.name,
                           collisionInfo.collider.name,
                           movement,
                           angle);
                }
                else
                {
                    printf("Animation stopped by a collision between %s.%s and %s",
                           thisColliderInfo.part.name,
                           thisColliderInfo.collider.name,
                           collisionInfo.collider.name);
                }

                float time = moduleAnimateGeneric.animTime;
                if (moduleAnimateGeneric.revClampPercent)
                {
                    time = 1 - time;
                }
                moduleAnimateGeneric.deployPercent    = 100.0f * time;
                moduleAnimateGeneric.allowDeployLimit = true;
                break;
            }
        }
Ejemplo n.º 2
0
        private void AddColliders(List <ColliderInfo> colliderInfos, Part part)
        {
            printf("Adding part %s to collider list", part.name);

            foreach (Collider collider in part.GetPartColliders())
            {
                ColliderInfo colliderInfo = new ColliderInfo();
                colliderInfo.collider = collider;
                colliderInfo.part     = part;
                colliderInfo.posRot   = PosRot.GetPosRot(collider.transform, part);
                colliderInfos.Add(colliderInfo);
            }
            foreach (Part child in part.children)
            {
                AddColliders(colliderInfos, child);
            }
        }
Ejemplo n.º 3
0
    private void UpdateAttachments(List <AttachedPartInfo> attachedPartInfos, bool debugPeriodic)
    {
        // Bail out if init failed
        if (attachedPartInfos == null)
        {
            if (debugPeriodic)
            {
                print("Empty attach node info list!");
            }
            return;
        }

        if (debugPeriodic)
        {
            printf("Updating %s/%s parts",
                   attachedPartInfos.Count,
                   part.children.Count);
        }

        foreach (AttachNode attachNode in part.attachNodes)
        {
            // We can't move attach nodes that are positioned in the cfg file
            if (attachNode.nodeTransform == null)
            {
                if (debugPeriodic)
                {
                    printf("Skipping %s since it lacks a node transform",
                           attachNode.id);
                }
                continue;
            }

            // 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 attachNodePosRot = PosRot.GetPosRot(attachNode.nodeTransform, part);

            // We can't animate decoupling shrouds
            if (attachNodePosRot == null)
            {
                if (debugPeriodic)
                {
                    printf("Skipping %s since it is a decoupler shroud",
                           attachNode.id);
                }
                continue;
            }

            // Update the attachNode
            attachNode.position    = attachNodePosRot.position;
            attachNode.orientation = attachNodePosRot.orientation;
        }

        for (int i = 0; i < part.children.Count; i++)
        {
            Part child = part.children[i];
            // Create new entries in the list if needed
            if (i >= attachedPartInfos.Count)
            {
                if (debug)
                {
                    printf("Adding child %s [%s]",
                           child.name,
                           i);
                }

                attachedPartInfos.Add(new AttachedPartInfo(this, child));
            }

            AttachedPartInfo attachedPartInfo = attachedPartInfos[i];
            // Assign parts to info structs newly loaded from a save file
            if (attachedPartInfo.loaded)
            {
                attachedPartInfo.attachedPart = child;
                attachedPartInfo.loaded       = false;

                if (debug)
                {
                    printf("Assigning child %s [%s]",
                           attachedPartInfo.attachedPart,
                           i);
                }
            }
            else
            // Remove stale entries
            if (attachedPartInfo.attachedPart != child)
            {
                if (debug)
                {
                    printf("Deleting child %s/%s",
                           attachedPartInfo.attachedPart,
                           child.name);
                }
                attachedPartInfos.Remove(attachedPartInfo);
                i--;
                continue;
            }

            if (debugPeriodic)
            {
                printf("Updating child %s [%s]",
                       attachedPartInfo,
                       i);
            }
            attachedPartInfo.UpdateAttachments(flightState, debug, debugPeriodic);
        }

        // Continue deleting surplus entries
        while (attachedPartInfos.Count > part.children.Count)
        {
            AttachedPartInfo attachedPartInfo = attachedPartInfos[part.children.Count];
            if (debug)
            {
                printf("Deleting child %s [%s]",
                       attachedPartInfo.attachedPart,
                       part.children.Count);
            }
            attachedPartInfos.Remove(attachedPartInfo);
        }
    }
Ejemplo n.º 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;
                }
            }
        }