Пример #1
0
        protected virtual void SetSnapJoint(VRTK_InteractableObject interactableObject)
        {
            Rigidbody snapTo = interactableObject.GetComponent <Rigidbody>();

            // No rigidbody on the object, use parenting instead
            if (snapTo != null && !snapByParenting)
            {
                // Remove all forces on the object
                snapTo.useGravity      = false;
                snapTo.velocity        = Vector3.zero;
                snapTo.angularVelocity = Vector3.zero;

                if (attachmentJoint == null)
                {
                    VRTK_Logger.Error(VRTK_Logger.GetCommonMessage(VRTK_Logger.CommonMessageKeys.REQUIRED_COMPONENT_MISSING_FROM_GAMEOBJECT, "SnapInteractionArea:" + name, "Joint", "the same", " because the `Snap Type` is set to `Use Joint`"));
                    return;
                }

                attachmentJoint.connectedBody = snapTo;
            }
            else
            {
                originalParent = interactableObject.transform.parent;

                interactableObject.transform.parent = transform;
            }
        }
Пример #2
0
    private void SetGravity(VRTK_InteractableObject obj, bool useGravity)
    {
        Rigidbody rb = obj.GetComponent <Rigidbody>();

        if (rb == null)
        {
            return;
        }

        if (!useGravity)
        {
            _prevValues.Add(obj, rb.useGravity);

            rb.useGravity = false;
            rb.AddForce(UnityEngine.Random.insideUnitSphere * 30f * rb.mass);
        }
        else
        {
            if (_prevValues.ContainsKey(obj))
            {
                rb.useGravity = _prevValues[obj];
            }
            else
            {
                rb.useGravity = true;
            }
        }
    }
Пример #3
0
 // Update is called once per frame
 void Update()
 {
     wandscript = wand.GetComponent <Wand>();
     if (lgrab.GetGrabbedObject() != null)
     {
         weapon                       = lgrab.GetGrabbedObject();
         controllerevents             = RController.GetComponent <VRTK_ControllerEvents>();
         wandscript.controller        = LController.GetComponent <VRTK_ControllerEvents>();
         swordscript.controllerEvents = LController.GetComponent <VRTK_ControllerEvents>();
     }
     else
     {
         weapon                       = rgrab.GetGrabbedObject();
         controllerevents             = RController.GetComponent <VRTK_ControllerEvents>();
         wandscript.controller        = RController.GetComponent <VRTK_ControllerEvents>();
         swordscript.controllerEvents = RController.GetComponent <VRTK_ControllerEvents>();
     }
     if (controllerevents == null)
     {
         VRTK_Logger.Error(VRTK_Logger.GetCommonMessage(VRTK_Logger.CommonMessageKeys.REQUIRED_COMPONENT_MISSING_FROM_GAMEOBJECT, "VRTK_ControllerEvents_ListenerExample", "VRTK_ControllerEvents", "the same"));
         return;
     }
     controllerevents.ButtonTwoPressed  += DoButtonTwoPressed;
     controllerevents.ButtonTwoReleased += DoButtonTwoReleased;
 }
Пример #4
0
        public override void Initialise(VRTK_InteractableObject currentGrabbdObject, VRTK_InteractGrab currentPrimaryGrabbingObject, VRTK_InteractGrab currentSecondaryGrabbingObject, Transform primaryGrabPoint, Transform secondaryGrabPoint)
        {
            base.Initialise(currentGrabbdObject, currentPrimaryGrabbingObject, currentSecondaryGrabbingObject, primaryGrabPoint, secondaryGrabPoint);

            ParentConstraint parentConstraint = secondaryInteractableToRemove.GetComponent <ParentConstraint>();

            // Make sure that the assigned Interactable Object is still a child of this object
            bool isStillChild = secondaryInteractableToRemove.transform.IsChildOf(transform) || (parentConstraint != null && parentConstraint.sourceCount > 0 && parentConstraint.GetSource(0).sourceTransform == transform);

            if (isStillChild)
            {
                // First, remove from the parent from the secondary object so that it is not affected by it's movement
                if (parentConstraint != null)
                {
                    // Note: We assume that the objects will only have 1 parent here
                    parentConstraint.RemoveSource(0);

                    parentConstraint.constraintActive = false;
                }
                else
                {
                    secondaryInteractableToRemove.transform.parent = null;
                }

                // Set the Grabbable field to true so it can be grabbed
                secondaryInteractableToRemove.isGrabbable = true;
                secondaryInteractableToRemove.GetComponentInChildren <Collider>().enabled = true;
                secondaryInteractableToRemove.GetComponent <Rigidbody>().useGravity       = true;

                // Force grab the object with the secondary grabbing object (the controller/hand) so that it can move with that object's motion
                currentGrabbdObject.ForceStopSecondaryGrabInteraction();
                currentSecondaryGrabbingObject.interactTouch.ForceStopTouching();
                currentSecondaryGrabbingObject.ForceRelease();
                currentSecondaryGrabbingObject.interactTouch.ForceTouch(secondaryInteractableToRemove.gameObject);
                currentSecondaryGrabbingObject.AttemptGrab();

                OnObjectRemovedFromParent(new EventArgs());

                // Enable the GameObject holding the IA that will allow the object to be returned to the parent
                if (returnToParentInteractionAreaObject != null)
                {
                    returnToParentInteractionAreaObject.SetActive(true);
                }
            }
        }
Пример #5
0
 // Use this for initialization
 void Start()
 {
     lgrab    = LController.GetComponent <VRTK_InteractGrab>();
     rgrab    = RController.GetComponent <VRTK_InteractGrab>();
     autograb = RController.GetComponent <VRTK_ObjectAutoGrab>();
     arrowSpawner.SetActive(false);
     isItASword              = true;
     swordscript             = sword.GetComponent <Sword>();
     swordscript.LController = LController;
     swordscript.RController = RController;
 }
    protected override void Start()
    {
        base.Start();

        words = textToEnter.Split(' ');

        flash = keyboard.GetComponent <FlashUntilNear>();

        keyboard.InteractableObjectUsed      += Keyboard_Used;
        keyboard.InteractableObjectUntouched += Keyboard_Untouched;
    }
    public void AllowGrab(VRTK_InteractableObject interactableObject)
    {
        interactableObject.isGrabbable = true;

        var highlighter = interactableObject.GetComponent <VRTK_InteractObjectHighlighter>();

        if (highlighter)
        {
            highlighter.enabled = true;
        }
    }
    /// <summary>
    /// Plants the seed in this Planter instance.
    /// </summary>
    /// <param name="seed">Seed.</param>
    void PlantSeed(VRTK_InteractableObject seed)
    {
        seedInPlanter = seed.GetComponent <Flori_Seed>();
        hasCrop       = true;

        if (seed.name == "If You Dare")
        {
            GameController.Instance.LeaveTheGarden();
        }
        else if (seed.name == "Be Happy")
        {
            LockSeedInPlanter();
            GameController.Instance.OpenIntroPath();
        }
    }
Пример #9
0
        public override void Initialise(VRTK_InteractableObject currentGrabbdObject, VRTK_InteractGrab currentPrimaryGrabbingObject, VRTK_InteractGrab currentSecondaryGrabbingObject, Transform primaryGrabPoint, Transform secondaryGrabPoint)
        {
            base.Initialise(currentGrabbdObject, currentPrimaryGrabbingObject, currentSecondaryGrabbingObject, primaryGrabPoint, secondaryGrabPoint);
            initialPosition = currentGrabbdObject.transform.localPosition;
            initialRotation = currentGrabbdObject.transform.localRotation;

            initialCameraRigRotation = cameraRig.localRotation;

            offset = Quaternion.Inverse(initialCameraRigRotation);

            joint = currentGrabbdObject.GetComponent <ConfigurableJoint> ();
            joint.angularYMotion = ConfigurableJointMotion.Free;
            joint.angularXMotion = ConfigurableJointMotion.Free;
            //joint.angularYMotion = ConfigurableJointMotion.Free;
            //limit = joint.angularYLimit;
            //limit.limit = 105f;

            StopRealignOnRelease();
        }
Пример #10
0
    private void OnTriggerStay(Collider other)
    {
        if (!other.CompareTag("SlitPlate") || snappedPlate)
        {
            return;
        }

        VRTK_InteractableObject plate = other.GetComponent <VRTK_InteractableObject>();

        if (!plate || plate.IsGrabbed())
        {
            return;
        }

        snappedPlate = plate;
        StorePreviousState();

        snappedPlate.transform.position   = Vector3.Lerp(plateHandleBodyRight.transform.position, plateHandleBodyLeft.transform.position, 0.5f);
        snappedPlate.transform.rotation   = Quaternion.Euler(90, 0, 0);
        snappedPlate.transform.localScale = plateScale;

        // Create Handle Joints
        FixedJoint handleJointRight = snappedPlate.gameObject.AddComponent <FixedJoint>();

        handleJointRight.connectedBody = plateHandleBodyRight;

        FixedJoint handleJointLeft = snappedPlate.gameObject.AddComponent <FixedJoint>();

        handleJointLeft.connectedBody = plateHandleBodyLeft;

        snappedPlate.GetComponent <Rigidbody>().constraints = RigidbodyConstraints.FreezeRotation | RigidbodyConstraints.FreezePositionY;

        snappedPlate.InteractableObjectGrabbed += OnSnappedPlateGrabbed;

        RegisterPlateWaveGenerators();
    }
Пример #11
0
 private void StorePreviousState()
 {
     previousPlateScale           = snappedPlate.transform.localScale;
     previousPlateBodyConstraints = snappedPlate.GetComponent <Rigidbody>().constraints;
 }
Пример #12
0
    /// <summary>
    /// Set Grabbed the cable end to be kinematic to rope.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void InteractObject_InteractableObjectGrabbed(object sender, InteractableObjectEventArgs e)
    {
        VRTK_InteractableObject Sender = (VRTK_InteractableObject)sender;

        Sender.GetComponent <ObiRigidbody>().kinematicForParticles = true;
    }
Пример #13
0
    // Update is called once per frame
    void Update()
    {
        if (!StaticData.isTapeAttachBothHands() && StaticData.getIsCut())
        {
            setControllerHighlight(CurState.singleAttach);
        }

        // after attach to both hands, show the first hint
        if (StaticData.isTapeAttachBothHands() && cur == 0)
        {
            // TODO: modify to handle different model

            // turn on the hint of trail renderer
            string modelName = StaticData.getTargetNumName();
            // GameObject.Find("fcum").transform.GetChild(0).gameObject.SetActive(true);
            GameObject.Find(modelName).transform.GetChild(0).gameObject.SetActive(true);

            // turn on step buttons
            hint[cur].GetComponent <MeshRenderer>().enabled = true;
            ParticleSystem particleSystem = hint[cur].GetComponent <ParticleSystem>();
            if (!particleSystem.isPlaying)
            {
                particleSystem.Play();
            }

            // turn on tooltips
            hint[cur].transform.GetChild(0).gameObject.SetActive(true);

            // turn on audio hint
            if (!audioHint[cur])
            {
                hint[cur].GetComponent <AudioSource>().Play(0);
                audioHint[cur] = true;
            }

            // set up highlighter
            setControllerHighlight(CurState.leftStep);
        }

        if (StaticData.isTapeAttachBothHands() && cur < hint.Length)
        {
            // set up highlighter
            if (cur < hint.Length - 1)
            {
                setControllerHighlight(CurState.leftStep);
            }
            else
            {
                setControllerHighlight(CurState.rightStep);
            }

            VRTK_InteractableObject stickBtn = hint[cur].GetComponent <VRTK_InteractableObject>();
            if (stickBtn.IsTouched())
            {
                ParticleSystem particleSystem = hint[cur].GetComponent <ParticleSystem>();
                if (!particleSystem.isStopped)
                {
                    particleSystem.Stop();
                }
                MeshRenderer color = stickBtn.GetComponent <MeshRenderer>();
                color.material = Resources.Load("activeBtn") as Material;
            }
            else
            {
                ParticleSystem particleSystem = hint[cur].GetComponent <ParticleSystem>();
                if (!particleSystem.isPlaying)
                {
                    particleSystem.Play();
                }
                MeshRenderer color = stickBtn.GetComponent <MeshRenderer>();
                color.material = Resources.Load("orange") as Material;
            }

            if (stickBtn != null && stickBtn.IsUsing())
            {
                // fix current position
                GameObject handler = getCurHandler();


                handler.transform.SetParent(stickPos[cur].transform);
                handler.transform.localPosition = new Vector3(0.0f, 0.0f, 0.0f);
                if (cur != hint.Length - 1)
                {
                    handler.transform.localRotation = Quaternion.Euler(new Vector3(0.0f, 0.0f, 0.0f));
                }
                handler.GetComponent <ObiParticleHandle>().enabled = true;


                // move on to next position
                leftController       = GameObject.Find("left_hand");
                leftCollider.enabled = true;


                ObiPinConstraints     pinConstraints     = obiCloth.GetComponent <ObiPinConstraints>();
                ObiPinConstraintBatch pinConstraintBatch = pinConstraints.GetFirstBatch();

                pinConstraints.RemoveFromSolver(null);


                // remove previous position constraints first
                // if (cur == 0)
                // {
                // do nothing
                // no constraint at the left hand side
                // }
                if (cur == 1)
                {
                    pinConstraintBatch.RemoveConstraint(3);
                    pinConstraintBatch.RemoveConstraint(2);
                }
                if (cur == 2)
                {
                    pinConstraintBatch.RemoveConstraint(3);
                    pinConstraintBatch.RemoveConstraint(2);
                }
                if (cur == 3)
                {
                    pinConstraintBatch.RemoveConstraint(1);
                    pinConstraintBatch.RemoveConstraint(0);
                }

                // add next position constraint
                if (cur == 0 || cur == 1)
                {
                    pinConstraintBatch.AddConstraint(leftAttachNode[cur * 2], leftCollider, offset, restDarboux, 1);
                    pinConstraintBatch.AddConstraint(leftAttachNode[cur * 2 + 1], leftCollider, offsetNeg, restDarboux, 1);
                }

                pinConstraints.AddToSolver(null);

                // turn off the current hint
                hint[cur].GetComponent <MeshRenderer>().enabled = false;
                ParticleSystem ps = hint[cur].GetComponent <ParticleSystem>();
                if (!ps.isStopped)
                {
                    ps.Stop();
                }
                hint[cur].transform.GetChild(0).gameObject.SetActive(false);

                ++cur;
                StaticData.setCurTapingStep(cur);

                // set up last step highlight
                if (cur == hint.Length - 1)
                {
                    setControllerHighlight(CurState.rightStep);
                }

                // turn on the next hint
                if (cur < hint.Length)
                {
                    hint[cur].GetComponent <MeshRenderer>().enabled = true;
                    ParticleSystem particleSystem = hint[cur].GetComponent <ParticleSystem>();
                    if (!particleSystem.isPlaying)
                    {
                        particleSystem.Play();
                    }

                    // turn on tooltip
                    hint[cur].transform.GetChild(0).gameObject.SetActive(true);

                    // turn on audio hint
                    if (!audioHint[cur])
                    {
                        hint[cur].GetComponent <AudioSource>().Play(0);
                        audioHint[cur] = true;
                    }
                }

                // Last step: use right hand to attach
                if (cur == hint.Length - 1)
                {
                    // set lefthand gesture unhold
                    setHandUnhold("[VRTK_SDKManager]/SDKSetups/SteamVR/[CameraRig]/Controller (left)/LeftController/VRTK_BasicHand/LeftHand");

                    rightHandler    = GameObject.Find("right_hand");
                    rightController = VRTK_DeviceFinder.GetControllerRightHand();
                }
            }
        }
        else if (StaticData.isTapeAttachBothHands() && cur >= hint.Length)
        {  // finish all steps
            // clear highlighter
            setControllerHighlight(CurState.finished);

            // set rightHand gesture unhold
            setHandUnhold("[VRTK_SDKManager]/SDKSetups/SteamVR/[CameraRig]/Controller (right)/RightController/VRTK_BasicHand/RightHand");

            // count 5 secs to reload main scene
            timeRemaining -= Time.deltaTime;
            if (timeRemaining <= 0)
            {
                Debug.Log("finish taping");
                SceneManager.LoadScene("testMain");
            }
        }
    }
Пример #14
0
    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        VRTK_InteractableObject targ = (VRTK_InteractableObject)target;

        GUILayout.Space(10);
        GUIStyle  guiStyle      = EditorStyles.foldout;
        FontStyle previousStyle = guiStyle.fontStyle;

        guiStyle.fontStyle = FontStyle.Bold;
        viewTouch          = EditorGUILayout.Foldout(viewTouch, "Touch Options", guiStyle);
        guiStyle.fontStyle = previousStyle;
        GUILayout.Space(2);
        if (viewTouch)
        {
            EditorGUI.indentLevel++;

            targ.highlightOnTouch = EditorGUILayout.Toggle("Highlight on Touch:", targ.highlightOnTouch);
            if (targ.highlightOnTouch)
            {
                targ.touchHighlightColor = EditorGUILayout.ColorField("Touch Highlight Color:", targ.touchHighlightColor);
            }

            GUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("Rumble on Touch:");
            EditorGUI.indentLevel--;
            GUILayout.Label("Strength", GUILayout.MinWidth(49f));
            float x = EditorGUILayout.FloatField(targ.rumbleOnTouch.x, GUILayout.MinWidth(10f));
            GUILayout.Label("Duration", GUILayout.MinWidth(50f));
            float y = EditorGUILayout.FloatField(targ.rumbleOnTouch.y, GUILayout.MinWidth(10f));
            targ.rumbleOnTouch = new Vector2(y, x);
            EditorGUI.indentLevel++;
            GUILayout.EndHorizontal();

            targ.allowedTouchControllers = (VRTK_InteractableObject.AllowedController)EditorGUILayout.EnumPopup("Allowed Touch Controllers:", targ.allowedTouchControllers);
            targ.hideControllerOnTouch   = (VRTK_InteractableObject.ControllerHideMode)EditorGUILayout.EnumPopup("Hide Controller On Touch:", targ.hideControllerOnTouch);

            EditorGUI.indentLevel--;
        }

        //Grab Layout
        GUILayout.Space(10);
        targ.isGrabbable = EditorGUILayout.Toggle("Is Grabbable:", targ.isGrabbable);
        if (targ.isGrabbable)
        {
            guiStyle           = EditorStyles.foldout;
            previousStyle      = guiStyle.fontStyle;
            guiStyle.fontStyle = FontStyle.Bold;
            viewGrab           = EditorGUILayout.Foldout(viewGrab, "Grab Options", guiStyle);
            guiStyle.fontStyle = previousStyle;
            GUILayout.Space(2);
            if (viewGrab)
            {
                EditorGUI.indentLevel++;

                targ.isDroppable        = EditorGUILayout.Toggle("Is Droppable:", targ.isDroppable);
                targ.isSwappable        = EditorGUILayout.Toggle("Is Swappable:", targ.isSwappable);
                targ.holdButtonToGrab   = EditorGUILayout.Toggle("Hold Button To Grab:", targ.holdButtonToGrab);
                targ.grabOverrideButton = (VRTK_ControllerEvents.ButtonAlias)EditorGUILayout.EnumPopup("Grab Override Button:", targ.grabOverrideButton);

                GUILayout.BeginHorizontal();
                EditorGUILayout.PrefixLabel("Rumble on Grab:");
                EditorGUI.indentLevel--;
                GUILayout.Label("Strength", GUILayout.MinWidth(49f));
                float x = EditorGUILayout.FloatField(targ.rumbleOnGrab.x, GUILayout.MinWidth(10f));
                GUILayout.Label("Duration", GUILayout.MinWidth(50f));
                float y = EditorGUILayout.FloatField(targ.rumbleOnGrab.y, GUILayout.MinWidth(10f));
                targ.rumbleOnGrab = new Vector2(y, x);
                EditorGUI.indentLevel++;
                GUILayout.EndHorizontal();

                targ.allowedGrabControllers = (VRTK_InteractableObject.AllowedController)EditorGUILayout.EnumPopup("Allowed Controllers:", targ.allowedGrabControllers);
                targ.precisionSnap          = EditorGUILayout.Toggle("Precision Snap:", targ.precisionSnap);
                if (!targ.precisionSnap)
                {
                    targ.rightSnapHandle = EditorGUILayout.ObjectField("Right Snap Handle:", targ.rightSnapHandle, typeof(Transform), true) as Transform;
                    targ.leftSnapHandle  = EditorGUILayout.ObjectField("Left Snap Handle:", targ.leftSnapHandle, typeof(Transform), true) as Transform;
                }
                targ.hideControllerOnGrab  = (VRTK_InteractableObject.ControllerHideMode)EditorGUILayout.EnumPopup("Hide Controller On Grab:", targ.hideControllerOnGrab);
                targ.stayGrabbedOnTeleport = EditorGUILayout.Toggle("Stay Grabbed on Teleport:", targ.stayGrabbedOnTeleport);
                targ.grabAttachMechanic    = (VRTK_InteractableObject.GrabAttachType)EditorGUILayout.EnumPopup("Grab Attach Mechanic:", targ.grabAttachMechanic);
                if (targ.grabAttachMechanic == VRTK_InteractableObject.GrabAttachType.Fixed_Joint || targ.grabAttachMechanic == VRTK_InteractableObject.GrabAttachType.Spring_Joint ||
                    targ.grabAttachMechanic == VRTK_InteractableObject.GrabAttachType.Track_Object || targ.grabAttachMechanic == VRTK_InteractableObject.GrabAttachType.Rotator_Track)
                {
                    targ.detachThreshold = EditorGUILayout.FloatField("Detach Threshold:", targ.detachThreshold);
                    if (targ.grabAttachMechanic == VRTK_InteractableObject.GrabAttachType.Spring_Joint)
                    {
                        targ.springJointStrength = EditorGUILayout.FloatField("Spring Joint Strength:", targ.springJointStrength);
                        targ.springJointDamper   = EditorGUILayout.FloatField("Spring Joint Damper:", targ.springJointDamper);
                    }
                }
                targ.throwMultiplier      = EditorGUILayout.FloatField("Throw Multiplier:", targ.throwMultiplier);
                targ.onGrabCollisionDelay = EditorGUILayout.FloatField("On Grab Collision Delay:", targ.onGrabCollisionDelay);

                EditorGUI.indentLevel--;
            }
        }

        GUILayout.Space(10);
        targ.isUsable = EditorGUILayout.Toggle("Is Usable:", targ.isUsable);
        if (targ.isUsable)
        {
            guiStyle           = EditorStyles.foldout;
            previousStyle      = guiStyle.fontStyle;
            guiStyle.fontStyle = FontStyle.Bold;
            viewUse            = EditorGUILayout.Foldout(viewUse, "Use Options", guiStyle);
            guiStyle.fontStyle = previousStyle;
            GUILayout.Space(2);
            if (viewUse)
            {
                EditorGUI.indentLevel++;

                targ.useOnlyIfGrabbed          = EditorGUILayout.Toggle("Use Only If Grabbed: ", targ.useOnlyIfGrabbed);
                targ.holdButtonToUse           = EditorGUILayout.Toggle("Hold Button To Use: ", targ.holdButtonToUse);
                targ.useOverrideButton         = (VRTK_ControllerEvents.ButtonAlias)EditorGUILayout.EnumPopup("Use Override Button:", targ.useOverrideButton);
                targ.pointerActivatesUseAction = EditorGUILayout.Toggle("Pointer Activates Use Action: ", targ.pointerActivatesUseAction);

                GUILayout.BeginHorizontal();
                EditorGUILayout.PrefixLabel("Rumble on Use:");
                EditorGUI.indentLevel--;
                GUILayout.Label("Strength", GUILayout.MinWidth(49f));
                float x = EditorGUILayout.FloatField(targ.rumbleOnUse.x, GUILayout.MinWidth(10f));
                GUILayout.Label("Duration", GUILayout.MinWidth(50f));
                float y = EditorGUILayout.FloatField(targ.rumbleOnUse.y, GUILayout.MinWidth(10f));
                targ.rumbleOnUse = new Vector2(y, x);
                EditorGUI.indentLevel++;
                GUILayout.EndHorizontal();

                targ.allowedUseControllers = (VRTK_InteractableObject.AllowedController)EditorGUILayout.EnumPopup("Allowed Use Controllers:", targ.allowedUseControllers);
                targ.hideControllerOnUse   = (VRTK_InteractableObject.ControllerHideMode)EditorGUILayout.EnumPopup("Hide Controller On Use:", targ.hideControllerOnUse);

                EditorGUI.indentLevel--;
            }
        }

        if (targ.GetComponent <VRTK_InteractableObject>().GetType().IsSubclassOf(typeof(VRTK_InteractableObject)))
        {
            GUILayout.Space(10);
            guiStyle           = EditorStyles.foldout;
            previousStyle      = guiStyle.fontStyle;
            guiStyle.fontStyle = FontStyle.Bold;
            viewCustom         = EditorGUILayout.Foldout(viewCustom, "Custom Options", guiStyle);
            guiStyle.fontStyle = previousStyle;
            GUILayout.Space(2);
            if (viewCustom)
            {
                DrawPropertiesExcluding(serializedObject, new string[] { "hideControllerOnUse", "allowedUseControllers", "rumbleOnUse", "pointerActivatesUseAction", "useOverrideButton",
                                                                         "holdButtonToUse", "useOnlyIfGrabbed", "throwMultiplier", "onGrabCollisionDelay", "springJointDamper", "springJointStrength", "detachThreshold", "grabAttachMechanic", "stayGrabbedOnTeleport",
                                                                         "hideControllerOnGrab", "leftSnapHandle", "rightSnapHandle", "precisionSnap", "allowedGrabControllers", "rumbleOnGrab", "grabOverrideButton", "holdButtonToGrab", "isSwappable", "isDroppable",
                                                                         "isGrabbable", "hideControllerOnTouch", "allowedTouchControllers", "rumbleOnTouch", "touchHighlightColor", "highlightOnTouch", "isUsable" });
            }
        }
        serializedObject.ApplyModifiedProperties();
    }