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);
        }
示例#3
0
        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));
        }
示例#5
0
        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);
        }
示例#6
0
        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);
            }
        }
示例#7
0
        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);
        }
示例#8
0
        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);
        }
示例#11
0
 private void HandleSaveButtonPressed()
 {
     if (_mapDataStore.Commit(_mapStoreId))
     {
         _logger.Log(LoggedFeature.MapEditor, "Successfully saved map data.");
     }
     else
     {
         _logger.LogError(LoggedFeature.MapEditor, "Error saving map data.");
     }
 }
示例#12
0
            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]);
        }
示例#14
0
        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++;
            }
        }
示例#15
0
        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);
        }
示例#18
0
        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));
            }
        }
示例#19
0
        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);
                }
            });
        }
示例#25
0
        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]);
        }