cubes.js 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109
  1. /*
  2. CUBES
  3. A Cube is composed of 27 Cubelets (3x3x3 grid) numbered 0 through 26.
  4. Cubelets are numbered beginning from the top-left-forward corner of the
  5. Cube and proceeding left to right, top to bottom, forward to back:
  6. -----------------------
  7. / 18 19 20 /|
  8. / / |
  9. / 9 10 11 / 20
  10. / / |
  11. / 0 1 2 / 11 |
  12. ----------------------- 23
  13. | |2 |
  14. | 0 1 2 | 14 |
  15. | | 26
  16. | |5 |
  17. | 3 4 5 | 17 /
  18. | | /
  19. | |8 /
  20. | 6 7 8 | /
  21. | | /
  22. -----------------------
  23. Portions of the Cube are grouped (Groups):
  24. this.core
  25. this.centers
  26. this.edges
  27. this.corners
  28. this.crosses
  29. Portions of the Cube are grouped and rotatable (Slices):
  30. Rotatable around the Z axis:
  31. this.front
  32. this.standing
  33. this.back
  34. Rotatable around the X axis:
  35. this.left
  36. this.middle
  37. this.right
  38. Rotatable around the Y axis:
  39. this.up
  40. this.equator
  41. this.down
  42. A Cube may be inspected through its Faces (see Slices for more
  43. information on Faces vs Slices). From the browser's JavaScript console:
  44. this.inspect()
  45. This will reveal each Face's Cubelet indexes and colors using the Face's
  46. compact inspection mode. The non-compact mode may be accessed by passing
  47. a non-false value as an argument:
  48. this.inspect( true )
  49. */
  50. export function Cube( id, preset ){
  51. // Important for working around lexical closures in things like
  52. // forEach() or setTimeout(), etc which change the scope of "this".
  53. var cube = this
  54. this.id = id;
  55. // Some important booleans.
  56. this.isReady = true
  57. this.isShuffling = false
  58. this.isRotating = false
  59. this.isSolving = false
  60. // Every fire of this.loop() will attempt to complete our tasks
  61. // which can only be run if this.isReady === true.
  62. this.taskQueue = new Queue()
  63. // We need the ability to gang up twist commands.
  64. // Every fire of this.loop() will attempt to empty it.
  65. this.twistQueue = new Queue( Twist.validate )
  66. // How long should a Cube.twist() take?
  67. this.twistDuration = SECOND
  68. // If we shuffle, how shall we do it?
  69. this.shuffleMethod = this.PRESERVE_LOGO
  70. // Size matters? Cubelets will attempt to read these values.
  71. this.size = 420
  72. this.cubeletSize = 140
  73. // We need to create and setup a new CSS3 Object
  74. // to represent our Cube.
  75. // THREE will take care of attaching it to the DOM, etc.
  76. ///////VWF_VIEW////
  77. // if( erno.renderMode === 'css' ){
  78. // this.domElement = document.createElement( 'div' )
  79. // this.domElement.classList.add( 'cube' )
  80. // this.threeObject = new THREE.CSS3DObject( this.domElement )
  81. // }
  82. // else if( erno.renderMode === 'svg' ){
  83. // this.threeObject = new THREE.Object3D()
  84. // }
  85. // this.threeObject.rotation.set(
  86. // ( 25 ).degreesToRadians(),
  87. // ( -30 ).degreesToRadians(),
  88. // 0
  89. // )
  90. // scene.add( this.threeObject )
  91. /////
  92. // If we enable Auto-Rotate then the cube will spin (not twist!) in space
  93. // by adding the following values to the Three object on each frame.
  94. this.rotationDeltaX = 0.1
  95. this.rotationDeltaY = 0.15
  96. this.rotationDeltaZ = 0
  97. // Here's the first big map we've come across in the program so far.
  98. // Imagine you're looking at the Cube straight on so you only see the front face.
  99. // We're going to map that front face from left to right (3), and top to bottom (3):
  100. // that's 3 x 3 = 9 Cubelets.
  101. // But then behind the Front slice we also have a Standing slice (9) and Back slice (9),
  102. // so that's going to be 27 Cubelets in total to create a Cube.
  103. this.cubelets = []
  104. ;([
  105. // Front slice
  106. [ W, O, , , G, ], [ W, O, , , , ], [ W, O, B, , , ],// 0, 1, 2
  107. [ W, , , , G, ], [ W, , , , , ], [ W, , B, , , ],// 3, 4, 5
  108. [ W, , , R, G, ], [ W, , , R, , ], [ W, , B, R, , ],// 6, 7, 8
  109. // Standing slice
  110. [ , O, , , G, ], [ , O, , , , ], [ , O, B, , , ],// 9, 10, 11
  111. [ , , , , G, ], [ , , , , , ], [ , , B, , , ],// 12, XX, 14
  112. [ , , , R, G, ], [ , , , R, , ], [ , , B, R, , ],// 15, 16, 17
  113. // Back slice
  114. [ , O, , , G, Y ], [ , O, , , , Y ], [ , O, B, , , Y ],// 18, 19, 20
  115. [ , , , , G, Y ], [ , , , , , Y ], [ , , B, , , Y ],// 21, 22, 23
  116. [ , , , R, G, Y ], [ , , , R, , Y ], [ , , B, R, , Y ] // 24, 25, 26
  117. ]).forEach( function( cubeletColorMap, cubeletId ){
  118. cube.cubelets.push( new Cubelet( cube, cubeletId, cubeletColorMap ))
  119. })
  120. // Mapping the Cube creates all the convenience shortcuts
  121. // that we will need later. (Demonstrated immediately below!)
  122. this.map()
  123. // Now that we have mapped faces we can create faceLabels
  124. /////////VWF_VIEW
  125. // if( erno.renderMode === 'css' ){
  126. // this.faces.forEach( function( face, i ){
  127. // var labelElement = document.createElement( 'div' )
  128. // labelElement.classList.add( 'faceLabel' )
  129. // labelElement.classList.add( 'face'+ face.face.capitalize() )
  130. // labelElement.innerHTML = face.face.toUpperCase()
  131. // cube.domElement.appendChild( labelElement )
  132. // })
  133. // }
  134. ///////////
  135. // We need to map our folds separately from Cube.map()
  136. // because we only want folds mapped at creation time.
  137. // Remapping folds with each Cube.twist() would get weird...
  138. this.folds = [
  139. new Fold( this.front, this.right ),
  140. new Fold( this.left, this.up ),
  141. new Fold( this.down, this.back )
  142. ]
  143. // Enable some "Hero" text for this Cube.
  144. /////VWF_VIEW
  145. // if( erno.renderMode === 'css' ){
  146. // this.setText( 'BEYONDRUBIKs CUBE', 0 )
  147. // this.setText( 'BEYONDRUBIKs CUBE', 1 )
  148. // this.setText( 'BEYONDRUBIKs CUBE', 2 )
  149. // }
  150. /////////
  151. // Shall we load some presets here?
  152. // preset = 'preset' + preset.capitalize()
  153. // if( this[ preset ] instanceof Function === false ) preset = 'presetBling'
  154. // this[ preset ]()
  155. // Get ready for major loop-age.
  156. // Our Cube checks these booleans at roughly 60fps.
  157. // setInterval( cube.loop, 16 )
  158. // Enable key commands for our Cube.
  159. /////VWF_VIEW/////
  160. // $( document ).keypress( function( event ){
  161. // if( $( 'input:focus, textarea:focus' ).length === 0 ){
  162. // var key = String.fromCharCode( event.which )
  163. // if( 'XxRrMmLlYyUuEeDdZzFfSsBb'.indexOf( key ) >= 0 ) cube.twistQueue.add( key )
  164. // }
  165. // })
  166. ////////
  167. }
  168. globalThis.setupTasks = globalThis.setupTasks || []
  169. globalThis.setupTasks.push( function(){
  170. Cube.swapMaps = {
  171. 'f':[
  172. [0,2],
  173. [1,5],
  174. [2,8],
  175. [3,1],
  176. [5,7],
  177. [6,0],
  178. [7,3],
  179. [8,6]
  180. ],
  181. 'F':[
  182. [0,6],
  183. [1,3],
  184. [2,0],
  185. [3,7],
  186. [5,1],
  187. [6,8],
  188. [7,5],
  189. [8,2]
  190. ],
  191. 'b':[
  192. [18,24],
  193. [19,21],
  194. [20,18],
  195. [21,25],
  196. [23,19],
  197. [24,26],
  198. [25,23],
  199. [26,20]
  200. ],
  201. 'B':[
  202. [18,20],
  203. [19,23],
  204. [20,26],
  205. [21,19],
  206. [23,25],
  207. [24,18],
  208. [25,21],
  209. [26,24]
  210. ],
  211. 'd':[
  212. [6,8],
  213. [7,17],
  214. [8,26],
  215. [15,7],
  216. [17,25],
  217. [24,6],
  218. [25,15],
  219. [26,24]
  220. ],
  221. 'D':[
  222. [6,24],
  223. [7,15],
  224. [8,6],
  225. [15,25],
  226. [17,7],
  227. [24,26],
  228. [25,17],
  229. [26,8]
  230. ],
  231. 'u':[
  232. [18,20],
  233. [19,11],
  234. [20,2],
  235. [9,19],
  236. [11,1],
  237. [0,18],
  238. [1,9],
  239. [2,0]
  240. ],
  241. 'U':[
  242. [18,0],
  243. [19,9],
  244. [20,18],
  245. [9,1],
  246. [11,19],
  247. [0,2],
  248. [1,11],
  249. [2,20]
  250. ],
  251. 'l':[
  252. [18,0],
  253. [9,3],
  254. [0,6],
  255. [21,9],
  256. [3,15],
  257. [24,18],
  258. [15,21],
  259. [6,24]
  260. ],
  261. 'L':[
  262. [18,24],
  263. [9,21],
  264. [0,18],
  265. [21,15],
  266. [3,9],
  267. [24,6],
  268. [15,3],
  269. [6,0]
  270. ],
  271. 'r':[
  272. [2,20],
  273. [11,23],
  274. [20,26],
  275. [5,11],
  276. [23,17],
  277. [8,2],
  278. [17,5],
  279. [26,8]
  280. ],
  281. 'R':[
  282. [2,8],
  283. [11,5],
  284. [20,2],
  285. [5,17],
  286. [23,11],
  287. [8,26],
  288. [17,23],
  289. [26,20]
  290. ]
  291. }
  292. Cube.verbosity = 0.5;
  293. Cube.prototype = Object.create( Group.prototype )
  294. Cube.prototype.constructor = Cube
  295. forceAugment( Cube, {
  296. // A Rubik's Cube is composed of 27 cubelets arranged 3 x 3 x 3.
  297. // We need a map that relates these 27 locations to the 27 cubelets
  298. // such that we can ask questions like:
  299. // What colors are on the Front face of the cube? Etc.
  300. map: function(){
  301. var that = this, i
  302. // Groups are simple collections of Cubelets.
  303. // Their position and rotation is irrelevant.
  304. this.core = new Group()
  305. this.centers = new Group()
  306. this.edges = new Group()
  307. this.corners = new Group()
  308. this.crosses = new Group()
  309. this.cubelets.forEach( function( cubelet, index ){
  310. if( cubelet.type === 'core' ) that.core.add( cubelet )
  311. if( cubelet.type === 'center' ) that.centers.add( cubelet )
  312. if( cubelet.type === 'edge' ) that.edges.add( cubelet )
  313. if( cubelet.type === 'corner' ) that.corners.add( cubelet )
  314. if( cubelet.type === 'center' || cubelet.type === 'edge' ) that.crosses.add( cubelet )
  315. })
  316. // Slices that can rotate about the X-axis:
  317. this.left = new Slice(
  318. this.cubelets[ 24 ], this.cubelets[ 21 ], this.cubelets[ 18 ],
  319. this.cubelets[ 15 ], this.cubelets[ 12 ], this.cubelets[ 9 ],
  320. this.cubelets[ 6 ], this.cubelets[ 3 ], this.cubelets[ 0 ]
  321. )
  322. this.left.name = 'left'
  323. this.middle = new Slice(
  324. this.cubelets[ 25 ], this.cubelets[ 22 ], this.cubelets[ 19 ],
  325. this.cubelets[ 16 ], this.cubelets[ 13 ], this.cubelets[ 10 ],
  326. this.cubelets[ 7 ], this.cubelets[ 4 ], this.cubelets[ 1 ]
  327. )
  328. this.middle.name = 'middle'
  329. this.right = new Slice(
  330. this.cubelets[ 2 ], this.cubelets[ 11 ], this.cubelets[ 20 ],
  331. this.cubelets[ 5 ], this.cubelets[ 14 ], this.cubelets[ 23 ],
  332. this.cubelets[ 8 ], this.cubelets[ 17 ], this.cubelets[ 26 ]
  333. )
  334. this.right.name = 'right'
  335. // Slices that can rotate about the Y-axis:
  336. this.up = new Slice(
  337. this.cubelets[ 18 ], this.cubelets[ 19 ], this.cubelets[ 20 ],
  338. this.cubelets[ 9 ], this.cubelets[ 10 ], this.cubelets[ 11 ],
  339. this.cubelets[ 0 ], this.cubelets[ 1 ], this.cubelets[ 2 ]
  340. )
  341. this.up.name = 'up'
  342. this.equator = new Slice(
  343. this.cubelets[ 21 ], this.cubelets[ 22 ], this.cubelets[ 23 ],
  344. this.cubelets[ 12 ], this.cubelets[ 13 ], this.cubelets[ 14 ],
  345. this.cubelets[ 3 ], this.cubelets[ 4 ], this.cubelets[ 5 ]
  346. )
  347. this.equator.name = 'equator'
  348. this.down = new Slice(
  349. this.cubelets[ 8 ], this.cubelets[ 17 ], this.cubelets[ 26 ],
  350. this.cubelets[ 7 ], this.cubelets[ 16 ], this.cubelets[ 25 ],
  351. this.cubelets[ 6 ], this.cubelets[ 15 ], this.cubelets[ 24 ]
  352. )
  353. this.down.name = 'down'
  354. // Slices are Groups with purpose; they are rotate-able!
  355. // These are Slices that can rotate about the Z-axis:
  356. this.front = new Slice(
  357. this.cubelets[ 0 ], this.cubelets[ 1 ], this.cubelets[ 2 ],
  358. this.cubelets[ 3 ], this.cubelets[ 4 ], this.cubelets[ 5 ],
  359. this.cubelets[ 6 ], this.cubelets[ 7 ], this.cubelets[ 8 ]
  360. )
  361. this.front.name = 'front'
  362. this.standing = new Slice(
  363. this.cubelets[ 9 ], this.cubelets[ 10 ], this.cubelets[ 11 ],
  364. this.cubelets[ 12 ], this.cubelets[ 13 ], this.cubelets[ 14 ],
  365. this.cubelets[ 15 ], this.cubelets[ 16 ], this.cubelets[ 17 ]
  366. )
  367. this.standing.name = 'standing'
  368. this.back = new Slice(
  369. this.cubelets[ 26 ], this.cubelets[ 23 ], this.cubelets[ 20 ],
  370. this.cubelets[ 25 ], this.cubelets[ 22 ], this.cubelets[ 19 ],
  371. this.cubelets[ 24 ], this.cubelets[ 21 ], this.cubelets[ 18 ]
  372. )
  373. this.back.name = 'back'
  374. // Faces .... special kind of Slice!
  375. this.faces = [ this.front, this.up, this.right, this.down, this.left, this.back ]
  376. // Good to let each Cubelet know where it exists
  377. // in relationship to our full Cube.
  378. for( i = 0; i < this.cubelets.length; i ++ ){
  379. this.cubelets[ i ].setAddress( i );
  380. //vwf_model
  381. // if(that.kernel && this.cubelets[ i ].nodeID){
  382. // that.kernel.setProperty(this.cubelets[ i ].nodeID, "address", this.cubelets[ i ].address);
  383. // }
  384. }
  385. },
  386. // We can read and write text to the Cube.
  387. // This is handled by Folds which are composed of two Faces.
  388. getText: function( fold ){
  389. if( fold === undefined ){
  390. return [
  391. this.folds[ 0 ].getText(),
  392. this.folds[ 1 ].getText(),
  393. this.folds[ 2 ].getText()
  394. ]
  395. }
  396. else if( isNumeric( fold ) && fold >= 0 && fold <= 2 ){
  397. return this.folds[ fold ].getText()
  398. }
  399. },
  400. setText: function( text, fold ){
  401. if( fold === undefined ){
  402. this.folds[ 0 ].setText( text )
  403. this.folds[ 1 ].setText( text )
  404. this.folds[ 2 ].setText( text )
  405. }
  406. else if( isNumeric( fold ) && fold >= 0 && fold <= 2 ){
  407. this.folds[ fold ].setText( text )
  408. }
  409. },
  410. // We'll inspect the Cube by specifically inspecting the Faces.
  411. // Bear in mind this is merely one way to think about the Cube
  412. // and does require some redundancy in terms of Cubelet indexes.
  413. // Here we'll default to 'compact' mode in order to give the
  414. // full Cube overview in the least amount of space.
  415. inspect: function( compact, side ){
  416. compact = !compact
  417. this.front.inspect( compact, side )
  418. this.up.inspect( compact, side )
  419. this.right.inspect( compact, side )
  420. this.down.inspect( compact, side )
  421. this.left.inspect( compact, side )
  422. this.back.inspect( compact, side )
  423. },
  424. solve: function(){
  425. this.isSolving = true
  426. },
  427. isSolved: function(){
  428. return (
  429. this.front.isSolved( FRONT ) &&
  430. this.up.isSolved( UP ) &&
  431. this.right.isSolved( RIGHT ) &&
  432. this.down.isSolved( DOWN ) &&
  433. this.left.isSolved( LEFT ) &&
  434. this.back.isSolved( BACK )
  435. )
  436. },
  437. remap: function(cubeletID, cubeCallback){
  438. // let cubeletID = methodParameters[0];
  439. // let cubeCallback = methodParameters[1]
  440. let threshold = 0.001
  441. // Here's some complexity.
  442. // We need to support partial rotations of arbitrary degrees
  443. // yet ensure our internal model is always in a valid state.
  444. // This means only remapping the Cubelet when it makes sense
  445. // and also remapping the Cube if this Cubelet is allowed to do so.
  446. //let myCube = node.cube;
  447. let cube = this; //node.cube;
  448. let cubelet = cube.cubelets.filter(el=> el.id == cubeletID)[0];
  449. var
  450. xRemaps = cubelet.x.divide( 90 ).round()
  451. .subtract( cubelet.xPrevious.divide( 90 ).round() )
  452. .absolute(),
  453. yRemaps = cubelet.y.divide( 90 ).round()
  454. .subtract( cubelet.yPrevious.divide( 90 ).round() )
  455. .absolute(),
  456. zRemaps = cubelet.z.divide( 90 ).round()
  457. .subtract( cubelet.zPrevious.divide( 90 ).round() )
  458. .absolute()
  459. if( Cube.verbosity >= 0.9 ){
  460. console.log( 'Cublet #'+ ( cubelet.id < 10 ? '0'+ cubelet.id : cubelet.id ),
  461. ' | xRemaps:', xRemaps, ' yRemaps:', yRemaps, ' zRemaps:', zRemaps,
  462. ' | xPrev:', cubelet.xPrevious, ' x:', cubelet.x,
  463. ' | yPrev:', cubelet.yPrevious, ' y:', cubelet.y,
  464. ' | zPrev:', cubelet.zPrevious, ' z:', cubelet.z )
  465. }
  466. if( xRemaps ){
  467. while( xRemaps -- ){
  468. if( cubelet.x < cubelet.xPrevious ) cubelet.faces = [ cubelet.up, cubelet.back, cubelet.right, cubelet.front, cubelet.left, cubelet.down ]
  469. else cubelet.faces = [ cubelet.down, cubelet.front, cubelet.right, cubelet.back, cubelet.left, cubelet.up ]
  470. cubelet.map()
  471. if( cubeCallback !== undefined ){
  472. let swapMap = Cube.swapMaps[cubeCallback];
  473. let swap = cubelet.cube.cubelets.slice();
  474. swapMap.forEach(el=>{
  475. cube.cubelets[el[0]] = swap[el[1]]
  476. })
  477. //cubeCallback( cubelet.cube.cubelets.slice())
  478. cubelet.cube.map()
  479. }
  480. }
  481. cubelet.xPrevious = cubelet.x
  482. }
  483. if( cubelet.x.modulo( 90 ).absolute() < threshold ){
  484. cubelet.x = 0
  485. cubelet.xPrevious = cubelet.x
  486. cubelet.isEngagedX = false
  487. }
  488. if( yRemaps ){
  489. while( yRemaps -- ){
  490. if( cubelet.y < cubelet.yPrevious ) cubelet.faces = [ cubelet.left, cubelet.up, cubelet.front, cubelet.down, cubelet.back, cubelet.right ]
  491. else cubelet.faces = [ cubelet.right, cubelet.up, cubelet.back, cubelet.down, cubelet.front, cubelet.left ]
  492. cubelet.map()
  493. if( cubeCallback !== undefined ){
  494. let swapMap = Cube.swapMaps[cubeCallback];
  495. let swap = cubelet.cube.cubelets.slice();
  496. swapMap.forEach(el=>{
  497. cube.cubelets[el[0]] = swap[el[1]]
  498. })
  499. //cubeCallback( cubelet.cube.cubelets.slice())
  500. cubelet.cube.map()
  501. }
  502. }
  503. cubelet.yPrevious = cubelet.y
  504. }
  505. if( cubelet.y.modulo( 90 ).absolute() < threshold ){
  506. cubelet.y = 0
  507. cubelet.yPrevious = cubelet.y
  508. cubelet.isEngagedY = false
  509. }
  510. if( zRemaps ){
  511. while( zRemaps -- ){
  512. if( cubelet.z < cubelet.zPrevious ) cubelet.faces = [ cubelet.front, cubelet.right, cubelet.down, cubelet.left, cubelet.up, cubelet.back ]
  513. else cubelet.faces = [ cubelet.front, cubelet.left, cubelet.up, cubelet.right, cubelet.down, cubelet.back ]
  514. cubelet.map()
  515. if( cubeCallback !== undefined ){
  516. //debugger;
  517. let swapMap = Cube.swapMaps[cubeCallback];
  518. let swap = cubelet.cube.cubelets.slice();
  519. swapMap.forEach(el=>{
  520. cube.cubelets[el[0]] = swap[el[1]]
  521. })
  522. //cubeCallback( cubelet.cube.cubelets.slice())
  523. cubelet.cube.map()
  524. }
  525. }
  526. cubelet.zPrevious = cubelet.z
  527. }
  528. if( cubelet.z.modulo( 90 ).absolute() < threshold ){
  529. cubelet.z = 0
  530. cubelet.zPrevious = cubelet.z
  531. cubelet.isEngagedZ = false
  532. }
  533. // Phew! Now we can turn off the tweening flag.
  534. cubelet.isTweening = false
  535. },
  536. twist: function( twist, local ){
  537. let cube = this;
  538. var onTwistComplete
  539. let command = twist.command;
  540. console.log(cube.isTweening());
  541. if( twist instanceof Twist && !cube.isTweening() ){
  542. let degrees = twist.degrees
  543. if( Cube.verbosity >= 0.8 ){
  544. console.log(
  545. 'Executing a twist command to rotate the '+
  546. twist.group +' '+ twist.wise +' by',
  547. twist.degrees, 'degrees.'
  548. )
  549. }
  550. // X-axis rotations
  551. if( command === 'X' && !cube.isEngagedY() && !cube.isEngagedZ() ){
  552. onTwistComplete = function( swap ){
  553. cube.cubelets = [
  554. swap[ 6 ], swap[ 7 ], swap[ 8 ],
  555. swap[ 15 ], swap[ 16 ], swap[ 17 ],
  556. swap[ 24 ], swap[ 25 ], swap[ 26 ],
  557. swap[ 3 ], swap[ 4 ], swap[ 5 ],
  558. swap[ 12 ], swap[ 13 ], swap[ 14 ],
  559. swap[ 21 ], swap[ 22 ], swap[ 23 ],
  560. swap[ 0 ], swap[ 1 ], swap[ 2 ],
  561. swap[ 9 ], swap[ 10 ], swap[ 11 ],
  562. swap[ 18 ], swap[ 19 ], swap[ 20 ]
  563. ]
  564. }
  565. if( degrees === undefined ) degrees = cube.getDistanceToPeg( 'X' )
  566. cube.cubelets.forEach( function( cubelet, i ){
  567. if( i === cube.cubelets.length - 1 ) cubelet.rotate( 'X', degrees, onTwistComplete )
  568. else cubelet.rotate( 'X', degrees )
  569. })
  570. }
  571. else if( command === 'x' && !cube.isEngagedY() && !cube.isEngagedZ() ){
  572. onTwistComplete = function( swap ){
  573. cube.cubelets = [
  574. swap[ 18 ], swap[ 19 ], swap[ 20 ],
  575. swap[ 9 ], swap[ 10 ], swap[ 11 ],
  576. swap[ 0 ], swap[ 1 ], swap[ 2 ],
  577. swap[ 21 ], swap[ 22 ], swap[ 23 ],
  578. swap[ 12 ], swap[ 13 ], swap[ 14 ],
  579. swap[ 3 ], swap[ 4 ], swap[ 5 ],
  580. swap[ 24 ], swap[ 25 ], swap[ 26 ],
  581. swap[ 15 ], swap[ 16 ], swap[ 17 ],
  582. swap[ 6 ], swap[ 7 ], swap[ 8 ]
  583. ]
  584. }
  585. if( degrees === undefined ) degrees = cube.getDistanceToPeg( 'x' )
  586. cube.cubelets.forEach( function( cubelet, i ){
  587. if( i === cube.cubelets.length - 1 ) cubelet.rotate( 'x', degrees, onTwistComplete )
  588. else cubelet.rotate( 'x', degrees )
  589. })
  590. }
  591. else if( command === 'R' && !cube.right.isEngagedY() && !cube.right.isEngagedZ() ){
  592. onTwistComplete = function( swap ){
  593. cube.cubelets[ 2 ] = swap[ 8 ]
  594. cube.cubelets[ 11 ] = swap[ 5 ]
  595. cube.cubelets[ 20 ] = swap[ 2 ]
  596. cube.cubelets[ 5 ] = swap[ 17 ]
  597. cube.cubelets[ 23 ] = swap[ 11 ]
  598. cube.cubelets[ 8 ] = swap[ 26 ]
  599. cube.cubelets[ 17 ] = swap[ 23 ]
  600. cube.cubelets[ 26 ] = swap[ 20 ]
  601. }
  602. if( degrees === undefined ) degrees = cube.right.getDistanceToPeg( 'X' )
  603. cube.right.cubelets.forEach( function( cubelet, i ){
  604. if( i === cube.right.cubelets.length - 1 ) {
  605. cubelet.rotate( 'X', degrees, 'R', local )
  606. } else {
  607. cubelet.rotate( 'X', degrees, undefined, local )
  608. }
  609. })
  610. }
  611. else if( command === 'r' && !cube.right.isEngagedY() && !cube.right.isEngagedZ() ){
  612. onTwistComplete = function( swap ){
  613. cube.cubelets[ 2 ] = swap[ 20 ]
  614. cube.cubelets[ 11 ] = swap[ 23 ]
  615. cube.cubelets[ 20 ] = swap[ 26 ]
  616. cube.cubelets[ 5 ] = swap[ 11 ]
  617. cube.cubelets[ 23 ] = swap[ 17 ]
  618. cube.cubelets[ 8 ] = swap[ 2 ]
  619. cube.cubelets[ 17 ] = swap[ 5 ]
  620. cube.cubelets[ 26 ] = swap[ 8 ]
  621. }
  622. if( degrees === undefined ) degrees = cube.right.getDistanceToPeg( 'x' )
  623. cube.right.cubelets.forEach( function( cubelet, i ){
  624. if( i === cube.right.cubelets.length - 1 ) {
  625. cubelet.rotate( 'x', degrees, 'r', local )
  626. } else {
  627. cubelet.rotate( 'x', degrees, undefined, local)
  628. }
  629. })
  630. }
  631. else if( command === 'M' && !cube.middle.isEngagedY() && !cube.middle.isEngagedZ() ){
  632. onTwistComplete = function( swap ){
  633. cube.cubelets[ 1 ] = swap[ 19 ]
  634. cube.cubelets[ 10 ] = swap[ 22 ]
  635. cube.cubelets[ 19 ] = swap[ 25 ]
  636. cube.cubelets[ 4 ] = swap[ 10 ]
  637. cube.cubelets[ 22 ] = swap[ 16 ]
  638. cube.cubelets[ 7 ] = swap[ 1 ]
  639. cube.cubelets[ 16 ] = swap[ 4 ]
  640. cube.cubelets[ 25 ] = swap[ 7 ]
  641. }
  642. if( degrees === undefined ) degrees = cube.middle.getDistanceToPeg( 'x' )
  643. cube.middle.cubelets.forEach( function( cubelet, i ){
  644. if( i === cube.middle.cubelets.length - 1 ) cubelet.rotate( 'x', degrees, onTwistComplete )
  645. else cubelet.rotate( 'x', degrees )
  646. })
  647. }
  648. else if( command === 'm' && !cube.middle.isEngagedY() && !cube.middle.isEngagedZ() ){
  649. onTwistComplete = function( swap ){
  650. cube.cubelets[ 1 ] = swap[ 7 ]
  651. cube.cubelets[ 10 ] = swap[ 4 ]
  652. cube.cubelets[ 19 ] = swap[ 1 ]
  653. cube.cubelets[ 4 ] = swap[ 16 ]
  654. cube.cubelets[ 22 ] = swap[ 10 ]
  655. cube.cubelets[ 7 ] = swap[ 25 ]
  656. cube.cubelets[ 16 ] = swap[ 22 ]
  657. cube.cubelets[ 25 ] = swap[ 19 ]
  658. }
  659. if( degrees === undefined ) degrees = cube.middle.getDistanceToPeg( 'X' )
  660. cube.middle.cubelets.forEach( function( cubelet, i ){
  661. if( i === cube.middle.cubelets.length - 1 ) cubelet.rotate( 'X', degrees, onTwistComplete )
  662. else cubelet.rotate( 'X', degrees, onTwistComplete )
  663. })
  664. }
  665. else if( command === 'L' && !cube.left.isEngagedY() && !cube.left.isEngagedZ() ){
  666. onTwistComplete = function( swap ){
  667. cube.cubelets[ 18 ] = swap[ 24 ]
  668. cube.cubelets[ 9 ] = swap[ 21 ]
  669. cube.cubelets[ 0 ] = swap[ 18 ]
  670. cube.cubelets[ 21 ] = swap[ 15 ]
  671. cube.cubelets[ 3 ] = swap[ 9 ]
  672. cube.cubelets[ 24 ] = swap[ 6 ]
  673. cube.cubelets[ 15 ] = swap[ 3 ]
  674. cube.cubelets[ 6 ] = swap[ 0 ]
  675. }
  676. if( degrees === undefined ) degrees = cube.left.getDistanceToPeg( 'x' )
  677. cube.left.cubelets.forEach( function( cubelet, i ){
  678. if( i === cube.left.cubelets.length - 1 ) {
  679. cubelet.rotate( 'x', degrees, 'L', local )
  680. } else {
  681. cubelet.rotate( 'x', degrees, undefined, local )
  682. }
  683. })
  684. }
  685. else if( command === 'l' && !cube.left.isEngagedY() && !cube.left.isEngagedZ() ){
  686. onTwistComplete = function( swap ){
  687. cube.cubelets[ 18 ] = swap[ 0 ]
  688. cube.cubelets[ 9 ] = swap[ 3 ]
  689. cube.cubelets[ 0 ] = swap[ 6 ]
  690. cube.cubelets[ 21 ] = swap[ 9 ]
  691. cube.cubelets[ 3 ] = swap[ 15 ]
  692. cube.cubelets[ 24 ] = swap[ 18 ]
  693. cube.cubelets[ 15 ] = swap[ 21 ]
  694. cube.cubelets[ 6 ] = swap[ 24 ]
  695. }
  696. if( degrees === undefined ) degrees = cube.left.getDistanceToPeg( 'X' )
  697. cube.left.cubelets.forEach( function( cubelet, i ){
  698. if( i === cube.left.cubelets.length - 1 ) {
  699. cubelet.rotate( 'X', degrees, 'l', local )
  700. } else {
  701. cubelet.rotate( 'X', degrees, undefined, local )
  702. }
  703. })
  704. }
  705. // Y-axis rotations
  706. if( command === 'Y' && !cube.isEngagedX() && !cube.isEngagedZ() ){
  707. onTwistComplete = function( swap ){
  708. cube.cubelets = [
  709. swap[ 2 ], swap[ 11 ], swap[ 20 ],
  710. swap[ 5 ], swap[ 14 ], swap[ 23 ],
  711. swap[ 8 ], swap[ 17 ], swap[ 26 ],
  712. swap[ 1 ], swap[ 10 ], swap[ 19 ],
  713. swap[ 4 ], swap[ 13 ], swap[ 22 ],
  714. swap[ 7 ], swap[ 16 ], swap[ 25 ],
  715. swap[ 0 ], swap[ 9 ], swap[ 18 ],
  716. swap[ 3 ], swap[ 12 ], swap[ 21 ],
  717. swap[ 6 ], swap[ 15 ], swap[ 24 ]
  718. ]
  719. }
  720. if( degrees === undefined ) degrees = cube.getDistanceToPeg( 'Y' )
  721. cube.cubelets.forEach( function( cubelet, i ){
  722. if( i === cube.cubelets.length - 1 ) cubelet.rotate( 'Y', degrees, onTwistComplete )
  723. else cubelet.rotate( 'Y', degrees )
  724. })
  725. }
  726. else if( command === 'y' && !cube.isEngagedX() && !cube.isEngagedZ() ){
  727. onTwistComplete = function( swap ){
  728. cube.cubelets = [
  729. swap[ 18 ], swap[ 9 ], swap[ 0 ],
  730. swap[ 21 ], swap[ 12 ], swap[ 3 ],
  731. swap[ 24 ], swap[ 15 ], swap[ 6 ],
  732. swap[ 19 ], swap[ 10 ], swap[ 1 ],
  733. swap[ 22 ], swap[ 13 ], swap[ 4 ],
  734. swap[ 25 ], swap[ 16 ], swap[ 7 ],
  735. swap[ 20 ], swap[ 11 ], swap[ 2 ],
  736. swap[ 23 ], swap[ 14 ], swap[ 5 ],
  737. swap[ 26 ], swap[ 17 ], swap[ 8 ]
  738. ]
  739. }
  740. if( degrees === undefined ) degrees = cube.getDistanceToPeg( 'y' )
  741. cube.cubelets.forEach( function( cubelet, i ){
  742. if( i === cube.cubelets.length - 1 ) cubelet.rotate( 'y', degrees, onTwistComplete )
  743. else cubelet.rotate( 'y', degrees )
  744. })
  745. }
  746. else if( command === 'U' && !cube.up.isEngagedX() && !cube.up.isEngagedZ() ){
  747. onTwistComplete = function( swap ){
  748. cube.cubelets[ 18 ] = swap[ 0 ]
  749. cube.cubelets[ 19 ] = swap[ 9 ]
  750. cube.cubelets[ 20 ] = swap[ 18 ]
  751. cube.cubelets[ 9 ] = swap[ 1 ]
  752. cube.cubelets[ 11 ] = swap[ 19 ]
  753. cube.cubelets[ 0 ] = swap[ 2 ]
  754. cube.cubelets[ 1 ] = swap[ 11 ]
  755. cube.cubelets[ 2 ] = swap[ 20 ]
  756. }
  757. if( degrees === undefined ) degrees = cube.up.getDistanceToPeg( 'Y' )
  758. cube.up.cubelets.forEach( function( cubelet, i ){
  759. if( i === cube.up.cubelets.length - 1 ) {
  760. cubelet.rotate( 'Y', degrees, 'U', local )
  761. } else {
  762. cubelet.rotate( 'Y', degrees, undefined, local )
  763. }
  764. })
  765. }
  766. else if( command === 'u' && !cube.up.isEngagedX() & !cube.up.isEngagedZ() ){
  767. onTwistComplete = function( swap ){
  768. cube.cubelets[ 18 ] = swap[ 20 ]
  769. cube.cubelets[ 19 ] = swap[ 11 ]
  770. cube.cubelets[ 20 ] = swap[ 2 ]
  771. cube.cubelets[ 9 ] = swap[ 19 ]
  772. cube.cubelets[ 11 ] = swap[ 1 ]
  773. cube.cubelets[ 0 ] = swap[ 18 ]
  774. cube.cubelets[ 1 ] = swap[ 9 ]
  775. cube.cubelets[ 2 ] = swap[ 0 ]
  776. }
  777. if( degrees === undefined ) degrees = cube.up.getDistanceToPeg( 'y' )
  778. cube.up.cubelets.forEach( function( cubelet, i ){
  779. if( i === cube.up.cubelets.length - 1 ) {
  780. cubelet.rotate( 'y', degrees, 'u', local )
  781. } else {
  782. cubelet.rotate( 'y', degrees, undefined, local )
  783. }
  784. })
  785. }
  786. else if( command === 'E' && !cube.equator.isEngagedX() && !cube.equator.isEngagedZ() ){
  787. onTwistComplete = function( swap ){
  788. cube.cubelets[ 21 ] = swap[ 23 ]
  789. cube.cubelets[ 22 ] = swap[ 14 ]
  790. cube.cubelets[ 23 ] = swap[ 5 ]
  791. cube.cubelets[ 12 ] = swap[ 22 ]
  792. cube.cubelets[ 14 ] = swap[ 4 ]
  793. cube.cubelets[ 3 ] = swap[ 21 ]
  794. cube.cubelets[ 4 ] = swap[ 12 ]
  795. cube.cubelets[ 5 ] = swap[ 3 ]
  796. }
  797. if( degrees === undefined ) degrees = cube.equator.getDistanceToPeg( 'y' )
  798. cube.equator.cubelets.forEach( function( cubelet, i ){
  799. if( i === cube.equator.cubelets.length - 1 ) cubelet.rotate( 'y', degrees, onTwistComplete )
  800. else cubelet.rotate( 'y', degrees )
  801. })
  802. }
  803. else if( command === 'e' && !cube.equator.isEngagedX() && !cube.equator.isEngagedZ() ){
  804. onTwistComplete = function( swap ){
  805. cube.cubelets[ 21 ] = swap[ 3 ]
  806. cube.cubelets[ 22 ] = swap[ 12 ]
  807. cube.cubelets[ 23 ] = swap[ 21 ]
  808. cube.cubelets[ 12 ] = swap[ 4 ]
  809. cube.cubelets[ 14 ] = swap[ 22 ]
  810. cube.cubelets[ 3 ] = swap[ 5 ]
  811. cube.cubelets[ 4 ] = swap[ 14 ]
  812. cube.cubelets[ 5 ] = swap[ 23 ]
  813. }
  814. if( degrees === undefined ) degrees = cube.equator.getDistanceToPeg( 'Y' )
  815. cube.equator.cubelets.forEach( function( cubelet, i ){
  816. if( i === cube.equator.cubelets.length - 1 ) cubelet.rotate( 'Y', degrees, onTwistComplete )
  817. else cubelet.rotate( 'Y', degrees )
  818. })
  819. }
  820. else if( command === 'D' && !cube.down.isEngagedX() && !cube.down.isEngagedZ() ){
  821. onTwistComplete = function( swap ){
  822. cube.cubelets[ 6 ] = swap[ 24 ]
  823. cube.cubelets[ 7 ] = swap[ 15 ]
  824. cube.cubelets[ 8 ] = swap[ 6 ]
  825. cube.cubelets[ 15 ] = swap[ 25 ]
  826. cube.cubelets[ 17 ] = swap[ 7 ]
  827. cube.cubelets[ 24 ] = swap[ 26 ]
  828. cube.cubelets[ 25 ] = swap[ 17 ]
  829. cube.cubelets[ 26 ] = swap[ 8 ]
  830. }
  831. if( degrees === undefined ) degrees = cube.down.getDistanceToPeg( 'y' )
  832. cube.down.cubelets.forEach( function( cubelet, i ){
  833. if( i === cube.down.cubelets.length - 1 ) {
  834. cubelet.rotate( 'y', degrees, 'D', local )
  835. } else {
  836. cubelet.rotate( 'y', degrees, undefined, local )
  837. }
  838. })
  839. }
  840. else if( command === 'd' && !cube.down.isEngagedX() && !cube.down.isEngagedZ() ){
  841. onTwistComplete = function( swap ){
  842. cube.cubelets[ 6 ] = swap[ 8 ]
  843. cube.cubelets[ 7 ] = swap[ 17 ]
  844. cube.cubelets[ 8 ] = swap[ 26 ]
  845. cube.cubelets[ 15 ] = swap[ 7 ]
  846. cube.cubelets[ 17 ] = swap[ 25 ]
  847. cube.cubelets[ 24 ] = swap[ 6 ]
  848. cube.cubelets[ 25 ] = swap[ 15 ]
  849. cube.cubelets[ 26 ] = swap[ 24 ]
  850. }
  851. if( degrees === undefined ) degrees = cube.down.getDistanceToPeg( 'Y' )
  852. cube.down.cubelets.forEach( function( cubelet, i ){
  853. if( i === cube.down.cubelets.length - 1 ) {
  854. cubelet.rotate( 'Y', degrees, 'd', local )
  855. } else {
  856. cubelet.rotate( 'Y', degrees, undefined, local )
  857. }
  858. })
  859. }
  860. // Z-axis rotations
  861. if( command === 'Z' && !cube.isEngagedX() && !cube.isEngagedY() ){
  862. onTwistComplete = function( swap ){
  863. cube.cubelets = [
  864. swap[ 6 ], swap[ 3 ], swap[ 0 ],
  865. swap[ 7 ], swap[ 4 ], swap[ 1 ],
  866. swap[ 8 ], swap[ 5 ], swap[ 2 ],
  867. swap[ 15 ], swap[ 12 ], swap[ 9 ],
  868. swap[ 16 ], swap[ 13 ], swap[ 10 ],
  869. swap[ 17 ], swap[ 14 ], swap[ 11 ],
  870. swap[ 24 ], swap[ 21 ], swap[ 18 ],
  871. swap[ 25 ], swap[ 22 ], swap[ 19 ],
  872. swap[ 26 ], swap[ 23 ], swap[ 20 ]
  873. ]
  874. }
  875. if( degrees === undefined ) degrees = cube.getDistanceToPeg( 'Z' )
  876. cube.cubelets.forEach( function( cubelet, i ){
  877. if( i === cube.cubelets.length - 1 ) cubelet.rotate( 'Z', degrees, onTwistComplete )
  878. else cubelet.rotate( 'Z', degrees )
  879. })
  880. }
  881. else if( command === 'z' && !cube.isEngagedX() && !cube.isEngagedY() ){
  882. onTwistComplete = function( swap ){
  883. cube.cubelets = [
  884. swap[ 2 ], swap[ 5 ], swap[ 8 ],
  885. swap[ 1 ], swap[ 4 ], swap[ 7 ],
  886. swap[ 0 ], swap[ 3 ], swap[ 6 ],
  887. swap[ 11 ], swap[ 14 ], swap[ 17 ],
  888. swap[ 10 ], swap[ 13 ], swap[ 16 ],
  889. swap[ 9 ], swap[ 12 ], swap[ 15 ],
  890. swap[ 20 ], swap[ 23 ], swap[ 26 ],
  891. swap[ 19 ], swap[ 22 ], swap[ 25 ],
  892. swap[ 18 ], swap[ 21 ], swap[ 24 ]
  893. ]
  894. }
  895. if( degrees === undefined ) degrees = cube.getDistanceToPeg( 'z' )
  896. cube.cubelets.forEach( function( cubelet, i ){
  897. if( i === cube.cubelets.length - 1 ) cubelet.rotate( 'z', degrees, onTwistComplete )
  898. else cubelet.rotate( 'z', degrees )
  899. })
  900. }
  901. else if( command === 'F' && !cube.front.isEngagedX() && !cube.front.isEngagedY() ){
  902. onTwistComplete = function( swap ){
  903. cube.cubelets[ 0 ] = swap[ 6 ]
  904. cube.cubelets[ 1 ] = swap[ 3 ]
  905. cube.cubelets[ 2 ] = swap[ 0 ]
  906. cube.cubelets[ 3 ] = swap[ 7 ]
  907. cube.cubelets[ 5 ] = swap[ 1 ]
  908. cube.cubelets[ 6 ] = swap[ 8 ]
  909. cube.cubelets[ 7 ] = swap[ 5 ]
  910. cube.cubelets[ 8 ] = swap[ 2 ]
  911. }
  912. if( degrees === undefined ) degrees = cube.front.getDistanceToPeg( 'Z' )
  913. cube.front.cubelets.forEach( function( cubelet, i ){
  914. if( i === cube.front.cubelets.length - 1 )
  915. {
  916. cubelet.rotate( 'Z', degrees, 'F', local)
  917. }
  918. else {
  919. cubelet.rotate( 'Z', degrees, undefined, local )
  920. }
  921. })
  922. }
  923. else if( command === 'f' && !cube.front.isEngagedX() && !cube.front.isEngagedY() ){
  924. onTwistComplete = function( swap ){
  925. cube.cubelets[ 0 ] = swap[ 2 ]
  926. cube.cubelets[ 1 ] = swap[ 5 ]
  927. cube.cubelets[ 2 ] = swap[ 8 ]
  928. cube.cubelets[ 3 ] = swap[ 1 ]
  929. cube.cubelets[ 5 ] = swap[ 7 ]
  930. cube.cubelets[ 6 ] = swap[ 0 ]
  931. cube.cubelets[ 7 ] = swap[ 3 ]
  932. cube.cubelets[ 8 ] = swap[ 6 ]
  933. }
  934. if( degrees === undefined ) degrees = cube.front.getDistanceToPeg( 'z' )
  935. cube.front.cubelets.forEach( function( cubelet, i ){
  936. if( i === cube.front.cubelets.length - 1 )
  937. {
  938. cubelet.rotate( 'z', degrees, 'f', local) //onTwistComplete ) //
  939. }
  940. else {
  941. cubelet.rotate( 'z', degrees, undefined, local )
  942. }
  943. })
  944. }
  945. else if( command === 'S' && !cube.standing.isEngagedX() && !cube.standing.isEngagedY() ){
  946. onTwistComplete = function( swap ){
  947. cube.cubelets[ 9 ] = swap[ 15 ]
  948. cube.cubelets[ 10 ] = swap[ 12 ]
  949. cube.cubelets[ 11 ] = swap[ 9 ]
  950. cube.cubelets[ 12 ] = swap[ 16 ]
  951. cube.cubelets[ 14 ] = swap[ 10 ]
  952. cube.cubelets[ 15 ] = swap[ 17 ]
  953. cube.cubelets[ 16 ] = swap[ 14 ]
  954. cube.cubelets[ 17 ] = swap[ 11 ]
  955. }
  956. if( degrees === undefined ) degrees = cube.standing.getDistanceToPeg( 'Z' )
  957. cube.standing.cubelets.forEach( function( cubelet, i ){
  958. if( i === cube.standing.cubelets.length - 1 ) cubelet.rotate( 'Z', degrees, onTwistComplete )
  959. else cubelet.rotate( 'Z', degrees )
  960. })
  961. }
  962. else if( command === 's' && !cube.standing.isEngagedX() && !cube.standing.isEngagedY() ){
  963. onTwistComplete = function( swap ){
  964. cube.cubelets[ 9 ] = swap[ 11 ]
  965. cube.cubelets[ 10 ] = swap[ 14 ]
  966. cube.cubelets[ 11 ] = swap[ 17 ]
  967. cube.cubelets[ 12 ] = swap[ 10 ]
  968. cube.cubelets[ 14 ] = swap[ 16 ]
  969. cube.cubelets[ 15 ] = swap[ 9 ]
  970. cube.cubelets[ 16 ] = swap[ 12 ]
  971. cube.cubelets[ 17 ] = swap[ 15 ]
  972. }
  973. if( degrees === undefined ) degrees = cube.standing.getDistanceToPeg( 'z' )
  974. cube.standing.cubelets.forEach( function( cubelet, i ){
  975. if( i === cube.standing.cubelets.length - 1 ) cubelet.rotate( 'z', degrees, onTwistComplete )
  976. else cubelet.rotate( 'z', degrees )
  977. })
  978. }
  979. else if( command === 'B' && !cube.back.isEngagedX() && !cube.back.isEngagedY() ){
  980. onTwistComplete = function( swap ){
  981. cube.cubelets[ 18 ] = swap[ 20 ]
  982. cube.cubelets[ 19 ] = swap[ 23 ]
  983. cube.cubelets[ 20 ] = swap[ 26 ]
  984. cube.cubelets[ 21 ] = swap[ 19 ]
  985. cube.cubelets[ 23 ] = swap[ 25 ]
  986. cube.cubelets[ 24 ] = swap[ 18 ]
  987. cube.cubelets[ 25 ] = swap[ 21 ]
  988. cube.cubelets[ 26 ] = swap[ 24 ]
  989. }
  990. if( degrees === undefined ) degrees = cube.back.getDistanceToPeg( 'z' )
  991. cube.back.cubelets.forEach( function( cubelet, i ){
  992. if( i === cube.back.cubelets.length - 1 ) {
  993. cubelet.rotate( 'z', degrees, 'B', local )
  994. }
  995. else {
  996. cubelet.rotate( 'z', degrees, undefined, local )
  997. }
  998. })
  999. }
  1000. else if( command === 'b' && !cube.back.isEngagedX() && !cube.back.isEngagedY() ){
  1001. onTwistComplete = function( swap ){
  1002. cube.cubelets[ 18 ] = swap[ 24 ]
  1003. cube.cubelets[ 19 ] = swap[ 21 ]
  1004. cube.cubelets[ 20 ] = swap[ 18 ]
  1005. cube.cubelets[ 21 ] = swap[ 25 ]
  1006. cube.cubelets[ 23 ] = swap[ 19 ]
  1007. cube.cubelets[ 24 ] = swap[ 26 ]
  1008. cube.cubelets[ 25 ] = swap[ 23 ]
  1009. cube.cubelets[ 26 ] = swap[ 20 ]
  1010. }
  1011. if( degrees === undefined ) degrees = cube.back.getDistanceToPeg( 'Z' )
  1012. cube.back.cubelets.forEach( function( cubelet, i ){
  1013. if( i === cube.back.cubelets.length - 1 ) {
  1014. cubelet.rotate( 'Z', degrees, 'b', local )
  1015. } else {
  1016. cubelet.rotate( 'Z', degrees, undefined, local )
  1017. }
  1018. })
  1019. }
  1020. //@@ COME BACK AND BETTER DOCUMENT WHAT'S HAPPENING HERE!
  1021. if( onTwistComplete instanceof Function ){
  1022. twist.completed = Date.now()
  1023. // $( '#twist' ).text( command ).fadeIn( 50, function(){
  1024. // var that = this
  1025. // setTimeout( function(){
  1026. // $( that ).fadeOut( 500 )
  1027. // }, 50 )
  1028. // })
  1029. }
  1030. else console.log( '! Received a twist command ('+ command +'), however some of the required Cubelets are currently engaged.' )
  1031. }
  1032. else if( Cube.verbosity >= 0.1 ) console.log( '! Received an invalid twist command: '+ command +'.' )
  1033. },
  1034. showFaceLabels: function(){
  1035. $( '.faceLabel' ).show()
  1036. this.showingFaceLabels = true
  1037. },
  1038. hideFaceLabels: function(){
  1039. $( '.faceLabel' ).hide()
  1040. this.showingFaceLabels = false
  1041. },
  1042. /////////////////
  1043. // //
  1044. // Presets //
  1045. // //
  1046. /////////////////
  1047. presetBling: function(){
  1048. var cube = this
  1049. this.threeObject.position.y = -2000
  1050. new TWEEN.Tween( this.threeObject.position )
  1051. .to({
  1052. y: 0
  1053. }, SECOND * 2 )
  1054. .easing( TWEEN.Easing.Quartic.Out )
  1055. .start()
  1056. this.threeObject.rotation.set(
  1057. ( 180 ).degreesToRadians(),
  1058. ( 180 ).degreesToRadians(),
  1059. ( 20 ).degreesToRadians()
  1060. )
  1061. new TWEEN.Tween( this.threeObject.rotation )
  1062. .to({
  1063. x: ( 25 ).degreesToRadians(),
  1064. y: ( -30 ).degreesToRadians(),
  1065. z: 0
  1066. }, SECOND * 3 )
  1067. .easing( TWEEN.Easing.Quartic.Out )
  1068. .onComplete( function(){
  1069. cube.isReady = true
  1070. updateControls()
  1071. })
  1072. .start()
  1073. this.isReady = false
  1074. // And we want each Cubelet to begin in an exploded position and tween inward.
  1075. this.cubelets.forEach( function( cubelet ){
  1076. // We want to start with each Cubelet exploded out away from the Cube center.
  1077. // We're reusing the x, y, and z we created far up above to handle Cubelet positions.
  1078. var distance = 1000
  1079. cubelet.anchor.position.set(
  1080. cubelet.addressX * distance,
  1081. cubelet.addressY * distance,
  1082. cubelet.addressZ * distance
  1083. )
  1084. // Let's vary the arrival time of flying Cubelets based on their type.
  1085. // An nice extra little but of sauce!
  1086. var delay
  1087. if( cubelet.type === 'core' ) delay = ( 0 ).random( 200 )
  1088. if( cubelet.type === 'center' ) delay = ( 200 ).random( 400 )
  1089. if( cubelet.type === 'edge' ) delay = ( 400 ).random( 800 )
  1090. if( cubelet.type === 'corner' ) delay = ( 800 ).random( 1000 )
  1091. new TWEEN.Tween( cubelet.anchor.position )
  1092. .to({
  1093. x: 0,
  1094. y: 0,
  1095. z: 0
  1096. }, SECOND )
  1097. .delay( delay )
  1098. .easing( TWEEN.Easing.Quartic.Out )
  1099. .onComplete( function(){
  1100. cubelet.isTweening = false
  1101. })
  1102. .start()
  1103. cubelet.isTweening = true
  1104. })
  1105. updateControls( this )
  1106. },
  1107. presetNormal: function(){
  1108. $( 'body' ).css( 'background-color', '#000' )
  1109. $( 'body' ).addClass( 'graydient' )
  1110. setTimeout( function(){ $( '.cubelet' ).removeClass( 'purty' )}, 1 )
  1111. this.show()
  1112. this.showIntroverts()
  1113. this.showPlastics()
  1114. this.showStickers()
  1115. this.hideTexts()
  1116. this.hideWireframes()
  1117. this.hideIds()
  1118. this.setOpacity()
  1119. this.setRadius()
  1120. updateControls( this )
  1121. },
  1122. presetText: function( virgin ){
  1123. $( 'body' ).css( 'background-color', '#F00' )
  1124. $( 'body' ).removeClass( 'graydient' )
  1125. setTimeout( function(){ $( '.cubelet' ).removeClass( 'purty' )}, 1 )
  1126. var cube = this
  1127. setTimeout( function(){
  1128. cube.show()
  1129. cube.hidePlastics()
  1130. cube.hideStickers()
  1131. cube.hideIds()
  1132. cube.hideIntroverts()
  1133. cube.showTexts()
  1134. cube.hideWireframes()
  1135. cube.setOpacity()
  1136. updateControls( cube )
  1137. }, 1 )
  1138. },
  1139. presetLogo: function(){
  1140. var cube = this
  1141. this.isReady = false
  1142. this.presetText()
  1143. new TWEEN.Tween( cube.threeObject.rotation )
  1144. .to({
  1145. x: 0,
  1146. y: ( -45 ).degreesToRadians(),
  1147. z: 0
  1148. }, SECOND * 2 )
  1149. .easing( TWEEN.Easing.Quartic.Out )
  1150. .onComplete( function(){
  1151. updateControls( cube )
  1152. cube.isReady = true
  1153. cube.twistQueue.add( 'E20d17' )
  1154. })
  1155. .start()
  1156. },
  1157. presetTextAnimate: function(){// Specifically for Monica!
  1158. var
  1159. delay = 1,//SECOND * 2,
  1160. twistDurationScaled = Math.max([ (20+90).absolute().scale( 0, 90, 0, cube.twistDuration ), 250 ])
  1161. _this = this
  1162. cube.shuffleMethod = cube.ALL_SLICES
  1163. presetHeroic( virgin )
  1164. setTimeout( function(){
  1165. _this.twist( 'E', 20 )
  1166. }, delay )
  1167. setTimeout( function(){
  1168. _this.twist( 'd', 20 )
  1169. //$('body').css('background-color', '#000')
  1170. }, delay + SECOND )
  1171. setTimeout( function(){
  1172. _this.twist( 'D', 20 + 90 )
  1173. _this.isRotating = true
  1174. }, delay + SECOND * 2 )
  1175. setTimeout( function(){
  1176. _this.twist( 'e', 20 + 90 )
  1177. _this.isShuffling = true
  1178. }, delay + SECOND * 2 + twistDurationScaled + 50 )
  1179. updateControls( this )
  1180. },
  1181. presetWireframe: function( included, excluded ){
  1182. setTimeout( function(){ $( '.cubelet' ).removeClass( 'purty' )}, 1 )
  1183. this.showIntroverts()
  1184. if( included === undefined ) included = new Group( this.cubelets )
  1185. if( excluded === undefined ){
  1186. excluded = new Group( this.cubelets )
  1187. excluded.remove( included )
  1188. }
  1189. this.show()
  1190. excluded.showPlastics()
  1191. excluded.showStickers()
  1192. excluded.hideWireframes()
  1193. included.hidePlastics()
  1194. included.hideStickers()
  1195. included.showWireframes()
  1196. updateControls( this )
  1197. },
  1198. presetHighlight: function( included, excluded ){
  1199. if( erno.state === 'setup' ) this.presetBling()
  1200. if( included === undefined ) included = new Group( this.cubelets )
  1201. if( excluded === undefined ){
  1202. excluded = new Group( this.cubelets )
  1203. excluded.remove( included )
  1204. }
  1205. excluded.setOpacity( 0.1 )
  1206. included.setOpacity()
  1207. updateControls( this )
  1208. },
  1209. presetHighlightCore: function(){
  1210. this.presetHighlight( this.core )
  1211. updateControls( this )
  1212. },
  1213. presetHighlightCenters: function(){
  1214. this.presetHighlight( this.centers )
  1215. updateControls( this )
  1216. },
  1217. presetHighlightEdges: function(){
  1218. this.presetHighlight( this.edges )
  1219. updateControls( this )
  1220. },
  1221. presetHighlightCorners: function(){
  1222. this.presetHighlight( this.corners )
  1223. updateControls( this )
  1224. },
  1225. presetHighlightWhite: function(){
  1226. this.presetHighlight( this.hasColor( WHITE ))
  1227. updateControls( this )
  1228. },
  1229. presetPurty: function(){
  1230. this.showIntroverts()
  1231. setTimeout( function(){
  1232. $( '.cubelet' ).addClass( 'purty' )
  1233. }, 1 )
  1234. this.threeObject.rotation.set(
  1235. ( 35.3).degreesToRadians(),
  1236. (-45 ).degreesToRadians(),
  1237. 0
  1238. )
  1239. updateControls( this )
  1240. },
  1241. presetDemo: function(){
  1242. var
  1243. cube = this,
  1244. loops = 0,
  1245. captions = $( '#captions' )
  1246. this.taskQueue.add(
  1247. // Rotation and twist demo.
  1248. function(){
  1249. cube.rotationDeltaX = -0.1
  1250. cube.rotationDeltaY = 0.15
  1251. cube.isRotating = true
  1252. cube.presetNormal()
  1253. cube.taskQueue.isReady = false
  1254. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1255. },
  1256. function(){
  1257. cube.twistQueue.add( 'rdRD'.multiply( 6 ))
  1258. },
  1259. // Opacity demo.
  1260. function(){
  1261. cube.back.setOpacity( 0.2 )
  1262. cube.taskQueue.isReady = false
  1263. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1264. },
  1265. function(){
  1266. cube.standing.setOpacity( 0.2 )
  1267. cube.taskQueue.isReady = false
  1268. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1269. },
  1270. function(){
  1271. cube.twistQueue.add( 'rdRD'.multiply( 3 ))
  1272. },
  1273. function(){
  1274. cube.showFaceLabels()
  1275. cube.twistQueue.add( 'rdRD'.multiply( 3 ))
  1276. },
  1277. function(){
  1278. cube.hideFaceLabels()
  1279. cube.standing.setOpacity( 1 )
  1280. cube.taskQueue.isReady = false
  1281. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1282. },
  1283. function(){
  1284. cube.back.setOpacity( 1 )
  1285. cube.taskQueue.isReady = false
  1286. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1287. },
  1288. // Radial demo.
  1289. function(){
  1290. cube.down.setRadius( 90 )
  1291. cube.taskQueue.isReady = false
  1292. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1293. },
  1294. function(){
  1295. cube.equator.setRadius( 90 )
  1296. cube.taskQueue.isReady = false
  1297. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1298. },
  1299. function(){
  1300. cube.up.setRadius( 90 )
  1301. cube.taskQueue.isReady = false
  1302. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1303. },
  1304. function(){
  1305. cube.twistQueue.add( 'rdRD'.multiply( 2 ))
  1306. },
  1307. function(){
  1308. cube.back.setRadius()
  1309. cube.taskQueue.isReady = false
  1310. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1311. },
  1312. function(){
  1313. cube.standing.setRadius()
  1314. cube.taskQueue.isReady = false
  1315. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1316. },
  1317. function(){
  1318. cube.twistQueue.add( 'rdRD'.multiply( 2 ))
  1319. },
  1320. function(){
  1321. var
  1322. excluded = new Group( cube.cubelets ),
  1323. included = cube.hasColors( RED, YELLOW, BLUE )
  1324. excluded.remove( included )
  1325. excluded.setRadius()
  1326. excluded.setOpacity( 0.5 )
  1327. included.setRadius( 120 )
  1328. included.setOpacity( 1 )
  1329. cube.back.setRadius()
  1330. cube.showIds()
  1331. cube.taskQueue.isReady = false
  1332. setTimeout( function(){ cube.taskQueue.isReady = true }, (6).seconds() )
  1333. },
  1334. function(){
  1335. cube.twistQueue.add( 'rdRD'.multiply( 2 ))
  1336. },
  1337. function(){
  1338. cube.taskQueue.isReady = false
  1339. setTimeout( function(){ cube.taskQueue.isReady = true }, (6).seconds() )
  1340. },
  1341. function(){
  1342. cube.setRadius()
  1343. cube.taskQueue.isReady = false
  1344. setTimeout( function(){ cube.taskQueue.isReady = true }, (3).seconds() )
  1345. },
  1346. // A cube is made up of cubelets
  1347. // and these can be a core or centers, edges, and corners.
  1348. function(){
  1349. captions.text( 'Core' ).fadeIn()
  1350. cube.presetHighlightCore()
  1351. cube.taskQueue.isReady = false
  1352. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1353. },
  1354. function(){
  1355. cube.showIds()
  1356. cube.taskQueue.isReady = false
  1357. setTimeout( function(){ cube.taskQueue.isReady = true }, (2).seconds() )
  1358. },
  1359. function(){
  1360. cube.twistQueue.add( 'rdRD'.multiply( 2 ))
  1361. },
  1362. function(){
  1363. captions.text( 'Centers' )
  1364. cube.presetHighlightCenters()
  1365. cube.twistQueue.add( 'rdRD'.multiply( 4 ))
  1366. },
  1367. function(){
  1368. captions.text( 'Edges' )
  1369. cube.presetHighlightEdges()
  1370. cube.twistQueue.add( 'rdRD'.multiply( 3 ))
  1371. },
  1372. function(){
  1373. captions.text( 'Corners' )
  1374. cube.presetHighlightCorners()
  1375. cube.twistQueue.add( 'rdRD'.multiply( 3 ))
  1376. },
  1377. function(){
  1378. captions.fadeOut()
  1379. cube.taskQueue.isReady = false
  1380. setTimeout( function(){ cube.taskQueue.isReady = true }, (2).seconds() )
  1381. },
  1382. // Wireframe demo.
  1383. function(){
  1384. cube.left.setOpacity( 0 )
  1385. cube.taskQueue.isReady = false
  1386. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1387. },
  1388. function(){
  1389. cube.left
  1390. .hidePlastics()
  1391. .hideStickers()
  1392. .showWireframes()
  1393. .showIds()
  1394. .setOpacity( 1 )
  1395. cube.taskQueue.isReady = false
  1396. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1397. },
  1398. function(){
  1399. cube.middle.setOpacity( 0 )
  1400. cube.taskQueue.isReady = false
  1401. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1402. },
  1403. function(){
  1404. cube.middle
  1405. .hidePlastics()
  1406. .hideStickers()
  1407. .showWireframes()
  1408. .showIds()
  1409. .setOpacity( 1 )
  1410. cube.taskQueue.isReady = false
  1411. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1412. },
  1413. function(){
  1414. cube.right.setOpacity( 0 )
  1415. cube.taskQueue.isReady = false
  1416. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1417. },
  1418. function(){
  1419. cube.right
  1420. .hidePlastics()
  1421. .hideStickers()
  1422. .showWireframes()
  1423. .showIds()
  1424. .setOpacity( 1 )
  1425. cube.taskQueue.isReady = false
  1426. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1427. },
  1428. function(){
  1429. cube.twistQueue.add( 'rdRD'.multiply( 3 ))
  1430. },
  1431. // Text demo.
  1432. function(){
  1433. cube.left.setOpacity( 0 )
  1434. cube.taskQueue.isReady = false
  1435. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1436. },
  1437. function(){
  1438. cube.left
  1439. .hidePlastics()
  1440. .hideStickers()
  1441. .hideWireframes()
  1442. .hideIds()
  1443. .showTexts()
  1444. .setOpacity( 1 )
  1445. cube.taskQueue.isReady = false
  1446. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1447. },
  1448. function(){
  1449. cube.middle.setOpacity( 0 )
  1450. cube.taskQueue.isReady = false
  1451. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1452. },
  1453. function(){
  1454. cube.middle
  1455. .hidePlastics()
  1456. .hideStickers()
  1457. .hideWireframes()
  1458. .hideIds()
  1459. .showTexts()
  1460. .setOpacity( 1 )
  1461. cube.taskQueue.isReady = false
  1462. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1463. },
  1464. function(){
  1465. cube.right.setOpacity( 0 )
  1466. cube.taskQueue.isReady = false
  1467. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1468. },
  1469. function(){
  1470. cube.right
  1471. .hidePlastics()
  1472. .hideStickers()
  1473. .hideWireframes()
  1474. .hideIds()
  1475. .showTexts()
  1476. .setOpacity( 1 )
  1477. cube.taskQueue.isReady = false
  1478. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1479. },
  1480. function(){
  1481. cube.twistQueue.add( 'rdRD'.multiply( 3 ))
  1482. },
  1483. function(){
  1484. cube.taskQueue.isReady = false
  1485. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND * 8 )
  1486. },
  1487. // Return to Normal mode
  1488. function(){
  1489. cube.left.setOpacity( 0 )
  1490. cube.taskQueue.isReady = false
  1491. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1492. },
  1493. function(){
  1494. cube.left
  1495. .showPlastics()
  1496. .showStickers()
  1497. .hideTexts()
  1498. .setOpacity( 1 )
  1499. cube.taskQueue.isReady = false
  1500. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1501. },
  1502. function(){
  1503. cube.middle.setOpacity( 0 )
  1504. cube.taskQueue.isReady = false
  1505. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1506. },
  1507. function(){
  1508. cube.middle
  1509. .showPlastics()
  1510. .showStickers()
  1511. .hideTexts()
  1512. .setOpacity( 1 )
  1513. cube.taskQueue.isReady = false
  1514. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1515. },
  1516. function(){
  1517. cube.right.setOpacity( 0 )
  1518. cube.taskQueue.isReady = false
  1519. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1520. },
  1521. function(){
  1522. cube.right
  1523. .showPlastics()
  1524. .showStickers()
  1525. .hideTexts()
  1526. .setOpacity( 1 )
  1527. cube.taskQueue.isReady = false
  1528. setTimeout( function(){ cube.taskQueue.isReady = true }, SECOND )
  1529. },
  1530. // Loop it.
  1531. function(){
  1532. loops ++
  1533. console.log( 'The cuber demo has completed', loops, 'loops.' )
  1534. cube.twistQueue.history = []// Lets just kill it outright.
  1535. }
  1536. )
  1537. this.taskQueue.isLooping = true
  1538. updateControls( this )
  1539. },
  1540. presetDemoStop: function(){
  1541. this.taskQueue.isLooping = false
  1542. this.twistQueue.empty()
  1543. this.taskQueue.empty()
  1544. this.isRotating = false
  1545. updateControls( this )
  1546. },
  1547. // Shuffle methods.
  1548. PRESERVE_LOGO: 'RrLlUuDdSsBb', // Preserve the logo position and rotation.
  1549. ALL_SLICES: 'RrMmLlUuEeDdFfSsBb', // Allow all slices to rotate.
  1550. EVERYTHING: 'XxRrMmLlYyUuEeDdZzFfSsBb',// Allow all slices, and also full cube X, Y, and Z rotations.
  1551. // The cube does its own loopage.
  1552. // It attempts to execute twists in the twistQueue
  1553. // and then tasks in the taskQueue.
  1554. // This is how shuffling and solving are handled.
  1555. loop: function(){
  1556. if( cube.isRotating ){
  1557. cube.threeObject.rotation.x += cube.rotationDeltaX.degreesToRadians()
  1558. cube.threeObject.rotation.y += cube.rotationDeltaY.degreesToRadians()
  1559. cube.threeObject.rotation.z += cube.rotationDeltaZ.degreesToRadians()
  1560. updateControls()
  1561. }
  1562. // If the Cube is "ready"
  1563. // and not a single cubelet is currently tweening
  1564. // regardless of it's resting state (engagement;
  1565. // meanging it could in theory not be tweening but
  1566. // has come to rest at where rotation % 90 !== 0.
  1567. if( cube.isReady && !cube.isTweening() ){
  1568. $( '#cubeIsTweening' ).fadeOut( 100 )
  1569. if( cube.twistQueue.isReady ){
  1570. // We have zero twists in the queue
  1571. // so perhaps we'd like to add some?
  1572. if( cube.twistQueue.future.length === 0 ){
  1573. $( '#cubeHasTwistsQueued' ).fadeOut( 100 )
  1574. // If the Cube ought to be shuffling then
  1575. // add a random command to the twist queue.
  1576. if( cube.isShuffling ){
  1577. cube.twistQueue.add( cube.shuffleMethod[ cube.shuffleMethod.length.rand() ])
  1578. }
  1579. // If the cube ought to be solving and a solver exists
  1580. // and we're not shuffling, tweening, etc.
  1581. else if( cube.isSolving && window.solver ){
  1582. cube.isSolving = window.solver.consider( cube )
  1583. }
  1584. // If we are doing absolutely nothing else
  1585. // then we can can try executing a task.
  1586. else if( cube.taskQueue.isReady === true ){
  1587. var task = cube.taskQueue.do()
  1588. if( task instanceof Function ) task()
  1589. }
  1590. }
  1591. // Otherwise, we have some twists in the queue
  1592. // and we should put everything else aside and tend to those.
  1593. else {
  1594. cube.twist( cube.twistQueue.do() )
  1595. if( cube.twistQueue.future.length > 0 ) $( '#cubeHasTwistsQueued' ).fadeIn( 100 )
  1596. }
  1597. }// cube.twistQueue.isReady
  1598. }
  1599. else if( cube.isTweening ){
  1600. $( '#cubeIsTweening' ).fadeIn( 100 )
  1601. }
  1602. }// loop: function()
  1603. })
  1604. })