diff --git a/src/app/haxe/ru/m/puzzlez/PuzzlezTheme.hx b/src/app/haxe/ru/m/puzzlez/PuzzlezTheme.hx
index 81ad05b..eeea168 100644
--- a/src/app/haxe/ru/m/puzzlez/PuzzlezTheme.hx
+++ b/src/app/haxe/ru/m/puzzlez/PuzzlezTheme.hx
@@ -18,6 +18,7 @@ class PuzzlezTheme extends Theme {
"restore" => "window-restore-solid.svg",
"compress" => "compress-solid.svg",
"expand" => "expand-solid.svg",
+ "spread" => "clone.svg",
];
public function new() {
diff --git a/src/app/haxe/ru/m/puzzlez/view/GameFrame.hx b/src/app/haxe/ru/m/puzzlez/view/GameFrame.hx
index ca81a22..4ec21e6 100644
--- a/src/app/haxe/ru/m/puzzlez/view/GameFrame.hx
+++ b/src/app/haxe/ru/m/puzzlez/view/GameFrame.hx
@@ -7,7 +7,9 @@ import hw.view.popup.ConfirmView;
import promhx.Promise;
import ru.m.puzzlez.image.Game;
import ru.m.puzzlez.image.IGame;
+import ru.m.puzzlez.proto.event.GameAction;
import ru.m.puzzlez.proto.event.GameEvent;
+import ru.m.puzzlez.proto.event.gameaction.Action;
import ru.m.puzzlez.proto.game.GameState;
import ru.m.puzzlez.proto.game.GameStatus;
import ru.m.puzzlez.render.IRender;
@@ -91,6 +93,16 @@ import ru.m.puzzlez.view.popup.PreviewPopup;
});
}
+ private function shuffle():Void {
+ // TODO: playerId?
+ game.action(new GameAction().setAction(Action.TABLE_SHUFFLE).setPlayerId("local"));
+ }
+
+ private function spread():Void {
+ // TODO: playerId?
+ game.action(new GameAction().setAction(Action.TABLE_SPREAD).setPlayerId("local"));
+ }
+
private function back():Void {
(game.state.status == GameStatus.COMPLETE ? Promise.promise(true) : ConfirmView.confirm("Exit?")).then(result -> {
if (result) {
diff --git a/src/app/haxe/ru/m/puzzlez/view/GameFrame.yaml b/src/app/haxe/ru/m/puzzlez/view/GameFrame.yaml
index 984ed2c..192a6aa 100644
--- a/src/app/haxe/ru/m/puzzlez/view/GameFrame.yaml
+++ b/src/app/haxe/ru/m/puzzlez/view/GameFrame.yaml
@@ -25,6 +25,12 @@ views:
- $type: hw.view.form.ButtonView
style: icon.restore
+onPress: ~render.manager.reset()
+ - $type: hw.view.form.ButtonView
+ style: icon.spread
+ +onPress: ~shuffle()
+ - $type: hw.view.form.ButtonView
+ style: icon.spread
+ +onPress: ~spread()
- $type: hw.view.form.ButtonView
style: icon.setting
geometry.margin.top: 30
diff --git a/src/app/resources/icon/clone.svg b/src/app/resources/icon/clone.svg
new file mode 100644
index 0000000..e85aefc
--- /dev/null
+++ b/src/app/resources/icon/clone.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/common/haxe/ru/m/ArrayUtil.hx b/src/common/haxe/ru/m/ArrayUtil.hx
new file mode 100644
index 0000000..33e7d11
--- /dev/null
+++ b/src/common/haxe/ru/m/ArrayUtil.hx
@@ -0,0 +1,17 @@
+package ru.m;
+
+class ArrayUtil {
+ public static function shuffle(source:Array):Array {
+ var target:Array = source.slice(0);
+ var currentIndex = target.length;
+
+ while (currentIndex != 0) {
+ var randomIndex = Math.floor(Math.random() * currentIndex);
+ currentIndex--;
+ var tmp = target[currentIndex];
+ target[currentIndex] = target[randomIndex];
+ target[randomIndex] = tmp;
+ }
+ return target;
+ }
+}
diff --git a/src/common/haxe/ru/m/puzzlez/image/Game.hx b/src/common/haxe/ru/m/puzzlez/image/Game.hx
index 7a29cda..7fdf13d 100644
--- a/src/common/haxe/ru/m/puzzlez/image/Game.hx
+++ b/src/common/haxe/ru/m/puzzlez/image/Game.hx
@@ -50,6 +50,29 @@ class Game implements IGame {
var x = bound + Math.random() * (state.preset.tableRect.width - part.rect.width - bound * 2);
var y = bound + Math.random() * (state.preset.tableRect.height - part.rect.height - bound * 2);
part.position = new PointExt(x, y);
+ events.emit(EventUtil.change(part));
+ case _:
+ }
+ }
+ }
+
+ private function spread():Void {
+ var partWidth = state.preset.imageRect.width / state.preset.grid.x;
+ var partHeight = state.preset.imageRect.height / state.preset.grid.y;
+ var bound = partWidth * 0.25;
+ var x = bound;
+ var y = bound;
+ var parts = ArrayUtil.shuffle(state.parts);
+ for (part in parts) {
+ switch part.location {
+ case PartLocation.TABLE:
+ part.position = new PointExt(x, y);
+ x += part.rect.width + bound;
+ if (x > state.preset.tableRect.width - partWidth - bound) {
+ x = bound;
+ y += part.rect.height + bound;
+ }
+ events.emit(EventUtil.change(part));
case _:
}
}
@@ -107,6 +130,10 @@ class Game implements IGame {
part.position = event.action.position;
events.emit(EventUtil.change(part));
}
+ case Action.TABLE_SHUFFLE:
+ shuffle();
+ case Action.TABLE_SPREAD:
+ spread();
}
}
}
diff --git a/src/common/proto/event.proto b/src/common/proto/event.proto
index a9b6175..dfda6b5 100644
--- a/src/common/proto/event.proto
+++ b/src/common/proto/event.proto
@@ -21,6 +21,8 @@ message GameAction {
TAKE = 0;
MOVE = 1;
PUT = 2;
+ TABLE_SHUFFLE = 4;
+ TABLE_SPREAD = 3;
}
Action action = 3;
ru.m.puzzlez.proto.core.Point position = 4;