Model.hx 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. package hrt.prefab;
  2. class Model extends Object3D {
  3. @:s public var animation : Null<String>;
  4. @:s var lockAnimation : Bool = false;
  5. @:s var retargetAnim : Bool = false;
  6. @:s var retargetIgnore : String;
  7. public function new(?parent) {
  8. super(parent);
  9. type = "model";
  10. }
  11. override function save() {
  12. if( retargetIgnore == "" ) retargetIgnore = null;
  13. return super.save();
  14. }
  15. override function makeInstance(ctx:Context):Context {
  16. if( source == null)
  17. return super.makeInstance(ctx);
  18. ctx = ctx.clone(this);
  19. #if editor
  20. try {
  21. #end
  22. var obj = ctx.loadModel(source);
  23. if(obj.defaultTransform != null && children.length > 0) {
  24. obj.name = "root";
  25. var root = new h3d.scene.Object();
  26. root.addChild(obj);
  27. obj = root;
  28. }
  29. #if editor
  30. for(m in obj.getMeshes())
  31. if( !Std.is(m,h3d.scene.Skin) )
  32. m.cullingCollider = new h3d.col.ObjectCollider(m, m.primitive.getBounds().toSphere());
  33. #end
  34. if( retargetAnim ) applyRetarget(obj);
  35. obj.name = name;
  36. ctx.local3d.addChild(obj);
  37. ctx.local3d = obj;
  38. updateInstance(ctx);
  39. if( animation != null )
  40. obj.playAnimation(ctx.loadAnimation(animation));
  41. return ctx;
  42. #if editor
  43. } catch( e : Dynamic ) {
  44. e.message = "Could not load model " + source + ": " + e.message;
  45. ctx.shared.onError(e);
  46. }
  47. #end
  48. ctx.local3d = new h3d.scene.Object(ctx.local3d);
  49. ctx.local3d.name = name;
  50. updateInstance(ctx);
  51. return ctx;
  52. }
  53. function applyRetarget( obj : h3d.scene.Object ) {
  54. if( !retargetAnim )
  55. return;
  56. var ignorePrefix = [], ignoreNames = new Map();
  57. if( retargetIgnore != null ) {
  58. for( i in retargetIgnore.split(",") ) {
  59. if( i.charCodeAt(i.length-1) == "*".code )
  60. ignorePrefix.push(i.substr(0,-1));
  61. else
  62. ignoreNames.set(i, true);
  63. }
  64. }
  65. for( o in obj.getMeshes() ) {
  66. var sk = Std.downcast(o, h3d.scene.Skin);
  67. if( sk == null ) continue;
  68. for( j in sk.getSkinData().allJoints ) {
  69. var ignored = ignoreNames.get(j.name);
  70. if( ignored ) continue;
  71. for( i in ignorePrefix )
  72. if( StringTools.startsWith(j.name,i) ) {
  73. ignored = true;
  74. break;
  75. }
  76. if( !ignored )
  77. j.retargetAnim = true;
  78. }
  79. }
  80. }
  81. #if editor
  82. override function updateInstance( ctx: Context, ?propName : String ) {
  83. super.updateInstance(ctx, propName);
  84. polys3D = null;
  85. boundingSphere = null;
  86. }
  87. var polys3D = null;
  88. var boundingSphere = null;
  89. override function localRayIntersection( ctx : Context, ray : h3d.col.Ray ) : Float {
  90. if( polys3D == null ) {
  91. polys3D = [];
  92. var bounds = ctx.local3d.getBounds();
  93. bounds.transform(ctx.local3d.getAbsPos().getInverse());
  94. boundingSphere = bounds.toSphere();
  95. for( m in ctx.shared.getObjects(this, h3d.scene.Mesh) ) {
  96. var p = cast(m.primitive, h3d.prim.HMDModel);
  97. var col = cast(cast(p.getCollider(), h3d.col.Collider.OptimizedCollider).b, h3d.col.PolygonBuffer);
  98. polys3D.push({ col : col, mat : m.getRelPos(ctx.local3d).getInverse() });
  99. }
  100. }
  101. if( boundingSphere.rayIntersection(ray,false) < 0 )
  102. return -1.;
  103. var minD = -1.;
  104. for( p in polys3D ) {
  105. var ray2 = ray.clone();
  106. ray2.transform(p.mat);
  107. var d = p.col.rayIntersection(ray2, true);
  108. if( d > 0 && (d < minD || minD == -1) )
  109. minD = d;
  110. }
  111. return minD;
  112. }
  113. override function edit( ctx : EditContext ) {
  114. super.edit(ctx);
  115. var props = ctx.properties.add(new hide.Element('
  116. <div class="group" name="Animation">
  117. <dl>
  118. <dt>Model</dt><dd><input type="model" field="source"/></dd>
  119. <dt>Animation</dt><dd><select><option value="">-- Choose --</option></select>
  120. <dt title="Don\'t save animation changes">Lock</dt><dd><input type="checkbox" field="lockAnimation"></dd>
  121. <dt>Retarget</dt><dd><input type="checkbox" field="retargetAnim"></dd>
  122. <dt>Retarget Ignore</dt><dd><input type="text" field="retargetIgnore"></dd>
  123. </dl>
  124. </div>
  125. '),this, function(pname) {
  126. if( pname == "retargetIgnore" && ctx.properties.isTempChange ) return;
  127. ctx.onChange(this, pname);
  128. });
  129. var select = props.find("select");
  130. var anims = try ctx.scene.listAnims(source) catch(e: Dynamic) [];
  131. for( a in anims )
  132. new hide.Element('<option>').attr("value", ctx.ide.makeRelative(a)).text(ctx.scene.animationName(a)).appendTo(select);
  133. if( animation != null )
  134. select.val(animation);
  135. select.change(function(_) {
  136. var v = select.val();
  137. var prev = animation;
  138. var obj = ctx.getContext(this).local3d;
  139. ctx.scene.setCurrent();
  140. if( v == "" ) {
  141. animation = null;
  142. obj.stopAnimation();
  143. } else {
  144. obj.playAnimation(ctx.rootContext.loadAnimation(v)).loop = true;
  145. if( lockAnimation ) return;
  146. animation = v;
  147. }
  148. var newValue = animation;
  149. ctx.properties.undo.change(Custom(function(undo) {
  150. var obj = ctx.getContext(this).local3d;
  151. animation = undo ? prev : newValue;
  152. if( animation == null ) {
  153. obj.stopAnimation();
  154. select.val("");
  155. } else {
  156. obj.playAnimation(ctx.rootContext.loadAnimation(animation)).loop = true;
  157. select.val(v);
  158. }
  159. }));
  160. });
  161. }
  162. override function getHideProps() : HideProps {
  163. return {
  164. icon : "cube", name : "Model", fileSource : ["fbx","hmd"],
  165. allowChildren : function(t) return Library.isOfType(t,Object3D) || Library.isOfType(t,Material) || Library.isOfType(t,Shader) || Library.isOfType(t, hrt.prefab.fx.AnimEvent),
  166. onResourceRenamed : function(f) animation = f(animation),
  167. };
  168. }
  169. #end
  170. static var _ = Library.register("model", Model);
  171. }