/// <inheritdoc/> public override void OnPartDie() { base.OnPartDie(); // Make sure the connector is locked into the winch to not leave it behind. if (connectorObj != null) { // Don't relay on the connector state machine, it will try to destroy immediately. KASInternalPhysicalConnector.Demote(connectorObj.gameObject, true); } SetConnectorState(ConnectorState.Locked); }
/// <summary>Converts a physical connector back into the physicsless model.</summary> /// <remarks>It's a cleanup method that must always succeed.</remarks> void StopPhysicsOnConnector() { if (connectorObj == null || !linkRenderer.isStarted) { return; // Nothing to do. } HostedDebugLog.Info(this, "Make the cable connector non-physical"); linkRenderer.StopRenderer(); cableJoint.StopPhysicalHead(); KASInternalPhysicalConnector.Demote(connectorObj.gameObject, false); Destroy(connectorObj.gameObject); connectorObj = null; part.mass += connectorMass; part.rb.mass += connectorMass; SaveConnectorModelPosAndRot(); }
/// <summary> /// Makes the winch connector an idependent physcal onbject or returns it into a part's model as /// a physicsless object. /// </summary> /// <remarks> /// Note, that physics objects on the connector don't die in this method call. They will be /// cleaned up at the frame end. The caller must consider it when dealing with the connector. /// </remarks> /// <param name="state">The physical state of the connector: <c>true</c> means "physical".</param> void TurnConnectorPhysics(bool state) { if (state && cableJoint.headRb == null) { HostedDebugLog.Info(this, "Make the cable connector physical"); var connector = KASInternalPhysicalConnector.Promote( this, connectorModelObj.gameObject, connectorInteractDistance); cableJoint.StartPhysicalHead(this, connectorCableAnchor); connector.connectorRb.mass = connectorMass; part.mass -= connectorMass; part.rb.mass -= connectorMass; } else if (!state && cableJoint.headRb != null) { HostedDebugLog.Info(this, "Make the cable connector non-physical"); cableJoint.StopPhysicalHead(); KASInternalPhysicalConnector.Demote(connectorModelObj.gameObject); part.mass += connectorMass; part.rb.mass += connectorMass; } }
/// <summary>Converts a physicsless connector model into a physical object.</summary> void StartPhysicsOnConnector() { HostedDebugLog.Info(this, "Make the cable connector physical"); var connectorPosAndRot = gameObject.transform.TransformPosAndRot(persistedConnectorPosAndRot); var connectorModel = GetConnectorModel(); var pipeAttach = GetConnectorModelPipeAnchor(); var partAttach = GetConnectorModelPartAnchor(); // Make a physical object and attach renderer to it. This will make connector following physics. // Adjust pipe and part transforms the same way as in the connector. connectorObj = new GameObject( "physicalConnectorObj" + part.launchID + "-" + linkRendererName).transform; connectorObj.SetPositionAndRotation(connectorModel.position, connectorModel.rotation); var physPartAttach = new GameObject(partAttach.name + "-reverseAnchor").transform; physPartAttach.SetPositionAndRotation( partAttach.position, Quaternion.LookRotation(-partAttach.forward, -partAttach.up)); physPartAttach.parent = connectorObj; var physPipeAttachObj = new GameObject(pipeAttach.name + "-Anchor").transform; physPipeAttachObj.parent = connectorObj; physPipeAttachObj.SetPositionAndRotation(pipeAttach.position, pipeAttach.rotation); connectorObj.SetPositionAndRotation(connectorPosAndRot.pos, connectorPosAndRot.rot); var connector = KASInternalPhysicalConnector.Promote( this, connectorObj.gameObject, connectorInteractDistance); connector.connectorRb.mass = connectorMass; part.mass -= connectorMass; part.rb.mass -= connectorMass; linkRenderer.StartRenderer(nodeTransform, physPartAttach); Colliders.UpdateColliders(connectorModel.gameObject); cableJoint.StartPhysicalHead(this, physPipeAttachObj); SaveConnectorModelPosAndRot(); }
/// <inheritdoc/> public void OnGUI() { var thisVesselIsActive = FlightGlobals.ActiveVessel == vessel; var pickupConnector = thisVesselIsActive && linkState == LinkState.Available ? closestConnector : null; if (pickupConnector != _focusedPickupConnector) { if (_focusedPickupConnector != null) { _focusedPickupConnector.SetHighlighting(null); } _focusedPickupConnector = pickupConnector; if (_focusedPickupConnector != null && closestConnectorHighlightColor != Color.black) { _focusedPickupConnector.SetHighlighting(closestConnectorHighlightColor); } } // Remove hints if any. if (!isLinked || !thisVesselIsActive) { ScreenMessages.RemoveMessage(_dropConnectorMessage); UpdateContextMenu(); } if (pickupConnector == null) { ScreenMessages.RemoveMessage(_pickupConnectorMessage); UpdateContextMenu(); } if (!thisVesselIsActive) { return; // No GUI for the inactive vessel. } // Handle the cable head drop/pickup events. if (Event.current.Equals(_dropConnectorKeyEvent) && isLinked) { Event.current.Use(); linkSource.BreakCurrentLink(LinkActorType.Player); } if (Event.current.Equals(_pickupConnectorKeyEvent) && pickupConnector != null) { Event.current.Use(); PickupConnectorEvent(); } // Show the head drop hint message. if (isLinked) { _dropConnectorMessage.message = DropConnectorHintMsg.Format(_dropConnectorKeyEvent); ScreenMessages.PostScreenMessage(_dropConnectorMessage); } if (pickupConnector != null) { _pickupConnectorMessage.message = PickupConnectorHintMsg.Format(_pickupConnectorKeyEvent); ScreenMessages.PostScreenMessage(_pickupConnectorMessage); } UpdateContextMenu(); }