public Phrase(Expression function, params Expression[] inputs) : base(null) { if (inputs.Length > function.GetNumFreeArgs()) { throw new ArgumentException("Too many arguments passed to a function expression"); } Expression newExpression = function; int counter = 0; for (int i = 0; i < inputs.Length; i++) { if (inputs[i] == null) { counter++; } newExpression = new Phrase(newExpression, inputs[i], counter); } this.type = newExpression.type; this.headString = newExpression.headString; this.headType = newExpression.headType; this.args = new Expression[newExpression.GetNumArgs()]; for (int i = 0; i < newExpression.GetNumArgs(); i++) { this.args[i] = newExpression.GetArg(i); } }
/** * returns false if 2 expressions shouldn't combine with each other */ public bool CombineWith(ExpressionPiece inputExpression, int index) { Expression expr = null; //try to create new Expression try { expr = new Phrase(this.expression, inputExpression.expression, index); } catch (Exception e) { Debug.LogException(e); this.gameController.failure.Play(); return(false); } // generate new Piece GameObject exprPiece = Resources.Load("Piece") as GameObject; GameObject exprPieceInstance = Instantiate(exprPiece, GetSpawnPosition(), Quaternion.identity) as GameObject; ExpressionPiece exprPieceScript = exprPieceInstance.GetComponent <ExpressionPiece>(); exprPieceScript.expression = expr; exprPieceScript.arguments = new ExpressionPiece[expr.GetNumArgs()]; if (exprPieceScript.arguments.Length > 0) { exprPieceScript.heightInUnits = 2; } float originalPieceX = this.transform.position.x; float originalPieceY = this.transform.position.y; // exprPieceInstance.transform.position = new Vector3(originalPieceX, originalPieceY, 0); exprPieceScript.gameController = gameController; exprPieceScript.id = expr.ToString(); exprPieceScript.index = this.index; if (this.parentExpressionPiece != null) { exprPieceScript.SetParentExpressionPiece(this.parentExpressionPiece.DeepCopy()); // DeepCopy here bc 'this' will get destroyed } // int noArgInputWidth = 1; // int noArgInputHeight = 1; // for (int i = 0; i < inputExpression.arguments.Legth; i++) { // if (!inputExpression[i].id.Equals("_")) { // noArgInputWidth += inputExpression[i].widthInUnits; // noArgInputHeight = Max(noArgInputHeight, inputExpression.heightInUnits + 1); // } // } exprPieceScript.widthInUnits = 1; exprPieceScript.widthInUnits += inputExpression.widthInUnits; exprPieceScript.heightInUnits = Max(exprPieceScript.heightInUnits, inputExpression.heightInUnits + 1); //Add the arguments to the new piece int counter = -1; for (int i = 0; i < arguments.Length; i++) { if (this.arguments[i] == null) { counter++; exprPieceScript.widthInUnits++; } else { // this happens to every argument, whether blank or filled float originalArgLocalX = this.arguments[i].transform.localPosition.x; float originalArgLocalY = this.arguments[i].transform.localPosition.y; // place a copy of the old argument in the same position in the new expression. exprPieceScript.arguments[i] = this.arguments[i].DeepCopy(); exprPieceScript.arguments[i].transform.SetParent(exprPieceInstance.transform); exprPieceScript.arguments[i].gameObject.transform.localPosition = new Vector3(originalArgLocalX, originalArgLocalY, 0); // changing the width and height of the new expression exprPieceScript.widthInUnits += exprPieceScript.arguments[i].widthInUnits; exprPieceScript.heightInUnits = Max(exprPieceScript.heightInUnits, exprPieceScript.arguments[i].heightInUnits + 1); // if it's an empty argument slot, then move forward in the // argument index, and decrement the argument slot's index by 1 if // the argument has already been placed to preserve the new indexing. if (this.arguments[i].id.Equals("_")) { if (counter > index) { exprPieceScript.arguments[i].index--; } counter++; } } // place the input expression in the appropriate argument position. if (counter == index) { float originalArgLocalX = this.arguments[i].transform.localPosition.x; float originalArgLocalY = this.arguments[i].transform.localPosition.y; //need to destroy the empty arg that this piece is replacing Destroy(exprPieceScript.arguments[i].gameObject, 0.0f); exprPieceScript.arguments[i] = inputExpression.DeepCopy(); exprPieceScript.arguments[i].gameObject.transform.localPosition = new Vector3(originalArgLocalX, originalArgLocalY, 0); exprPieceScript.arguments[i].transform.SetParent(exprPieceInstance.transform); counter++; exprPieceScript.widthInUnits--; } } int xPositionInUnits = 1; // this is setting the parentexpressionpiece and parent of all of the new // expression's arguments as the new expression. This doesn't happen in // deepcopy because deepcopy makes a new copy of the expression to set. for (int i = 0; i < arguments.Length; i++) { float argLocalX = exprPieceScript.arguments[i].transform.localPosition.x; float argLocalY = exprPieceScript.arguments[i].transform.localPosition.y; float changeY = ((exprPieceScript.heightInUnits - 2) / 2f) * PIXELS_PER_UNIT; if (exprPieceScript.arguments[i].id.Equals("_")) { exprPieceScript.arguments[i].gameObject.transform.localPosition = new Vector3( ((-0.5f * exprPieceScript.widthInUnits) + xPositionInUnits + 0.5f - BUFFER_IN_UNITS) * PIXELS_PER_UNIT, argLocalY + changeY); } exprPieceScript.arguments[i].SetParentExpressionPiece(exprPieceScript); exprPieceInstance.transform.SetParent(this.transform.parent.transform); // Debug.Log(exprPieceScript.expression + "'s width is " + exprPieceScript.widthInUnits); // Debug.Log(exprPieceScript.expression + "[" + i + "]'s width is " + arguments[i].widthInUnits); xPositionInUnits += exprPieceScript.arguments[i].widthInUnits; } exprPieceInstance.transform.SetParent(this.transform.parent.transform); exprPieceScript.SetVisual(exprPieceScript.GenerateVisual()); int indexToOccupy = this.gameObject.transform.GetSiblingIndex(); // foreach (ExpressionPiece arg in this.arguments) { // Destroy(arg.gameObject, 0.0f); // } Destroy(this.gameObject, 0.0f); // the arguments to the input expression aren't being destroyed properly. They're just floating around Destroy(inputExpression.gameObject, 0.0f); exprPiece.transform.SetSiblingIndex(indexToOccupy); return(true); }