Cesium3DTilesInspector.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. import Check from '../../Core/Check.js';
  2. import defaultValue from '../../Core/defaultValue.js';
  3. import defined from '../../Core/defined.js';
  4. import defineProperties from '../../Core/defineProperties.js';
  5. import destroyObject from '../../Core/destroyObject.js';
  6. import knockout from '../../ThirdParty/knockout.js';
  7. import getElement from '../getElement.js';
  8. import InspectorShared from '../InspectorShared.js';
  9. import Cesium3DTilesInspectorViewModel from './Cesium3DTilesInspectorViewModel.js';
  10. /**
  11. * Inspector widget to aid in debugging 3D Tiles
  12. *
  13. * @alias Cesium3DTilesInspector
  14. * @constructor
  15. *
  16. * @param {Element|String} container The DOM element or ID that will contain the widget.
  17. * @param {Scene} scene the Scene instance to use.
  18. */
  19. function Cesium3DTilesInspector(container, scene) {
  20. //>>includeStart('debug', pragmas.debug);
  21. Check.defined('container', container);
  22. Check.typeOf.object('scene', scene);
  23. //>>includeEnd('debug');
  24. container = getElement(container);
  25. var element = document.createElement('div');
  26. var performanceContainer = document.createElement('div');
  27. performanceContainer.setAttribute('data-bind', 'visible: performance');
  28. var viewModel = new Cesium3DTilesInspectorViewModel(scene, performanceContainer);
  29. this._viewModel = viewModel;
  30. this._container = container;
  31. this._element = element;
  32. var text = document.createElement('div');
  33. text.textContent = '3D Tiles Inspector';
  34. text.className = 'cesium-cesiumInspector-button';
  35. text.setAttribute('data-bind', 'click: toggleInspector');
  36. element.appendChild(text);
  37. element.className = 'cesium-cesiumInspector cesium-3DTilesInspector';
  38. element.setAttribute('data-bind', 'css: { "cesium-cesiumInspector-visible" : inspectorVisible, "cesium-cesiumInspector-hidden" : !inspectorVisible}');
  39. container.appendChild(element);
  40. var panel = document.createElement('div');
  41. this._panel = panel;
  42. panel.className = 'cesium-cesiumInspector-dropDown';
  43. element.appendChild(panel);
  44. var createSection = InspectorShared.createSection;
  45. var createCheckbox = InspectorShared.createCheckbox;
  46. var tilesetPanelContents = createSection(panel, 'Tileset', 'tilesetVisible', 'toggleTileset');
  47. var displayPanelContents = createSection(panel, 'Display', 'displayVisible', 'toggleDisplay');
  48. var updatePanelContents = createSection(panel, 'Update', 'updateVisible', 'toggleUpdate');
  49. var loggingPanelContents = createSection(panel, 'Logging', 'loggingVisible', 'toggleLogging');
  50. var tileDebugLabelsPanelContents = createSection(panel, 'Tile Debug Labels', 'tileDebugLabelsVisible', 'toggleTileDebugLabels');
  51. var stylePanelContents = createSection(panel, 'Style', 'styleVisible', 'toggleStyle');
  52. var optimizationPanelContents = createSection(panel, 'Optimization', 'optimizationVisible', 'toggleOptimization');
  53. var properties = document.createElement('div');
  54. properties.className = 'field-group';
  55. var propertiesLabel = document.createElement('label');
  56. propertiesLabel.className = 'field-label';
  57. propertiesLabel.appendChild(document.createTextNode('Properties: '));
  58. var propertiesField = document.createElement('div');
  59. propertiesField.setAttribute('data-bind', 'text: properties');
  60. properties.appendChild(propertiesLabel);
  61. properties.appendChild(propertiesField);
  62. tilesetPanelContents.appendChild(properties);
  63. tilesetPanelContents.appendChild(makeButton('togglePickTileset', 'Pick Tileset', 'pickActive'));
  64. tilesetPanelContents.appendChild(makeButton('trimTilesCache', 'Trim Tiles Cache'));
  65. tilesetPanelContents.appendChild(createCheckbox('Enable Picking', 'picking'));
  66. displayPanelContents.appendChild(createCheckbox('Colorize', 'colorize'));
  67. displayPanelContents.appendChild(createCheckbox('Wireframe', 'wireframe'));
  68. displayPanelContents.appendChild(createCheckbox('Bounding Volumes', 'showBoundingVolumes'));
  69. displayPanelContents.appendChild(createCheckbox('Content Volumes', 'showContentBoundingVolumes'));
  70. displayPanelContents.appendChild(createCheckbox('Request Volumes', 'showRequestVolumes'));
  71. displayPanelContents.appendChild(createCheckbox('Point Cloud Shading', 'pointCloudShading'));
  72. var pointCloudShadingContainer = document.createElement('div');
  73. pointCloudShadingContainer.setAttribute('data-bind', 'visible: pointCloudShading');
  74. pointCloudShadingContainer.appendChild(makeRangeInput('geometricErrorScale', 0, 2, 0.01, 'Geometric Error Scale'));
  75. pointCloudShadingContainer.appendChild(makeRangeInput('maximumAttenuation', 0, 32, 1, 'Maximum Attenuation'));
  76. pointCloudShadingContainer.appendChild(makeRangeInput('baseResolution', 0, 1, 0.01, 'Base Resolution'));
  77. pointCloudShadingContainer.appendChild(createCheckbox('Eye Dome Lighting (EDL)', 'eyeDomeLighting'));
  78. displayPanelContents.appendChild(pointCloudShadingContainer);
  79. var edlContainer = document.createElement('div');
  80. edlContainer.setAttribute('data-bind', 'visible: eyeDomeLighting');
  81. edlContainer.appendChild(makeRangeInput('eyeDomeLightingStrength', 0, 2.0, 0.1, 'EDL Strength'));
  82. edlContainer.appendChild(makeRangeInput('eyeDomeLightingRadius', 0, 4.0, 0.1, 'EDL Radius'));
  83. pointCloudShadingContainer.appendChild(edlContainer);
  84. updatePanelContents.appendChild(createCheckbox('Freeze Frame', 'freezeFrame'));
  85. updatePanelContents.appendChild(createCheckbox('Dynamic Screen Space Error', 'dynamicScreenSpaceError'));
  86. var sseContainer = document.createElement('div');
  87. sseContainer.appendChild(makeRangeInput('maximumScreenSpaceError', 0, 128, 1, 'Maximum Screen Space Error'));
  88. updatePanelContents.appendChild(sseContainer);
  89. var dynamicScreenSpaceErrorContainer = document.createElement('div');
  90. dynamicScreenSpaceErrorContainer.setAttribute('data-bind', 'visible: dynamicScreenSpaceError');
  91. dynamicScreenSpaceErrorContainer.appendChild(makeRangeInput('dynamicScreenSpaceErrorDensitySliderValue', 0, 1, 0.005, 'Screen Space Error Density', 'dynamicScreenSpaceErrorDensity'));
  92. dynamicScreenSpaceErrorContainer.appendChild(makeRangeInput('dynamicScreenSpaceErrorFactor', 1, 10, 0.1, 'Screen Space Error Factor'));
  93. updatePanelContents.appendChild(dynamicScreenSpaceErrorContainer);
  94. loggingPanelContents.appendChild(createCheckbox('Performance', 'performance'));
  95. loggingPanelContents.appendChild(performanceContainer);
  96. loggingPanelContents.appendChild(createCheckbox('Statistics', 'showStatistics'));
  97. var statistics = document.createElement('div');
  98. statistics.className = 'cesium-3dTilesInspector-statistics';
  99. statistics.setAttribute('data-bind', 'html: statisticsText, visible: showStatistics');
  100. loggingPanelContents.appendChild(statistics);
  101. loggingPanelContents.appendChild(createCheckbox('Pick Statistics', 'showPickStatistics'));
  102. var pickStatistics = document.createElement('div');
  103. pickStatistics.className = 'cesium-3dTilesInspector-statistics';
  104. pickStatistics.setAttribute('data-bind', 'html: pickStatisticsText, visible: showPickStatistics');
  105. loggingPanelContents.appendChild(pickStatistics);
  106. var stylePanelEditor = document.createElement('div');
  107. stylePanelContents.appendChild(stylePanelEditor);
  108. stylePanelEditor.appendChild(document.createTextNode('Color Blend Mode: '));
  109. var blendDropdown = document.createElement('select');
  110. blendDropdown.setAttribute('data-bind', 'options: colorBlendModes, ' +
  111. 'optionsText: "text", ' +
  112. 'optionsValue: "value", ' +
  113. 'value: colorBlendMode');
  114. stylePanelEditor.appendChild(blendDropdown);
  115. var styleEditor = document.createElement('textarea');
  116. styleEditor.setAttribute('data-bind', 'textInput: styleString, event: { keydown: styleEditorKeyPress }');
  117. stylePanelEditor.className = 'cesium-cesiumInspector-styleEditor';
  118. stylePanelEditor.appendChild(styleEditor);
  119. var closeStylesBtn = makeButton('compileStyle', 'Compile (Ctrl+Enter)');
  120. stylePanelEditor.appendChild(closeStylesBtn);
  121. var errorBox = document.createElement('div');
  122. errorBox.className = 'cesium-cesiumInspector-error';
  123. errorBox.setAttribute('data-bind', 'text: editorError');
  124. stylePanelEditor.appendChild(errorBox);
  125. tileDebugLabelsPanelContents.appendChild(createCheckbox('Show Picked Only', 'showOnlyPickedTileDebugLabel'));
  126. tileDebugLabelsPanelContents.appendChild(createCheckbox('Geometric Error', 'showGeometricError'));
  127. tileDebugLabelsPanelContents.appendChild(createCheckbox('Rendering Statistics', 'showRenderingStatistics'));
  128. tileDebugLabelsPanelContents.appendChild(createCheckbox('Memory Usage (MB)', 'showMemoryUsage'));
  129. tileDebugLabelsPanelContents.appendChild(createCheckbox('Url', 'showUrl'));
  130. optimizationPanelContents.appendChild(createCheckbox('Skip Tile LODs', 'skipLevelOfDetail'));
  131. var skipScreenSpaceErrorFactorContainer = document.createElement('div');
  132. skipScreenSpaceErrorFactorContainer.appendChild(makeRangeInput('skipScreenSpaceErrorFactor', 1, 50, 1, 'Skip SSE Factor'));
  133. optimizationPanelContents.appendChild(skipScreenSpaceErrorFactorContainer);
  134. var baseScreenSpaceError = document.createElement('div');
  135. baseScreenSpaceError.appendChild(makeRangeInput('baseScreenSpaceError', 0, 4096, 1, 'SSE before skipping LOD'));
  136. optimizationPanelContents.appendChild(baseScreenSpaceError);
  137. var skipLevelsContainer = document.createElement('div');
  138. skipLevelsContainer.appendChild(makeRangeInput('skipLevels', 0, 10, 1, 'Min. levels to skip'));
  139. optimizationPanelContents.appendChild(skipLevelsContainer);
  140. optimizationPanelContents.appendChild(createCheckbox('Load only tiles that meet the max SSE.', 'immediatelyLoadDesiredLevelOfDetail'));
  141. optimizationPanelContents.appendChild(createCheckbox('Load siblings of visible tiles', 'loadSiblings'));
  142. knockout.applyBindings(viewModel, element);
  143. }
  144. defineProperties(Cesium3DTilesInspector.prototype, {
  145. /**
  146. * Gets the parent container.
  147. * @memberof Cesium3DTilesInspector.prototype
  148. *
  149. * @type {Element}
  150. */
  151. container : {
  152. get : function() {
  153. return this._container;
  154. }
  155. },
  156. /**
  157. * Gets the view model.
  158. * @memberof Cesium3DTilesInspector.prototype
  159. *
  160. * @type {Cesium3DTilesInspectorViewModel}
  161. */
  162. viewModel : {
  163. get : function() {
  164. return this._viewModel;
  165. }
  166. }
  167. });
  168. /**
  169. * @returns {Boolean} true if the object has been destroyed, false otherwise.
  170. */
  171. Cesium3DTilesInspector.prototype.isDestroyed = function() {
  172. return false;
  173. };
  174. /**
  175. * Destroys the widget. Should be called if permanently
  176. * removing the widget from layout.
  177. */
  178. Cesium3DTilesInspector.prototype.destroy = function() {
  179. knockout.cleanNode(this._element);
  180. this._container.removeChild(this._element);
  181. this.viewModel.destroy();
  182. return destroyObject(this);
  183. };
  184. function makeRangeInput(property, min, max, step, text, displayProperty) {
  185. displayProperty = defaultValue(displayProperty, property);
  186. var input = document.createElement('input');
  187. input.setAttribute('data-bind', 'value: ' + displayProperty);
  188. input.type = 'number';
  189. var slider = document.createElement('input');
  190. slider.type = 'range';
  191. slider.min = min;
  192. slider.max = max;
  193. slider.step = step;
  194. slider.setAttribute('data-bind', 'valueUpdate: "input", value: ' + property);
  195. var wrapper = document.createElement('div');
  196. wrapper.appendChild(slider);
  197. var container = document.createElement('div');
  198. container.className = 'cesium-cesiumInspector-slider';
  199. container.appendChild(document.createTextNode(text));
  200. container.appendChild(input);
  201. container.appendChild(wrapper);
  202. return container;
  203. }
  204. function makeButton(action, text, active) {
  205. var button = document.createElement('button');
  206. button.type = 'button';
  207. button.textContent = text;
  208. button.className = 'cesium-cesiumInspector-pickButton';
  209. var binding = 'click: ' + action;
  210. if (defined(active)) {
  211. binding += ', css: {"cesium-cesiumInspector-pickButtonHighlight" : ' + active + '}';
  212. }
  213. button.setAttribute('data-bind', binding);
  214. return button;
  215. }
  216. export default Cesium3DTilesInspector;