/* * If the player releases the right mouse button, the last grid-element is being removed and the input-behaviour is reset. * @param context The information provided with the triggering event. In this case the release of the right-mouse-button. */ public void StopRemoving(InputAction.CallbackContext context) { // Before resetting the input-bevaviour to not remove any object, after the mouse moved, remove the last element which was hit. // Placing and removing objects is only allowed, when the selection is not blocked. // This indicates that there is no socket left to place for a logic-element. if (!_selectionBlocked) { // Cast a ray from the camera through the cursor and identify the hit object. Ray ray = _camera.go.GetComponent <Camera>().ScreenPointToRay(Mouse.current.position.ReadValue()); RaycastHit hit; // If any object has been hit, remove it from the grid and play a feedback sound. if (Physics.Raycast(ray, out hit)) { // Play a sound through to indicate a successfull removal. AudioManager.instance.PlaySound(clips[0]); // Identify the hit by it's coordinates in the grid. Vector2Int temp = _mainGrid.grid.GetCoordinate(hit.point); // Place a filler-element on the identified coordinates, thusly "removing" the element. Placer.PlaceObject(_mainGrid.grid, _filler.go, temp.x, temp.y, _filler.go); } } // After the last element has been removed, reset to normal input-bevahiour _inputs.Schaltnetz.PreviewBuilding.performed -= RemoveMore; }
private void Awake() { UITableFiller.FillTable(_panel, _resolveResults, _variableCount.value, _expectedResults.valueArray, 2); UITableFiller.FillTable(_expectedPanel, _expectedResults.valueArray, _variableCount.value, _expectedResults.valueArray, 2); inventory = new Grid(1, 1, 20, new Vector3(-30, 0, 0)); grid = new Grid(_width, _height, _cellSize, _offset); _mainGrid.grid = grid; _auxGrid.grid = inventory; GameObject ground = Resources.Load <GameObject>("Prefabs/ground"); for (int i = 0; i < _width; i++) { for (int j = 0; j < _height; j++) { Placer.PlaceObject(grid, ground, i, j); } } InputHandler.instance.ChangeGIT(GameInputType.GateBuilder); Placer.PlaceObject(inventory, ground, 0, 0); GameObject start = Resources.Load <GameObject>("Prefabs/start"); GameObject end = Resources.Load <GameObject>("Prefabs/end"); foreach (StartingPointData startingpoint in _startingpoints) { GameObject temp = Placer.PlaceObject(grid, start, startingpoint.position.x, startingpoint.position.y); temp.GetComponent <StartingPoint>().SetCharge(startingpoint.charge); } Placer.PlaceObject(grid, end, _endpoint.x, _endpoint.y); }
private void Awake() { _selectionPanel.go = _selectionPanelGO; _results = new int[(int)Mathf.Pow(2, _variableCount.value)]; _outputs = new MultiCellElement[_outputCount.value]; _mainCamera.go = this.gameObject; _grid = new Grid(100, 100, 5, Vector3.zero); InputHandler.instance.ChangeGIT(GameInputType.Plotter); InputHandler.instance.floatingText = _floatingText; _mainGrid.grid = _grid; GameObject empty = Resources.Load <GameObject>("Prefabs/emptyCube"); _filler.go = empty; for (int i = 0; i < _width; i++) { for (int j = 0; j < _height; j++) { GameObject tempObj = Placer.PlaceObject(_grid, empty, i, j); } } int offSetX = _startingPointGo.GetComponent <GridElement>().size.x; int offSetY = _startingPointGo.GetComponent <GridElement>().size.y; for (int i = 0; i < _variableCount.value; i++) { GameObject tempMCE = Placer.PlaceMultiCellObject(_grid, _startingPointGo, _startingpoints[i].x, _startingpoints[i].y, _filler.go); if (tempMCE.GetComponentInChildren <TMP_Text>()) { tempMCE.GetComponentInChildren <TMP_Text>().text = ((Charge)i + 1).ToString(); } Vector2Int tempVecOutgoingSocket = new Vector2Int(_startingpoints[i].x + offSetX, _startingpoints[i].y); GameObject tempObj = Placer.PlaceObject(_grid, _outGoingSocket, _startingpoints[i].x + offSetX, _startingpoints[i].y); tempMCE.GetComponent <MultiCellElement>().AddToList(tempMCE.GetComponent <MultiCellElement>().outgoingSockets, tempVecOutgoingSocket); tempMCE.GetComponent <MultiCellElement>().outgoingSocketObjects.Add(tempObj.GetComponent <OutGoingSocket>()); } for (int j = 0; j < _outputCount.value; j++) { GameObject tempMCE = Placer.PlaceMultiCellObject(_grid, _endPointGo, _endPoints[j].x, _endPoints[j].y, _filler.go); if (tempMCE.GetComponentInChildren <TMP_Text>()) { tempMCE.GetComponentInChildren <TMP_Text>().text = j.ToString(); } Vector2Int tempVecIncomingSocket = new Vector2Int(_endPoints[j].x - 1, _endPoints[j].y); GameObject tempObj = Placer.PlaceObject(_grid, _incomingSocket, tempVecIncomingSocket.x, tempVecIncomingSocket.y); tempObj.GetComponent <SocketOfGridElement>().coordsToTarget = new Vector2Int(_endPoints[j].x, _endPoints[j].y); tempObj.GetComponent <SocketOfGridElement>().targetGo = tempMCE; tempMCE.GetComponent <MultiCellElement>().AddToList(tempMCE.GetComponent <MultiCellElement>().incomingSockets, tempVecIncomingSocket); _outputs[j] = tempMCE.GetComponent <MultiCellElement>(); } }
//////////////////////////////////////////////////////////////////////////////////////////// // General Input-Behaviour Methods /* * Cancel method, to either present the Pause menu, or stop placing a logic element on Powercity. * @param context Information provided by the triggering event. In this case the buttonpress on the ESC-key. */ private void Cancel(InputAction.CallbackContext context) { // If the selection is blocked, and therefore the player must be placing sockets to an logic-element in powercity, stop this process. if (_selectionBlocked) { Placer.PlaceObject(_mainGrid.grid, _filler.go, tempTargetCoord.x, tempTargetCoord.y, _filler.go); _incomingSocketsToPlace = 0; _outgoingSocketsToPlace = 0; _selectionBlocked = false; selected.go = null; return; } // In any other case, pause the game. PauseGame(); }
/* * After being added to the input-behaviour, this method is called every frame the mouse has moved and is used to continously place connections, * while the left mouse-button is being held down. * @param context Information provided by the triggering event. In this case the movement of the mouse. */ private void PlaceConnection(InputAction.CallbackContext context) { // Cast a ray from the camera through the cursor and keep a reference to the hit object. Ray ray = _camera.go.GetComponent <Camera>().ScreenPointToRay(Mouse.current.position.ReadValue()); RaycastHit hit; // If an object was hit, place a connection-element on it's place. if (Physics.Raycast(ray, out hit)) { // Get the coordinates of the hit grid-element, if it is one. Vector2Int temp = _mainGrid.grid.GetCoordinate(hit.point); // Place a connection element on the hit grid-element. Placer.PlaceObject(_mainGrid.grid, selected.go, temp.x, temp.y, _filler.go); } }
// Start is called before the first frame update void Awake() { SetParams(); UITableFiller.FillTable(_expectedPanel, _expectedResults.valueArray, _variableCount.value, _expectedResults.valueArray); int cellCount = Convert.ToInt32(Math.Pow(2, _variableCount.value)); while (_width * _height != cellCount) { if (_width == _height) { _width *= 2; } else { _height *= 2; } } _charges.keyValuePairs = new Dictionary <char, bool>(); _charges.keyValuePairs['A'] = true; _charges.keyValuePairs['B'] = true; _charges.keyValuePairs['C'] = true; _charges.keyValuePairs['D'] = true; _charges.keyValuePairs['E'] = true; _grid = new Grid(_width, _height, 12, _gridOffset); _mainGrid.grid = _grid; InputHandler.instance.ChangeGIT(GameInputType.KV); Dictionary <char, bool> temp = new Dictionary <char, bool>(); GameObject empty = Resources.Load <GameObject>("Prefabs/empty"); for (int i = 0; i < _width; i++) { for (int j = 0; j < _height; j++) { temp = PrepareCharge(i, j); GameObject tempObj = Placer.PlaceObject(_grid, empty, i, j); tempObj.GetComponent <KVelement>().charge = ChargeCombinationToInt(temp); tempObj.GetComponent <KVelement>().text.text = ChargeCombinationToInt(temp).ToString(); } } DrawIndicators(); }
/* * This functions places an incoming socket and adjusts it's parameters to react correctly when being visited. * @param coords The coordinates to place the socket on the grid. * @param targetCoord The coordinates of the logic-element to which this sockets belongs to. * @param filler The filler-object that is used to fill spaces, in case the placement of the sockets causes a conflict with a multi-cell-element. */ private void PlaceIncomingSocket(Vector2Int coords, Vector2Int targetCoords, GameObject filler) { // Only place the socket, if the coords is adjacent to the logic-element. if (Placer.IsAdjacent(_mainGrid.grid, coords, targetCoords)) { // Get a reference to the newly placed socket. GameObject tempObj; tempObj = Placer.PlaceObject(_mainGrid.grid, selected.go, coords.x, coords.y, _filler.go); // If the placement was successfull, play a sound and adjust attributes of the socket and the logic-element. if (tempObj) { // Auditive feedback for the successfull placement. AudioManager.instance.PlaySound(clips[0]); // Set the target-logic-element coordinates to the saved coordinates. tempObj.GetComponent <SocketOfGridElement>().coordsToTarget = tempTargetCoord; // Set the target-logic-element to be the target of the socket. tempObj.GetComponent <SocketOfGridElement>().targetGo = _mainGrid.grid.GetObjFromCoordinate(tempTargetCoord); // Add this socket to the list of incoming sockets of the logic-element. MultiCellElement targetMCE = _mainGrid.grid.GetObjFromCoordinate(tempTargetCoord).GetComponent <MultiCellElement>(); // Nullchecking the element. Might not really be neccessary, if the inventory is correct, which it should. if (tempObj.GetComponentInChildren <TMP_Text>()) { // Set the text of the prefab to the corresponding variable it resembles. // The first incoming socket is always A, the second is B, the third is C and so on. tempObj.GetComponentInChildren <TMP_Text>().text = ((Charge)targetMCE.incomingSockets.Count + 1).ToString(); } targetMCE.AddToList(targetMCE.incomingSockets, coords); // Decrement the number of incoming sockets needed to be placed by the player. _incomingSocketsToPlace--; } } // Show a message, reminding the player that sockets need to be placed adjacent to the element. else { floatingText.GetComponent <Animation>().Play(); } }
/* * Similar to placing an incoming socket, but still different. * @param coords The coordinates to place the socket on the grid. * @param targetCoord The coordinates of the logic-element to which this sockets belongs to. * @param filler The filler-object that is used to fill spaces, in case the placement of the sockets causes a conflict with a multi-cell-element. */ private void PlaceOutgoingSocket(Vector2Int coords, Vector2Int targetCoords, GameObject filler) { // Also outgoing sockets can only be placed adjacent to logic-elements. if (Placer.IsAdjacent(_mainGrid.grid, coords, targetCoords)) { // Get a reference to the newly placed socket. GameObject tempObj; tempObj = Placer.PlaceObject(_mainGrid.grid, selected.go, coords.x, coords.y, _filler.go); // If the placement was successfull, play a sound and adjust attributes of the socket and the logic-element. if (tempObj) { AudioManager.instance.PlaySound(clips[0]); // Since outgoingsockets can't be visited, we only need to add the socket to the logic-elements list of outgoing sockets. // There is no need to define a target for the outgoing socket. MultiCellElement targetMCE = _mainGrid.grid.GetObjFromCoordinate(tempTargetCoord).GetComponent <MultiCellElement>(); if (tempObj.GetComponentInChildren <TMP_Text>()) { // Set the text of the prefab to the corresponding variable it resembles. // The first outgoing socket is always 0, the second is 1, the third is 2 and so on. tempObj.GetComponentInChildren <TMP_Text>().text = targetMCE.outgoingSockets.Count.ToString(); } targetMCE.AddToList(targetMCE.outgoingSockets, coords); targetMCE.outgoingSocketObjects.Add(tempObj.GetComponent <OutGoingSocket>()); // Decrement the number of incoming sockets needed to be placed by the player. _outgoingSocketsToPlace--; } } // Show a message, reminding the player that sockets need to be placed adjacent to the element. else { floatingText.GetComponent <Animation>().Play(); } }
//////////////////////////////////////////////////////////////////////////////////////////// // Trackymania Input-Behaviour Methods /* * Function to place a selected Track onto the grid in the scene. * Is triggered by left-mouse interaction on GateBuilder ActionMap and ClickAction Action. * @param context Inputcontext given bei the Actionevent. This is not needed for further calculations, but is neccessary to subscribe to inputevents. */ private void PlaceSelected(InputAction.CallbackContext context) { // Fire a ray from the Camera through the Cursor to determine which Object was clicked. Ray ray = _camera.go.GetComponent <Camera>().ScreenPointToRay(Mouse.current.position.ReadValue()); // Hit information of the raycast. RaycastHit hit; // Continue only if the Raycast hit an object in the scene. if (Physics.Raycast(ray, out hit)) { // Calculate the Coordinates of the GameObject hit by the Raycast. Vector2Int temp = _mainGrid.grid.GetCoordinate(hit.point); // Check if the hit element is a Gridelement. GridElement selection = hit.collider.gameObject.GetComponent <GridElement>(); // If the hit Object has valid coordinates, it must be on the grid. Place the selected Object onto the grid on the calculated coordinates. if (temp.x >= 0) { // If the player has a grid element in the inventory, place it on the gameboard and play a sound. if (selected.go != null) { AudioManager.instance.PlaySound(clips[4]); Placer.PlaceObject(_mainGrid.grid, selected.go, temp.x, temp.y); } } // If the Coordinates of the hit object are not valid, check if the hit object is a gridelement. // This must mean the player has selected a grid element for the inventory. else if (selection != null) { // To add the newly chosen element to the inventory, it must be removeable. // This must be done, to remove it from the inventory, in case the player chooses another element for the inventory in the future. selection.isRemoveable = true; selected.go = Placer.PlaceObject(_auxGrid.grid, selection.gameObject, 0, 0); } } }
/* * Method to be added to the input-behaviour when removing objects is needed. This will be done by the Remove-Method. * After adding this method to the input-behaviour, it will be triggered every frame the mouse has moved, removing all objects the mouse has hit. * @param context Informationen provided with the triggering event. In this case the movement of the mouse. */ public void RemoveMore(InputAction.CallbackContext context) { // Placing and removing objects is only allowed, when the selection is not blocked. // This indicates that there is no socket left to place for a logic-element. if (!_selectionBlocked) { // Cast a ray from the camera through the cursor and get a refenrence to the hit object, if there is one. Ray ray = _camera.go.GetComponent <Camera>().ScreenPointToRay(Mouse.current.position.ReadValue()); RaycastHit hit; // If an object was hit, try removing it. This will be successfull, if it is a removeable grid-element. if (Physics.Raycast(ray, out hit)) { // Play a sound to indicate a successfull removal. AudioManager.instance.PlaySound(clips[0]); // Get the coordinates of the hit object in the grid. Vector2Int temp = _mainGrid.grid.GetCoordinate(hit.point); // Remove the hit object by placing a filler-element on it's coordinates. Placer.PlaceObject(_mainGrid.grid, _filler.go, temp.x, temp.y, _filler.go); } } }
/* * Method to handle left-mouse clicks. These can lead to various cases, depending on the clicked Object in the scene. * @param context Context of the Actionevent. In this case the method is triggered by leftclick. The information about the event are not used further. */ private void LeftClickPC(InputAction.CallbackContext context) { // First, cast a ray from the camera through the mouse-cursor and check for hits. Ray ray = _camera.go.GetComponent <Camera>().ScreenPointToRay(Mouse.current.position.ReadValue()); RaycastHit hit; // If an object was hit, check various cases. if (Physics.Raycast(ray, out hit)) { // Get the coordinates of the hit object in the grid. Vector2Int temp = _mainGrid.grid.GetCoordinate(hit.point); // If the hit object in the grid is a multiCellElement, show it's truthtable in the selection UI-Panel and return. if (_mainGrid.grid.GetObjFromCoordinate(temp).GetComponent <MultiCellElement>()) { FillSelectionResultTable(_mainGrid.grid.GetObjFromCoordinate(temp).GetComponent <MultiCellElement>()); return; } // If anything else was hit, hide the selection UI-panel. else { selectionPanel.go.SetActive(false); } // If the player hasn't selected a specific object to place, start placing connections as long as the left-mouse button is held down. // This is done by changing input-behaviour to place a connection every frame, that the mouse has moved. // Either the player has already placed a connection-element, in that case only the input-behaviour has to be changed. // Otherwise, the connection-element has to be placed in the inventory. if (!selected.go) { _inputs.Schaltnetz.PreviewBuilding.performed += PlaceConnection; selected.go = _connection.go; UpdatePreview(); } else if (selected.go == _connection.go) { _inputs.Schaltnetz.PreviewBuilding.performed += PlaceConnection; } // If the player has something in the inventory, that is not null or a connection-element, takes this route. if (temp.x >= 0) { // Check if the player still has to place incoming or outgoingsockets. If so, try to place the correct element on the clicked spot. // If there are no left sockets left to place, skip this part // If there are sockets to place, first the incoming, then the outgoing sockets are going to be placed. if (_incomingSocketsToPlace > 0 || _outgoingSocketsToPlace > 0) { if (_incomingSocketsToPlace > 0) { PlaceIncomingSocket(temp, tempTargetCoord, _filler.go); // After placing the last incoming socket, change the element in the inventory for the next placement. if (_incomingSocketsToPlace <= 0) { selected.go = _outgoingSocketPrefab; UpdatePreview(); } } // After all incoming sockets have been placed, place all outgoing sockets. else { PlaceOutgoingSocket(temp, tempTargetCoord, _filler.go); // When all outgoingsockets are placed, reset the inventory and unlock the selection. if (_outgoingSocketsToPlace <= 0) { _selectionBlocked = false; selected.go = null; UpdatePreview(); } } } // This section handles the case, that the player wants to place an element, that is not a connection and has no sockets left to place. else { // Variable used to store a reference to the newly placed element. GameObject tempObj; // Give the player auditive feedback about the placement. AudioManager.instance.PlaySound(clips[0]); // If the element in the inventory only is 1x1 gridcells big, just place it on the grid. if (selected.go.GetComponent <GridElement>().size.x == 1 && selected.go.GetComponent <GridElement>().size.y == 1) { // Place the object and take a reference. tempObj = Placer.PlaceObject(_mainGrid.grid, selected.go, temp.x, temp.y, _filler.go); } // Bigger elements need to be placed differently, since there can happen multiple conflicts while placing them on the grid. else { // Place the object and take a reference. tempObj = Placer.PlaceMultiCellObject(_mainGrid.grid, selected.go, temp.x, temp.y, _filler.go); // Bigger elements get a text to identify them on the board. They get a Tag with the given name that is placed right above them. if (tempObj.GetComponentInChildren <TMP_Text>()) { tempObj.GetComponentInChildren <TMP_Text>().text = tempObj.GetComponent <MultiCellElement>().name; } } // After placing an object, check if the object needs to have incoming or outgoing sockets. If so, set the counters and lock the selection. // This way, the player will have to place all remaining sockets before being able to place more elements. if (tempObj && (tempObj.GetComponent <GridElement>().incomingSocketCount > 0 || tempObj.GetComponent <GridElement>().outComingSocketCount > 0)) { // Block the player from placing other elements, while having to place sockets. _selectionBlocked = true; // Save the coordinates of the newly placed object for when the incoming and outgoing sockets are being planced. tempTargetCoord = temp; // Increase the counter to show how many sockets need to be placed. _incomingSocketsToPlace = tempObj.GetComponent <GridElement>().incomingSocketCount; _outgoingSocketsToPlace = tempObj.GetComponent <GridElement>().outComingSocketCount; // Start by placing incoming sockets by filling the inventory with an incoming socket. selected.go = _incomingSocketPrefab; // Update the preview, so the player can see where the element would be placed. UpdatePreview(); } } } } }