Browse Source

[cdb] datafiles implementation

Nicolas Cannasse 5 years ago
parent
commit
085ba7ba04

+ 124 - 0
hide/comp/cdb/DataFiles.hx

@@ -0,0 +1,124 @@
+package hide.comp.cdb;
+
+typedef DataProps = {
+	var file : String;
+	var path : String;
+	var origin : String;
+}
+
+class DataFiles {
+
+	static var changed : Bool;
+	static var skip : Int = 0;
+	static var watching : Map<String, Bool> = new Map();
+	static var base(get,never) : cdb.Database;
+
+	static function get_base() return Ide.inst.database;
+
+	public static function load() {
+		for( sheet in base.sheets )
+			if( sheet.props.dataFiles != null && sheet.lines == null )
+				loadSheet(sheet);
+	}
+
+	static function onFileChanged() {
+		if( skip > 0 ) {
+			skip--;
+			return;
+		}
+		changed = true;
+		haxe.Timer.delay(function() {
+			if( !changed ) return;
+			changed = false;
+			for( s in base.sheets )
+				if( s.props.dataFiles != null ) @:privateAccess {
+					s.sheet.lines = null;
+					s.sheet.linesData = null;
+				}
+			load();
+			Editor.refreshAll(true);
+		},0);
+	}
+
+	static function loadSheet( sheet : cdb.Sheet ) {
+		var ide = Ide.inst;
+		var lines : Array<Dynamic> = [];
+		var linesData : Array<DataProps> = [];
+		@:privateAccess {
+			sheet.sheet.lines = lines;
+			sheet.sheet.linesData = linesData;
+		}
+		if( !sys.FileSystem.exists(ide.getPath(sheet.props.dataFiles)) )
+			return;
+		function loadFile( file : String ) {
+			function loadRec( p : hrt.prefab.Prefab ) {
+				if( p.getCdbModel() == sheet ) {
+					var dprops : DataProps = {
+						file : file,
+						path : p.getAbsPath(),
+						origin : haxe.Json.stringify(p.props),
+					};
+					linesData.push(dprops);
+					lines.push(p.props);
+				}
+				for( p in p ) loadRec(p);
+			}
+			var p = ide.loadPrefab(file);
+			loadRec(p);
+			if( !watching.exists(file) ) {
+				watching.set(file, true);
+				ide.fileWatcher.register(file, onFileChanged);
+			}
+		}
+		loadFile(sheet.props.dataFiles);
+	}
+
+	public static function save( ?onSaveBase, ?force ) {
+		var ide = Ide.inst;
+		var temp = [];
+		var prefabs = new Map();
+		for( s in base.sheets )
+			if( s.props.dataFiles != null ) {
+				var ldata = @:privateAccess s.sheet.linesData;
+				temp.push({ lines : s.lines, data : ldata });
+				for( i in 0...s.lines.length ) {
+					var o = s.lines[i];
+					var p : DataProps = ldata[i];
+					var str = haxe.Json.stringify(o);
+					if( str != p.origin || force ) {
+						p.origin = str;
+						var pf : hrt.prefab.Prefab = prefabs.get(p.file);
+						if( pf == null ) {
+							pf = ide.loadPrefab(p.file);
+							prefabs.set(p.file, pf);
+						}
+						var inst : hrt.prefab.Prefab = pf.getPrefabByPath(p.path);
+						if( inst == null || inst.getCdbModel() != s )
+							ide.error("Can't save prefab data "+p.path);
+						else
+							inst.props = o;
+					}
+				}
+				@:privateAccess {
+					Reflect.deleteField(s.sheet,"lines");
+					Reflect.deleteField(s.sheet,"linesData");
+				}
+			}
+		for( file => pf in prefabs ) {
+			skip++;
+			sys.io.File.saveContent(ide.getPath(file), ide.toJSON(pf.saveData()));
+		}
+		if( onSaveBase != null )
+			onSaveBase();
+		for( s in base.sheets ) {
+			if( s.props.dataFiles != null ) {
+				var d = temp.shift();
+				@:privateAccess {
+					s.sheet.lines = d.lines;
+					s.sheet.linesData = d.data;
+				}
+			}
+		}
+	}
+
+}

+ 65 - 36
hide/comp/cdb/Editor.hx

@@ -49,7 +49,6 @@ class Editor extends Component {
 		this.api = api;
 		this.config = config;
 		view = cast this.config.get("cdb.view");
-		currentValue = api.copy();
 		undo = new hide.ui.UndoHistory();
 	}
 
@@ -110,6 +109,8 @@ class Editor extends Component {
 		base = sheet.base;
 		cursor = new Cursor(this);
 		if( displayMode == null ) displayMode = Table;
+		DataFiles.load();
+		if( currentValue == null ) currentValue = api.copy();
 		refresh();
 	}
 
@@ -414,7 +415,7 @@ class Editor extends Component {
 		var state = undoState[0];
 		var newSheet = getCurrentSheet();
 		currentValue = newValue;
-		api.save();
+		save();
 		undo.change(Custom(function(undo) {
 			var currentSheet;
 			if( undo ) {
@@ -427,15 +428,20 @@ class Editor extends Component {
 				currentSheet = newSheet;
 			}
 			api.load(currentValue);
+			DataFiles.save(true); // save reloaded data
 			element.removeClass("is-cdb-editor");
 			refreshAll();
 			element.addClass("is-cdb-editor");
 			syncSheet(currentSheet);
 			refresh(state);
-			api.save();
+			save();
 		}));
 	}
 
+	function save() {
+		DataFiles.save(function() api.save());
+	}
+
 	public static function refreshAll( eraseUndo = false ) {
 		var editors : Array<Editor> = [for( e in new Element(".is-cdb-editor").elements() ) e.data("cdb")];
 		for( e in editors ) {
@@ -795,7 +801,7 @@ class Editor extends Component {
 		if( sheet == null ) sheet = this.currentSheet;
 		if( onChange == null ) onChange = function() {}
 		var index = base.sheets.indexOf(sheet);
-		new hide.comp.ContextMenu([
+		var content : Array<ContextMenu.ContextMenuItem> = [
 			{ label : "Add Sheet", click : function() { beginChanges(); var db = ide.createDBSheet(index+1); endChanges(); if( db != null ) onChange(); } },
 			{ label : "Move Left", click : function() { beginChanges(); base.moveSheet(sheet,-1); endChanges(); onChange(); } },
 			{ label : "Move Right", click : function() { beginChanges(); base.moveSheet(sheet,1); endChanges(); onChange(); } },
@@ -812,39 +818,62 @@ class Editor extends Component {
 				onChange();
 			}},
 			{ label : "", isSeparator: true },
-			{ label : "Add Index", checked : sheet.props.hasIndex, click : function() {
-				beginChanges();
-				if( sheet.props.hasIndex ) {
-					for( o in sheet.getLines() )
-						Reflect.deleteField(o, "index");
-					sheet.props.hasIndex = false;
-				} else {
-					for( c in sheet.columns )
-						if( c.name == "index" ) {
-							ide.error("Column 'index' already exists");
-							return;
-						}
-					sheet.props.hasIndex = true;
-				}
-				endChanges();
-			}},
-			{ label : "Add Group", checked : sheet.props.hasGroup, click : function() {
-				beginChanges();
-				if( sheet.props.hasGroup ) {
-					for( o in sheet.getLines() )
-						Reflect.deleteField(o, "group");
-					sheet.props.hasGroup = false;
-				} else {
-					for( c in sheet.columns )
-						if( c.name == "group" ) {
-							ide.error("Column 'group' already exists");
-							return;
-						}
-					sheet.props.hasGroup = true;
+		];
+		if( sheet.props.dataFiles == null )
+			content = content.concat([
+				{ label : "Add Index", checked : sheet.props.hasIndex, click : function() {
+					beginChanges();
+					if( sheet.props.hasIndex ) {
+						for( o in sheet.getLines() )
+							Reflect.deleteField(o, "index");
+						sheet.props.hasIndex = false;
+					} else {
+						for( c in sheet.columns )
+							if( c.name == "index" ) {
+								ide.error("Column 'index' already exists");
+								return;
+							}
+						sheet.props.hasIndex = true;
+					}
+					endChanges();
+				}},
+				{ label : "Add Group", checked : sheet.props.hasGroup, click : function() {
+					beginChanges();
+					if( sheet.props.hasGroup ) {
+						for( o in sheet.getLines() )
+							Reflect.deleteField(o, "group");
+						sheet.props.hasGroup = false;
+					} else {
+						for( c in sheet.columns )
+							if( c.name == "group" ) {
+								ide.error("Column 'group' already exists");
+								return;
+							}
+						sheet.props.hasGroup = true;
+					}
+					endChanges();
+				}},
+			]);
+		if( sheet.lines.length == 0 || sheet.props.dataFiles != null )
+			content.push({
+				label : "Data Files",
+				checked : sheet.props.dataFiles != null,
+				click : function() {
+					beginChanges();
+					var txt = StringTools.trim(ide.ask("Data Files Path", sheet.props.dataFiles));
+					if( txt == "" ) {
+						Reflect.deleteField(sheet.props,"dataFile");
+						@:privateAccess sheet.sheet.lines = [];
+					} else {
+						sheet.props.dataFiles = txt;
+						@:privateAccess sheet.sheet.lines = null;
+						DataFiles.load();
+					}
+					endChanges();
+					refresh();
 				}
-				endChanges();
-			}},
-		]);
+			});
+		new ContextMenu(content);
 	}
 
 	public function close() {

+ 22 - 6
hide/comp/cdb/ObjEditor.hx

@@ -4,11 +4,11 @@ class ObjEditor extends Editor {
 
     public dynamic function onChange(propName : String) {}
 
+    var obj : {};
+
     public function new( sheet : cdb.Sheet, props, obj : {}, ?parent : Element ) {
-        var sheetData = Reflect.copy(@:privateAccess sheet.sheet);
-        sheetData.lines = [for( i in 0...sheet.columns.length ) obj];
-        var pseudoSheet = new cdb.Sheet(sheet.base, sheetData);
         this.displayMode = AllProperties;
+        this.obj = obj;
         var api = {
             load : function(v:Any) {
                 var obj2 = haxe.Json.parse((v:String));
@@ -18,10 +18,26 @@ class ObjEditor extends Editor {
                     Reflect.setField(obj, f, Reflect.field(obj2,f));
             },
             copy : function() return (haxe.Json.stringify(obj) : Any),
-            save : function() {},
+            save : function() throw "assert",
         };
-		super(props, api);
-		show(pseudoSheet, parent);
+        super(props, api);
+        sheet = makePseudoSheet(sheet);
+		show(sheet, parent);
+    }
+
+    override function syncSheet(?base:cdb.Database, ?name:String) {
+        super.syncSheet(base, name);
+        currentSheet = makePseudoSheet(currentSheet);
+    }
+
+    function makePseudoSheet( sheet : cdb.Sheet ) {
+        var sheetData = Reflect.copy(@:privateAccess sheet.sheet);
+        sheetData.linesData = null;
+        sheetData.lines = [for( i in 0...sheet.columns.length ) obj];
+        return new cdb.Sheet(sheet.base, sheetData);
+    }
+
+    override function save() {
     }
 
 	override function changeObject(line:Line, column:cdb.Data.Column, value:Dynamic) {

+ 1 - 1
hide/comp/cdb/SubTable.hx

@@ -117,7 +117,7 @@ class SubTable extends Table {
 			if( isEmpty ) {
 				// not a change to really undo, perform direct change
 				Reflect.deleteField(cell.line.obj, cell.column.name);
-				editor.api.save();
+				editor.save();
 			}
 		}
 		cell.refresh();

+ 1 - 0
hide/comp/cdb/Table.hx

@@ -50,6 +50,7 @@ class Table extends Component {
 	}
 
 	public function canInsert() {
+		if( sheet.props.dataFiles != null ) return false;
 		return view == null || view.insert;
 	}
 

+ 12 - 6
hide/view/l3d/Level3D.hx

@@ -786,9 +786,6 @@ class Level3D extends FileView {
 		return ret;
 	}
 
-	static function getLevelSheet() {
-		return Ide.inst.database.getSheet(Ide.inst.currentConfig.get("l3d.cdbLevel", "level"));
-	}
 
 	static function resolveCdbType(id: String) {
 		var types = Level3D.getCdbTypes();
@@ -796,9 +793,18 @@ class Level3D extends FileView {
 	}
 
 	static function getCdbTypes() {
-		var levelSheet = getLevelSheet();
-		if(levelSheet == null) return [];
-		return [for(c in levelSheet.columns) if(c.type == TList) levelSheet.getSub(c)];
+		var sheets = [];
+		var ide = Ide.inst;
+		var levelSheet = ide.database.getSheet(Ide.inst.currentConfig.get("l3d.cdbLevel", "level"));
+		for( s in ide.database.sheets )
+			if( s.props.dataFiles != null )
+				sheets.push(s);
+		if(levelSheet != null) {
+			for(c in levelSheet.columns)
+				if( c.type == TList )
+					sheets.push(levelSheet.getSub(c));
+		}
+		return sheets;
 	}
 
 	static function getCdbTypeId(?p: PrefabElement, ?sheet: cdb.Sheet) : String {