[editor] support level pack edit
This commit is contained in:
18
gulpfile.js
18
gulpfile.js
@@ -1,11 +1,8 @@
|
|||||||
const gulp = require('gulp');
|
const gulp = require('gulp');
|
||||||
const zip = require('gulp-zip');
|
|
||||||
const foreach = require('gulp-foreach');
|
|
||||||
const gulpClean = require('gulp-clean');
|
const gulpClean = require('gulp-clean');
|
||||||
const Config = require('./config.json');
|
const Config = require('./config.json');
|
||||||
const packageInfo = require('./package.json');
|
const packageInfo = require('./package.json');
|
||||||
const {System, Sdk, Haxe, Project} = require('gulp-haxetool');
|
const {System, Sdk, Haxe, Project} = require('gulp-haxetool');
|
||||||
const path = require('path');
|
|
||||||
const dateformat = require('dateformat');
|
const dateformat = require('dateformat');
|
||||||
const argv = require('yargs').argv;
|
const argv = require('yargs').argv;
|
||||||
const publish = require('./tasks/gulp-publish');
|
const publish = require('./tasks/gulp-publish');
|
||||||
@@ -26,19 +23,6 @@ exports.generate = function generate() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.levels = function levels() {
|
|
||||||
return gulp.src("./src/common/level/*").pipe(foreach(function (stream, file) {
|
|
||||||
const type = file.path.substr(file.path.lastIndexOf(path.sep) + 1);
|
|
||||||
gulp.src("./src/common/level/" + type + "/*").pipe(foreach(function (stream, file) {
|
|
||||||
const name = file.path.substr(file.path.lastIndexOf(path.sep) + 1);
|
|
||||||
gulp.src("./src/common/level/" + type + "/" + name + "/*")
|
|
||||||
.pipe(zip(`${type}_${name}.zip`))
|
|
||||||
.pipe(gulp.dest("./target/levels"));
|
|
||||||
}));
|
|
||||||
return stream;
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* base config
|
* base config
|
||||||
*/
|
*/
|
||||||
@@ -59,7 +43,6 @@ const config = new Project.Config({
|
|||||||
],
|
],
|
||||||
assets: [
|
assets: [
|
||||||
'src/common/resources',
|
'src/common/resources',
|
||||||
'target/levels'
|
|
||||||
],
|
],
|
||||||
flags: [
|
flags: [
|
||||||
//'proto_debug',
|
//'proto_debug',
|
||||||
@@ -168,7 +151,6 @@ module.exports.publish = publish(packageInfo.name, packageInfo.version, Config.P
|
|||||||
*/
|
*/
|
||||||
const defaultSeries = [
|
const defaultSeries = [
|
||||||
exports.clean,
|
exports.clean,
|
||||||
exports.levels,
|
|
||||||
exports.generate,
|
exports.generate,
|
||||||
module.exports['client:flash:build'],
|
module.exports['client:flash:build'],
|
||||||
module.exports['client:flash:html'],
|
module.exports['client:flash:html'],
|
||||||
|
|||||||
1063
package-lock.json
generated
1063
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -7,9 +7,7 @@
|
|||||||
"gulp": "^4.0.0",
|
"gulp": "^4.0.0",
|
||||||
"gulp-add": "0.0.2",
|
"gulp-add": "0.0.2",
|
||||||
"gulp-clean": "^0.4.0",
|
"gulp-clean": "^0.4.0",
|
||||||
"gulp-foreach": "^0.1.0",
|
|
||||||
"gulp-haxetool": "0.1.0",
|
"gulp-haxetool": "0.1.0",
|
||||||
"gulp-zip": "^5.0.0",
|
|
||||||
"yargs": "^13.2.4"
|
"yargs": "^13.2.4"
|
||||||
},
|
},
|
||||||
"haxeDependencies": {
|
"haxeDependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package ru.m.tankz.bundle;
|
package ru.m.tankz.bundle;
|
||||||
|
|
||||||
import openfl.Assets;
|
import openfl.Assets;
|
||||||
|
import openfl.utils.AssetType;
|
||||||
import ru.m.tankz.config.Config;
|
import ru.m.tankz.config.Config;
|
||||||
import ru.m.tankz.Type;
|
import ru.m.tankz.Type;
|
||||||
import ru.m.tankz.util.LevelUtil;
|
import ru.m.tankz.util.LevelUtil;
|
||||||
@@ -12,7 +13,7 @@ class LevelBundle implements ILevelBundle {
|
|||||||
public function new() {}
|
public function new() {}
|
||||||
|
|
||||||
private function resolve(id:PackId):LevelPack {
|
private function resolve(id:PackId):LevelPack {
|
||||||
var bytes = Assets.getBytes('levels/${id}.zip');
|
var bytes = Assets.getBytes('resources/level/${id}.zip');
|
||||||
return {
|
return {
|
||||||
id: id,
|
id: id,
|
||||||
data: LevelUtil.unpack(bytes).map(function(level) {
|
data: LevelUtil.unpack(bytes).map(function(level) {
|
||||||
@@ -28,4 +29,14 @@ class LevelBundle implements ILevelBundle {
|
|||||||
}
|
}
|
||||||
return _cache.get(id);
|
return _cache.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function list():Array<PackId> {
|
||||||
|
var result = [];
|
||||||
|
for (path in Assets.list(AssetType.BINARY)) {
|
||||||
|
if (StringTools.startsWith(path, "resources/level")) {
|
||||||
|
result.push(PackId.fromString(path.split("/").pop().split(".").shift()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class LocalGame extends GameRunner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (humansTeams.length == 1 && result.winner == humansTeams[0]) {
|
if (humansTeams.length == 1 && result.winner == humansTeams[0]) {
|
||||||
var progress = gameStorage.get(new PackId(result.state.type));
|
var progress = gameStorage.get(result.level.packId);
|
||||||
progress.completeLevel(result.level.id, result.state.presetId);
|
progress.completeLevel(result.level.id, result.state.presetId);
|
||||||
gameStorage.set(progress);
|
gameStorage.set(progress);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import ru.m.tankz.game.GameState;
|
|||||||
import ru.m.tankz.storage.GameStorage;
|
import ru.m.tankz.storage.GameStorage;
|
||||||
import ru.m.tankz.Type.PackId;
|
import ru.m.tankz.Type.PackId;
|
||||||
|
|
||||||
|
using ru.m.tankz.view.ViewUtil;
|
||||||
|
|
||||||
@:template class LevelFrame extends FrameView<PackId> {
|
@:template class LevelFrame extends FrameView<PackId> {
|
||||||
public static inline var ID = "level";
|
public static inline var ID = "level";
|
||||||
|
|
||||||
@@ -35,7 +37,7 @@ import ru.m.tankz.Type.PackId;
|
|||||||
}
|
}
|
||||||
|
|
||||||
override public function onShow(data:PackId):Void {
|
override public function onShow(data:PackId):Void {
|
||||||
header.text = data.type;
|
header.text = data.toPackLabel();
|
||||||
pack = levelBundle.get(data);
|
pack = levelBundle.get(data);
|
||||||
levels.data = pack.data;
|
levels.data = pack.data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package ru.m.tankz.view;
|
package ru.m.tankz.view;
|
||||||
|
|
||||||
|
import haxework.view.data.DataView;
|
||||||
import haxework.view.form.ButtonView;
|
import haxework.view.form.ButtonView;
|
||||||
import haxework.view.form.LabelView;
|
import haxework.view.form.LabelView;
|
||||||
import haxework.view.frame.FrameSwitcher;
|
import haxework.view.frame.FrameSwitcher;
|
||||||
import haxework.view.frame.FrameView;
|
import haxework.view.frame.FrameView;
|
||||||
|
import ru.m.tankz.bundle.ILevelBundle;
|
||||||
import ru.m.tankz.game.GameInit;
|
import ru.m.tankz.game.GameInit;
|
||||||
import ru.m.tankz.game.GameState;
|
import ru.m.tankz.game.GameState;
|
||||||
import ru.m.tankz.network.NetworkManager;
|
import ru.m.tankz.network.NetworkManager;
|
||||||
@@ -12,15 +14,19 @@ import ru.m.tankz.view.network.RoomFrame;
|
|||||||
import ru.m.tankz.view.network.RoomListFrame;
|
import ru.m.tankz.view.network.RoomListFrame;
|
||||||
import ru.m.tankz.view.popup.LoginPopup;
|
import ru.m.tankz.view.popup.LoginPopup;
|
||||||
|
|
||||||
|
using ru.m.tankz.view.ViewUtil;
|
||||||
|
|
||||||
@:template class MenuFrame extends FrameView<Dynamic> {
|
@:template class MenuFrame extends FrameView<Dynamic> {
|
||||||
|
|
||||||
public static var ID(default, never):String = "menu";
|
public static var ID(default, never):String = "menu";
|
||||||
|
|
||||||
@:provide var gameInit:GameInit;
|
@:provide static var gameInit:GameInit;
|
||||||
@:provide var switcher:FrameSwitcher;
|
@:provide static var switcher:FrameSwitcher;
|
||||||
@:provide var network:NetworkManager;
|
@:provide static var network:NetworkManager;
|
||||||
@:provide var appUpdater:Updater;
|
@:provide static var appUpdater:Updater;
|
||||||
|
@:provide static var levelBundle:ILevelBundle;
|
||||||
|
|
||||||
|
@:view var packs:DataView<PackId, ButtonView>;
|
||||||
@:view var username:LabelView;
|
@:view var username:LabelView;
|
||||||
@:view("login") var loginButton:ButtonView;
|
@:view("login") var loginButton:ButtonView;
|
||||||
@:view("logout") var logoutButton:ButtonView;
|
@:view("logout") var logoutButton:ButtonView;
|
||||||
@@ -40,6 +46,9 @@ import ru.m.tankz.view.popup.LoginPopup;
|
|||||||
updateButton.text = 'Update ${appUpdater.bundle.version}';
|
updateButton.text = 'Update ${appUpdater.bundle.version}';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
var list = levelBundle.list();
|
||||||
|
list.sort(function(a:PackId, b:PackId) return a.toPackLabel() > b.toPackLabel() ? 1 : -1);
|
||||||
|
packs.data = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
override public function onHide():Void {
|
override public function onHide():Void {
|
||||||
@@ -47,9 +56,16 @@ import ru.m.tankz.view.popup.LoginPopup;
|
|||||||
network.stateSignal.disconnect(onConnectionState);
|
network.stateSignal.disconnect(onConnectionState);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function startGame(type:GameType):Void {
|
private function packButtonFactory(index:Int, packId:PackId):ButtonView {
|
||||||
gameInit = LOCAL({state: new GameState(type), level: null});
|
var result = new ButtonView();
|
||||||
switcher.change(LevelFrame.ID, new PackId(type));
|
result.style = "button.menu";
|
||||||
|
result.text = packId.toPackLabel();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function startGame(packId:PackId):Void {
|
||||||
|
gameInit = LOCAL({state: new GameState(packId.type), level: null});
|
||||||
|
switcher.change(LevelFrame.ID, packId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function startNetwork():Void {
|
private function startNetwork():Void {
|
||||||
|
|||||||
@@ -1,79 +1,74 @@
|
|||||||
---
|
---
|
||||||
views:
|
views:
|
||||||
- $type: haxework.view.group.VGroupView
|
- $type: haxework.view.group.VGroupView
|
||||||
style: container
|
style: container
|
||||||
overflow.y: scroll
|
overflow.y: scroll
|
||||||
views:
|
views:
|
||||||
- $type: haxework.view.group.VGroupView
|
- $type: haxework.view.group.VGroupView
|
||||||
layout.margin: 10
|
layout.margin: 10
|
||||||
layout.hAlign: center
|
layout.hAlign: center
|
||||||
views:
|
views:
|
||||||
- $type: haxework.view.form.LabelView
|
- $type: haxework.view.form.LabelView
|
||||||
text: Tank'z
|
text: Tank'z
|
||||||
style: font
|
style: font
|
||||||
font.size: 100
|
font.size: 100
|
||||||
geometry.margin.bottom: 30
|
geometry.margin.bottom: 30
|
||||||
- $type: haxework.view.form.ButtonView
|
- id: packs
|
||||||
style: button.menu
|
$type: haxework.view.data.DataView
|
||||||
+onPress: ~startGame('classic')
|
layout:
|
||||||
text: Classic
|
$type: haxework.view.layout.VerticalLayout
|
||||||
- $type: haxework.view.form.ButtonView
|
margin: 10
|
||||||
style: button.menu
|
factory: ~packButtonFactory
|
||||||
+onPress: ~startGame('dota')
|
+onDataSelect: ~startGame
|
||||||
text: DotA
|
|
||||||
- $type: haxework.view.form.ButtonView
|
|
||||||
style: button.menu
|
|
||||||
+onPress: ~startGame('death')
|
|
||||||
text: DeathMatch
|
|
||||||
- $type: haxework.view.SpriteView
|
|
||||||
style: line
|
|
||||||
geometry.width: 250
|
|
||||||
geometry.margin: [0, 10]
|
|
||||||
visible: false
|
|
||||||
- $type: haxework.view.form.ButtonView
|
|
||||||
style: button.menu
|
|
||||||
+onPress: ~switcher.change('record')
|
|
||||||
text: Records
|
|
||||||
visible: false
|
|
||||||
- id: network
|
|
||||||
$type: haxework.view.form.ButtonView
|
|
||||||
style: button.menu
|
|
||||||
+onPress: ~startNetwork()
|
|
||||||
text: Network
|
|
||||||
visible: false
|
|
||||||
- $type: haxework.view.form.LabelView
|
|
||||||
geometry.hAlign: right
|
|
||||||
geometry.vAlign: top
|
|
||||||
geometry.position: absolute
|
|
||||||
geometry.margin: [0, 20, 20, 0]
|
|
||||||
style: text.box
|
|
||||||
text: $r:text:version
|
|
||||||
- $type: haxework.view.group.HGroupView
|
|
||||||
style: panel
|
|
||||||
layout.margin: 10
|
|
||||||
views:
|
|
||||||
- id: settings
|
|
||||||
$type: haxework.view.form.ButtonView
|
|
||||||
style: button.settings
|
|
||||||
+onPress: ~switcher.change('settings')
|
|
||||||
- $type: haxework.view.SpriteView
|
- $type: haxework.view.SpriteView
|
||||||
geometry.width: 50%
|
style: line
|
||||||
- id: username
|
geometry.width: 250
|
||||||
$type: haxework.view.form.LabelView
|
geometry.margin: [0, 10]
|
||||||
style: text
|
|
||||||
- id: login
|
|
||||||
$type: haxework.view.form.ButtonView
|
|
||||||
style: button.login
|
|
||||||
+onPress: ~login()
|
|
||||||
- id: logout
|
|
||||||
$type: haxework.view.form.ButtonView
|
|
||||||
style: button.logout
|
|
||||||
+onPress: ~logout()
|
|
||||||
visible: false
|
visible: false
|
||||||
- $type: haxework.view.SpriteView
|
- $type: haxework.view.form.ButtonView
|
||||||
geometry.width: 50%
|
style: button.menu
|
||||||
- id: update
|
+onPress: ~switcher.change('record')
|
||||||
$type: haxework.view.form.ButtonView
|
text: Records
|
||||||
style: button.active
|
|
||||||
+onPress: ~appUpdate()
|
|
||||||
visible: false
|
visible: false
|
||||||
|
- id: network
|
||||||
|
$type: haxework.view.form.ButtonView
|
||||||
|
style: button.menu
|
||||||
|
+onPress: ~startNetwork()
|
||||||
|
text: Network
|
||||||
|
visible: false
|
||||||
|
- $type: haxework.view.form.LabelView
|
||||||
|
geometry.hAlign: right
|
||||||
|
geometry.vAlign: top
|
||||||
|
geometry.position: absolute
|
||||||
|
geometry.margin: [0, 20, 20, 0]
|
||||||
|
style: text.box
|
||||||
|
text: $r:text:version
|
||||||
|
- $type: haxework.view.group.HGroupView
|
||||||
|
style: panel
|
||||||
|
layout.margin: 10
|
||||||
|
views:
|
||||||
|
- id: settings
|
||||||
|
$type: haxework.view.form.ButtonView
|
||||||
|
style: button.settings
|
||||||
|
+onPress: ~switcher.change('settings')
|
||||||
|
- $type: haxework.view.SpriteView
|
||||||
|
geometry.width: 50%
|
||||||
|
- id: username
|
||||||
|
$type: haxework.view.form.LabelView
|
||||||
|
style: text
|
||||||
|
- id: login
|
||||||
|
$type: haxework.view.form.ButtonView
|
||||||
|
style: button.login
|
||||||
|
+onPress: ~login()
|
||||||
|
- id: logout
|
||||||
|
$type: haxework.view.form.ButtonView
|
||||||
|
style: button.logout
|
||||||
|
+onPress: ~logout()
|
||||||
|
visible: false
|
||||||
|
- $type: haxework.view.SpriteView
|
||||||
|
geometry.width: 50%
|
||||||
|
- id: update
|
||||||
|
$type: haxework.view.form.ButtonView
|
||||||
|
style: button.active
|
||||||
|
+onPress: ~appUpdate()
|
||||||
|
visible: false
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package ru.m.tankz.view;
|
package ru.m.tankz.view;
|
||||||
|
|
||||||
|
import ru.m.tankz.Type.PackId;
|
||||||
import openfl.Assets;
|
import openfl.Assets;
|
||||||
import ru.m.control.DeviceAction;
|
import ru.m.control.DeviceAction;
|
||||||
import ru.m.tankz.config.Config;
|
import ru.m.tankz.config.Config;
|
||||||
@@ -40,6 +41,10 @@ class ViewUtil {
|
|||||||
return result.join(oneline ? " " : "\n");
|
return result.join(oneline ? " " : "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function toPackLabel(packId:PackId):String {
|
||||||
|
return packId.name != PackId.DEFAULT ? '${packId.type} #${packId.name}' : packId.type;
|
||||||
|
}
|
||||||
|
|
||||||
public static function toActionLabel(action:TankAction):String {
|
public static function toActionLabel(action:TankAction):String {
|
||||||
return switch (action) {
|
return switch (action) {
|
||||||
case MOVE(d): 'MOVE_$d';
|
case MOVE(d): 'MOVE_$d';
|
||||||
|
|||||||
@@ -80,6 +80,10 @@ abstract PackId(Array<Dynamic>) {
|
|||||||
return new PackId(value[0], value[1]);
|
return new PackId(value[0], value[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@:from static public function fromString(value:String):PackId {
|
||||||
|
return fromArray(value.split("_"));
|
||||||
|
}
|
||||||
|
|
||||||
@:to public inline function toString():String {
|
@:to public inline function toString():String {
|
||||||
return '${type}_${name}';
|
return '${type}_${name}';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,4 +5,5 @@ import ru.m.tankz.Type;
|
|||||||
|
|
||||||
interface ILevelBundle {
|
interface ILevelBundle {
|
||||||
public function get(id:PackId):LevelPack;
|
public function get(id:PackId):LevelPack;
|
||||||
|
public function list():Array<PackId>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
package ru.m.tankz.util;
|
package ru.m.tankz.util;
|
||||||
|
|
||||||
|
import haxe.zip.Tools;
|
||||||
|
import haxe.io.BytesOutput;
|
||||||
|
import haxe.zip.Writer;
|
||||||
|
import flash.utils.ByteArray;
|
||||||
import haxe.io.Bytes;
|
import haxe.io.Bytes;
|
||||||
import haxe.io.BytesInput;
|
import haxe.io.BytesInput;
|
||||||
import haxe.zip.Entry;
|
import haxe.zip.Entry;
|
||||||
@@ -87,8 +91,32 @@ class LevelUtil {
|
|||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function compress(level:LevelConfig):Entry {
|
||||||
|
var content = LevelUtil.dumps(null, level);
|
||||||
|
var bytes = Bytes.ofString(content);
|
||||||
|
var crc = haxe.crypto.Crc32.make(bytes);
|
||||||
|
var result:Entry = {
|
||||||
|
fileName: '${formatLevel(level.id)}.txt',
|
||||||
|
fileSize: bytes.length,
|
||||||
|
fileTime : Date.now(),
|
||||||
|
compressed : false,
|
||||||
|
dataSize : bytes.length,
|
||||||
|
data : bytes,
|
||||||
|
crc32 : crc,
|
||||||
|
};
|
||||||
|
Tools.compress(result, 9);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static function unpack(bytes:Bytes):Array<LevelConfig> {
|
public static function unpack(bytes:Bytes):Array<LevelConfig> {
|
||||||
var files = Reader.readZip(new BytesInput(bytes));
|
var files = Reader.readZip(new BytesInput(bytes));
|
||||||
return Lambda.array(files.map(extract));
|
return Lambda.array(files.map(extract));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function pack(data:Array<LevelConfig>):Bytes {
|
||||||
|
var output = new BytesOutput();
|
||||||
|
var writer = new Writer(output);
|
||||||
|
writer.write(Lambda.list(data.map(compress)));
|
||||||
|
return output.getBytes();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
src/common/resources/level/classic_modern.zip
Normal file
BIN
src/common/resources/level/classic_modern.zip
Normal file
Binary file not shown.
BIN
src/common/resources/level/classic_standard.zip
Normal file
BIN
src/common/resources/level/classic_standard.zip
Normal file
Binary file not shown.
BIN
src/common/resources/level/death_standard.zip
Normal file
BIN
src/common/resources/level/death_standard.zip
Normal file
Binary file not shown.
BIN
src/common/resources/level/dota_standard.zip
Normal file
BIN
src/common/resources/level/dota_standard.zip
Normal file
Binary file not shown.
@@ -19,6 +19,7 @@ class Editor {
|
|||||||
@:provide static var resources:IResources;
|
@:provide static var resources:IResources;
|
||||||
@:provide static var theme:ITheme;
|
@:provide static var theme:ITheme;
|
||||||
@:provide static var switcher:FrameSwitcher;
|
@:provide static var switcher:FrameSwitcher;
|
||||||
|
@:provide static var storage:EditorStorage;
|
||||||
|
|
||||||
public static function main() {
|
public static function main() {
|
||||||
L.push(new haxework.log.TraceLogger());
|
L.push(new haxework.log.TraceLogger());
|
||||||
@@ -39,6 +40,7 @@ class Editor {
|
|||||||
|
|
||||||
Provider.setFactory(IConfigBundle, ConfigBundle);
|
Provider.setFactory(IConfigBundle, ConfigBundle);
|
||||||
Provider.setFactory(ILevelBundle, LevelBundle);
|
Provider.setFactory(ILevelBundle, LevelBundle);
|
||||||
|
storage = new EditorStorage();
|
||||||
|
|
||||||
var view = new EditorView();
|
var view = new EditorView();
|
||||||
Root.bind(view);
|
Root.bind(view);
|
||||||
|
|||||||
22
src/editor/haxe/ru/m/tankz/editor/EditorStorage.hx
Normal file
22
src/editor/haxe/ru/m/tankz/editor/EditorStorage.hx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package ru.m.tankz.editor;
|
||||||
|
|
||||||
|
import haxe.DynamicAccess;
|
||||||
|
import haxework.storage.SharedObjectStorage;
|
||||||
|
import ru.m.tankz.Type;
|
||||||
|
|
||||||
|
class EditorStorage extends SharedObjectStorage {
|
||||||
|
private static inline var VERSION = 2;
|
||||||
|
|
||||||
|
public function new() {
|
||||||
|
super('editor_${VERSION}');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function packList():Array<PackId> {
|
||||||
|
var result = [];
|
||||||
|
var data:DynamicAccess<String> = so.data;
|
||||||
|
for (id in data.keys()) {
|
||||||
|
result.push(PackId.fromString(id));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,19 +1,18 @@
|
|||||||
package ru.m.tankz.editor;
|
package ru.m.tankz.editor;
|
||||||
|
|
||||||
import promhx.Deferred;
|
|
||||||
import flash.events.ProgressEvent;
|
|
||||||
import flash.events.IOErrorEvent;
|
|
||||||
import flash.events.Event;
|
import flash.events.Event;
|
||||||
|
import flash.events.IOErrorEvent;
|
||||||
|
import flash.events.ProgressEvent;
|
||||||
import flash.net.FileReference;
|
import flash.net.FileReference;
|
||||||
|
import haxe.io.Bytes;
|
||||||
|
import promhx.Deferred;
|
||||||
import promhx.Promise;
|
import promhx.Promise;
|
||||||
|
|
||||||
|
|
||||||
typedef FileContent = {
|
typedef FileContent = {
|
||||||
var name:String;
|
var name:String;
|
||||||
var content:String;
|
var content:Bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class FileUtil {
|
class FileUtil {
|
||||||
|
|
||||||
public static function browse():Promise<FileContent> {
|
public static function browse():Promise<FileContent> {
|
||||||
@@ -30,10 +29,9 @@ class FileUtil {
|
|||||||
});
|
});
|
||||||
file.addEventListener(Event.COMPLETE, function(event:Event) {
|
file.addEventListener(Event.COMPLETE, function(event:Event) {
|
||||||
var f:FileReference = cast event.target;
|
var f:FileReference = cast event.target;
|
||||||
var data = f.data.readUTFBytes(f.data.length);
|
|
||||||
d.resolve({
|
d.resolve({
|
||||||
name: f.name,
|
name: f.name,
|
||||||
content: data
|
content: Bytes.ofData(f.data),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
file.browse();
|
file.browse();
|
||||||
@@ -42,7 +40,6 @@ class FileUtil {
|
|||||||
|
|
||||||
public static function save(content:FileContent):Void {
|
public static function save(content:FileContent):Void {
|
||||||
var file = new FileReference();
|
var file = new FileReference();
|
||||||
file.save(content.content, content.name);
|
file.save(content.content.getData(), content.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
package ru.m.tankz.editor.view;
|
package ru.m.tankz.editor.view;
|
||||||
|
|
||||||
import haxework.view.list.LabelListItem;
|
import ru.m.tankz.util.LevelUtil;
|
||||||
import haxework.view.data.DataView;
|
import haxework.view.data.DataView;
|
||||||
import haxework.view.form.InputView;
|
import haxework.view.form.InputView;
|
||||||
import haxework.view.frame.FrameSwitcher;
|
import haxework.view.frame.FrameSwitcher;
|
||||||
import haxework.view.frame.FrameView;
|
import haxework.view.frame.FrameView;
|
||||||
|
import haxework.view.list.LabelListItem;
|
||||||
import haxework.view.list.ListView;
|
import haxework.view.list.ListView;
|
||||||
import ru.m.tankz.bundle.IConfigBundle;
|
import ru.m.tankz.bundle.IConfigBundle;
|
||||||
import ru.m.tankz.config.Config;
|
import ru.m.tankz.config.Config;
|
||||||
import ru.m.tankz.editor.FileUtil;
|
|
||||||
import ru.m.tankz.editor.view.map.BrickView;
|
import ru.m.tankz.editor.view.map.BrickView;
|
||||||
import ru.m.tankz.editor.view.map.MapEditView;
|
import ru.m.tankz.editor.view.map.MapEditView;
|
||||||
import ru.m.tankz.editor.view.map.SpawnPointView;
|
import ru.m.tankz.editor.view.map.SpawnPointView;
|
||||||
import ru.m.tankz.Type;
|
import ru.m.tankz.Type;
|
||||||
import ru.m.tankz.util.LevelUtil;
|
|
||||||
|
|
||||||
using ru.m.tankz.view.ViewUtil;
|
using ru.m.tankz.view.ViewUtil;
|
||||||
|
|
||||||
@@ -24,6 +23,7 @@ using ru.m.tankz.view.ViewUtil;
|
|||||||
public var level(default, set):LevelConfig;
|
public var level(default, set):LevelConfig;
|
||||||
|
|
||||||
private var fileName:String;
|
private var fileName:String;
|
||||||
|
private var pack:LevelPack;
|
||||||
|
|
||||||
@:view var levels:ListView<LevelConfig>;
|
@:view var levels:ListView<LevelConfig>;
|
||||||
@:view var levelName:InputView;
|
@:view var levelName:InputView;
|
||||||
@@ -36,6 +36,7 @@ using ru.m.tankz.view.ViewUtil;
|
|||||||
@:provide var configBundle:IConfigBundle;
|
@:provide var configBundle:IConfigBundle;
|
||||||
@:provide var config:Config;
|
@:provide var config:Config;
|
||||||
@:provide static var switcher:FrameSwitcher;
|
@:provide static var switcher:FrameSwitcher;
|
||||||
|
@:provide static var storage:EditorStorage;
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
super(ID);
|
super(ID);
|
||||||
@@ -43,8 +44,12 @@ using ru.m.tankz.view.ViewUtil;
|
|||||||
|
|
||||||
override public function onShow(data:LevelPack):Void {
|
override public function onShow(data:LevelPack):Void {
|
||||||
super.onShow(data);
|
super.onShow(data);
|
||||||
type = data.id.type;
|
pack = data;
|
||||||
levels.data = data.data;
|
type = pack.id.type;
|
||||||
|
levels.data = pack.data;
|
||||||
|
if (pack.data.length > 0) {
|
||||||
|
level = pack.data[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function set_type(value:GameType):GameType {
|
private function set_type(value:GameType):GameType {
|
||||||
@@ -104,20 +109,14 @@ using ru.m.tankz.view.ViewUtil;
|
|||||||
updateSelected(null, point);
|
updateSelected(null, point);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function open():Void {
|
|
||||||
FileUtil.browse().then(function(content:FileContent) {
|
|
||||||
fileName = content.name;
|
|
||||||
level = LevelUtil.loads(content.content);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private function save():Void {
|
private function save():Void {
|
||||||
var data = mapView.data;
|
var data = mapView.data;
|
||||||
|
data.id = level.id;
|
||||||
|
data.packId = pack.id;
|
||||||
data.name = levelName.text;
|
data.name = levelName.text;
|
||||||
FileUtil.save({
|
pack.data[data.id] = data;
|
||||||
name: fileName,
|
levels.data = pack.data;
|
||||||
content: LevelUtil.dumps(config, data),
|
storage.write(pack.id, pack);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function applySize():Void {
|
private function applySize():Void {
|
||||||
@@ -129,4 +128,23 @@ using ru.m.tankz.view.ViewUtil;
|
|||||||
heightInput.text = Std.string(config.map.grid.height);
|
heightInput.text = Std.string(config.map.grid.height);
|
||||||
mapView.gridSize = null;
|
mapView.gridSize = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function addLevel():Void {
|
||||||
|
var level = LevelUtil.empty(config.map.grid, 0);
|
||||||
|
level.id = pack.data.length;
|
||||||
|
level.packId = pack.id;
|
||||||
|
pack.data.push(level);
|
||||||
|
levels.data = pack.data;
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function removeLevel():Void {
|
||||||
|
if (level != null) {
|
||||||
|
pack.data.remove(level);
|
||||||
|
levels.data = pack.data;
|
||||||
|
if (pack.data.length > 0) {
|
||||||
|
this.level = pack.data[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,20 @@ views:
|
|||||||
- $type: haxework.view.group.HGroupView
|
- $type: haxework.view.group.HGroupView
|
||||||
geometry.stretch: true
|
geometry.stretch: true
|
||||||
views:
|
views:
|
||||||
- id: levels
|
- $type: haxework.view.group.VGroupView
|
||||||
$type: haxework.view.list.VListView
|
|
||||||
geometry.width: 200
|
|
||||||
geometry.height: 100%
|
geometry.height: 100%
|
||||||
factory: ~levelViewFactory
|
views:
|
||||||
+onItemSelect: ~onLevelSelect
|
- id: levels
|
||||||
scroll:
|
$type: haxework.view.list.VListView
|
||||||
$type: haxework.view.list.VScrollBarView
|
geometry.width: 200
|
||||||
|
geometry.height: 100%
|
||||||
|
factory: ~levelViewFactory
|
||||||
|
+onItemSelect: ~onLevelSelect
|
||||||
|
scroll:
|
||||||
|
$type: haxework.view.list.VScrollBarView
|
||||||
|
- $type: haxework.view.form.ButtonView
|
||||||
|
text: +
|
||||||
|
+onPress: ~addLevel()
|
||||||
- $type: haxework.view.group.VGroupView
|
- $type: haxework.view.group.VGroupView
|
||||||
geometry.stretch: true
|
geometry.stretch: true
|
||||||
views:
|
views:
|
||||||
@@ -69,22 +75,20 @@ views:
|
|||||||
overflow.x: crop
|
overflow.x: crop
|
||||||
overflow.y: crop
|
overflow.y: crop
|
||||||
views:
|
views:
|
||||||
- $type: ru.m.tankz.view.game.GameViewContainer
|
- $type: ru.m.tankz.view.game.GameViewContainer
|
||||||
views:
|
views:
|
||||||
- id: mapView
|
- id: mapView
|
||||||
$type: ru.m.tankz.editor.view.map.MapEditView
|
$type: ru.m.tankz.editor.view.map.MapEditView
|
||||||
- $type: haxework.view.group.HGroupView
|
- $type: haxework.view.group.HGroupView
|
||||||
style: panel
|
style: panel
|
||||||
layout.margin: 10
|
layout.margin: 10
|
||||||
views:
|
views:
|
||||||
- $type: haxework.view.SpriteView
|
- $type: haxework.view.SpriteView
|
||||||
geometry.width: 100%
|
geometry.width: 100%
|
||||||
- id: openButton
|
- $type: haxework.view.form.ButtonView
|
||||||
$type: haxework.view.form.ButtonView
|
text: Remove
|
||||||
text: Open
|
+onPress: ~removeLevel()
|
||||||
+onPress: ~open()
|
- $type: haxework.view.form.ButtonView
|
||||||
- id: saveButton
|
|
||||||
$type: haxework.view.form.ButtonView
|
|
||||||
text: Save
|
text: Save
|
||||||
+onPress: ~save()
|
+onPress: ~save()
|
||||||
- $type: haxework.view.form.ButtonView
|
- $type: haxework.view.form.ButtonView
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
package ru.m.tankz.editor.view;
|
package ru.m.tankz.editor.view;
|
||||||
|
|
||||||
import haxework.view.data.DataView;
|
import haxework.view.data.DataView;
|
||||||
import haxework.view.form.ButtonView;
|
|
||||||
import haxework.view.frame.FrameSwitcher;
|
import haxework.view.frame.FrameSwitcher;
|
||||||
import haxework.view.frame.FrameView;
|
import haxework.view.frame.FrameView;
|
||||||
import ru.m.tankz.bundle.ILevelBundle;
|
import ru.m.tankz.bundle.ILevelBundle;
|
||||||
import ru.m.tankz.config.Config;
|
import ru.m.tankz.config.Config;
|
||||||
|
import ru.m.tankz.editor.FileUtil;
|
||||||
import ru.m.tankz.Type;
|
import ru.m.tankz.Type;
|
||||||
|
import ru.m.tankz.util.LevelUtil;
|
||||||
|
|
||||||
@:template class PackListFrame extends FrameView<Dynamic> {
|
@:template class PackListFrame extends FrameView<Dynamic> {
|
||||||
public static inline var ID = "pack_list";
|
public static inline var ID = "pack_list";
|
||||||
|
|
||||||
@:view("packs") var packView:DataView<LevelPack, ButtonView>;
|
@:view("packs") var packView:DataView<PackId, PackView>;
|
||||||
|
|
||||||
@:provide static var levelBundle:ILevelBundle;
|
@:provide static var levelBundle:ILevelBundle;
|
||||||
@:provide static var switcher:FrameSwitcher;
|
@:provide static var switcher:FrameSwitcher;
|
||||||
|
@:provide static var storage:EditorStorage;
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
super(ID);
|
super(ID);
|
||||||
@@ -22,20 +24,49 @@ import ru.m.tankz.Type;
|
|||||||
|
|
||||||
override public function onShow(data:Dynamic):Void {
|
override public function onShow(data:Dynamic):Void {
|
||||||
super.onShow(data);
|
super.onShow(data);
|
||||||
packView.data = [
|
packView.data = storage.packList();
|
||||||
levelBundle.get(new PackId("classic")),
|
|
||||||
levelBundle.get(new PackId("dota")),
|
|
||||||
levelBundle.get(new PackId("death")),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function packViewFactory(index:Int, value:LevelPack):ButtonView {
|
private function onPackAction(value:PackId, action:String):Void {
|
||||||
var result = new ButtonView();
|
switch action {
|
||||||
result.text = value.id;
|
case "export":
|
||||||
return result;
|
var pack:LevelPack = storage.read(value);
|
||||||
|
FileUtil.save({
|
||||||
|
name: '${value}.zip',
|
||||||
|
content: LevelUtil.pack(pack.data),
|
||||||
|
});
|
||||||
|
case "edit":
|
||||||
|
switcher.change(PackFrame.ID, storage.read(value));
|
||||||
|
case "delete":
|
||||||
|
storage.delete(value);
|
||||||
|
packView.data = storage.packList();
|
||||||
|
case _:
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function onPackSelect(value:LevelPack):Void {
|
private function create():Void {
|
||||||
switcher.change(PackFrame.ID, value);
|
var levelPack:LevelPack = {
|
||||||
|
id: new PackId("classic", "modern"),
|
||||||
|
data: [],
|
||||||
|
}
|
||||||
|
storage.write(levelPack.id, levelPack);
|
||||||
|
packView.data.push(levelPack.id);
|
||||||
|
packView.data = packView.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function open():Void {
|
||||||
|
FileUtil.browse().then(function(file:FileContent) {
|
||||||
|
var packId = PackId.fromArray(file.name.split("/").pop().split(".").shift().split("_"));
|
||||||
|
var levelPack:LevelPack = {
|
||||||
|
id: packId,
|
||||||
|
data: LevelUtil.unpack(file.content).map(function(level) {
|
||||||
|
level.packId = packId;
|
||||||
|
return level;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
storage.write(levelPack.id, levelPack);
|
||||||
|
packView.data.push(levelPack.id);
|
||||||
|
packView.data = packView.data;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,22 @@
|
|||||||
---
|
---
|
||||||
views:
|
views:
|
||||||
- id: packs
|
- $type: haxework.view.group.VGroupView
|
||||||
$type: haxework.view.data.DataView
|
style: container
|
||||||
geometry.width: 100%
|
layout.margin: 10
|
||||||
geometry.height: 100%
|
views:
|
||||||
geometry.padding: 30
|
- $type: haxework.view.form.ButtonView
|
||||||
overflow.y: scroll
|
text: New
|
||||||
layout:
|
+onPress: ~create()
|
||||||
$type: haxework.view.layout.TailLayout
|
- id: packs
|
||||||
rowSize: 10
|
$type: haxework.view.data.DataView
|
||||||
margin: 5
|
layout:
|
||||||
factory: ~packViewFactory
|
$type: haxework.view.layout.VerticalLayout
|
||||||
+onDataSelect: ~onPackSelect
|
margin: 5
|
||||||
|
factory: ~ru.m.tankz.editor.view.PackView.factory
|
||||||
|
+onDataAction: ~onPackAction
|
||||||
|
- $type: haxework.view.form.ButtonView
|
||||||
|
text: Open
|
||||||
|
+onPress: ~open()
|
||||||
- $type: haxework.view.group.HGroupView
|
- $type: haxework.view.group.HGroupView
|
||||||
style: panel
|
style: panel
|
||||||
layout.margin: 10
|
layout.margin: 10
|
||||||
|
|||||||
50
src/editor/haxe/ru/m/tankz/editor/view/PackView.hx
Normal file
50
src/editor/haxe/ru/m/tankz/editor/view/PackView.hx
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package ru.m.tankz.editor.view;
|
||||||
|
|
||||||
|
import haxework.signal.Signal;
|
||||||
|
import haxework.view.data.DataView;
|
||||||
|
import haxework.view.form.ButtonView;
|
||||||
|
import haxework.view.group.HGroupView;
|
||||||
|
import haxework.view.list.ListView;
|
||||||
|
import ru.m.tankz.Type;
|
||||||
|
|
||||||
|
using ru.m.tankz.view.ViewUtil;
|
||||||
|
|
||||||
|
@:template class PackView extends HGroupView implements IListItemView<PackId> {
|
||||||
|
|
||||||
|
public var item_index(default, default):Int;
|
||||||
|
public var data(default, set):PackId;
|
||||||
|
|
||||||
|
private var actionSignal(get, null):Signal2<PackId, String>;
|
||||||
|
|
||||||
|
@:view var label:ButtonView;
|
||||||
|
|
||||||
|
private function set_data(value:PackId):PackId {
|
||||||
|
data = value;
|
||||||
|
label.text = data.toPackLabel();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function get_actionSignal():Signal2<PackId, String> {
|
||||||
|
var dataView:DataView<PackId, PackView> = cast parent;
|
||||||
|
return dataView.onDataAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function export():Void {
|
||||||
|
actionSignal.emit(data, "export");
|
||||||
|
}
|
||||||
|
|
||||||
|
private function edit():Void {
|
||||||
|
actionSignal.emit(data, "edit");
|
||||||
|
}
|
||||||
|
|
||||||
|
private function delete():Void {
|
||||||
|
actionSignal.emit(data, "delete");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function factory(index:Int, value:PackId):PackView {
|
||||||
|
var result = new PackView();
|
||||||
|
result.item_index = index;
|
||||||
|
result.data = value;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/editor/haxe/ru/m/tankz/editor/view/PackView.yaml
Normal file
14
src/editor/haxe/ru/m/tankz/editor/view/PackView.yaml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
layout.margin: 5
|
||||||
|
views:
|
||||||
|
- $type: haxework.view.form.ButtonView
|
||||||
|
style: button.prev
|
||||||
|
+onPress: ~export()
|
||||||
|
- id: label
|
||||||
|
$type: haxework.view.form.ButtonView
|
||||||
|
geometry.width: 250
|
||||||
|
+onPress: ~edit()
|
||||||
|
- $type: haxework.view.form.ButtonView
|
||||||
|
style: button.close
|
||||||
|
+onPress: ~delete()
|
||||||
|
|
||||||
Reference in New Issue
Block a user