[refactoring] #1
This commit is contained in:
22
src/app/haxe/ru/m/data/DataSource.hx
Normal file
22
src/app/haxe/ru/m/data/DataSource.hx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package ru.m.data;
|
||||||
|
|
||||||
|
import promhx.Promise;
|
||||||
|
|
||||||
|
typedef PageParams = Map<String, Dynamic>;
|
||||||
|
|
||||||
|
typedef Page = {
|
||||||
|
var index:Int;
|
||||||
|
var count:Int;
|
||||||
|
@:optional var params:PageParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef DataPage<D> = {
|
||||||
|
var page:Page;
|
||||||
|
var data:Array<D>;
|
||||||
|
var total:Int;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DataSource<D> {
|
||||||
|
public function getPage(page:Page):Promise<DataPage<D>>;
|
||||||
|
// public function get(id):D;
|
||||||
|
}
|
||||||
@@ -1,202 +0,0 @@
|
|||||||
package ru.m.data;
|
|
||||||
|
|
||||||
import flash.net.SharedObject;
|
|
||||||
import haxe.DynamicAccess;
|
|
||||||
import haxe.io.Bytes;
|
|
||||||
import haxe.Serializer;
|
|
||||||
import haxe.Unserializer;
|
|
||||||
import hw.connect.PacketUtil;
|
|
||||||
import promhx.Promise;
|
|
||||||
import ru.m.data.IDataSource;
|
|
||||||
|
|
||||||
class Converter<D, S> {
|
|
||||||
private var serializer:D -> S;
|
|
||||||
private var desirealizer:S -> D;
|
|
||||||
|
|
||||||
public function new(serializer:D -> S, desirealizer:S -> D) {
|
|
||||||
this.serializer = serializer;
|
|
||||||
this.desirealizer = desirealizer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public inline function serialize(item:D):S {
|
|
||||||
return serializer(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
public inline function deserialize(data:S):D {
|
|
||||||
return desirealizer(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DefaultConverter<D> extends Converter<D, String> {
|
|
||||||
public function new () {
|
|
||||||
super(
|
|
||||||
item -> Serializer.run(item),
|
|
||||||
data -> new Unserializer(data).unserialize()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ProtoConverter<D:protohx.Message> extends Converter<D, String> {
|
|
||||||
public function new(messageClass:Class<D>) {
|
|
||||||
super(
|
|
||||||
item -> PacketUtil.toBytes(item).toHex(),
|
|
||||||
data -> PacketUtil.fromBytes(Bytes.ofHex(data), messageClass)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class EmptyConverter<T> extends Converter<T, T> {
|
|
||||||
public function new() {
|
|
||||||
super(item -> item, data -> data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MetaBuilder<D> extends DefaultConverter<DataMeta> {
|
|
||||||
private var builder:D -> DataMeta;
|
|
||||||
|
|
||||||
public function new(builder:D -> DataMeta) {
|
|
||||||
super();
|
|
||||||
this.builder = builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function build(item:D):DataMeta {
|
|
||||||
return builder(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef DataMeta = Filter;
|
|
||||||
|
|
||||||
typedef IdValue<I> = {id:I, meta:DataMeta};
|
|
||||||
|
|
||||||
class DataStorage<I, D> implements IDataManager<I, D> implements IDataIndex<I> {
|
|
||||||
|
|
||||||
inline private static var DATA_KEY = "item";
|
|
||||||
|
|
||||||
private var name:String;
|
|
||||||
private var metaBuilder:MetaBuilder<D>;
|
|
||||||
private var idConverter:Converter<I, String>;
|
|
||||||
private var dataConverter:Converter<D, Dynamic>;
|
|
||||||
private var indexData:SharedObject;
|
|
||||||
|
|
||||||
public function new(
|
|
||||||
name:String,
|
|
||||||
metaBuilder:MetaBuilder<D>,
|
|
||||||
idConverter:Converter<I, String> = null,
|
|
||||||
dataConverter:Converter<D, Dynamic> = null
|
|
||||||
) {
|
|
||||||
this.name = name;
|
|
||||||
this.metaBuilder = metaBuilder;
|
|
||||||
this.idConverter = idConverter != null ? idConverter : new DefaultConverter();
|
|
||||||
this.dataConverter = dataConverter != null ? dataConverter : new DefaultConverter();
|
|
||||||
this.indexData = SharedObject.getLocal('${name}/index');
|
|
||||||
}
|
|
||||||
|
|
||||||
private function serializeId(id:I):String {
|
|
||||||
return idConverter.serialize(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function desirealizeId(data:String):I {
|
|
||||||
return idConverter.deserialize(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function buildMeta(item:D):DataMeta {
|
|
||||||
return metaBuilder.build(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function checkFilter(filter:Null<Filter>, meta:DataMeta):Bool {
|
|
||||||
if (filter != null) {
|
|
||||||
for (k => v in filter) {
|
|
||||||
if (meta.exists(k) && meta.get(k) != v) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function sort(order:Order, values:Array<IdValue<I>>):Void {
|
|
||||||
if (order != null) {
|
|
||||||
values.sort((a:IdValue<I>, b:IdValue<I>) -> {
|
|
||||||
for (item in order) {
|
|
||||||
var av = a.meta.get(item.key);
|
|
||||||
var bv = b.meta.get(item.key);
|
|
||||||
if (av > bv) {
|
|
||||||
return item.reverse ? - 1 : 1;
|
|
||||||
} else if (av < bv) {
|
|
||||||
return item.reverse ? 1 : -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function serialize(item:D):Dynamic {
|
|
||||||
return dataConverter.serialize(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function unserialize(data:Dynamic):D {
|
|
||||||
return dataConverter.deserialize(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getIndexPage(page:Page):Promise<DataPage<I>> {
|
|
||||||
var data:DynamicAccess<String> = indexData.data;
|
|
||||||
var values:Array<IdValue<I>> = [];
|
|
||||||
for (k => v in data) {
|
|
||||||
var meta = metaBuilder.deserialize(v);
|
|
||||||
if (checkFilter(page.filter, meta)) {
|
|
||||||
values.push({id: desirealizeId(k), meta: meta});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort(page.order, values);
|
|
||||||
var result:Array<I> = values.slice(page.index * page.count, page.index * page.count + page.count).map(value -> value.id);
|
|
||||||
return Promise.promise({
|
|
||||||
page: page,
|
|
||||||
total: values.length,
|
|
||||||
data: result,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPage(page:Page):Promise<DataPage<D>> {
|
|
||||||
return getIndexPage(page).pipe((indexPage:DataPage<I>) -> {
|
|
||||||
return Promise.whenAll([for (id in indexPage.data) get(id)]).then((data:Array<D>) -> {
|
|
||||||
return {
|
|
||||||
page: indexPage.page,
|
|
||||||
total: indexPage.total,
|
|
||||||
data: data,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function get(id:I):Promise<D> {
|
|
||||||
var stringId = serializeId(id);
|
|
||||||
var itemData = SharedObject.getLocal('${name}/${stringId}');
|
|
||||||
var result:D = null;
|
|
||||||
if (Reflect.hasField(itemData.data, DATA_KEY)) {
|
|
||||||
result = unserialize(Reflect.field(itemData.data, DATA_KEY));
|
|
||||||
}
|
|
||||||
return Promise.promise(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function save(item:D):Promise<D> {
|
|
||||||
var meta = metaBuilder.build(item);
|
|
||||||
var stringId = meta.get("id");
|
|
||||||
var itemData = SharedObject.getLocal('${name}/${stringId}');
|
|
||||||
itemData.setProperty(DATA_KEY, serialize(item));
|
|
||||||
itemData.flush();
|
|
||||||
indexData.setProperty(stringId, metaBuilder.serialize(meta));
|
|
||||||
indexData.flush();
|
|
||||||
return Promise.promise(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function delete(id:I):Promise<Bool> {
|
|
||||||
var stringId = serializeId(id);
|
|
||||||
var itemData = SharedObject.getLocal('${name}/${stringId}');
|
|
||||||
itemData.clear();
|
|
||||||
var data:DynamicAccess<String> = indexData.data;
|
|
||||||
data.remove(stringId);
|
|
||||||
indexData.flush();
|
|
||||||
return Promise.promise(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
package ru.m.data;
|
|
||||||
|
|
||||||
import promhx.Promise;
|
|
||||||
|
|
||||||
typedef Filter = Map<String, String>;
|
|
||||||
|
|
||||||
typedef Order = Array<{key: String, ?reverse:Bool}>;
|
|
||||||
|
|
||||||
typedef Page = {
|
|
||||||
var index:Int;
|
|
||||||
var count:Int;
|
|
||||||
@:optional var order:Order;
|
|
||||||
@:optional var filter:Filter;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef DataPage<T> = {
|
|
||||||
var page:Page;
|
|
||||||
var total:Int;
|
|
||||||
var data:Array<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IDataIndex<I> {
|
|
||||||
public function getIndexPage(page:Page):Promise<DataPage<I>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IDataSource<I, D> {
|
|
||||||
public function getPage(page:Page):Promise<DataPage<D>>;
|
|
||||||
public function get(id:I):Promise<D>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IDataManager<I, D> extends IDataSource<I, D> {
|
|
||||||
public function save(item:D):Promise<D>;
|
|
||||||
public function delete(id:I):Promise<Bool>;
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,6 @@ package ru.m.pixabay;
|
|||||||
|
|
||||||
import hw.net.JsonLoader;
|
import hw.net.JsonLoader;
|
||||||
import promhx.Promise;
|
import promhx.Promise;
|
||||||
import ru.m.data.IDataSource;
|
|
||||||
|
|
||||||
typedef PixabayImage = {
|
typedef PixabayImage = {
|
||||||
var id:Int;
|
var id:Int;
|
||||||
@@ -47,7 +46,7 @@ enum abstract PixabayImageType(String) from String to String {
|
|||||||
var VECTOR = "vector";
|
var VECTOR = "vector";
|
||||||
}
|
}
|
||||||
|
|
||||||
class PixabayApi implements IDataSource<Int, PixabayImage> {
|
class PixabayApi {
|
||||||
private var baseUrl:String = "https://pixabay.com/api/";
|
private var baseUrl:String = "https://pixabay.com/api/";
|
||||||
private var key:String;
|
private var key:String;
|
||||||
|
|
||||||
@@ -61,24 +60,15 @@ class PixabayApi implements IDataSource<Int, PixabayImage> {
|
|||||||
return '${baseUrl}?${query}';
|
return '${baseUrl}?${query}';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPage(page:Page):Promise<DataPage<PixabayImage>> {
|
public function getPage(page:Int, perPage:Int, category:PixabayCategory = PixabayCategory.NATURE):Promise<PixabayResponse> {
|
||||||
var category = PixabayCategory.NATURE;
|
|
||||||
if (page.filter != null && page.filter.exists("type")) {
|
|
||||||
category = page.filter.get("type");
|
|
||||||
}
|
|
||||||
return new JsonLoader<PixabayResponse>()
|
return new JsonLoader<PixabayResponse>()
|
||||||
.GET(buildRequest([
|
.GET(buildRequest([
|
||||||
"category" => category,
|
"category" => category,
|
||||||
"image_type" => PixabayImageType.PHOTO,
|
"image_type" => PixabayImageType.PHOTO,
|
||||||
"editors_choice" => true,
|
"editors_choice" => true,
|
||||||
"per_page" => page.count,
|
"per_page" => perPage,
|
||||||
"page" => page.index + 1,
|
"page" => page,
|
||||||
]))
|
]));
|
||||||
.then((response:PixabayResponse) -> ({
|
|
||||||
page: page,
|
|
||||||
total: response.totalHits,
|
|
||||||
data: response.hits,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get(id:Int):Promise<PixabayImage> {
|
public function get(id:Int):Promise<PixabayImage> {
|
||||||
|
|||||||
@@ -1,25 +1,27 @@
|
|||||||
package ru.m.puzzlez;
|
package ru.m.puzzlez;
|
||||||
|
|
||||||
|
import ru.m.puzzlez.image.PixabayImageSource;
|
||||||
|
import ru.m.puzzlez.render.part.IPartBuilder;
|
||||||
|
import ru.m.puzzlez.image.AssetImageSource;
|
||||||
|
import ru.m.puzzlez.image.ImageSourceBundle;
|
||||||
|
import ru.m.puzzlez.settings.Settings;
|
||||||
|
import ru.m.puzzlez.view.PuzzlezAppView;
|
||||||
import hw.app.App;
|
import hw.app.App;
|
||||||
import hw.app.Const;
|
import hw.app.Const;
|
||||||
import hw.log.TraceLogger;
|
import hw.log.TraceLogger;
|
||||||
import ru.m.puzzlez.render.part.IPartBuilder;
|
|
||||||
import ru.m.puzzlez.storage.GameStorage;
|
|
||||||
import ru.m.puzzlez.storage.ImageStorage;
|
|
||||||
import ru.m.puzzlez.storage.SettingsStorage;
|
|
||||||
import ru.m.puzzlez.view.PuzzlezAppView;
|
|
||||||
import ru.m.update.Updater;
|
import ru.m.update.Updater;
|
||||||
|
|
||||||
class PuzzlezApp {
|
class PuzzlezApp {
|
||||||
|
|
||||||
@:provide static var updater:Updater;
|
@:provide static var updater:Updater;
|
||||||
|
@:provide static var sourceBundle:ImageSourceBundle;
|
||||||
|
|
||||||
public static function main() {
|
public static function main() {
|
||||||
// ToDo: fix @:provide macro
|
// ToDo: fix @:provide macro
|
||||||
GameStorage;
|
Settings;
|
||||||
ImageStorage;
|
|
||||||
SettingsStorage;
|
|
||||||
IPartBuilder;
|
IPartBuilder;
|
||||||
|
sourceBundle.register(new AssetImageSource());
|
||||||
|
sourceBundle.register(new PixabayImageSource());
|
||||||
L.push(new TraceLogger());
|
L.push(new TraceLogger());
|
||||||
updater = new Updater(Const.instance.VERSION, "https://shmyga.ru/repo/puzzlez/packages.json");
|
updater = new Updater(Const.instance.VERSION, "https://shmyga.ru/repo/puzzlez/packages.json");
|
||||||
var app = new App();
|
var app = new App();
|
||||||
|
|||||||
26
src/app/haxe/ru/m/puzzlez/image/AssetImageSource.hx
Normal file
26
src/app/haxe/ru/m/puzzlez/image/AssetImageSource.hx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package ru.m.puzzlez.image;
|
||||||
|
|
||||||
|
import openfl.utils.Assets;
|
||||||
|
import promhx.Promise;
|
||||||
|
import ru.m.data.DataSource;
|
||||||
|
import ru.m.puzzlez.image.ImageSource;
|
||||||
|
import ru.m.puzzlez.proto.game.ImageId;
|
||||||
|
|
||||||
|
class AssetImageSource implements ImageSource {
|
||||||
|
public var id(default, never):String = "asset";
|
||||||
|
|
||||||
|
public function new() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPage(page:Page):Promise<DataPage<ImageId>> {
|
||||||
|
return Promise.promise({
|
||||||
|
page: page,
|
||||||
|
data: [],
|
||||||
|
total: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function load(id:String):Promise<ImageValue> {
|
||||||
|
return Promise.promise(ImageValue.BITMAP(Assets.getBitmapData(id)));
|
||||||
|
}
|
||||||
|
}
|
||||||
50
src/app/haxe/ru/m/puzzlez/image/ImageData.hx
Normal file
50
src/app/haxe/ru/m/puzzlez/image/ImageData.hx
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package ru.m.puzzlez.image;
|
||||||
|
|
||||||
|
import flash.display.BitmapData;
|
||||||
|
import haxe.io.Bytes;
|
||||||
|
import hw.net.BytesLoader;
|
||||||
|
import promhx.Promise;
|
||||||
|
import ru.m.puzzlez.image.ImageSource;
|
||||||
|
import ru.m.puzzlez.proto.game.ImageId;
|
||||||
|
|
||||||
|
abstract ImageData(ImageId) from ImageId {
|
||||||
|
|
||||||
|
private static var cache:Map<String, Promise<BitmapData>> = new Map();
|
||||||
|
private static var storageCache:StorageCache = new StorageCache();
|
||||||
|
|
||||||
|
@:provide private var sourceBundle:ImageSourceBundle;
|
||||||
|
|
||||||
|
public function new(image: ImageId) {
|
||||||
|
this = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
@:from public static function fromImageId(value:ImageId):ImageData {
|
||||||
|
return new ImageData(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function extractImage(key:String, value:ImageValue):Promise<BitmapData> {
|
||||||
|
return switch value {
|
||||||
|
case ImageValue.BITMAP(value):
|
||||||
|
Promise.promise(value);
|
||||||
|
case ImageValue.BYTES(value):
|
||||||
|
if (!storageCache.exists(key)) {
|
||||||
|
storageCache.set(key, value);
|
||||||
|
}
|
||||||
|
ImageUtil.bytesToImage(value);
|
||||||
|
case ImageValue.URL(value):
|
||||||
|
new BytesLoader().GET(value).pipe(bytes -> extractImage(key, ImageValue.BYTES(Bytes.ofData(bytes))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function resolve():Promise<BitmapData> {
|
||||||
|
var key = '${this.source}:${this.id}';
|
||||||
|
if (!cache.exists(key)) {
|
||||||
|
if (storageCache.exists(key)) {
|
||||||
|
cache.set(key, extractImage(key, ImageValue.BYTES(storageCache.get(key))));
|
||||||
|
} else {
|
||||||
|
cache.set(key, sourceBundle.get(this.source).load(this.id).pipe(value -> extractImage(key, value)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cache.get(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/app/haxe/ru/m/puzzlez/image/ImageSource.hx
Normal file
18
src/app/haxe/ru/m/puzzlez/image/ImageSource.hx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package ru.m.puzzlez.image;
|
||||||
|
|
||||||
|
import flash.display.BitmapData;
|
||||||
|
import haxe.io.Bytes;
|
||||||
|
import promhx.Promise;
|
||||||
|
import ru.m.data.DataSource;
|
||||||
|
import ru.m.puzzlez.proto.game.ImageId;
|
||||||
|
|
||||||
|
enum ImageValue {
|
||||||
|
BITMAP(value:BitmapData);
|
||||||
|
BYTES(value:Bytes);
|
||||||
|
URL(value:String);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ImageSource extends DataSource<ImageId> {
|
||||||
|
public var id(default, never):String;
|
||||||
|
public function load(id:String):Promise<ImageValue>;
|
||||||
|
}
|
||||||
20
src/app/haxe/ru/m/puzzlez/image/ImageSourceBundle.hx
Normal file
20
src/app/haxe/ru/m/puzzlez/image/ImageSourceBundle.hx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package ru.m.puzzlez.image;
|
||||||
|
|
||||||
|
@:provide class ImageSourceBundle {
|
||||||
|
private var sources:Map<String, ImageSource>;
|
||||||
|
|
||||||
|
public function new() {
|
||||||
|
sources = new Map();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function register(source:ImageSource):Void {
|
||||||
|
sources.set(source.id, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get(sourceId:String):ImageSource {
|
||||||
|
if (!sources.exists(sourceId)) {
|
||||||
|
throw 'ImageSource "$sourceId" not registered';
|
||||||
|
}
|
||||||
|
return sources.get(sourceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
45
src/app/haxe/ru/m/puzzlez/image/PixabayImageSource.hx
Normal file
45
src/app/haxe/ru/m/puzzlez/image/PixabayImageSource.hx
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package ru.m.puzzlez.image;
|
||||||
|
|
||||||
|
import promhx.Promise;
|
||||||
|
import ru.m.data.DataSource;
|
||||||
|
import ru.m.pixabay.PixabayApi;
|
||||||
|
import ru.m.puzzlez.image.ImageSource;
|
||||||
|
import ru.m.puzzlez.proto.game.ImageId;
|
||||||
|
|
||||||
|
class PixabayImageSource implements ImageSource {
|
||||||
|
public var id(default, never):String = "pixabay";
|
||||||
|
|
||||||
|
private var api:PixabayApi;
|
||||||
|
private static var imageUrlsCache:Map<Int, String> = new Map();
|
||||||
|
|
||||||
|
public function new() {
|
||||||
|
api = new PixabayApi("14915210-5eae157281211e0ad28bc8def");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPage(page:Page):Promise<DataPage<ImageId>> {
|
||||||
|
return this.api.getPage(page.index + 1, page.count).then((response:PixabayResponse) -> {
|
||||||
|
var data:Array<ImageId> = [];
|
||||||
|
for (hit in response.hits) {
|
||||||
|
imageUrlsCache.set(hit.id, hit.largeImageURL);
|
||||||
|
data.push(new ImageId().setSource(id).setId(Std.string(hit.id)));
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
page: page,
|
||||||
|
data: data,
|
||||||
|
total: response.totalHits,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function load(id:String):Promise<ImageValue> {
|
||||||
|
var imageId = Std.parseInt(id);
|
||||||
|
if (imageUrlsCache.exists(imageId)) {
|
||||||
|
return Promise.promise(ImageValue.URL(imageUrlsCache.get(imageId)));
|
||||||
|
} else {
|
||||||
|
return api.get(imageId).then((data:PixabayImage) -> {
|
||||||
|
imageUrlsCache.set(imageId, data.largeImageURL);
|
||||||
|
return ImageValue.URL(data.largeImageURL);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/app/haxe/ru/m/puzzlez/image/StorageCache.hx
Normal file
38
src/app/haxe/ru/m/puzzlez/image/StorageCache.hx
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package ru.m.puzzlez.image;
|
||||||
|
|
||||||
|
import flash.net.SharedObject;
|
||||||
|
import haxe.crypto.Md5;
|
||||||
|
import haxe.io.Bytes;
|
||||||
|
|
||||||
|
class StorageCache {
|
||||||
|
private static var DATA_KEY:String = "data";
|
||||||
|
|
||||||
|
private var name:String;
|
||||||
|
|
||||||
|
public function new() {
|
||||||
|
name = "cache";
|
||||||
|
}
|
||||||
|
|
||||||
|
private function resolveDataObject(key:String):SharedObject {
|
||||||
|
return SharedObject.getLocal('${name}/${Md5.encode(key)}');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function exists(key:String):Bool {
|
||||||
|
var dataObject = resolveDataObject(key);
|
||||||
|
return Reflect.hasField(dataObject.data, DATA_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get(key:String):Null<Bytes> {
|
||||||
|
var dataObject = resolveDataObject(key);
|
||||||
|
if (Reflect.hasField(dataObject.data, DATA_KEY)) {
|
||||||
|
return Bytes.ofHex(Reflect.field(dataObject.data, DATA_KEY));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function set(key:String, data:Bytes):Void {
|
||||||
|
var dataObject = resolveDataObject(key);
|
||||||
|
dataObject.setProperty(DATA_KEY, data.toHex());
|
||||||
|
dataObject.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,6 @@ import hw.signal.Signal;
|
|||||||
import hw.storage.SharedObjectStorage;
|
import hw.storage.SharedObjectStorage;
|
||||||
import promhx.Promise;
|
import promhx.Promise;
|
||||||
import ru.m.data.IDataSource;
|
import ru.m.data.IDataSource;
|
||||||
import ru.m.puzzlez.core.Id;
|
|
||||||
import ru.m.puzzlez.proto.core.User;
|
import ru.m.puzzlez.proto.core.User;
|
||||||
import ru.m.puzzlez.proto.event.GameAction;
|
import ru.m.puzzlez.proto.event.GameAction;
|
||||||
import ru.m.puzzlez.proto.event.GameEvent;
|
import ru.m.puzzlez.proto.event.GameEvent;
|
||||||
@@ -22,7 +21,7 @@ import ru.m.puzzlez.proto.pack.NotificationResponse;
|
|||||||
import ru.m.puzzlez.proto.pack.Request;
|
import ru.m.puzzlez.proto.pack.Request;
|
||||||
import ru.m.puzzlez.proto.pack.Response;
|
import ru.m.puzzlez.proto.pack.Response;
|
||||||
|
|
||||||
@:provide class Network implements IDataIndex<ImageId> {
|
@:provide class Network implements IDataSource<String, GameState> {
|
||||||
public var userSignal:Signal<User> = new Signal();
|
public var userSignal:Signal<User> = new Signal();
|
||||||
public var notificationSignal:Signal<NotificationResponse> = new Signal();
|
public var notificationSignal:Signal<NotificationResponse> = new Signal();
|
||||||
public var listSignal:Signal<GameListResponse> = new Signal();
|
public var listSignal:Signal<GameListResponse> = new Signal();
|
||||||
@@ -101,7 +100,7 @@ import ru.m.puzzlez.proto.pack.Response;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getIndexPage(page:Page):Promise<DataPage<ImageId>> {
|
public function getPage(page:Page):Promise<DataPage<GameState>> {
|
||||||
connection.send(new Request().setList(new GameListRequest().setCount(page.count).setPage(page.index)));
|
connection.send(new Request().setList(new GameListRequest().setCount(page.count).setPage(page.index)));
|
||||||
return listSignal.next().then((list:GameListResponse) -> ({
|
return listSignal.next().then((list:GameListResponse) -> ({
|
||||||
page: {
|
page: {
|
||||||
@@ -111,7 +110,11 @@ import ru.m.puzzlez.proto.pack.Response;
|
|||||||
order: null,
|
order: null,
|
||||||
},
|
},
|
||||||
total: list.total,
|
total: list.total,
|
||||||
data: list.games.map(item -> ImageId.fromString(item.preset.imageId)),
|
data: list.games,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function get(id:String):GameState {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package ru.m.puzzlez.net;
|
|||||||
|
|
||||||
import ru.m.puzzlez.proto.event.GameStart;
|
import ru.m.puzzlez.proto.event.GameStart;
|
||||||
import hw.signal.Signal;
|
import hw.signal.Signal;
|
||||||
import ru.m.puzzlez.core.IGame;
|
import ru.m.puzzlez.image.IGame;
|
||||||
import ru.m.puzzlez.proto.event.GameAction;
|
import ru.m.puzzlez.proto.event.GameAction;
|
||||||
import ru.m.puzzlez.proto.event.GameEvent;
|
import ru.m.puzzlez.proto.event.GameEvent;
|
||||||
import ru.m.puzzlez.proto.game.GameState;
|
import ru.m.puzzlez.proto.game.GameState;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package ru.m.puzzlez.render;
|
package ru.m.puzzlez.render;
|
||||||
|
|
||||||
import hw.color.Color;
|
import hw.color.Color;
|
||||||
import ru.m.puzzlez.core.Id;
|
import ru.m.puzzlez.proto.game.ImageId;
|
||||||
|
|
||||||
enum Background {
|
enum Background {
|
||||||
NONE;
|
NONE;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import flash.display.Bitmap;
|
|||||||
import flash.display.BitmapData;
|
import flash.display.BitmapData;
|
||||||
import flash.display.PixelSnapping;
|
import flash.display.PixelSnapping;
|
||||||
import flash.display.Sprite;
|
import flash.display.Sprite;
|
||||||
import ru.m.puzzlez.core.Id;
|
|
||||||
import ru.m.puzzlez.proto.core.Point;
|
import ru.m.puzzlez.proto.core.Point;
|
||||||
import ru.m.puzzlez.proto.game.Part;
|
import ru.m.puzzlez.proto.game.Part;
|
||||||
import ru.m.puzzlez.render.part.IPartBuilder;
|
import ru.m.puzzlez.render.part.IPartBuilder;
|
||||||
@@ -46,9 +45,9 @@ class PartView extends Sprite {
|
|||||||
|
|
||||||
public var size(default, null):Point;
|
public var size(default, null):Point;
|
||||||
|
|
||||||
public var playerId(default, set):Null<PlayerId>;
|
public var playerId(default, set):Null<String>;
|
||||||
|
|
||||||
private function set_playerId(value:Null<PlayerId>):Null<PlayerId> {
|
private function set_playerId(value:Null<String>):Null<String> {
|
||||||
if (playerId != value) {
|
if (playerId != value) {
|
||||||
playerId = value;
|
playerId = value;
|
||||||
redraw();
|
redraw();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package ru.m.puzzlez.render;
|
package ru.m.puzzlez.render;
|
||||||
|
|
||||||
|
import ru.m.puzzlez.image.ImageData;
|
||||||
import flash.display.BitmapData;
|
import flash.display.BitmapData;
|
||||||
import flash.display.PNGEncoderOptions;
|
import flash.display.PNGEncoderOptions;
|
||||||
import flash.display.Sprite;
|
import flash.display.Sprite;
|
||||||
@@ -11,16 +12,13 @@ import flash.utils.ByteArray;
|
|||||||
import hw.signal.Signal;
|
import hw.signal.Signal;
|
||||||
import hw.view.popup.AlertView;
|
import hw.view.popup.AlertView;
|
||||||
import hw.view.SpriteView;
|
import hw.view.SpriteView;
|
||||||
import ru.m.puzzlez.core.Id;
|
|
||||||
import ru.m.puzzlez.net.Network;
|
|
||||||
import ru.m.puzzlez.proto.event.gameaction.Action;
|
import ru.m.puzzlez.proto.event.gameaction.Action;
|
||||||
import ru.m.puzzlez.proto.event.GameAction;
|
import ru.m.puzzlez.proto.event.GameAction;
|
||||||
import ru.m.puzzlez.proto.event.GameEvent;
|
import ru.m.puzzlez.proto.event.GameEvent;
|
||||||
import ru.m.puzzlez.proto.game.GameState;
|
import ru.m.puzzlez.proto.game.GameState;
|
||||||
import ru.m.puzzlez.proto.game.PartLocation;
|
import ru.m.puzzlez.proto.game.PartLocation;
|
||||||
import ru.m.puzzlez.render.ImagePartBuilder;
|
import ru.m.puzzlez.render.ImagePartBuilder;
|
||||||
import ru.m.puzzlez.storage.ImageStorage;
|
import ru.m.puzzlez.settings.Settings;
|
||||||
import ru.m.puzzlez.storage.SettingsStorage;
|
|
||||||
import ru.m.puzzlez.wrap.PointExt;
|
import ru.m.puzzlez.wrap.PointExt;
|
||||||
|
|
||||||
class Render extends SpriteView implements IRender {
|
class Render extends SpriteView implements IRender {
|
||||||
@@ -29,12 +27,11 @@ class Render extends SpriteView implements IRender {
|
|||||||
public var scale(get, set):Float;
|
public var scale(get, set):Float;
|
||||||
public var manager(default, null):RenderManager;
|
public var manager(default, null):RenderManager;
|
||||||
|
|
||||||
@:provide static var settings:SettingsStorage;
|
@:provide static var settings:Settings;
|
||||||
@:provide static var network:Network;
|
|
||||||
|
|
||||||
private var playerId(get, never):PlayerId;
|
private var playerId(get, never):String;
|
||||||
|
|
||||||
private function get_playerId():PlayerId {
|
private function get_playerId():String {
|
||||||
// ToDo: network user
|
// ToDo: network user
|
||||||
return "local";
|
return "local";
|
||||||
}
|
}
|
||||||
@@ -64,7 +61,7 @@ class Render extends SpriteView implements IRender {
|
|||||||
|
|
||||||
private var movePoint:FlashPoint;
|
private var movePoint:FlashPoint;
|
||||||
|
|
||||||
@:provide var imageStorage:ImageStorage;
|
//@:provide var imageStorage:ImageStorage;
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
super();
|
super();
|
||||||
@@ -123,7 +120,7 @@ class Render extends SpriteView implements IRender {
|
|||||||
imageView.redraw();
|
imageView.redraw();
|
||||||
progress.text = "Loading image";
|
progress.text = "Loading image";
|
||||||
content.addChild(progress.content);
|
content.addChild(progress.content);
|
||||||
imageStorage.resolve(state.preset.imageId).then(onImageResolved);
|
ImageData.fromImageId(state.preset.image).resolve().then(onImageResolved);
|
||||||
toUpdate();
|
toUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,12 +160,12 @@ class Render extends SpriteView implements IRender {
|
|||||||
content.graphics.drawRect(0, 0, width, height);
|
content.graphics.drawRect(0, 0, width, height);
|
||||||
content.graphics.endFill();
|
content.graphics.endFill();
|
||||||
case Background.IMAGE(id):
|
case Background.IMAGE(id):
|
||||||
imageStorage.resolve(id).then(result -> {
|
/*imageStorage.resolve(id).then(result -> {
|
||||||
content.graphics.clear();
|
content.graphics.clear();
|
||||||
content.graphics.beginBitmapFill(result);
|
content.graphics.beginBitmapFill(result);
|
||||||
content.graphics.drawRect(0, 0, width, height);
|
content.graphics.drawRect(0, 0, width, height);
|
||||||
content.graphics.endFill();
|
content.graphics.endFill();
|
||||||
});
|
});*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package ru.m.puzzlez.storage;
|
package ru.m.puzzlez.settings;
|
||||||
|
|
||||||
import hw.storage.SharedObjectStorage;
|
import hw.storage.SharedObjectStorage;
|
||||||
import ru.m.puzzlez.render.Background;
|
import ru.m.puzzlez.render.Background;
|
||||||
|
|
||||||
@:provide class SettingsStorage extends SharedObjectStorage {
|
@:provide class Settings extends SharedObjectStorage {
|
||||||
private inline static var VERSION = 1;
|
private inline static var VERSION = 2;
|
||||||
private inline static var BACKGROUND_KEY = "background";
|
private inline static var BACKGROUND_KEY = "background";
|
||||||
|
|
||||||
public var background(get, set):Background;
|
public var background(get, set):Background;
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
package ru.m.puzzlez.source;
|
|
||||||
|
|
||||||
import ru.m.data.IDataSource;
|
|
||||||
import flash.display.BitmapData;
|
|
||||||
import openfl.Assets;
|
|
||||||
import openfl.utils.AssetType;
|
|
||||||
import promhx.Promise;
|
|
||||||
import ru.m.puzzlez.core.Id;
|
|
||||||
|
|
||||||
class AssetSource implements IImageSource {
|
|
||||||
public static var ID:SourceId = "asset";
|
|
||||||
|
|
||||||
public var id(default, never):SourceId = ID;
|
|
||||||
|
|
||||||
private var data:Array<ImageId>;
|
|
||||||
|
|
||||||
public function new() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private function resolveData():Array<ImageId> {
|
|
||||||
return [for (name in Assets.list(AssetType.IMAGE).filter((name:String) -> name.substr(0, 15) == "resources/image")) new ImageId(id, name)];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getIndexPage(page:Page):Promise<DataPage<ImageId>> {
|
|
||||||
if (data == null) {
|
|
||||||
data = resolveData();
|
|
||||||
}
|
|
||||||
// ToDo: pagination
|
|
||||||
return Promise.promise({
|
|
||||||
page: page,
|
|
||||||
total: data.length,
|
|
||||||
data: data,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function loadImage(id:ImageId, preview:Bool = false):Promise<BitmapData> {
|
|
||||||
return Promise.promise(Assets.getBitmapData(id.id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package ru.m.puzzlez.source;
|
|
||||||
|
|
||||||
import flash.display.BitmapData;
|
|
||||||
import haxe.io.Bytes;
|
|
||||||
import promhx.Promise;
|
|
||||||
import ru.m.data.IDataSource;
|
|
||||||
import ru.m.puzzlez.core.Id;
|
|
||||||
import ru.m.puzzlez.storage.FileStorage;
|
|
||||||
|
|
||||||
class FileSource implements IImageSource {
|
|
||||||
public static var ID:SourceId = "file";
|
|
||||||
|
|
||||||
public var id(default, never):SourceId = ID;
|
|
||||||
|
|
||||||
private var storage:FileStorage;
|
|
||||||
|
|
||||||
public function new() {
|
|
||||||
storage = new FileStorage();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getIndexPage(page:Page):Promise<DataPage<ImageId>> {
|
|
||||||
return storage.getIndexPage(page).then(data -> ({page: data.page, total: data.total, data: data.data.map(item -> new ImageId(id, item))}));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function loadImage(id:ImageId, preview:Bool = false):Promise<BitmapData> {
|
|
||||||
return storage.get(id.id).pipe(ImageUtil.bytesToImage);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function append(data:Bytes):Promise<Dynamic> {
|
|
||||||
return storage.save(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function remove(id:ImageId):Promise<Dynamic> {
|
|
||||||
return storage.delete(id.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function clean():Void {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package ru.m.puzzlez.source;
|
|
||||||
|
|
||||||
import flash.display.BitmapData;
|
|
||||||
import promhx.Promise;
|
|
||||||
import ru.m.data.IDataSource;
|
|
||||||
import ru.m.puzzlez.core.Id;
|
|
||||||
|
|
||||||
interface IImageSource extends IDataIndex<ImageId> {
|
|
||||||
public var id(default, never):SourceId;
|
|
||||||
public function loadImage(id:ImageId, preview:Bool = false):Promise<BitmapData>;
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
package ru.m.puzzlez.source;
|
|
||||||
|
|
||||||
import flash.display.BitmapData;
|
|
||||||
import flash.utils.ByteArray;
|
|
||||||
import haxe.io.Bytes;
|
|
||||||
import hw.net.BytesLoader;
|
|
||||||
import promhx.Promise;
|
|
||||||
import ru.m.data.IDataSource;
|
|
||||||
import ru.m.pixabay.PixabayApi;
|
|
||||||
import ru.m.puzzlez.core.Id;
|
|
||||||
import ru.m.puzzlez.core.ImageListSource;
|
|
||||||
import ru.m.puzzlez.storage.CacheStorage;
|
|
||||||
|
|
||||||
class PixabaySource implements IImageSource {
|
|
||||||
public static var ID:SourceId = "pixabay";
|
|
||||||
|
|
||||||
public var id(default, never):SourceId = ID;
|
|
||||||
|
|
||||||
private var api:PixabayApi;
|
|
||||||
|
|
||||||
@:provide static var imageCache:CacheStorage;
|
|
||||||
|
|
||||||
public function new() {
|
|
||||||
api = new PixabayApi("14915210-5eae157281211e0ad28bc8def");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getIndexPage(page:Page):Promise<DataPage<ImageId>> {
|
|
||||||
return api.getPage(page).then(data -> ({page: data.page, total: data.total, data: data.data.map(item -> new ImageId(id, Std.string(item.id)))}));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function loadImage(id:ImageId, preview:Bool = false):Promise<BitmapData> {
|
|
||||||
var key = '${id}_${preview}';
|
|
||||||
if (imageCache.exists(key)) {
|
|
||||||
return ImageUtil.bytesToImage(imageCache.read(key));
|
|
||||||
} else {
|
|
||||||
return api.get(Std.parseInt(id.id))
|
|
||||||
.pipe((data:PixabayImage) -> new BytesLoader().GET(preview ? data.webformatURL : data.largeImageURL))
|
|
||||||
.pipe((data:ByteArray) -> {
|
|
||||||
var bytes = Bytes.ofData(data);
|
|
||||||
imageCache.write(key, bytes);
|
|
||||||
return ImageUtil.bytesToImage(bytes);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function categorySource(category:PixabayCategory):ImageListSource {
|
|
||||||
return {
|
|
||||||
title: category,
|
|
||||||
source: this,
|
|
||||||
filter: ["type" => category],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
package ru.m.puzzlez.storage;
|
|
||||||
|
|
||||||
import flash.net.SharedObject;
|
|
||||||
import haxe.io.Bytes;
|
|
||||||
|
|
||||||
#if html5
|
|
||||||
@:provide class CacheStorage {
|
|
||||||
public function new() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public function exists(key:String):Bool {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function read(key:String):Null<Bytes> {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function write(key:String, data:Bytes):Void {
|
|
||||||
}
|
|
||||||
|
|
||||||
public function remove(key:String):Void {
|
|
||||||
}
|
|
||||||
|
|
||||||
public function clean():Void {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
@:provide class CacheStorage {
|
|
||||||
|
|
||||||
public function new() {
|
|
||||||
}
|
|
||||||
|
|
||||||
private inline function getSharedObject(key:String):SharedObject {
|
|
||||||
key = StringTools.replace(key, "/", "_");
|
|
||||||
key = StringTools.replace(key, ":", "_");
|
|
||||||
key = StringTools.replace(key, ".", "_");
|
|
||||||
return SharedObject.getLocal('cache/${key}');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function exists(key:String):Bool {
|
|
||||||
var so = getSharedObject(key);
|
|
||||||
return so.size > 0 && Reflect.hasField(so.data, "data");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function read(key:String):Null<Bytes> {
|
|
||||||
var so = getSharedObject(key);
|
|
||||||
return Bytes.ofData(Reflect.field(so.data, "data"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function write(key:String, data:Bytes):Void {
|
|
||||||
var so = getSharedObject(key);
|
|
||||||
so.setProperty("data", data.getData());
|
|
||||||
so.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function remove(key:String):Void {
|
|
||||||
var so = getSharedObject(key);
|
|
||||||
so.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function clean():Void {
|
|
||||||
//SharedObject.deleteAll("cache/");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#end
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package ru.m.puzzlez.storage;
|
|
||||||
|
|
||||||
import haxe.crypto.Md5;
|
|
||||||
import haxe.io.Bytes;
|
|
||||||
import ru.m.data.DataStorage;
|
|
||||||
|
|
||||||
class FileStorage extends DataStorage<String, Bytes> {
|
|
||||||
inline private static var NAME = "file";
|
|
||||||
inline private static var VERSION = 1;
|
|
||||||
|
|
||||||
public function new() {
|
|
||||||
super(
|
|
||||||
'${NAME}/${VERSION}',
|
|
||||||
new MetaBuilder<Bytes>(item -> ["id" => Md5.make(item).toHex(), "date" => Date.now().toString()]),
|
|
||||||
new EmptyConverter<String>(),
|
|
||||||
new Converter<Bytes, String>(item -> item.toHex(), data -> Bytes.ofHex(data))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
package ru.m.puzzlez.storage;
|
|
||||||
|
|
||||||
import ru.m.data.DataStorage;
|
|
||||||
import ru.m.puzzlez.core.Id;
|
|
||||||
import ru.m.puzzlez.core.ImageListSource;
|
|
||||||
import ru.m.puzzlez.proto.game.GameState;
|
|
||||||
|
|
||||||
@:provide class GameStorage extends DataStorage<ImageId, GameState> {
|
|
||||||
inline private static var NAME = "game";
|
|
||||||
inline private static var VERSION = 6;
|
|
||||||
|
|
||||||
public function new() {
|
|
||||||
super(
|
|
||||||
'${NAME}/${VERSION}',
|
|
||||||
new MetaBuilder<GameState>(item -> [
|
|
||||||
"id" => item.preset.imageId,
|
|
||||||
"status" => Std.string(item.status),
|
|
||||||
"date" => Date.now().toString()
|
|
||||||
]),
|
|
||||||
new Converter<ImageId, String>(id -> id.toString(), data -> ImageId.fromString(data)),
|
|
||||||
new ProtoConverter(GameState)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function statusSource(status:Int):ImageListSource {
|
|
||||||
return {
|
|
||||||
title: Std.string(status), // # ToDo:
|
|
||||||
source: this,
|
|
||||||
filter: ["status" => Std.string(status)],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
package ru.m.puzzlez.storage;
|
|
||||||
|
|
||||||
import flash.display.BitmapData;
|
|
||||||
import flash.net.SharedObject;
|
|
||||||
import promhx.Promise;
|
|
||||||
import Reflect;
|
|
||||||
import ru.m.puzzlez.core.Id;
|
|
||||||
import ru.m.puzzlez.source.AssetSource;
|
|
||||||
import ru.m.puzzlez.source.FileSource;
|
|
||||||
import ru.m.puzzlez.source.IImageSource;
|
|
||||||
import ru.m.puzzlez.source.PixabaySource;
|
|
||||||
|
|
||||||
@:provide class ImageStorage {
|
|
||||||
|
|
||||||
public var sources(default, null):Map<SourceId, IImageSource>;
|
|
||||||
|
|
||||||
private var cache:Map<String, Promise<BitmapData>>;
|
|
||||||
|
|
||||||
public function new() {
|
|
||||||
sources = new Map();
|
|
||||||
cache = new Map();
|
|
||||||
register(new AssetSource());
|
|
||||||
register(new FileSource());
|
|
||||||
register(new PixabaySource());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function register(source:IImageSource):Void {
|
|
||||||
sources.set(source.id, source);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function read(id:ImageId):BitmapData {
|
|
||||||
var so = SharedObject.getLocal(id);
|
|
||||||
return Reflect.field(so.data, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function write(id:ImageId, data:BitmapData):Void {
|
|
||||||
var so = SharedObject.getLocal(id);
|
|
||||||
so.setProperty("", data);
|
|
||||||
so.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function resolve(id:ImageId, preview:Bool = false):Promise<BitmapData> {
|
|
||||||
var key = '${id}_${preview}';
|
|
||||||
if (cache.exists(key)) {
|
|
||||||
return cache.get(key);
|
|
||||||
}
|
|
||||||
var result = sources.get(id.source).loadImage(id, preview);
|
|
||||||
cache.set(key, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +1,18 @@
|
|||||||
package ru.m.puzzlez.view;
|
package ru.m.puzzlez.view;
|
||||||
|
|
||||||
import ru.m.puzzlez.proto.game.GameStatus;
|
|
||||||
import haxe.Timer;
|
import haxe.Timer;
|
||||||
import hw.view.frame.FrameSwitcher;
|
import hw.view.frame.FrameSwitcher;
|
||||||
import hw.view.frame.FrameView;
|
import hw.view.frame.FrameView;
|
||||||
import hw.view.popup.ConfirmView;
|
import hw.view.popup.ConfirmView;
|
||||||
import promhx.Promise;
|
import promhx.Promise;
|
||||||
import ru.m.puzzlez.core.Game;
|
import ru.m.puzzlez.image.Game;
|
||||||
import ru.m.puzzlez.core.IGame;
|
import ru.m.puzzlez.image.IGame;
|
||||||
import ru.m.puzzlez.net.NetworkGame;
|
//import ru.m.puzzlez.net.NetworkGame;
|
||||||
import ru.m.puzzlez.proto.event.GameEvent;
|
import ru.m.puzzlez.proto.event.GameEvent;
|
||||||
import ru.m.puzzlez.proto.game.GameState;
|
import ru.m.puzzlez.proto.game.GameState;
|
||||||
|
import ru.m.puzzlez.proto.game.GameStatus;
|
||||||
import ru.m.puzzlez.render.IRender;
|
import ru.m.puzzlez.render.IRender;
|
||||||
import ru.m.puzzlez.storage.GameStorage;
|
import ru.m.puzzlez.settings.Settings;
|
||||||
import ru.m.puzzlez.storage.SettingsStorage;
|
|
||||||
import ru.m.puzzlez.view.popup.BackgroundPopup;
|
import ru.m.puzzlez.view.popup.BackgroundPopup;
|
||||||
import ru.m.puzzlez.view.popup.PreviewPopup;
|
import ru.m.puzzlez.view.popup.PreviewPopup;
|
||||||
|
|
||||||
@@ -23,8 +22,8 @@ import ru.m.puzzlez.view.popup.PreviewPopup;
|
|||||||
@:view private var render:IRender;
|
@:view private var render:IRender;
|
||||||
private var game:IGame;
|
private var game:IGame;
|
||||||
@:provide var switcher:FrameSwitcher;
|
@:provide var switcher:FrameSwitcher;
|
||||||
@:provide var storage:GameStorage;
|
// @:provide var storage:GameStorage;
|
||||||
@:provide var settings:SettingsStorage;
|
@:provide var settings:Settings;
|
||||||
|
|
||||||
private var saveTimer:Timer;
|
private var saveTimer:Timer;
|
||||||
|
|
||||||
@@ -35,7 +34,7 @@ import ru.m.puzzlez.view.popup.PreviewPopup;
|
|||||||
override public function onShow(state:GameState):Void {
|
override public function onShow(state:GameState):Void {
|
||||||
onHide();
|
onHide();
|
||||||
if (state.online) {
|
if (state.online) {
|
||||||
game = new NetworkGame(state);
|
//game = new NetworkGame(state);
|
||||||
} else {
|
} else {
|
||||||
game = new Game(state);
|
game = new Game(state);
|
||||||
}
|
}
|
||||||
@@ -69,7 +68,7 @@ import ru.m.puzzlez.view.popup.PreviewPopup;
|
|||||||
saveTimer = null;
|
saveTimer = null;
|
||||||
}
|
}
|
||||||
if (game != null) {
|
if (game != null) {
|
||||||
storage.save(game.state);
|
// storage.save(game.state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +95,8 @@ import ru.m.puzzlez.view.popup.PreviewPopup;
|
|||||||
(game.state.status == GameStatus.COMPLETE ? Promise.promise(true) : ConfirmView.confirm("Exit?"))
|
(game.state.status == GameStatus.COMPLETE ? Promise.promise(true) : ConfirmView.confirm("Exit?"))
|
||||||
.then(result -> {
|
.then(result -> {
|
||||||
if (result) {
|
if (result) {
|
||||||
switcher.change(ImageListFrame.ID, storage.statusSource(game.state.status));
|
switcher.change(StartFrame.ID);
|
||||||
|
// switcher.change(ImageListFrame.ID, storage.statusSource(game.state.status));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
package ru.m.puzzlez.view;
|
|
||||||
|
|
||||||
import hw.view.form.ButtonView;
|
|
||||||
import hw.view.form.LabelView;
|
|
||||||
import hw.view.frame.FrameSwitcher;
|
|
||||||
import hw.view.frame.FrameView;
|
|
||||||
import ru.m.puzzlez.core.ImageListSource;
|
|
||||||
import ru.m.puzzlez.FileUtil;
|
|
||||||
import ru.m.puzzlez.source.FileSource;
|
|
||||||
import ru.m.puzzlez.storage.GameStorage;
|
|
||||||
import ru.m.puzzlez.storage.ImageStorage;
|
|
||||||
import ru.m.puzzlez.view.common.ImageDataList;
|
|
||||||
|
|
||||||
@:template class ImageListFrame extends FrameView<ImageListSource> {
|
|
||||||
public static var ID = "image_list";
|
|
||||||
|
|
||||||
@:view("header") var headerView:LabelView;
|
|
||||||
@:view("images") var imagesView:ImageDataList;
|
|
||||||
@:view var select:ButtonView;
|
|
||||||
|
|
||||||
@:provide var gameStorage:GameStorage;
|
|
||||||
@:provide var imageStorage:ImageStorage;
|
|
||||||
@:provide var switcher:FrameSwitcher;
|
|
||||||
|
|
||||||
public function new() {
|
|
||||||
super(ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
override public function onShow(data:ImageListSource):Void {
|
|
||||||
imagesView.reset();
|
|
||||||
if (data != null) {
|
|
||||||
headerView.text = data.title;
|
|
||||||
// ToDo:
|
|
||||||
select.visible = Std.is(data.source, FileSource);
|
|
||||||
imagesView.page.filter = data.filter;
|
|
||||||
imagesView.source = data.source;
|
|
||||||
imagesView.refresh();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function selectFile():Void {
|
|
||||||
FileUtil.browse().then((data:FileContent) -> {
|
|
||||||
var fileSource:FileSource = cast imageStorage.sources.get(FileSource.ID);
|
|
||||||
fileSource.append(data.content).then(_ -> imagesView.refresh());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private function back():Void {
|
|
||||||
switcher.change(StartFrame.ID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
46
src/app/haxe/ru/m/puzzlez/view/ImageSourceFrame.hx
Normal file
46
src/app/haxe/ru/m/puzzlez/view/ImageSourceFrame.hx
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package ru.m.puzzlez.view;
|
||||||
|
|
||||||
|
import hw.view.form.LabelView;
|
||||||
|
import hw.view.frame.FrameSwitcher;
|
||||||
|
import hw.view.frame.FrameView;
|
||||||
|
import ru.m.puzzlez.image.GameUtil;
|
||||||
|
import ru.m.puzzlez.image.ImageSourceBundle;
|
||||||
|
import ru.m.puzzlez.proto.game.ImageId;
|
||||||
|
import ru.m.puzzlez.view.common.ImageDataList;
|
||||||
|
|
||||||
|
typedef ImageSourceConfig = {
|
||||||
|
var title:String;
|
||||||
|
var sourceId:String;
|
||||||
|
}
|
||||||
|
|
||||||
|
@:template class ImageSourceFrame extends FrameView<ImageSourceConfig> {
|
||||||
|
public static var ID = "source";
|
||||||
|
|
||||||
|
@:view var header:LabelView;
|
||||||
|
@:view var images:ImageDataList;
|
||||||
|
@:provide var switcher:FrameSwitcher;
|
||||||
|
@:provide var sourceBundle:ImageSourceBundle;
|
||||||
|
|
||||||
|
public function new() {
|
||||||
|
super(ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
override public function onShow(data:ImageSourceConfig):Void {
|
||||||
|
images.reset();
|
||||||
|
if (data != null) {
|
||||||
|
header.text = data.title;
|
||||||
|
// images.page.filter = data.filter;
|
||||||
|
images.source = sourceBundle.get(data.sourceId);
|
||||||
|
images.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function start(imageId:ImageId):Void {
|
||||||
|
var state = GameUtil.buildState(GameUtil.buildPreset(imageId, 2, 2));
|
||||||
|
switcher.change(GameFrame.ID, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function back():Void {
|
||||||
|
switcher.change(StartFrame.ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,11 +7,7 @@ views:
|
|||||||
- id: images
|
- id: images
|
||||||
$type: ru.m.puzzlez.view.common.ImageDataList
|
$type: ru.m.puzzlez.view.common.ImageDataList
|
||||||
geometry.stretch: true
|
geometry.stretch: true
|
||||||
- id: select
|
+onImageSelect: ~start
|
||||||
$type: hw.view.form.ButtonView
|
|
||||||
text: Select...
|
|
||||||
+onPress: ~selectFile()
|
|
||||||
visible: false
|
|
||||||
- $type: hw.view.form.ButtonView
|
- $type: hw.view.form.ButtonView
|
||||||
text: Back
|
text: Back
|
||||||
geometry.position: absolute
|
geometry.position: absolute
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
package ru.m.puzzlez.view;
|
package ru.m.puzzlez.view;
|
||||||
|
|
||||||
import ru.m.puzzlez.net.Network;
|
|
||||||
import hw.geom.IntPoint;
|
import hw.geom.IntPoint;
|
||||||
import hw.view.data.DataView;
|
import hw.view.data.DataView;
|
||||||
import hw.view.form.ToggleButtonView;
|
import hw.view.form.ToggleButtonView;
|
||||||
import hw.view.frame.FrameSwitcher;
|
import hw.view.frame.FrameSwitcher;
|
||||||
import hw.view.frame.FrameView;
|
import hw.view.frame.FrameView;
|
||||||
import ru.m.puzzlez.core.GameUtil;
|
import ru.m.puzzlez.image.GameUtil;
|
||||||
import ru.m.puzzlez.core.Id;
|
import ru.m.puzzlez.net.Network;
|
||||||
import ru.m.puzzlez.storage.ImageStorage;
|
import ru.m.puzzlez.proto.game.ImageId;
|
||||||
|
import ru.m.puzzlez.settings.ImageStorage;
|
||||||
import ru.m.puzzlez.view.common.PresetView;
|
import ru.m.puzzlez.view.common.PresetView;
|
||||||
|
|
||||||
@:template class PresetFrame extends FrameView<ImageId> {
|
@:template class PresetFrame extends FrameView<ImageId> {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import hw.view.form.ButtonView;
|
|||||||
import hw.view.form.LabelView;
|
import hw.view.form.LabelView;
|
||||||
import hw.view.frame.FrameSwitcher;
|
import hw.view.frame.FrameSwitcher;
|
||||||
import hw.view.group.VGroupView;
|
import hw.view.group.VGroupView;
|
||||||
import ru.m.puzzlez.net.Network;
|
|
||||||
|
|
||||||
@:template class PuzzlezAppView extends VGroupView {
|
@:template class PuzzlezAppView extends VGroupView {
|
||||||
|
|
||||||
@@ -16,7 +15,6 @@ import ru.m.puzzlez.net.Network;
|
|||||||
@:view("user") var userLabel:LabelView;
|
@:view("user") var userLabel:LabelView;
|
||||||
|
|
||||||
@:provide static var switcher:FrameSwitcher;
|
@:provide static var switcher:FrameSwitcher;
|
||||||
@:provide static var network:Network;
|
|
||||||
@:provide static var app:App;
|
@:provide static var app:App;
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
@@ -28,12 +26,11 @@ import ru.m.puzzlez.net.Network;
|
|||||||
stage.addEventListener(KeyboardEvent.KEY_DOWN, (event:KeyboardEvent) -> {
|
stage.addEventListener(KeyboardEvent.KEY_DOWN, (event:KeyboardEvent) -> {
|
||||||
switch event.keyCode {
|
switch event.keyCode {
|
||||||
case Keyboard.ESCAPE:
|
case Keyboard.ESCAPE:
|
||||||
switcher.change(StartFrame.ID);
|
//switcher.change(StartFrame.ID);
|
||||||
case Keyboard.F:
|
case Keyboard.F:
|
||||||
app.fullScreen = !app.fullScreen;
|
app.fullScreen = !app.fullScreen;
|
||||||
case _:
|
case _:
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
network.userSignal.connect(user -> userLabel.text = user.name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ views:
|
|||||||
style: dark
|
style: dark
|
||||||
factory:
|
factory:
|
||||||
_start_: {$class: ru.m.puzzlez.view.StartFrame}
|
_start_: {$class: ru.m.puzzlez.view.StartFrame}
|
||||||
_image_list_: {$class: ru.m.puzzlez.view.ImageListFrame}
|
_source_: {$class: ru.m.puzzlez.view.ImageSourceFrame}
|
||||||
_preset_: {$class: ru.m.puzzlez.view.PresetFrame}
|
#_preset_: {$class: ru.m.puzzlez.view.PresetFrame}
|
||||||
_game_: {$class: ru.m.puzzlez.view.GameFrame}
|
_game_: {$class: ru.m.puzzlez.view.GameFrame}
|
||||||
- $type: hw.view.group.HGroupView
|
- $type: hw.view.group.HGroupView
|
||||||
geometry.position: absolute
|
geometry.position: absolute
|
||||||
|
|||||||
@@ -1,101 +1,33 @@
|
|||||||
package ru.m.puzzlez.view;
|
package ru.m.puzzlez.view;
|
||||||
|
|
||||||
import hw.view.data.DataView;
|
|
||||||
import hw.view.form.ButtonView;
|
import hw.view.form.ButtonView;
|
||||||
import hw.view.frame.FrameSwitcher;
|
import hw.view.frame.FrameSwitcher;
|
||||||
import hw.view.frame.FrameView;
|
import hw.view.frame.FrameView;
|
||||||
import ru.m.data.IDataSource;
|
import ru.m.puzzlez.view.ImageSourceFrame;
|
||||||
import ru.m.pixabay.PixabayApi;
|
|
||||||
import ru.m.puzzlez.core.ImageListSource;
|
|
||||||
import ru.m.puzzlez.net.Network;
|
|
||||||
import ru.m.puzzlez.proto.game.GameStatus;
|
|
||||||
import ru.m.puzzlez.proto.pack.NotificationResponse;
|
|
||||||
import ru.m.puzzlez.source.AssetSource;
|
|
||||||
import ru.m.puzzlez.source.FileSource;
|
|
||||||
import ru.m.puzzlez.source.PixabaySource;
|
|
||||||
import ru.m.puzzlez.storage.GameStorage;
|
|
||||||
import ru.m.puzzlez.storage.ImageStorage;
|
|
||||||
import ru.m.update.Updater;
|
import ru.m.update.Updater;
|
||||||
|
|
||||||
@:template class StartFrame extends FrameView<Dynamic> {
|
@:template class StartFrame extends FrameView<Dynamic> {
|
||||||
public static var ID = "start";
|
public static var ID = "start";
|
||||||
|
|
||||||
@:view var sources:DataView<ImageListSource, ButtonView>;
|
@:view var updateButton:ButtonView;
|
||||||
@:view("load") var loadButton:ButtonView;
|
|
||||||
@:view("complete") var completeButton:ButtonView;
|
|
||||||
@:view("network") var networkButton:ButtonView;
|
|
||||||
@:view("update") var updateButton:ButtonView;
|
|
||||||
|
|
||||||
@:provide var storage:ImageStorage;
|
|
||||||
@:provide var switcher:FrameSwitcher;
|
@:provide var switcher:FrameSwitcher;
|
||||||
@:provide var gameStorage:GameStorage;
|
|
||||||
@:provide var network:Network;
|
|
||||||
@:provide static var appUpdater:Updater;
|
@:provide static var appUpdater:Updater;
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
super(ID);
|
super(ID);
|
||||||
var data:Array<ImageListSource> = [];
|
|
||||||
data.push({title: "Assets", source: storage.sources.get(AssetSource.ID)});
|
|
||||||
data.push({title: "Files", source: storage.sources.get(FileSource.ID)});
|
|
||||||
var pixabay:PixabaySource = cast storage.sources.get(PixabaySource.ID);
|
|
||||||
for (type in AbstractEnumTools.getValues(PixabayCategory)) {
|
|
||||||
data.push(pixabay.categorySource(type));
|
|
||||||
}
|
|
||||||
sources.data = data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function refresh():Void {
|
public function openSource(source:ImageSourceConfig):Void {
|
||||||
var startedRequest:Page = {index: 0, count: 0, filter: ["status" => Std.string(GameStatus.STARTED)]};
|
switcher.change(ImageSourceFrame.ID, source);
|
||||||
gameStorage.getIndexPage(startedRequest).then(page -> {
|
|
||||||
var total = page.total;
|
|
||||||
loadButton.text = 'Resume (${total})';
|
|
||||||
loadButton.disabled = total == 0;
|
|
||||||
});
|
|
||||||
var completeRequest:Page = {index: 0, count: 0, filter: ["status" => Std.string(GameStatus.COMPLETE)]};
|
|
||||||
gameStorage.getIndexPage(completeRequest).then(page -> {
|
|
||||||
var total = page.total;
|
|
||||||
completeButton.text = 'Complete (${total})';
|
|
||||||
completeButton.disabled = total == 0;
|
|
||||||
});
|
|
||||||
network.notificationSignal.next().then(onNotification);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function onNotification(notification:NotificationResponse):Void {
|
|
||||||
var total = notification.games;
|
|
||||||
networkButton.text = 'Network (${total})';
|
|
||||||
networkButton.disabled = total == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override public function onShow(data:Dynamic):Void {
|
override public function onShow(data:Dynamic):Void {
|
||||||
refresh();
|
|
||||||
appUpdater.check().then((info:Null<PackageInfo>) -> {
|
appUpdater.check().then((info:Null<PackageInfo>) -> {
|
||||||
if (info != null) {
|
if (info != null) {
|
||||||
updateButton.visible = true;
|
updateButton.visible = true;
|
||||||
updateButton.text = 'Update ${info.version}';
|
updateButton.text = 'Update ${info.version}';
|
||||||
}
|
}
|
||||||
}).catchError(error -> L.w('Update', 'failed: ${error}'));
|
}).catchError(error -> L.w('Update', 'failed: ${error}'));
|
||||||
network.notificationSignal.connect(onNotification);
|
|
||||||
}
|
|
||||||
|
|
||||||
override public function onHide():Void {
|
|
||||||
network.notificationSignal.disconnect(onNotification);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function sourceViewFactory(index:Int, source:ImageListSource):ButtonView {
|
|
||||||
var result = new ButtonView();
|
|
||||||
result.text = source.title;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function load(source:ImageListSource):Void {
|
|
||||||
switcher.change(ImageListFrame.ID, source);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function openGames(status:Int):Void {
|
|
||||||
switcher.change(ImageListFrame.ID, gameStorage.statusSource(status));
|
|
||||||
}
|
|
||||||
|
|
||||||
private function openNetwork():Void {
|
|
||||||
switcher.change(ImageListFrame.ID, {title: 'Network', source: network});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,43 +15,16 @@ views:
|
|||||||
- $type: hw.view.form.LabelView
|
- $type: hw.view.form.LabelView
|
||||||
text: $r:text:app.name
|
text: $r:text:app.name
|
||||||
font.size: 50
|
font.size: 50
|
||||||
- id: sources
|
- $type: hw.view.form.ButtonView
|
||||||
$type: hw.view.data.DataView
|
text: Pixabay
|
||||||
layout:
|
geometry.hAlign: center
|
||||||
$type: hw.view.layout.TailLayout
|
+onPress: "~openSource({title: 'Pixabay', sourceId: 'pixabay'})"
|
||||||
rowSize: 5
|
|
||||||
margin: 10
|
|
||||||
vAlign: middle
|
|
||||||
geometry.stretch: true
|
|
||||||
factory: ~sourceViewFactory
|
|
||||||
+onDataSelect: ~load
|
|
||||||
geometry.margin: 5
|
|
||||||
overflow.y: scroll
|
|
||||||
- $type: hw.view.group.HGroupView
|
|
||||||
geometry.width: 100%
|
|
||||||
layout.vAlign: middle
|
|
||||||
layout.margin: 10
|
|
||||||
views:
|
|
||||||
- id: load
|
|
||||||
$type: hw.view.form.ButtonView
|
|
||||||
text: Load
|
|
||||||
+onPress: ~openGames(1)
|
|
||||||
- id: complete
|
|
||||||
$type: hw.view.form.ButtonView
|
|
||||||
text: Complete
|
|
||||||
+onPress: ~openGames(2)
|
|
||||||
- id: network
|
|
||||||
$type: hw.view.form.ButtonView
|
|
||||||
text: Network
|
|
||||||
+onPress: ~openNetwork()
|
|
||||||
- $type: hw.view.SpriteView
|
|
||||||
geometry.width: 100%
|
|
||||||
- $type: hw.view.form.LabelView
|
- $type: hw.view.form.LabelView
|
||||||
text: $r:text:app.version
|
text: $r:text:app.version
|
||||||
geometry.position: absolute
|
geometry.position: absolute
|
||||||
geometry.hAlign: right
|
geometry.hAlign: right
|
||||||
geometry.vAlign: top
|
geometry.vAlign: top
|
||||||
- id: update
|
- id: updateButton
|
||||||
$type: hw.view.form.ButtonView
|
$type: hw.view.form.ButtonView
|
||||||
style: button.active
|
style: button.active
|
||||||
geometry.position: absolute
|
geometry.position: absolute
|
||||||
|
|||||||
@@ -1,34 +1,30 @@
|
|||||||
package ru.m.puzzlez.view.common;
|
package ru.m.puzzlez.view.common;
|
||||||
|
|
||||||
import ru.m.puzzlez.net.Network;
|
import hw.signal.Signal;
|
||||||
import hw.view.data.DataView;
|
import hw.view.data.DataView;
|
||||||
import hw.view.form.ToggleButtonView;
|
import hw.view.form.ToggleButtonView;
|
||||||
import hw.view.frame.FrameSwitcher;
|
import hw.view.frame.FrameSwitcher;
|
||||||
import hw.view.group.VGroupView;
|
import hw.view.group.VGroupView;
|
||||||
import hw.view.popup.ConfirmView;
|
import ru.m.data.DataSource.DataPage;
|
||||||
import ru.m.data.IDataSource;
|
import ru.m.data.DataSource.Page;
|
||||||
import ru.m.puzzlez.core.Id;
|
import ru.m.puzzlez.image.ImageSource;
|
||||||
import ru.m.puzzlez.source.FileSource;
|
import ru.m.puzzlez.proto.game.ImageId;
|
||||||
import ru.m.puzzlez.storage.GameStorage;
|
|
||||||
import ru.m.puzzlez.storage.ImageStorage;
|
|
||||||
import ru.m.puzzlez.view.common.PuzzleImageView;
|
|
||||||
|
|
||||||
@:template class ImageDataList extends VGroupView {
|
@:template class ImageDataList extends VGroupView {
|
||||||
|
|
||||||
public var source:IDataIndex<ImageId>;
|
public var source:ImageSource;
|
||||||
public var page:Page;
|
public var page:Page;
|
||||||
|
|
||||||
@:view("images") var imagesView:ActionDataView<ImageId, PuzzleImageView, Action>;
|
@:view("images") var imagesView:DataView<ImageId, ImageIdView>;
|
||||||
@:view("paginator") var paginatorView:PaginatorView;
|
@:view("paginator") var paginatorView:PaginatorView;
|
||||||
private var loading:LoadingWrapper;
|
private var loading:LoadingWrapper;
|
||||||
|
|
||||||
@:provide var switcher:FrameSwitcher;
|
@:provide var switcher:FrameSwitcher;
|
||||||
@:provide var gameStorage:GameStorage;
|
|
||||||
@:provide var imageStorage:ImageStorage;
|
|
||||||
@:provide var network:Network;
|
|
||||||
|
|
||||||
public var data(default, set):DataPage<ImageId>;
|
public var data(default, set):DataPage<ImageId>;
|
||||||
|
|
||||||
|
public var onImageSelect(default, null):Signal<ImageId> = new Signal();
|
||||||
|
|
||||||
private function set_data(value:DataPage<ImageId>):DataPage<ImageId> {
|
private function set_data(value:DataPage<ImageId>):DataPage<ImageId> {
|
||||||
data = value;
|
data = value;
|
||||||
imagesView.data = data.data;
|
imagesView.data = data.data;
|
||||||
@@ -39,7 +35,7 @@ import ru.m.puzzlez.view.common.PuzzleImageView;
|
|||||||
public function new() {
|
public function new() {
|
||||||
super();
|
super();
|
||||||
loading = new LoadingWrapper(imagesView);
|
loading = new LoadingWrapper(imagesView);
|
||||||
page = {index: 0, count: 6, order: [{key: "date", reverse: true}]};
|
page = {index: 0, count: 6};
|
||||||
}
|
}
|
||||||
|
|
||||||
private function pageFactory(index:Int, value:Int):ToggleButtonView {
|
private function pageFactory(index:Int, value:Int):ToggleButtonView {
|
||||||
@@ -49,40 +45,8 @@ import ru.m.puzzlez.view.common.PuzzleImageView;
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function start(imageId:ImageId):Void {
|
|
||||||
gameStorage.get(imageId).then(state -> {
|
|
||||||
if (state != null) {
|
|
||||||
switcher.change(GameFrame.ID, state);
|
|
||||||
} else {
|
|
||||||
switcher.change(PresetFrame.ID, imageId);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private function onAction(imageId:ImageId, action:Action):Void {
|
|
||||||
switch action {
|
|
||||||
case REMOVE:
|
|
||||||
var fileSource:FileSource = cast imageStorage.sources.get(FileSource.ID);
|
|
||||||
if (fileSource != null) {
|
|
||||||
ConfirmView.confirm("Delete image?").then(result -> {
|
|
||||||
if (result) {
|
|
||||||
fileSource.remove(imageId).then(_ -> refresh());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
case CLEAN:
|
|
||||||
ConfirmView.confirm("Delete state?").then(result -> {
|
|
||||||
if (result) {
|
|
||||||
gameStorage.delete(imageId).then(_ -> refresh());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
case JOIN:
|
|
||||||
// ToDo:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function refresh():Void {
|
public function refresh():Void {
|
||||||
loading.promise = source.getIndexPage(page).then(data -> this.data = data);
|
loading.promise = source.getPage(page).then(data -> this.data = data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function reset():Void {
|
public function reset():Void {
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
---
|
---
|
||||||
views:
|
views:
|
||||||
- id: images
|
- id: images
|
||||||
$type: hw.view.data.ActionDataView
|
$type: hw.view.data.DataView
|
||||||
layout:
|
layout:
|
||||||
$type: hw.view.layout.TailLayout
|
$type: hw.view.layout.TailLayout
|
||||||
rowSize: 3
|
rowSize: 3
|
||||||
margin: 5
|
margin: 5
|
||||||
vAlign: middle
|
vAlign: middle
|
||||||
geometry.stretch: true
|
geometry.stretch: true
|
||||||
factory: ~ru.m.puzzlez.view.common.PuzzleImageView.factory
|
factory: ~ru.m.puzzlez.view.common.ImageIdView.factory
|
||||||
+onDataSelect: ~start
|
+onDataSelect: ~onImageSelect.emit
|
||||||
+onDataAction: ~onAction
|
|
||||||
geometry.margin: 5
|
geometry.margin: 5
|
||||||
overflow.y: scroll
|
overflow.y: scroll
|
||||||
- id: paginator
|
- id: paginator
|
||||||
|
|||||||
30
src/app/haxe/ru/m/puzzlez/view/common/ImageIdView.hx
Normal file
30
src/app/haxe/ru/m/puzzlez/view/common/ImageIdView.hx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package ru.m.puzzlez.view.common;
|
||||||
|
|
||||||
|
import hw.view.utils.DrawUtil;
|
||||||
|
import hw.view.ImageView;
|
||||||
|
import ru.m.puzzlez.image.ImageData;
|
||||||
|
import ru.m.puzzlez.proto.game.ImageId;
|
||||||
|
|
||||||
|
class ImageIdView extends ImageView {
|
||||||
|
public var imageId(default, set):ImageId;
|
||||||
|
|
||||||
|
private function set_imageId(value:ImageId):ImageId {
|
||||||
|
imageId = value;
|
||||||
|
ImageData.fromImageId(imageId).resolve().then(data -> this.image = data);
|
||||||
|
return imageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function new(imageId:ImageId = null) {
|
||||||
|
super();
|
||||||
|
style = "view";
|
||||||
|
stretch = false;
|
||||||
|
fillType = FillType.COVER;
|
||||||
|
if (imageId != null) {
|
||||||
|
this.imageId = imageId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function factory(index:Int, value:ImageId):ImageIdView {
|
||||||
|
return new ImageIdView(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
package ru.m.puzzlez.view.common;
|
package ru.m.puzzlez.view.common;
|
||||||
|
|
||||||
|
import ru.m.data.DataSource;
|
||||||
import hw.signal.Signal;
|
import hw.signal.Signal;
|
||||||
import hw.view.data.DataView;
|
import hw.view.data.DataView;
|
||||||
import hw.view.form.ToggleButtonView;
|
import hw.view.form.ToggleButtonView;
|
||||||
import hw.view.layout.TailLayout;
|
import hw.view.layout.TailLayout;
|
||||||
import ru.m.data.IDataSource.DataPage;
|
|
||||||
|
|
||||||
enum PaginatorAction {
|
enum PaginatorAction {
|
||||||
START;
|
START;
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
package ru.m.puzzlez.view.common;
|
package ru.m.puzzlez.view.common;
|
||||||
|
|
||||||
import ru.m.puzzlez.wrap.RectangleExt;
|
|
||||||
import ru.m.puzzlez.proto.game.GameState;
|
|
||||||
import flash.display.Graphics;
|
|
||||||
import flash.display.BitmapData;
|
import flash.display.BitmapData;
|
||||||
|
import flash.display.Graphics;
|
||||||
import flash.display.Shape;
|
import flash.display.Shape;
|
||||||
import hw.view.group.GroupView;
|
import hw.view.group.GroupView;
|
||||||
|
import ru.m.puzzlez.image.ImageData;
|
||||||
|
import ru.m.puzzlez.proto.game.GameState;
|
||||||
import ru.m.puzzlez.render.part.IPartBuilder;
|
import ru.m.puzzlez.render.part.IPartBuilder;
|
||||||
import ru.m.puzzlez.render.RenderUtil;
|
import ru.m.puzzlez.render.RenderUtil;
|
||||||
import ru.m.puzzlez.storage.ImageStorage;
|
import ru.m.puzzlez.wrap.RectangleExt;
|
||||||
|
|
||||||
class PresetView extends GroupView {
|
class PresetView extends GroupView {
|
||||||
@:provide var imageStorage:ImageStorage;
|
|
||||||
@:provide static var builder:IPartBuilder;
|
@:provide static var builder:IPartBuilder;
|
||||||
|
|
||||||
public var scale(get, set):Float;
|
public var scale(get, set):Float;
|
||||||
@@ -33,7 +32,7 @@ class PresetView extends GroupView {
|
|||||||
state = value;
|
state = value;
|
||||||
this.image = null;
|
this.image = null;
|
||||||
table.graphics.clear();
|
table.graphics.clear();
|
||||||
loading.promise = imageStorage.resolve(state.preset.imageId).then(image -> {
|
loading.promise = ImageData.fromImageId(state.preset.image).resolve().then(image -> {
|
||||||
this.image = RenderUtil.cropImage(image, state.preset.imageRect);
|
this.image = RenderUtil.cropImage(image, state.preset.imageRect);
|
||||||
toRedraw();
|
toRedraw();
|
||||||
toUpdate();
|
toUpdate();
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
package ru.m.puzzlez.view.common;
|
|
||||||
|
|
||||||
import ru.m.puzzlez.net.Network;
|
|
||||||
import hw.view.data.DataView;
|
|
||||||
import hw.view.form.ButtonView;
|
|
||||||
import hw.view.form.LabelView;
|
|
||||||
import hw.view.group.GroupView;
|
|
||||||
import hw.view.ImageView;
|
|
||||||
import ru.m.puzzlez.core.GameUtil;
|
|
||||||
import ru.m.puzzlez.core.Id;
|
|
||||||
import ru.m.puzzlez.source.FileSource;
|
|
||||||
import ru.m.puzzlez.storage.GameStorage;
|
|
||||||
import ru.m.puzzlez.storage.ImageStorage;
|
|
||||||
|
|
||||||
enum Action {
|
|
||||||
CLEAN;
|
|
||||||
REMOVE;
|
|
||||||
JOIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
@:template class PuzzleImageView extends GroupView {
|
|
||||||
|
|
||||||
public var imageId(default, set):ImageId;
|
|
||||||
|
|
||||||
private function set_imageId(value:ImageId):ImageId {
|
|
||||||
if (imageId != value) {
|
|
||||||
imageId = value;
|
|
||||||
loading.promise = imageStorage.resolve(imageId, true).then(data -> imageView.image = data);
|
|
||||||
}
|
|
||||||
return imageId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public var text(default, set):String;
|
|
||||||
|
|
||||||
private function set_text(value:String):String {
|
|
||||||
if (text != value) {
|
|
||||||
text = value;
|
|
||||||
labelView.text = text;
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
|
|
||||||
@:view("image") var imageView:ImageView;
|
|
||||||
@:view("label") var labelView:LabelView;
|
|
||||||
@:view("clean") var cleanButton:ButtonView;
|
|
||||||
@:view("remove") var removeButton:ButtonView;
|
|
||||||
@:view("join") var joinButton:ButtonView;
|
|
||||||
@:provide static var imageStorage:ImageStorage;
|
|
||||||
@:provide static var gameStorage:GameStorage;
|
|
||||||
@:provide static var network:Network;
|
|
||||||
private var loading:LoadingWrapper;
|
|
||||||
|
|
||||||
public function new() {
|
|
||||||
super();
|
|
||||||
cleanButton.visible = false;
|
|
||||||
removeButton.visible = false;
|
|
||||||
joinButton.visible = false;
|
|
||||||
loading = new LoadingWrapper(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function emit(action:Action):Void {
|
|
||||||
var dataView:ActionDataView<Dynamic, PuzzleImageView, Action> = Std.instance(parent, ActionDataView);
|
|
||||||
if (dataView != null) {
|
|
||||||
var index = dataView.dataViews.indexOf(this);
|
|
||||||
dataView.onDataAction.emit(dataView.data[index], action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function factory(index:Int, imageId:ImageId):PuzzleImageView {
|
|
||||||
var result = new PuzzleImageView();
|
|
||||||
result.imageId = imageId;
|
|
||||||
gameStorage.get(imageId).then(state -> {
|
|
||||||
if (state != null) {
|
|
||||||
var progress = GameUtil.calcProgress(state);
|
|
||||||
result.text = '${progress.complete}/${progress.total}';
|
|
||||||
result.cleanButton.visible = true;
|
|
||||||
} else if (imageId.source == FileSource.ID) {
|
|
||||||
result.removeButton.visible = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// ToDo:
|
|
||||||
result.joinButton.visible = false;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
---
|
|
||||||
style: view
|
|
||||||
views:
|
|
||||||
- id: image
|
|
||||||
$type: hw.view.ImageView
|
|
||||||
geometry.stretch: true
|
|
||||||
stretch: false
|
|
||||||
fillType: COVER
|
|
||||||
- id: label
|
|
||||||
$type: hw.view.form.LabelView
|
|
||||||
- id: remove
|
|
||||||
$type: hw.view.form.ButtonView
|
|
||||||
propagation: false
|
|
||||||
style: icon.control.small.close.red
|
|
||||||
+onPress: ~emit(Action.REMOVE)
|
|
||||||
- id: clean
|
|
||||||
$type: hw.view.form.ButtonView
|
|
||||||
propagation: false
|
|
||||||
style: icon.control.small.close.orange
|
|
||||||
+onPress: ~emit(Action.CLEAN)
|
|
||||||
- id: join
|
|
||||||
$type: hw.view.form.ButtonView
|
|
||||||
propagation: false
|
|
||||||
style: icon.control.small.close.green
|
|
||||||
+onPress: ~emit(Action.JOIN)
|
|
||||||
@@ -10,9 +10,9 @@ import hw.view.utils.DrawUtil;
|
|||||||
import openfl.Assets;
|
import openfl.Assets;
|
||||||
import openfl.utils.AssetType;
|
import openfl.utils.AssetType;
|
||||||
import promhx.Promise;
|
import promhx.Promise;
|
||||||
import ru.m.puzzlez.core.Id.ImageId;
|
import ru.m.puzzlez.proto.game.ImageId;
|
||||||
import ru.m.puzzlez.render.Background;
|
import ru.m.puzzlez.render.Background;
|
||||||
import ru.m.puzzlez.storage.ImageStorage;
|
// import ru.m.puzzlez.settings.ImageStorage;
|
||||||
|
|
||||||
@:singleton @:template class BackgroundPopup extends PopupView<Background> {
|
@:singleton @:template class BackgroundPopup extends PopupView<Background> {
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ import ru.m.puzzlez.storage.ImageStorage;
|
|||||||
|
|
||||||
public var selected(default, set):Background;
|
public var selected(default, set):Background;
|
||||||
|
|
||||||
@:provide static var imageStorage:ImageStorage;
|
// @:provide static var imageStorage:ImageStorage;
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
super();
|
super();
|
||||||
@@ -50,7 +50,7 @@ import ru.m.puzzlez.storage.ImageStorage;
|
|||||||
var textures = [];
|
var textures = [];
|
||||||
for (name in Assets.list(AssetType.IMAGE)) {
|
for (name in Assets.list(AssetType.IMAGE)) {
|
||||||
if (StringTools.startsWith(name, 'resources/texture')) {
|
if (StringTools.startsWith(name, 'resources/texture')) {
|
||||||
textures.push(new ImageId('asset', name));
|
textures.push(new ImageId().setSource('asset').setId(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
texturesView.data = textures;
|
texturesView.data = textures;
|
||||||
@@ -64,10 +64,10 @@ import ru.m.puzzlez.storage.ImageStorage;
|
|||||||
case COLOR(color):
|
case COLOR(color):
|
||||||
selectedView.skin = Skin.color(color);
|
selectedView.skin = Skin.color(color);
|
||||||
case IMAGE(id):
|
case IMAGE(id):
|
||||||
imageStorage.resolve(id).then(result -> {
|
/*imageStorage.resolve(id).then(result -> {
|
||||||
selectedView.skin = Skin.bitmap(result, REPEAT);
|
selectedView.skin = Skin.bitmap(result, REPEAT);
|
||||||
selectedView.toRedraw();
|
selectedView.toRedraw();
|
||||||
});
|
});*/
|
||||||
}
|
}
|
||||||
selectedView.toRedraw();
|
selectedView.toRedraw();
|
||||||
return selected;
|
return selected;
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
package ru.m.puzzlez.core;
|
|
||||||
|
|
||||||
typedef SourceId = String;
|
|
||||||
|
|
||||||
abstract ImageId({source:SourceId, id:String}) {
|
|
||||||
public var source(get, never):SourceId;
|
|
||||||
|
|
||||||
private inline function get_source():SourceId return this.source;
|
|
||||||
|
|
||||||
public var id(get, never):String;
|
|
||||||
|
|
||||||
private inline function get_id():String return this.id;
|
|
||||||
|
|
||||||
public function new(source:SourceId, id:String) {
|
|
||||||
this = {source: source, id: id};
|
|
||||||
}
|
|
||||||
|
|
||||||
@:from public static function fromString(value:String):ImageId {
|
|
||||||
var args = value.split("_");
|
|
||||||
return new ImageId(args[0], args[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@:to public function toString():String {
|
|
||||||
return '${this.source}_${this.id}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef PlayerId = String;
|
|
||||||
|
|
||||||
typedef PartId = Int;
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package ru.m.puzzlez.core;
|
|
||||||
|
|
||||||
import ru.m.data.IDataSource;
|
|
||||||
import ru.m.puzzlez.core.Id;
|
|
||||||
|
|
||||||
typedef ImageListSource = {
|
|
||||||
var title:String;
|
|
||||||
var source:IDataIndex<ImageId>;
|
|
||||||
@:optional var filter:Filter;
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package ru.m.puzzlez.core;
|
package ru.m.puzzlez.image;
|
||||||
|
|
||||||
import ru.m.puzzlez.proto.event.GameComplete;
|
import ru.m.puzzlez.proto.event.GameComplete;
|
||||||
import ru.m.puzzlez.proto.event.GameChange;
|
import ru.m.puzzlez.proto.event.GameChange;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package ru.m.puzzlez.core;
|
package ru.m.puzzlez.image;
|
||||||
|
|
||||||
import ru.m.puzzlez.proto.core.Point;
|
|
||||||
import hw.signal.Signal;
|
import hw.signal.Signal;
|
||||||
|
import ru.m.puzzlez.proto.core.Point;
|
||||||
import ru.m.puzzlez.proto.event.gameaction.Action;
|
import ru.m.puzzlez.proto.event.gameaction.Action;
|
||||||
import ru.m.puzzlez.proto.event.GameAction;
|
import ru.m.puzzlez.proto.event.GameAction;
|
||||||
import ru.m.puzzlez.proto.event.GameEvent;
|
import ru.m.puzzlez.proto.event.GameEvent;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package ru.m.puzzlez.core;
|
package ru.m.puzzlez.image;
|
||||||
|
|
||||||
import ru.m.puzzlez.core.Id;
|
import ru.m.puzzlez.proto.game.ImageId;
|
||||||
import ru.m.puzzlez.core.Side;
|
import ru.m.puzzlez.image.Side;
|
||||||
import ru.m.puzzlez.proto.core.IntPoint;
|
import ru.m.puzzlez.proto.core.IntPoint;
|
||||||
import ru.m.puzzlez.proto.core.Point;
|
import ru.m.puzzlez.proto.core.Point;
|
||||||
import ru.m.puzzlez.proto.core.Rectangle;
|
import ru.m.puzzlez.proto.core.Rectangle;
|
||||||
@@ -72,7 +72,7 @@ class GameUtil {
|
|||||||
return Math.isNaN(size) ? maxValue : size < 1 ? 1 : size > maxValue ? maxValue : size;
|
return Math.isNaN(size) ? maxValue : size < 1 ? 1 : size > maxValue ? maxValue : size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function buildPreset(imageId:ImageId, width:Int = 8, height:Int = MAX_SIZE):GamePreset {
|
public static function buildPreset(image: ImageId, width:Int = 8, height:Int = MAX_SIZE):GamePreset {
|
||||||
width = normilizeSize(width);
|
width = normilizeSize(width);
|
||||||
height = normilizeSize(height);
|
height = normilizeSize(height);
|
||||||
var offsetX = 500;
|
var offsetX = 500;
|
||||||
@@ -90,7 +90,7 @@ class GameUtil {
|
|||||||
.setWidth(imageRect.width + offsetX * 2)
|
.setWidth(imageRect.width + offsetX * 2)
|
||||||
.setHeight(imageRect.height + offsetY * 2);
|
.setHeight(imageRect.height + offsetY * 2);
|
||||||
return new GamePreset()
|
return new GamePreset()
|
||||||
.setImageId(imageId)
|
.setImage(image)
|
||||||
.setGrid(new IntPoint().setX(width).setY(height))
|
.setGrid(new IntPoint().setX(width).setY(height))
|
||||||
.setTableRect(tableRect)
|
.setTableRect(tableRect)
|
||||||
.setImageRect(imageRect);
|
.setImageRect(imageRect);
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package ru.m.puzzlez.core;
|
package ru.m.puzzlez.image;
|
||||||
|
|
||||||
import hw.signal.Signal;
|
import hw.signal.Signal;
|
||||||
import ru.m.puzzlez.proto.event.GameAction;
|
import ru.m.puzzlez.proto.event.GameAction;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package ru.m.puzzlez.core;
|
package ru.m.puzzlez.image;
|
||||||
|
|
||||||
enum Side {
|
enum Side {
|
||||||
TOP;
|
TOP;
|
||||||
@@ -4,6 +4,11 @@ import "core.proto";
|
|||||||
|
|
||||||
package ru.m.puzzlez.proto.game;
|
package ru.m.puzzlez.proto.game;
|
||||||
|
|
||||||
|
message ImageId {
|
||||||
|
string source = 1;
|
||||||
|
string id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
enum BoundType {
|
enum BoundType {
|
||||||
NONE = 0;
|
NONE = 0;
|
||||||
OUT = 1;
|
OUT = 1;
|
||||||
@@ -39,7 +44,7 @@ message Part {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message GamePreset {
|
message GamePreset {
|
||||||
string imageId = 1;
|
ImageId image = 1;
|
||||||
ru.m.puzzlez.proto.core.IntPoint grid = 2;
|
ru.m.puzzlez.proto.core.IntPoint grid = 2;
|
||||||
ru.m.puzzlez.proto.core.Rectangle tableRect = 3;
|
ru.m.puzzlez.proto.core.Rectangle tableRect = 3;
|
||||||
ru.m.puzzlez.proto.core.Rectangle imageRect = 4;
|
ru.m.puzzlez.proto.core.Rectangle imageRect = 4;
|
||||||
@@ -53,9 +58,9 @@ enum GameStatus {
|
|||||||
|
|
||||||
message GameState {
|
message GameState {
|
||||||
string id = 1;
|
string id = 1;
|
||||||
GameStatus status = 2;
|
GameStatus status = 3;
|
||||||
GamePreset preset = 3;
|
GamePreset preset = 4;
|
||||||
repeated ru.m.puzzlez.proto.core.User users = 4;
|
repeated ru.m.puzzlez.proto.core.User users = 5;
|
||||||
repeated Part parts = 5;
|
repeated Part parts = 6;
|
||||||
bool online = 6;
|
bool online = 7;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,11 +23,13 @@ message AuthResponse {
|
|||||||
ru.m.puzzlez.proto.core.User user = 1;
|
ru.m.puzzlez.proto.core.User user = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message GameCreateRequest {
|
||||||
|
bytes image = 1;
|
||||||
|
ru.m.puzzlez.proto.game.GamePreset preset = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message GameJoinRequest {
|
message GameJoinRequest {
|
||||||
oneof content {
|
string gameId = 1;
|
||||||
ru.m.puzzlez.proto.game.GamePreset preset = 1;
|
|
||||||
string gameId = 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message GameJoinResponse {
|
message GameJoinResponse {
|
||||||
@@ -67,6 +69,7 @@ message Request {
|
|||||||
oneof content {
|
oneof content {
|
||||||
AuthRequest auth = 10;
|
AuthRequest auth = 10;
|
||||||
GameListRequest list = 20;
|
GameListRequest list = 20;
|
||||||
|
GameCreateRequest create = 25;
|
||||||
GameJoinRequest join = 30;
|
GameJoinRequest join = 30;
|
||||||
GameLeaveRequest leave = 40;
|
GameLeaveRequest leave = 40;
|
||||||
GameActionRequest action = 100;
|
GameActionRequest action = 100;
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
package ru.m.puzzlez;
|
package ru.m.puzzlez;
|
||||||
|
|
||||||
|
import ru.m.puzzlez.proto.pack.GameCreateRequest;
|
||||||
import ru.m.puzzlez.proto.pack.GameListResponse;
|
import ru.m.puzzlez.proto.pack.GameListResponse;
|
||||||
import ru.m.puzzlez.proto.pack.GameListRequest;
|
import ru.m.puzzlez.proto.pack.GameListRequest;
|
||||||
import hw.connect.session.ProtoSession;
|
import hw.connect.session.ProtoSession;
|
||||||
import hw.log.BaseLogger.LoggerUtil;
|
import hw.log.BaseLogger.LoggerUtil;
|
||||||
import ru.m.puzzlez.core.Game;
|
import ru.m.puzzlez.image.Game;
|
||||||
import ru.m.puzzlez.core.GameUtil;
|
import ru.m.puzzlez.image.GameUtil;
|
||||||
import ru.m.puzzlez.proto.core.User;
|
import ru.m.puzzlez.proto.core.User;
|
||||||
import ru.m.puzzlez.proto.event.GameAction;
|
import ru.m.puzzlez.proto.event.GameAction;
|
||||||
import ru.m.puzzlez.proto.event.GameEvent;
|
import ru.m.puzzlez.proto.event.GameEvent;
|
||||||
import ru.m.puzzlez.proto.event.gameplayer.GamePlayerAction;
|
import ru.m.puzzlez.proto.event.gameplayer.GamePlayerAction;
|
||||||
import ru.m.puzzlez.proto.event.GamePlayer;
|
import ru.m.puzzlez.proto.event.GamePlayer;
|
||||||
import ru.m.puzzlez.proto.game.GamePreset;
|
|
||||||
import ru.m.puzzlez.proto.pack.AuthRequest;
|
import ru.m.puzzlez.proto.pack.AuthRequest;
|
||||||
import ru.m.puzzlez.proto.pack.AuthResponse;
|
import ru.m.puzzlez.proto.pack.AuthResponse;
|
||||||
import ru.m.puzzlez.proto.pack.ErrorResponse;
|
import ru.m.puzzlez.proto.pack.ErrorResponse;
|
||||||
@@ -74,8 +74,8 @@ class GameSession extends ProtoSession<Response, Request> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function create(preset:GamePreset):Void {
|
private function create(create:GameCreateRequest):Void {
|
||||||
var game = new Game(GameUtil.buildState(preset).setOnline(true));
|
var game = new Game(GameUtil.buildState(create.preset).setOnline(true));
|
||||||
game.start();
|
game.start();
|
||||||
gamesById.set(game.state.id, game);
|
gamesById.set(game.state.id, game);
|
||||||
join(game.state.id);
|
join(game.state.id);
|
||||||
@@ -111,12 +111,10 @@ class GameSession extends ProtoSession<Response, Request> {
|
|||||||
auth(request.auth);
|
auth(request.auth);
|
||||||
} else if (request.hasList()) {
|
} else if (request.hasList()) {
|
||||||
list(request.list);
|
list(request.list);
|
||||||
|
} else if (request.hasCreate()) {
|
||||||
|
create(request.create);
|
||||||
} else if (request.hasJoin()) {
|
} else if (request.hasJoin()) {
|
||||||
if (request.join.hasPreset()) {
|
join(request.join.gameId);
|
||||||
create(request.join.preset);
|
|
||||||
} else if (request.join.hasGameId()) {
|
|
||||||
join(request.join.gameId);
|
|
||||||
}
|
|
||||||
} else if (request.hasLeave()) {
|
} else if (request.hasLeave()) {
|
||||||
leave();
|
leave();
|
||||||
} else if (request.hasAction()) {
|
} else if (request.hasAction()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user