protected override void OnSelectExit(XRBaseInteractor interactor) { if (interactor is XRDirectInteractor) { SavedTransform savedTransform = null; if (m_SavedTransforms.TryGetValue(interactor, out savedTransform)) { interactor.attachTransform.localPosition = savedTransform.OriginalPosition; interactor.attachTransform.localRotation = savedTransform.OriginalRotation; m_SavedTransforms.Remove(interactor); } } base.OnSelectExit(interactor); }
protected override void OnSelectEnter(XRBaseInteractor interactor) { if (interactor is XRDirectInteractor) { SavedTransform savedTransform = new SavedTransform(); savedTransform.OriginalPosition = interactor.attachTransform.localPosition; savedTransform.OriginalRotation = interactor.attachTransform.localRotation; m_SavedTransforms[interactor] = savedTransform; bool haveAttach = attachTransform != null; interactor.attachTransform.position = haveAttach ? attachTransform.position : m_Rb.worldCenterOfMass; interactor.attachTransform.rotation = haveAttach ? attachTransform.rotation : m_Rb.rotation; } base.OnSelectEnter(interactor); }
private void Build() { for (int i = 0; i < currentPath.Length; i++) { switch (currentPath[i]) { case 'F': { initialPosition = transform.position; bool isLeaf = false; //sets current object as branch or blossom GameObject currentObject; if (currentPath[(i + 1) % currentPath.Length] == 'X' || currentPath[(i + 3) % currentPath.Length] == 'F' && currentPath[(i + 4) % currentPath.Length] == 'X') { currentObject = Instantiate(blossom); isLeaf = true; } else { currentObject = Instantiate(branch); } //set parent currentObject.transform.SetParent(tree.transform); //set position and rotation currentObject.transform.SetPositionAndRotation(transform.position, transform.rotation); //set shape float length; if (isLeaf) { length = Random.Range(minPetalLength, maxPetalLength) * 0.1f; currentObject.transform.localScale = new Vector3(length, length, length); } else { length = Random.Range(minBranchLength, maxBranchLength); currentObject.transform.localScale = new Vector3(width, length, width); transform.Translate(Vector3.up * length * 2f); } } break; case 'X': break; case '-': transform.Rotate(Vector3.forward * angle * (1f + variance / 100f * randomRotations[i % randomRotations.Length])); break; case '+': transform.Rotate(Vector3.back * angle * (1f + variance / 100f * randomRotations[i % randomRotations.Length])); break; case '*': transform.Rotate(Vector3.left * angle * (1f + variance / 100f * randomRotations[i % randomRotations.Length])); break; case '/': transform.Rotate(Vector3.right * angle * (1f + variance / 100f * randomRotations[i % randomRotations.Length])); break; case '[': savedTransforms.Push(new SavedTransform { position = transform.position, rotation = transform.rotation }); width *= widthScale; minBranchLength *= lengthScale; maxBranchLength *= lengthScale; break; case ']': SavedTransform saved = savedTransforms.Pop(); width /= widthScale; minBranchLength /= lengthScale; maxBranchLength /= lengthScale; transform.position = saved.position; transform.rotation = saved.rotation; break; default: Debug.LogError("Not a Valid Key: " + currentPath[i]); break; } } }
// Generate the L-tree public void Generate() { // Destroy the existing tree foreach (GameObject o in tree) { Destroy(o); } tree.Clear(); // Reset the position of the LSystemGenerator transform.position = Vector3.zero; transform.rotation = Quaternion.identity; string axiomString = axiom.text; string fRuleString = fRule.text; string xRuleString = xRule.text; float angleFloat = angle.value; float lengthFloat = length.value; float lengthLeafFloat = lengthLeaf.value; float widthFloat = width.value; float widthLeafFloat = widthLeaf.value; int stepInt = Convert.ToInt32(step.text); current = axiomString; // Loops a number of times equal to the number of steps for (int i = 0; i < stepInt; i++) { // Algorithm replaces characters with their rule results or default value for each character StringBuilder sb = new StringBuilder(); foreach (char c in current) { sb.Append(c == 'F' ? fRuleString : c == 'X' ? xRuleString : c.ToString()); } current = sb.ToString(); } foreach (char c in current) { // Each character does something specific switch (c) { // On 'F' save the starting position and move up by the value of length. Instantiate and draw a branch, with a preset width, from the start position to the current position case 'F': Vector3 startPos = transform.position; transform.Translate(Vector3.up * lengthFloat); GameObject branchObj = Instantiate(branch); tree.Add(branchObj); LineRenderer lr = branchObj.GetComponent <LineRenderer>(); lr.startWidth = widthFloat; lr.SetPosition(0, startPos); lr.SetPosition(1, transform.position); break; // On 'X' do nothing case 'X': break; // On '+' rotate right by the preset angle case '+': transform.Rotate(Vector3.forward * angleFloat); break; // On '-' rotate left by the preset angle case '-': transform.Rotate(Vector3.back * angleFloat); break; // On '[' save the current position and rotation of the LSystemGenerator to the stack case '[': savedTransformStack.Push(new SavedTransform() { position = transform.position, rotation = transform.rotation }); break; // On ']' instantiate and draw a leaf at the end of the branch. Then pop the most recent position and rotation from the stack and move the LSystemGenerator back to it case ']': Vector3 startPosLeaf = transform.position; transform.Translate(Vector3.up * lengthLeafFloat); GameObject leafObj = Instantiate(leaf); tree.Add(leafObj); LineRenderer lr2 = leafObj.GetComponent <LineRenderer>(); lr2.startWidth = widthLeafFloat; lr2.SetPosition(0, startPosLeaf); lr2.SetPosition(1, transform.position); SavedTransform st = savedTransformStack.Pop(); transform.position = st.position; transform.rotation = st.rotation; break; // Throw an exception if any other invalid symbol is used default: throw new InvalidOperationException("Incorrect Character Entered"); } } }
private IEnumerator Generate() { currentPath = axiom; StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < iterations; i++) { char[] currentPathChars = currentPath.ToCharArray(); for (int j = 0; j < currentPathChars.Length; j++) { stringBuilder.Append(rules.ContainsKey(currentPathChars[j]) ? rules[currentPathChars[j]] : currentPathChars[j].ToString()); } currentPath = stringBuilder.ToString(); stringBuilder = new StringBuilder(); } for (int k = 0; k < currentPath.Length; k++) { switch (currentPath[k]) { case 'F': bool isLeaf = false; GameObject currentElement; if (currentPath[(k + 1) % currentPath.Length] == 'X' || currentPath[(k + 3) % currentPath.Length] == 'F' && currentPath[(k + 4) % currentPath.Length] == 'X') { isLeaf = true; } if (isLeaf) { currentElement = Instantiate(leaf, currentPosition, currentRotation); currentPosition += currentRotation * Vector3.up * Random.Range(minLeafLength, maxLeafLength); } else { currentElement = Instantiate(branch, currentPosition, currentRotation); currentPosition += currentRotation * Vector3.up * Random.Range(minBranchLength, maxBranchLength); } currentElement.transform.SetParent(tree.transform); // TreeElement currentTreeElement = currentElement.GetComponent<TreeElement>(); // currentTreeElement.lineRenderer.startWidth = width; // currentTreeElement.lineRenderer.endWidth = width; // currentTreeElement.lineRenderer.sharedMaterial = currentTreeElement.material; break; case 'X': break; case '+': currentRotation.eulerAngles += Vector3.forward * angle * (1f + variance / 100f * randomRotations[k % randomRotations.Length]); // currentRotation.eulerAngles += Vector3.forward * angle; // transform.Rotate(Vector3.forward * angle); break; case '-': currentRotation.eulerAngles += Vector3.back * angle * (1f + variance / 100f * randomRotations[k % randomRotations.Length]); // currentRotation.eulerAngles += Vector3.back * angle; // transform.Rotate(Vector3.back * angle); break; // case '*': // transform.Rotate(Vector3.up * 120f * (1f + variance / 100f * randomRotations[k%randomRotations.Length])); // break; // case '/': // transform.Rotate(Vector3.down * 120f * (1f + variance / 100f * randomRotations[k%randomRotations.Length])); // break; case '[': savedTransforms.Push( new SavedTransform() { position = currentPosition, rotation = currentRotation } ); break; case ']': SavedTransform savedTransform = savedTransforms.Pop(); currentPosition = savedTransform.position; currentRotation = savedTransform.rotation; break; } Debug.Log(currentPath[k]); Debug.Log(currentPosition); Debug.Log(currentRotation.eulerAngles); yield return(null); } }
public void Generate(GameObject tree) { currentPath = axiom; StringBuilder stringBuilder = new StringBuilder(); TreeRoot currentTreeRoot = tree.GetComponent <TreeRoot>(); int currentGrowthStep = currentTreeRoot.growthStep; for (int i = 0; i < iterations; i++) { char[] currentPathChars = currentPath.ToCharArray(); for (int j = 0; j < currentPathChars.Length; j++) { stringBuilder.Append(rules.ContainsKey(currentPathChars[j]) ? rules[currentPathChars[j]] : currentPathChars[j].ToString()); } currentPath = stringBuilder.ToString(); stringBuilder = new StringBuilder(); } bool previousWasLeaf = false; tempBranchParent = new GameObject("Fresh Branch"); for (int k = 0; k < currentPath.Length; k++) { switch (currentPath[k]) { // F == forward case 'F': initialPosition = transform.position; bool isLeaf = false; if (initialPosition == Vector3.zero) { branchRoot = new GameObject("Root " + k); branchRoot.transform.SetParent(tree.transform); } GameObject currentElement; bool nextIsLeaf = currentPath[k + 1] % currentPath.Length == 'X'; bool aheadIsLeaf = aheadIsLeaf = currentPath[(k + 3) % currentPath.Length] % currentPath.Length == 'F' && currentPath[(k + 4) % currentPath.Length] % currentPath.Length == 'X'; if (nextIsLeaf || aheadIsLeaf) { currentElement = Instantiate(leaf, transform.position, transform.rotation); isLeaf = true; } else { currentElement = Instantiate(branch, transform.position, transform.rotation); } if (previousWasLeaf && !isLeaf) { // time to start a new branch tempBranchParent = new GameObject("Fresh Branch " + k); } tempBranchParent.transform.SetParent(branchRoot.transform); currentElement.transform.SetParent(tempBranchParent.transform); TreeElement currentTreeElement = currentElement.GetComponent <TreeElement>(); float length = 0f; if (isLeaf) { length = Random.Range(minLeafLength, maxLeafLength); transform.Translate(Vector3.up * 1f * length); } else { length = Random.Range(minBranchLength, maxBranchLength); transform.Translate(Vector3.up * 1f * length); } currentTreeElement.lineRenderer.SetPosition(1, new Vector3(0, length, 0)); currentTreeElement.lineRenderer.startWidth = currentTreeElement.lineRenderer.startWidth * width; currentTreeElement.lineRenderer.endWidth = currentTreeElement.lineRenderer.endWidth * width; currentTreeElement.lineRenderer.sharedMaterial = currentTreeElement.material; previousWasLeaf = isLeaf; break; // axiom, nothing happens case 'X': break; case '+': transform.Rotate(Vector3.forward * angle2d * (1f + variance / 100f * Random.Range(-1f, 1f))); break; case '-': transform.Rotate(Vector3.back * angle2d * (1f + variance / 100f * Random.Range(-1f, 1f))); break; case '*': transform.Rotate(Vector3.up * angle3d * (1f + variance / 100f * Random.Range(-1f, 1f))); break; case '/': transform.Rotate(Vector3.down * angle3d * (1f + variance / 100f * Random.Range(-1f, 1f))); break; case '[': savedTransforms.Push(new SavedTransform() { position = transform.position, rotation = transform.rotation }); break; case ']': SavedTransform stack = savedTransforms.Pop(); transform.position = stack.position; transform.rotation = stack.rotation; break; } } }
private void DrawAlt() { for (int k = 0; k < currentPath.Length; k++) { switch (currentPath[k]) { // 'F' Means a straight line-- continue on. case 'F': initalPosition = transform.position; GameObject treeSegment; bool isLeaf = false; if (currentPath[k + 1] % currentPath.Length == 'X' || currentPath[k + 3] % currentPath.Length == 'F' && currentPath[k + 4] % currentPath.Length == 'X') { treeSegment = Instantiate(leaf); isLeaf = true; } else { treeSegment = Instantiate(branch); } //treeSegment.transform.SetParent(gameObject.transform); //transform.position = initalPosition; treeSegment.transform.SetParent(gameObject.transform, false); transform.Translate(Vector3.up * maxBranchLength); //this.SetParent(treeSegment.transform, transform.parent); //GameObject treeSegment = Instantiate(branch); if (isLeaf) { transform.Translate(Vector3.up * Random.Range(minLeafLength, maxLeafLength)); treeSegment.GetComponent <LineRenderer>().SetPosition(0, initalPosition); treeSegment.GetComponent <LineRenderer>().SetPosition(1, transform.position); treeSegment.GetComponent <LineRenderer>().startWidth = leafWidth; treeSegment.GetComponent <LineRenderer>().endWidth = 0; //treeSegment.GetComponent<LineRenderer>().SetColors(leafColor, leafColor); treeSegment.GetComponent <LineRenderer>().startColor = leafColor; treeSegment.GetComponent <LineRenderer>().endColor = leafColor; } else { transform.Translate(Vector3.up * Random.Range(minBranchLength, maxBranchLength)); treeSegment.GetComponent <LineRenderer>().SetPosition(0, initalPosition); treeSegment.GetComponent <LineRenderer>().SetPosition(1, transform.position); treeSegment.GetComponent <LineRenderer>().startWidth = branchWidth; treeSegment.GetComponent <LineRenderer>().endWidth = branchWidth; treeSegment.GetComponent <LineRenderer>().startColor = branchColor; treeSegment.GetComponent <LineRenderer>().endColor = branchColor; } break; case 'X': // Do nothing, its just part of the algorithm break; case '+': // Rotate clockwise transform.Rotate(Vector3.back * angle * (1f + variance / 10f * randomRotations[k % randomRotations.Length])); break; case '-': // Rotate counter-clockwise transform.Rotate(Vector3.forward * angle * (1f + variance / 10f * randomRotations[k % randomRotations.Length])); break; case '*': transform.Rotate(Vector3.up * 120f * (1f + variance / 10f * randomRotations[k % randomRotations.Length])); break; case '/': transform.Rotate(Vector3.down * 120f * (1f + variance / 10f * randomRotations[k % randomRotations.Length])); break; case '[': // Save current transform to stack savedTransforms.Push(new SavedTransform() { position = transform.position, rotation = transform.rotation }); break; case ']': // Pop saved transform from stack SavedTransform savedTransform = savedTransforms.Pop(); transform.position = savedTransform.position; transform.rotation = savedTransform.rotation; break; } } }
private void Draw() { for (int k = 0; k < currentPath.Length; k++) { switch (currentPath[k]) { // 'F' Means a straight line-- continue on. In this particular implementation, it uses a fancy algorith to case 'F': initalPosition = transform.position; // By default, elements are NOT leaves bool isLeaf = false; GameObject currentElement; // I have no idea how this works, but it determines if the next element to draw should be a leaf or a branch. if (currentPath[k + 1] % currentPath.Length == 'X' || currentPath[k + 3] % currentPath.Length == 'F' && currentPath[k + 4] % currentPath.Length == 'X') { currentElement = Instantiate(leaf); isLeaf = true; } else { currentElement = Instantiate(branch); } // Make the newest element drawn inherit from the tree prefab (???) currentElement.transform.SetParent(tree.transform); TreeElement currentTreeElement = currentElement.GetComponent <TreeElement>(); if (isLeaf) { transform.Translate(Vector3.up * 2f * Random.Range(minLeafLength, maxLeafLength)); currentTreeElement.GetComponent <LineRenderer>().startWidth = 0; currentTreeElement.GetComponent <LineRenderer>().endWidth = leafWidth; leafCount++; } else { transform.Translate(Vector3.up * 2f * Random.Range(minBranchLength, maxBranchLength)); currentTreeElement.lineRenderer.startWidth = branchWidth; currentTreeElement.lineRenderer.endWidth = branchWidth; branchCount++; } currentTreeElement.lineRenderer.SetPosition(0, initalPosition); currentTreeElement.lineRenderer.SetPosition(1, transform.position); currentTreeElement.lineRenderer.sharedMaterial = currentTreeElement.material; break; case 'X': break; case '+': transform.Rotate(Vector3.forward * angle * (1f + variance / 10f * randomRotations[k % randomRotations.Length])); break; case '-': transform.Rotate(Vector3.back * angle * (1f + variance / 10f * randomRotations[k % randomRotations.Length])); break; case '*': transform.Rotate(Vector3.up * 120f * (1f + variance / 10f * randomRotations[k % randomRotations.Length])); break; case '/': transform.Rotate(Vector3.down * 120f * (1f + variance / 10f * randomRotations[k % randomRotations.Length])); break; case '[': SavedTransform savedTransformPush = new SavedTransform(); savedTransformPush.position = transform.position; savedTransformPush.rotation = transform.rotation; savedTransforms.Push(savedTransformPush); break; case ']': SavedTransform savedTransformPop = savedTransforms.Pop(); transform.position = savedTransformPop.position; transform.rotation = savedTransformPop.rotation; break; } } Debug.Log("leafCount : " + leafCount + " , branchCount : " + branchCount); }
public void Generate() { CancelAnimation(); allLines = new List <TreeElement>(); boundsMinMaxX = new Vector2(float.MaxValue, float.MinValue); boundsMinMaxY = new Vector2(float.MaxValue, float.MinValue); Destroy(tree); tree = Instantiate(treeParent); //------------PART ONE - GROWING OF THE STRING/PATH-------------------------------- //We are starting out to setting our currentString that is going to be our //"growing path" to our start position (the axiom) currentString = axiom; //We are using System.Text to make use of a stringbuilder StringBuilder stringBuilder = new StringBuilder(); //We are looping through our iterations as we are repeating the process that many times. for (int i = 0; i < iterations; i++) { //We are then getting an array consisting of all the chars in our currentString, //because we want to loop over them.To check if our current set of rules contains //this char, if it does we want to apply our rules. //This is how our stirng will grow. char[] currentStringChars = currentString.ToCharArray(); for (int j = 0; j < currentStringChars.Length; j++) { stringBuilder.Append(rules.ContainsKey(currentStringChars[j]) ? rules[currentStringChars[j]] : currentStringChars[j].ToString()); } currentString = stringBuilder.ToString(); stringBuilder = new StringBuilder(); } //------------PART TWO - DRAWING OF THE LINES-------------------------------- //We are starting out by looping over every character in our currentString //to then apply our instructions to each of them and draw the lines approprietly for (int k = 0; k < currentString.Length; k++) { switch (currentString[k]) { case 'F': //Positioning Changes - Moving our Object up/Forwards initialPosition = transform.position; bool isLeaf = false; GameObject currentElement; //Since every F - so therefore every move forward is represented in a new Tree Element we need to decide //if this new Element should be a Leaf or a Branch. if (currentString[k + 1] % currentString.Length == 'X' || currentString[k + 3] % currentString.Length == 'F' && currentString[k + 4] % currentString.Length == 'X') { currentElement = Instantiate(leaf); isLeaf = true; } else { currentElement = Instantiate(branch); } currentElement.transform.SetParent(tree.transform); //Getting the currentTreeElement so that we can access the linerenderer TreeElement currentTreeElement = currentElement.GetComponent <TreeElement>(); //Setting the LineRenderers start and endpoint aswell as its thiccness and color currentTreeElement.lineRenderer.SetPosition(0, initialPosition); if (isLeaf) { transform.Translate(Vector3.up * 2f * Random.Range(minLeafLength, maxLeafLength)); } else { transform.Translate(Vector3.up * 2f * Random.Range(minlength, maxLength)); } currentTreeElement.lineRenderer.SetPosition(1, transform.position); if (isLeaf) { currentTreeElement.lineRenderer.startWidth = width * 2f; currentTreeElement.lineRenderer.endWidth = width / 4f; currentTreeElement.isLeaf = true; } else { currentTreeElement.lineRenderer.startWidth = width; currentTreeElement.lineRenderer.endWidth = width; } currentTreeElement.lineRenderer.sharedMaterial = currentTreeElement.lineMaterial; allLines.Add(currentTreeElement); break; case 'X': break; //For +,-,* and / we want to rotate in differenct directions. //We are using our Array of Random Directions here. case '+': transform.Rotate(Vector3.back * angle * (1 + variance / 100 * randomRotations[k % randomRotations.Length])); break; case '-': transform.Rotate(Vector3.forward * angle * (1 + variance / 100 * randomRotations[k % randomRotations.Length])); break; case '*': transform.Rotate(Vector3.up * 120f * (1f + variance / 100f * randomRotations[k % randomRotations.Length])); break; case '/': transform.Rotate(Vector3.down * 120f * (1f + variance / 100f * randomRotations[k % randomRotations.Length])); break; //Now, for the spikey bracket we are saving the current position and placing it at //the top of our Stack. The best way to explain this process is the following: //If we are trying to draw a tree on paper, which has multiple end points, as it has different branches and such //We will need to lift the pen off the paper every now and then. So what we are doing is we are saving //the position were we want to draw a branch at a later point. And then once we finished the current branch we were //working on we are going back to that saved position to add our new branch there. case '[': transformStack.Push(new SavedTransform(transform.position, transform.rotation)); break; //We are getting the last saved transform from our strack and apply it to our gameobject. //to then continue from this position. case ']': SavedTransform savedTransform = transformStack.Pop(); transform.position = savedTransform.Position; transform.rotation = savedTransform.Rotation; break; } //Calculating the bounds to make sure that our newly generated tree can be displayed boundsMinMaxX.x = Mathf.Min(transform.position.x, boundsMinMaxX.x); boundsMinMaxX.y = Mathf.Max(transform.position.x, boundsMinMaxX.y); boundsMinMaxY.x = Mathf.Min(transform.position.y, boundsMinMaxY.x); boundsMinMaxY.y = Mathf.Max(transform.position.y, boundsMinMaxY.y); } //Applying the calculated bounds minimum and maximum in comparison to the rect to our camera for scaling the viewport to our tree. float aspect = (float)Screen.width / Screen.height; Vector3 treeCentre = new Vector3(boundsMinMaxX.x + boundsMinMaxX.y, boundsMinMaxY.x + boundsMinMaxY.y) * .5f; float treeHeight = boundsMinMaxY.y - boundsMinMaxY.x; float treeWidth = boundsMinMaxX.y - boundsMinMaxX.x; float treeSize = Mathf.Max(treeHeight, treeWidth * aspect); Camera.main.orthographic = true; Camera.main.orthographicSize = treeSize * .5f + 1.5f; Camera.main.transform.position = treeCentre + Vector3.back + Vector3.left * Camera.main.orthographicSize * aspect * .5f; }
/// <summary> /// Reset to the time drag started. /// </summary> public void ResetPosition(SavedTransform savedTransform) { transform.position = preTransform.position; transform.rotation = preTransform.rotation; transform.localScale = preTransform.scale; }