Cesium3DTilesInspectorViewModel.js 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576
  1. import Check from "../../Core/Check.js";
  2. import Color from "../../Core/Color.js";
  3. import defined from "../../Core/defined.js";
  4. import destroyObject from "../../Core/destroyObject.js";
  5. import ScreenSpaceEventHandler from "../../Core/ScreenSpaceEventHandler.js";
  6. import ScreenSpaceEventType from "../../Core/ScreenSpaceEventType.js";
  7. import Cesium3DTileColorBlendMode from "../../Scene/Cesium3DTileColorBlendMode.js";
  8. import Cesium3DTileFeature from "../../Scene/Cesium3DTileFeature.js";
  9. import Cesium3DTilePass from "../../Scene/Cesium3DTilePass.js";
  10. import Cesium3DTileset from "../../Scene/Cesium3DTileset.js";
  11. import Cesium3DTileStyle from "../../Scene/Cesium3DTileStyle.js";
  12. import PerformanceDisplay from "../../Scene/PerformanceDisplay.js";
  13. import knockout from "../../ThirdParty/knockout.js";
  14. function getPickTileset(viewModel) {
  15. return function (e) {
  16. var pick = viewModel._scene.pick(e.position);
  17. if (defined(pick) && pick.primitive instanceof Cesium3DTileset) {
  18. viewModel.tileset = pick.primitive;
  19. }
  20. viewModel.pickActive = false;
  21. };
  22. }
  23. function selectTilesetOnHover(viewModel, value) {
  24. if (value) {
  25. viewModel._eventHandler.setInputAction(function (e) {
  26. var pick = viewModel._scene.pick(e.endPosition);
  27. if (defined(pick) && pick.primitive instanceof Cesium3DTileset) {
  28. viewModel.tileset = pick.primitive;
  29. }
  30. }, ScreenSpaceEventType.MOUSE_MOVE);
  31. } else {
  32. viewModel._eventHandler.removeInputAction(ScreenSpaceEventType.MOUSE_MOVE);
  33. // Restore hover-over selection to its current value
  34. // eslint-disable-next-line no-self-assign
  35. viewModel.picking = viewModel.picking;
  36. }
  37. }
  38. var stringOptions = {
  39. maximumFractionDigits: 3,
  40. };
  41. function formatMemoryString(memorySizeInBytes) {
  42. var memoryInMegabytes = memorySizeInBytes / 1048576;
  43. if (memoryInMegabytes < 1.0) {
  44. return memoryInMegabytes.toLocaleString(undefined, stringOptions);
  45. }
  46. return Math.round(memoryInMegabytes).toLocaleString();
  47. }
  48. function getStatistics(tileset, isPick) {
  49. if (!defined(tileset)) {
  50. return "";
  51. }
  52. var statistics = isPick
  53. ? tileset._statisticsPerPass[Cesium3DTilePass.PICK]
  54. : tileset._statisticsPerPass[Cesium3DTilePass.RENDER];
  55. // Since the pick pass uses a smaller frustum around the pixel of interest,
  56. // the statistics will be different than the normal render pass.
  57. var s = '<ul class="cesium-cesiumInspector-statistics">';
  58. s +=
  59. // --- Rendering statistics
  60. "<li><strong>Visited: </strong>" +
  61. statistics.visited.toLocaleString() +
  62. "</li>" +
  63. // Number of commands returned is likely to be higher than the number of tiles selected
  64. // because of tiles that create multiple commands.
  65. "<li><strong>Selected: </strong>" +
  66. statistics.selected.toLocaleString() +
  67. "</li>" +
  68. // Number of commands executed is likely to be higher because of commands overlapping
  69. // multiple frustums.
  70. "<li><strong>Commands: </strong>" +
  71. statistics.numberOfCommands.toLocaleString() +
  72. "</li>";
  73. s += "</ul>";
  74. if (!isPick) {
  75. s += '<ul class="cesium-cesiumInspector-statistics">';
  76. s +=
  77. // --- Cache/loading statistics
  78. "<li><strong>Requests: </strong>" +
  79. statistics.numberOfPendingRequests.toLocaleString() +
  80. "</li>" +
  81. "<li><strong>Attempted: </strong>" +
  82. statistics.numberOfAttemptedRequests.toLocaleString() +
  83. "</li>" +
  84. "<li><strong>Processing: </strong>" +
  85. statistics.numberOfTilesProcessing.toLocaleString() +
  86. "</li>" +
  87. "<li><strong>Content Ready: </strong>" +
  88. statistics.numberOfTilesWithContentReady.toLocaleString() +
  89. "</li>" +
  90. // Total number of tiles includes tiles without content, so "Ready" may never reach
  91. // "Total." Total also will increase when a tile with a tileset JSON content is loaded.
  92. "<li><strong>Total: </strong>" +
  93. statistics.numberOfTilesTotal.toLocaleString() +
  94. "</li>";
  95. s += "</ul>";
  96. s += '<ul class="cesium-cesiumInspector-statistics">';
  97. s +=
  98. // --- Features statistics
  99. "<li><strong>Features Selected: </strong>" +
  100. statistics.numberOfFeaturesSelected.toLocaleString() +
  101. "</li>" +
  102. "<li><strong>Features Loaded: </strong>" +
  103. statistics.numberOfFeaturesLoaded.toLocaleString() +
  104. "</li>" +
  105. "<li><strong>Points Selected: </strong>" +
  106. statistics.numberOfPointsSelected.toLocaleString() +
  107. "</li>" +
  108. "<li><strong>Points Loaded: </strong>" +
  109. statistics.numberOfPointsLoaded.toLocaleString() +
  110. "</li>" +
  111. "<li><strong>Triangles Selected: </strong>" +
  112. statistics.numberOfTrianglesSelected.toLocaleString() +
  113. "</li>";
  114. s += "</ul>";
  115. s += '<ul class="cesium-cesiumInspector-statistics">';
  116. s +=
  117. // --- Styling statistics
  118. "<li><strong>Tiles styled: </strong>" +
  119. statistics.numberOfTilesStyled.toLocaleString() +
  120. "</li>" +
  121. "<li><strong>Features styled: </strong>" +
  122. statistics.numberOfFeaturesStyled.toLocaleString() +
  123. "</li>";
  124. s += "</ul>";
  125. s += '<ul class="cesium-cesiumInspector-statistics">';
  126. s +=
  127. // --- Optimization statistics
  128. "<li><strong>Children Union Culled: </strong>" +
  129. statistics.numberOfTilesCulledWithChildrenUnion.toLocaleString() +
  130. "</li>";
  131. s += "</ul>";
  132. s += '<ul class="cesium-cesiumInspector-statistics">';
  133. s +=
  134. // --- Memory statistics
  135. "<li><strong>Geometry Memory (MB): </strong>" +
  136. formatMemoryString(statistics.geometryByteLength) +
  137. "</li>" +
  138. "<li><strong>Texture Memory (MB): </strong>" +
  139. formatMemoryString(statistics.texturesByteLength) +
  140. "</li>" +
  141. "<li><strong>Batch Table Memory (MB): </strong>" +
  142. formatMemoryString(statistics.batchTableByteLength) +
  143. "</li>";
  144. s += "</ul>";
  145. }
  146. return s;
  147. }
  148. var colorBlendModes = [
  149. {
  150. text: "Highlight",
  151. value: Cesium3DTileColorBlendMode.HIGHLIGHT,
  152. },
  153. {
  154. text: "Replace",
  155. value: Cesium3DTileColorBlendMode.REPLACE,
  156. },
  157. {
  158. text: "Mix",
  159. value: Cesium3DTileColorBlendMode.MIX,
  160. },
  161. ];
  162. var highlightColor = new Color(1.0, 1.0, 0.0, 0.4);
  163. var scratchColor = new Color();
  164. var oldColor = new Color();
  165. /**
  166. * The view model for {@link Cesium3DTilesInspector}.
  167. * @alias Cesium3DTilesInspectorViewModel
  168. * @constructor
  169. *
  170. * @param {Scene} scene The scene instance to use.
  171. * @param {HTMLElement} performanceContainer The container for the performance display
  172. */
  173. function Cesium3DTilesInspectorViewModel(scene, performanceContainer) {
  174. //>>includeStart('debug', pragmas.debug);
  175. Check.typeOf.object("scene", scene);
  176. Check.typeOf.object("performanceContainer", performanceContainer);
  177. //>>includeEnd('debug');
  178. var that = this;
  179. var canvas = scene.canvas;
  180. this._eventHandler = new ScreenSpaceEventHandler(canvas);
  181. this._scene = scene;
  182. this._performanceContainer = performanceContainer;
  183. this._canvas = canvas;
  184. this._performanceDisplay = new PerformanceDisplay({
  185. container: performanceContainer,
  186. });
  187. this._statisticsText = "";
  188. this._pickStatisticsText = "";
  189. this._editorError = "";
  190. /**
  191. * Gets or sets the flag to enable performance display. This property is observable.
  192. *
  193. * @type {Boolean}
  194. * @default false
  195. */
  196. this.performance = false;
  197. /**
  198. * Gets or sets the flag to show statistics. This property is observable.
  199. *
  200. * @type {Boolean}
  201. * @default true
  202. */
  203. this.showStatistics = true;
  204. /**
  205. * Gets or sets the flag to show pick statistics. This property is observable.
  206. *
  207. * @type {Boolean}
  208. * @default false
  209. */
  210. this.showPickStatistics = true;
  211. /**
  212. * Gets or sets the flag to show the inspector. This property is observable.
  213. *
  214. * @type {Boolean}
  215. * @default true
  216. */
  217. this.inspectorVisible = true;
  218. /**
  219. * Gets or sets the flag to show the tileset section. This property is observable.
  220. *
  221. * @type {Boolean}
  222. * @default false
  223. */
  224. this.tilesetVisible = false;
  225. /**
  226. * Gets or sets the flag to show the display section. This property is observable.
  227. *
  228. * @type {Boolean}
  229. * @default false
  230. */
  231. this.displayVisible = false;
  232. /**
  233. * Gets or sets the flag to show the update section. This property is observable.
  234. *
  235. * @type {Boolean}
  236. * @default false
  237. */
  238. this.updateVisible = false;
  239. /**
  240. * Gets or sets the flag to show the logging section. This property is observable.
  241. *
  242. * @type {Boolean}
  243. * @default false
  244. */
  245. this.loggingVisible = false;
  246. /**
  247. * Gets or sets the flag to show the style section. This property is observable.
  248. *
  249. * @type {Boolean}
  250. * @default false
  251. */
  252. this.styleVisible = false;
  253. /**
  254. * Gets or sets the flag to show the tile info section. This property is observable.
  255. *
  256. * @type {Boolean}
  257. * @default false
  258. */
  259. this.tileDebugLabelsVisible = false;
  260. /**
  261. * Gets or sets the flag to show the optimization info section. This property is observable.
  262. *
  263. * @type {Boolean}
  264. * @default false;
  265. */
  266. this.optimizationVisible = false;
  267. /**
  268. * Gets or sets the JSON for the tileset style. This property is observable.
  269. *
  270. * @type {String}
  271. * @default '{}'
  272. */
  273. this.styleString = "{}";
  274. this._tileset = undefined;
  275. this._feature = undefined;
  276. this._tile = undefined;
  277. knockout.track(this, [
  278. "performance",
  279. "inspectorVisible",
  280. "_statisticsText",
  281. "_pickStatisticsText",
  282. "_editorError",
  283. "showPickStatistics",
  284. "showStatistics",
  285. "tilesetVisible",
  286. "displayVisible",
  287. "updateVisible",
  288. "loggingVisible",
  289. "styleVisible",
  290. "optimizationVisible",
  291. "tileDebugLabelsVisible",
  292. "styleString",
  293. "_feature",
  294. "_tile",
  295. ]);
  296. this._properties = knockout.observable({});
  297. /**
  298. * Gets the names of the properties in the tileset. This property is observable.
  299. * @type {String[]}
  300. * @readonly
  301. */
  302. this.properties = [];
  303. knockout.defineProperty(this, "properties", function () {
  304. var names = [];
  305. var properties = that._properties();
  306. for (var prop in properties) {
  307. if (properties.hasOwnProperty(prop)) {
  308. names.push(prop);
  309. }
  310. }
  311. return names;
  312. });
  313. var dynamicScreenSpaceError = knockout.observable();
  314. knockout.defineProperty(this, "dynamicScreenSpaceError", {
  315. get: function () {
  316. return dynamicScreenSpaceError();
  317. },
  318. set: function (value) {
  319. dynamicScreenSpaceError(value);
  320. if (defined(that._tileset)) {
  321. that._tileset.dynamicScreenSpaceError = value;
  322. }
  323. },
  324. });
  325. /**
  326. * Gets or sets the flag to enable dynamic screen space error. This property is observable.
  327. *
  328. * @type {Boolean}
  329. * @default false
  330. */
  331. this.dynamicScreenSpaceError = false;
  332. var colorBlendMode = knockout.observable();
  333. knockout.defineProperty(this, "colorBlendMode", {
  334. get: function () {
  335. return colorBlendMode();
  336. },
  337. set: function (value) {
  338. colorBlendMode(value);
  339. if (defined(that._tileset)) {
  340. that._tileset.colorBlendMode = value;
  341. that._scene.requestRender();
  342. }
  343. },
  344. });
  345. /**
  346. * Gets or sets the color blend mode. This property is observable.
  347. *
  348. * @type {Cesium3DTileColorBlendMode}
  349. * @default Cesium3DTileColorBlendMode.HIGHLIGHT
  350. */
  351. this.colorBlendMode = Cesium3DTileColorBlendMode.HIGHLIGHT;
  352. var showOnlyPickedTileDebugLabel = knockout.observable();
  353. var picking = knockout.observable();
  354. knockout.defineProperty(this, "picking", {
  355. get: function () {
  356. return picking();
  357. },
  358. set: function (value) {
  359. picking(value);
  360. if (value) {
  361. that._eventHandler.setInputAction(function (e) {
  362. var picked = scene.pick(e.endPosition);
  363. if (picked instanceof Cesium3DTileFeature) {
  364. // Picked a feature
  365. that.feature = picked;
  366. that.tile = picked.content.tile;
  367. } else if (defined(picked) && defined(picked.content)) {
  368. // Picked a tile
  369. that.feature = undefined;
  370. that.tile = picked.content.tile;
  371. } else {
  372. // Picked nothing
  373. that.feature = undefined;
  374. that.tile = undefined;
  375. }
  376. if (!defined(that._tileset)) {
  377. return;
  378. }
  379. if (
  380. showOnlyPickedTileDebugLabel &&
  381. defined(picked) &&
  382. defined(picked.content)
  383. ) {
  384. var position;
  385. if (scene.pickPositionSupported) {
  386. position = scene.pickPosition(e.endPosition);
  387. if (defined(position)) {
  388. that._tileset.debugPickPosition = position;
  389. }
  390. }
  391. that._tileset.debugPickedTile = picked.content.tile;
  392. } else {
  393. that._tileset.debugPickedTile = undefined;
  394. }
  395. that._scene.requestRender();
  396. }, ScreenSpaceEventType.MOUSE_MOVE);
  397. } else {
  398. that.feature = undefined;
  399. that.tile = undefined;
  400. that._eventHandler.removeInputAction(ScreenSpaceEventType.MOUSE_MOVE);
  401. }
  402. },
  403. });
  404. /**
  405. * Gets or sets the flag to enable picking. This property is observable.
  406. *
  407. * @type {Boolean}
  408. * @default true
  409. */
  410. this.picking = true;
  411. var colorize = knockout.observable();
  412. knockout.defineProperty(this, "colorize", {
  413. get: function () {
  414. return colorize();
  415. },
  416. set: function (value) {
  417. colorize(value);
  418. if (defined(that._tileset)) {
  419. that._tileset.debugColorizeTiles = value;
  420. that._scene.requestRender();
  421. }
  422. },
  423. });
  424. /**
  425. * Gets or sets the flag to colorize tiles. This property is observable.
  426. *
  427. * @type {Boolean}
  428. * @default false
  429. */
  430. this.colorize = false;
  431. var wireframe = knockout.observable();
  432. knockout.defineProperty(this, "wireframe", {
  433. get: function () {
  434. return wireframe();
  435. },
  436. set: function (value) {
  437. wireframe(value);
  438. if (defined(that._tileset)) {
  439. that._tileset.debugWireframe = value;
  440. that._scene.requestRender();
  441. }
  442. },
  443. });
  444. /**
  445. * Gets or sets the flag to draw with wireframe. This property is observable.
  446. *
  447. * @type {Boolean}
  448. * @default false
  449. */
  450. this.wireframe = false;
  451. var showBoundingVolumes = knockout.observable();
  452. knockout.defineProperty(this, "showBoundingVolumes", {
  453. get: function () {
  454. return showBoundingVolumes();
  455. },
  456. set: function (value) {
  457. showBoundingVolumes(value);
  458. if (defined(that._tileset)) {
  459. that._tileset.debugShowBoundingVolume = value;
  460. that._scene.requestRender();
  461. }
  462. },
  463. });
  464. /**
  465. * Gets or sets the flag to show bounding volumes. This property is observable.
  466. *
  467. * @type {Boolean}
  468. * @default false
  469. */
  470. this.showBoundingVolumes = false;
  471. var showContentBoundingVolumes = knockout.observable();
  472. knockout.defineProperty(this, "showContentBoundingVolumes", {
  473. get: function () {
  474. return showContentBoundingVolumes();
  475. },
  476. set: function (value) {
  477. showContentBoundingVolumes(value);
  478. if (defined(that._tileset)) {
  479. that._tileset.debugShowContentBoundingVolume = value;
  480. that._scene.requestRender();
  481. }
  482. },
  483. });
  484. /**
  485. * Gets or sets the flag to show content volumes. This property is observable.
  486. *
  487. * @type {Boolean}
  488. * @default false
  489. */
  490. this.showContentBoundingVolumes = false;
  491. var showRequestVolumes = knockout.observable();
  492. knockout.defineProperty(this, "showRequestVolumes", {
  493. get: function () {
  494. return showRequestVolumes();
  495. },
  496. set: function (value) {
  497. showRequestVolumes(value);
  498. if (defined(that._tileset)) {
  499. that._tileset.debugShowViewerRequestVolume = value;
  500. that._scene.requestRender();
  501. }
  502. },
  503. });
  504. /**
  505. * Gets or sets the flag to show request volumes. This property is observable.
  506. *
  507. * @type {Boolean}
  508. * @default false
  509. */
  510. this.showRequestVolumes = false;
  511. var freezeFrame = knockout.observable();
  512. knockout.defineProperty(this, "freezeFrame", {
  513. get: function () {
  514. return freezeFrame();
  515. },
  516. set: function (value) {
  517. freezeFrame(value);
  518. if (defined(that._tileset)) {
  519. that._tileset.debugFreezeFrame = value;
  520. that._scene.debugShowFrustumPlanes = value;
  521. that._scene.requestRender();
  522. }
  523. },
  524. });
  525. /**
  526. * Gets or sets the flag to suspend updates. This property is observable.
  527. *
  528. * @type {Boolean}
  529. * @default false
  530. */
  531. this.freezeFrame = false;
  532. knockout.defineProperty(this, "showOnlyPickedTileDebugLabel", {
  533. get: function () {
  534. return showOnlyPickedTileDebugLabel();
  535. },
  536. set: function (value) {
  537. showOnlyPickedTileDebugLabel(value);
  538. if (defined(that._tileset)) {
  539. that._tileset.debugPickedTileLabelOnly = value;
  540. that._scene.requestRender();
  541. }
  542. },
  543. });
  544. /**
  545. * Gets or sets the flag to show debug labels only for the currently picked tile. This property is observable.
  546. *
  547. * @type {Boolean}
  548. * @default false
  549. */
  550. this.showOnlyPickedTileDebugLabel = false;
  551. var showGeometricError = knockout.observable();
  552. knockout.defineProperty(this, "showGeometricError", {
  553. get: function () {
  554. return showGeometricError();
  555. },
  556. set: function (value) {
  557. showGeometricError(value);
  558. if (defined(that._tileset)) {
  559. that._tileset.debugShowGeometricError = value;
  560. that._scene.requestRender();
  561. }
  562. },
  563. });
  564. /**
  565. * Gets or sets the flag to show tile geometric error. This property is observable.
  566. *
  567. * @type {Boolean}
  568. * @default false
  569. */
  570. this.showGeometricError = false;
  571. var showRenderingStatistics = knockout.observable();
  572. knockout.defineProperty(this, "showRenderingStatistics", {
  573. get: function () {
  574. return showRenderingStatistics();
  575. },
  576. set: function (value) {
  577. showRenderingStatistics(value);
  578. if (defined(that._tileset)) {
  579. that._tileset.debugShowRenderingStatistics = value;
  580. that._scene.requestRender();
  581. }
  582. },
  583. });
  584. /**
  585. * Displays the number of commands, points, triangles and features used per tile. This property is observable.
  586. *
  587. * @type {Boolean}
  588. * @default false
  589. */
  590. this.showRenderingStatistics = false;
  591. var showMemoryUsage = knockout.observable();
  592. knockout.defineProperty(this, "showMemoryUsage", {
  593. get: function () {
  594. return showMemoryUsage();
  595. },
  596. set: function (value) {
  597. showMemoryUsage(value);
  598. if (defined(that._tileset)) {
  599. that._tileset.debugShowMemoryUsage = value;
  600. that._scene.requestRender();
  601. }
  602. },
  603. });
  604. /**
  605. * Displays the memory used per tile. This property is observable.
  606. *
  607. * @type {Boolean}
  608. * @default false
  609. */
  610. this.showMemoryUsage = false;
  611. var showUrl = knockout.observable();
  612. knockout.defineProperty(this, "showUrl", {
  613. get: function () {
  614. return showUrl();
  615. },
  616. set: function (value) {
  617. showUrl(value);
  618. if (defined(that._tileset)) {
  619. that._tileset.debugShowUrl = value;
  620. that._scene.requestRender();
  621. }
  622. },
  623. });
  624. /**
  625. * Gets or sets the flag to show the tile url. This property is observable.
  626. *
  627. * @type {Boolean}
  628. * @default false
  629. */
  630. this.showUrl = false;
  631. var maximumScreenSpaceError = knockout.observable();
  632. knockout.defineProperty(this, "maximumScreenSpaceError", {
  633. get: function () {
  634. return maximumScreenSpaceError();
  635. },
  636. set: function (value) {
  637. value = Number(value);
  638. if (!isNaN(value)) {
  639. maximumScreenSpaceError(value);
  640. if (defined(that._tileset)) {
  641. that._tileset.maximumScreenSpaceError = value;
  642. }
  643. }
  644. },
  645. });
  646. /**
  647. * Gets or sets the maximum screen space error. This property is observable.
  648. *
  649. * @type {Number}
  650. * @default 16
  651. */
  652. this.maximumScreenSpaceError = 16;
  653. var dynamicScreenSpaceErrorDensity = knockout.observable();
  654. knockout.defineProperty(this, "dynamicScreenSpaceErrorDensity", {
  655. get: function () {
  656. return dynamicScreenSpaceErrorDensity();
  657. },
  658. set: function (value) {
  659. value = Number(value);
  660. if (!isNaN(value)) {
  661. dynamicScreenSpaceErrorDensity(value);
  662. if (defined(that._tileset)) {
  663. that._tileset.dynamicScreenSpaceErrorDensity = value;
  664. }
  665. }
  666. },
  667. });
  668. /**
  669. * Gets or sets the dynamic screen space error density. This property is observable.
  670. *
  671. * @type {Number}
  672. * @default 0.00278
  673. */
  674. this.dynamicScreenSpaceErrorDensity = 0.00278;
  675. /**
  676. * Gets or sets the dynamic screen space error density slider value.
  677. * This allows the slider to be exponential because values tend to be closer to 0 than 1.
  678. * This property is observable.
  679. *
  680. * @type {Number}
  681. * @default 0.00278
  682. */
  683. this.dynamicScreenSpaceErrorDensitySliderValue = undefined;
  684. knockout.defineProperty(this, "dynamicScreenSpaceErrorDensitySliderValue", {
  685. get: function () {
  686. return Math.pow(dynamicScreenSpaceErrorDensity(), 1 / 6);
  687. },
  688. set: function (value) {
  689. dynamicScreenSpaceErrorDensity(Math.pow(value, 6));
  690. },
  691. });
  692. var dynamicScreenSpaceErrorFactor = knockout.observable();
  693. knockout.defineProperty(this, "dynamicScreenSpaceErrorFactor", {
  694. get: function () {
  695. return dynamicScreenSpaceErrorFactor();
  696. },
  697. set: function (value) {
  698. value = Number(value);
  699. if (!isNaN(value)) {
  700. dynamicScreenSpaceErrorFactor(value);
  701. if (defined(that._tileset)) {
  702. that._tileset.dynamicScreenSpaceErrorFactor = value;
  703. }
  704. }
  705. },
  706. });
  707. /**
  708. * Gets or sets the dynamic screen space error factor. This property is observable.
  709. *
  710. * @type {Number}
  711. * @default 4.0
  712. */
  713. this.dynamicScreenSpaceErrorFactor = 4.0;
  714. var pickTileset = getPickTileset(this);
  715. var pickActive = knockout.observable();
  716. knockout.defineProperty(this, "pickActive", {
  717. get: function () {
  718. return pickActive();
  719. },
  720. set: function (value) {
  721. pickActive(value);
  722. if (value) {
  723. that._eventHandler.setInputAction(
  724. pickTileset,
  725. ScreenSpaceEventType.LEFT_CLICK
  726. );
  727. } else {
  728. that._eventHandler.removeInputAction(ScreenSpaceEventType.LEFT_CLICK);
  729. }
  730. },
  731. });
  732. var pointCloudShading = knockout.observable();
  733. knockout.defineProperty(this, "pointCloudShading", {
  734. get: function () {
  735. return pointCloudShading();
  736. },
  737. set: function (value) {
  738. pointCloudShading(value);
  739. if (defined(that._tileset)) {
  740. that._tileset.pointCloudShading.attenuation = value;
  741. }
  742. },
  743. });
  744. /**
  745. * Gets or sets the flag to enable point cloud shading. This property is observable.
  746. *
  747. * @type {Boolean}
  748. * @default false
  749. */
  750. this.pointCloudShading = false;
  751. var geometricErrorScale = knockout.observable();
  752. knockout.defineProperty(this, "geometricErrorScale", {
  753. get: function () {
  754. return geometricErrorScale();
  755. },
  756. set: function (value) {
  757. value = Number(value);
  758. if (!isNaN(value)) {
  759. geometricErrorScale(value);
  760. if (defined(that._tileset)) {
  761. that._tileset.pointCloudShading.geometricErrorScale = value;
  762. }
  763. }
  764. },
  765. });
  766. /**
  767. * Gets or sets the geometric error scale. This property is observable.
  768. *
  769. * @type {Number}
  770. * @default 1.0
  771. */
  772. this.geometricErrorScale = 1.0;
  773. var maximumAttenuation = knockout.observable();
  774. knockout.defineProperty(this, "maximumAttenuation", {
  775. get: function () {
  776. return maximumAttenuation();
  777. },
  778. set: function (value) {
  779. value = Number(value);
  780. if (!isNaN(value)) {
  781. maximumAttenuation(value);
  782. if (defined(that._tileset)) {
  783. that._tileset.pointCloudShading.maximumAttenuation =
  784. value === 0 ? undefined : value;
  785. }
  786. }
  787. },
  788. });
  789. /**
  790. * Gets or sets the maximum attenuation. This property is observable.
  791. *
  792. * @type {Number}
  793. * @default 0
  794. */
  795. this.maximumAttenuation = 0;
  796. var baseResolution = knockout.observable();
  797. knockout.defineProperty(this, "baseResolution", {
  798. get: function () {
  799. return baseResolution();
  800. },
  801. set: function (value) {
  802. value = Number(value);
  803. if (!isNaN(value)) {
  804. baseResolution(value);
  805. if (defined(that._tileset)) {
  806. that._tileset.pointCloudShading.baseResolution =
  807. value === 0 ? undefined : value;
  808. }
  809. }
  810. },
  811. });
  812. /**
  813. * Gets or sets the base resolution. This property is observable.
  814. *
  815. * @type {Number}
  816. * @default 0
  817. */
  818. this.baseResolution = 0;
  819. var eyeDomeLighting = knockout.observable();
  820. knockout.defineProperty(this, "eyeDomeLighting", {
  821. get: function () {
  822. return eyeDomeLighting();
  823. },
  824. set: function (value) {
  825. eyeDomeLighting(value);
  826. if (defined(that._tileset)) {
  827. that._tileset.pointCloudShading.eyeDomeLighting = value;
  828. }
  829. },
  830. });
  831. /**
  832. * Gets or sets the flag to enable eye dome lighting. This property is observable.
  833. *
  834. * @type {Boolean}
  835. * @default false
  836. */
  837. this.eyeDomeLighting = false;
  838. var eyeDomeLightingStrength = knockout.observable();
  839. knockout.defineProperty(this, "eyeDomeLightingStrength", {
  840. get: function () {
  841. return eyeDomeLightingStrength();
  842. },
  843. set: function (value) {
  844. value = Number(value);
  845. if (!isNaN(value)) {
  846. eyeDomeLightingStrength(value);
  847. if (defined(that._tileset)) {
  848. that._tileset.pointCloudShading.eyeDomeLightingStrength = value;
  849. }
  850. }
  851. },
  852. });
  853. /**
  854. * Gets or sets the eye dome lighting strength. This property is observable.
  855. *
  856. * @type {Number}
  857. * @default 1.0
  858. */
  859. this.eyeDomeLightingStrength = 1.0;
  860. var eyeDomeLightingRadius = knockout.observable();
  861. knockout.defineProperty(this, "eyeDomeLightingRadius", {
  862. get: function () {
  863. return eyeDomeLightingRadius();
  864. },
  865. set: function (value) {
  866. value = Number(value);
  867. if (!isNaN(value)) {
  868. eyeDomeLightingRadius(value);
  869. if (defined(that._tileset)) {
  870. that._tileset.pointCloudShading.eyeDomeLightingRadius = value;
  871. }
  872. }
  873. },
  874. });
  875. /**
  876. * Gets or sets the eye dome lighting radius. This property is observable.
  877. *
  878. * @type {Number}
  879. * @default 1.0
  880. */
  881. this.eyeDomeLightingRadius = 1.0;
  882. /**
  883. * Gets or sets the pick state
  884. *
  885. * @type {Boolean}
  886. * @default false
  887. */
  888. this.pickActive = false;
  889. var skipLevelOfDetail = knockout.observable();
  890. knockout.defineProperty(this, "skipLevelOfDetail", {
  891. get: function () {
  892. return skipLevelOfDetail();
  893. },
  894. set: function (value) {
  895. skipLevelOfDetail(value);
  896. if (defined(that._tileset)) {
  897. that._tileset.skipLevelOfDetail = value;
  898. }
  899. },
  900. });
  901. /**
  902. * Gets or sets the flag to determine if level of detail skipping should be applied during the traversal.
  903. * This property is observable.
  904. * @type {Boolean}
  905. * @default true
  906. */
  907. this.skipLevelOfDetail = true;
  908. var skipScreenSpaceErrorFactor = knockout.observable();
  909. knockout.defineProperty(this, "skipScreenSpaceErrorFactor", {
  910. get: function () {
  911. return skipScreenSpaceErrorFactor();
  912. },
  913. set: function (value) {
  914. value = Number(value);
  915. if (!isNaN(value)) {
  916. skipScreenSpaceErrorFactor(value);
  917. if (defined(that._tileset)) {
  918. that._tileset.skipScreenSpaceErrorFactor = value;
  919. }
  920. }
  921. },
  922. });
  923. /**
  924. * Gets or sets the multiplier defining the minimum screen space error to skip. This property is observable.
  925. * @type {Number}
  926. * @default 16
  927. */
  928. this.skipScreenSpaceErrorFactor = 16;
  929. var baseScreenSpaceError = knockout.observable();
  930. knockout.defineProperty(this, "baseScreenSpaceError", {
  931. get: function () {
  932. return baseScreenSpaceError();
  933. },
  934. set: function (value) {
  935. value = Number(value);
  936. if (!isNaN(value)) {
  937. baseScreenSpaceError(value);
  938. if (defined(that._tileset)) {
  939. that._tileset.baseScreenSpaceError = value;
  940. }
  941. }
  942. },
  943. });
  944. /**
  945. * Gets or sets the screen space error that must be reached before skipping levels of detail. This property is observable.
  946. * @type {Number}
  947. * @default 1024
  948. */
  949. this.baseScreenSpaceError = 1024;
  950. var skipLevels = knockout.observable();
  951. knockout.defineProperty(this, "skipLevels", {
  952. get: function () {
  953. return skipLevels();
  954. },
  955. set: function (value) {
  956. value = Number(value);
  957. if (!isNaN(value)) {
  958. skipLevels(value);
  959. if (defined(that._tileset)) {
  960. that._tileset.skipLevels = value;
  961. }
  962. }
  963. },
  964. });
  965. /**
  966. * Gets or sets the constant defining the minimum number of levels to skip when loading tiles. This property is observable.
  967. * @type {Number}
  968. * @default 1
  969. */
  970. this.skipLevels = 1;
  971. var immediatelyLoadDesiredLevelOfDetail = knockout.observable();
  972. knockout.defineProperty(this, "immediatelyLoadDesiredLevelOfDetail", {
  973. get: function () {
  974. return immediatelyLoadDesiredLevelOfDetail();
  975. },
  976. set: function (value) {
  977. immediatelyLoadDesiredLevelOfDetail(value);
  978. if (defined(that._tileset)) {
  979. that._tileset.immediatelyLoadDesiredLevelOfDetail = value;
  980. }
  981. },
  982. });
  983. /**
  984. * Gets or sets the flag which, when true, only tiles that meet the maximum screen space error will ever be downloaded.
  985. * This property is observable.
  986. * @type {Boolean}
  987. * @default false
  988. */
  989. this.immediatelyLoadDesiredLevelOfDetail = false;
  990. var loadSiblings = knockout.observable();
  991. knockout.defineProperty(this, "loadSiblings", {
  992. get: function () {
  993. return loadSiblings();
  994. },
  995. set: function (value) {
  996. loadSiblings(value);
  997. if (defined(that._tileset)) {
  998. that._tileset.loadSiblings = value;
  999. }
  1000. },
  1001. });
  1002. /**
  1003. * Gets or sets the flag which determines whether siblings of visible tiles are always downloaded during traversal.
  1004. * This property is observable
  1005. * @type {Boolean}
  1006. * @default false
  1007. */
  1008. this.loadSiblings = false;
  1009. this._style = undefined;
  1010. this._shouldStyle = false;
  1011. this._definedProperties = [
  1012. "properties",
  1013. "dynamicScreenSpaceError",
  1014. "colorBlendMode",
  1015. "picking",
  1016. "colorize",
  1017. "wireframe",
  1018. "showBoundingVolumes",
  1019. "showContentBoundingVolumes",
  1020. "showRequestVolumes",
  1021. "freezeFrame",
  1022. "maximumScreenSpaceError",
  1023. "dynamicScreenSpaceErrorDensity",
  1024. "baseScreenSpaceError",
  1025. "skipScreenSpaceErrorFactor",
  1026. "skipLevelOfDetail",
  1027. "skipLevels",
  1028. "immediatelyLoadDesiredLevelOfDetail",
  1029. "loadSiblings",
  1030. "dynamicScreenSpaceErrorDensitySliderValue",
  1031. "dynamicScreenSpaceErrorFactor",
  1032. "pickActive",
  1033. "showOnlyPickedTileDebugLabel",
  1034. "showGeometricError",
  1035. "showRenderingStatistics",
  1036. "showMemoryUsage",
  1037. "showUrl",
  1038. "pointCloudShading",
  1039. "geometricErrorScale",
  1040. "maximumAttenuation",
  1041. "baseResolution",
  1042. "eyeDomeLighting",
  1043. "eyeDomeLightingStrength",
  1044. "eyeDomeLightingRadius",
  1045. ];
  1046. this._removePostRenderEvent = scene.postRender.addEventListener(function () {
  1047. that._update();
  1048. });
  1049. if (!defined(this._tileset)) {
  1050. selectTilesetOnHover(this, true);
  1051. }
  1052. }
  1053. Object.defineProperties(Cesium3DTilesInspectorViewModel.prototype, {
  1054. /**
  1055. * Gets the scene
  1056. * @memberof Cesium3DTilesInspectorViewModel.prototype
  1057. * @type {Scene}
  1058. * @readonly
  1059. */
  1060. scene: {
  1061. get: function () {
  1062. return this._scene;
  1063. },
  1064. },
  1065. /**
  1066. * Gets the performance container
  1067. * @memberof Cesium3DTilesInspectorViewModel.prototype
  1068. * @type {HTMLElement}
  1069. * @readonly
  1070. */
  1071. performanceContainer: {
  1072. get: function () {
  1073. return this._performanceContainer;
  1074. },
  1075. },
  1076. /**
  1077. * Gets the statistics text. This property is observable.
  1078. * @memberof Cesium3DTilesInspectorViewModel.prototype
  1079. * @type {String}
  1080. * @readonly
  1081. */
  1082. statisticsText: {
  1083. get: function () {
  1084. return this._statisticsText;
  1085. },
  1086. },
  1087. /**
  1088. * Gets the pick statistics text. This property is observable.
  1089. * @memberof Cesium3DTilesInspectorViewModel.prototype
  1090. * @type {String}
  1091. * @readonly
  1092. */
  1093. pickStatisticsText: {
  1094. get: function () {
  1095. return this._pickStatisticsText;
  1096. },
  1097. },
  1098. /**
  1099. * Gets the available blend modes
  1100. * @memberof Cesium3DTilesInspectorViewModel.prototype
  1101. * @type {Object[]}
  1102. * @readonly
  1103. */
  1104. colorBlendModes: {
  1105. get: function () {
  1106. return colorBlendModes;
  1107. },
  1108. },
  1109. /**
  1110. * Gets the editor error message
  1111. * @memberof Cesium3DTilesInspectorViewModel.prototype
  1112. * @type {String}
  1113. * @readonly
  1114. */
  1115. editorError: {
  1116. get: function () {
  1117. return this._editorError;
  1118. },
  1119. },
  1120. /**
  1121. * Gets or sets the tileset of the view model.
  1122. * @memberof Cesium3DTilesInspectorViewModel.prototype
  1123. * @type {Cesium3DTileset}
  1124. */
  1125. tileset: {
  1126. get: function () {
  1127. return this._tileset;
  1128. },
  1129. set: function (tileset) {
  1130. this._tileset = tileset;
  1131. this._style = undefined;
  1132. this.styleString = "{}";
  1133. this.feature = undefined;
  1134. this.tile = undefined;
  1135. if (defined(tileset)) {
  1136. var that = this;
  1137. tileset.readyPromise.then(function (t) {
  1138. if (!that.isDestroyed()) {
  1139. that._properties(t.properties);
  1140. }
  1141. });
  1142. // update tileset with existing settings
  1143. var settings = [
  1144. "colorize",
  1145. "wireframe",
  1146. "showBoundingVolumes",
  1147. "showContentBoundingVolumes",
  1148. "showRequestVolumes",
  1149. "freezeFrame",
  1150. "showOnlyPickedTileDebugLabel",
  1151. "showGeometricError",
  1152. "showRenderingStatistics",
  1153. "showMemoryUsage",
  1154. "showUrl",
  1155. ];
  1156. var length = settings.length;
  1157. for (var i = 0; i < length; ++i) {
  1158. var setting = settings[i];
  1159. //eslint-disable-next-line no-self-assign
  1160. this[setting] = this[setting];
  1161. }
  1162. // update view model with existing tileset settings
  1163. this.maximumScreenSpaceError = tileset.maximumScreenSpaceError;
  1164. this.dynamicScreenSpaceError = tileset.dynamicScreenSpaceError;
  1165. this.dynamicScreenSpaceErrorDensity =
  1166. tileset.dynamicScreenSpaceErrorDensity;
  1167. this.dynamicScreenSpaceErrorFactor =
  1168. tileset.dynamicScreenSpaceErrorFactor;
  1169. this.colorBlendMode = tileset.colorBlendMode;
  1170. this.skipLevelOfDetail = tileset.skipLevelOfDetail;
  1171. this.skipScreenSpaceErrorFactor = tileset.skipScreenSpaceErrorFactor;
  1172. this.baseScreenSpaceError = tileset.baseScreenSpaceError;
  1173. this.skipLevels = tileset.skipLevels;
  1174. this.immediatelyLoadDesiredLevelOfDetail =
  1175. tileset.immediatelyLoadDesiredLevelOfDetail;
  1176. this.loadSiblings = tileset.loadSiblings;
  1177. var pointCloudShading = tileset.pointCloudShading;
  1178. this.pointCloudShading = pointCloudShading.attenuation;
  1179. this.geometricErrorScale = pointCloudShading.geometricErrorScale;
  1180. this.maximumAttenuation = pointCloudShading.maximumAttenuation
  1181. ? pointCloudShading.maximumAttenuation
  1182. : 0.0;
  1183. this.baseResolution = pointCloudShading.baseResolution
  1184. ? pointCloudShading.baseResolution
  1185. : 0.0;
  1186. this.eyeDomeLighting = pointCloudShading.eyeDomeLighting;
  1187. this.eyeDomeLightingStrength =
  1188. pointCloudShading.eyeDomeLightingStrength;
  1189. this.eyeDomeLightingRadius = pointCloudShading.eyeDomeLightingRadius;
  1190. this._scene.requestRender();
  1191. } else {
  1192. this._properties({});
  1193. }
  1194. this._statisticsText = getStatistics(tileset, false);
  1195. this._pickStatisticsText = getStatistics(tileset, true);
  1196. selectTilesetOnHover(this, false);
  1197. },
  1198. },
  1199. /**
  1200. * Gets the current feature of the view model.
  1201. * @memberof Cesium3DTilesInspectorViewModel.prototype
  1202. * @type {Cesium3DTileFeature}
  1203. */
  1204. feature: {
  1205. get: function () {
  1206. return this._feature;
  1207. },
  1208. set: function (feature) {
  1209. if (this._feature === feature) {
  1210. return;
  1211. }
  1212. var currentFeature = this._feature;
  1213. if (defined(currentFeature) && !currentFeature.content.isDestroyed()) {
  1214. // Restore original color to feature that is no longer selected
  1215. if (!this.colorize && defined(this._style)) {
  1216. currentFeature.color = defined(this._style.color)
  1217. ? this._style.color.evaluateColor(currentFeature, scratchColor)
  1218. : Color.WHITE;
  1219. } else {
  1220. currentFeature.color = oldColor;
  1221. }
  1222. this._scene.requestRender();
  1223. }
  1224. if (defined(feature)) {
  1225. // Highlight new feature
  1226. Color.clone(feature.color, oldColor);
  1227. feature.color = highlightColor;
  1228. this._scene.requestRender();
  1229. }
  1230. this._feature = feature;
  1231. },
  1232. },
  1233. /**
  1234. * Gets the current tile of the view model
  1235. * @memberof Cesium3DTilesInspectorViewModel.prototype
  1236. * @type {Cesium3DTile}
  1237. */
  1238. tile: {
  1239. get: function () {
  1240. return this._tile;
  1241. },
  1242. set: function (tile) {
  1243. if (this._tile === tile) {
  1244. return;
  1245. }
  1246. var currentTile = this._tile;
  1247. if (
  1248. defined(currentTile) &&
  1249. !currentTile.isDestroyed() &&
  1250. !hasFeatures(currentTile.content)
  1251. ) {
  1252. // Restore original color to tile that is no longer selected
  1253. currentTile.color = oldColor;
  1254. this._scene.requestRender();
  1255. }
  1256. if (defined(tile) && !hasFeatures(tile.content)) {
  1257. // Highlight new tile
  1258. Color.clone(tile.color, oldColor);
  1259. tile.color = highlightColor;
  1260. this._scene.requestRender();
  1261. }
  1262. this._tile = tile;
  1263. },
  1264. },
  1265. });
  1266. function hasFeatures(content) {
  1267. if (content.featuresLength > 0) {
  1268. return true;
  1269. }
  1270. var innerContents = content.innerContents;
  1271. if (defined(innerContents)) {
  1272. var length = innerContents.length;
  1273. for (var i = 0; i < length; ++i) {
  1274. if (!hasFeatures(innerContents[i])) {
  1275. return false;
  1276. }
  1277. }
  1278. return true;
  1279. }
  1280. return false;
  1281. }
  1282. /**
  1283. * Toggles the pick tileset mode
  1284. */
  1285. Cesium3DTilesInspectorViewModel.prototype.togglePickTileset = function () {
  1286. this.pickActive = !this.pickActive;
  1287. };
  1288. /**
  1289. * Toggles the inspector visibility
  1290. */
  1291. Cesium3DTilesInspectorViewModel.prototype.toggleInspector = function () {
  1292. this.inspectorVisible = !this.inspectorVisible;
  1293. };
  1294. /**
  1295. * Toggles the visibility of the tileset section
  1296. */
  1297. Cesium3DTilesInspectorViewModel.prototype.toggleTileset = function () {
  1298. this.tilesetVisible = !this.tilesetVisible;
  1299. };
  1300. /**
  1301. * Toggles the visibility of the display section
  1302. */
  1303. Cesium3DTilesInspectorViewModel.prototype.toggleDisplay = function () {
  1304. this.displayVisible = !this.displayVisible;
  1305. };
  1306. /**
  1307. * Toggles the visibility of the update section
  1308. */
  1309. Cesium3DTilesInspectorViewModel.prototype.toggleUpdate = function () {
  1310. this.updateVisible = !this.updateVisible;
  1311. };
  1312. /**
  1313. * Toggles the visibility of the logging section
  1314. */
  1315. Cesium3DTilesInspectorViewModel.prototype.toggleLogging = function () {
  1316. this.loggingVisible = !this.loggingVisible;
  1317. };
  1318. /**
  1319. * Toggles the visibility of the style section
  1320. */
  1321. Cesium3DTilesInspectorViewModel.prototype.toggleStyle = function () {
  1322. this.styleVisible = !this.styleVisible;
  1323. };
  1324. /**
  1325. * Toggles the visibility of the tile Debug Info section
  1326. */
  1327. Cesium3DTilesInspectorViewModel.prototype.toggleTileDebugLabels = function () {
  1328. this.tileDebugLabelsVisible = !this.tileDebugLabelsVisible;
  1329. };
  1330. /**
  1331. * Toggles the visibility of the optimization section
  1332. */
  1333. Cesium3DTilesInspectorViewModel.prototype.toggleOptimization = function () {
  1334. this.optimizationVisible = !this.optimizationVisible;
  1335. };
  1336. /**
  1337. * Trims tile cache
  1338. */
  1339. Cesium3DTilesInspectorViewModel.prototype.trimTilesCache = function () {
  1340. if (defined(this._tileset)) {
  1341. this._tileset.trimLoadedTiles();
  1342. }
  1343. };
  1344. /**
  1345. * Compiles the style in the style editor.
  1346. */
  1347. Cesium3DTilesInspectorViewModel.prototype.compileStyle = function () {
  1348. var tileset = this._tileset;
  1349. if (!defined(tileset) || this.styleString === JSON.stringify(tileset.style)) {
  1350. return;
  1351. }
  1352. this._editorError = "";
  1353. try {
  1354. if (this.styleString.length === 0) {
  1355. this.styleString = "{}";
  1356. }
  1357. this._style = new Cesium3DTileStyle(JSON.parse(this.styleString));
  1358. this._shouldStyle = true;
  1359. this._scene.requestRender();
  1360. } catch (err) {
  1361. this._editorError = err.toString();
  1362. }
  1363. // set feature again so pick coloring is set
  1364. this.feature = this._feature;
  1365. this.tile = this._tile;
  1366. };
  1367. /**
  1368. * Handles key press events on the style editor.
  1369. */
  1370. Cesium3DTilesInspectorViewModel.prototype.styleEditorKeyPress = function (
  1371. sender,
  1372. event
  1373. ) {
  1374. if (event.keyCode === 9) {
  1375. //tab
  1376. event.preventDefault();
  1377. var textArea = event.target;
  1378. var start = textArea.selectionStart;
  1379. var end = textArea.selectionEnd;
  1380. var newEnd = end;
  1381. var selected = textArea.value.slice(start, end);
  1382. var lines = selected.split("\n");
  1383. var length = lines.length;
  1384. var i;
  1385. if (!event.shiftKey) {
  1386. for (i = 0; i < length; ++i) {
  1387. lines[i] = " " + lines[i];
  1388. newEnd += 2;
  1389. }
  1390. } else {
  1391. for (i = 0; i < length; ++i) {
  1392. if (lines[i][0] === " ") {
  1393. if (lines[i][1] === " ") {
  1394. lines[i] = lines[i].substr(2);
  1395. newEnd -= 2;
  1396. } else {
  1397. lines[i] = lines[i].substr(1);
  1398. newEnd -= 1;
  1399. }
  1400. }
  1401. }
  1402. }
  1403. var newText = lines.join("\n");
  1404. textArea.value =
  1405. textArea.value.slice(0, start) + newText + textArea.value.slice(end);
  1406. textArea.selectionStart = start !== end ? start : newEnd;
  1407. textArea.selectionEnd = newEnd;
  1408. } else if (event.ctrlKey && (event.keyCode === 10 || event.keyCode === 13)) {
  1409. //ctrl + enter
  1410. this.compileStyle();
  1411. }
  1412. return true;
  1413. };
  1414. /**
  1415. * Updates the values of view model
  1416. * @private
  1417. */
  1418. Cesium3DTilesInspectorViewModel.prototype._update = function () {
  1419. var tileset = this._tileset;
  1420. if (this.performance) {
  1421. this._performanceDisplay.update();
  1422. }
  1423. if (defined(tileset)) {
  1424. if (tileset.isDestroyed()) {
  1425. this.tile = undefined;
  1426. this.feature = undefined;
  1427. this.tileset = undefined;
  1428. return;
  1429. }
  1430. var style = tileset.style;
  1431. if (this._style !== tileset.style) {
  1432. if (this._shouldStyle) {
  1433. tileset.style = this._style;
  1434. this._shouldStyle = false;
  1435. } else {
  1436. this._style = style;
  1437. this.styleString = JSON.stringify(style.style, null, " ");
  1438. }
  1439. }
  1440. }
  1441. if (this.showStatistics) {
  1442. this._statisticsText = getStatistics(tileset, false);
  1443. this._pickStatisticsText = getStatistics(tileset, true);
  1444. }
  1445. };
  1446. /**
  1447. * @returns {Boolean} true if the object has been destroyed, false otherwise.
  1448. */
  1449. Cesium3DTilesInspectorViewModel.prototype.isDestroyed = function () {
  1450. return false;
  1451. };
  1452. /**
  1453. * Destroys the widget. Should be called if permanently
  1454. * removing the widget from layout.
  1455. */
  1456. Cesium3DTilesInspectorViewModel.prototype.destroy = function () {
  1457. this._eventHandler.destroy();
  1458. this._removePostRenderEvent();
  1459. var that = this;
  1460. this._definedProperties.forEach(function (property) {
  1461. knockout.getObservable(that, property).dispose();
  1462. });
  1463. return destroyObject(this);
  1464. };
  1465. /**
  1466. * Generates an HTML string of the statistics
  1467. *
  1468. * @function
  1469. * @param {Cesium3DTileset} tileset The tileset
  1470. * @param {Boolean} isPick Whether this is getting the statistics for the pick pass
  1471. * @returns {String} The formatted statistics
  1472. */
  1473. Cesium3DTilesInspectorViewModel.getStatistics = getStatistics;
  1474. export default Cesium3DTilesInspectorViewModel;