ContextShared.hx 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. package hrt.prefab;
  2. typedef ShaderDef = {
  3. var shader : hxsl.SharedShader;
  4. var inits : Array<{ v : hxsl.Ast.TVar, e : hxsl.Ast.TExpr }>;
  5. }
  6. typedef ShaderDefCache = Map<String, ShaderDef>;
  7. class ContextShared {
  8. public var root2d : h2d.Object;
  9. public var root3d : h3d.scene.Object;
  10. public var contexts : Map<Prefab,Context>;
  11. public var references : Map<Prefab,Array<Context>>;
  12. public var currentPath : String;
  13. public var editorDisplay : Bool;
  14. var cache : h3d.prim.ModelCache;
  15. var shaderCache : ShaderDefCache;
  16. var bakedData : Map<String, haxe.io.Bytes>;
  17. public function new() {
  18. root2d = new h2d.Object();
  19. root3d = new h3d.scene.Object();
  20. contexts = new Map();
  21. references = new Map();
  22. cache = new h3d.prim.ModelCache();
  23. shaderCache = new ShaderDefCache();
  24. }
  25. public function onError( e : Dynamic ) {
  26. throw e;
  27. }
  28. public function elements() {
  29. return [for(e in contexts.keys()) e];
  30. }
  31. public function getContexts(p: Prefab) {
  32. var ret : Array<Context> = [];
  33. var ctx = contexts.get(p);
  34. if(ctx != null)
  35. ret.push(ctx);
  36. var ctxs = references.get(p);
  37. if(ctxs != null)
  38. return ret.concat(ctxs);
  39. return ret;
  40. }
  41. public function loadDir(p : String, ?dir : String ) : Array<hxd.res.Any> {
  42. var datPath = new haxe.io.Path(currentPath);
  43. datPath.ext = "dat";
  44. var path = datPath.toString() + "/" + p;
  45. if(dir != null) path += "/" + dir;
  46. return try hxd.res.Loader.currentInstance.dir(path) catch( e : hxd.res.NotFound ) null;
  47. }
  48. public function loadPrefabDat(file : String, ext : String, p : String) : hxd.res.Any {
  49. var datPath = new haxe.io.Path(currentPath);
  50. datPath.ext = "dat";
  51. var path = new haxe.io.Path(datPath.toString() + "/" + p + "/" + file);
  52. path.ext = ext;
  53. return try hxd.res.Loader.currentInstance.load(path.toString()) catch( e : hxd.res.NotFound ) null;
  54. }
  55. public function savePrefabDat(file : String, ext : String, p : String, bytes : haxe.io.Bytes ) {
  56. throw "Not implemented";
  57. }
  58. public function loadPrefab( path : String ) : Prefab {
  59. throw "Not implemented";
  60. }
  61. public function loadShader( path : String ) : ShaderDef {
  62. var r = shaderCache.get(path);
  63. if(r != null)
  64. return r;
  65. var cl = Type.resolveClass(path.split("/").join("."));
  66. if(cl == null) return null;
  67. var shader = new hxsl.SharedShader(Reflect.field(cl, "SRC"));
  68. r = {
  69. shader: shader,
  70. inits: []
  71. };
  72. shaderCache.set(path, r);
  73. return r;
  74. }
  75. public function loadModel( path : String ) {
  76. return cache.loadModel(hxd.res.Loader.currentInstance.load(path).toModel());
  77. }
  78. public function loadAnimation( path : String ) {
  79. return @:privateAccess cache.loadAnimation(hxd.res.Loader.currentInstance.load(path).toModel());
  80. }
  81. public function loadTexture( path : String ) {
  82. return cache.loadTexture(null, path);
  83. }
  84. public function loadBytes( file : String) : haxe.io.Bytes {
  85. return try hxd.res.Loader.currentInstance.load(file).entry.getBytes() catch( e : hxd.res.NotFound ) null;
  86. }
  87. public function loadBakedBytes( file : String ) {
  88. if( bakedData == null ) loadBakedData();
  89. return bakedData.get(file);
  90. }
  91. public function saveBakedBytes( file : String, bytes : haxe.io.Bytes ) {
  92. if( bakedData == null ) loadBakedData();
  93. if( bytes == null ) {
  94. if( !bakedData.remove(file) )
  95. return;
  96. } else
  97. bakedData.set(file, bytes);
  98. var keys = Lambda.array({ iterator : bakedData.keys });
  99. if( keys.length == 0 ) {
  100. saveBakedFile(null);
  101. return;
  102. }
  103. var bytes = new haxe.io.BytesOutput();
  104. bytes.writeString("BAKE");
  105. bytes.writeInt32(keys.length);
  106. var headerSize = 8;
  107. for( name in keys )
  108. headerSize += 2 + name.length + 8;
  109. for( name in keys ) {
  110. bytes.writeUInt16(name.length);
  111. bytes.writeString(name);
  112. bytes.writeInt32(headerSize);
  113. var len = bakedData.get(name).length;
  114. bytes.writeInt32(len);
  115. headerSize += len + 1;
  116. }
  117. for( name in keys ) {
  118. bytes.write(bakedData.get(name));
  119. bytes.writeByte(0xFE); // stop
  120. }
  121. saveBakedFile(bytes.getBytes());
  122. }
  123. public function saveTexture( file : String, bytes : haxe.io.Bytes , dir : String, ext : String) {
  124. throw "Don't know how to save texture";
  125. }
  126. function saveBakedFile( bytes : haxe.io.Bytes ) {
  127. throw "Don't know how to save baked file";
  128. }
  129. function loadBakedFile() {
  130. var path = new haxe.io.Path(currentPath);
  131. path.ext = "bake";
  132. return try hxd.res.Loader.currentInstance.load(path.toString()).entry.getBytes() catch( e : hxd.res.NotFound ) null;
  133. }
  134. function loadBakedData() {
  135. bakedData = new Map();
  136. var data = loadBakedFile();
  137. if( data == null )
  138. return;
  139. if( data.getString(0,4) != "BAKE" )
  140. throw "Invalid bake file";
  141. var count = data.getInt32(4);
  142. var pos = 8;
  143. for( i in 0...count ) {
  144. var len = data.getUInt16(pos);
  145. pos += 2;
  146. var name = data.getString(pos, len);
  147. pos += len;
  148. var bytesPos = data.getInt32(pos);
  149. pos += 4;
  150. var bytesLen = data.getInt32(pos);
  151. pos += 4;
  152. bakedData.set(name,data.sub(bytesPos,bytesLen));
  153. if( data.get(bytesPos+bytesLen) != 0xFE )
  154. throw "Corrupted bake file";
  155. }
  156. }
  157. function getChildrenRoots( base : h3d.scene.Object, p : Prefab, out : Array<h3d.scene.Object> ) {
  158. for( c in p.children ) {
  159. var ctx = contexts.get(c);
  160. if( ctx == null ) continue;
  161. if( ctx.local3d == base )
  162. getChildrenRoots(base, c, out);
  163. else
  164. out.push(ctx.local3d);
  165. }
  166. return out;
  167. }
  168. public function getObjects<T:h3d.scene.Object>( p : Prefab, c: Class<T> ) : Array<T> {
  169. var ctx = contexts.get(p);
  170. if( ctx == null )
  171. return [];
  172. var root = ctx.local3d;
  173. var childObjs = getChildrenRoots(root, p, []);
  174. var ret = [];
  175. function rec(o : h3d.scene.Object) {
  176. var m = Std.instance(o, c);
  177. if(m != null) ret.push(m);
  178. for( child in o )
  179. if( childObjs.indexOf(child) < 0 )
  180. rec(child);
  181. }
  182. rec(root);
  183. return ret;
  184. }
  185. public function getMaterials( p : Prefab ) {
  186. var ctx = contexts.get(p);
  187. if( ctx == null )
  188. return [];
  189. var root = ctx.local3d;
  190. var childObjs = getChildrenRoots(root, p, []);
  191. var ret = [];
  192. function rec(o : h3d.scene.Object) {
  193. if( o.isMesh() ) {
  194. var m = o.toMesh();
  195. var multi = Std.instance(m, h3d.scene.MultiMaterial);
  196. if( multi != null ) {
  197. for( m in multi.materials )
  198. if( m != null )
  199. ret.push(m);
  200. } else if( m.material != null )
  201. ret.push(m.material);
  202. }
  203. for( child in o )
  204. if( childObjs.indexOf(child) < 0 )
  205. rec(child);
  206. }
  207. rec(root);
  208. return ret;
  209. }
  210. }