123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 |
- package hrt.prefab;
- import hxd.Math;
- using Lambda;
- class Object3D extends Prefab {
- @:s public var x : Float = 0.;
- @:s public var y : Float = 0.;
- @:s public var z : Float = 0.;
- @:s public var scaleX : Float = 1.;
- @:s public var scaleY : Float = 1.;
- @:s public var scaleZ : Float = 1.;
- @:s public var rotationX : Float = 0.;
- @:s public var rotationY : Float = 0.;
- @:s public var rotationZ : Float = 0.;
- @:s public var visible : Bool = true;
- public function new(?parent) {
- super(parent);
- type = "object";
- }
- public function loadTransform(t) {
- x = t.x;
- y = t.y;
- z = t.z;
- scaleX = t.scaleX;
- scaleY = t.scaleY;
- scaleZ = t.scaleZ;
- rotationX = t.rotationX;
- rotationY = t.rotationY;
- rotationZ = t.rotationZ;
- }
- public function saveTransform() {
- return { x : x, y : y, z : z, scaleX : scaleX, scaleY : scaleY, scaleZ : scaleZ, rotationX : rotationX, rotationY : rotationY, rotationZ : rotationZ };
- }
- public function localRayIntersection( ctx : Context, ray : h3d.col.Ray ) : Float {
- return -1;
- }
- function createObject(ctx:Context) {
- return new h3d.scene.Object(ctx.local3d);
- }
- override function makeInstance(ctx:Context):Context {
- ctx = ctx.clone(this);
- ctx.local3d = createObject(ctx);
- ctx.local3d.name = name;
- updateInstance(ctx);
- return ctx;
- }
- public function setTransform(mat : h3d.Matrix) {
- var rot = mat.getEulerAngles();
- x = mat.tx;
- y = mat.ty;
- z = mat.tz;
- var s = mat.getScale();
- scaleX = s.x;
- scaleY = s.y;
- scaleZ = s.z;
- rotationX = Math.radToDeg(rot.x);
- rotationY = Math.radToDeg(rot.y);
- rotationZ = Math.radToDeg(rot.z);
- }
- public function getTransform( ?m: h3d.Matrix ) {
- if( m == null ) m = new h3d.Matrix();
- m.initScale(scaleX, scaleY, scaleZ);
- m.rotate(Math.degToRad(rotationX), Math.degToRad(rotationY), Math.degToRad(rotationZ));
- m.translate(x, y, z);
- return m;
- }
- public function getAbsPos() {
- var p = parent;
- while( p != null ) {
- var obj = p.to(Object3D);
- if( obj == null ) {
- p = p.parent;
- continue;
- }
- var m = getTransform();
- var abs = obj.getAbsPos();
- m.multiply3x4(m, abs);
- return m;
- }
- return getTransform();
- }
- public function applyTransform( o : h3d.scene.Object ) {
- o.x = x;
- o.y = y;
- o.z = z;
- o.scaleX = scaleX;
- o.scaleY = scaleY;
- o.scaleZ = scaleZ;
- o.setRotation(Math.degToRad(rotationX), Math.degToRad(rotationY), Math.degToRad(rotationZ));
- }
- override function updateInstance( ctx: Context, ?propName : String ) {
- var o = ctx.local3d;
- applyTransform(o);
- o.visible = visible;
- #if editor
- addEditorUI(ctx);
- #end
- }
- override function removeInstance(ctx: Context):Bool {
- if(ctx.local3d != null)
- ctx.local3d.remove();
- #if editor
- if( ctx.local2d != null ) {
- var f = Std.downcast(ctx.local2d, h2d.ObjectFollower);
- if( f != null && f.follow == ctx.local3d ) f.remove();
- }
- #end
- return true;
- }
- #if editor
- override function setSelected(ctx:Context, b:Bool):Bool {
- var materials = ctx.shared.getMaterials(this);
- if( !b ) {
- for( m in materials ) {
- //m.mainPass.stencil = null;
- m.removePass(m.getPass("highlight"));
- m.removePass(m.getPass("highlightBack"));
- }
- return true;
- }
- var shader = new h3d.shader.FixedColor(0xffffff);
- var shader2 = new h3d.shader.FixedColor(0xff8000);
- for( m in materials ) {
- if( m.name != null && StringTools.startsWith(m.name,"$UI.") )
- continue;
- var p = m.allocPass("highlight");
- p.culling = None;
- p.depthWrite = false;
- p.depthTest = LessEqual;
- p.addShader(shader);
- var p = m.allocPass("highlightBack");
- p.culling = None;
- p.depthWrite = false;
- p.depthTest = Always;
- p.addShader(shader2);
- }
- return true;
- }
- public function addEditorUI( ctx : Context ) {
- for( r in ctx.shared.getObjects(this,h3d.scene.Object) )
- if( r.name != null && StringTools.startsWith(r.name,"$UI.") )
- r.remove();
- // add ranges
- var shared = Std.downcast(ctx.shared, hide.prefab.ContextShared);
- if( shared != null && shared.editorDisplay ) {
- var sheet = getCdbType();
- if( sheet != null ) {
- var ide = hide.Ide.inst;
- var ranges = Reflect.field(shared.scene.config.get("sceneeditor.ranges"), sheet);
- if( ranges != null ) {
- for( key in Reflect.fields(ranges) ) {
- var color = Std.parseInt(Reflect.field(ranges,key));
- var value : Dynamic = ide.resolveCDBValue(sheet,key, props);
- if( value != null ) {
- var mesh = new h3d.scene.Mesh(h3d.prim.Cylinder.defaultUnitCylinder(128), ctx.local3d);
- mesh.name = "$UI.RANGE";
- mesh.ignoreCollide = true;
- mesh.ignoreBounds = true;
- mesh.material.mainPass.culling = None;
- mesh.material.name = "$UI.RANGE";
- mesh.setScale(value * 2);
- mesh.scaleZ = 0.1;
- mesh.material.color.setColor(color|0xFF000000);
- mesh.material.mainPass.enableLights = false;
- mesh.material.shadows = false;
- mesh.material.mainPass.setPassName("overlay");
- }
- }
- }
- var huds : Dynamic = shared.scene.config.get("sceneeditor.huds");
- var icon = Reflect.field(huds, sheet);
- if( icon != null ) {
- var t : Dynamic = ide.resolveCDBValue(sheet,icon, props);
- if( t != null && (t.file != null || Std.is(t,String)) ) {
- var obj = Std.downcast(ctx.local2d, h2d.ObjectFollower);
- if( obj == null || obj.follow != ctx.local3d ) {
- ctx.local2d = obj = new h2d.ObjectFollower(ctx.local3d, ctx.local2d);
- obj.horizontalAlign = Middle;
- obj.followVisibility = true;
- }
- if( t.file != null ) {
- var t : cdb.Types.TilePos = t;
- var bmp = Std.downcast(obj.getObjectByName("$huds"), h2d.Bitmap);
- if( bmp == null ) {
- bmp = new h2d.Bitmap(null, obj);
- bmp.name = "$huds";
- }
- bmp.tile = h2d.Tile.fromTexture(ctx.loadTexture(t.file)).sub(
- t.x * t.size,
- t.y * t.size,
- (t.width == null ? 1 : t.width) * t.size,
- (t.height == null ? 1 : t.height) * t.size
- );
- var maxWidth : Dynamic = huds.maxWidth;
- if( maxWidth != null && bmp.tile.width > maxWidth )
- bmp.width = maxWidth;
- } else {
- var f = Std.downcast(obj.getObjectByName("$huds_f"), h2d.Flow);
- if( f == null ) {
- f = new h2d.Flow(obj);
- f.name = "$huds_f";
- f.padding = 3;
- f.paddingTop = 1;
- f.backgroundTile = h2d.Tile.fromColor(0,1,1,0.5);
- }
- var tf = cast(f.getChildAt(1), h2d.Text);
- if( tf == null )
- tf = new h2d.Text(hxd.res.DefaultFont.get(), f);
- tf.text = t;
- }
- }
- }
- }
- }
- }
- override function makeInteractive( ctx : Context ) : hxd.SceneEvents.Interactive {
- var local3d = ctx.local3d;
- if(local3d == null)
- return null;
- var meshes = ctx.shared.getObjects(this, h3d.scene.Mesh);
- var invRootMat = local3d.getAbsPos().clone();
- invRootMat.invert();
- var bounds = new h3d.col.Bounds();
- var localBounds = [];
- var totalSeparateBounds = 0.;
- var visibleMeshes = [];
- var hasSkin = false;
- inline function getVolume(b:h3d.col.Bounds) {
- var c = b.getSize();
- return c.x * c.y * c.z;
- }
- for(mesh in meshes) {
- if(mesh.ignoreCollide)
- continue;
- // invisible objects are ignored collision wise
- var p : h3d.scene.Object = mesh;
- while( p != local3d ) {
- if( !p.visible ) break;
- p = p.parent;
- }
- if( p != local3d ) continue;
- var localMat = mesh.getAbsPos().clone();
- localMat.multiply(localMat, invRootMat);
- if( mesh.primitive == null ) continue;
- visibleMeshes.push(mesh);
- if( Std.downcast(mesh, h3d.scene.Skin) != null ) {
- hasSkin = true;
- continue;
- }
- var lb = mesh.primitive.getBounds().clone();
- lb.transform(localMat);
- bounds.add(lb);
- totalSeparateBounds += getVolume(lb);
- for( b in localBounds ) {
- var tmp = new h3d.col.Bounds();
- tmp.intersection(lb, b);
- totalSeparateBounds -= getVolume(tmp);
- }
- localBounds.push(lb);
- }
- if( visibleMeshes.length == 0 )
- return null;
- var colliders = [for(m in visibleMeshes) {
- var c : h3d.col.Collider = try m.getGlobalCollider() catch(e: Dynamic) null;
- if(c != null) c;
- }];
- var meshCollider = colliders.length == 1 ? colliders[0] : new h3d.col.Collider.GroupCollider(colliders);
- var collider : h3d.col.Collider = new h3d.col.ObjectCollider(local3d, bounds);
- if( hasSkin ) {
- collider = meshCollider; // can't trust bounds
- meshCollider = null;
- } else if( totalSeparateBounds / getVolume(bounds) < 0.5 ) {
- collider = new h3d.col.Collider.OptimizedCollider(collider, meshCollider);
- meshCollider = null;
- }
- var int = new h3d.scene.Interactive(collider, local3d);
- int.ignoreParentTransform = true;
- int.preciseShape = meshCollider;
- int.propagateEvents = true;
- int.enableRightButton = true;
- return int;
- }
- override function edit( ctx : EditContext ) {
- var props = new hide.Element('
- <div class="group" name="Position">
- <dl>
- <dt>X</dt><dd><input type="range" min="-10" max="10" value="0" field="x"/></dd>
- <dt>Y</dt><dd><input type="range" min="-10" max="10" value="0" field="y"/></dd>
- <dt>Z</dt><dd><input type="range" min="-10" max="10" value="0" field="z"/></dd>
- <dt>Scale X</dt><dd><input type="range" min="0" max="5" value="1" field="scaleX"/></dd>
- <dt>Scale Y</dt><dd><input type="range" min="0" max="5" value="1" field="scaleY"/></dd>
- <dt>Scale Z</dt><dd><input type="range" min="0" max="5" value="1" field="scaleZ"/></dd>
- <dt>Rotation X</dt><dd><input type="range" min="-180" max="180" value="0" field="rotationX" /></dd>
- <dt>Rotation Y</dt><dd><input type="range" min="-180" max="180" value="0" field="rotationY" /></dd>
- <dt>Rotation Z</dt><dd><input type="range" min="-180" max="180" value="0" field="rotationZ" /></dd>
- <dt>Visible</dt><dd><input type="checkbox" field="visible"/></dd>
- </dl>
- </div>
- ');
- ctx.properties.add(props, this, function(pname) {
- ctx.onChange(this, pname);
- });
- }
- override function getHideProps() : HideProps {
- // Check children
- var cname = Type.getClassName(Type.getClass(this)).split(".").pop();
- return {
- icon : children == null || children.length > 0 ? "folder-open" : "genderless",
- name : cname == "Object3D" ? "Group" : cname,
- };
- }
- #end
- override function getDefaultName() {
- return type == "object" ? "group" : super.getDefaultName();
- }
- static var _ = Library.register("object", Object3D);
- }
|