소스 검색

Props -> Config

ncannasse 7 년 전
부모
커밋
076fd77eae

+ 1 - 1
bin/defaultProps.json

@@ -57,7 +57,7 @@
 	// script support
 
 	"script.api.files" : [],
-	"script.cdbModule" : "Data",
+	"script.cdbPackage" : "",
 	"script.api" : {
 		"TableName.fieldName" : {
 			"globals" : { "this" : "ThisClass" },

+ 17 - 17
hide/ui/Props.hx → hide/Config.hx

@@ -1,6 +1,6 @@
-package hide.ui;
+package hide;
 
-typedef HideProps = {
+typedef HideConfig = {
 	var autoSaveLayout : Null<Bool>;
 	var layouts : Array<{ name : String, state : Dynamic }>;
 
@@ -11,21 +11,21 @@ typedef HideProps = {
 	var renderer : String;
 };
 
-typedef PropsDef = {
+typedef ConfigDef = {
 
-	var hide : HideProps;
+	var hide : HideConfig;
 
 };
 
-class Props {
+class Config {
 
 	var ide : Ide;
-	var parent : Props;
+	var parent : Config;
 	public var path(default,null) : String;
-	public var source(default, null) : PropsDef;
-	public var current : PropsDef;
+	public var source(default, null) : ConfigDef;
+	public var current : ConfigDef;
 
-	public function new( ?parent : Props ) {
+	public function new( ?parent : Config ) {
 		ide = Ide.inst;
 		this.parent = parent;
 		sync();
@@ -88,10 +88,10 @@ class Props {
 	public static function loadForProject( projectPath : String, resourcePath : String ) {
 		var hidePath = Ide.inst.appPath;
 
-		var defaults = new Props();
+		var defaults = new Config();
 		defaults.load(hidePath + "/defaultProps.json");
 
-		var userGlobals = new Props(defaults);
+		var userGlobals = new Config(defaults);
 		userGlobals.load(hidePath + "/props.json");
 
 		if( userGlobals.source.hide == null )
@@ -104,13 +104,13 @@ class Props {
 				renderer : null,
 			};
 
-		var perProject = new Props(userGlobals);
+		var perProject = new Config(userGlobals);
 		perProject.load(resourcePath + "/props.json");
 
-		var projectUserCustom = new Props(perProject);
+		var projectUserCustom = new Config(perProject);
 		projectUserCustom.load(nw.App.dataPath + "/" + projectPath.split("/").join("_").split(":").join("_") + ".json");
 
-		var current = new Props(projectUserCustom);
+		var current = new Config(projectUserCustom);
 
 		return {
 			global : userGlobals,
@@ -134,12 +134,12 @@ class Props {
 			first = false;
 			parts.pop();
 		}
-		var parent = ide.currentProps;
+		var parent = ide.currentConfig;
 		for( p in propFiles ) {
-			parent = new Props(parent);
+			parent = new Config(parent);
 			parent.load(p);
 		}
-		return allowSave ? parent : new Props(parent);
+		return allowSave ? parent : new Config(parent);
 	}
 
 }

+ 56 - 57
hide/Ide.hx

@@ -1,11 +1,10 @@
 package hide;
-import hide.ui.Props;
 import hxd.inspect.Group;
 
 @:expose
 class Ide {
 
-	public var currentProps(get,never) : Props;
+	public var currentConfig(get,never) : Config;
 	public var projectDir(get,never) : String;
 	public var resourceDir(get,never) : String;
 	public var initializing(default,null) : Bool;
@@ -23,13 +22,13 @@ class Ide {
 
 	var databaseFile : String;
 
-	var props : {
-		global : Props,
-		project : Props,
-		user : Props,
-		current : Props,
+	var config : {
+		global : Config,
+		project : Config,
+		user : Config,
+		current : Config,
 	};
-	var ideProps(get, never) : hide.ui.Props.HideProps;
+	var ideConfig(get, never) : hide.Config.HideConfig;
 
 	var window : nw.Window;
 	var layout : golden.Layout;
@@ -50,7 +49,7 @@ class Ide {
 		inst = this;
 		window = nw.Window.get();
 		var cwd = Sys.getCwd();
-		props = Props.loadForProject(cwd, cwd+"/res");
+		config = Config.loadForProject(cwd, cwd+"/res");
 
 		var args = js.Browser.document.URL.split("?")[1];
 		if( args != null ) {
@@ -68,7 +67,7 @@ class Ide {
 		}
 
 		if( subView == null ) {
-			var wp = props.global.current.hide.windowPos;
+			var wp = config.global.current.hide.windowPos;
 			if( wp != null ) {
 				if( wp.w > 400 && wp.h > 300 )
 					window.resizeBy(wp.w - Std.int(window.window.outerWidth), wp.h - Std.int(window.window.outerHeight));
@@ -82,12 +81,12 @@ class Ide {
 		}
 		window.show(true);
 
-		if( props.global.get("hide") == null )
+		if( config.global.get("hide") == null )
 			error("Failed to load defaultProps.json");
 
 		fileWatcher = new hide.tools.FileWatcher();
 
-		setProject(ideProps.currentProject);
+		setProject(ideConfig.currentProject);
 		window.window.document.addEventListener("mousemove", function(e) {
 			mouseX = e.x;
 			mouseY = e.y;
@@ -209,16 +208,16 @@ class Ide {
 	function onWindowChange() {
 		if( hasReloaded )
 			return;
-		if( ideProps.windowPos == null ) ideProps.windowPos = { x : 0, y : 0, w : 0, h : 0, max : false };
-		ideProps.windowPos.max = maximized;
+		if( ideConfig.windowPos == null ) ideConfig.windowPos = { x : 0, y : 0, w : 0, h : 0, max : false };
+		ideConfig.windowPos.max = maximized;
 		if( !maximized ) {
-			ideProps.windowPos.x = window.x;
-			ideProps.windowPos.y = window.y;
-			ideProps.windowPos.w = Std.int(window.window.outerWidth);
-			ideProps.windowPos.h = Std.int(window.window.outerHeight);
+			ideConfig.windowPos.x = window.x;
+			ideConfig.windowPos.y = window.y;
+			ideConfig.windowPos.w = Std.int(window.window.outerWidth);
+			ideConfig.windowPos.h = Std.int(window.window.outerHeight);
 		}
 		if( subView == null )
-			props.global.save();
+			config.global.save();
 	}
 
 	function initLayout( ?state : { name : String, state : Dynamic } ) {
@@ -231,16 +230,16 @@ class Ide {
 		}
 
 		var defaultLayout = null;
-		for( p in props.current.current.hide.layouts )
+		for( p in config.current.current.hide.layouts )
 			if( p.name == "Default" ) {
 				defaultLayout = p;
 				break;
 			}
 		if( defaultLayout == null ) {
 			defaultLayout = { name : "Default", state : [] };
-			ideProps.layouts.push(defaultLayout);
-			props.current.sync();
-			props.global.save();
+			ideConfig.layouts.push(defaultLayout);
+			config.current.sync();
+			config.global.save();
 		}
 		if( state == null )
 			state = defaultLayout;
@@ -276,10 +275,10 @@ class Ide {
 
 		layout.init();
 		layout.on('stateChanged', function() {
-			if( !ideProps.autoSaveLayout )
+			if( !ideConfig.autoSaveLayout )
 				return;
 			defaultLayout.state = saveLayout();
-			if( subView == null ) props.global.save();
+			if( subView == null ) this.config.global.save();
 		});
 
 		var waitCount = 0;
@@ -322,8 +321,8 @@ class Ide {
 		return layout.toConfig().content;
 	}
 
-	function get_ideProps() return props.global.source.hide;
-	function get_currentProps() return props.user;
+	function get_ideConfig() return config.global.source.hide;
+	function get_currentConfig() return config.user;
 	function get_appPath() {
 		var path = js.Node.process.argv[0].split("\\").join("/").split("/");
 		path.pop();
@@ -373,19 +372,19 @@ class Ide {
 		js.Browser.console.error(e);
 	}
 
-	function get_projectDir() return ideProps.currentProject.split("\\").join("/");
+	function get_projectDir() return ideConfig.currentProject.split("\\").join("/");
 	function get_resourceDir() return projectDir+"/res";
 
 	function setProject( dir : String ) {
-		if( dir != ideProps.currentProject ) {
-			ideProps.currentProject = dir;
-			ideProps.recentProjects.remove(dir);
-			ideProps.recentProjects.unshift(dir);
-			if( ideProps.recentProjects.length > 10 ) ideProps.recentProjects.pop();
-			props.global.save();
+		if( dir != ideConfig.currentProject ) {
+			ideConfig.currentProject = dir;
+			ideConfig.recentProjects.remove(dir);
+			ideConfig.recentProjects.unshift(dir);
+			if( ideConfig.recentProjects.length > 10 ) ideConfig.recentProjects.pop();
+			config.global.save();
 		}
 		window.title = "HIDE - " + dir;
-		props = Props.loadForProject(projectDir, resourceDir);
+		config = Config.loadForProject(projectDir, resourceDir);
 		shaderLoader = new hide.tools.ShaderLoader();
 		typesCache = new hide.tools.TypesCache();
 
@@ -396,11 +395,11 @@ class Ide {
 			new hide.Renderer.PbrSetup("PBR"),
 		];
 
-		var plugins : Array<String> = props.current.get("plugins");
+		var plugins : Array<String> = config.current.get("plugins");
 		for( file in plugins )
 			loadScript(file, function() {});
 
-		var db = getPath(props.project.get("cdb.databaseFile"));
+		var db = getPath(config.project.get("cdb.databaseFile"));
 		databaseFile = db;
 		database = new cdb.Database();
 		if( sys.FileSystem.exists(db) ) {
@@ -411,7 +410,7 @@ class Ide {
 			}
 		}
 
-		if( props.project.get("debug.displayErrors")  ) {
+		if( config.project.get("debug.displayErrors")  ) {
 			js.Browser.window.onerror = function(msg, url, line, col, error) {
 				var e = error.stack;
 				e = ~/\(?chrome-extension:\/\/[a-z0-9\-\.\/]+.js:[0-9]+:[0-9]+\)?/g.replace(e,"");
@@ -424,7 +423,7 @@ class Ide {
 			Reflect.deleteField(js.Browser.window, "onerror");
 
 		waitScripts(function() {
-			var extraRenderers = props.current.get("renderers");
+			var extraRenderers = config.current.get("renderers");
 			for( name in Reflect.fields(extraRenderers) ) {
 				var clName = Reflect.field(extraRenderers, name);
 				var cl = try js.Lib.eval(clName) catch( e : Dynamic ) null;
@@ -437,7 +436,7 @@ class Ide {
 
 			var render = renderers[0];
 			for( r in renderers )
-				if( r.name == props.current.current.hide.renderer ) {
+				if( r.name == config.current.current.hide.renderer ) {
 					render = r;
 					break;
 				}
@@ -632,12 +631,12 @@ class Ide {
 		var menu = new Element(new Element("#mainmenu").get(0).outerHTML);
 
 		// project
-		if( ideProps.recentProjects.length > 0 )
+		if( ideConfig.recentProjects.length > 0 )
 			menu.find(".project .recents").html("");
-		for( v in ideProps.recentProjects.copy() ) {
+		for( v in ideConfig.recentProjects.copy() ) {
 			if( !sys.FileSystem.exists(v) ) {
-				ideProps.recentProjects.remove(v);
-				props.global.save();
+				ideConfig.recentProjects.remove(v);
+				config.global.save();
 				continue;
 			}
 			new Element("<menu>").attr("label",v).appendTo(menu.find(".project .recents")).click(function(_){
@@ -652,8 +651,8 @@ class Ide {
 			});
 		});
 		menu.find(".project .clear").click(function(_) {
-			ideProps.recentProjects = [];
-			props.global.save();
+			ideConfig.recentProjects = [];
+			config.global.save();
 			initMenu();
 		});
 		menu.find(".project .exit").click(function(_) {
@@ -663,10 +662,10 @@ class Ide {
 		for( r in renderers ) {
 			new Element("<menu type='checkbox'>").attr("label", r.name).prop("checked",r == h3d.mat.MaterialSetup.current).appendTo(menu.find(".project .renderers")).click(function(_) {
 				if( r != h3d.mat.MaterialSetup.current ) {
-					if( props.user.source.hide == null ) props.user.source.hide = cast {};
-					props.user.source.hide.renderer = r.name;
-					props.user.save();
-					setProject(ideProps.currentProject);
+					if( config.user.source.hide == null ) config.user.source.hide = cast {};
+					config.user.source.hide.renderer = r.name;
+					config.user.save();
+					setProject(ideConfig.currentProject);
 				}
 			});
 		}
@@ -699,27 +698,27 @@ class Ide {
 		// layout
 		var layouts = menu.find(".layout .content");
 		layouts.html("");
-		for( l in props.current.current.hide.layouts ) {
+		for( l in config.current.current.hide.layouts ) {
 			if( l.name == "Default" ) continue;
 			new Element("<menu>").attr("label",l.name).addClass(l.name).appendTo(layouts).click(function(_) {
 				initLayout(l);
 			});
 		}
 		menu.find(".layout .autosave").click(function(_) {
-			ideProps.autoSaveLayout = !ideProps.autoSaveLayout;
-			props.global.save();
-		}).prop("checked",ideProps.autoSaveLayout);
+			ideConfig.autoSaveLayout = !ideConfig.autoSaveLayout;
+			config.global.save();
+		}).prop("checked",ideConfig.autoSaveLayout);
 
 		menu.find(".layout .saveas").click(function(_) {
 			var name = ask("Please enter a layout name:");
 			if( name == null || name == "" ) return;
-			ideProps.layouts.push({ name : name, state : saveLayout() });
-			props.global.save();
+			ideConfig.layouts.push({ name : name, state : saveLayout() });
+			config.global.save();
 			initMenu();
 		});
 		menu.find(".layout .save").click(function(_) {
 			currentLayout.state = saveLayout();
-			props.global.save();
+			config.global.save();
 		});
 
 		window.menu = new hide.ui.Menu(menu).root;

+ 3 - 3
hide/Renderer.hx

@@ -91,7 +91,7 @@ class PbrSetup extends h3d.mat.PbrMaterialSetup {
 	function getEnvMap() {
 		var ide = hide.Ide.inst;
 		var scene = hide.comp.Scene.getCurrent();
-		var path = ide.getPath(scene.props.get("scene.environment"));
+		var path = ide.getPath(scene.config.get("scene.environment"));
 		var data = sys.io.File.getBytes(path);
 		var pix = hxd.res.Any.fromBytes(path, data).toImage().getPixels();
 		var t = h3d.mat.Texture.fromPixels(pix); // sync
@@ -142,7 +142,7 @@ class PbrRenderer extends h3d.scene.pbr.Renderer {
 	public function new(env) {
 		super(env);
 		tonemap.addShader(outline);
-	} 
+	}
 
 	override function getDefaultProps( ?kind : String ) : Any {
 		var props : h3d.scene.pbr.Renderer.RenderProps = super.getDefaultProps(kind);
@@ -155,7 +155,7 @@ class PbrRenderer extends h3d.scene.pbr.Renderer {
 		output.draw(getSort("alpha"));
 		output.draw(get("additive"));
 
-		
+
 		var outlineTex = allocTarget("outline", false);
 		setTarget(outlineTex);
 		clear(0);

+ 7 - 7
hide/comp/Scene.hx

@@ -62,7 +62,7 @@ class Scene extends Component implements h3d.IDrawable {
 	var pathsMap = new Map<String, String>();
 	var cleanup = new Array<Void->Void>();
 	var defaultCamera : h3d.Camera;
-	public var props : hide.ui.Props;
+	public var config : hide.Config;
 	public var engine : h3d.Engine;
 	public var width(get, never) : Int;
 	public var height(get, never) : Int;
@@ -72,9 +72,9 @@ class Scene extends Component implements h3d.IDrawable {
 	public var speed : Float = 1.0;
 	public var visible(default, null) : Bool = true;
 
-	public function new(props : hide.ui.Props, parent, el) {
+	public function new(config, parent, el) {
 		super(parent,el);
-		this.props = props;
+		this.config = config;
 		element.addClass("hide-scene-container");
 		canvas = cast new Element("<canvas class='hide-scene' style='width:100%;height:100%'/>").appendTo(element)[0];
 		canvas.addEventListener("mousemove",function(_) canvas.focus());
@@ -141,7 +141,7 @@ class Scene extends Component implements h3d.IDrawable {
 	}
 
 	public function init( ?root : h3d.scene.Object ) {
-		var autoHide : Array<String> = props.get("scene.autoHide");
+		var autoHide : Array<String> = config.get("scene.autoHide");
 		function initRec( obj : h3d.scene.Object ) {
 			if( autoHide.indexOf(obj.name) >= 0 )
 				obj.visible = false;
@@ -150,7 +150,7 @@ class Scene extends Component implements h3d.IDrawable {
 		}
 		if( root == null ) {
 			root = s3d;
-			engine.backgroundColor = Std.parseInt("0x"+props.get("scene.backgroundColor").substr(1)) | 0xFF000000;
+			engine.backgroundColor = Std.parseInt("0x"+config.get("scene.backgroundColor").substr(1)) | 0xFF000000;
 		}
 		initRec(root);
 	}
@@ -227,9 +227,9 @@ class Scene extends Component implements h3d.IDrawable {
 		if( StringTools.endsWith(path.toLowerCase(), ".hsd") )
 			return [];
 
-		var props = hide.ui.Props.loadForFile(ide, path);
+		var config = hide.Config.loadForFile(ide, path);
 
-		var dirs : Array<String> = props.get("hmd.animPaths");
+		var dirs : Array<String> = config.get("hmd.animPaths");
 		if( dirs == null ) dirs = [];
 		dirs = [for( d in dirs ) ide.resourceDir + d];
 

+ 8 - 8
hide/comp/SceneEditor.hx

@@ -117,7 +117,7 @@ class SceneEditor {
 		tree.autoOpenNodes = false;
 
 		var sceneEl = new Element('<div class="scene"></div>');
-		scene = new hide.comp.Scene(view.props, null, sceneEl);
+		scene = new hide.comp.Scene(view.config, null, sceneEl);
 		scene.onReady = onSceneReady;
 		scene.onResize = function() {
 			context.shared.root2d.x = scene.width >> 1;
@@ -228,7 +228,7 @@ class SceneEditor {
 		scene.s3d.addChild(context.shared.root3d);
 
 		gizmo = new hide.view.l3d.Gizmo(scene);
-		gizmo.moveStep = view.props.get("sceneeditor.gridSnapStep");
+		gizmo.moveStep = view.config.get("sceneeditor.gridSnapStep");
 
 		cameraController = makeCamController();
 
@@ -497,9 +497,9 @@ class SceneEditor {
 				m;
 			}];
 
-			var posQuant = view.props.get("sceneeditor.xyzPrecision");
-			var scaleQuant = view.props.get("sceneeditor.scalePrecision");
-			var rotQuant = view.props.get("sceneeditor.rotatePrecision");
+			var posQuant = view.config.get("sceneeditor.xyzPrecision");
+			var scaleQuant = view.config.get("sceneeditor.scalePrecision");
+			var rotQuant = view.config.get("sceneeditor.rotatePrecision");
 
 			inline function quantize(x: Float, step: Float) {
 				if(step > 0) {
@@ -694,7 +694,7 @@ class SceneEditor {
 						setVisible(curEdit.elements, isHidden(obj3d));
 					else
 						setVisible([obj3d], isHidden(obj3d));
-					
+
 					e.preventDefault();
 					e.stopPropagation();
 				});
@@ -703,7 +703,7 @@ class SceneEditor {
 	}
 
 	public function applySceneStyle(p: PrefabElement) {
-	
+
 	}
 
 	public function getContext(elt : PrefabElement) {
@@ -1367,7 +1367,7 @@ class SceneEditor {
 
 		var menu = [custom];
 
-		var shaders : Array<String> = hide.Ide.inst.currentProps.get("fx.shaders", []);
+		var shaders : Array<String> = hide.Ide.inst.currentConfig.get("fx.shaders", []);
 		for(path in shaders) {
 			var name = path;
 			if(StringTools.endsWith(name, ".hx")) {

+ 113 - 68
hide/comp/ScriptEditor.hx

@@ -6,80 +6,48 @@ typedef GlobalsDef = haxe.DynamicAccess<{
 	var cdbEnums : Bool;
 }>;
 
-class ScriptEditor extends Component {
-
-	static var INIT_DONE = false;
-
-	var editor : monaco.Editor;
-	var errorMessage : Element;
-	var checker : hscript.Checker;
-	var currrentDecos : Array<String> = [];
-	var props : hide.ui.Props;
-	public var documentName : String;
-	public var script(get,never) : String;
-
-	public var checkScript : Bool = false;
-	public var checkAsync : Bool = true;
-
-	public function new( documentName : String, script : String, props : hide.ui.Props, ?parent : Element, ?root : Element ) {
-		super(parent,root);
-		this.props = props;
-		this.documentName = documentName;
-
-		if( !INIT_DONE ) {
-			INIT_DONE = true;
-			monaco.Languages.registerCompletionItemProvider("javascript", {
-				provideCompletionItems : function(model,position,_,_) {
-					var comp : ScriptEditor = (model : Dynamic).__comp__;
-					return comp.getCompletion(position);
-				}
-			});
-		}
+class ScriptChecker {
 
-		var root = element;
-		root.addClass("scripteditor");
-		root.on("keydown", function(e) e.stopPropagation());
+	static var TYPES_SAVE = new Map();
+	public var checker : hscript.Checker;
 
-		editor = monaco.Editor.create(root[0],{
-			value : script,
-			language : "javascript",
-			automaticLayout : true,
-			wordWrap : true,
-			theme : "vs-dark",
-		});
-		(editor.getModel() : Dynamic).__comp__ = this;
-		editor.onDidChangeModelContent(doCheckScript);
-		editor.addCommand(monaco.KeyCode.KEY_S | monaco.KeyMod.CtrlCmd, function() onSave());
-		errorMessage = new Element('<div class="scriptErrorMessage"></div>').appendTo(root).hide();
+	public function new( config : hide.Config, documentName : String ) {
 
 		checker = new hscript.Checker();
 
-		var files : Array<String> = props.get("script.api.files");
+		var ide = hide.Ide.inst;
+		var files : Array<String> = config.get("script.api.files");
 		if( files.length >= 0 ) {
-			for( f in files ) {
-				// TODO : reload + recheck script when modified
-				var content = try sys.io.File.getContent(ide.getPath(f)) catch( e : Dynamic ) { ide.error(e); continue; };
-				checker.addXmlApi(Xml.parse(content).firstElement());
+			var types = TYPES_SAVE.get(files.join(";"));
+			if( types == null ) {
+				types = new hscript.Checker.CheckerTypes();
+				for( f in files ) {
+					// TODO : reload + recheck script when modified
+					var content = try sys.io.File.getContent(ide.getPath(f)) catch( e : Dynamic ) { ide.error(e); continue; };
+					types.addXmlApi(Xml.parse(content).firstElement());
+				}
+				TYPES_SAVE.set(files.join(";"), types);
 			}
+			checker.types = types;
 		}
 
 		var parts = documentName.split("/");
-		var cdbMod : String = props.get("script.cdbModule");
+		var cdbPack : String = config.get("script.cdbPackage");
 		while( parts.length > 0 ) {
 			var path = parts.join("/");
 			parts.pop();
-			var api = (props.get("script.api") : GlobalsDef).get(path);
+			var api = (config.get("script.api") : GlobalsDef).get(path);
 			if( api == null ) continue;
 
 			for( f in api.globals.keys() ) {
 				var tname = api.globals.get(f);
-				var t = checker.resolveType(tname);
+				var t = checker.types.resolve(tname);
 				if( t == null ) ide.error('Global type $tname not found in $files ($f)');
 				checker.setGlobal(f, t);
 			}
 
 			if( api.context != null ) {
-				var t = checker.resolveType(api.context);
+				var t = checker.types.resolve(api.context);
 				if( t == null ) ide.error("Missing context type "+api.context);
 				while( t != null )
 					switch (t) {
@@ -100,8 +68,9 @@ class ScriptEditor extends Component {
 					for( c in s.columns )
 						if( c.type == TId ) {
 							var name = s.name.charAt(0).toUpperCase() + s.name.substr(1);
-							var kname = cdbMod+"."+name+"Kind";
-							var kind = checker.resolveType(kname);
+							var kname = name+"Kind";
+							if( cdbPack != "" ) kname = cdbPack + "." + kname;
+							var kind = checker.types.resolve(kname);
 							if( kind == null )
 								kind = TEnum({ name : kname, params : [], constructors : new Map() },[]);
 							var cl : hscript.Checker.CClass = {
@@ -120,21 +89,101 @@ class ScriptEditor extends Component {
 				}
 			}
 		}
+	}
+
+	public function check( script : String, checkTypes = true ) {
+		var parser = new hscript.Parser();
+		parser.allowMetadata = true;
+		parser.allowTypes = true;
+		parser.allowJSON = true;
+		try {
+			var expr = parser.parseString(script, "");
+			if( checkTypes ) {
+				checker.allowAsync = true;
+				checker.check(expr);
+			}
+			return null;
+		} catch( e : hscript.Expr.Error ) {
+			return e;
+		}
+	}
+
+}
 
+class ScriptEditor extends Component {
+
+	static var INIT_DONE = false;
+
+	var editor : monaco.Editor;
+	var errorMessage : Element;
+	var checker : ScriptChecker;
+	var currrentDecos : Array<String> = [];
+	var config : hide.Config;
+	public var documentName : String;
+	public var script(get,never) : String;
+	public var checkTypes : Bool = false;
+
+	public function new( documentName : String, script : String, config, ?parent : Element, ?root : Element ) {
+		super(parent,root);
+		this.config = config;
+		this.documentName = documentName;
+
+		if( !INIT_DONE ) {
+			INIT_DONE = true;
+			monaco.Languages.registerCompletionItemProvider("javascript", {
+				provideCompletionItems : function(model,position,_,_) {
+					var comp : ScriptEditor = (model : Dynamic).__comp__;
+					return comp.getCompletion(position);
+				}
+			});
+		}
+
+		var root = element;
+		root.addClass("scripteditor");
+		root.on("keydown", function(e) e.stopPropagation());
+
+		editor = monaco.Editor.create(root[0],{
+			value : script,
+			language : "javascript",
+			automaticLayout : true,
+			wordWrap : true,
+			minimap : { enabled : false },
+			theme : "vs-dark",
+		});
+		var model = editor.getModel();
+		(model : Dynamic).__comp__ = this;
+		model.updateOptions({ insertSpaces:false, trimAutoWhitespace:true });
+		editor.onDidChangeModelContent(doCheckScript);
+		editor.addCommand(monaco.KeyCode.KEY_S | monaco.KeyMod.CtrlCmd, function() { clearSpaces(); onSave(); });
+		errorMessage = new Element('<div class="scriptErrorMessage"></div>').appendTo(root).hide();
+		checker = new ScriptChecker(config, documentName);
 		haxe.Timer.delay(function() doCheckScript(), 0);
 	}
 
+	function clearSpaces() {
+		var script = script;
+		var newScript = [for( l in StringTools.trim(script).split("\n") ) StringTools.rtrim(l)].join("\n");
+		if( newScript != script ) {
+			var p = editor.getPosition();
+			setScript(newScript);
+			editor.setPosition(p);
+		}
+	}
+
 	function get_script() {
 		return editor.getValue({preserveBOM:true});
 	}
 
-	var rnd = Std.random(1000);
+	public function setScript( script : String ) {
+		editor.setValue(script);
+	}
 
 	function getCompletion( position : monaco.Position ) : Array<monaco.Languages.CompletionItem> {
+		var checker = checker.checker;
 		var globals = checker.getGlobals();
 		return [for( k in globals.keys() ) {
 			var t = globals.get(k);
-			if( checkAsync && StringTools.startsWith(k,"a_") ) {
+			if( StringTools.startsWith(k,"a_") ) {
 				t = checker.unasync(t);
 				k = k.substr(2);
 			}
@@ -143,14 +192,14 @@ class ScriptEditor extends Component {
 				{
 					kind : Field,
 					label : k,
-					detail : checker.typeStr(t),
+					detail : hscript.Checker.typeStr(t),
 					commitCharacters: ["("],
 				}
 			} else {
 				{
 					kind : Field,
 					label : k,
-					detail : checker.typeStr(t),
+					detail : hscript.Checker.typeStr(t),
 				}
 			}
 		}];
@@ -158,25 +207,21 @@ class ScriptEditor extends Component {
 
 	function doCheckScript() {
 		var script = script;
-		try {
-			var expr = new hscript.Parser().parseString(script, "");
-			if( checkScript ) {
-				checker.allowAsync = checkAsync;
-				checker.check(expr);
-			}
+		var error = checker.check(script, checkTypes);
+		if( error == null ) {
 			if( currrentDecos.length != 0 )
 				currrentDecos = editor.deltaDecorations(currrentDecos,[]);
 			errorMessage.hide();
-		} catch( e : hscript.Expr.Error ) {
-			var linePos = script.substr(0,e.pmin).lastIndexOf("\n");
+		} else {
+			var linePos = script.substr(0,error.pmin).lastIndexOf("\n");
 			//trace(e, e.pmin, e.pmax, cur.substr(e.pmin, e.pmax - e.pmin + 1), linePos);
 			if( linePos < 0 ) linePos = 0 else linePos++;
-			var range = new monaco.Range(e.line,e.pmin + 1 - linePos,e.line,e.pmax + 2 - linePos);
+			var range = new monaco.Range(error.line,error.pmin + 1 - linePos,error.line,error.pmax + 2 - linePos);
 			currrentDecos = editor.deltaDecorations(currrentDecos,[
 				{ range : range, options : { inlineClassName: "scriptErrorContentLine", isWholeLine : true } },
 				{ range : range, options : { linesDecorationsClassName: "scriptErrorLine", inlineClassName: "scriptErrorContent" } }
 			]);
-			errorMessage.text(hscript.Printer.errorToString(e));
+			errorMessage.text(hscript.Printer.errorToString(error));
 			errorMessage.show();
 		}
 	}

+ 8 - 3
hide/comp/cdb/Cell.hx

@@ -40,9 +40,9 @@ class Cell extends Component {
 		element.removeClass("edit");
 		element.removeClass("edit_long");
 		switch( column.type ) {
-		case TBool :
+		case TBool:
 			element.removeClass("true false").addClass( value==true ? "true" : "false" );
-		case TInt, TFloat :
+		case TInt, TFloat:
 			element.removeClass("zero");
 			if( value == 0 ) element.addClass("zero");
 		default:
@@ -178,9 +178,14 @@ class Cell extends Component {
 
 	static var KWDS = ["for","if","var","this","while","else","do","break","continue","switch","function","return","new","throw","try","catch","case","default"];
 	static var KWD_REG = new EReg([for( k in KWDS ) "(\\b"+k+"\\b)"].join("|"),"g");
-	function colorizeScript( code : String ) {
+	function colorizeScript( ecode : String ) {
+		var code = ecode;
 		code = StringTools.htmlEscape(code);
 		code = code.split("\n").join("<br/>");
+		// typecheck
+		var error = new ScriptEditor.ScriptChecker(editor.config, "cdb/"+table.sheet.name+"/"+column.name).check(ecode);
+		if( error != null )
+			return '<span class="error">'+code+'</span>';
 		// strings
 		code = ~/("[^"]*")/g.replace(code,'<span class="str">$1</span>');
 		code = ~/('[^']*')/g.replace(code,'<span class="str">$1</span>');

+ 10 - 3
hide/comp/cdb/Editor.hx

@@ -15,14 +15,14 @@ class Editor extends Component {
 		data : {},
 		schema : Array<cdb.Data.Column>,
 	};
-	public var props : hide.ui.Props;
+	public var config : hide.Config;
 	public var cursor : Cursor;
 	public var keys : hide.ui.Keys;
 	public var undo : hide.ui.UndoHistory;
 
-	public function new(sheet,props,?parent) {
+	public function new(sheet,config,?parent) {
 		super(parent,null);
-		this.props = props;
+		this.config = config;
 		this.undo = new hide.ui.UndoHistory();
 		this.sheet = sheet;
 		element.attr("tabindex", 0);
@@ -272,6 +272,13 @@ class Editor extends Component {
 	}
 
 	public function popupColumn( table : Table, col : cdb.Data.Column ) {
+		var menu : Array<hide.comp.ContextMenu.ContextMenuItem> = [];
+		if( col.type == TString && col.kind == Script )
+			menu.push({ label : "Edit all", click : function() editScripts(table,col) });
+		new hide.comp.ContextMenu(menu);
+	}
+
+	function editScripts( table : Table, col : cdb.Data.Column ) {
 	}
 
 	public function addChanges( changes : cdb.Database.Changes ) {

+ 3 - 2
hide/comp/cdb/ScriptTable.hx

@@ -22,8 +22,9 @@ class ScriptTable extends SubTable {
 	override function refresh() {
 		var first = script == null;
 		element.html("<div class='cdb-script'></div>");
-		script = new ScriptEditor("cdb/"+cell.table.sheet.name+"/"+cell.column.name,cell.value, editor.props, element.find("div"));
-		script.checkScript = true;
+		script = new ScriptEditor("cdb/"+cell.table.sheet.name+"/"+cell.column.name,cell.value, editor.config, element.find("div"));
+		script.onSave = function() @:privateAccess cell.setValue(script.script);
+		script.checkTypes = true;
 		lines = [new Line(this,[],0,script.element)];
 		if( first ) script.focus();
 	}

+ 2 - 2
hide/prefab/Terrain.hx

@@ -373,7 +373,7 @@ class Terrain extends Object3D {
 				</dl>
 			</div>
 		');
-		var brushes : Array<Dynamic> = ctx.scene.props.get("terrain.brushes");
+		var brushes : Array<Dynamic> = ctx.scene.config.get("terrain.brushes");
 		var brushesContainer = props.find(".terrain-brushes");
 		for( brush in brushes){
 			var label = brush.name + "<br/>Step : " + brush.step + "<br/>Strength : " + brush.strength + "<br/>Size : " + brush.size ;
@@ -401,7 +401,7 @@ class Terrain extends Object3D {
 		}
 
 		var surfacesContainer = props.find(".terrain-surfaces");
-		var surfacesPath : Dynamic = ctx.scene.props.get("terrain.surfacesPath");
+		var surfacesPath : Dynamic = ctx.scene.config.get("terrain.surfacesPath");
 		var dir = hide.Ide.inst.getPath(surfacesPath);
 		for( f in try sys.FileSystem.readDirectory(dir) catch( e : Dynamic ) [] ){
 			if( StringTools.endsWith(f,"_Albedo.png") ){

+ 1 - 1
hide/tools/ShaderLoader.hx

@@ -16,7 +16,7 @@ class ShaderLoader {
 
 	public function new() {
 		ide = hide.Ide.inst;
-		shaderPath = ide.currentProps.get("haxe.classPath");
+		shaderPath = ide.currentConfig.get("haxe.classPath");
 	}
 
 	public function load( name : String ) {

+ 1 - 1
hide/tools/TypesCache.hx

@@ -56,7 +56,7 @@ class TypesCache {
 		types = [];
 		needRebuild = false;
 
-		var src : Array<Dynamic> = ide.currentProps.get("haxe.classPath");
+		var src : Array<Dynamic> = ide.currentConfig.get("haxe.classPath");
 		for( dir in src ) {
 			var path = ide.projectDir + "/" + dir;
 			if( !sys.FileSystem.exists(path) )

+ 2 - 2
hide/ui/Keys.hx

@@ -25,7 +25,7 @@ class Keys {
 		listeners.push(l);
 	}
 
-	public function processEvent( e : js.jquery.Event, config : Props ) {
+	public function processEvent( e : js.jquery.Event, config : Config ) {
 		var parts = [];
 		if( e.altKey )
 			parts.push("Alt");
@@ -55,7 +55,7 @@ class Keys {
 		return false;
 	}
 
-	public function triggerKey( e : js.jquery.Event, key : String, config : Props ) {
+	public function triggerKey( e : js.jquery.Event, key : String, config : Config ) {
 		for( l in listeners )
 			if( l(e) )
 				return true;

+ 7 - 7
hide/ui/View.hx

@@ -17,7 +17,7 @@ class View<T> extends hide.comp.Component {
 	public var keys(get,null) : Keys;
 	public var state(default, null) : T;
 	public var undo(default, null) = new hide.ui.UndoHistory();
-	public var props(get, null) : Props;
+	public var config(get, null) : Config;
 	public var viewClass(get, never) : String;
 	public var defaultOptions(get,never) : ViewOptions;
 
@@ -44,10 +44,10 @@ class View<T> extends hide.comp.Component {
 			ide.fileWatcher.unregister(w.path, w.callb);
 	}
 
-	function get_props() {
-		if( props == null )
-			props = ide.currentProps;
-		return props;
+	function get_config() {
+		if( config == null )
+			config = ide.currentConfig;
+		return config;
 	}
 
 	function get_keys() {
@@ -98,11 +98,11 @@ class View<T> extends hide.comp.Component {
 				continue;
 			var keys = hide.ui.Keys.get(el);
 			if( keys == null ) continue;
-			if( keys.processEvent(e,props) )
+			if( keys.processEvent(e,config) )
 				return true;
 		}
 		// global keys
-		return keys.processEvent(e,props);
+		return keys.processEvent(e,config);
 	}
 
 	public function setContainer(cont) {

+ 1 - 1
hide/view/CdbTable.hx

@@ -20,7 +20,7 @@ class CdbTable extends hide.ui.View<{ path : String }> {
 			return;
 		}
 		element.addClass("hide-scroll");
-		editor = new hide.comp.cdb.Editor(sheet,props,element);
+		editor = new hide.comp.cdb.Editor(sheet,config,element);
 		editor.undo = undo;
 		undo.onChange = function() {
 			editor.save();

+ 5 - 5
hide/view/FileView.hx

@@ -76,12 +76,12 @@ class FileView extends hide.ui.View<{ path : String }> {
 		return super.onBeforeClose();
 	}
 
-	override function get_props() {
-		if( props == null ) {
-			if( state.path == null ) return super.get_props();
-			props = hide.ui.Props.loadForFile(ide, state.path);
+	override function get_config() {
+		if( config == null ) {
+			if( state.path == null ) return super.get_config();
+			config = hide.Config.loadForFile(ide, state.path);
 		}
-		return props;
+		return config;
 	}
 
 	function set_modified(b) {

+ 1 - 1
hide/view/Image.hx

@@ -53,7 +53,7 @@ class Image extends FileView {
 				if( b ) channelSelect.channels |= 1 << i;
 			});
 		}
-		scene = new hide.comp.Scene(props, null, element.find(".scene"));
+		scene = new hide.comp.Scene(config, null, element.find(".scene"));
 		scene.onReady = function() {
 			scene.loadTexture(state.path, state.path, function(t) {
 				bmp = new h2d.Bitmap(h2d.Tile.fromTexture(t), scene.s2d);

+ 1 - 1
hide/view/Model.hx

@@ -54,7 +54,7 @@ class Model extends FileView {
 		overlay = element.find(".hide-scene-layer .tree");
 
 		if( rootPath == null )
-			rootPath = props.get("model.renderProps");
+			rootPath = config.get("model.renderProps");
 
 		if( rootPath != null )
 			root = ide.loadPrefab(rootPath, hxd.prefab.Library);

+ 1 - 1
hide/view/Particles2D.hx

@@ -28,7 +28,7 @@ class Particles2D extends FileView {
 		');
 		properties = new hide.comp.PropsEditor(undo, null, element.find(".props"));
 		properties.saveDisplayKey = "particles2D";
-		scene = new hide.comp.Scene(props, null,element.find(".scene"));
+		scene = new hide.comp.Scene(config, null,element.find(".scene"));
 		scene.onReady = init;
 	}
 

+ 1 - 1
hide/view/Particles3D.hx

@@ -24,7 +24,7 @@ class Particles3D extends FileView {
 		');
 		properties = new hide.comp.PropsEditor(undo, null, element.find(".props"));
 		properties.saveDisplayKey = "particles3D";
-		scene = new hide.comp.Scene(props, null,element.find(".scene"));
+		scene = new hide.comp.Scene(config, null,element.find(".scene"));
 		scene.onReady = init;
 		scene.onUpdate = update;
 	}

+ 4 - 4
hide/view/l3d/Level3D.hx

@@ -266,7 +266,7 @@ private class Level3DSceneEditor extends hide.comp.SceneEditor {
 
 		if(sheet != null) {
 			var props = new hide.Element('<div></div>').appendTo(group.find(".content"));
-			var editor = new hide.comp.cdb.ObjEditor(sheet, parent.props, e.props, props);
+			var editor = new hide.comp.cdb.ObjEditor(sheet, parent.config, e.props, props);
 			editor.undo = properties.undo;
 			editor.onChange = function(pname) {
 				edit.onChange(e, 'props.$pname');
@@ -578,7 +578,7 @@ class Level3D extends FileView {
 	}
 
 	function applyTreeStyle(p: PrefabElement, el: Element) {
-		var styles = ide.currentProps.get("l3d.treeStyles");
+		var styles = ide.currentConfig.get("l3d.treeStyles");
 		var style: Dynamic = null;
 		var typeId = getCdbTypeId(p);
 		if(typeId != null) {
@@ -639,7 +639,7 @@ class Level3D extends FileView {
 	function getDisplayColor(p: PrefabElement) : Null<Int> {
 		var typeId = getCdbTypeId(p);
 		if(typeId != null) {
-			var colors = ide.currentProps.get("l3d.colors");
+			var colors = ide.currentConfig.get("l3d.colors");
 			var color = Reflect.field(colors, typeId);
 			if(color != null) {
 				return Std.parseInt("0x"+color.substr(1)) | 0xff000000;
@@ -649,7 +649,7 @@ class Level3D extends FileView {
 	}
 
 	public static function getLevelSheet() {
-		return Ide.inst.database.getSheet(Ide.inst.currentProps.get("l3d.cdbLevel", "level"));
+		return Ide.inst.database.getSheet(Ide.inst.currentConfig.get("l3d.cdbLevel", "level"));
 	}
 
 	static function resolveCdbType(id: String) {

+ 4 - 0
libs/monaco/Editor.hx

@@ -11,6 +11,10 @@ extern class Editor {
 	function dispose() : Void;
 	function getModel() : Model;
 	function deltaDecorations( old : Array<String>, newDeco : Array<ModelDeltaDecoration> ) : Array<String>;
+	function setValue( script : String ) : Void;
+	function updateOptions( options : Dynamic ) : Void;
+	function getPosition() : Position;
+	function setPosition( p : Position ) : Void;
 
 	public static function create( elt : js.html.Element, ?options : Dynamic ) : Editor;
 

+ 1 - 0
libs/monaco/Model.hx

@@ -1,4 +1,5 @@
 package monaco;
 
 extern class Model {
+	function updateOptions( opts : {?insertSpaces:Bool,?tabSize:Int,?trimAutoWhitespace:Bool} ) : Void;
 }