diff --git a/src/client/haxe/ru/m/control/ControlBus.hx b/src/client/haxe/ru/m/control/ControlBus.hx new file mode 100644 index 0000000..cdbcdd9 --- /dev/null +++ b/src/client/haxe/ru/m/control/ControlBus.hx @@ -0,0 +1,30 @@ +package ru.m.control; + +import ru.m.control.IControlBus; +import haxework.signal.Signal; + +class ControlBus implements IControlBus { + + public var signal(default, null):Signal3; + private var connections:MapBool->Void>; + + public function new() { + signal = new Signal3(); + connections = new Map(); + } + + public function connect(device:IControlDevice):Void { + var connector = function(action:DeviceAction, on:Bool):Void { + signal.emit(device.type, action, on); + } + connections.set(device.type, connector); + device.signal.connect(connector); + } + + public function disconnect(device:IControlDevice):Void { + if (connections.exists(device.type)) { + device.signal.disconnect(connections.get(device.type)); + connections.remove(device.type); + } + } +} diff --git a/src/client/haxe/ru/m/control/DeviceAction.hx b/src/client/haxe/ru/m/control/DeviceAction.hx new file mode 100644 index 0000000..b711555 --- /dev/null +++ b/src/client/haxe/ru/m/control/DeviceAction.hx @@ -0,0 +1,8 @@ +package ru.m.control; + +import ru.m.geom.Direction; + +enum DeviceAction { + DIRECTION(direction:Direction); + KEY(code:Int); +} diff --git a/src/client/haxe/ru/m/control/DeviceType.hx b/src/client/haxe/ru/m/control/DeviceType.hx new file mode 100644 index 0000000..7d47901 --- /dev/null +++ b/src/client/haxe/ru/m/control/DeviceType.hx @@ -0,0 +1,7 @@ +package ru.m.control; + +enum DeviceType { + NONE; + KEYBOARD; + GAMEPAD(id:Int); +} diff --git a/src/client/haxe/ru/m/control/IControlBus.hx b/src/client/haxe/ru/m/control/IControlBus.hx new file mode 100644 index 0000000..3757b9c --- /dev/null +++ b/src/client/haxe/ru/m/control/IControlBus.hx @@ -0,0 +1,10 @@ +package ru.m.control; + +import haxework.signal.Signal; + +interface IControlBus { + public var signal(default, null):Signal3; + + public function connect(device:IControlDevice):Void; + public function disconnect(device:IControlDevice):Void; +} diff --git a/src/client/haxe/ru/m/control/IControlDevice.hx b/src/client/haxe/ru/m/control/IControlDevice.hx new file mode 100644 index 0000000..a870c45 --- /dev/null +++ b/src/client/haxe/ru/m/control/IControlDevice.hx @@ -0,0 +1,10 @@ +package ru.m.control; + +import haxework.signal.Signal; + +interface IControlDevice { + public var type(default, null):DeviceType; + public var signal(default, null):Signal2; + + public function dispose():Void; +} diff --git a/src/client/haxe/ru/m/control/KeyboardDevice.hx b/src/client/haxe/ru/m/control/KeyboardDevice.hx new file mode 100644 index 0000000..fbdd6f1 --- /dev/null +++ b/src/client/haxe/ru/m/control/KeyboardDevice.hx @@ -0,0 +1,38 @@ +package ru.m.control; + +import flash.display.Stage; +import flash.events.KeyboardEvent; +import haxework.signal.Signal; +import ru.m.control.DeviceAction; + +class KeyboardDevice implements IControlDevice { + + public var type(default, null):DeviceType; + public var signal(default, null):Signal2; + + private var stage:Stage; + + public function new(stage:Stage) { + this.stage = stage; + type = DeviceType.KEYBOARD; + signal = new Signal2(); + stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); + stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp); + } + + private function onKeyDown(event:KeyboardEvent):Void { + signal.emit(KEY(event.keyCode), true); + } + + private function onKeyUp(event:KeyboardEvent):Void { + signal.emit(KEY(event.keyCode), false); + } + + public function dispose():Void { + if (stage != null) { + stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); + stage.removeEventListener(KeyboardEvent.KEY_UP, onKeyUp); + stage = null; + } + } +} diff --git a/src/client/haxe/ru/m/tankz/Init.hx b/src/client/haxe/ru/m/tankz/Init.hx index 1aa3b04..3d2b080 100644 --- a/src/client/haxe/ru/m/tankz/Init.hx +++ b/src/client/haxe/ru/m/tankz/Init.hx @@ -1,5 +1,9 @@ package ru.m.tankz; +import flash.Lib; +import ru.m.control.KeyboardDevice; +import ru.m.control.ControlBus; +import ru.m.control.IControlBus; import lime.ui.Joystick; import lime.ui.Gamepad; import haxework.animate.FadeAnimate; @@ -34,6 +38,7 @@ class Init { @:provide static var networkManager:NetworkManager; @:provide static var popupManager:PopupManager; @:provide static var connection:IConnection; + @:provide static var bus:IControlBus; private static function buildConnection():IConnection { var host:String = CompilationOption.get("host"); @@ -65,6 +70,9 @@ class Init { connection = buildConnection(); networkManager = new NetworkManager(); + bus = new ControlBus(); + bus.connect(new KeyboardDevice(Lib.current.stage)); + for (device in Gamepad.devices) { trace('gamepad', device); } diff --git a/src/client/haxe/ru/m/tankz/control/ActionConfig.hx b/src/client/haxe/ru/m/tankz/control/ActionConfig.hx index ec96bd1..0e683e5 100644 --- a/src/client/haxe/ru/m/tankz/control/ActionConfig.hx +++ b/src/client/haxe/ru/m/tankz/control/ActionConfig.hx @@ -1,27 +1,18 @@ package ru.m.tankz.control; -import ru.m.tankz.control.Control.TankAction; +import ru.m.control.DeviceAction; +import ru.m.control.DeviceType; +import ru.m.tankz.control.Control; -typedef ActionItem = { - public var action:TankAction; - public var key:Int; -} - -typedef KeyBinding = Map; +typedef Binding = Map; class ActionConfig { - public var data(default, null):Array; + public var device(default, null):DeviceType; + public var binding(default, null):Binding; - public function new(data:Array) { - this.data = data; - } - - public function asKeyBinding():KeyBinding { - var result = new KeyBinding(); - for (item in data) { - result[item.key] = item.action; - } - return result; + public function new(device:DeviceType = null, binding:Binding = null) { + this.device = device != null ? device : NONE; + this.binding = binding != null ? binding : new Map(); } } diff --git a/src/client/haxe/ru/m/tankz/control/HumanControl.hx b/src/client/haxe/ru/m/tankz/control/HumanControl.hx index e5aaee0..7557660 100644 --- a/src/client/haxe/ru/m/tankz/control/HumanControl.hx +++ b/src/client/haxe/ru/m/tankz/control/HumanControl.hx @@ -1,39 +1,54 @@ package ru.m.tankz.control; +import haxe.EnumTools.EnumValueTools; import flash.events.FocusEvent; -import flash.events.KeyboardEvent; -import flash.Lib; import haxe.Timer; +import ru.m.control.DeviceAction; +import ru.m.control.DeviceType; +import ru.m.control.IControlBus; import ru.m.geom.Direction; -import ru.m.tankz.control.ActionConfig; import ru.m.tankz.control.Control; import ru.m.tankz.storage.SettingsStorage; import ru.m.tankz.Type; class HumanControl extends Control { - @:provide var storage:SettingsStorage; + @:provide static var storage:SettingsStorage; + @:provide static var bus:IControlBus; + + private var config:ActionConfig; - private var keyBinding:KeyBinding; private var moveQueue:Array; private var shotTimer:Timer; public function new(playerId:PlayerId, controlIndex:Int) { super(playerId); - this.keyBinding = storage.getActionConfig(controlIndex).asKeyBinding(); + config = storage.getActionConfig(controlIndex); + trace(controlIndex, config.device, config.binding); moveQueue = []; } + private function onDeviceAction(device:DeviceType, action:DeviceAction, on:Bool):Void { + if (EnumValueTools.equals(config.device, device)) { + switch action { + case DIRECTION(direction): + toggleAction(MOVE(direction), on); + case any: + if (config.binding.exists(any)) { + toggleAction(config.binding.get(any), on); + } + } + } + } + override public function start():Void { super.start(); - Lib.current.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); - Lib.current.stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp); + bus.signal.connect(onDeviceAction); } override public function stop():Void { super.stop(); - Lib.current.stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); - Lib.current.stage.removeEventListener(KeyboardEvent.KEY_UP, onKeyUp); + bus.signal.disconnect(onDeviceAction); moveQueue = []; if (shotTimer != null) { shotTimer.stop(); @@ -69,18 +84,6 @@ class HumanControl extends Control { } } - private function onKeyDown(event:KeyboardEvent):Void { - if (keyBinding.exists(event.keyCode)) { - toggleAction(keyBinding.get(event.keyCode), true); - } - } - - private function onKeyUp(event:KeyboardEvent):Void { - if (keyBinding.exists(event.keyCode)) { - toggleAction(keyBinding.get(event.keyCode), false); - } - } - private function onFocusOut(event:FocusEvent):Void { moveQueue = []; updateMove(); @@ -88,13 +91,13 @@ class HumanControl extends Control { private function updateMove():Void { if (moveQueue.length == 0) { - action(TankAction.STOP); + action(STOP); } else { - action(TankAction.MOVE(moveQueue[0])); + action(MOVE(moveQueue[0])); } } private function shot():Void { - action(TankAction.SHOT); + action(SHOT); } } diff --git a/src/client/haxe/ru/m/tankz/storage/SettingsStorage.hx b/src/client/haxe/ru/m/tankz/storage/SettingsStorage.hx index e571349..764c834 100644 --- a/src/client/haxe/ru/m/tankz/storage/SettingsStorage.hx +++ b/src/client/haxe/ru/m/tankz/storage/SettingsStorage.hx @@ -3,6 +3,8 @@ package ru.m.tankz.storage; import flash.ui.Keyboard; import haxework.storage.SharedObjectStorage; import haxework.utils.ObjectUtil; +import ru.m.control.DeviceAction; +import ru.m.control.DeviceType; import ru.m.geom.Direction; import ru.m.tankz.control.ActionConfig; import ru.m.tankz.control.Control.TankAction; @@ -12,7 +14,7 @@ class SettingsStorage extends SharedObjectStorage { public var screenGamepad(get, set):Bool; public function new() { - super("settings"); + super("settings-2"); } private function get_screenGamepad():Bool { @@ -37,27 +39,37 @@ class SettingsStorage extends SharedObjectStorage { } private static var defaults:Map = [ - 0 => new ActionConfig([ - {action:TankAction.MOVE(Direction.TOP), key:Keyboard.W}, - {action:TankAction.MOVE(Direction.LEFT), key:Keyboard.A}, - {action:TankAction.MOVE(Direction.BOTTOM), key:Keyboard.S}, - {action:TankAction.MOVE(Direction.RIGHT), key:Keyboard.D}, - {action:TankAction.SHOT, key:Keyboard.SPACE}, + 0 => new ActionConfig(KEYBOARD, [ + KEY(Keyboard.W) => MOVE(Direction.TOP), + KEY(Keyboard.A) => MOVE(Direction.LEFT), + KEY(Keyboard.S) => MOVE(Direction.BOTTOM), + KEY(Keyboard.D) => MOVE(Direction.RIGHT), + KEY(Keyboard.SPACE) => SHOT, ]), - 1 => new ActionConfig([ - {action:TankAction.MOVE(Direction.TOP), key:Keyboard.UP}, - {action:TankAction.MOVE(Direction.LEFT), key:Keyboard.LEFT}, - {action:TankAction.MOVE(Direction.BOTTOM), key:Keyboard.DOWN}, - {action:TankAction.MOVE(Direction.RIGHT), key:Keyboard.RIGHT}, - {action:TankAction.SHOT, key:Keyboard.NUMPAD_0}, + 1 => new ActionConfig(KEYBOARD, [ + KEY(Keyboard.UP) => MOVE(Direction.TOP), + KEY(Keyboard.LEFT) => MOVE(Direction.LEFT), + KEY(Keyboard.DOWN) => MOVE(Direction.BOTTOM), + KEY(Keyboard.RIGHT) => MOVE(Direction.RIGHT), + KEY(Keyboard.NUMPAD_0) => SHOT, ]), ]; - private static var empty:ActionConfig = new ActionConfig([ - {action:TankAction.MOVE(Direction.TOP), key:-1}, - {action:TankAction.MOVE(Direction.LEFT), key:-1}, - {action:TankAction.MOVE(Direction.BOTTOM), key:-1}, - {action:TankAction.MOVE(Direction.RIGHT), key:-1}, - {action:TankAction.SHOT, key:-1}, + private static var empty:ActionConfig = new ActionConfig(NONE, [ + KEY(-1) => MOVE(Direction.TOP), + KEY(-1) => MOVE(Direction.LEFT), + KEY(-1) => MOVE(Direction.BOTTOM), + KEY(-1) => MOVE(Direction.RIGHT), + KEY(-1) => SHOT, ]); + + public static function gamepadConfig(id:Int):ActionConfig { + return new ActionConfig(GAMEPAD(id), [ + DIRECTION(Direction.TOP) => MOVE(Direction.TOP), + DIRECTION(Direction.LEFT) => MOVE(Direction.LEFT), + DIRECTION(Direction.BOTTOM) => MOVE(Direction.BOTTOM), + DIRECTION(Direction.RIGHT) => MOVE(Direction.RIGHT), + KEY(0) => SHOT, + ]); + } } diff --git a/src/client/haxe/ru/m/tankz/view/GameFrame.hx b/src/client/haxe/ru/m/tankz/view/GameFrame.hx index 0811951..db83b1f 100644 --- a/src/client/haxe/ru/m/tankz/view/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/GameFrame.hx @@ -1,11 +1,8 @@ package ru.m.tankz.view; -import ru.m.tankz.storage.SettingsStorage; -import ru.m.tankz.control.Control.TankAction; -import ru.m.geom.Direction; -import ru.m.tankz.control.HumanControl; import haxework.view.frame.FrameSwitcher; import haxework.view.VGroupView; +import ru.m.control.IControlBus; import ru.m.tankz.game.GameEvent; import ru.m.tankz.game.GameState; import ru.m.tankz.game.IGame; @@ -13,6 +10,7 @@ import ru.m.tankz.game.record.GameRecord; import ru.m.tankz.network.NetworkManager; import ru.m.tankz.sound.SoundManager; import ru.m.tankz.storage.GameStorage; +import ru.m.tankz.storage.SettingsStorage; import ru.m.tankz.view.game.GameView; import ru.m.tankz.view.GamepadView; @@ -33,9 +31,11 @@ import ru.m.tankz.view.GamepadView; @:provide var settings:SettingsStorage; @:provide var game:IGame; + @:provide static var bus:IControlBus; public function onShow():Void { gamepad.visible = settings.screenGamepad; + bus.connect(gamepad); gameView.type = game.type; soundManager.config = game.config; gameView.render.config = game.config; @@ -58,7 +58,7 @@ import ru.m.tankz.view.GamepadView; public function onGameEvent(event:GameEvent):Void { switch event { - case GameEvent.COMPLETE(state, winner): + case COMPLETE(state, winner): this.state = state; stop(); switcher.change(ResultFrame.ID); @@ -67,6 +67,7 @@ import ru.m.tankz.view.GamepadView; } public function onHide():Void { + bus.disconnect(gamepad); stop(); soundManager.stopAll(); } @@ -74,21 +75,4 @@ import ru.m.tankz.view.GamepadView; public function close():Void { switcher.change(LevelFrame.ID); } - - private function onGamepadAction(action:GamepadAction, on:Bool):Void { - // ToDo: - for (control in game.controls) { - if (Std.is(control, HumanControl)) { - var tankAction:TankAction = switch action { - case UP: MOVE(Direction.TOP); - case LEFT: MOVE(Direction.LEFT); - case DOWN: MOVE(Direction.BOTTOM); - case RIGHT: MOVE(Direction.RIGHT); - case BUTTON_1: SHOT; - } - cast(control, HumanControl).toggleAction(tankAction, on); - break; - } - } - } } diff --git a/src/client/haxe/ru/m/tankz/view/GameFrame.yaml b/src/client/haxe/ru/m/tankz/view/GameFrame.yaml index 23b8fc5..66b6706 100644 --- a/src/client/haxe/ru/m/tankz/view/GameFrame.yaml +++ b/src/client/haxe/ru/m/tankz/view/GameFrame.yaml @@ -10,5 +10,4 @@ views: $type: ru.m.tankz.view.GamepadView geometry.position: absolute geometry.size.stretch: true - +actionSignal: $this:onGamepadAction visible: false diff --git a/src/client/haxe/ru/m/tankz/view/GamepadView.hx b/src/client/haxe/ru/m/tankz/view/GamepadView.hx index 0a44912..13ed27c 100644 --- a/src/client/haxe/ru/m/tankz/view/GamepadView.hx +++ b/src/client/haxe/ru/m/tankz/view/GamepadView.hx @@ -1,23 +1,20 @@ package ru.m.tankz.view; +import flash.events.MouseEvent; import flash.display.Graphics; import flash.events.TouchEvent; import haxework.signal.Signal; import haxework.view.skin.ISkin; import haxework.view.SpriteView; +import ru.m.control.DeviceAction; +import ru.m.control.DeviceType; +import ru.m.control.IControlDevice; +import ru.m.geom.Direction; import ru.m.geom.Point; import ru.m.geom.Rectangle; -enum GamepadAction { - UP; - LEFT; - DOWN; - RIGHT; - BUTTON_1; -} - typedef ActionArea = { - var action:GamepadAction; + var action:DeviceAction; var rect:Rectangle; } @@ -44,22 +41,47 @@ class GamepadSkin implements ISkin { } } -class GamepadView extends SpriteView { +class GamepadView extends SpriteView implements IControlDevice { + public static var ID:Int = -128; - public var actionSignal(default, null):Signal2; + public var type(default, null):DeviceType; + public var signal(default, null):Signal2; public var areas(default, null):Array; public var currentAreas(default, null):Map; + private static function touchSupport():Bool { + return false; + } + public function new() { super(); + type = GAMEPAD(ID); + signal = new Signal2(); areas = []; currentAreas = new Map(); - actionSignal = new Signal2(); skin = [new GamepadSkin(0x00ff00)]; + content.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); content.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin); } + private function onMouseDown(event:MouseEvent):Void { + onMouseMove(event); + content.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); + content.stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); + } + + private function onMouseMove(event:MouseEvent):Void { + var point = new Point(event.localX, event.localY); + updateTouch(-1, point); + } + + private function onMouseUp(event:MouseEvent):Void { + endTouch(-1); + content.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); + content.stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp); + } + private function onTouchBegin(event:TouchEvent):Void { onTouchMove(event); content.stage.addEventListener(TouchEvent.TOUCH_MOVE, onTouchMove); @@ -68,30 +90,38 @@ class GamepadView extends SpriteView { private function onTouchMove(event:TouchEvent):Void { var point = new Point(event.localX, event.localY); - if (currentAreas.exists(event.touchPointID)) { - var area = currentAreas[event.touchPointID]; + updateTouch(event.touchPointID, point); + } + + private function onTouchEnd(event:TouchEvent):Void { + endTouch(event.touchPointID); + if (Lambda.count(currentAreas) == 0) { + content.stage.removeEventListener(TouchEvent.TOUCH_MOVE, onTouchMove); + content.stage.removeEventListener(TouchEvent.TOUCH_END, onTouchEnd); + } + } + + private function updateTouch(pointID:Int, point:Point):Void { + if (currentAreas.exists(pointID)) { + var area = currentAreas[pointID]; if (!area.rect.contain(point)) { - currentAreas.remove(event.touchPointID); - actionSignal.emit(area.action, false); + currentAreas.remove(pointID); + signal.emit(area.action, false); } } for (area in areas) { if (area.rect.contain(point)) { - currentAreas[event.touchPointID] = area; - actionSignal.emit(area.action, true); + currentAreas[pointID] = area; + signal.emit(area.action, true); break; } } } - private function onTouchEnd(event:TouchEvent):Void { - if (currentAreas.exists(event.touchPointID)) { - actionSignal.emit(currentAreas[event.touchPointID].action, false); - currentAreas.remove(event.touchPointID); - } - if (Lambda.count(currentAreas) == 0) { - content.stage.removeEventListener(TouchEvent.TOUCH_MOVE, onTouchMove); - content.stage.removeEventListener(TouchEvent.TOUCH_END, onTouchEnd); + private function endTouch(pointID:Int):Void { + if (currentAreas.exists(pointID)) { + signal.emit(currentAreas[pointID].action, false); + currentAreas.remove(pointID); } } @@ -101,24 +131,26 @@ class GamepadView extends SpriteView { var size = Math.min(width, height) / 7; var padding = size / 2; areas.push({ - action: GamepadAction.UP, + action: DIRECTION(Direction.TOP), rect: new Rectangle(padding + size, height - size * 3 - padding, size, size) }); areas.push({ - action: GamepadAction.LEFT, + action: DIRECTION(Direction.LEFT), rect: new Rectangle(padding, height - size * 2 - padding, size, size) }); areas.push({ - action: GamepadAction.DOWN, + action: DIRECTION(Direction.BOTTOM), rect: new Rectangle(padding + size, height - size - padding, size, size) }); areas.push({ - action: GamepadAction.RIGHT, + action: DIRECTION(Direction.RIGHT), rect: new Rectangle(padding + size * 2, height - size * 2 - padding, size, size) }); areas.push({ - action: GamepadAction.BUTTON_1, + action: KEY(0), rect: new Rectangle(width - size * 1.5 - padding, height - size * 2 - padding, size, size) }); } + + public function dispose():Void {} } diff --git a/src/client/haxe/ru/m/tankz/view/SettingsFrame.hx b/src/client/haxe/ru/m/tankz/view/SettingsFrame.hx index 8e34627..f98c211 100644 --- a/src/client/haxe/ru/m/tankz/view/SettingsFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/SettingsFrame.hx @@ -17,5 +17,10 @@ import ru.m.tankz.storage.SettingsStorage; private function toggleGamepad():Void { gamepadButton.on = settings.screenGamepad = !settings.screenGamepad; + if (settings.screenGamepad) { + settings.setActionConffig(0, SettingsStorage.gamepadConfig(GamepadView.ID)); + } else { + settings.setActionConffig(0, SettingsStorage.getDefaultActionConfig(0)); + } } } diff --git a/src/client/haxe/ru/m/tankz/view/settings/ActionView.hx b/src/client/haxe/ru/m/tankz/view/settings/ActionView.hx index 660de00..c0c2aab 100755 --- a/src/client/haxe/ru/m/tankz/view/settings/ActionView.hx +++ b/src/client/haxe/ru/m/tankz/view/settings/ActionView.hx @@ -2,14 +2,19 @@ package ru.m.tankz.view.settings; import haxework.view.HGroupView; import haxework.view.LabelView; -import haxework.view.list.ListView.IListItemView; +import haxework.view.list.ListView; import openfl.Assets; import openfl.events.KeyboardEvent; import promhx.Deferred; import promhx.Promise; -import ru.m.tankz.control.ActionConfig; +import ru.m.control.DeviceAction; import ru.m.tankz.control.Control; +typedef ActionItem = { + var tankAction:TankAction; + var deviceAction:DeviceAction; +} + class KeyboardMap { private var data:Map; @@ -26,9 +31,9 @@ class KeyboardMap { } - private static var instance: KeyboardMap; + private static var instance:KeyboardMap; - public static function getName(key: Int): String { + public static function getName(key:Int):String { if (instance == null) instance = new KeyboardMap(); return key == -1 ? "(NONE)" : instance.data.exists(key) ? instance.data.get(key) : Std.string(key); } @@ -42,9 +47,9 @@ class KeyboardMap { @:view var action(default, null):LabelView; @:view var key(default, null):LabelView; - private var editDeferred: Deferred; + private var editDeferred:Deferred; - private static function actionLabel(action: TankAction): String { + private static function actionLabel(action:TankAction):String { return switch (action) { case TankAction.SHOT: "SHOT"; case TankAction.MOVE(d): 'MOVE_$d'; @@ -52,18 +57,21 @@ class KeyboardMap { } } - private static function keyLabel(key: Int): String { - return KeyboardMap.getName(key); + private static function keyLabel(action:DeviceAction):String { + return switch action { + case KEY(code): KeyboardMap.getName(code); + case DIRECTION(direction): Std.string(direction); + }; } private function set_data(value:ActionItem):ActionItem { data = value; - action.text = actionLabel(data.action); - key.text = keyLabel(data.key); + action.text = actionLabel(data.tankAction); + key.text = keyLabel(data.deviceAction); return data; } - public function edit():Promise { + public function edit():Promise { action.skinId = key.skinId = "text.box.active"; toRedraw(); editDeferred = new Deferred(); @@ -71,13 +79,13 @@ class KeyboardMap { return editDeferred.promise(); } - private function onKeyDown(event: KeyboardEvent):Void { + private function onKeyDown(event:KeyboardEvent):Void { content.stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); action.skinId = key.skinId = "text.box"; toRedraw(); - data.key = event.keyCode; - key.text = keyLabel(data.key); - editDeferred.resolve(data.key); + data.deviceAction = KEY(event.keyCode); + key.text = keyLabel(data.deviceAction); + editDeferred.resolve(data.deviceAction); editDeferred = null; } } diff --git a/src/client/haxe/ru/m/tankz/view/settings/SettingsEditor.hx b/src/client/haxe/ru/m/tankz/view/settings/SettingsEditor.hx index 4674379..f5f97e1 100644 --- a/src/client/haxe/ru/m/tankz/view/settings/SettingsEditor.hx +++ b/src/client/haxe/ru/m/tankz/view/settings/SettingsEditor.hx @@ -4,8 +4,11 @@ import haxework.view.DataView; import haxework.view.LabelView; import haxework.view.VGroupView; import promhx.Promise; +import ru.m.control.DeviceAction; +import ru.m.control.DeviceType; import ru.m.tankz.control.ActionConfig; import ru.m.tankz.storage.SettingsStorage; +import ru.m.tankz.view.settings.ActionView; @:template class SettingsEditor extends VGroupView { @@ -14,12 +17,12 @@ import ru.m.tankz.storage.SettingsStorage; @:view var label:LabelView; @:view var list:DataView; - @:provide var storage:SettingsStorage; + @:provide static var storage:SettingsStorage; private function set_controlIndex(value: Int): Int { this.controlIndex = value; label.text = 'Player ${controlIndex+1}'; - list.data = storage.getActionConfig(controlIndex).data; + list.data = bindingToArray(storage.getActionConfig(controlIndex).binding); return this.controlIndex; } @@ -31,21 +34,21 @@ import ru.m.tankz.storage.SettingsStorage; } private function onItemSelect(index:Int, value:ActionItem, view:ActionView):Void { - view.edit(); + view.edit().then(function(_) save()); } private function change():Void { - var p: Promise = Promise.promise(0); + var p:Promise = Promise.promise(null); for (view in list.views) { var v: ActionView = cast view; - p = p.pipe(function(_):Promise return v.edit()); + p = p.pipe(function(_) return v.edit()); } p.then(function(_) save()); } private function clear():Void { for (item in list.data) { - item.key = -1; + item.deviceAction = KEY(-1); } list.data = list.data; list.toUpdate(); @@ -53,12 +56,28 @@ import ru.m.tankz.storage.SettingsStorage; } private function reset():Void { - list.data = SettingsStorage.getDefaultActionConfig(controlIndex).data; + list.data = bindingToArray(SettingsStorage.getDefaultActionConfig(controlIndex).binding); list.toUpdate(); save(); } private function save():Void { - storage.setActionConffig(controlIndex, new ActionConfig(list.data)); + storage.setActionConffig(controlIndex, new ActionConfig(KEYBOARD, arrayToBinding(list.data))); + } + + private static function bindingToArray(binding:Binding):Array { + var result:Array = []; + for (deviceAction in binding.keys()) { + result.push({deviceAction: deviceAction, tankAction: binding.get(deviceAction)}); + } + return result; + } + + private static function arrayToBinding(array:Array):Binding { + var result = new Binding(); + for (item in array) { + result.set(item.deviceAction, item.tankAction); + } + return result; } }