From db0adbac30482c10f6d6647a5c7276ba8bfc2f34 Mon Sep 17 00:00:00 2001 From: shmyga Date: Wed, 19 Jun 2019 22:35:11 +0300 Subject: [PATCH] [client] control settings rework --- .../haxe/ru/m/tankz/control/ActionConfig.hx | 18 --- src/client/haxe/ru/m/tankz/control/Binding.hx | 12 ++ .../haxe/ru/m/tankz/control/HumanControl.hx | 24 ++-- .../ru/m/tankz/storage/SettingsStorage.hx | 82 ++++++------- src/client/haxe/ru/m/tankz/view/GameFrame.hx | 14 ++- .../haxe/ru/m/tankz/view/GamepadView.hx | 4 +- .../ru/m/tankz/view/settings/ActionView.hx | 42 +++---- .../ru/m/tankz/view/settings/ActionView.yaml | 4 +- .../m/tankz/view/settings/SettingsEditor.hx | 116 +++++++++++------- .../m/tankz/view/settings/SettingsEditor.yaml | 33 +++-- 10 files changed, 179 insertions(+), 170 deletions(-) delete mode 100644 src/client/haxe/ru/m/tankz/control/ActionConfig.hx create mode 100644 src/client/haxe/ru/m/tankz/control/Binding.hx diff --git a/src/client/haxe/ru/m/tankz/control/ActionConfig.hx b/src/client/haxe/ru/m/tankz/control/ActionConfig.hx deleted file mode 100644 index 0e683e5..0000000 --- a/src/client/haxe/ru/m/tankz/control/ActionConfig.hx +++ /dev/null @@ -1,18 +0,0 @@ -package ru.m.tankz.control; - -import ru.m.control.DeviceAction; -import ru.m.control.DeviceType; -import ru.m.tankz.control.Control; - -typedef Binding = Map; - -class ActionConfig { - - public var device(default, null):DeviceType; - public var binding(default, null):Binding; - - 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/Binding.hx b/src/client/haxe/ru/m/tankz/control/Binding.hx new file mode 100644 index 0000000..ba210a8 --- /dev/null +++ b/src/client/haxe/ru/m/tankz/control/Binding.hx @@ -0,0 +1,12 @@ +package ru.m.tankz.control; + +import ru.m.control.DeviceAction; +import ru.m.control.DeviceType; +import ru.m.tankz.control.Control; + +typedef BindAction = { + var device:DeviceType; + var action:DeviceAction; +} + +typedef Binding = Map; diff --git a/src/client/haxe/ru/m/tankz/control/HumanControl.hx b/src/client/haxe/ru/m/tankz/control/HumanControl.hx index 2690d7d..57a19c0 100644 --- a/src/client/haxe/ru/m/tankz/control/HumanControl.hx +++ b/src/client/haxe/ru/m/tankz/control/HumanControl.hx @@ -1,6 +1,5 @@ package ru.m.tankz.control; -import haxe.EnumTools.EnumValueTools; import flash.events.FocusEvent; import haxe.Timer; import ru.m.control.DeviceAction; @@ -16,27 +15,28 @@ class HumanControl extends Control { @:provide static var storage:SettingsStorage; @:provide static var bus:IControlBus; - private var config:ActionConfig; + private var binding:Map>; private var moveQueue:Array; private var shotTimer:Timer; public function new(playerId:PlayerId, controlIndex:Int) { super(playerId); - config = storage.getActionConfig(controlIndex); + var config = storage.getBinding(controlIndex); + binding = new Map(); + for (action in config.keys()) { + var bind = config.get(action); + if (!binding.exists(bind.device)) { + binding.set(bind.device, new Map()); + } + binding.get(bind.device).set(bind.action, action); + } 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); - } - } + if (binding.exists(device) && binding[device].exists(action)) { + toggleAction(binding[device][action], on); } } diff --git a/src/client/haxe/ru/m/tankz/storage/SettingsStorage.hx b/src/client/haxe/ru/m/tankz/storage/SettingsStorage.hx index 3161ad5..a22ba3d 100644 --- a/src/client/haxe/ru/m/tankz/storage/SettingsStorage.hx +++ b/src/client/haxe/ru/m/tankz/storage/SettingsStorage.hx @@ -6,59 +6,59 @@ 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; +import ru.m.tankz.control.Binding; +import ru.m.tankz.control.Control; class SettingsStorage extends SharedObjectStorage { public function new() { - super("settings-2"); + super("settings-3"); } - public function getActionConfig(index:Int):ActionConfig { - return exists('action:$index') ? read('action:$index') : getDefaultActionConfig(index); + public function getBinding(index:Int):Binding { + return exists('action:$index') ? read('action:$index') : getDefaultBinding(index); } - public function setActionConffig(index:Int, value:ActionConfig) { + public function saveBinding(index:Int, value:Binding) { write('action:$index', value); } - public static function getDefaultActionConfig(index:Int):ActionConfig { - return ObjectUtil.clone(defaults.exists(index) ? defaults.get(index) : empty); + public static function getDefaultBinding(index:Int):Binding { + return ObjectUtil.clone(defaults.exists(index) ? defaults.get(index) : defaults.get(-1)); } - private static var defaults:Map = [ - 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(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, - ]), + public static function buildGamepadBinding(id:Int):Binding { + var device = GAMEPAD(id); + return [ + MOVE(Direction.TOP) => {device: device, action: DIRECTION(Direction.TOP)}, + MOVE(Direction.LEFT) => {device: device, action: DIRECTION(Direction.LEFT)}, + MOVE(Direction.BOTTOM) => {device: device, action: DIRECTION(Direction.BOTTOM)}, + MOVE(Direction.RIGHT) => {device: device, action: DIRECTION(Direction.RIGHT)}, + SHOT => {device: device, action: KEY(0)}, + ]; + } + + private static var defaults:Map = [ + -1 => [ + MOVE(Direction.TOP) => null, + MOVE(Direction.LEFT) => null, + MOVE(Direction.BOTTOM) => null, + MOVE(Direction.RIGHT) => null, + SHOT => null, + ], + 0 => [ + MOVE(Direction.TOP) => {device: KEYBOARD, action: KEY(Keyboard.W)}, + MOVE(Direction.LEFT) => {device: KEYBOARD, action: KEY(Keyboard.A)}, + MOVE(Direction.BOTTOM) => {device: KEYBOARD, action: KEY(Keyboard.S)}, + MOVE(Direction.RIGHT) => {device: KEYBOARD, action: KEY(Keyboard.D)}, + SHOT => {device: KEYBOARD, action: KEY(Keyboard.SPACE)}, + ], + 1 => [ + MOVE(Direction.TOP) => {device: KEYBOARD, action: KEY(Keyboard.UP)}, + MOVE(Direction.LEFT) => {device: KEYBOARD, action: KEY(Keyboard.LEFT)}, + MOVE(Direction.BOTTOM) => {device: KEYBOARD, action: KEY(Keyboard.DOWN)}, + MOVE(Direction.RIGHT) => {device: KEYBOARD, action: KEY(Keyboard.RIGHT)}, + SHOT => {device: KEYBOARD, action: KEY(Keyboard.NUMPAD_0)}, + ], ]; - - 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 995cf24..97d00df 100644 --- a/src/client/haxe/ru/m/tankz/view/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/GameFrame.hx @@ -1,8 +1,8 @@ package ru.m.tankz.view; -import ru.m.control.DeviceType; import haxework.view.frame.FrameSwitcher; import haxework.view.VGroupView; +import ru.m.control.DeviceType; import ru.m.control.IControlBus; import ru.m.tankz.game.GameEvent; import ru.m.tankz.game.GameState; @@ -42,11 +42,13 @@ import ru.m.tankz.view.GamepadView; gamepad.visible = false; // ToDo: for (i in 0...1) { - switch settings.getActionConfig(i).device { - case GAMEPAD(GamepadView.ID): - gamepad.visible = true; - break; - case _: + for (bind in settings.getBinding(i)) { + switch bind.device { + case GAMEPAD(GamepadView.ID): + gamepad.visible = true; + break; + case _: + } } } gameView.type = game.type; diff --git a/src/client/haxe/ru/m/tankz/view/GamepadView.hx b/src/client/haxe/ru/m/tankz/view/GamepadView.hx index 5f97d7e..43dc3c2 100644 --- a/src/client/haxe/ru/m/tankz/view/GamepadView.hx +++ b/src/client/haxe/ru/m/tankz/view/GamepadView.hx @@ -66,7 +66,7 @@ class GamepadView extends SpriteView implements IControlDevice { private function onMouseDown(event:MouseEvent):Void { onMouseMove(event); - stage = event.relatedObject.stage; + stage = content.stage; stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); } @@ -84,7 +84,7 @@ class GamepadView extends SpriteView implements IControlDevice { private function onTouchBegin(event:TouchEvent):Void { onTouchMove(event); - stage = event.relatedObject.stage; + stage = content.stage; stage.addEventListener(TouchEvent.TOUCH_MOVE, onTouchMove); stage.addEventListener(TouchEvent.TOUCH_END, onTouchEnd); } 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 c0c2aab..31fd6e6 100755 --- a/src/client/haxe/ru/m/tankz/view/settings/ActionView.hx +++ b/src/client/haxe/ru/m/tankz/view/settings/ActionView.hx @@ -4,15 +4,13 @@ import haxework.view.HGroupView; import haxework.view.LabelView; import haxework.view.list.ListView; import openfl.Assets; -import openfl.events.KeyboardEvent; -import promhx.Deferred; -import promhx.Promise; import ru.m.control.DeviceAction; +import ru.m.tankz.control.Binding; import ru.m.tankz.control.Control; typedef ActionItem = { - var tankAction:TankAction; - var deviceAction:DeviceAction; + var action:TankAction; + var bind:BindAction; } class KeyboardMap { @@ -44,11 +42,11 @@ class KeyboardMap { public var item_index(default, default):Int; public var data(default, set):ActionItem; + public var edit(default, set):Bool; + @:view var action(default, null):LabelView; @:view var key(default, null):LabelView; - private var editDeferred:Deferred; - private static function actionLabel(action:TankAction):String { return switch (action) { case TankAction.SHOT: "SHOT"; @@ -57,8 +55,8 @@ class KeyboardMap { } } - private static function keyLabel(action:DeviceAction):String { - return switch action { + private static function bindLabel(bind:BindAction):String { + return bind == null ? "(NONE)" : Std.string(bind.device) + " " + switch bind.action { case KEY(code): KeyboardMap.getName(code); case DIRECTION(direction): Std.string(direction); }; @@ -66,26 +64,16 @@ class KeyboardMap { private function set_data(value:ActionItem):ActionItem { data = value; - action.text = actionLabel(data.tankAction); - key.text = keyLabel(data.deviceAction); + action.text = actionLabel(data.action); + key.text = bindLabel(data.bind); return data; } - public function edit():Promise { - action.skinId = key.skinId = "text.box.active"; - toRedraw(); - editDeferred = new Deferred(); - content.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); - return editDeferred.promise(); - } - - private function onKeyDown(event:KeyboardEvent):Void { - content.stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); - action.skinId = key.skinId = "text.box"; - toRedraw(); - data.deviceAction = KEY(event.keyCode); - key.text = keyLabel(data.deviceAction); - editDeferred.resolve(data.deviceAction); - editDeferred = null; + private function set_edit(value:Bool):Bool { + if (edit != value) { + edit = value; + action.skinId = key.skinId = edit ? "text.box.active" : "text.box"; + } + return edit; } } diff --git a/src/client/haxe/ru/m/tankz/view/settings/ActionView.yaml b/src/client/haxe/ru/m/tankz/view/settings/ActionView.yaml index e388c50..a7bf998 100644 --- a/src/client/haxe/ru/m/tankz/view/settings/ActionView.yaml +++ b/src/client/haxe/ru/m/tankz/view/settings/ActionView.yaml @@ -4,9 +4,9 @@ layout.margin: 5 views: - id: action $type: haxework.view.LabelView - geometry.size.fixed: [200, 38] + geometry.size.fixed: [180, 38] skinId: text.box - id: key $type: haxework.view.LabelView - geometry.size.fixed: [200, 38] + geometry.size.fixed: [250, 38] skinId: text.box 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 2d214db..e1ea3a6 100644 --- a/src/client/haxe/ru/m/tankz/view/settings/SettingsEditor.hx +++ b/src/client/haxe/ru/m/tankz/view/settings/SettingsEditor.hx @@ -1,19 +1,67 @@ package ru.m.tankz.view.settings; -import haxe.EnumTools.EnumValueTools; -import haxework.view.ButtonGroup; import haxework.view.DataView; import haxework.view.GroupView; import haxework.view.LabelView; import haxework.view.VGroupView; +import promhx.Deferred; import promhx.Promise; import ru.m.control.DeviceAction; import ru.m.control.DeviceType; import ru.m.control.IControlBus; -import ru.m.tankz.control.ActionConfig; +import ru.m.tankz.control.Binding; import ru.m.tankz.storage.SettingsStorage; import ru.m.tankz.view.settings.ActionView; +class BindEditor { + + private var editViews:Array; + + @:provide static var bus:IControlBus; + + private var def:Deferred; + + public function new() { + editViews = []; + bus.signal.connect(onBusAction); + } + + private function onBusAction(device:DeviceType, action:DeviceAction, on:Bool):Void { + if (on && editViews.length > 0) { + var view = editViews.shift(); + view.edit = false; + view.data.bind = {device: device, action: action}; + view.data = view.data; + if (editViews.length > 0) { + editViews[0].edit = true; + } else { + def.resolve(true); + } + } + } + + public function push(views:Array):Promise { + for (view in editViews) { + view.edit = false; + } + editViews = views.slice(0); + if (editViews.length > 0) { + editViews[0].edit = true; + } + def = new Deferred(); + return def.promise(); + } + + public static var i(get, null):BindEditor; + + private static function get_i():BindEditor { + if (i == null) { + i = new BindEditor(); + } + return i; + } +} + @:template class SettingsEditor extends VGroupView { public var controlIndex(default, set): Int; @@ -21,22 +69,14 @@ import ru.m.tankz.view.settings.ActionView; @:view var label:LabelView; @:view var list:DataView; @:view var panel:GroupView; - @:view var device:ButtonGroup; @:provide static var storage:SettingsStorage; @:provide static var bus:IControlBus; - public function init() { - bus.devicesSignal.connect(function(devices) refresh()); - } - private function refresh():Void { label.text = 'Player ${controlIndex+1}'; - var config = storage.getActionConfig(controlIndex); - list.data = bindingToArray(config.binding); - device.data = bus.devices.map(function(device) return device.type); - device.selected = config.device; - panel.visible = list.visible = EnumValueTools.equals(config.device, KEYBOARD); + var binding = storage.getBinding(controlIndex); + list.data = bindingToArray(binding); } private function set_controlIndex(value: Int): Int { @@ -45,16 +85,6 @@ import ru.m.tankz.view.settings.ActionView; return this.controlIndex; } - private function onDeviceSelect(value:DeviceType):Void { - var config = switch value { - case GAMEPAD(id): SettingsStorage.gamepadConfig(id); - case KEYBOARD | NONE: SettingsStorage.getDefaultActionConfig(controlIndex); - } - panel.visible = list.visible = EnumValueTools.equals(config.device, KEYBOARD); - storage.setActionConffig(controlIndex, config); - refresh(); - } - private function viewFactory(index:Int, value:ActionItem) { var view = new ActionView(); view.item_index = index; @@ -63,41 +93,39 @@ import ru.m.tankz.view.settings.ActionView; } private function onItemSelect(index:Int, value:ActionItem, view:ActionView):Void { - view.edit().then(function(_) save()); + BindEditor.i.push([view]).then(function(_) save()); } - private function change():Void { - var p:Promise = Promise.promise(null); - for (view in list.views) { - var v: ActionView = cast view; - p = p.pipe(function(_) return v.edit()); - } - p.then(function(_) save()); - } - - private function clear():Void { - for (item in list.data) { - item.deviceAction = KEY(-1); - } - list.data = list.data; + private function screen():Void { + list.data = bindingToArray(SettingsStorage.buildGamepadBinding(GamepadView.ID)); list.toUpdate(); save(); } - private function reset():Void { - list.data = bindingToArray(SettingsStorage.getDefaultActionConfig(controlIndex).binding); + private function change():Void { + BindEditor.i.push(list.dataViews).then(function(_) save()); + } + + private function clear():Void { + list.data = bindingToArray(SettingsStorage.getDefaultBinding(-1)); + list.toUpdate(); + save(); + } + + private function default_():Void { + list.data = bindingToArray(SettingsStorage.getDefaultBinding(controlIndex)); list.toUpdate(); save(); } private function save():Void { - storage.setActionConffig(controlIndex, new ActionConfig(KEYBOARD, arrayToBinding(list.data))); + storage.saveBinding(controlIndex, 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)}); + for (action in binding.keys()) { + result.push({action: action, bind: binding.get(action)}); } return result; } @@ -105,7 +133,7 @@ import ru.m.tankz.view.settings.ActionView; private static function arrayToBinding(array:Array):Binding { var result = new Binding(); for (item in array) { - result.set(item.deviceAction, item.tankAction); + result.set(item.action, item.bind); } return result; } diff --git a/src/client/haxe/ru/m/tankz/view/settings/SettingsEditor.yaml b/src/client/haxe/ru/m/tankz/view/settings/SettingsEditor.yaml index 921b266..49e03bc 100644 --- a/src/client/haxe/ru/m/tankz/view/settings/SettingsEditor.yaml +++ b/src/client/haxe/ru/m/tankz/view/settings/SettingsEditor.yaml @@ -5,33 +5,30 @@ views: - id: label $type: haxework.view.LabelView skinId: text - - id: device - $type: haxework.view.ButtonGroup - geometry.size.width: 100% - layout: - $type: haxework.view.layout.TailLayout - margin: 3 - buttonSkinId: button.simple - +onDataSelect: $this:onDeviceSelect - id: panel - $type: haxework.view.HGroupView - layout.margin: 10 + $type: haxework.view.GroupView + layout: + $type: haxework.view.layout.TailLayout + rowSize: 2 + margin: 10 + geometry.size.width: 100% views: - - id: change - $type: haxework.view.ButtonView + - $type: haxework.view.ButtonView + +onPress: $code:screen() + skinId: button.simple + text: Screen + - $type: haxework.view.ButtonView +onPress: $code:change() skinId: button.simple text: Change - - id: clear - $type: haxework.view.ButtonView + - $type: haxework.view.ButtonView +onPress: $code:clear() skinId: button.simple text: Clear - - id: reset - $type: haxework.view.ButtonView - +onPress: $code:reset() + - $type: haxework.view.ButtonView + +onPress: $code:default_() skinId: button.simple - text: Reset + text: Default - id: list $type: haxework.view.DataView layout: