Пример #1
0
 public FeedWriter(IFeedDefinition <T> definition, ILinkSource <T> links, IUrlRegistry urls, IOutputWriter writer)
 {
     _definition = definition;
     _links      = links;
     _urls       = urls;
     _writer     = writer;
 }
Пример #2
0
        /// <summary>
        /// Creates a distance joint between the source and an arbitrary physical object.
        /// </summary>
        /// <remarks>It sets the maximum cable length to the persisted value. Even if it's zero!</remarks>
        /// <param name="source">The source of the link.</param>
        /// <param name="tgtRb">The rigidbody of the physical object.</param>
        /// <param name="tgtAnchor">The anchor at the physical object in world coordinates.</param>
        void CreateDistanceJoint(ILinkSource source, Rigidbody tgtRb, Vector3 tgtAnchor)
        {
            var distanceLimit = originalLength
                                ?? Vector3.Distance(GetSourcePhysicalAnchor(source), tgtAnchor);
            var joint = source.part.gameObject.AddComponent <ConfigurableJoint>();

            KASAPI.JointUtils.ResetJoint(joint);
            if (distanceLimit < 0.001f)
            {
                // Reset the distance if it's below the KSP distance resolution.
                HostedDebugLog.Fine(this, "Reset joint to zero: distance={0}", distanceLimit);
                distanceLimit = 0;
            }

            KASAPI.JointUtils.SetupDistanceJoint(
                joint,
                springForce: cableSpringForce, springDamper: cableSpringDamper,
                maxDistance: distanceLimit);
            joint.autoConfigureConnectedAnchor = false;
            joint.anchor = source.part.Rigidbody.transform.InverseTransformPoint(
                GetSourcePhysicalAnchor(source));
            joint.connectedBody   = tgtRb;
            joint.connectedAnchor = tgtRb.transform.InverseTransformPoint(tgtAnchor);
            SetBreakForces(joint);
            SetCustomJoints(new[] { joint });
            cableJoint = joint;
        }
Пример #3
0
 /// <summary>Restores available state when connection mode is over.</summary>
 /// <remarks>It's only listened in state <see cref="LinkState.RejectingLinks"/>.
 /// <para>Event handler for <see cref="IKasEvents.OnStopLinking"/>.</para>
 /// </remarks>
 /// <param name="source">Source module that started the mode.</param>
 void OnStopLinkingKASEvent(ILinkSource source)
 {
     if (!isLocked)
     {
         SetLinkState(LinkState.Available);
     }
 }
Пример #4
0
 /// <summary>Cancels  the linking mode on this module.</summary>
 /// <remarks>KAS events listener.</remarks>
 /// <param name="connectionSource"></param>
 protected virtual void OnStopLinkingKASEvent(ILinkSource connectionSource)
 {
     if (!isLocked)
     {
         SetLinkState(LinkState.Available);
     }
 }
Пример #5
0
 /// <summary>Creates an event info.</summary>
 /// <param name="source">The source that initiated the link.</param>
 /// <param name="target">The target that accepted the link.</param>
 /// <param name="actorType">The actor that did the change.</param>
 public KasLinkEventImpl(ILinkSource source, ILinkTarget target,
                         LinkActorType actorType = LinkActorType.API)
 {
     _source = source;
     _target = target;
     _actor  = actorType;
 }
Пример #6
0
 /// <summary>Creates an event info.</summary>
 /// <param name="source">The source that initiated the link.</param>
 /// <param name="target">The target that accepted the link.</param>
 /// <param name="actorType">The actor that did the change.</param>
 public KasLinkEventImpl(ILinkSource source, ILinkTarget target,
                         LinkActorType actorType = LinkActorType.API)
 {
     this.source = source;
     this.target = target;
     actor       = actorType;
 }
Пример #7
0
 /// <summary>
 /// Fires when this module can link, and there is a source that has actived the linking mode.
 /// </summary>
 /// <remarks>KAS events listener.</remarks>
 /// <param name="source"></param>
 protected virtual void OnStartLinkingKASEvent(ILinkSource source)
 {
     if (CheckCanLinkWith(source))
     {
         SetLinkState(LinkState.AcceptingLinks);
     }
 }
Пример #8
0
 /// <inheritdoc/>
 public virtual void StopPhysicalHead()
 {
     headRb     = null;
     headSource = null;
     Destroy(cableJoint);
     cableJoint = null;
     SetOriginalLength(null);
 }
Пример #9
0
 public FeedWriter(IFeedSource <T> feedSource, IFeedDefinition <T> definition, ILinkSource <T> links,
                   IUrlRegistry urls)
 {
     _feedSource = feedSource;
     _definition = definition;
     _links      = links;
     _urls       = urls;
 }
Пример #10
0
 public MediaWriter(IMediaDocument document, ILinkSource <T> links, IUrlRegistry urls,
                    IValueProjection <T> projection)
 {
     _document   = document;
     _links      = links;
     _urls       = urls;
     _projection = projection;
 }
Пример #11
0
 public MediaWriter(IMediaDocument document, ILinkSource <T> links, IUrlRegistry urls, IProjection <T> projection, IServiceLocator services)
 {
     _document   = document;
     _links      = links;
     _urls       = urls;
     _projection = projection;
     _services   = services;
 }
Пример #12
0
        /// <summary>Checks if the link's angle at the target joint is within the limits.</summary>
        /// <remarks>This method takes into consideration the anchor settings.</remarks>
        /// <param name="source">The possible source of the link.</param>
        /// <param name="target">The possible target of the link.</param>
        /// <returns>An error message if the angle is over limit or <c>null</c> otherwise.</returns>
        /// <seealso cref="anchorAtSource"/>
        /// <seealso cref="anchorAtTarget"/>
        protected string CheckAngleLimitAtTarget(ILinkSource source, ILinkTarget target)
        {
            var linkVector = GetSourcePhysicalAnchor(source) - GetTargetPhysicalAnchor(source, target);
            var angle      = Vector3.Angle(target.nodeTransform.rotation * Vector3.forward, linkVector);

            return(targetLinkAngleLimit > 0 && angle > targetLinkAngleLimit
        ? TargetNodeAngleLimitReachedMsg.Format(angle, targetLinkAngleLimit)
        : null);
        }
Пример #13
0
        // Регистрирует пару "объект-наблюдатель"
        public void Register(ILinkSource source, ILinkTarget target)
        {
            if (source == null || target == null || _links.Any(l => l.Item1.Equals(source) && l.Item2.Equals(target)))
            {
                return;
            }

            _links.Add(new Tuple <ILinkSource, ILinkTarget>(source, target));
        }
Пример #14
0
        /// <inheritdoc/>
        public virtual string[] CheckConstraints(ILinkSource source, ILinkTarget target)
        {
            var errors = new[] {
                CheckLengthLimit(source, target),
                CheckAngleLimitAtSource(source, target),
                CheckAngleLimitAtTarget(source, target),
            };

            return(errors.Where(x => x != null).ToArray());
        }
Пример #15
0
 /// <summary>Verifies that part can link with the source.</summary>
 /// <param name="source">Source to check against.</param>
 /// <returns>
 /// <c>true</c> if link is <i>technically</i> possible. It's not guaranteed that the link will
 /// succeed.
 /// </returns>
 protected virtual bool CheckCanLinkWith(ILinkSource source)
 {
     // Cannot attach to itself or incompatible link type.
     if (part != source.part && cfgLinkType == source.cfgLinkType)
     {
         return(true);
     }
     // Link is not allowed.
     return(false);
 }
Пример #16
0
        // Уведомление конкретного получателя
        public void Notify <TTarget>(ILinkSource source, int commandId, Dictionary <string, object> parameters)
        {
            var target = _links.FirstOrDefault(l => l.Item1.Equals(source) && l.Item2.GetType() == typeof(TTarget));

            if (target == null)
            {
                return;
            }
            target.Item2.Update(commandId, parameters);
        }
Пример #17
0
 /// <summary>Cleans up the attach nodes and, optionally, breaks the link.</summary>
 /// <remarks>
 /// The actual changes are delyed till the end of frame. So it's safe to call this method from an
 /// event handler.
 /// </remarks>
 /// <param name="source">The link source at the moemnt of cleanup.</param>
 /// <param name="target">The link target at the moment of cleanup.</param>
 void MaybeBreakLink(ILinkSource source, ILinkTarget target)
 {
     // Delay the nodes cleanup to let the other logic work smoothly. Copy the properties since
     // they will be null'ed on the link destruction.
     AsyncCall.CallOnEndOfFrame(this, () => {
         if (isLinked)
         {
             source.BreakCurrentLink(LinkActorType.Physics);
         }
     });
 }
Пример #18
0
 /// <inheritdoc/>
 public override bool CreateJoint(ILinkSource source, ILinkTarget target)
 {
     if (!base.CreateJoint(source, target))
     {
         return(false);
     }
     trgJoint.angularXMotion = ConfigurableJointMotion.Locked;
     SetLockingMode(persistedLockingMode, updateUi: false);
     SetActiveSteeringState(persistedActiveSteeringEnabled);
     return(true);
 }
Пример #19
0
        public object GetState(ILinkTarget target, ILinkSource source)
        {
            if (target == null || source == null)
            {
                return(null);
            }

            var link = _links.FirstOrDefault(l => l.Item1.Equals(source) && l.Item2.Equals(target));

            return(link == null ? null : link.Item1.GetState());
        }
Пример #20
0
        /// <summary>Returns an anchor for the physical joint at the target part.</summary>
        /// <remarks>
        /// The anchor will be calculated in the source's part scale, and the target's model scale will
        /// be ignored.
        /// </remarks>
        /// <param name="source">The source of the link.</param>
        /// <param name="target">The target of the link.</param>
        /// <returns>The position in the world coordinates.</returns>
        protected Vector3 GetTargetPhysicalAnchor(ILinkSource source, ILinkTarget target)
        {
            var scale = source.nodeTransform.lossyScale;

            if (Mathf.Abs(scale.x - scale.y) > 1e-05 || Mathf.Abs(scale.x - scale.z) > 1e-05)
            {
                HostedDebugLog.Error(this, "Uneven scale on the source part is not supported: {0}",
                                     DbgFormatter.Vector(scale));
            }
            return(target.nodeTransform.position
                   + target.nodeTransform.rotation * (anchorAtTarget * scale.x));
        }
Пример #21
0
        // Запускает обновление наблюдателям
        public void Notify(ILinkSource source, int commandId, Dictionary <string, object> parameters)
        {
            if (source == null)
            {
                return;
            }

            foreach (var link in _links.Where(l => l.Item1.Equals(source)).ToList())
            {
                link.Item2.Update(commandId, parameters);
            }
        }
Пример #22
0
        // Starts a renderer between the source and target.
        public static void StartRendrer(Part part, ILinkSource source, ILinkTarget target)
        {
            // It's a good idea to pre-cache this module in OnStart() method.
            var renderer = part.FindModulesImplementing <ILinkRenderer>()
                           .FirstOrDefault(r => r.cfgRendererName == "MyRendererName");

            if (renderer == null)
            {
                Debug.LogError("Ops! No renderer found");
                return;
            }
            renderer.StartRenderer(source.nodeTransform, target.nodeTransform);
        }
Пример #23
0
        /// <summary>Checks if the link's length is within the limits.</summary>
        /// <remarks>This method takes into consideration the anchor settings.</remarks>
        /// <param name="source">The possible source of the link.</param>
        /// <param name="target">The possible target of the link.</param>
        /// <returns>An error message if link length is over limit or <c>null</c> otherwise.</returns>
        /// <seealso cref="anchorAtSource"/>
        /// <seealso cref="anchorAtTarget"/>
        protected string CheckLengthLimit(ILinkSource source, ILinkTarget target)
        {
            var length = Vector3.Distance(
                GetSourcePhysicalAnchor(source), GetTargetPhysicalAnchor(source, target));

            if (maxLinkLength > 0 && length > maxLinkLength)
            {
                return(MaxLengthLimitReachedMsg.Format(length, maxLinkLength));
            }
            if (minLinkLength > 0 && length < minLinkLength)
            {
                return(MinLengthLimitReachedMsg.Format(length, minLinkLength));
            }
            return(null);
        }
Пример #24
0
        /// <inheritdoc/>
        public virtual void StartPhysicalHead(ILinkSource source, Transform headObjAnchor)
        {
            headRb = headObjAnchor.GetComponentInParent <Rigidbody>();
            if (isHeadStarted || isLinked || headRb == null)
            {
                HostedDebugLog.Error(this,
                                     "Bad link state for the physical head start: isLinked={0}, isHeadStarted={1}, hasRb={2}",
                                     isLinked, isHeadStarted, headRb != null);
                return;
            }
            headSource = source;

            // Attach the head to the source.
            CreateDistanceJoint(source, headRb, headObjAnchor.position);
            SetOriginalLength(deployedCableLength);
        }
Пример #25
0
        /// <inheritdoc/>
        public virtual void StartPhysicalHead(ILinkSource source, Transform headObjAnchor)
        {
            //FIXME: add the physical head module here.
            headRb = headObjAnchor.GetComponentInParent <Rigidbody>();
            if (isHeadStarted || isLinked || headRb == null)
            {
                HostedDebugLog.Error(this,
                                     "Bad link state for the physical head start: isLinked={0}, isHeadStarted={1}, hasRb=[2}",
                                     isLinked, isHeadStarted, headRb != null);
                return;
            }
            headSource         = source;
            headPhysicalAnchor = headObjAnchor;

            // Attach the head to the source.
            CreateDistanceJoint(source, headRb, headObjAnchor.position);
        }
Пример #26
0
 /// <summary>Restores the name and type of the vessels of the former coupled parts.</summary>
 /// <remarks>
 /// The source and target parts need to be separated, but the logical link still need to exist.
 /// On restore the vessel info will be cleared on the module. Alas, when the link is broken
 /// extrenally, the root vessel part cannot be properly restored.
 /// </remarks>
 void RestorePartialVesselInfo(ILinkSource source, ILinkTarget target, bool weDecouple)
 {
     AsyncCall.CallOnEndOfFrame(this, () => {
         var vesselInfo = weDecouple ? persistedSrcVesselInfo : persistedTgtVesselInfo;
         var childPart  = weDecouple ? source.part : target.part;
         if (childPart.vessel.vesselType != vesselInfo.vesselType ||
             childPart.vessel.vesselName != vesselInfo.name)
         {
             HostedDebugLog.Warning(this, "Partially restoring vessel info on {0}: type={1}, name={2}",
                                    childPart, vesselInfo.vesselType, vesselInfo.name);
             childPart.vessel.vesselType = vesselInfo.vesselType;
             childPart.vessel.vesselName = vesselInfo.name;
         }
         persistedSrcVesselInfo = null;
         persistedTgtVesselInfo = null;
     });
 }
Пример #27
0
 /// <inheritdoc/>
 public override void OnBeforeDebugAdjustablesUpdate()
 {
     base.OnBeforeDebugAdjustablesUpdate();
     if (linkState != LinkState.Linked && linkState != LinkState.Available)
     {
         throw new InvalidOperationException("Cannot adjust value in link state: " + linkState);
     }
     dbgOldSource = linkSource;
     if (isLinked)
     {
         var cableJoint = linkSource.linkJoint as ILinkCableJoint;
         if (cableJoint != null)
         {
             cableLength = cableJoint.deployedCableLength;
         }
         linkSource.BreakCurrentLink(LinkActorType.Player);
     }
 }
Пример #28
0
 /// <inheritdoc/>
 public virtual bool CreateJoint(ILinkSource source, ILinkTarget target)
 {
     if (isLinked)
     {
         HostedDebugLog.Error(
             this, "Cannot link the joint which is already linked to: {0}", linkTarget);
         return(false);
     }
     if (!CheckCoupled(source, target))
     {
         var errors = CheckConstraints(source, target);
         if (errors.Length > 0)
         {
             HostedDebugLog.Error(this, "Cannot create joint:\n{0}", DbgFormatter.C2S(errors));
             return(false);
         }
     }
     else
     {
         HostedDebugLog.Fine(this, "The parts are coupled. Skip the constraints check");
     }
     linkSource = source;
     linkTarget = target;
     if (!originalLength.HasValue)
     {
         SetOrigianlLength(Vector3.Distance(
                               GetSourcePhysicalAnchor(source), GetTargetPhysicalAnchor(source, target)));
     }
     isLinked = true;
     // If the parts are already coupled at this moment, then the mode must be set as such.
     coupleOnLinkMode |= isCoupled;
     // Ensure the coupling can be done.
     coupleOnLinkMode &= linkSource.coupleNode != null && linkTarget.coupleNode != null;
     if (coupleOnLinkMode)
     {
         CoupleParts();
     }
     else
     {
         AttachParts();
     }
     return(true);
 }
Пример #29
0
        /// <summary>
        /// Creates a distance joint between the source and an arbitrary physical object.
        /// </summary>
        /// <remarks>It sets the maximum cable length to the persisted value. Even if it's zero!</remarks>
        /// <param name="source">The source of the link.</param>
        /// <param name="tgtRb">The rigidbody of the physical object.</param>
        /// <param name="tgtAnchor">The anchor at the physical object in world coordinates.</param>
        void CreateDistanceJoint(ILinkSource source, Rigidbody tgtRb, Vector3 tgtAnchor)
        {
            var distanceLimit =
                originalLength ?? Vector3.Distance(GetSourcePhysicalAnchor(source), tgtAnchor);
            var joint = source.part.gameObject.AddComponent <ConfigurableJoint>();

            KASAPI.JointUtils.ResetJoint(joint);
            KASAPI.JointUtils.SetupDistanceJoint(
                joint,
                springForce: cableSpringForce, springDamper: cableSpringDamper,
                maxDistance: distanceLimit);
            joint.autoConfigureConnectedAnchor = false;
            joint.anchor = source.part.Rigidbody.transform.InverseTransformPoint(
                GetSourcePhysicalAnchor(source));
            joint.connectedBody   = tgtRb;
            joint.connectedAnchor = tgtRb.transform.InverseTransformPoint(tgtAnchor);
            SetBreakForces(joint);
            SetCustomJoints(new[] { joint });
            cableJoint = joint;
        }
Пример #30
0
        public void AddSource(ILinkSource NewSource)
        {
            List <ILinkingEventHandler> pendinglist;
            ILinkSource testoption;

            if (this._sources.TryGetValue(NewSource.ID, out testoption) == true)
            {
                throw new TsGuiKnownException("Duplicate ID found in LinkableLibrary: " + NewSource.ID, "");
            }
            else
            {
                this._sources.Add(NewSource.ID, NewSource);
            }

            //now register any pending targets and cleanup
            if (this._pendingqueries.TryGetValue(NewSource.ID, out pendinglist) == true)
            {
                foreach (ILinkingEventHandler handler in pendinglist)
                {
                    this.RegisterHandlerToSource(NewSource, handler);
                }
                this._pendingqueries.Remove(NewSource.ID);
            }
        }