Переглянути джерело

Copy/paste whole properties from the editor

Clement Espeute 2 роки тому
батько
коміт
cf72733b8d
3 змінених файлів з 122 додано та 3 видалено
  1. 21 2
      hide/comp/PropsEditor.hx
  2. 99 1
      hide/comp/SceneEditor.hx
  3. 2 0
      hide/prefab/PolygonEditor.hx

+ 21 - 2
hide/comp/PropsEditor.hx

@@ -160,6 +160,8 @@ class PropsEditor extends Component {
 	public function build( e : Element, ?context : Dynamic, ?onChange : String -> Void ) {
 	public function build( e : Element, ?context : Dynamic, ?onChange : String -> Void ) {
 		e = e.wrap("<div></div>").parent(); // necessary to have find working on top level element
 		e = e.wrap("<div></div>").parent(); // necessary to have find working on top level element
 
 
+
+
 		e.find("input[type=checkbox]").wrap("<div class='checkbox-wrapper'></div>");
 		e.find("input[type=checkbox]").wrap("<div class='checkbox-wrapper'></div>");
 		e.find("input[type=range]").not("[step]").attr({step: "any", tabindex:"-1"});
 		e.find("input[type=range]").not("[step]").attr({step: "any", tabindex:"-1"});
 
 
@@ -224,6 +226,7 @@ class PropsEditor extends Component {
 			e.getThis().closest(".group").find(">.title").val(e.getThis().val());
 			e.getThis().closest(".group").find(">.title").val(e.getThis().val());
 		});
 		});
 
 
+		var groupFields = [];
 		// init input reflection
 		// init input reflection
 		for( f in e.find("[field]").elements() ) {
 		for( f in e.find("[field]").elements() ) {
 			var f = new PropsField(this, f, context);
 			var f = new PropsField(this, f, context);
@@ -233,8 +236,8 @@ class PropsEditor extends Component {
 				if( onChange != null ) onChange(@:privateAccess f.fname);
 				if( onChange != null ) onChange(@:privateAccess f.fname);
 				isTempChange = false;
 				isTempChange = false;
 			};
 			};
+			groupFields.push(f);
 			fields.push(f);
 			fields.push(f);
-
 			// Init reset buttons
 			// Init reset buttons
 			var def = f.element.attr("value");
 			var def = f.element.attr("value");
 			if(def != null) {
 			if(def != null) {
@@ -252,6 +255,8 @@ class PropsEditor extends Component {
 				});
 				});
 			}
 			}
 		}
 		}
+
+
 		return e;
 		return e;
 	}
 	}
 
 
@@ -284,6 +289,8 @@ class PropsField extends Component {
 	var viewRoot : Element;
 	var viewRoot : Element;
 	var range : hide.comp.Range;
 	var range : hide.comp.Range;
 
 
+	var subfields : Array<String>;
+
 	public function new(props, el, context) {
 	public function new(props, el, context) {
 		super(null,el);
 		super(null,el);
 		viewRoot = element.closest(".lm_content");
 		viewRoot = element.closest(".lm_content");
@@ -452,7 +459,7 @@ class PropsField extends Component {
 			return;
 			return;
 		case "multi-range":
 		case "multi-range":
 			var subfieldStr = f.attr("data-subfields");
 			var subfieldStr = f.attr("data-subfields");
-			var subfields = subfieldStr.split(",");
+			subfields = subfieldStr.split(",");
 
 
 			var name = f.parent().prev("dt").text();
 			var name = f.parent().prev("dt").text();
 			var parentDiv = f.parent().parent();
 			var parentDiv = f.parent().parent();
@@ -600,6 +607,18 @@ class PropsField extends Component {
 		return { obj : obj, index : -1, name : field };
 		return { obj : obj, index : -1, name : field };
 	}
 	}
 
 
+	function getAccesses() : Array<{ obj : Dynamic, index : Int, name : String }> {
+		if (subfields == null)
+			return [getAccess()];
+		return [
+			for (subfield in subfields) {
+				var a = getAccess();
+				a.name = a.name + subfield;
+				a;
+			}
+		];
+	}
+
 
 
 	function getFieldValue() {
 	function getFieldValue() {
 		var a = getAccess();
 		var a = getAccess();

+ 99 - 1
hide/comp/SceneEditor.hx

@@ -1498,8 +1498,106 @@ class SceneEditor {
 		return props;
 		return props;
 	}
 	}
 
 
-	function fillProps( edit, e : PrefabElement ) {
+	function serializeProps(fields : Array<hide.comp.PropsEditor.PropsField>) : String {
+		var out = new Array<String>();
+		for (field in fields) {
+			@:privateAccess var accesses = field.getAccesses();
+			for (a in accesses) {
+				var v = Reflect.getProperty(a.obj, a.name);
+				var json = haxe.Json.stringify(v);
+				out.push('${a.name}:$json');
+			}
+		}
+		return haxe.Json.stringify(out);
+	}
+
+	// Return true if unseialization was successfull
+	function unserializeProps(fields : Array<hide.comp.PropsEditor.PropsField>, s : String) : Bool {
+		var data : Null<Array<Dynamic>> = null;
+		try {
+			data = cast(haxe.Json.parse(s), Array<Dynamic>);
+		}
+		catch(_) {
+
+		}
+		if (data != null) {
+			var map = new Map<String, Dynamic>();
+			for (field in data) {
+				var field : String = cast field;
+				var delimPos = field.indexOf(":");
+				var fieldName = field.substr(0, delimPos);
+				var fieldData = field.substr(delimPos+1);
+
+				var subdata : Dynamic = null;
+				try {
+					subdata = haxe.Json.parse(fieldData);
+				}
+				catch (_) {
+
+				}
+
+				if (subdata != null) {
+					map.set(fieldName, subdata);
+				}
+			}
+
+			for (field in fields) {
+				@:privateAccess var accesses = field.getAccesses();
+				for (a in accesses) {
+					if (map.exists(a.name)) {
+						Reflect.setProperty(a.obj, a.name, map.get(a.name));
+						field.onChange(false);
+					}
+				}
+			}
+
+			return true;
+		}
+		return false;
+	}
+
+	function pasteFields(edit : SceneEditorContext, fields : Array<hide.comp.PropsEditor.PropsField>, e : PrefabElement) {
+		var pasteData = ide.getClipboard();
+		var currentData = serializeProps(fields);
+		var success = unserializeProps(fields, pasteData);
+		if (success) {
+			undo.change(Custom(function(undo) {
+				if (undo) {
+					unserializeProps(fields, currentData);
+					edit.onChange(e, "props");
+					edit.rebuildProperties();
+				} else {
+					unserializeProps(fields, pasteData);
+					edit.onChange(e, "props");
+					edit.rebuildProperties();
+				}
+			}));
+
+			edit.onChange(e, "props");
+			edit.rebuildProperties();
+		}
+	}
+
+
+	function copyFields(fields : Array<hide.comp.PropsEditor.PropsField>) {
+		ide.setClipboard(serializeProps(fields));
+	}
+
+	function fillProps( edit : SceneEditorContext, e : PrefabElement ) {
 		properties.element.append(new Element('<h1 class="prefab-name">${e.getHideProps().name}</h1>'));
 		properties.element.append(new Element('<h1 class="prefab-name">${e.getHideProps().name}</h1>'));
+
+		var copyButton = new Element('<div class="button" title="Copy all properties">').append(new Element('<div class="icon ico ico-copy">'));
+		copyButton.click(function(event : js.jquery.Event) {
+			copyFields(properties.fields);
+		});
+		properties.element.append(copyButton);
+
+		var pasteButton = new Element('<div class="button" title="Paste values from the clipboard">').append(new Element('<div class="icon ico ico-paste">'));
+		pasteButton.click(function(event : js.jquery.Event) {
+			pasteFields(edit, properties.fields, e);
+		});
+		properties.element.append(pasteButton);
+
 		e.edit(edit);
 		e.edit(edit);
 
 
 		var typeName = e.getCdbType();
 		var typeName = e.getCdbType();

+ 2 - 0
hide/prefab/PolygonEditor.hx

@@ -493,6 +493,8 @@ class PolygonEditor {
 	}
 	}
 
 
 	function drawTriangles( b : Bool ){
 	function drawTriangles( b : Bool ){
+		if (triangleGraphics == null)
+			return;
 		triangleGraphics.clear();
 		triangleGraphics.clear();
 		if(b && polygonPrefab.getPrimitive(getContext()) != null){
 		if(b && polygonPrefab.getPrimitive(getContext()) != null){
 			var i = 0;
 			var i = 0;