SplineEditor.hx 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. package hide.prefab;
  2. import hxd.Key as K;
  3. import hrt.prefab.l3d.Spline;
  4. #if editor
  5. class NewSplinePointViewer extends h3d.scene.Object {
  6. var pointViewer : h3d.scene.Mesh;
  7. var connectionViewer : h3d.scene.Graphics;
  8. var tangentViewer : h3d.scene.Graphics;
  9. public function new( parent : h3d.scene.Object ) {
  10. super(parent);
  11. name = "SplinePointViewer";
  12. pointViewer = new h3d.scene.Mesh(h3d.prim.Sphere.defaultUnitSphere(), null, this);
  13. pointViewer.name = "pointViewer";
  14. pointViewer.material.setDefaultProps("ui");
  15. pointViewer.material.color.set(1,1,0,1);
  16. pointViewer.material.mainPass.depthTest = Always;
  17. connectionViewer = new h3d.scene.Graphics(this);
  18. connectionViewer.name = "connectionViewer";
  19. connectionViewer.lineStyle(3, 0xFFFF00);
  20. connectionViewer.material.mainPass.setPassName("ui");
  21. connectionViewer.material.mainPass.depthTest = Always;
  22. connectionViewer.clear();
  23. tangentViewer = new h3d.scene.Graphics(this);
  24. tangentViewer.name = "tangentViewerViewer";
  25. tangentViewer.lineStyle(3, 0xFFFF00);
  26. tangentViewer.material.mainPass.setPassName("ui");
  27. tangentViewer.material.mainPass.depthTest = Always;
  28. tangentViewer.clear();
  29. }
  30. override function sync( ctx : h3d.scene.RenderContext ) {
  31. var cam = ctx.camera;
  32. var gpos = getAbsPos().getPosition();
  33. var distToCam = cam.pos.sub(gpos).length();
  34. var engine = h3d.Engine.getCurrent();
  35. var ratio = 18 / engine.height;
  36. var correctionFromParents = 1.0 / getAbsPos().getScale().x;
  37. pointViewer.setScale(correctionFromParents * ratio * distToCam * Math.tan(cam.fovY * 0.5 * Math.PI / 180.0));
  38. calcAbsPos();
  39. super.sync(ctx);
  40. }
  41. public function update( spd : SplinePointData ) {
  42. pointViewer.setPosition(spd.pos.x, spd.pos.y, spd.pos.z);
  43. tangentViewer.clear();
  44. tangentViewer.visible = spd.tangent != null;
  45. if( spd.tangent != null ) {
  46. var scale = 1.0;
  47. if( spd.prev != null && spd.next != null ) scale = (spd.prev.scaleX + spd.next.scaleX) * 0.5;
  48. else if( spd.prev != null ) scale = spd.prev.scaleX;
  49. else if( spd.next != null ) scale = spd.next.scaleX;
  50. tangentViewer.moveTo(spd.pos.x - spd.tangent.x * scale, spd.pos.y - spd.tangent.y * scale, spd.pos.z - spd.tangent.z * scale);
  51. tangentViewer.lineTo(spd.pos.x + spd.tangent.x * scale, spd.pos.y + spd.tangent.y * scale, spd.pos.z + spd.tangent.z * scale);
  52. }
  53. // Only display the connection if we are adding the new point at the end or the beggining fo the spline
  54. connectionViewer.clear();
  55. connectionViewer.visible = spd.prev == null || spd.next == null;
  56. if( connectionViewer.visible ) {
  57. var startPos = spd.prev == null ? spd.next.getPoint() : spd.prev.getPoint();
  58. connectionViewer.moveTo(startPos.x, startPos.y, startPos.z);
  59. connectionViewer.lineTo(spd.pos.x, spd.pos.y, spd.pos.z);
  60. }
  61. }
  62. }
  63. @:access(hrt.prefab.l3d.Spline)
  64. class SplineEditor {
  65. public var prefab : Spline;
  66. public var editContext : EditContext;
  67. var editMode = false;
  68. var undo : hide.ui.UndoHistory;
  69. var interactive : h2d.Interactive;
  70. // Easy way to keep track of viewers
  71. var gizmos : Array<hide.view.l3d.Gizmo> = [];
  72. var newSplinePointViewer : NewSplinePointViewer;
  73. public function new( prefab : Spline, undo : hide.ui.UndoHistory ){
  74. this.prefab = prefab;
  75. this.undo = undo;
  76. }
  77. public function update( ctx : hrt.prefab.Context , ?propName : String ) {
  78. if( editMode ) {
  79. showViewers();
  80. }
  81. }
  82. function reset() {
  83. removeViewers();
  84. removeGizmos();
  85. if( interactive != null ) {
  86. interactive.remove();
  87. interactive = null;
  88. }
  89. if( newSplinePointViewer != null ) {
  90. newSplinePointViewer.remove();
  91. newSplinePointViewer = null;
  92. }
  93. }
  94. inline function getContext() {
  95. return editContext.getContext(prefab);
  96. }
  97. function getClosestSplinePointFromMouse( mouseX : Float, mouseY : Float, ctx : hrt.prefab.Context ) : SplinePoint {
  98. if( ctx == null || ctx.local3d == null || ctx.local3d.getScene() == null )
  99. return null;
  100. var mousePos = new h3d.Vector( mouseX / h3d.Engine.getCurrent().width, 1.0 - mouseY / h3d.Engine.getCurrent().height, 0);
  101. var minDist = -1.0;
  102. var result : SplinePoint = null;
  103. for( sp in prefab.points ) {
  104. var screenPos = sp.getPoint().toVector();
  105. screenPos.project(ctx.local3d.getScene().camera.m);
  106. screenPos.z = 0;
  107. screenPos.scale3(0.5);
  108. screenPos = screenPos.add(new h3d.Vector(0.5,0.5));
  109. var dist = screenPos.distance(mousePos);
  110. if( dist < minDist || minDist == -1 ) {
  111. minDist = dist;
  112. result = sp;
  113. }
  114. }
  115. return result;
  116. }
  117. function getNewPointPosition( mouseX : Float, mouseY : Float, ctx : hrt.prefab.Context ) : SplinePointData {
  118. if( prefab.points.length == 0 ) {
  119. return { pos : ctx.local3d.getAbsPos().getPosition().toPoint(), tangent : ctx.local3d.getAbsPos().right().toPoint() , prev : null, next : null };
  120. }
  121. var closestPt = getClosestPointFromMouse(mouseX, mouseY, ctx);
  122. // If we are are adding a new point at the beginning/end, just make a raycast 'cursor -> plane' with the transform of the first/last SplinePoint
  123. if( !prefab.loop && (closestPt.next == null || closestPt.prev == null) ) {
  124. var camera = @:privateAccess ctx.local3d.getScene().camera;
  125. var ray = camera.rayFromScreen(mouseX, mouseY);
  126. var normal = closestPt.next == null ? closestPt.prev.getAbsPos().up().toPoint() : closestPt.next.getAbsPos().up().toPoint();
  127. var point = closestPt.next == null ? closestPt.prev.getAbsPos().getPosition().toPoint() : closestPt.next.getAbsPos().getPosition().toPoint();
  128. var plane = h3d.col.Plane.fromNormalPoint(normal, point);
  129. var pt = ray.intersect(plane);
  130. return { pos : pt, tangent : closestPt.tangent, prev : closestPt.prev, next : closestPt.next };
  131. }
  132. else
  133. return closestPt;
  134. }
  135. function getClosestPointFromMouse( mouseX : Float, mouseY : Float, ctx : hrt.prefab.Context ) : SplinePointData {
  136. if( ctx == null || ctx.local3d == null || ctx.local3d.getScene() == null )
  137. return null;
  138. var result : SplinePointData = null;
  139. var mousePos = new h3d.Vector( mouseX / h3d.Engine.getCurrent().width, 1.0 - mouseY / h3d.Engine.getCurrent().height, 0);
  140. var minDist = -1.0;
  141. for( s in prefab.data.samples ) {
  142. var screenPos = s.pos.toVector();
  143. screenPos.project(ctx.local3d.getScene().camera.m);
  144. screenPos.z = 0;
  145. screenPos.scale3(0.5);
  146. screenPos = screenPos.add(new h3d.Vector(0.5,0.5));
  147. var dist = screenPos.distance(mousePos);
  148. if( (dist < minDist || minDist == -1) && dist < 0.1 ) {
  149. minDist = dist;
  150. result = s;
  151. }
  152. }
  153. if( result == null ) {
  154. result = { pos : null, tangent : null, prev : null, next : null };
  155. var firstSp = prefab.points[0];
  156. var firstPt = firstSp.getPoint();
  157. var firstPtScreenPos = firstPt.toVector();
  158. firstPtScreenPos.project(ctx.local3d.getScene().camera.m);
  159. firstPtScreenPos.z = 0;
  160. firstPtScreenPos.scale3(0.5);
  161. firstPtScreenPos = firstPtScreenPos.add(new h3d.Vector(0.5,0.5));
  162. var distToFirstPoint = firstPtScreenPos.distance(mousePos);
  163. var lastSp = prefab.points[prefab.points.length - 1];
  164. var lastPt = lastSp.getPoint();
  165. var lastPtSreenPos = lastPt.toVector();
  166. lastPtSreenPos.project(ctx.local3d.getScene().camera.m);
  167. lastPtSreenPos.z = 0;
  168. lastPtSreenPos.scale3(0.5);
  169. lastPtSreenPos = lastPtSreenPos.add(new h3d.Vector(0.5,0.5));
  170. var distTolastPoint = lastPtSreenPos.distance(mousePos);
  171. if( distTolastPoint < distToFirstPoint ) {
  172. result.pos = lastPt;
  173. result.tangent = lastSp.getAbsPos().right().toPoint();
  174. result.prev = prefab.points[prefab.points.length - 1];
  175. result.next = null;
  176. }
  177. else {
  178. result.pos = firstPt;
  179. result.tangent = firstSp.getAbsPos().right().toPoint();
  180. result.prev = null;
  181. result.next = prefab.points[0];
  182. }
  183. }
  184. return result;
  185. }
  186. function addSplinePoint( spd : SplinePointData, ctx : hrt.prefab.Context ) : SplinePoint {
  187. var invMatrix = new h3d.Matrix();
  188. invMatrix.identity();
  189. var o : hrt.prefab.Object3D = prefab;
  190. while(o != null) {
  191. invMatrix.multiply(invMatrix, o.getTransform());
  192. o = o.parent.to(hrt.prefab.Object3D);
  193. }
  194. invMatrix.initInverse(invMatrix);
  195. var pos = spd.pos.toVector();
  196. pos.project(invMatrix);
  197. var index = 0;
  198. var scale = 1.0;
  199. if( spd.prev == null && spd.next == null ) {
  200. scale = 1.0;
  201. index = 0;
  202. }
  203. else if( spd.prev == null ) {
  204. index = 0;
  205. scale = prefab.points[0].getAbsPos().getScale().x;
  206. }
  207. else if( spd.next == null ) {
  208. index = prefab.points.length;
  209. scale = prefab.points[prefab.points.length - 1].getAbsPos().getScale().x;
  210. }
  211. else {
  212. index = prefab.points.indexOf(spd.next);
  213. scale = (spd.prev.scaleX + spd.next.scaleX) * 0.5;
  214. }
  215. var sp = new SplinePoint(prefab);
  216. sp.x = pos.x;
  217. sp.y = pos.y;
  218. sp.z = pos.z;
  219. prefab.children.remove(sp);
  220. prefab.children.insert(index, sp);
  221. if( spd.tangent != null ) {
  222. var dir = spd.tangent.toVector();
  223. dir.transform3x3(invMatrix); // Don't take the translation
  224. dir.scale3(-1);
  225. sp.rotationX = h3d.Matrix.lookAtX(dir).getFloats()[0];
  226. sp.rotationY = h3d.Matrix.lookAtX(dir).getFloats()[1];
  227. sp.rotationZ = h3d.Matrix.lookAtX(dir).getFloats()[2];
  228. }
  229. sp.scaleX = scale;
  230. sp.scaleY = scale;
  231. sp.scaleZ = scale;
  232. editContext.scene.editor.addElements([sp], false, true, false);
  233. prefab.updateInstance(ctx);
  234. showViewers();
  235. return sp;
  236. }
  237. function removeViewers() {
  238. for( sp in prefab.points ) {
  239. sp.setViewerVisible(false);
  240. }
  241. }
  242. function showViewers() {
  243. for( sp in prefab.points ) {
  244. sp.setViewerVisible(true);
  245. }
  246. }
  247. function removeGizmos() {
  248. for( g in gizmos ) {
  249. g.remove();
  250. @:privateAccess editContext.scene.editor.updates.remove(g.update);
  251. }
  252. gizmos = [];
  253. }
  254. function createGizmos( ctx : hrt.prefab.Context ) {
  255. removeGizmos(); // Security, avoid duplication
  256. var sceneEditor = @:privateAccess editContext.scene.editor;
  257. for( sp in prefab.points ) {
  258. var gizmo = new hide.view.l3d.Gizmo(editContext.scene);
  259. gizmo.getRotationQuat().identity();
  260. gizmo.visible = true;
  261. var tmpMat = new h3d.Matrix();
  262. tmpMat.load(sp.getAbsPos());
  263. var tmpScale = new h3d.Vector();
  264. tmpMat.getScale(tmpScale);
  265. tmpMat.prependScale(1.0/tmpScale.x, 1.0/tmpScale.y, 1.0/tmpScale.z);
  266. gizmo.setTransform(tmpMat);
  267. @:privateAccess sceneEditor.updates.push( gizmo.update );
  268. gizmos.insert(gizmos.length, gizmo);
  269. gizmo.visible = false; // Not visible by default, only show the closest in the onMove of interactive
  270. var posQuant = @:privateAccess sceneEditor.view.config.get("sceneeditor.xyzPrecision");
  271. var scaleQuant = @:privateAccess sceneEditor.view.config.get("sceneeditor.scalePrecision");
  272. var rotQuant = @:privateAccess sceneEditor.view.config.get("sceneeditor.rotatePrecision");
  273. inline function quantize(x: Float, step: Float) {
  274. if(step > 0) {
  275. x = Math.round(x / step) * step;
  276. x = untyped parseFloat(x.toFixed(5)); // Snap to closest nicely displayed float :cold_sweat:
  277. }
  278. return x;
  279. }
  280. gizmo.onStartMove = function(mode) {
  281. var sceneObj = sceneEditor.getContext(sp).local3d;
  282. var obj3d = sp.to(hrt.prefab.Object3D);
  283. var pivotPt = sceneObj.getAbsPos().getPosition();
  284. var pivot = new h3d.Matrix();
  285. pivot.initTranslation(pivotPt.x, pivotPt.y, pivotPt.z);
  286. var invPivot = pivot.clone();
  287. invPivot.invert();
  288. var localMat : h3d.Matrix = sceneEditor.worldMat(sceneObj).clone();
  289. localMat.multiply(localMat, invPivot);
  290. var prevState = obj3d.saveTransform();
  291. gizmo.onMove = function(translate: h3d.Vector, rot: h3d.Quat, scale: h3d.Vector) {
  292. var transf = new h3d.Matrix();
  293. transf.identity();
  294. if(rot != null) rot.toMatrix(transf);
  295. if(translate != null) transf.translate(translate.x, translate.y, translate.z);
  296. var newMat = localMat.clone();
  297. newMat.multiply(newMat, transf);
  298. newMat.multiply(newMat, pivot);
  299. if(sceneEditor.snapToGround && mode == MoveXY) {
  300. newMat.tz = sceneEditor.getZ(newMat.tx, newMat.ty);
  301. }
  302. var parentInvMat = sceneObj.parent.getAbsPos().clone();
  303. parentInvMat.initInverse(parentInvMat);
  304. newMat.multiply(newMat, parentInvMat);
  305. if(scale != null) newMat.prependScale(scale.x, scale.y, scale.z);
  306. var rot = newMat.getEulerAngles();
  307. obj3d.x = quantize(newMat.tx, posQuant);
  308. obj3d.y = quantize(newMat.ty, posQuant);
  309. obj3d.z = quantize(newMat.tz, posQuant);
  310. obj3d.rotationX = quantize(hxd.Math.radToDeg(rot.x), rotQuant);
  311. obj3d.rotationY = quantize(hxd.Math.radToDeg(rot.y), rotQuant);
  312. obj3d.rotationZ = quantize(hxd.Math.radToDeg(rot.z), rotQuant);
  313. if(scale != null) {
  314. inline function scaleSnap(x: Float) {
  315. if(K.isDown(K.CTRL)) {
  316. var step = K.isDown(K.SHIFT) ? 0.5 : 1.0;
  317. x = Math.round(x / step) * step;
  318. }
  319. return x;
  320. }
  321. var s = newMat.getScale();
  322. obj3d.scaleX = quantize(scaleSnap(s.x), scaleQuant);
  323. obj3d.scaleY = quantize(scaleSnap(s.y), scaleQuant);
  324. obj3d.scaleZ = quantize(scaleSnap(s.z), scaleQuant);
  325. }
  326. obj3d.applyTransform(sceneObj);
  327. }
  328. gizmo.onFinishMove = function() {
  329. var newState = obj3d.saveTransform();
  330. undo.change(Custom(function(undo) {
  331. if( undo ) {
  332. obj3d.loadTransform(prevState);
  333. obj3d.applyTransform(sceneObj);
  334. prefab.updateInstance(ctx);
  335. showViewers();
  336. @:privateAccess editContext.scene.editor.refresh(Partial);
  337. showViewers();
  338. createGizmos(ctx);
  339. }
  340. else {
  341. obj3d.loadTransform(newState);
  342. obj3d.applyTransform(sceneObj);
  343. prefab.updateInstance(ctx);
  344. showViewers();
  345. createGizmos(ctx);
  346. }
  347. }));
  348. var worldPos = ctx.local3d.localToGlobal(new h3d.col.Point(sp.x, sp.y, sp.z));
  349. gizmo.setPosition(worldPos.x, worldPos.y, worldPos.z);
  350. }
  351. }
  352. }
  353. }
  354. public function setSelected( ctx : hrt.prefab.Context , b : Bool ) {
  355. reset();
  356. if( !b ) {
  357. editMode = false;
  358. return;
  359. }
  360. if( editMode ) {
  361. createGizmos(ctx);
  362. var s2d = @:privateAccess ctx.local2d.getScene();
  363. interactive = new h2d.Interactive(10000, 10000, s2d);
  364. interactive.propagateEvents = true;
  365. interactive.onPush =
  366. function(e) {
  367. // Add a new point
  368. if( K.isDown( K.MOUSE_LEFT ) && K.isDown( K.CTRL ) ) {
  369. e.propagate = false;
  370. var pt = getNewPointPosition(s2d.mouseX, s2d.mouseY, ctx);
  371. var sp = addSplinePoint(pt, ctx);
  372. showViewers();
  373. createGizmos(ctx);
  374. undo.change(Custom(function(undo) {
  375. if( undo ) {
  376. editContext.scene.editor.deleteElements([sp], () -> {}, false, false);
  377. for (sp in prefab.points)
  378. sp.computeName(editContext.getContext(sp));
  379. @:privateAccess editContext.scene.editor.refresh(Partial);
  380. prefab.updateInstance(ctx);
  381. showViewers();
  382. createGizmos(ctx);
  383. }
  384. else {
  385. addSplinePoint(pt, ctx);
  386. showViewers();
  387. createGizmos(ctx);
  388. }
  389. }));
  390. }
  391. // Delete a point
  392. if( K.isDown( K.MOUSE_LEFT ) && K.isDown( K.SHIFT ) ) {
  393. e.propagate = false;
  394. var sp = getClosestSplinePointFromMouse(s2d.mouseX, s2d.mouseY, ctx);
  395. var index = prefab.points.indexOf(sp);
  396. editContext.scene.editor.deleteElements([sp], () -> {}, false, false);
  397. for (sp in prefab.points)
  398. sp.computeName(editContext.getContext(sp));
  399. @:privateAccess editContext.scene.editor.refresh(Partial);
  400. prefab.updateInstance(ctx);
  401. showViewers();
  402. createGizmos(ctx);
  403. undo.change(Custom(function(undo) {
  404. if( undo ) {
  405. prefab.children.insert(index, sp);
  406. editContext.scene.editor.addElements([sp], false, true, false);
  407. prefab.updateInstance(ctx);
  408. showViewers();
  409. createGizmos(ctx);
  410. }
  411. else {
  412. editContext.scene.editor.deleteElements([sp], () -> {}, false, false);
  413. for (sp in prefab.points)
  414. sp.computeName(editContext.getContext(sp));
  415. @:privateAccess editContext.scene.editor.refresh(Partial);
  416. prefab.updateInstance(ctx);
  417. showViewers();
  418. createGizmos(ctx);
  419. }
  420. }));
  421. }
  422. };
  423. interactive.onMove =
  424. function(e) {
  425. if( prefab.points.length == 0 )
  426. return;
  427. // Only show the gizmo of the closest splinePoint
  428. var closetSp = getClosestSplinePointFromMouse(s2d.mouseX, s2d.mouseY, ctx);
  429. var index = prefab.points.indexOf(closetSp);
  430. for( g in gizmos ) {
  431. g.visible = gizmos.indexOf(g) == index && !K.isDown( K.CTRL ) && !K.isDown( K.SHIFT );
  432. }
  433. if( K.isDown( K.CTRL ) ) {
  434. if( newSplinePointViewer == null )
  435. newSplinePointViewer = new NewSplinePointViewer(ctx.local3d.getScene());
  436. newSplinePointViewer.visible = true;
  437. var npt = getNewPointPosition(s2d.mouseX, s2d.mouseY, ctx);
  438. newSplinePointViewer.update(npt);
  439. }
  440. else {
  441. if( newSplinePointViewer != null )
  442. newSplinePointViewer.visible = false;
  443. }
  444. if( K.isDown( K.SHIFT ) ) {
  445. var index = prefab.points.indexOf(getClosestSplinePointFromMouse(s2d.mouseX, s2d.mouseY, ctx));
  446. for( sp in prefab.points ) {
  447. if( index == prefab.points.indexOf(sp) )
  448. sp.setColor(0xFFFF0000);
  449. else
  450. sp.setColor(0xFF0000FF);
  451. }
  452. }
  453. };
  454. }
  455. }
  456. public function edit( ctx : EditContext ) {
  457. var props = new hide.Element('
  458. <div class="spline-editor">
  459. <div class="group" name="Utility">
  460. <div align="center">
  461. <input type="button" value="Reverse" class="reverse"/>
  462. </div>
  463. </div>
  464. <div class="group" name="Description">
  465. <div class="description">
  466. <i>Ctrl + Left Click</i> Add a point on the spline <br>
  467. <i>Shift + Left Click</i> Delete a point from the spline
  468. </div>
  469. </div>
  470. <div class="group" name="Tool">
  471. <div align="center">
  472. <input type="button" value="Edit Mode : Disabled" class="editModeButton" />
  473. </div>
  474. </div>
  475. </div>');
  476. var reverseButton = props.find(".reverse");
  477. reverseButton.click(function(_) {
  478. prefab.children.reverse();
  479. for (sp in prefab.points) {
  480. sp.rotationZ += hxd.Math.degToRad(180);
  481. sp.computeName(editContext.getContext(sp));
  482. }
  483. @:privateAccess editContext.scene.editor.refresh(Partial);
  484. undo.change(Custom(function(undo) {
  485. prefab.children.reverse();
  486. for (sp in prefab.points) {
  487. sp.rotationZ += hxd.Math.degToRad(180);
  488. sp.computeName(editContext.getContext(sp));
  489. }
  490. @:privateAccess editContext.scene.editor.refresh(Partial);
  491. }));
  492. ctx.onChange(prefab, null);
  493. removeGizmos();
  494. createGizmos(getContext());
  495. });
  496. var editModeButton = props.find(".editModeButton");
  497. editModeButton.toggleClass("editModeEnabled", editMode);
  498. editModeButton.click(function(_) {
  499. editMode = !editMode;
  500. prefab.onEdit(editMode);
  501. editModeButton.val(editMode ? "Edit Mode : Enabled" : "Edit Mode : Disabled");
  502. editModeButton.toggleClass("editModeEnabled", editMode);
  503. setSelected(getContext(), true);
  504. @:privateAccess editContext.scene.editor.showGizmo = !editMode;
  505. ctx.onChange(prefab, null);
  506. });
  507. ctx.properties.add(props, this, function(pname) {
  508. ctx.onChange(prefab, pname);
  509. });
  510. return props;
  511. }
  512. }
  513. #end