ui.three.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /**
  2. * @author mrdoob / http://mrdoob.com/
  3. */
  4. UI.Texture = function ( mapping ) {
  5. UI.Element.call( this );
  6. var scope = this;
  7. var dom = document.createElement( 'span' );
  8. var input = document.createElement( 'input' );
  9. input.type = 'file';
  10. input.addEventListener( 'change', function ( event ) {
  11. loadFile( event.target.files[ 0 ] );
  12. } );
  13. var canvas = document.createElement( 'canvas' );
  14. canvas.width = 32;
  15. canvas.height = 16;
  16. canvas.style.cursor = 'pointer';
  17. canvas.style.marginRight = '5px';
  18. canvas.style.border = '1px solid #888';
  19. canvas.addEventListener( 'click', function ( event ) {
  20. input.click();
  21. }, false );
  22. canvas.addEventListener( 'drop', function ( event ) {
  23. event.preventDefault();
  24. event.stopPropagation();
  25. loadFile( event.dataTransfer.files[ 0 ] );
  26. }, false );
  27. dom.appendChild( canvas );
  28. var name = document.createElement( 'input' );
  29. name.disabled = true;
  30. name.style.width = '64px';
  31. name.style.border = '1px solid #ccc';
  32. dom.appendChild( name );
  33. var loadFile = function ( file ) {
  34. if ( file.type.match( 'image.*' ) ) {
  35. var reader = new FileReader();
  36. reader.addEventListener( 'load', function ( event ) {
  37. var image = document.createElement( 'img' );
  38. image.addEventListener( 'load', function( event ) {
  39. var texture = new THREE.Texture( this, mapping );
  40. texture.sourceFile = file.name;
  41. texture.needsUpdate = true;
  42. scope.setValue( texture );
  43. if ( scope.onChangeCallback ) scope.onChangeCallback();
  44. }, false );
  45. image.src = event.target.result;
  46. }, false );
  47. reader.readAsDataURL( file );
  48. }
  49. }
  50. this.dom = dom;
  51. this.texture = null;
  52. this.onChangeCallback = null;
  53. return this;
  54. };
  55. UI.Texture.prototype = Object.create( UI.Element.prototype );
  56. UI.Texture.prototype.constructor = UI.Texture;
  57. UI.Texture.prototype.getValue = function () {
  58. return this.texture;
  59. };
  60. UI.Texture.prototype.setValue = function ( texture ) {
  61. var canvas = this.dom.children[ 0 ];
  62. var name = this.dom.children[ 1 ];
  63. var context = canvas.getContext( '2d' );
  64. if ( texture !== null ) {
  65. var image = texture.image;
  66. if ( image !== undefined && image.width > 0 ) {
  67. name.value = texture.sourceFile;
  68. var scale = canvas.width / image.width;
  69. context.drawImage( image, 0, 0, image.width * scale, image.height * scale );
  70. } else {
  71. name.value = texture.sourceFile + ' (error)';
  72. context.clearRect( 0, 0, canvas.width, canvas.height );
  73. }
  74. } else {
  75. name.value = '';
  76. context.clearRect( 0, 0, canvas.width, canvas.height );
  77. }
  78. this.texture = texture;
  79. };
  80. UI.Texture.prototype.onChange = function ( callback ) {
  81. this.onChangeCallback = callback;
  82. return this;
  83. };
  84. // Outliner
  85. UI.Outliner = function ( editor ) {
  86. UI.Element.call( this );
  87. var scope = this;
  88. var dom = document.createElement( 'div' );
  89. dom.className = 'Outliner';
  90. dom.tabIndex = 0; // keyup event is ignored without setting tabIndex
  91. var scene = editor.scene;
  92. var sortable = Sortable.create( dom, {
  93. draggable: '.draggable',
  94. onUpdate: function ( event ) {
  95. var item = event.item;
  96. var object = scene.getObjectById( item.value );
  97. if ( item.nextSibling === null ) {
  98. editor.execute( new MoveObjectCommand( object, editor.scene ) );
  99. } else {
  100. var nextObject = scene.getObjectById( item.nextSibling.value );
  101. editor.execute( new MoveObjectCommand( object, nextObject.parent, nextObject ) );
  102. }
  103. }
  104. } );
  105. // Broadcast for object selection after arrow navigation
  106. var changeEvent = document.createEvent('HTMLEvents');
  107. changeEvent.initEvent( 'change', true, true );
  108. // Prevent native scroll behavior
  109. dom.addEventListener( 'keydown', function (event) {
  110. switch ( event.keyCode ) {
  111. case 38: // up
  112. case 40: // down
  113. event.preventDefault();
  114. event.stopPropagation();
  115. break;
  116. }
  117. }, false);
  118. // Keybindings to support arrow navigation
  119. dom.addEventListener( 'keyup', function (event) {
  120. function select( index ) {
  121. if ( index >= 0 && index < scope.options.length ) {
  122. scope.selectedIndex = index;
  123. // Highlight selected dom elem and scroll parent if needed
  124. scope.setValue( scope.options[ index ].value );
  125. scope.dom.dispatchEvent( changeEvent );
  126. }
  127. }
  128. switch ( event.keyCode ) {
  129. case 38: // up
  130. select( scope.selectedIndex - 1 );
  131. break;
  132. case 40: // down
  133. select( scope.selectedIndex + 1 );
  134. break;
  135. }
  136. }, false);
  137. this.dom = dom;
  138. this.options = [];
  139. this.selectedIndex = -1;
  140. this.selectedValue = null;
  141. return this;
  142. };
  143. UI.Outliner.prototype = Object.create( UI.Element.prototype );
  144. UI.Outliner.prototype.constructor = UI.Outliner;
  145. UI.Outliner.prototype.setOptions = function ( options ) {
  146. var scope = this;
  147. var changeEvent = document.createEvent( 'HTMLEvents' );
  148. changeEvent.initEvent( 'change', true, true );
  149. while ( scope.dom.children.length > 0 ) {
  150. scope.dom.removeChild( scope.dom.firstChild );
  151. }
  152. scope.options = [];
  153. for ( var i = 0; i < options.length; i ++ ) {
  154. var option = options[ i ];
  155. var div = document.createElement( 'div' );
  156. div.className = 'option ' + ( option.static === true ? '': 'draggable' );
  157. div.innerHTML = option.html;
  158. div.value = option.value;
  159. scope.dom.appendChild( div );
  160. scope.options.push( div );
  161. div.addEventListener( 'click', function ( event ) {
  162. scope.setValue( this.value );
  163. scope.dom.dispatchEvent( changeEvent );
  164. }, false );
  165. }
  166. return scope;
  167. };
  168. UI.Outliner.prototype.getValue = function () {
  169. return this.selectedValue;
  170. };
  171. UI.Outliner.prototype.setValue = function ( value ) {
  172. for ( var i = 0; i < this.options.length; i ++ ) {
  173. var element = this.options[ i ];
  174. if ( element.value === value ) {
  175. element.classList.add( 'active' );
  176. // scroll into view
  177. var y = element.offsetTop - this.dom.offsetTop;
  178. var bottomY = y + element.offsetHeight;
  179. var minScroll = bottomY - this.dom.offsetHeight;
  180. if ( this.dom.scrollTop > y ) {
  181. this.dom.scrollTop = y
  182. } else if ( this.dom.scrollTop < minScroll ) {
  183. this.dom.scrollTop = minScroll;
  184. }
  185. this.selectedIndex = i;
  186. } else {
  187. element.classList.remove( 'active' );
  188. }
  189. }
  190. this.selectedValue = value;
  191. return this;
  192. };
  193. UI.THREE = {};
  194. UI.THREE.Boolean = function ( boolean, text ) {
  195. UI.Span.call( this );
  196. this.setMarginRight( '10px' )
  197. this.checkbox = new UI.Checkbox( boolean );
  198. this.text = new UI.Text( text ).setMarginLeft( '3px' );
  199. this.add( this.checkbox );
  200. this.add( this.text );
  201. };
  202. UI.THREE.Boolean.prototype = Object.create( UI.Span.prototype );
  203. UI.THREE.Boolean.prototype.constructor = UI.THREE.Boolean;
  204. UI.THREE.Boolean.prototype.getValue = function () {
  205. return this.checkbox.getValue();
  206. };
  207. UI.THREE.Boolean.prototype.setValue = function ( value ) {
  208. return this.checkbox.setValue( value );
  209. };