[client] add ControlBus

This commit is contained in:
2019-06-18 12:14:04 +03:00
parent f999c66fea
commit 2ff374abb6
16 changed files with 303 additions and 139 deletions

View File

@@ -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<DeviceType, DeviceAction, Bool>;
private var connections:Map<DeviceType, DeviceAction->Bool->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);
}
}
}

View File

@@ -0,0 +1,8 @@
package ru.m.control;
import ru.m.geom.Direction;
enum DeviceAction {
DIRECTION(direction:Direction);
KEY(code:Int);
}

View File

@@ -0,0 +1,7 @@
package ru.m.control;
enum DeviceType {
NONE;
KEYBOARD;
GAMEPAD(id:Int);
}

View File

@@ -0,0 +1,10 @@
package ru.m.control;
import haxework.signal.Signal;
interface IControlBus {
public var signal(default, null):Signal3<DeviceType, DeviceAction, Bool>;
public function connect(device:IControlDevice):Void;
public function disconnect(device:IControlDevice):Void;
}

View File

@@ -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<DeviceAction, Bool>;
public function dispose():Void;
}

View File

@@ -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<DeviceAction, Bool>;
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;
}
}
}

View File

@@ -1,5 +1,9 @@
package ru.m.tankz; 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.Joystick;
import lime.ui.Gamepad; import lime.ui.Gamepad;
import haxework.animate.FadeAnimate; import haxework.animate.FadeAnimate;
@@ -34,6 +38,7 @@ class Init {
@:provide static var networkManager:NetworkManager; @:provide static var networkManager:NetworkManager;
@:provide static var popupManager:PopupManager; @:provide static var popupManager:PopupManager;
@:provide static var connection:IConnection<Request, Response>; @:provide static var connection:IConnection<Request, Response>;
@:provide static var bus:IControlBus;
private static function buildConnection():IConnection<Request, Response> { private static function buildConnection():IConnection<Request, Response> {
var host:String = CompilationOption.get("host"); var host:String = CompilationOption.get("host");
@@ -65,6 +70,9 @@ class Init {
connection = buildConnection(); connection = buildConnection();
networkManager = new NetworkManager(); networkManager = new NetworkManager();
bus = new ControlBus();
bus.connect(new KeyboardDevice(Lib.current.stage));
for (device in Gamepad.devices) { for (device in Gamepad.devices) {
trace('gamepad', device); trace('gamepad', device);
} }

View File

@@ -1,27 +1,18 @@
package ru.m.tankz.control; 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 = { typedef Binding = Map<DeviceAction, TankAction>;
public var action:TankAction;
public var key:Int;
}
typedef KeyBinding = Map<Int, TankAction>;
class ActionConfig { class ActionConfig {
public var data(default, null):Array<ActionItem>; public var device(default, null):DeviceType;
public var binding(default, null):Binding;
public function new(data:Array<ActionItem>) { public function new(device:DeviceType = null, binding:Binding = null) {
this.data = data; this.device = device != null ? device : NONE;
} this.binding = binding != null ? binding : new Map();
public function asKeyBinding():KeyBinding {
var result = new KeyBinding();
for (item in data) {
result[item.key] = item.action;
}
return result;
} }
} }

View File

@@ -1,39 +1,54 @@
package ru.m.tankz.control; package ru.m.tankz.control;
import haxe.EnumTools.EnumValueTools;
import flash.events.FocusEvent; import flash.events.FocusEvent;
import flash.events.KeyboardEvent;
import flash.Lib;
import haxe.Timer; 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.geom.Direction;
import ru.m.tankz.control.ActionConfig;
import ru.m.tankz.control.Control; import ru.m.tankz.control.Control;
import ru.m.tankz.storage.SettingsStorage; import ru.m.tankz.storage.SettingsStorage;
import ru.m.tankz.Type; import ru.m.tankz.Type;
class HumanControl extends Control { 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<Direction>; private var moveQueue:Array<Direction>;
private var shotTimer:Timer; private var shotTimer:Timer;
public function new(playerId:PlayerId, controlIndex:Int) { public function new(playerId:PlayerId, controlIndex:Int) {
super(playerId); super(playerId);
this.keyBinding = storage.getActionConfig(controlIndex).asKeyBinding(); config = storage.getActionConfig(controlIndex);
trace(controlIndex, config.device, config.binding);
moveQueue = []; 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 { override public function start():Void {
super.start(); super.start();
Lib.current.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); bus.signal.connect(onDeviceAction);
Lib.current.stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
} }
override public function stop():Void { override public function stop():Void {
super.stop(); super.stop();
Lib.current.stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); bus.signal.disconnect(onDeviceAction);
Lib.current.stage.removeEventListener(KeyboardEvent.KEY_UP, onKeyUp);
moveQueue = []; moveQueue = [];
if (shotTimer != null) { if (shotTimer != null) {
shotTimer.stop(); 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 { private function onFocusOut(event:FocusEvent):Void {
moveQueue = []; moveQueue = [];
updateMove(); updateMove();
@@ -88,13 +91,13 @@ class HumanControl extends Control {
private function updateMove():Void { private function updateMove():Void {
if (moveQueue.length == 0) { if (moveQueue.length == 0) {
action(TankAction.STOP); action(STOP);
} else { } else {
action(TankAction.MOVE(moveQueue[0])); action(MOVE(moveQueue[0]));
} }
} }
private function shot():Void { private function shot():Void {
action(TankAction.SHOT); action(SHOT);
} }
} }

View File

@@ -3,6 +3,8 @@ package ru.m.tankz.storage;
import flash.ui.Keyboard; import flash.ui.Keyboard;
import haxework.storage.SharedObjectStorage; import haxework.storage.SharedObjectStorage;
import haxework.utils.ObjectUtil; import haxework.utils.ObjectUtil;
import ru.m.control.DeviceAction;
import ru.m.control.DeviceType;
import ru.m.geom.Direction; import ru.m.geom.Direction;
import ru.m.tankz.control.ActionConfig; import ru.m.tankz.control.ActionConfig;
import ru.m.tankz.control.Control.TankAction; import ru.m.tankz.control.Control.TankAction;
@@ -12,7 +14,7 @@ class SettingsStorage extends SharedObjectStorage {
public var screenGamepad(get, set):Bool; public var screenGamepad(get, set):Bool;
public function new() { public function new() {
super("settings"); super("settings-2");
} }
private function get_screenGamepad():Bool { private function get_screenGamepad():Bool {
@@ -37,27 +39,37 @@ class SettingsStorage extends SharedObjectStorage {
} }
private static var defaults:Map<Int, ActionConfig> = [ private static var defaults:Map<Int, ActionConfig> = [
0 => new ActionConfig([ 0 => new ActionConfig(KEYBOARD, [
{action:TankAction.MOVE(Direction.TOP), key:Keyboard.W}, KEY(Keyboard.W) => MOVE(Direction.TOP),
{action:TankAction.MOVE(Direction.LEFT), key:Keyboard.A}, KEY(Keyboard.A) => MOVE(Direction.LEFT),
{action:TankAction.MOVE(Direction.BOTTOM), key:Keyboard.S}, KEY(Keyboard.S) => MOVE(Direction.BOTTOM),
{action:TankAction.MOVE(Direction.RIGHT), key:Keyboard.D}, KEY(Keyboard.D) => MOVE(Direction.RIGHT),
{action:TankAction.SHOT, key:Keyboard.SPACE}, KEY(Keyboard.SPACE) => SHOT,
]), ]),
1 => new ActionConfig([ 1 => new ActionConfig(KEYBOARD, [
{action:TankAction.MOVE(Direction.TOP), key:Keyboard.UP}, KEY(Keyboard.UP) => MOVE(Direction.TOP),
{action:TankAction.MOVE(Direction.LEFT), key:Keyboard.LEFT}, KEY(Keyboard.LEFT) => MOVE(Direction.LEFT),
{action:TankAction.MOVE(Direction.BOTTOM), key:Keyboard.DOWN}, KEY(Keyboard.DOWN) => MOVE(Direction.BOTTOM),
{action:TankAction.MOVE(Direction.RIGHT), key:Keyboard.RIGHT}, KEY(Keyboard.RIGHT) => MOVE(Direction.RIGHT),
{action:TankAction.SHOT, key:Keyboard.NUMPAD_0}, KEY(Keyboard.NUMPAD_0) => SHOT,
]), ]),
]; ];
private static var empty:ActionConfig = new ActionConfig([ private static var empty:ActionConfig = new ActionConfig(NONE, [
{action:TankAction.MOVE(Direction.TOP), key:-1}, KEY(-1) => MOVE(Direction.TOP),
{action:TankAction.MOVE(Direction.LEFT), key:-1}, KEY(-1) => MOVE(Direction.LEFT),
{action:TankAction.MOVE(Direction.BOTTOM), key:-1}, KEY(-1) => MOVE(Direction.BOTTOM),
{action:TankAction.MOVE(Direction.RIGHT), key:-1}, KEY(-1) => MOVE(Direction.RIGHT),
{action:TankAction.SHOT, key:-1}, 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,
]); ]);
} }
}

View File

@@ -1,11 +1,8 @@
package ru.m.tankz.view; 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.frame.FrameSwitcher;
import haxework.view.VGroupView; import haxework.view.VGroupView;
import ru.m.control.IControlBus;
import ru.m.tankz.game.GameEvent; import ru.m.tankz.game.GameEvent;
import ru.m.tankz.game.GameState; import ru.m.tankz.game.GameState;
import ru.m.tankz.game.IGame; 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.network.NetworkManager;
import ru.m.tankz.sound.SoundManager; import ru.m.tankz.sound.SoundManager;
import ru.m.tankz.storage.GameStorage; import ru.m.tankz.storage.GameStorage;
import ru.m.tankz.storage.SettingsStorage;
import ru.m.tankz.view.game.GameView; import ru.m.tankz.view.game.GameView;
import ru.m.tankz.view.GamepadView; import ru.m.tankz.view.GamepadView;
@@ -33,9 +31,11 @@ import ru.m.tankz.view.GamepadView;
@:provide var settings:SettingsStorage; @:provide var settings:SettingsStorage;
@:provide var game:IGame; @:provide var game:IGame;
@:provide static var bus:IControlBus;
public function onShow():Void { public function onShow():Void {
gamepad.visible = settings.screenGamepad; gamepad.visible = settings.screenGamepad;
bus.connect(gamepad);
gameView.type = game.type; gameView.type = game.type;
soundManager.config = game.config; soundManager.config = game.config;
gameView.render.config = game.config; gameView.render.config = game.config;
@@ -58,7 +58,7 @@ import ru.m.tankz.view.GamepadView;
public function onGameEvent(event:GameEvent):Void { public function onGameEvent(event:GameEvent):Void {
switch event { switch event {
case GameEvent.COMPLETE(state, winner): case COMPLETE(state, winner):
this.state = state; this.state = state;
stop(); stop();
switcher.change(ResultFrame.ID); switcher.change(ResultFrame.ID);
@@ -67,6 +67,7 @@ import ru.m.tankz.view.GamepadView;
} }
public function onHide():Void { public function onHide():Void {
bus.disconnect(gamepad);
stop(); stop();
soundManager.stopAll(); soundManager.stopAll();
} }
@@ -74,21 +75,4 @@ import ru.m.tankz.view.GamepadView;
public function close():Void { public function close():Void {
switcher.change(LevelFrame.ID); 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;
}
}
}
} }

View File

@@ -10,5 +10,4 @@ views:
$type: ru.m.tankz.view.GamepadView $type: ru.m.tankz.view.GamepadView
geometry.position: absolute geometry.position: absolute
geometry.size.stretch: true geometry.size.stretch: true
+actionSignal: $this:onGamepadAction
visible: false visible: false

View File

@@ -1,23 +1,20 @@
package ru.m.tankz.view; package ru.m.tankz.view;
import flash.events.MouseEvent;
import flash.display.Graphics; import flash.display.Graphics;
import flash.events.TouchEvent; import flash.events.TouchEvent;
import haxework.signal.Signal; import haxework.signal.Signal;
import haxework.view.skin.ISkin; import haxework.view.skin.ISkin;
import haxework.view.SpriteView; 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.Point;
import ru.m.geom.Rectangle; import ru.m.geom.Rectangle;
enum GamepadAction {
UP;
LEFT;
DOWN;
RIGHT;
BUTTON_1;
}
typedef ActionArea = { typedef ActionArea = {
var action:GamepadAction; var action:DeviceAction;
var rect:Rectangle; var rect:Rectangle;
} }
@@ -44,22 +41,47 @@ class GamepadSkin implements ISkin<GamepadView> {
} }
} }
class GamepadView extends SpriteView { class GamepadView extends SpriteView implements IControlDevice {
public static var ID:Int = -128;
public var actionSignal(default, null):Signal2<GamepadAction, Bool>; public var type(default, null):DeviceType;
public var signal(default, null):Signal2<DeviceAction, Bool>;
public var areas(default, null):Array<ActionArea>; public var areas(default, null):Array<ActionArea>;
public var currentAreas(default, null):Map<Int, ActionArea>; public var currentAreas(default, null):Map<Int, ActionArea>;
private static function touchSupport():Bool {
return false;
}
public function new() { public function new() {
super(); super();
type = GAMEPAD(ID);
signal = new Signal2();
areas = []; areas = [];
currentAreas = new Map(); currentAreas = new Map();
actionSignal = new Signal2();
skin = [new GamepadSkin(0x00ff00)]; skin = [new GamepadSkin(0x00ff00)];
content.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
content.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin); 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 { private function onTouchBegin(event:TouchEvent):Void {
onTouchMove(event); onTouchMove(event);
content.stage.addEventListener(TouchEvent.TOUCH_MOVE, onTouchMove); content.stage.addEventListener(TouchEvent.TOUCH_MOVE, onTouchMove);
@@ -68,30 +90,38 @@ class GamepadView extends SpriteView {
private function onTouchMove(event:TouchEvent):Void { private function onTouchMove(event:TouchEvent):Void {
var point = new Point(event.localX, event.localY); var point = new Point(event.localX, event.localY);
if (currentAreas.exists(event.touchPointID)) { updateTouch(event.touchPointID, point);
var area = currentAreas[event.touchPointID]; }
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)) { if (!area.rect.contain(point)) {
currentAreas.remove(event.touchPointID); currentAreas.remove(pointID);
actionSignal.emit(area.action, false); signal.emit(area.action, false);
} }
} }
for (area in areas) { for (area in areas) {
if (area.rect.contain(point)) { if (area.rect.contain(point)) {
currentAreas[event.touchPointID] = area; currentAreas[pointID] = area;
actionSignal.emit(area.action, true); signal.emit(area.action, true);
break; break;
} }
} }
} }
private function onTouchEnd(event:TouchEvent):Void { private function endTouch(pointID:Int):Void {
if (currentAreas.exists(event.touchPointID)) { if (currentAreas.exists(pointID)) {
actionSignal.emit(currentAreas[event.touchPointID].action, false); signal.emit(currentAreas[pointID].action, false);
currentAreas.remove(event.touchPointID); currentAreas.remove(pointID);
}
if (Lambda.count(currentAreas) == 0) {
content.stage.removeEventListener(TouchEvent.TOUCH_MOVE, onTouchMove);
content.stage.removeEventListener(TouchEvent.TOUCH_END, onTouchEnd);
} }
} }
@@ -101,24 +131,26 @@ class GamepadView extends SpriteView {
var size = Math.min(width, height) / 7; var size = Math.min(width, height) / 7;
var padding = size / 2; var padding = size / 2;
areas.push({ areas.push({
action: GamepadAction.UP, action: DIRECTION(Direction.TOP),
rect: new Rectangle(padding + size, height - size * 3 - padding, size, size) rect: new Rectangle(padding + size, height - size * 3 - padding, size, size)
}); });
areas.push({ areas.push({
action: GamepadAction.LEFT, action: DIRECTION(Direction.LEFT),
rect: new Rectangle(padding, height - size * 2 - padding, size, size) rect: new Rectangle(padding, height - size * 2 - padding, size, size)
}); });
areas.push({ areas.push({
action: GamepadAction.DOWN, action: DIRECTION(Direction.BOTTOM),
rect: new Rectangle(padding + size, height - size - padding, size, size) rect: new Rectangle(padding + size, height - size - padding, size, size)
}); });
areas.push({ areas.push({
action: GamepadAction.RIGHT, action: DIRECTION(Direction.RIGHT),
rect: new Rectangle(padding + size * 2, height - size * 2 - padding, size, size) rect: new Rectangle(padding + size * 2, height - size * 2 - padding, size, size)
}); });
areas.push({ areas.push({
action: GamepadAction.BUTTON_1, action: KEY(0),
rect: new Rectangle(width - size * 1.5 - padding, height - size * 2 - padding, size, size) rect: new Rectangle(width - size * 1.5 - padding, height - size * 2 - padding, size, size)
}); });
} }
public function dispose():Void {}
} }

View File

@@ -17,5 +17,10 @@ import ru.m.tankz.storage.SettingsStorage;
private function toggleGamepad():Void { private function toggleGamepad():Void {
gamepadButton.on = settings.screenGamepad = !settings.screenGamepad; gamepadButton.on = settings.screenGamepad = !settings.screenGamepad;
if (settings.screenGamepad) {
settings.setActionConffig(0, SettingsStorage.gamepadConfig(GamepadView.ID));
} else {
settings.setActionConffig(0, SettingsStorage.getDefaultActionConfig(0));
}
} }
} }

View File

@@ -2,14 +2,19 @@ package ru.m.tankz.view.settings;
import haxework.view.HGroupView; import haxework.view.HGroupView;
import haxework.view.LabelView; import haxework.view.LabelView;
import haxework.view.list.ListView.IListItemView; import haxework.view.list.ListView;
import openfl.Assets; import openfl.Assets;
import openfl.events.KeyboardEvent; import openfl.events.KeyboardEvent;
import promhx.Deferred; import promhx.Deferred;
import promhx.Promise; import promhx.Promise;
import ru.m.tankz.control.ActionConfig; import ru.m.control.DeviceAction;
import ru.m.tankz.control.Control; import ru.m.tankz.control.Control;
typedef ActionItem = {
var tankAction:TankAction;
var deviceAction:DeviceAction;
}
class KeyboardMap { class KeyboardMap {
private var data:Map<Int, String>; private var data:Map<Int, String>;
@@ -42,7 +47,7 @@ class KeyboardMap {
@:view var action(default, null):LabelView; @:view var action(default, null):LabelView;
@:view var key(default, null):LabelView; @:view var key(default, null):LabelView;
private var editDeferred: Deferred<Int>; private var editDeferred:Deferred<DeviceAction>;
private static function actionLabel(action:TankAction):String { private static function actionLabel(action:TankAction):String {
return switch (action) { return switch (action) {
@@ -52,18 +57,21 @@ class KeyboardMap {
} }
} }
private static function keyLabel(key: Int): String { private static function keyLabel(action:DeviceAction):String {
return KeyboardMap.getName(key); return switch action {
case KEY(code): KeyboardMap.getName(code);
case DIRECTION(direction): Std.string(direction);
};
} }
private function set_data(value:ActionItem):ActionItem { private function set_data(value:ActionItem):ActionItem {
data = value; data = value;
action.text = actionLabel(data.action); action.text = actionLabel(data.tankAction);
key.text = keyLabel(data.key); key.text = keyLabel(data.deviceAction);
return data; return data;
} }
public function edit():Promise<Int> { public function edit():Promise<DeviceAction> {
action.skinId = key.skinId = "text.box.active"; action.skinId = key.skinId = "text.box.active";
toRedraw(); toRedraw();
editDeferred = new Deferred(); editDeferred = new Deferred();
@@ -75,9 +83,9 @@ class KeyboardMap {
content.stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); content.stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
action.skinId = key.skinId = "text.box"; action.skinId = key.skinId = "text.box";
toRedraw(); toRedraw();
data.key = event.keyCode; data.deviceAction = KEY(event.keyCode);
key.text = keyLabel(data.key); key.text = keyLabel(data.deviceAction);
editDeferred.resolve(data.key); editDeferred.resolve(data.deviceAction);
editDeferred = null; editDeferred = null;
} }
} }

View File

@@ -4,8 +4,11 @@ import haxework.view.DataView;
import haxework.view.LabelView; import haxework.view.LabelView;
import haxework.view.VGroupView; import haxework.view.VGroupView;
import promhx.Promise; import promhx.Promise;
import ru.m.control.DeviceAction;
import ru.m.control.DeviceType;
import ru.m.tankz.control.ActionConfig; import ru.m.tankz.control.ActionConfig;
import ru.m.tankz.storage.SettingsStorage; import ru.m.tankz.storage.SettingsStorage;
import ru.m.tankz.view.settings.ActionView;
@:template class SettingsEditor extends VGroupView { @:template class SettingsEditor extends VGroupView {
@@ -14,12 +17,12 @@ import ru.m.tankz.storage.SettingsStorage;
@:view var label:LabelView; @:view var label:LabelView;
@:view var list:DataView<ActionItem, ActionView>; @:view var list:DataView<ActionItem, ActionView>;
@:provide var storage:SettingsStorage; @:provide static var storage:SettingsStorage;
private function set_controlIndex(value: Int): Int { private function set_controlIndex(value: Int): Int {
this.controlIndex = value; this.controlIndex = value;
label.text = 'Player ${controlIndex+1}'; label.text = 'Player ${controlIndex+1}';
list.data = storage.getActionConfig(controlIndex).data; list.data = bindingToArray(storage.getActionConfig(controlIndex).binding);
return this.controlIndex; return this.controlIndex;
} }
@@ -31,21 +34,21 @@ import ru.m.tankz.storage.SettingsStorage;
} }
private function onItemSelect(index:Int, value:ActionItem, view:ActionView):Void { private function onItemSelect(index:Int, value:ActionItem, view:ActionView):Void {
view.edit(); view.edit().then(function(_) save());
} }
private function change():Void { private function change():Void {
var p: Promise<Int> = Promise.promise(0); var p:Promise<DeviceAction> = Promise.promise(null);
for (view in list.views) { for (view in list.views) {
var v: ActionView = cast view; var v: ActionView = cast view;
p = p.pipe(function(_):Promise<Int> return v.edit()); p = p.pipe(function(_) return v.edit());
} }
p.then(function(_) save()); p.then(function(_) save());
} }
private function clear():Void { private function clear():Void {
for (item in list.data) { for (item in list.data) {
item.key = -1; item.deviceAction = KEY(-1);
} }
list.data = list.data; list.data = list.data;
list.toUpdate(); list.toUpdate();
@@ -53,12 +56,28 @@ import ru.m.tankz.storage.SettingsStorage;
} }
private function reset():Void { private function reset():Void {
list.data = SettingsStorage.getDefaultActionConfig(controlIndex).data; list.data = bindingToArray(SettingsStorage.getDefaultActionConfig(controlIndex).binding);
list.toUpdate(); list.toUpdate();
save(); save();
} }
private function save():Void { 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<ActionItem> {
var result:Array<ActionItem> = [];
for (deviceAction in binding.keys()) {
result.push({deviceAction: deviceAction, tankAction: binding.get(deviceAction)});
}
return result;
}
private static function arrayToBinding(array:Array<ActionItem>):Binding {
var result = new Binding();
for (item in array) {
result.set(item.deviceAction, item.tankAction);
}
return result;
} }
} }