TreeView.hx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. package;
  2. import hxd.Res;
  3. class Joint {
  4. var j : h3d.anim.Skin.Joint;
  5. var s : h3d.scene.Mesh;
  6. public var visible(default, set) : Bool;
  7. public function new (j : h3d.anim.Skin.Joint, parent: h3d.scene.Skin) {
  8. this.j = j;
  9. var p = new h3d.prim.Sphere(1, 16, 16);
  10. p.addNormals();
  11. s = new h3d.scene.Mesh(p, parent);
  12. s.setScale(0.015);
  13. s.follow = parent.getObjectByName(j.name);
  14. s.name = "Joint("+j.name+")";
  15. s.material.color.setColor(0xFF0000);
  16. s.material.mainPass.depth(false, Always);
  17. s.material.mainPass.setPassName("add");
  18. s.material.mainPass.enableLights = false;
  19. visible = false;
  20. }
  21. function set_visible(b : Bool) {
  22. return s.visible = visible = b;
  23. }
  24. public function remove() {
  25. s.remove();
  26. }
  27. public function update(dt : Float) {
  28. }
  29. }
  30. class TreeView
  31. {
  32. static var minWidth(default, set) = 0;
  33. static var minHeight(default, set) = 0;
  34. static var elts : Array<TreeView>;
  35. static var curr : Array<TreeView>;
  36. static var cont : h2d.Sprite;
  37. static var box : h2d.Bitmap;
  38. static var height = 18;
  39. static var bt : h2d.Interactive;
  40. static var fg : h2d.Bitmap;
  41. static var select : h2d.Bitmap;
  42. static var highlight : TreeView;
  43. static var s2d : h2d.Scene.Scene;
  44. static var dot : h2d.Bitmap;
  45. static var dummy : h3d.scene.Mesh;
  46. var obj : h3d.scene.Object;
  47. var childs : Array<TreeView>;
  48. var parent : TreeView;
  49. var unfold = true;
  50. var tf : h2d.Text;
  51. var arrow : h2d.Bitmap;
  52. var joints : Array<Joint>;
  53. var isdummy = false;
  54. public var showJoints(default, set): Bool;
  55. public var visible(default, set): Bool;
  56. public var x(default, set) : Float;
  57. public var y(default, set) : Float;
  58. public var selected : TreeView;
  59. public static var currentOver : TreeView;
  60. public function new (o, parent = null) {
  61. if(cont == null)
  62. throw("TreeView must be initialized");
  63. this.obj = o;
  64. this.parent = parent;
  65. this.childs = [];
  66. elts.push(this);
  67. if(Std.is(o, h3d.scene.Skin)) {
  68. unfold = false;
  69. var s = cast(o, h3d.scene.Skin);
  70. joints = [];
  71. for( j in s.getSkinData().allJoints)
  72. joints.push(new Joint(j, s));
  73. }
  74. if(!o.isMesh() && o.numChildren == 0 )
  75. isdummy = true;
  76. if(parent == null) {
  77. function getCur(e:hxd.Event) {
  78. var id = Std.int(e.relY / height);
  79. return curr[id];
  80. }
  81. bt.onOver = function(e:hxd.Event) {
  82. fg.visible = true;
  83. currentOver = getCur(e);
  84. }
  85. bt.onOut = function(e:hxd.Event) {
  86. fg.visible = false;
  87. if(!select.visible)
  88. setHighligth(null);
  89. currentOver = null;
  90. }
  91. bt.onMove = function(e:hxd.Event) {
  92. var id = Std.int(e.relY / height);
  93. fg.y = id * height;
  94. currentOver = getCur(e);
  95. if(!select.visible){
  96. select.y = id * height;
  97. setHighligth(curr[id]);
  98. }
  99. else setHighligth(curr[Std.int(select.y / height)]);
  100. }
  101. bt.onClick = function(e:hxd.Event) {
  102. var row = getCur(e);
  103. selected = row;
  104. if(row.childs.length == 0) {
  105. if(fg.y == select.y)
  106. select.visible = !select.visible;
  107. else {
  108. select.y = fg.y;
  109. select.visible = true;
  110. }
  111. }
  112. else {
  113. row.unfold = !row.unfold;
  114. if(!row.unfold && select.visible) {
  115. //remove selected if parent is closed
  116. var e = curr[Std.int(select.y / height)];
  117. if(row.parent == null || e.parent == row)
  118. select.visible = false;
  119. }
  120. var old = select.visible ? curr[Std.int(select.y / height)] : null;
  121. draw();
  122. //update new select position
  123. if(old != null)
  124. for( i in 0...curr.length) {
  125. if(curr[i] == old) {
  126. select.y = i * height;
  127. break;
  128. }
  129. }
  130. }
  131. bt.onMove(e);
  132. }
  133. bt.onWheel = function(e : hxd.Event) {
  134. cont.y -= e.wheelDelta * height * 3;
  135. };
  136. bt.onKeyDown = function(e) {
  137. e.propagate = true;
  138. };
  139. bt.onKeyUp = function(e) {
  140. e.propagate = true;
  141. };
  142. getObjectsLib(this);
  143. draw();
  144. }
  145. }
  146. public function onKey(e:hxd.Event) {
  147. if( e.keyCode == "V".code )
  148. obj.visible = !obj.visible;
  149. }
  150. function setHighligth(e : TreeView) {
  151. if(highlight != null) {
  152. for( m in highlight.getMaterials() )
  153. m.mainPass.removeShader(m.mainPass.getShader(h3d.shader.ColorAdd));
  154. var skin = highlight.joints != null ? highlight : null;
  155. if(skin == null && highlight.parent != null)
  156. skin = highlight.parent.joints != null ? highlight.parent : null;
  157. if(skin != null && !Viewer.props.showBones) {
  158. cast(skin.obj, h3d.scene.Skin).showJoints = false;
  159. for(j in skin.joints)
  160. j.visible = false;
  161. }
  162. if(highlight.obj.name != null && highlight.obj.name.substr(0, 5) == "Joint") {
  163. highlight.obj.toMesh().material.color.setColor(0xFF0000);
  164. highlight.obj.setScale(0.015);
  165. }
  166. setDummy();
  167. }
  168. highlight = e;
  169. if(highlight != null) {
  170. var skin = highlight.joints != null ? highlight : null;
  171. if(skin == null && highlight.parent != null && highlight.obj.name.substr(0, 5) == "Joint")
  172. skin = highlight.parent.joints != null ? highlight.parent : null;
  173. if(skin != null) {
  174. cast(skin.obj, h3d.scene.Skin).showJoints = true;
  175. for(j in skin.joints)
  176. j.visible = true;
  177. }
  178. if(highlight.obj.name != null && highlight.obj.name.substr(0, 5) == "Joint") {
  179. highlight.obj.toMesh().material.color.setColor(0xFF00FF);
  180. highlight.obj.setScale(0.025);
  181. }
  182. if(e.isdummy)
  183. setDummy(e.obj);
  184. }
  185. }
  186. function getObjectsLib(parent : TreeView) {
  187. function getObjectsRec( e : TreeView) {
  188. for( o in e.obj ) {
  189. var child = new TreeView(o, e);
  190. e.childs.push(child);
  191. getObjectsRec(child);
  192. }
  193. if( Viewer.props.materials ) {
  194. var m = e.obj.isMesh() ? e.obj.toMesh() : null;
  195. var mm = Std.instance(m, h3d.scene.MultiMaterial);
  196. var mats = if( mm != null ) mm.materials else if( m != null && m.material.name != null ) [m.material] else [];
  197. for( m in mats ) {
  198. var child = new TreeMaterial(e.obj, e, m);
  199. e.childs.push(child);
  200. }
  201. }
  202. }
  203. getObjectsRec(parent);
  204. }
  205. static function set_minWidth(v : Int) {
  206. box.tile = h2d.Tile.fromColor(0, v, minHeight, 0.3);
  207. fg.tile = h2d.Tile.fromColor(0, v, height, 0.3);
  208. select.tile = h2d.Tile.fromColor(0, v, height, 0.3);
  209. bt.width = v;
  210. return minWidth = v;
  211. }
  212. static function set_minHeight(v : Int) {
  213. box.tile = h2d.Tile.fromColor(0, minWidth, v, 0.3);
  214. bt.height = v;
  215. return minHeight = v;
  216. }
  217. function set_x(v : Float) {
  218. return cont.x = v;
  219. }
  220. function set_y(v : Float) {
  221. return cont.y = v;
  222. }
  223. public static function init(scene2d) {
  224. s2d = scene2d;
  225. if(cont == null) {
  226. cont = new h2d.Sprite(s2d);
  227. box = new h2d.Bitmap(h2d.Tile.fromColor(0), cont);
  228. fg = new h2d.Bitmap(h2d.Tile.fromColor(0), cont);
  229. fg.visible = false;
  230. select = new h2d.Bitmap(h2d.Tile.fromColor(0), cont);
  231. select.visible = false;
  232. bt = new h2d.Interactive(0, 0, cont);
  233. var t = Res.dot.toTile();
  234. t.dx -= t.width >> 1;
  235. t.dy -= t.height >> 1;
  236. dot = new h2d.Bitmap(t, cont);
  237. dot.visible = false;
  238. }
  239. clear();
  240. elts = [];
  241. if(dummy != null) {
  242. dummy.remove();
  243. dummy = null;
  244. }
  245. }
  246. static function clear() {
  247. minWidth = 0;
  248. minHeight = 0;
  249. curr = [];
  250. if(elts != null)
  251. for( e in elts)
  252. if(e.tf != null) {
  253. e.tf.remove();
  254. if(e.arrow != null)
  255. e.arrow.remove();
  256. }
  257. }
  258. function getName() {
  259. var str = obj.toString();
  260. return StringTools.startsWith(str, "Mesh(Joint(") ? str.substr(5, str.length - 6) : str;
  261. }
  262. function isVisible() {
  263. return obj.visible;
  264. }
  265. public function draw(level = 0) {
  266. if(level == 0)
  267. clear();
  268. var dx = 14 + (parent != null ? parent.tf.x : 0);
  269. var font = hxd.res.DefaultFont.get();
  270. if(childs.length != 0) {
  271. var t = Res.arrow.toTile();
  272. t.dx -= t.width >> 1;
  273. t.dy -= t.height >> 1;
  274. arrow = new h2d.Bitmap(t, cont);
  275. arrow.x = dx - 5;
  276. arrow.y = minHeight + (height >> 1) + 1;
  277. }
  278. if(tf != null) tf.remove();
  279. tf = new h2d.Text(font, cont);
  280. tf.text = getName();
  281. tf.color.setColor(isVisible() ? 0xFFFFFFFF : 0xFF808080);
  282. tf.x = 5 + dx;
  283. tf.y = 1 + minHeight;
  284. minWidth = Std.int(Math.max(minWidth, tf.x + tf.textWidth + 10));
  285. minHeight += height;
  286. curr.push(this);
  287. if(unfold) {
  288. if(arrow != null) {
  289. arrow.rotation = Math.PI * 0.5;
  290. arrow.y += 1;
  291. }
  292. for(c in childs)
  293. c.draw(level + 1);
  294. }
  295. }
  296. function set_showJoints(b : Bool) {
  297. for ( e in elts) {
  298. if(e.joints != null)
  299. for(j in e.joints)
  300. j.visible = b;
  301. }
  302. return showJoints = b;
  303. }
  304. function getMaterials() {
  305. return obj.getMaterials();
  306. }
  307. function setDummy(?o : h3d.scene.Object) {
  308. if(o == null) {
  309. if(dummy != null)
  310. dummy.visible = false;
  311. return;
  312. }
  313. if(dummy == null) {
  314. var p = new h3d.prim.Sphere(16, 16);
  315. p.addNormals();
  316. dummy = new h3d.scene.Mesh(p, o);
  317. dummy.material.color.setColor(0xFF00FF);
  318. dummy.material.mainPass.depth(false, Always);
  319. dummy.material.mainPass.setPassName("add");
  320. dummy.material.mainPass.enableLights = false;
  321. }
  322. o.addChild(dummy);
  323. dummy.visible = true;
  324. }
  325. var vect = new h3d.Vector(1, 0.5, 0.5);
  326. var cpt = 0.;
  327. public function update(dt:Float) {
  328. if(parent == null) {
  329. if(highlight != null) {
  330. var s = 0.8 + 0.2 * Math.sin(cpt);
  331. var color = new h3d.Vector(vect.x * s, vect.y * s, vect.z * s);
  332. for( m in highlight.getMaterials() ) {
  333. m.mainPass.removeShader(m.mainPass.getShader(h3d.shader.ColorAdd));
  334. m.mainPass.addShader(new h3d.shader.ColorAdd(color.toColor()));
  335. }
  336. }
  337. cpt += 0.5 * dt;
  338. }
  339. for(c in childs)
  340. c.update(dt);
  341. if(joints != null)
  342. for (j in joints)
  343. j.update(dt);
  344. if(box.tile.height <= s2d.height)
  345. cont.y = 0;
  346. else cont.y = Math.max( -box.tile.height + s2d.height - height, Math.min(0, cont.y));
  347. dot.visible = select.visible;
  348. if(dot.visible) {
  349. var e = curr[Std.int(select.y / height)];
  350. dot.x = e.tf.x - 10;
  351. dot.y = select.y + 12;
  352. }
  353. if(dummy != null && dummy.visible) {
  354. var cam = @:privateAccess Viewer.inst.s3d.camera;
  355. var d = cam.pos.sub(cam.target).length();
  356. dummy.setScale(0.003 * d);
  357. }
  358. }
  359. function set_visible(b : Bool) {
  360. cont.visible = b;
  361. return visible = b;
  362. }
  363. public function trace(level = 0) {
  364. var offset = "";
  365. for (i in 0...level) offset += " ";
  366. offset += "-> ";
  367. trace(offset + obj);
  368. for(c in childs)
  369. c.trace(level + 1);
  370. }
  371. }
  372. class TreeMaterial extends TreeView {
  373. var mat : h3d.mat.Material;
  374. public function new(o, parent, mat) {
  375. this.mat = mat;
  376. super(o, parent);
  377. }
  378. override function getObjectsLib(parent:TreeView) {
  379. // nothing
  380. }
  381. override function getName() {
  382. return "Material" + mat.name;
  383. }
  384. override function onKey(e:hxd.Event) {
  385. switch( e.keyCode ) {
  386. case "V".code:
  387. mat.mainPass.culling = (mat.mainPass.culling == Both ? None : Both);
  388. case "T".code:
  389. hxd.File.browse(function(sel) {
  390. sel.load(function(bytes) {
  391. mat.texture = hxd.res.Any.fromBytes("", bytes).toTexture();
  392. });
  393. },{ fileTypes : [{ name : "Texture", extensions : ["png","gif","jpg","jpeg"] }] });
  394. default:
  395. }
  396. }
  397. override function getMaterials() : Array<h3d.mat.Material> {
  398. return [mat];
  399. }
  400. override function isVisible() {
  401. return mat.mainPass.culling != Both && super.isVisible();
  402. }
  403. }