示例#1
0
        private void MoveDrop(Part tgtPart, Vector3 pos, Quaternion rot)
        {
            KIS_Shared.DebugLog("Move part");
            ModuleKISPickup modulePickup = GetActivePickupNearest(pos);

            if (modulePickup)
            {
                if (movingPart.parent)
                {
                    bool movingPartMounted   = false;
                    ModuleKISPartMount partM = movingPart.parent.GetComponent <ModuleKISPartMount>();
                    if (partM)
                    {
                        if (partM.PartIsMounted(movingPart))
                        {
                            movingPartMounted = true;
                        }
                    }
                    if (!movingPartMounted)
                    {
                        AudioSource.PlayClipAtPoint(GameDatabase.Instance.GetAudioClip(modulePickup.detachPartSndPath), movingPart.transform.position);
                    }
                }
                AudioSource.PlayClipAtPoint(GameDatabase.Instance.GetAudioClip(modulePickup.dropSndPath), pos);
            }
            KIS_Shared.DecoupleFromAll(movingPart);
            movingPart.transform.position = pos;
            movingPart.transform.rotation = rot;
            KIS_Shared.SendKISMessage(movingPart, KIS_Shared.MessageAction.DropEnd, KISAddonPointer.GetCurrentAttachNode(), tgtPart);
            KISAddonPointer.StopPointer();
            movingPart = null;
        }
示例#2
0
        static void OnMouseEnterPart(Part hoverPart)
        {
            if (hoverPart == partToAttach)
            {
                return;
            }

            if (allowMount)
            {
                ModuleKISPartMount pMount = hoverPart.GetComponent <ModuleKISPartMount>();
                if (pMount)
                {
                    // Set current attach node
                    AttachNode an = attachNodes.Find(f => f.id == pMount.mountedPartNode);
                    if (an != null)
                    {
                        attachNodeIndex = attachNodes.IndexOf(an);
                        SetPointerVisible(false);
                    }
                    else
                    {
                        SetPointerVisible(true);
                    }
                    // Init attach node
                    foreach (KeyValuePair <AttachNode, List <string> > mount in pMount.GetMounts())
                    {
                        if (!mount.Key.attachedPart)
                        {
                            KIS_Shared.AssignAttachIcon(hoverPart, mount.Key, colorMountOk, "KISMount");
                        }
                    }
                }
            }
            if (allowStack && currentAttachNode.nodeType != AttachNode.NodeType.Surface)
            {
                var variant = VariantsUtils.GetCurrentPartVariant(hoverPart);
                if (variant != null)
                {
                    VariantsUtils.ApplyVariantOnAttachNodes(hoverPart, variant);
                }
                foreach (var an in KIS_Shared.GetAvailableAttachNodes(hoverPart, needSrf: false))
                {
                    KIS_Shared.AssignAttachIcon(hoverPart, an, colorStack);
                }
            }
            SendPointerState(pointerTarget, PointerState.OnMouseEnterPart, hoverPart, null);
        }
示例#3
0
 static void OnMouseEnterPart(Part hoverPart)
 {
     if (hoverPart == partToAttach)
     {
         return;
     }
     if (allowMount)
     {
         ModuleKISPartMount pMount = hoverPart.GetComponent <ModuleKISPartMount>();
         if (pMount)
         {
             // Set current attach node
             AttachNode an = attachNodes.Find(f => f.id == pMount.mountedPartNode);
             if (an != null)
             {
                 attachNodeIndex = attachNodes.FindIndex(f => f.id == pMount.mountedPartNode);
                 if (pointer)
                 {
                     UnityEngine.Object.Destroy(pointer);
                 }
             }
             // Init attach node
             foreach (KeyValuePair <AttachNode, List <string> > mount in pMount.GetMounts())
             {
                 if (!mount.Key.attachedPart)
                 {
                     KIS_Shared.AssignAttachIcon(hoverPart, mount.Key, colorMountOk, "KISMount");
                 }
             }
         }
     }
     if (allowStack && GetCurrentAttachNode().nodeType != AttachNode.NodeType.Surface)
     {
         foreach (AttachNode an in hoverPart.attachNodes)
         {
             if (!an.attachedPart)
             {
                 KIS_Shared.AssignAttachIcon(hoverPart, an, colorStack);
             }
         }
     }
     SendPointerState(pointerTarget, PointerState.OnMouseEnterPart, hoverPart, null);
 }
示例#4
0
        public void UpdatePointer()
        {
            // Stop pointer on map
            if (running && MapView.MapIsEnabled)
            {
                StopPointer();
                return;
            }

            // Remove pointer if not running.
            if (!running)
            {
                DestroyPointer();
                return;
            }

            // Hide pointer if the raycast do not hit anything.
            if (pointerTarget == PointerTarget.Nothing)
            {
                SetPointerVisible(false);
                return;
            }

            SetPointerVisible(true);

            // Custom rotation
            float rotDegree = 15;

            if (Input.GetKey(KeyCode.LeftShift))
            {
                rotDegree = 1;
            }
            if (GameSettings.Editor_rollLeft.GetKeyDown())
            {
                customRot -= new Vector3(0, -1, 0) * rotDegree;
            }
            if (GameSettings.Editor_rollRight.GetKeyDown())
            {
                customRot += new Vector3(0, -1, 0) * rotDegree;
            }
            if (GameSettings.Editor_pitchDown.GetKeyDown())
            {
                customRot -= new Vector3(1, 0, 0) * rotDegree;
            }
            if (GameSettings.Editor_pitchUp.GetKeyDown())
            {
                customRot += new Vector3(1, 0, 0) * rotDegree;
            }
            if (GameSettings.Editor_yawLeft.GetKeyDown())
            {
                customRot -= new Vector3(0, 0, 1) * rotDegree;
            }
            if (GameSettings.Editor_yawRight.GetKeyDown())
            {
                customRot += new Vector3(0, 0, 1) * rotDegree;
            }
            if (GameSettings.Editor_resetRotation.GetKeyDown())
            {
                customRot = new Vector3(0, 0, 0);
            }
            Quaternion rotAdjust =
                Quaternion.Euler(0, 0, customRot.z) * Quaternion.Euler(customRot.x, customRot.y, 0);

            // Move to position
            if (pointerTarget == PointerTarget.PartMount)
            {
                //Mount snap
                KIS_Shared.MoveAlign(pointer.transform, pointerNodeTransform, hoveredNode.nodeTransform);
            }
            else if (pointerTarget == PointerTarget.PartNode)
            {
                //Part node snap
                KIS_Shared.MoveAlign(pointer.transform, pointerNodeTransform,
                                     hoveredNode.nodeTransform, rotAdjust);
            }
            else
            {
                KIS_Shared.MoveAlign(pointer.transform, pointerNodeTransform, hit, rotAdjust);
            }

            // Move above
            if (allowOffset)
            {
                if (pointerTarget != PointerTarget.PartMount)
                {
                    if (KIS_Shared.IsKeyDown(offsetUpKey) && aboveDistance < maxOffsetDist)
                    {
                        aboveDistance += aboveOffsetStep;
                    }
                    if (KIS_Shared.IsKeyDown(offsetDownKey) && aboveDistance > -maxOffsetDist)
                    {
                        aboveDistance -= aboveOffsetStep;
                    }
                    if (GameSettings.Editor_resetRotation.GetKeyDown())
                    {
                        aboveDistance = 0;
                    }
                    pointer.transform.position =
                        pointer.transform.position + (hit.normal.normalized * aboveDistance);
                }
            }

            //Check distance
            float sourceDist = 0;

            if (sourceTransform)
            {
                sourceDist =
                    Vector3.Distance(FlightGlobals.ActiveVessel.transform.position, sourceTransform.position);
            }
            float targetDist = Vector3.Distance(FlightGlobals.ActiveVessel.transform.position, hit.point);

            //Set color
            Color color               = colorOk;
            bool  invalidTarget       = false;
            bool  notAllowedOnMount   = false;
            bool  cannotSurfaceAttach = false;
            bool  invalidCurrentNode  = false;
            bool  itselfIsInvalid     = !allowPartItself &&
                                        partToAttach != null && partToAttach.hasIndirectChild(hoveredPart);
            bool restrictedPart =
                allowedAttachmentParts != null && !allowedAttachmentParts.Contains(hoveredPart);

            switch (pointerTarget)
            {
            case PointerTarget.Static:
            case PointerTarget.StaticRb:
                invalidTarget = !allowStatic;
                break;

            case PointerTarget.KerbalEva:
                invalidTarget = !allowEva;
                break;

            case PointerTarget.Part:
                if (allowPart)
                {
                    if (useAttachRules)
                    {
                        if (hoveredPart.attachRules.allowSrfAttach)
                        {
                            invalidCurrentNode = currentAttachNode.nodeType != AttachNode.NodeType.Surface;
                        }
                        else
                        {
                            cannotSurfaceAttach = true;
                        }
                    }
                }
                else
                {
                    invalidTarget = true;
                }
                break;

            case PointerTarget.PartMount:
                if (allowMount)
                {
                    ModuleKISPartMount pMount = hoveredPart.GetComponent <ModuleKISPartMount>();
                    var allowedPartNames      = new List <string>();
                    pMount.GetMounts().TryGetValue(hoveredNode, out allowedPartNames);
                    notAllowedOnMount =
                        partToAttach != null && !allowedPartNames.Contains(partToAttach.partInfo.name);
                    color = colorMountOk;
                }
                break;

            case PointerTarget.PartNode:
                invalidTarget = !allowStack;
                color         = colorStack;
                break;
            }

            // Handle generic "not OK" color.
            if (sourceDist > maxDist || targetDist > maxDist)
            {
                color = colorDistNok;
            }
            else if (invalidTarget || cannotSurfaceAttach || invalidCurrentNode ||
                     itselfIsInvalid || restrictedPart)
            {
                color = colorNok;
            }

            color.a = 0.5f;
            foreach (var mr in allModelRenderers)
            {
                mr.material.color = color;
            }

            //On click.
            if (Input.GetMouseButtonDown(0))
            {
                if (invalidTarget)
                {
                    ScreenMessaging.ShowInfoScreenMessage(TargetObjectNotAllowedMsg);
                    UISounds.PlayBipWrong();
                }
                else if (itselfIsInvalid)
                {
                    ScreenMessaging.ShowInfoScreenMessage(CannotAttachOnItselfMsg);
                    UISounds.PlayBipWrong();
                }
                else if (notAllowedOnMount)
                {
                    ScreenMessaging.ShowInfoScreenMessage(NotAllowedOnTheMountMsg);
                    UISounds.PlayBipWrong();
                }
                else if (cannotSurfaceAttach)
                {
                    ScreenMessaging.ShowInfoScreenMessage(TargetDoesntAllowSurfaceAttachMsg);
                    UISounds.PlayBipWrong();
                }
                else if (invalidCurrentNode)
                {
                    ScreenMessaging.ShowInfoScreenMessage(NodeNotForSurfaceAttachMsg);
                    UISounds.PlayBipWrong();
                }
                else if (sourceDist > maxDist)
                {
                    ScreenMessaging.ShowInfoScreenMessage(TooFarFromSourceMsg.Format(sourceDist, maxDist));
                    UISounds.PlayBipWrong();
                }
                else if (targetDist > maxDist)
                {
                    ScreenMessaging.ShowInfoScreenMessage(TooFarFromTargetMsg.Format(targetDist, maxDist));
                    UISounds.PlayBipWrong();
                }
                else if (restrictedPart)
                {
                    ScreenMessaging.ShowInfoScreenMessage(
                        CannotAttachToPartMsg.Format(hoveredPart.partInfo.title));
                    UISounds.PlayBipWrong();
                }
                else
                {
                    SendPointerClick(pointerTarget, pointer.transform.position, pointer.transform.rotation,
                                     hoveredPart, currentAttachNode.id, hoveredNode);
                }
            }
        }
示例#5
0
        void OnMouseDetachEnterPart(Part part)
        {
            if (!detachActive)
            {
                return;
            }
            detachOk = false;
            if (!HighLogic.LoadedSceneIsFlight)
            {
                return;
            }
            if (KISAddonPointer.isRunning)
            {
                return;
            }
            if (hoverInventoryGui())
            {
                return;
            }
            if (draggedPart)
            {
                return;
            }
            ModuleKISPartDrag  pDrag       = part.GetComponent <ModuleKISPartDrag>();
            ModuleKISItem      item        = part.GetComponent <ModuleKISItem>();
            ModuleKISPartMount parentMount = null;

            if (part.parent)
            {
                parentMount = part.parent.GetComponent <ModuleKISPartMount>();
            }

            // Do nothing if part is EVA
            if (part.vessel.isEVA)
            {
                return;
            }

            // Check part distance
            if (!HasActivePickupInRange(part))
            {
                KISAddonCursor.CursorEnable("KIS/Textures/tooFar", "Too far", "(Move closer to the part)");
                return;
            }


            // Check if part is static attached
            if (item)
            {
                if (item.staticAttached)
                {
                    ModuleKISPickup pickupModule = GetActivePickupNearest(part, canStaticAttachOnly: true);
                    if ((item.allowStaticAttach == 1) || (pickupModule && item.allowStaticAttach == 2))
                    {
                        part.SetHighlightColor(XKCDColors.Periwinkle);
                        part.SetHighlight(true, false);
                        KISAddonCursor.CursorEnable("KIS/Textures/detachOk", "Detach from ground", '(' + part.partInfo.title + ')');
                        detachOk = true;
                        return;
                    }
                    else
                    {
                        if (FlightGlobals.ActiveVessel.isEVA)
                        {
                            KISAddonCursor.CursorEnable("KIS/Textures/needtool", "Tool needed", "(This part can't be detached from the ground without a tool)");
                            return;
                        }
                        else
                        {
                            KISAddonCursor.CursorEnable("KIS/Textures/forbidden", "Not supported", "(Detach from ground function is not supported on this part)");
                            return;
                        }
                    }
                }
            }


            // Check if part can be detached
            if (!parentMount)
            {
                if (part.children.Count > 0 || part.parent)
                {
                    //Part with a child or a parent
                    if (item)
                    {
                        if (item.allowPartAttach == 0)
                        {
                            KISAddonCursor.CursorEnable("KIS/Textures/forbidden", "Can't detach", "(This part can't be detached)");
                            return;
                        }
                        else if (item.allowPartAttach == 2)
                        {
                            ModuleKISPickup pickupModule = GetActivePickupNearest(part, canPartAttachOnly: true);
                            if (!pickupModule)
                            {
                                if (FlightGlobals.ActiveVessel.isEVA)
                                {
                                    KISAddonCursor.CursorEnable("KIS/Textures/needtool", "Tool needed", "(Part can't be detached without a tool)");
                                    return;
                                }
                                else
                                {
                                    KISAddonCursor.CursorEnable("KIS/Textures/forbidden", "Not supported", "(Detach function is not supported on this part)");
                                    return;
                                }
                            }
                        }
                    }
                    else
                    {
                        ModuleKISPickup pickupModule = GetActivePickupNearest(part, canPartAttachOnly: true);
                        if (!pickupModule)
                        {
                            if (FlightGlobals.ActiveVessel.isEVA)
                            {
                                KISAddonCursor.CursorEnable("KIS/Textures/needtool", "Tool needed", "(Part can't be detached without a tool)");
                                return;
                            }
                            else
                            {
                                KISAddonCursor.CursorEnable("KIS/Textures/forbidden", "Not supported", "(Detach function is not supported on this part)");
                                return;
                            }
                        }
                    }
                }
                else
                {
                    // Part without childs and parent
                    return;
                }
            }

            // Check if part is a root
            if (!part.parent)
            {
                KISAddonCursor.CursorEnable("KIS/Textures/forbidden", "Root part", "(Cannot detach a root part)");
                return;
            }

            // Detach icon
            part.SetHighlightColor(XKCDColors.Periwinkle);
            part.SetHighlight(true, false);
            part.parent.SetHighlightColor(XKCDColors.Periwinkle);
            part.parent.SetHighlight(true, false);
            KISAddonCursor.CursorEnable("KIS/Textures/detachOk", "Detach", '(' + part.partInfo.title + ')');
            detachOk = true;
        }
示例#6
0
        void OnMouseGrabEnterPart(Part part)
        {
            if (!grabActive)
            {
                return;
            }
            grabOk = false;
            if (!HighLogic.LoadedSceneIsFlight)
            {
                return;
            }
            if (KISAddonPointer.isRunning)
            {
                return;
            }
            if (hoverInventoryGui())
            {
                return;
            }
            if (draggedPart == part)
            {
                return;
            }
            ModuleKISPartDrag  pDrag       = part.GetComponent <ModuleKISPartDrag>();
            ModuleKISPartMount parentMount = null;

            if (part.parent)
            {
                parentMount = part.parent.GetComponent <ModuleKISPartMount>();
            }
            ModuleKISItem item = part.GetComponent <ModuleKISItem>();

            // Drag part over another one if possible (ex : mount)
            if (draggedPart && pDrag)
            {
                KISAddonCursor.CursorEnable(pDrag.dragIconPath, pDrag.dragText, '(' + pDrag.dragText2 + ')');
                return;
            }

            if (draggedPart)
            {
                KISAddonCursor.CursorDisable();
                return;
            }

            // Do nothing if part is EVA
            if (part.vessel.isEVA)
            {
                return;
            }

            // Check part distance
            if (!HasActivePickupInRange(part))
            {
                KISAddonCursor.CursorEnable("KIS/Textures/tooFar", "Too far", "(Move closer to the part)");
                return;
            }

            // Check part mass
            float pMass         = (part.mass + part.GetResourceMass());
            float pickupMaxMass = GetAllPickupMaxMassInRange(part);

            if (pMass > pickupMaxMass)
            {
                KISAddonCursor.CursorEnable("KIS/Textures/tooHeavy", "Too heavy", "(Bring more kerbal [" + pMass + " > " + pickupMaxMass + ")");
                return;
            }

            // Check if part can be detached and grabbed
            if (!parentMount)
            {
                if (part.children.Count > 0 || part.parent)
                {
                    //Part with a child or a parent
                    if (item)
                    {
                        if (item.allowPartAttach == 0)
                        {
                            KISAddonCursor.CursorEnable("KIS/Textures/forbidden", "Can't grab", "(This part can't be detached)");
                            return;
                        }
                        else if (item.allowPartAttach == 2)
                        {
                            ModuleKISPickup pickupModule = GetActivePickupNearest(part, canPartAttachOnly: true);
                            if (!pickupModule)
                            {
                                if (FlightGlobals.ActiveVessel.isEVA)
                                {
                                    KISAddonCursor.CursorEnable("KIS/Textures/needtool", "Tool needed", "(This part can't be detached without a tool)");
                                    return;
                                }
                                else
                                {
                                    KISAddonCursor.CursorEnable("KIS/Textures/forbidden", "Not supported", "(Detach function is not supported on this part)");
                                    return;
                                }
                            }
                        }
                    }
                    else
                    {
                        ModuleKISPickup pickupModule = GetActivePickupNearest(part, canPartAttachOnly: true);
                        if (!pickupModule)
                        {
                            if (FlightGlobals.ActiveVessel.isEVA)
                            {
                                KISAddonCursor.CursorEnable("KIS/Textures/needtool", "Tool needed", "(This part can't be detached without a tool)");
                                return;
                            }
                            else
                            {
                                KISAddonCursor.CursorEnable("KIS/Textures/forbidden", "Not supported", "(Detach function is not supported on this part)");
                                return;
                            }
                        }
                    }
                }
                else
                {
                    // Part without childs and parent
                    if (item)
                    {
                        if (item.staticAttached && item.allowStaticAttach == 2)
                        {
                            ModuleKISPickup pickupModule = GetActivePickupNearest(part, canStaticAttachOnly: true);
                            if (!pickupModule)
                            {
                                if (FlightGlobals.ActiveVessel.isEVA)
                                {
                                    KISAddonCursor.CursorEnable("KIS/Textures/needtool", "Tool needed", "(This part can't be detached from the ground without a tool)");
                                    return;
                                }
                                else
                                {
                                    KISAddonCursor.CursorEnable("KIS/Textures/forbidden", "Not supported", "(Detach from ground function is not supported on this part)");
                                    return;
                                }
                            }
                        }
                    }
                }
            }

            // check number of part attached
            if (part.parent)
            {
                if (part.children.Count > 0)
                {
                    KISAddonCursor.CursorEnable("KIS/Textures/forbidden", "Can't grab", "(" + (part.children.Count + 1) + " parts is attached to it)");
                    return;
                }
            }
            else
            {
                if (part.children.Count > 1)
                {
                    KISAddonCursor.CursorEnable("KIS/Textures/forbidden", "Can't grab", "(" + part.children.Count + " parts is attached to it)");
                    return;
                }
            }

            // Grab icon
            if (part.children.Count > 0 || part.parent)
            {
                KISAddonCursor.CursorEnable("KIS/Textures/grabOk", "Detach & Grab", '(' + part.partInfo.title + ')');
            }
            else
            {
                KISAddonCursor.CursorEnable("KIS/Textures/grabOk", "Grab", '(' + part.partInfo.title + ')');
            }

            part.SetHighlight(true, false);
            grabOk = true;
        }
示例#7
0
        private void OnPointerAction(KISAddonPointer.PointerTarget pointerTarget, Vector3 pos, Quaternion rot, Part tgtPart, string srcAttachNodeID = null, AttachNode tgtAttachNode = null)
        {
            if (pointerTarget == KISAddonPointer.PointerTarget.PartMount)
            {
                if (movingPart)
                {
                    MoveAttach(tgtPart, pos, rot, srcAttachNodeID, tgtAttachNode);
                }
                else
                {
                    CreateAttach(tgtPart, pos, rot, srcAttachNodeID, tgtAttachNode);
                }
                ModuleKISPartMount pMount = tgtPart.GetComponent <ModuleKISPartMount>();
                if (pMount)
                {
                    pMount.sndFxStore.audio.Play();
                }
            }

            if (pointerTarget == KISAddonPointer.PointerTarget.Part ||
                pointerTarget == KISAddonPointer.PointerTarget.PartNode ||
                pointerTarget == KISAddonPointer.PointerTarget.Static ||
                pointerTarget == KISAddonPointer.PointerTarget.KerbalEva)
            {
                if (pointerMode == PointerMode.Drop)
                {
                    if (movingPart)
                    {
                        MoveDrop(tgtPart, pos, rot);
                    }
                    else
                    {
                        CreateDrop(tgtPart, pos, rot);
                    }
                }
                if (pointerMode == PointerMode.Attach)
                {
                    if (movingPart)
                    {
                        MoveAttach(tgtPart, pos, rot, srcAttachNodeID, tgtAttachNode);
                    }
                    else
                    {
                        CreateAttach(tgtPart, pos, rot, srcAttachNodeID, tgtAttachNode);
                    }
                    // sound
                    ModuleKISPickup modulePickup = GetActivePickupNearest(pos);
                    if (tgtPart)
                    {
                        if (modulePickup)
                        {
                            AudioSource.PlayClipAtPoint(GameDatabase.Instance.GetAudioClip(modulePickup.attachPartSndPath), pos);
                        }
                    }
                }
            }
            draggedItem = null;
            draggedPart = null;
            movingPart  = null;
            KISAddonCursor.CursorDefault();
        }
示例#8
0
        public void UpdatePointer()
        {
            // Stop pointer on map
            if (running && MapView.MapIsEnabled)
            {
                StopPointer();
            }

            // Remove pointer if not running or if the raycast do not hit anything
            if (!running || pointerTarget == PointerTarget.Nothing)
            {
                if (pointer)
                {
                    UnityEngine.Object.Destroy(pointer);
                }
                return;
            }

            //Create pointer if needed
            if (!pointer)
            {
                GameObject modelGo      = partToAttach.FindModelTransform("model").gameObject;
                GameObject pointerModel = Mesh.Instantiate(modelGo, new Vector3(0, 0, 100), Quaternion.identity) as GameObject;
                foreach (Collider col in pointerModel.GetComponentsInChildren <Collider>())
                {
                    UnityEngine.Object.DestroyImmediate(col);
                }

                pointer = new GameObject("KISPointer");
                pointerModel.transform.parent        = pointer.transform;
                pointerModel.transform.localPosition = modelGo.transform.localPosition;
                pointerModel.transform.localRotation = modelGo.transform.localRotation;
                pointer.transform.localScale         = new Vector3(scale, scale, scale);

                allModelMr = new List <MeshRenderer>();
                // Remove attached tube mesh renderer if any
                List <MeshRenderer> tmpAllModelMr = new List <MeshRenderer>(pointerModel.GetComponentsInChildren <MeshRenderer>() as MeshRenderer[]);
                foreach (MeshRenderer mr in tmpAllModelMr)
                {
                    if (mr.name == "KAStube" || mr.name == "KASsrcSphere" || mr.name == "KASsrcTube" || mr.name == "KAStgtSphere" || mr.name == "KAStgtTube")
                    {
                        Destroy(mr);
                        continue;
                    }
                    allModelMr.Add(mr);
                    mr.material = new Material(Shader.Find("Transparent/Diffuse"));
                }
                // Set pointer attach node
                pointerNodeTransform               = new GameObject("KASPointerPartNode").transform;
                pointerNodeTransform.parent        = pointer.transform;
                pointerNodeTransform.localPosition = GetCurrentAttachNode().position;
                pointerNodeTransform.localRotation = KIS_Shared.GetNodeRotation(GetCurrentAttachNode());
            }

            // Custom rotation
            float rotDegree = 15;

            if (Input.GetKey(KeyCode.LeftShift))
            {
                rotDegree = 1;
            }
            if (GameSettings.Editor_rollLeft.GetKeyDown())
            {
                customRot -= new Vector3(0, -1, 0) * rotDegree;
            }
            if (GameSettings.Editor_rollRight.GetKeyDown())
            {
                customRot += new Vector3(0, -1, 0) * rotDegree;
            }
            if (GameSettings.Editor_pitchDown.GetKeyDown())
            {
                customRot -= new Vector3(1, 0, 0) * rotDegree;
            }
            if (GameSettings.Editor_pitchUp.GetKeyDown())
            {
                customRot += new Vector3(1, 0, 0) * rotDegree;
            }
            if (GameSettings.Editor_yawLeft.GetKeyDown())
            {
                customRot -= new Vector3(0, 0, 1) * rotDegree;
            }
            if (GameSettings.Editor_yawRight.GetKeyDown())
            {
                customRot += new Vector3(0, 0, 1) * rotDegree;
            }
            if (GameSettings.Editor_resetRotation.GetKeyDown())
            {
                customRot = new Vector3(0, 0, 0);
            }
            Quaternion rotAdjust = Quaternion.Euler(0, 0, customRot.z) * Quaternion.Euler(customRot.x, customRot.y, 0);

            // Move to position
            if (pointerTarget == PointerTarget.PartMount)
            {
                //Mount snap
                KIS_Shared.MoveAlign(pointer.transform, pointerNodeTransform, hoveredNode.nodeTransform);
                pointer.transform.rotation *= Quaternion.Euler(hoveredNode.orientation);
            }
            else if (pointerTarget == PointerTarget.PartNode)
            {
                //Part node snap
                KIS_Shared.MoveAlign(pointer.transform, pointerNodeTransform, hoveredNode.nodeTransform, rotAdjust);
            }
            else
            {
                KIS_Shared.MoveAlign(pointer.transform, pointerNodeTransform, hit, rotAdjust);
            }

            // Move above
            if (allowOffset)
            {
                if (pointerTarget != PointerTarget.PartMount)
                {
                    if (Input.GetKeyDown(offsetUpKey))
                    {
                        if (aboveDistance < maxOffsetDist)
                        {
                            aboveDistance += aboveOffsetStep;
                        }
                    }
                    if (Input.GetKeyDown(offsetDownKey))
                    {
                        if (aboveDistance > -maxOffsetDist)
                        {
                            aboveDistance -= aboveOffsetStep;
                        }
                    }
                    if (GameSettings.Editor_resetRotation.GetKeyDown())
                    {
                        aboveDistance = 0;
                    }
                    pointer.transform.position = pointer.transform.position + (hit.normal.normalized * aboveDistance);
                }
            }

            //Check distance
            bool isValidSourceDist = true;

            if (sourceTransform)
            {
                isValidSourceDist = Vector3.Distance(FlightGlobals.ActiveVessel.transform.position, sourceTransform.position) <= maxDist;
            }
            bool isValidTargetDist = Vector3.Distance(FlightGlobals.ActiveVessel.transform.position, hit.point) <= maxDist;

            //Set color
            Color color               = colorNok;
            bool  invalidTarget       = false;
            bool  notAllowedOnMount   = false;
            bool  cannotSurfaceAttach = false;
            bool  invalidCurrentNode  = false;
            bool  itselfIsInvalid     = false;

            switch (pointerTarget)
            {
            case PointerTarget.Static:
                if (allowStatic)
                {
                    color = colorOk;
                }
                else
                {
                    invalidTarget = true;
                }
                break;

            case PointerTarget.StaticRb:
                if (allowStatic)
                {
                    color = colorOk;
                }
                else
                {
                    invalidTarget = true;
                }
                break;

            case PointerTarget.KerbalEva:
                if (allowEva)
                {
                    color = colorOk;
                }
                else
                {
                    invalidTarget = true;
                }
                break;

            case PointerTarget.Part:
                if (allowPart)
                {
                    if (hoveredPart == partToAttach && !allowPartItself)
                    {
                        itselfIsInvalid = true;
                    }
                    else
                    {
                        if (useAttachRules)
                        {
                            if (hoveredPart.attachRules.allowSrfAttach)
                            {
                                if (GetCurrentAttachNode().nodeType == AttachNode.NodeType.Surface)
                                {
                                    color = colorOk;
                                }
                                else
                                {
                                    invalidCurrentNode = true;
                                }
                            }
                            else
                            {
                                cannotSurfaceAttach = true;
                            }
                        }
                        else
                        {
                            color = colorOk;
                        }
                    }
                }
                else
                {
                    invalidTarget = true;
                }
                break;

            case PointerTarget.PartMount:
                if (allowMount)
                {
                    ModuleKISPartMount pMount           = hoveredPart.GetComponent <ModuleKISPartMount>();
                    List <string>      allowedPartNames = new List <string>();
                    pMount.GetMounts().TryGetValue(hoveredNode, out allowedPartNames);
                    if (allowedPartNames.Contains(partToAttach.partInfo.name))
                    {
                        color = colorMountOk;
                    }
                    else
                    {
                        color             = colorMountNok;
                        notAllowedOnMount = true;
                    }
                }
                break;

            case PointerTarget.PartNode:
                if (allowStack)
                {
                    color = colorStack;
                }
                else
                {
                    invalidTarget = true;
                }
                break;

            default:
                break;
            }
            if (!isValidSourceDist || !isValidTargetDist)
            {
                color = colorDistNok;
            }
            color.a = 0.5f;
            foreach (MeshRenderer mr in allModelMr)
            {
                mr.material.color = color;
            }


            //On click
            if (Input.GetKeyDown(KeyCode.Mouse0))
            {
                if (invalidTarget)
                {
                    ScreenMessages.PostScreenMessage("Target object is not allowed !");
                    audioBipWrong.Play();
                    return;
                }
                else if (itselfIsInvalid)
                {
                    ScreenMessages.PostScreenMessage("Cannot attach on itself !");
                    audioBipWrong.Play();
                    return;
                }
                else if (notAllowedOnMount)
                {
                    ScreenMessages.PostScreenMessage("This part is not allowed on the mount !");
                    audioBipWrong.Play();
                    return;
                }
                else if (cannotSurfaceAttach)
                {
                    ScreenMessages.PostScreenMessage("Target part do not allow surface attach !");
                    audioBipWrong.Play();
                    return;
                }
                else if (invalidCurrentNode)
                {
                    ScreenMessages.PostScreenMessage("This node cannot be used for surface attach !");
                    audioBipWrong.Play();
                    return;
                }
                else if (!isValidSourceDist)
                {
                    ScreenMessages.PostScreenMessage("Too far from source !");
                    audioBipWrong.Play();
                    return;
                }
                else if (!isValidTargetDist)
                {
                    ScreenMessages.PostScreenMessage("Too far from target !");
                    audioBipWrong.Play();
                    return;
                }
                else
                {
                    SendPointerClick(pointerTarget, pointer.transform.position, pointer.transform.rotation, hoveredPart, GetCurrentAttachNode().id, hoveredNode);
                }
            }
        }