123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- package hrt.prefab;
- class DynamicShader extends Shader {
- var shaderDef : hrt.prefab.ContextShared.ShaderDef;
- var shaderClass : Class<hxsl.Shader>;
- @:s var isInstance : Bool;
- public function new(?parent) {
- super(parent);
- type = "shader";
- }
- override function setShaderParam(shader:hxsl.Shader, v:hxsl.Ast.TVar, value:Dynamic) {
- if( isInstance ) {
- super.setShaderParam(shader,v,value);
- return;
- }
- cast(shader,hxsl.DynamicShader).setParamValue(v, value);
- }
- override function getShaderDefinition(ctx:Context):hxsl.SharedShader {
- if( shaderDef == null && ctx != null )
- loadShaderDef(ctx);
- return shaderDef == null ? null : shaderDef.shader;
- }
- override function makeShader( ?ctx:Context ) {
- if( getShaderDefinition(ctx) == null )
- return null;
- var shader;
- if( isInstance )
- shader = Type.createInstance(shaderClass,[]);
- else {
- var dshader = new hxsl.DynamicShader(shaderDef.shader);
- for( v in shaderDef.inits ) {
- #if !hscript
- throw "hscript required";
- #else
- dshader.hscriptSet(v.variable.name, v.value);
- #end
- }
- shader = dshader;
- }
- syncShaderVars(shader, shaderDef.shader);
- return shader;
- }
- override function makeInstance(ctx:Context):Context {
- if( source == null )
- return ctx;
- return super.makeInstance(ctx);
- }
- function fixSourcePath() {
- #if editor
- // shader source is loaded with ../src/path/to/Shader.hx
- // but we want the path relative to source path path/to/Shader.hx only
- var ide = hide.Ide.inst;
- var shadersPath = ide.projectDir + "/src"; // TODO: serach in haxe.classPath?
- var path = ide.getPath(source);
- var fpath = sys.FileSystem.fullPath(path);
- if( fpath != null ) path = fpath;
- path = path.split("\\").join("/");
- if( StringTools.startsWith(path.toLowerCase(), shadersPath.toLowerCase()+"/") ) {
- path = path.substr(shadersPath.length + 1);
- source = path;
- }
- #end
- }
- function loadShaderClass(opt=false) : Class<hxsl.Shader> {
- var path = source;
- if(StringTools.endsWith(path, ".hx")) path = path.substr(0, -3);
- var cpath = path.split("/").join(".");
- var cl = cast Type.resolveClass(cpath);
- if( cl == null && !opt ) throw "Missing shader class"+cpath;
- return cl;
- }
- public function loadShaderDef(ctx: Context) {
- if(shaderDef == null) {
- fixSourcePath();
- if( isInstance ) {
- shaderClass = loadShaderClass();
- var shared : hxsl.SharedShader = (shaderClass:Dynamic)._SHADER;
- if( shared == null ) {
- @:privateAccess Type.createEmptyInstance(shaderClass).initialize();
- shared = (shaderClass:Dynamic)._SHADER;
- }
- shaderDef = { shader : shared, inits : [] };
- } else {
- var path = source;
- if(StringTools.endsWith(path, ".hx")) path = path.substr(0, -3);
- shaderDef = ctx.loadShader(path);
- }
- }
- if(shaderDef == null)
- return;
- #if editor
- // TODO: Where to init prefab default values?
- for( v in shaderDef.inits ) {
- if(!Reflect.hasField(props, v.variable.name)) {
- Reflect.setField(props, v.variable.name, v.value);
- }
- }
- for(v in shaderDef.shader.data.vars) {
- if(v.kind != Param)
- continue;
- if(!Reflect.hasField(props, v.name)) {
- Reflect.setField(props, v.name, getDefault(v.type));
- }
- }
- #end
- }
- #if editor
- override function edit( ectx ) {
- super.edit(ectx);
- if( isInstance || loadShaderClass(true) != null ) {
- ectx.properties.add(hide.comp.PropsEditor.makePropsList([{
- name : "isInstance",
- t : PBool,
- }]), this);
- }
- }
- #end
- public static function evalConst( e : hxsl.Ast.TExpr ) : Dynamic {
- return switch( e.e ) {
- case TConst(c):
- switch( c ) {
- case CNull: null;
- case CBool(b): b;
- case CInt(i): i;
- case CFloat(f): f;
- case CString(s): s;
- }
- case TCall({ e : TGlobal(Vec2 | Vec3 | Vec4) }, args):
- var vals = [for( a in args ) evalConst(a)];
- if( vals.length == 1 )
- switch( e.t ) {
- case TVec(n, _):
- for( i in 0...n - 1 ) vals.push(vals[0]);
- return vals;
- default:
- throw "assert";
- }
- return vals;
- default:
- throw "Unhandled constant init " + hxsl.Printer.toString(e);
- }
- }
- public static function getDefault(type: hxsl.Ast.Type): Dynamic {
- switch(type) {
- case TBool:
- return false;
- case TInt:
- return 0;
- case TFloat:
- return 0.0;
- case TVec( size, VFloat ):
- return [for(i in 0...size) 0];
- default:
- return null;
- }
- return null;
- }
- static var _ = Library.register("shader", DynamicShader);
- }
|