//---------------------------------------------------------------------------------- // Monobehaviour #region Monobehaviour void Start() { //load material props, if required. if (this.materialDataBase != null) { if (this.materialDataBase.Length == 0) { this.materialDataBase = SenseGlove_Material.baseFileName; } SenseGloveMats.MaterialLibraries.LoadLibrary(Application.dataPath + "/", this.materialDataBase); } if (this.materialName.Length > 0) { this.materialName = this.materialName.Split(new char[] { ' ' }, System.StringSplitOptions.RemoveEmptyEntries)[0]; //remove spaces } if (this.material == VirtualMaterial.FromDataBase) { this.LoadMaterialProps(); } else if (this.material != VirtualMaterial.Custom) { this.LoadMaterialProps(this.material); //don't load yield distances if the material has been edited? } //load grab options this.myInteractable = this.gameObject.GetComponent <SenseGlove_Interactable>(); if (myInteractable == null && this.mustBeGrabbed) { this.mustBeGrabbed = false; //we cannot require this material to be grabbed if it's not an interactable. } }
//Fires during initalization private void Start() { if (this.linkedObject == null) { this.linkedObject = this.GetComponent <SenseGlove_Interactable>(); } }
//-------------------------------------------------------------------------------------------------------------------------- // Collision Detection / Force Feedback #region Collision // Called when this object enters the collider of another object void OnTriggerEnter(Collider col) { if (this.touchedObject == null) { SenseGlove_Material material = col.GetComponent <SenseGlove_Material>(); SenseGlove_Interactable interactable = col.GetComponent <SenseGlove_Interactable>(); if (material || interactable) { // SenseGlove_Debugger.Log("Touching " + col.name + "; material = " + (material != null) + ", interactable = " + (interactable != null)); this.touchedObject = col.gameObject; this.touchedScript = interactable; this.touchedMaterial = material; this.touchedDeform = col.GetComponent <SenseGlove_MeshDeform>(); if (this.handModel.forceFeedback == ForceFeedbackType.Simple && material) { this.motorLevel = material.maxForce; } else if (this.handModel.forceFeedback == ForceFeedbackType.MaterialBased) { this.FindForceDirection(col); this.motorLevel = 0; //still 0 since OP == EO } if (material && material.hapticFeedback) { this.buzzLevel = material.hapticMagnitude; this.buzzTime = material.hapticDuration; } } } }
/// <summary> CHeck if this script wishes to release objects at the moment. </summary> /// <returns></returns> protected override bool CanRelease(SenseGlove_Interactable obj) { if (obj.releaseMethod == ReleaseMethod.MustOpenHand) { return(!this.wantsGrab[0] && !this.wantsGrab[1]); //only index and thumb atm. } return(base.CanRelease(obj)); }
// Called when this object exits the collider of another object void OnTriggerExit(Collider col) { if (this.IsTouching(col.gameObject)) { this.touchedObject = null; this.touchedScript = null; } }
/// <summary> Return a list of GameObjects that this script is Currently Interacting with. </summary> /// <returns></returns> public virtual SenseGlove_Interactable[] HeldObjects() { SenseGlove_Interactable[] objects = new SenseGlove_Interactable[this.heldObjects.Count]; for (int i = 0; i < this.heldObjects.Count; i++) { objects[i] = this.heldObjects[i]; } return(objects); }
//-------------------------------------------------------------------------------------------------------------------------- // Collision Detection / Force Feedback // Called when this object enters the collider of another object protected virtual void OnTriggerEnter(Collider col) { SenseGlove_Interactable interact = col.attachedRigidbody != null?col.attachedRigidbody.GetComponent <SenseGlove_Interactable>() : col.GetComponent <SenseGlove_Interactable>(); if (interact != null) { interact.TouchedBy(this); if (this.touchedObject == null) { //if (!this.IsTouching(col.gameObject)) //{ // //touching a new object! //} this.touchedObject = interact.gameObject; this.touchedScript = interact; if (this.touchedObject.transform.parent != null) { if (this.touchedObject.transform.parent.name == "Tastatur" && this.name == "indexPickupCollider") { this.transform.root.GetComponent <SenseGlove_Object>().SendBuzzCmd(new bool[5] { false, true, false, false, false }, 100, 50); GlobalCtrl text = this.transform.root.GetComponent <GlobalCtrl>(); text.textChange(this.touchedObject); } else if (this.touchedObject.transform.parent.name == "GUILoad" && this.name == "indexPickupCollider") { this.transform.root.GetComponent <SenseGlove_Object>().SendBuzzCmd(new bool[5] { false, true, false, false, false }, 100, 50); if (this.touchedObject.name == "Down") { GlobalCtrl.updown += 1; } else if (this.touchedObject.name == "Up" && GlobalCtrl.updown >= 1) { GlobalCtrl.updown -= 1; } else if (this.touchedObject.name.StartsWith("Platz")) { List <atomData> loadFile = new List <atomData>(); loadFile = (List <atomData>)CFileHelper.LoadData(Application.dataPath + "/MoleculeFiles/" + touchedObject.transform.GetChild(0).GetComponent <Text>().text, typeof(List <atomData>)); this.transform.root.GetComponent <GlobalCtrl>().loadMolecule(loadFile); } else if (this.touchedObject.name == "ExitLoadGui") { GlobalCtrl.loadGUI = false; GameObject.Find("GUILoad").SetActive(false); molecule.SetActive(true); } } } } } }
/// <summary> Check if a SenseGlove_Interactable is already connected to this GrabZone. </summary> /// <param name="obj"></param> /// <returns></returns> private int ConnectionIndex(SenseGlove_Interactable obj) { for (int i = 0; i < this.connectedTo.Count; i++) { if (GameObject.ReferenceEquals(this.connectedTo[i].gameObject, obj.gameObject)) { return(i); } } return(-1); }
/// <summary> This script can also check via simple gestures. </summary> /// <param name="obj"></param> /// <returns></returns> protected override bool WantsRelease(SenseGlove_Interactable obj) { if (obj.CanInteract()) //separate if statement to catch more releaseMethods. { if (obj.releaseMethod == ReleaseMethod.MustOpenHand) { return(!wantsGrab[1] && !wantsGrab[2]); } } return(base.WantsRelease(obj)); }
/// <summary>Check if an interactable is within an array of other interactables.</summary> /// <remarks>Used multiple times</remarks> /// <param name="obj"></param> /// <param name="list"></param> /// <returns></returns> protected bool IsInside(SenseGlove_Interactable obj, List <SenseGlove_Interactable> list) { for (int i = 0; i < list.Count; i++) { if (GameObject.ReferenceEquals(list[i], obj)) { return(true); } } return(false); }
// Called when this object exits the collider of another object void OnTriggerExit(Collider col) { if (this.IsTouching(col.gameObject)) { this.touchedObject = null; this.touchedScript = null; if (this.debugLvl == PickupDebug.ToggleOnTouch) { this.SetDebug(false); } } }
/// <summary> Connect a new Interactable to this GrabZone. Returns true if succesful.</summary> /// <param name="obj"></param> /// <returns></returns> public bool ConnectTo(SenseGlove_Interactable obj) { if (obj != null) { int index = this.ConnectionIndex(obj); if (index < 0) { //new entry this.connectedTo.Add(obj); return(true); } } return(false); }
//-------------------------------------------------------------------------------------------------------------------------- // Collision Detection / Force Feedback // Called when this object enters the collider of another object void OnTriggerEnter(Collider col) { SenseGlove_Interactable interact = col.GetComponent <SenseGlove_Interactable>(); if (interact != null && this.touchedObject == null) { //if (!this.IsTouching(col.gameObject)) //{ // //touching a new object! //} this.touchedObject = col.gameObject; this.touchedScript = interact; } }
// Called during a physics update. void FixedUpdate() { if (touch != null) { touch.isTrigger = true; } //enure the touch collider is always kinematic. if (this.touchedObject == null || (this.touchedObject != null && !this.touchedObject.activeInHierarchy) || (this.touchedScript != null && !this.touchedScript.CanInteract())) { //SenseGlove_Debugger.Log("Object no longer exists. Releasing."); this.touchedObject = null; this.touchedScript = null; } }
/// <summary> If this grabscript is holding obj, end its interaction with it. </summary> /// <param name="obj"></param> /// <param name="callEvent">Call the EndInteraction on this object.</param> public virtual void EndInteraction(SenseGlove_Interactable obj) { if (obj != null) { for (int i = 0; i < this.heldObjects.Count; i++) { if (this.heldObjects[i].Equals(obj)) { //we have this object this.heldObjects.RemoveAt(i); //remove refrences to this. this.heldObjects[i].EndInteraction(this, true); break; } } } }
//-------------------------------------------------------------------------------------------------------------------------- // Collision Detection / Force Feedback // Called when this object enters the collider of another object void OnTriggerEnter(Collider col) { SenseGlove_Interactable interact = col.GetComponent <SenseGlove_Interactable>(); if (interact != null && this.touchedObject == null) { //if (!this.IsTouching(col.gameObject)) //{ // //touching a new object! //} this.touchedObject = col.gameObject; this.touchedScript = interact; if (this.debugLvl == PickupDebug.ToggleOnTouch) { this.SetDebug(true); } } }
/// <summary> Reset the object to before its broken state. </summary> public virtual void UnBreak() { //remove the broken object if we have one. if (this.brokenObject != null) { SenseGlove_Interactable senseScript = this.brokenObject.GetComponent <SenseGlove_Interactable>(); if (senseScript) { senseScript.EndInteraction(senseScript.GrabScript()); } this.brokenObject.gameObject.SetActive(false); if (this.brokenMaterial) { this.brokenMaterial.UnBreak(); } if (this.brokenDeform) { this.brokenDeform.ResetMesh(); } //Debug.Log("WholeObject is now on the position of the broken object"); this.wholeObject.transform.position = this.brokenObject.transform.position; this.wholeObject.transform.rotation = this.brokenObject.transform.rotation; } //stop the particle effect(s) if (this.breakParticles) { this.breakParticles.Stop(); } if (this.breakSound) { this.breakSound.Stop(); } //unbreak the whole object if (this.wholeMaterial) { this.wholeMaterial.UnBreak(); } this.wholeObject.gameObject.SetActive(true); this.resetTime = 0; }
//-------------------------------------------------------------------------------------------------------------------------- // Collision Detection / Force Feedback // Called when this object enters the collider of another object void OnTriggerEnter(Collider col) { SenseGlove_Material material = col.GetComponent <SenseGlove_Material>(); SenseGlove_Interactable interactable = col.GetComponent <SenseGlove_Interactable>(); if (material || interactable) { //if (!this.IsTouching(col.gameObject)) //{ // //touching a new object! //} this.touchedObject = col.gameObject; if (this.handModel.forceFeedback == ForceFeedbackType.Simple) { if (this.handModel.forceFeedback == ForceFeedbackType.Simple) { if (material) { this.motorLevel = material.passiveForce; } else { this.motorLevel = SenseGlove_Material.defaultPassiveForce; } } } else if (this.handModel.forceFeedback == ForceFeedbackType.MaterialBased) { this.entryPos = this.touch.transform.position; Vector3 closest = col.ClosestPoint(this.entryPos); //if something went wrong with ClosestPoint, it returns the entryPos. if (!closest.Equals(this.entryPos)) { this.entryPoint = closest; } else { // Debug.Log("WARNING: ClosestPoint == Origin, resulting in a DIV0 exception. Use an alterantive method?"); this.entryPoint = closest; } this.motorLevel = 0; //still 0 since OP == EO } } }
// Called when this object exits the collider of another object protected virtual void OnTriggerExit(Collider col) { GameObject gObj = col.attachedRigidbody != null ? col.attachedRigidbody.gameObject : col.gameObject; SenseGlove_Interactable interact = gObj.GetComponent <SenseGlove_Interactable>(); if (interact != null) { interact.UnTouchedBy(this); } if (this.IsTouching(gObj)) { this.touchedScript.UnTouchedBy(this); this.touchedObject = null; this.touchedScript = null; } }
//-------------------------------------------------------------------------------------------------------------------------- // Collision Detection / Force Feedback // Called when this object enters the collider of another object protected virtual void OnTriggerEnter(Collider col) { SenseGlove_Interactable interact = col.attachedRigidbody != null?col.attachedRigidbody.GetComponent <SenseGlove_Interactable>() : col.GetComponent <SenseGlove_Interactable>(); if (interact != null) { interact.TouchedBy(this); if (this.touchedObject == null) { //if (!this.IsTouching(col.gameObject)) //{ // //touching a new object! //} this.touchedObject = interact.gameObject; this.touchedScript = interact; } } }
/// <summary> Reset this objects position and materials. </summary> public virtual void ResetObject() { SenseGlove_Interactable senseScript = this.wholeObject.GetComponent <SenseGlove_Interactable>(); //TODO: Move this to init. if (senseScript != null) { senseScript.EndInteraction(senseScript.GrabScript()); senseScript.ResetObject(); } if (this.brokenObject != null) { senseScript = this.brokenObject.GetComponent <SenseGlove_Interactable>(); if (senseScript != null) { senseScript.EndInteraction(senseScript.GrabScript()); senseScript.ResetObject(); } } this.UnBreak(); }
/// <summary> Break the object: Hide the whole object, show the broken one and play the particle effect(s) </summary> public virtual void Break() { SenseGlove_Interactable senseScript = this.wholeObject.GetComponent <SenseGlove_Interactable>(); if (senseScript) { senseScript.EndInteraction(senseScript.GrabScript()); } if (this.wholeDeform) { this.wholeDeform.ResetMesh(); } this.wholeObject.gameObject.SetActive(false); if (this.brokenObject) { this.brokenObject.transform.position = this.wholeObject.transform.position; this.brokenObject.transform.rotation = this.wholeObject.transform.rotation; this.brokenObject.gameObject.SetActive(true); } if (this.breakParticles) { this.breakParticles.gameObject.transform.position = this.wholeObject.transform.position; this.breakParticles.gameObject.transform.rotation = this.wholeObject.transform.rotation; this.breakParticles.Play(); } if (this.breakSound) { this.breakSound.Play(); } if (this.resets) { this.resetTime = 0; } }
// Called during a physics update. void FixedUpdate() { if (touch != null) { touch.isTrigger = true; } //enure the touch collider is always kinematic. if ((this.touchedObject != null && !this.touchedObject.activeInHierarchy) || (this.touchedScript != null && !this.touchedScript.isInteractable)) { //SenseGlove_Debugger.Log("Object no longer exists. Releasing."); this.SetDebug(false); this.touchedObject = null; this.touchedScript = null; } //check debug logic if (this.grabScript != null && this.grabScript is SenseGlove_PhysGrab) { if (((SenseGlove_PhysGrab)this.grabScript).debugMode != this.debugLvl) { this.debugLvl = ((SenseGlove_PhysGrab)this.grabScript).debugMode; if (this.debugLvl == PickupDebug.Off) { this.SetDebug(false); } else if (this.debugLvl == PickupDebug.AlwaysOn) { this.SetDebug(true); } else if (this.debugLvl == PickupDebug.ToggleOnTouch) { this.SetDebug(this.touchedObject != null); } } } }
/// <summary> Calculate the force feedback levels based on material properties. </summary> /// <param name="col"></param> /// <remarks>Placed in a separate method so that one can control when it is called in Unity's execution order.</remarks> private void CalculateMaterialBased(GameObject obj, SenseGlove_Material material, SenseGlove_Interactable interactable, bool showLines = false) { Vector3 O = obj.transform.TransformPoint(this.entryOrigin); //O origin of collider on touch Vector3 E = obj.transform.TransformPoint(this.entryPoint); //E point where the collider touched the object Vector3 P = this.transform.position; //P current collider position if (showLines) { Debug.DrawLine(O, E); Debug.DrawLine(O, P); } Vector3 OE = (E - O).normalized; Vector3 OP = P - O; if (OP.magnitude > 0 && OE.magnitude > 0) { float cos = Vector3.Dot(OE, OP) / (/*OE.magnitude */ OP.magnitude); //removed OE.magnitude since it is normalized now. this.dist = OP.magnitude * cos; } else { this.dist = 0; } //we have calculated the distance, now for the material (if any is present) if (material != null) { this.motorLevel = material.CalculateForce(this.dist, this.scriptIndex); if (dist > 0 && this.touchedDeform != null) { Vector3 deformPoint = this.transform.position; if (dist > this.touchedDeform.maxDisplacement) { deformPoint = O + (OE * this.touchedDeform.maxDisplacement); } this.touchedDeform.AddDeformation(-OE, deformPoint, this.dist); } } }
/// <summary> Check if an interactable is already being held by this GrabScript </summary> /// <param name="interactable"></param> /// <returns></returns> public bool AlreadyHeld(SenseGlove_Interactable interactable) { return(IsInside(interactable, this.heldObjects)); }
// Called every FixedUpdate while this collider is inside another collider. void OnTriggerStay(Collider col) { if (this.IsTouching(col.gameObject)) //Check if we're still on the same object? { //any object that we are touching has either an Interactable and/or a material //Calculate Motor Level SenseGlove_Material material = col.GetComponent <SenseGlove_Material>(); SenseGlove_Interactable interactable = col.GetComponent <SenseGlove_Interactable>(); if (this.handModel.forceFeedback == ForceFeedbackType.Simple) { if (material) { this.motorLevel = material.passiveForce; } else if (interactable) { this.motorLevel = SenseGlove_Material.defaultPassiveForce; } } else if (this.handModel.forceFeedback == ForceFeedbackType.MaterialBased) { //transform the position of the SenseGlove_Touch to the //O touch point when it was created //E touch point on the collider //P current finger position Vector3 OE = this.entryPoint - this.entryPos; Vector3 OP = this.transform.position - this.entryPos; Debug.DrawLine(this.entryPos, this.transform.position); Debug.DrawLine(this.entryPos, this.entryPoint); if (OE.magnitude == 0) // If OE.magnitude is 0, then something went wrong with Collider.ClosestPoint, which returns O. { //check if we are outside of the collider now... Vector3 thisPos = this.transform.position; Vector3 clostest = col.ClosestPoint(thisPos); if (!thisPos.Equals(clostest)) { this.entryPoint = clostest; this.entryPos = thisPos; } return; //try again next frame } if (OP.magnitude == 0) // If OP.magnitude is 0, then then 0 == P, meaning we are back onto the entry position. in that case this.dist = 0. { this.dist = 0; } else { float cos = Vector3.Dot(OE, OP) / (OE.magnitude * OP.magnitude);; this.dist = OP.magnitude * cos; } if (material) { this.motorLevel = material.CalculateForce(this.dist); } else if (interactable) { this.motorLevel = SenseGlove_Material.CalculateDefault(this.dist); } } } }
/// <summary> Check if an objects wants to be released </summary> /// <returns></returns> protected virtual bool WantsRelease(SenseGlove_Interactable obj) { return(!obj.CanInteract() || (obj.releaseMethod == ReleaseMethod.Default)); }
/// <summary> Check if this GrabScript is allowed to release an object, based on its release parameters. </summary> /// <param name="obj"></param> /// <returns></returns> protected virtual bool CanRelease(SenseGlove_Interactable obj) { return(true); }