/// <summary> Calls an ObjectReleased event. </summary> /// <param name="obj"></param> protected void OnReleasedObject(SG_Interactable obj) { if (ObjectReleased != null) { ObjectReleased(this, new SG_GrabEventArgs(obj)); } }
/// <summary> Attempt to release an Interactable in heldObjects. If succesful, fire the ObjectReleased event. </summary> /// <param name="index"></param> /// <returns></returns> protected virtual int ReleaseObjectAt(int index) //returns new index; { bool released = false; if (heldObjects[index] != null) { if (heldObjects[index].MustBeReleased() || (this.CanRelease(heldObjects[index]) && heldObjects[index].EndInteractAllowed())) { released = heldObjects[index].EndInteraction(this); } } else { released = true; } //the object is null, so remove it from the list anyway if (released) { SG_Interactable hObj = heldObjects[index]; //grab a ref brefore it is removed? heldObjects.RemoveAt(index); if (hObj != null) { this.OnReleasedObject(hObj); } //only fire if the object is not null } else { index++; } return(index); }
/// <summary> Return a list of GameObjects that this script is Currently Interacting with. </summary> /// <returns></returns> public virtual SG_Interactable[] HeldObjects() { SG_Interactable[] objects = new SG_Interactable[this.heldObjects.Count]; for (int i = 0; i < this.heldObjects.Count; i++) { objects[i] = this.heldObjects[i]; } return(objects); }
/// <summary> Returns the index of an SG_Interactable in this script's touchedObjects. </summary> /// <param name="iScript"></param> /// <returns></returns> protected int ListIndex(SG_Interactable iScript) { for (int i = 0; i < interactablesTouched.Count; i++) { if (GameObject.ReferenceEquals(iScript.gameObject, interactablesTouched[i].gameObject)) { return(i); } } return(-1); }
/// <summary> Returns true if this GrabScript is grabbing a specific SG_Interactable. </summary> /// <param name="obj"></param> /// <returns></returns> public virtual bool IsGrabbing(SG_Interactable obj) { for (int i = 0; i < this.heldObjects.Count; i++) { if (GameObject.ReferenceEquals(obj.gameObject, heldObjects[i].gameObject)) { return(true); } } return(false); }
/// <summary> Returns true if this script is touching a specific SG_Interactable. </summary> /// <param name="interactable"></param> /// <returns></returns> public bool IsTouching(SG_Interactable interactable) { for (int i = 0; i < interactablesTouched.Count; i++) { if (interactablesTouched[i] == interactable) { return(true); } } return(false); }
/// <summary> Check if a SG_Interactable is already connected to this GrabZone. </summary> /// <param name="obj"></param> /// <returns></returns> private int ConnectionIndex(SG_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> Returns true if an SG_Interactable is inside a list of other SG_Interactables </summary> /// <param name="heldObject"></param> /// <param name="objectsToGrab"></param> /// <returns></returns> public static bool IsInside(SG_Interactable heldObject, List <SG_Interactable> objectsToGrab) { for (int i = 0; i < objectsToGrab.Count; i++) { if (GameObject.ReferenceEquals(objectsToGrab[i].gameObject, heldObject.gameObject)) { return(true); } } return(false); }
/// <summary> Attempt to grab an Interactable. If succesful, fire the ObjectGrabbed event. </summary> /// <param name="obj"></param> protected virtual void TryGrabObject(SG_Interactable obj) { if (!obj.MustBeReleased() && !IsGrabbing(obj)) { bool grabbed = obj.BeginInteraction(this); if (grabbed) { this.heldObjects.Add(obj); this.OnGrabbedObject(obj); } } }
/// <summary> Returns true if this grabscript can release an object </summary> /// <param name="obj"></param> /// <returns></returns> protected override bool CanRelease(SG_Interactable obj) { if (obj.releaseMethod == ReleaseMethod.FunctionCall) { return(false); } else if (obj.releaseMethod == ReleaseMethod.MustOpenHand) { //Can only release if our fingers do not want to grab return(!(wantsGrab[1] || wantsGrab[2])); } return(base.CanRelease(obj)); }
/// <summary> Connect a new Interactable to this GrabZone. Returns true if succesful.</summary> /// <param name="obj"></param> /// <returns></returns> public bool ConnectTo(SG_Interactable obj) { if (obj != null) { int index = this.ConnectionIndex(obj); if (index < 0) { //new entry this.connectedTo.Add(obj); return(true); } } return(false); }
//---------------------------------------------------------------------------------- // Monobehaviour #region Monobehaviour protected virtual void Start() { 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 <SG_Interactable>(); if (myInteractable == null && this.mustBeGrabbed) { this.mustBeGrabbed = false; //we cannot require this material to be grabbed if it's not an interactable. } }
/// <summary> Add a new (collider of) an SG_Interactable script to this script's touchedObjects </summary> /// <param name="script"></param> protected void AddToList(SG_Interactable script) { int index = ListIndex(script); if (index > -1) //different collider of existing object { collidersInside[index] = collidersInside[index] + 1; //don;t think += 1 works here...? } else //collider of a new object { interactablesTouched.Add(script); collidersInside.Add(1); } }
/// <summary> Checks if a collider is connected to a specific touchedScript </summary> /// <param name="col"></param> /// <param name="touchedScript"></param> /// <returns></returns> public static bool SameScript(Collider col, SG_Interactable touchedScript) { if (touchedScript != null && col != null) { if (GameObject.ReferenceEquals(col.gameObject, touchedScript.gameObject)) { return(true); //this is the touched object. } // at this line, col does not have the same material, but perhaps its attachedRigidbody does. return(col.attachedRigidbody != null && GameObject.ReferenceEquals(col.attachedRigidbody.gameObject, touchedScript.gameObject)); } return(false); }
/// <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(SG_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; } } } }
/// <summary> Break the object: Hide the whole object, optionally show the broken one and play the particle effect(s) </summary> public virtual void Break() { SG_Interactable senseScript = this.wholeObject.GetComponent <SG_Interactable>(); if (senseScript) { senseScript.EndInteraction(); } 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(); } this.resetTime = 0; this.OnObjectBreaks(); }
/// <summary> Retrieve a SG_Interactable object from a collider. Returns true if one is found. </summary> /// <param name="col"></param> /// <param name="interactable"></param> /// <param name="favourSpecific"></param> /// <returns></returns> public static bool GetInteractableScript(Collider col, out SG_Interactable interactable, bool favourSpecific = true) { SG_Interactable myScript = col.gameObject.GetComponent <SG_Interactable>(); if (myScript != null && favourSpecific) //we favour the 'specific' material over a global material. { interactable = myScript; return(true); } //myMat might exist, but we favour the connected one if possible. SG_Interactable connectedScript = col.attachedRigidbody != null? col.attachedRigidbody.gameObject.GetComponent <SG_Interactable>() : null; if (connectedScript == null) { interactable = myScript; } //the connected body does not have a material, so regardless we'll try the specific one. else { interactable = connectedScript; } return(interactable != null); }
public SG_GrabEventArgs(SG_Interactable obj) { Interactable = obj; }
/// <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(SG_Interactable obj) { return(true); }