private void Start() { if (_dropdown == null) { _logger.LogError(LoggedFeature.Replays, "Dropdown not assigned."); return; } if (_loadReplayButton == null) { _logger.LogError(LoggedFeature.Replays, "Load button not assigned."); return; } _dropdown.ClearOptions(); List <Dropdown.OptionData> options = new List <Dropdown.OptionData>(); foreach (var saveName in _commandHistoryLoader.SavedCommandHistories) { options.Add(new Dropdown.OptionData(saveName)); } _dropdown.AddOptions(options); _loadReplayButton.onClick.AddListener(HandleLoadButtonPressed); }
private void HandleConfirmPressed() { if (_selectedIndex < 0 || _selectedIndex >= _mapData.Sections.Length) { _logger.LogError(LoggedFeature.MapEditor, "Invalid section index: {0}", _selectedIndex); return; } uint sectionIndex = _dropdownIndexMap.FirstOrDefault(x => x.Value == _selectedIndex).Key; _mapSectionData.SetSectionConnection(_tileCoords, sectionIndex); }
public IObservable <Unit> Run() { ITransformableUnit unit = _unitRegistry.GetTransformableUnit(_data.unitId); if (unit == null) { string errorMsg = $"Unit not found in registry: {_data.unitId}"; _logger.LogError(LoggedFeature.Units, errorMsg); return(Observable.Throw <Unit>(new Exception(errorMsg))); } // TODO: Maybe encapsulate rotation of units unit.Transform.Rotate(Vector3.forward, _data.degrees); return(Observable.ReturnUnit()); }
public UniTask Show(IUnit unit) { var unitCoords = _gridUnitManager.GetUnitCoords(unit); if (unitCoords == null) { var msg = $"Unit not in tile: {unit}"; _logger.LogError(LoggedFeature.Units, msg); return(UniTask.FromException(new Exception(msg))); } // Acquire input lock. _lockToken = _inputLock.Lock(); // Set selected unit and events _unit = unit; _moveUnitButton.onClick.AddListener(HandleMoveUnitButtonPressed); _removeUnitButton.onClick.AddListener(HandleRemoveUnitButtonPressed); _rotateUnitButton.onClick.AddListener(HandleRotateUnitPressed); _cancelButton.onClick.AddListener(HandleCancelButtonPressed); // Show radial menu var worldPosition = _gridPositionCalculator.GetTileCenterWorldPosition(unitCoords.Value); _menuScreenPositon = _camera.WorldToScreenPoint(worldPosition); return(_radialMenu.Show(_menuScreenPositon)); }
public ICommand Create(Type commandType, Type dataType, ISerializable data) { // Otherwise, we iterate through the containers statically injected, which may not be in context. foreach (var container in _containers) { if (!container.HasBinding(commandType)) { continue; } // TODO: Avoid using instantiate explicit here ICommand command = (ICommand)container.InstantiateExplicit(commandType, new List <TypeValuePair> { new TypeValuePair(dataType, data) }); if (command != null) { return(command); } } _logger.LogError(LoggedFeature.CommandSystem, "Command not found in registered contexts: {0}", commandType); return(null); }
private void HandleOnSpawnButtonClicked(IntVector2 tileCoords) { var selectedIndex = (uint)_dropdown.value; int numUnits = _unitAmountDropdown.value + 1; IUnitData unitData; if (selectedIndex < _numPlayers) { unitData = _unitDataIndexResolver.ResolveUnitData(UnitType.Player, selectedIndex); } else { unitData = _unitDataIndexResolver.ResolveUnitData(UnitType.NonPlayer, selectedIndex - _numPlayers); } if (unitData == null) { _logger.LogError(LoggedFeature.Units, "Invalid unit index: {0}", selectedIndex); return; } // If only one unit, just spawn at the point. if (numUnits == 1) { SpawnUnit(unitData, tileCoords); return; } // For multiple units, spawn randomly around the position. IntVector2[] tilePositions = _randomGridPositionProvider.GetRandomUniquePositions(tileCoords, 1, numUnits); foreach (var tilePosition in tilePositions) { SpawnUnit(unitData, tilePosition); } }
public IObservable <Rect> Show() { if (_selectionSprite.drawMode != SpriteDrawMode.Sliced) { var msg = "SelectionSprite drawMode must be sliced"; _logger.LogError(LoggedFeature.UI, msg); throw new Exception(msg); } // Subscribe to mouse events var mouseDownStream = Observable.EveryUpdate() .Where(_ => Input.GetMouseButtonDown(0)) .Select(_ => _cameraInput.MouseWorldPosition); // Return a drag stream for each time we receive a mouse down. // This builds an observable of observables which will only emit as we drag. mouseDownStream .Select(_ => GetMouseDragStream(_cameraInput.MouseWorldPosition)) // Switch "Flattens" the observable and only emits the drag events. .Switch() .Subscribe(HandleMouseDrag) .AddTo(_disposables); // Same deal but this time only emit mouse ups. This is the event that we want to return. // Note that we need to pass in the "StartPosition" to the mouse up stream method to // create a different observable based on the start position, which depends on mouseDownStream. var mouseUpObservable = mouseDownStream.Select(x => GetMouseUpStream(x)).Switch(); mouseUpObservable.Subscribe(HandleMouseUp).AddTo(_disposables); return(mouseUpObservable); }
public IObservable <UniRx.Unit> Run() { IUnitData[] unitDatas = _unitSpawnSettings.GetUnits(_data.unitCommandData.UnitType); if (_data.unitCommandData.UnitIndex >= unitDatas.Length) { string errorMsg = string.Format("Unit Index not in unit datas range: {0}", _data.unitCommandData.UnitIndex); _logger.LogError(LoggedFeature.Units, errorMsg); return(Observable.Throw <UniRx.Unit>(new IndexOutOfRangeException(errorMsg))); } IUnitData unitData = unitDatas[(int)_data.unitCommandData.UnitIndex]; // First, spawn the pets recursively. // We create commands that we execute directly, because // we don't want to treat these as standalone commands (they are only ever children of this command) IUnit[] pets = new IUnit[_data.unitCommandData.pets.Length]; for (var i = 0; i < _data.unitCommandData.pets.Length; i++) { SpawnUnitData petSpawnUnitData = new SpawnUnitData(_data.unitCommandData.pets[i], _data.tileCoords, _data.isInitialSpawn); ICommand petSpawnCommand = _commandFactory.Create(typeof(SpawnUnitCommand), typeof(SpawnUnitData), petSpawnUnitData); petSpawnCommand.Run(); pets[i] = _unitRegistry.GetUnit(_data.unitCommandData.pets[i].unitId); } // Now, spawn the unit itself. IUnit unit = _unitPool.Spawn(_data.unitCommandData.unitId, unitData, pets); _gridUnitManager.PlaceUnitAtTile(unit, _data.tileCoords); _logger.Log(LoggedFeature.Units, "Spawned: {0}. Id: {1}", unitData.Name, unit.UnitId); return(Observable.ReturnUnit()); }
public void Tick() { // _logger.Log(LoggedFeature.Assets, "{0}", _camera.ScreenToViewportPoint(UnityEngine.Input.mousePosition)); // if (!_isEnabled) { return; } // Are we inside the grid? IntVector2?tileAtMouse = _gridInputManager.TileAtMousePosition; if (tileAtMouse == null) { return; } // We we clicked? if (!UnityEngine.Input.GetMouseButtonDown(0) && !UnityEngine.Input.GetMouseButton(0)) { return; } // Are we over a UI element? if (_eventSystem.IsPointerOverGameObject()) { return; } // This may lazily instantiate the tile used to draw, so it is important that it happens before the raycast. IDrawableTile drawableTile = _drawableTileRegistry.GetDrawableTileAtCoordinates(tileAtMouse.Value); Vector2 mouseWorldPoint = _camera.ScreenToWorldPoint(UnityEngine.Input.mousePosition); RaycastHit2D raycastHit = Physics2D.Raycast(mouseWorldPoint, Vector2.zero, LayerMask.NameToLayer(kDrawingLayerName)); if (raycastHit.collider == null) { return; } Vector2?localPosition = _drawableTileRegistry.GetLocalPosition(raycastHit.point); if (localPosition == null) { _logger.LogError(LoggedFeature.Drawing, "Raycast hit point not found inside drawable tile. Point: {0}. Tile: {1}", raycastHit.point, drawableTile); return; } Vector2 pixelPosition = GetLocalToPixelCoordinates(drawableTile.Sprite, localPosition.Value); PaintPixelData paintPixelData = new PaintPixelData(tileAtMouse.Value, IntVector2.Of(pixelPosition), _drawingViewController.PaintParams); _commandQueue.Enqueue <PaintPixelCommand, PaintPixelData>(paintPixelData, CommandSource.Game); }
public bool RemoveUnit(IUnit unit) { if (!_unitMap.ContainsKey(unit.UnitId)) { _logger.LogError(LoggedFeature.Grid, "Unit not found in grid: {0}", unit.UnitId); return(false); } // Remove unit from our unit / tile caches. int tileIndex = _unitMap[unit.UnitId]; IntVector2 tileCoords = IntVector2.Of((int)(tileIndex % _grid.NumTilesX), (int)(tileIndex / _grid.NumTilesY)); _tiles[tileCoords.x, tileCoords.y].Remove(unit); _unitMap.Remove(unit.UnitId); // Notify listeners. UnitRemovedFromTile.Invoke(unit, tileCoords); return(true); }
private void HandleSaveButtonPressed() { if (_mapDataStore.Commit(_mapStoreId)) { _logger.Log(LoggedFeature.MapEditor, "Successfully saved map data."); } else { _logger.LogError(LoggedFeature.MapEditor, "Error saving map data."); } }
public void Despawn(IntVector2 tileCoords) { if (!_spawnedRenderers.ContainsKey(tileCoords)) { _logger.LogError(LoggedFeature.MapEditor, "Despawning map element not in coords: {0}", tileCoords); return; } Despawn(_spawnedRenderers[tileCoords]); _spawnedRenderers.Remove(tileCoords); }
public void Despawn(UnitId unitId) { if (!_unitBehaviours.ContainsKey(unitId)) { _logger.LogError(LoggedFeature.Units, "Despawn called on unitId not found: {0}", unitId); return; } _unitRegistry.UnregisterUnit(unitId); _unitRendererPool.Despawn(_unitBehaviours[unitId]); }
public void LoadTiles() { if (_mapSectionData.Sprites == null || _mapSectionData.Sprites.Length == 0) { _logger.LogError(LoggedFeature.Map, "Map Data has no sprites"); return; } uint y = 0; int i = 0; uint yIndex = 0; uint numTilesX = _mapSectionData.GridData.NumTilesX; uint numTilesY = _mapSectionData.GridData.NumTilesY; Sprite firstSprite = _mapSectionData.Sprites[0]; // Calculate how many units in X this unit generates // For now, we assume that all sprites are the same size. uint numTilesInSpriteX = (uint)Mathf.CeilToInt(firstSprite.bounds.size.x / _mapSectionData.PixelsPerUnit); uint numTilesInSpriteY = (uint)Mathf.CeilToInt(firstSprite.bounds.size.y / _mapSectionData.PixelsPerUnit); uint numSpritesX = (uint)Mathf.CeilToInt(numTilesX / (float)numTilesInSpriteX); uint numSpritesY = (uint)Mathf.CeilToInt(numTilesY / (float)numTilesInSpriteY); while (i < _mapSectionData.Sprites.Length && y < numTilesY) { uint x = 0; uint xIndex = 0; uint miny = UInt32.MaxValue; while (i < _mapSectionData.Sprites.Length && x < numTilesX) { uint index = (numSpritesY - 1 - yIndex) * numSpritesX + xIndex; Sprite sprite = _mapSectionData.Sprites[index]; TileRendererBehaviour tileRendererBehaviour = _tileRendererPool.Spawn(sprite); tileRendererBehaviour.transform.position = _positionCalculator.GetTileOriginWorldPosition(IntVector2.Of(x, y)) + new Vector2(sprite.bounds.extents.x, sprite.bounds.extents.y); x += numTilesInSpriteX; xIndex++; miny = System.Math.Min(numTilesInSpriteY, miny); i++; } y += miny; yIndex++; } }
private bool ValidateParentContext(PreloadedAsset preloadedAsset, HashSet <string> allowedParentContracts) { foreach (var preloadedAssetSceneContext in preloadedAsset.sceneContexts) { if (!allowedParentContracts.Overlaps(preloadedAssetSceneContext.ParentContractNames)) { _logger.LogError(LoggedFeature.Assets, "Preloaded asset scene context: {0} should have a parent contract in: {1}", preloadedAssetSceneContext.name, _enforcedParentContext.name); return(false); } } return(true); }
private void HandleUnitPlacedAtTile(IUnit unit, IntVector2 tileCoords) { uint?unitIndex = _unitDataIndexResolver.ResolveUnitIndex(unit.UnitData); if (unitIndex == null) { _logger.LogError(LoggedFeature.Units, "Error adding unit with name: {0}. Index not resolved.", unit.UnitData.Name); return; } var unitDataReference = new UnitDataReference(unitIndex.Value, unit.UnitData.UnitType); _mapSectionData.AddInitialUnit(tileCoords, unitDataReference); }
public Sprite Create() { string spritePath = string.Format(_drawbleSpriteSettings.format, _drawbleSpriteSettings.path, _numTiles); _numTiles++; Sprite sprite = Resources.Load <Sprite>(spritePath); if (sprite == null) { _logger.LogError(LoggedFeature.Drawing, "Sprite not found: {0}.", spritePath); } return(sprite); }
public void LoadCommandHistory(string saveName) { string savePath = Path.Combine(Application.persistentDataPath, _settings.savePath, saveName); if (!File.Exists(savePath)) { _logger.LogError(LoggedFeature.Replays, "Save not found: {0}", savePath); return; } BinaryFormatter binaryFormatter = new BinaryFormatter(); using (FileStream fileStream = File.Open(savePath, FileMode.Open)) { EnqueueCommandHistory((SerializableCommandHistory)binaryFormatter.Deserialize(fileStream)); } }
public void HandleActionPlanned(IUnit unit) { var coords = _gridUnitManager.GetUnitCoords(unit); if (coords == null) { _logger.LogError(LoggedFeature.Units, "Unit not in tile: {0}", unit); return; } var baseSpeedTiles = _gridPositionCalculator.GetTilesAtDistance(coords.Value, unit.UnitData.UnitStats.speed / 5); foreach (var tileCoords in baseSpeedTiles) { _gridCellHighlightPool.Spawn(tileCoords, new Color(0, 1, 0, 0.6f)); _validTiles.Add(tileCoords); } }
private void HandleTileMetadataChanged(IntVector2 tileCoords, uint?sectionConnection) { if (sectionConnection == null) { _tileRendererPool.Despawn(tileCoords); return; } if (sectionConnection.Value >= _mapData.Sections.Length) { _logger.LogError(LoggedFeature.MapEditor, "Metadata change on SectionConnection out of bounds: {0}", sectionConnection.Value); return; } string sectionName = _mapData.Sections[sectionConnection.Value].SectionName; _tileRendererPool.Spawn(tileCoords, _sprite, sectionName); }
/// <summary> /// Shows the batch selection UI and highlights the selected units. /// Returns a task that is completed once the UI has closed or the batch action is complete. /// </summary> /// <param name="units"></param> /// <returns></returns> public async UniTask ShowAndWaitForAction(IUnit[] units) { // Show the menu var unitCoords = _gridUnitManager.GetUnitCoords(units[0]); if (unitCoords == null) { var msg = $"Unit not in tile: {units[0]}"; _logger.LogError(LoggedFeature.Units, msg); throw new Exception(msg); } _selectedUnits = units; var worldPosition = _gridPositionCalculator.GetTileCenterWorldPosition(unitCoords.Value); _radialMenu.Show(_camera.WorldToScreenPoint(worldPosition)); // Add listeners _removeUnitButton.onClick.AddListener(HandleRemoveUnitPressed); _rotateUnitButton.onClick.AddListener(HandleRotateUnitPressed); _cancelSelectionButton.onClick.AddListener(HandleCancelSelectionPressed); // Highlights _unitSelectionHighlighter.HighlightUnits(units); // Mouse Up / Down streams var mouseUpStream = Observable.EveryUpdate() .Where(_ => Input.GetMouseButtonUp(0)); var mouseDownStream = Observable.EveryUpdate() .Where(_ => Input.GetMouseButtonDown(0)) .Where(_ => _gridUnitInputManager.UnitsAtMousePosition.Length > 0) .Where(_ => units.Intersect(_gridUnitInputManager.UnitsAtMousePosition).Any()) .First(); _observer = mouseDownStream.Select(_ => mouseUpStream).Subscribe(_ => { HandleUnitMouseDown(units); }); await UniTask.WaitUntil(() => _selectedUnits == null); }
private void Start() { if (_dropdown == null) { _logger.LogError(LoggedFeature.Map, "Dropdown not assigned."); return; } if (_loadMapButton == null) { _logger.LogError(LoggedFeature.Map, "Spawn button not assigned."); return; } _loadMapButton.onClick.AddListener(HandleOnLoadMapClicked); _editMapButton.onClick.AddListener(HandleOnEditMapClicked); _dropdown.onValueChanged.AddListener(HandleOnValueChanged); }
public void LoadTiles() { if (_mapSectionData.Sprites == null || _mapSectionData.Sprites.Length == 0) { _logger.LogError(LoggedFeature.Map, "Map Data has no sprites"); return; } uint x = 0; uint y = 0; while (y < _mapSectionData.GridData.NumTilesY) { x = 0; uint miny = UInt32.MaxValue; while (x < _mapSectionData.GridData.NumTilesX) { Sprite sprite = _mapSectionData.Sprites[_randomProvider.GetRandomIntegerInRange(0, _mapSectionData.Sprites.Length)]; TileRendererBehaviour tileRendererBehaviour = _tileRendererPool.Spawn(sprite); tileRendererBehaviour.SpriteRenderer.flipX = _randomProvider.GetRandomIntegerInRange(0, 2) == 0; tileRendererBehaviour.SpriteRenderer.flipY = _randomProvider.GetRandomIntegerInRange(0, 2) == 0; tileRendererBehaviour.transform.position = _positionCalculator.GetTileOriginWorldPosition(IntVector2.Of(x, y)) + new Vector2(sprite.bounds.extents.x, sprite.bounds.extents.y); // Calculate how many units in X this unit generates (assume square for now). uint numXTiles = (uint)Mathf.CeilToInt(sprite.bounds.size.x / _mapSectionData.PixelsPerUnit); uint numYTiles = (uint)Mathf.CeilToInt(sprite.bounds.size.y / _mapSectionData.PixelsPerUnit); x += numXTiles; miny = System.Math.Min(numYTiles, miny); } y += miny; } }
public void HandleActionPlanned(IUnit[] units) { if (_gridInputManager.TileAtMousePosition == null) { _logger.LogError(LoggedFeature.Units, "Drag and drop action planned on units when not inside grid."); return; } _startCoordinate = _gridInputManager.TileAtMousePosition.Value; var unitStartingCoordinates = units.ToDictionary(unit => unit, unit => _gridUnitManager.GetUnitCoords(unit) .GetValueChecked()); _disposable = _gridInputManager.MouseEnteredTile.Subscribe(coords => { IntVector2 mouseCoords = _gridInputManager.TileAtMousePosition.GetValueChecked(); foreach (var unit in units) { IntVector2 moveDistance = mouseCoords - _startCoordinate.GetValueChecked(); IntVector2 unitStart = unitStartingCoordinates[unit]; PreviewUnitMovement(unit, unitStart + moveDistance); } }); }
public IDrawableTile GetDrawableTileAtCoordinates(IntVector2 tileCoords) { if (!_grid.TileBounds().Contains(tileCoords)) { _logger.LogError(LoggedFeature.Drawing, "GetDrawableTileAtCoordinates called out of bounds. {0}", tileCoords); return(null); } IntVector2 drawableCoords = GetDrawableTilePositionForTile(tileCoords); if (_tiles.ContainsKey(drawableCoords)) { return(_tiles[drawableCoords]); } IntVector2 bottomLeftTileCoords = GetBottomLeftGridTileCoords(tileCoords); Vector2 tileOrigin = _gridPositionCalculator.GetTileOriginWorldPosition(bottomLeftTileCoords); Vector2 tileCenter = GetCenterWorldPositionWithOrigin(tileOrigin); _tiles[drawableCoords] = _drawableTilePool.Spawn(tileCenter); return(_tiles[drawableCoords]); }