public GameObject SpawnExpression(Expression expression) { GameObject wordContainer = ArgumentContainer.From(expression); ArgumentContainer wordContainerScript = wordContainer.GetComponent <ArgumentContainer>(); wordContainerScript.GenerateVisual(); wordContainer.transform.SetParent(Workspace.transform); wordContainer.transform.localRotation = Quaternion.identity; int width = wordContainerScript.Width; int height = wordContainerScript.Height; wordContainer.transform.localScale = new Vector3(0.125f * 0.875f * width, 0.125f * 0.875f * height, 1); // find the next available slot that // can accommodate the expression for (int i = 0; i < slotsY; i++) { for (int j = 0; j < slotsX; j++) { bool empty = true; for (int h = 0; h < height; h++) { if (!empty) { break; } if (i + h >= slotsY) { empty = false; break; } for (int w = 0; w < width; w++) { if (j + w >= slotsX) { empty = false; break; } if (slots[i + h, j + w] != null) { empty = false; } } } // we've found a rectangular region // that can fit this new container if (empty) { // here, we add the open arguments in this expression // to a map which will be used when expressions of the // right type are selected. if (wordContainerScript.Argument is Expression) { List <Argument> arguments = new List <Argument>(); Expression e = (Expression)wordContainerScript.Argument; int index = 0; foreach (Transform child in wordContainer.transform) { var script = child.gameObject.GetComponent <ArgumentContainer>(); if (script == null) { continue; } if (script.Argument is Empty) { var newArguments = new List <Argument>(); foreach (Argument arg in newArguments) { newArguments.Add(new Empty(arg.Type)); } arguments.Add(script.Argument); openArgumentSlots[i + 1, j + index] = new OpenArgumentInfo(j, i, script.gameObject, wordContainer, arguments); } index += script.Width; } } // here, we set the container's position to the first available grid position. wordContainer.transform.localPosition = new Vector3(0.95f * (-0.5f + width / 16.0f + 0.125f * j), 0.95f * ((0.5f - height / 16.0f) - 0.125f * i), -0.01f); // if no pointer is active on the workspace, we set the pointer active // to this expression. if (!Pointer.active) { Pointer.active = true; Pointer.transform.localPosition = new Vector3(wordContainer.transform.localPosition.x, wordContainer.transform.localPosition.y + (3.0f * height / 32.0f), -0.01f); } // fill the slots in the grid with the ID // of this container. for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { slots[i + h, j + w] = wordContainer; } } return(wordContainer); } } } Destroy(wordContainer); return(null); // @NOTE the workspace should expand when there's // no room for another word. // Need to implement scroll and zoom. Debug.Log("no more room :'("); }
// Update is called once per frame void Update() { // the menu button was pressed if (Input.GetButtonDown("Menu")) { // the workspace is already open if (IsWorkspaceActive) { IsRadialMenuActive = true; RadialMenu.enabled = true; // do stuff with the radial menu RadialMenu.HandleMenuOpen(); } else { // the workspace isn't open yet // lock the player's movement PlayerMovement.enabled = false; MouseLook.enabled = false; // HighlightPoint.SetActive(false); // set the workspace to active IsWorkspaceActive = true; Workspace.SetActive(true); } } // @NOTE: for each of cursor movements, the traversal should // be different from how it is. It should follow a zig-zag // traversal pattern that covers the whole rectangular region // starting from the position of the cursor. // move the cursor to the expression to the right // of the current expression if (Input.GetAxis("Horizontal") > 0 && Time.time - lastStepHorizontal > timeBetweenSteps) { lastStepHorizontal = Time.time; int bestX = -1; int bestY = -1; int bestNorm = int.MaxValue; GameObject bestObject = null; if (SelectedExpression == null) { GameObject currentlySelected = slots[cursorY, cursorX]; for (int i = 0; i < slotsY; i++) { for (int j = cursorX + 1; j < slotsX; j++) { GameObject o = slots[i, j]; if (o == null || o == currentlySelected) { continue; } int dx = j - cursorX; int dy = i - cursorY; int norm = (dx * dx) + (dy * dy); if (norm < bestNorm) { bestX = j; bestY = i; bestNorm = norm; bestObject = o; } } } if (bestX != -1 && bestY != -1) { cursorX = bestX; cursorY = bestY; Pointer.transform.localPosition = new Vector3(bestObject.transform.localPosition.x, bestObject.transform.localPosition.y + (3.0f * bestObject.GetComponent <ArgumentContainer>().Height / 32.0f), -0.01f); } } else { for (int i = 0; i < slotsY; i++) { for (int j = cursorX + 1; j < slotsX; j++) { if (openArgumentSlots[i, j] == null || !openArgumentSlots[i, j].Type.Equals(SelectedExpression.GetComponent <ArgumentContainer>().Argument.Type)) { continue; } int dx = j - cursorX; int dy = i - cursorY; int norm = (dx * dx) + (dy * dy); if (norm < bestNorm) { bestX = j; bestY = i; bestNorm = norm; } } } if (bestX != -1 && bestY != -1) { cursorX = bestX; cursorY = bestY; Pointer.transform.localPosition = new Vector3(0.95f * (-0.5f + 1 / 16.0f + 0.125f * cursorX), 0.95f * ((0.5f + 1 / 16.0f) - 0.125f * cursorY), -0.02f); } } } // move the cursor to the expression to the left // of the current expression if (Input.GetAxis("Horizontal") < 0 && Time.time - lastStepHorizontal > timeBetweenSteps) { lastStepHorizontal = Time.time; int bestX = -1; int bestY = -1; int bestNorm = int.MaxValue; GameObject bestObject = null; if (SelectedExpression == null) { GameObject currentlySelected = slots[cursorY, cursorX]; for (int i = 0; i < slotsY; i++) { for (int j = 0; j < cursorX; j++) { GameObject o = slots[i, j]; if (o == null || o == currentlySelected) { continue; } int dx = j - cursorX; int dy = i - cursorY; int norm = (dx * dx) + (dy * dy); if (norm < bestNorm) { bestX = j; bestY = i; bestNorm = norm; bestObject = o; } } } if (bestX != -1 && bestY != -1) { cursorX = bestX; cursorY = bestY; Pointer.transform.localPosition = new Vector3(bestObject.transform.localPosition.x, bestObject.transform.localPosition.y + (3.0f * bestObject.GetComponent <ArgumentContainer>().Height / 32.0f), -0.01f); } } else { for (int i = 0; i < slotsY; i++) { for (int j = 0; j < cursorX; j++) { if (openArgumentSlots[i, j] == null || !openArgumentSlots[i, j].Type.Equals(SelectedExpression.GetComponent <ArgumentContainer>().Argument.Type)) { continue; } int dx = j - cursorX; int dy = i - cursorY; int norm = (dx * dx) + (dy * dy); if (norm < bestNorm) { bestX = j; bestY = i; bestNorm = norm; } } } if (bestX != -1 && bestY != -1) { cursorX = bestX; cursorY = bestY; Pointer.transform.localPosition = new Vector3(0.95f * (-0.5f + 1 / 16.0f + 0.125f * cursorX), 0.95f * ((0.5f + 1 / 16.0f) - 0.125f * cursorY), -0.02f); } } } // move the cursor to the expression downard // from the current expression if (Input.GetAxis("Vertical") < 0 && Time.time - lastStepVertical > timeBetweenSteps) { lastStepVertical = Time.time; int bestX = -1; int bestY = -1; int bestNorm = int.MaxValue; GameObject bestObject = null; if (SelectedExpression == null) { GameObject currentlySelected = slots[cursorY, cursorX]; for (int i = cursorY + 1; i < slotsY; i++) { for (int j = 0; j < slotsX; j++) { GameObject o = slots[i, j]; if (o == null || o == currentlySelected) { continue; } int dx = j - cursorX; int dy = i - cursorY; int norm = (dx * dx) + (dy * dy); if (norm < bestNorm) { bestX = j; bestY = i; bestNorm = norm; bestObject = o; } } } if (bestX != -1 && bestY != -1) { cursorX = bestX; cursorY = bestY; Pointer.transform.localPosition = new Vector3(bestObject.transform.localPosition.x, bestObject.transform.localPosition.y + (3.0f * bestObject.GetComponent <ArgumentContainer>().Height / 32.0f), -0.01f); } } else { for (int i = cursorY + 1; i < slotsY; i++) { for (int j = 0; j < slotsX; j++) { if (openArgumentSlots[i, j] == null || !openArgumentSlots[i, j].Type.Equals(SelectedExpression.GetComponent <ArgumentContainer>().Argument.Type)) { continue; } int dx = j - cursorX; int dy = i - cursorY; int norm = (dx * dx) + (dy * dy); if (norm < bestNorm) { bestX = j; bestY = i; bestNorm = norm; } } } if (bestX != -1 && bestY != -1) { cursorX = bestX; cursorY = bestY; Pointer.transform.localPosition = new Vector3(0.95f * (-0.5f + 1 / 16.0f + 0.125f * cursorX), 0.95f * ((0.5f + 1 / 16.0f) - 0.125f * cursorY), -0.02f); } } } // move the cursor to the expression upward // from the current expression if (Input.GetAxis("Vertical") > 0 && Time.time - lastStepVertical > timeBetweenSteps) { lastStepVertical = Time.time; int bestX = -1; int bestY = -1; int bestNorm = int.MaxValue; GameObject bestObject = null; if (SelectedExpression == null) { GameObject currentlySelected = slots[cursorY, cursorX]; for (int i = 0; i < cursorY; i++) { for (int j = 0; j < slotsX; j++) { GameObject o = slots[i, j]; if (o == null || o == currentlySelected) { continue; } int dx = j - cursorX; int dy = i - cursorY; int norm = (dx * dx) + (dy * dy); if (norm < bestNorm) { bestX = j; bestY = i; bestNorm = norm; bestObject = o; } } } if (bestX != -1 && bestY != -1) { cursorX = bestX; cursorY = bestY; Pointer.transform.localPosition = new Vector3(bestObject.transform.localPosition.x, bestObject.transform.localPosition.y + (3.0f * bestObject.GetComponent <ArgumentContainer>().Height / 32.0f), -0.01f); } } else { for (int i = 0; i < cursorY; i++) { for (int j = 0; j < slotsX; j++) { if (openArgumentSlots[i, j] == null || !openArgumentSlots[i, j].Type.Equals(SelectedExpression.GetComponent <ArgumentContainer>().Argument.Type)) { continue; } int dx = j - cursorX; int dy = i - cursorY; int norm = (dx * dx) + (dy * dy); if (norm < bestNorm) { bestX = j; bestY = i; bestNorm = norm; } } } if (bestX != -1 && bestY != -1) { cursorX = bestX; cursorY = bestY; Pointer.transform.localPosition = new Vector3(0.95f * (-0.5f + 1 / 16.0f + 0.125f * cursorX), 0.95f * ((0.5f + 1 / 16.0f) - 0.125f * cursorY), -0.02f); } } } if (Input.GetButtonDown("Submit") && IsWorkspaceActive) { if (SelectedExpression == null) { SelectedExpression = slots[cursorY, cursorX]; var selectedType = SelectedExpression.GetComponent <ArgumentContainer>().Argument.Type; bool oneOpenSlot = false; for (int i = 0; i < slotsY; i++) { if (oneOpenSlot) { break; } for (int j = 0; j < slotsX; j++) { OpenArgumentInfo openArgumentSlot = openArgumentSlots[i, j]; if (openArgumentSlot == null || !openArgumentSlot.Type.Equals(selectedType)) { continue; } if (openArgumentSlot.Arguments.Length > 0 && openArgumentSlot.Type.Equals(SelectedExpression.GetComponent <ArgumentContainer>().Argument.Type)) { cursorX = j; cursorY = i; } Pointer.transform.localPosition = new Vector3(0.95f * (-0.5f + 1 / 16.0f + 0.125f * j), 0.95f * ((0.5f + 1 / 16.0f) - 0.125f * i), -0.02f); oneOpenSlot = true; break; } } } else { // Debug.Log("Combining " + SelectedExpression + " at " + CurrentArguments[ArgumentIndex]); var openArgumentSlot = openArgumentSlots[cursorY, cursorX]; Argument selectedArgument = SelectedExpression.GetComponent <ArgumentContainer>().Argument; if (openArgumentSlot != null && openArgumentSlot.Type.Equals(selectedArgument.Type)) { openArgumentSlot.Arguments[openArgumentSlot.Arguments.Length - 1] = selectedArgument; var parentContainerScript = openArgumentSlot.ParentContainer.GetComponent <ArgumentContainer>(); for (int i = openArgumentSlot.ParentY; i < openArgumentSlot.ParentY + parentContainerScript.Height; i++) { for (int j = openArgumentSlot.ParentX; j < openArgumentSlot.ParentX + parentContainerScript.Width; j++) { slots[i, j] = null; openArgumentSlots[i, j] = null; } } var combinedExpression = new Expression(parentContainerScript.Argument as Expression, openArgumentSlot.Arguments); Destroy(openArgumentSlot.ParentContainer); var o = SpawnExpression(combinedExpression); Pointer.transform.localPosition = new Vector3(o.transform.localPosition.x, o.transform.localPosition.y + (3.0f * o.GetComponent <ArgumentContainer>().Height / 32.0f), -0.01f); // TODO: make this more efficient for (int i = 0; i < slotsY; i++) { for (int j = 0; j < slotsX; j++) { if (slots[i, j] == SelectedExpression) { slots[i, j] = null; } } } Destroy(SelectedExpression); } } } if (Input.GetButtonDown("Use")) { if (IsWorkspaceActive) { if (SelectedExpression != null && !IsRadialMenuActive) { // set expression to center of screen SelectedExpression.transform.SetParent(Workspace.transform.parent); SelectedExpression.transform.localPosition = new Vector3(0, 0, 0.5f); // @TODO move the pointer to another expression, if one exists // (this should probably be its own method) // disable the workspace IsWorkspaceActive = false; Workspace.SetActive(false); PlayerMovement.enabled = true; MouseLook.enabled = true; // set equipped expression EquippedExpression = SelectedExpression; SelectedExpression = null; } } else { if (EquippedExpression != null) { // Raycast RaycastHit hit; bool collided = Physics.Raycast( Camera.transform.position, // Camera.transform.forward, Camera.transform.TransformDirection(Vector3.forward), out hit, 10, 1 << 10); if (collided) { var targetedObject = hit.transform.gameObject; // @Note the object should be displayed // and received by other NPC's sensors, // not sent directly. But this is less // error-prone to start out with. var targetedMentalState = targetedObject.GetComponent <MentalState>(); var targetedActuator = targetedObject.GetComponent <Actuator>(); if (targetedMentalState != null && targetedActuator != null) { // TODO uncomment this when you have the ability // to make a polymorphic functional expression. // targetedMentalState.StartCoroutine(targetedMentalState.Assert( // new Expression(Expression.SAY, Expression.CHARLIE, // EquippedExpression.GetComponent<ArgumentContainer>().Argument as Expression))); targetedActuator.StartCoroutine( targetedActuator.RespondTo(EquippedExpression.GetComponent <ArgumentContainer>().Argument as Expression, Expression.CHARLIE)); Destroy(EquippedExpression); EquippedExpression = null; } } } } } if (Input.GetButtonDown("Cancel") && IsWorkspaceActive) { if (IsRadialMenuActive) { RadialMenu.ExitMenu(); RadialMenu.enabled = false; IsRadialMenuActive = false; } else if (SelectedExpression != null) { Pointer.transform.localPosition = new Vector3(SelectedExpression.transform.localPosition.x, SelectedExpression.transform.localPosition.y + (3.0f * SelectedExpression.GetComponent <ArgumentContainer>().Height / 32.0f), -0.01f); SelectedExpression = null; } else { IsWorkspaceActive = false; Workspace.SetActive(false); PlayerMovement.enabled = true; MouseLook.enabled = true; } // HighlightPoint.SetActive(true); } }