primitives.js 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888
  1. 'use strict'
  2. goog.provide('Blockly.OpenSCAD.primitives');
  3. goog.require('Blockly.OpenSCAD');
  4. Blockly.OpenSCAD['sphere'] = function(block) {
  5. var value_rad = Blockly.OpenSCAD.valueToCode(block, 'RAD', Blockly.OpenSCAD.ORDER_ATOMIC);
  6. // missing fields?
  7. if (!value_rad)
  8. Blockscad.missingFields.push(block.id);
  9. // illegal field value?
  10. if (value_rad && value_rad <= 0) {
  11. Blockscad.illegalValue.push(block.inputList[1].connection.targetBlock().id);
  12. }
  13. var code = 'sphere(' + 'r=' + value_rad + ');';
  14. return code;
  15. };
  16. Blockly.OpenSCAD['cylinder'] = function(block) {
  17. var value_rad1 = Blockly.OpenSCAD.valueToCode(block, 'RAD1', Blockly.OpenSCAD.ORDER_ATOMIC);
  18. var value_rad2 = Blockly.OpenSCAD.valueToCode(block, 'RAD2', Blockly.OpenSCAD.ORDER_ATOMIC);
  19. var value_height = Blockly.OpenSCAD.valueToCode(block, 'HEIGHT', Blockly.OpenSCAD.ORDER_ATOMIC);
  20. var dropdown_center = block.getFieldValue('CENTERDROPDOWN');
  21. // missing fields?
  22. if (!value_rad1 || !value_rad2 || !value_height)
  23. Blockscad.missingFields.push(block.id);
  24. // illegal field value?
  25. // console.log(block);
  26. // m1 and m2 will keep me from double-counting errors on blocks
  27. var m1 = false;
  28. var m2 = false;
  29. if (value_rad1 && value_rad1 < 0) {
  30. Blockscad.illegalValue.push(block.inputList[1].connection.targetBlock().id);
  31. m1 = true;
  32. }
  33. if (value_rad2 && value_rad2 < 0) {
  34. Blockscad.illegalValue.push(block.inputList[3].connection.targetBlock().id);
  35. m2 = true;
  36. }
  37. if ((!m1 && !m2) && value_rad1 && value_rad1 == 0) {
  38. if (value_rad2 && value_rad2 == 0) {
  39. Blockscad.illegalValue.push(block.inputList[1].connection.targetBlock().id);
  40. Blockscad.illegalValue.push(block.inputList[3].connection.targetBlock().id);
  41. }
  42. }
  43. if (value_height && value_height <= 0)
  44. Blockscad.illegalValue.push(block.inputList[4].connection.targetBlock().id);
  45. var code = 'cylinder(' + 'r1=' + value_rad1 + ', r2=' + value_rad2 + ', h=' + value_height +', center=' + dropdown_center + ');';
  46. return code;
  47. };
  48. Blockly.OpenSCAD['simple_cylinder'] = function(block) {
  49. var value_rad1 = Blockly.OpenSCAD.valueToCode(block, 'RAD1', Blockly.OpenSCAD.ORDER_ATOMIC);
  50. var value_height = Blockly.OpenSCAD.valueToCode(block, 'HEIGHT', Blockly.OpenSCAD.ORDER_ATOMIC);
  51. var dropdown_center = block.getFieldValue('CENTERDROPDOWN');
  52. // missing fields?
  53. if (!value_rad1 || !value_height)
  54. Blockscad.missingFields.push(block.id);
  55. // illegal field value?
  56. // console.log(block);
  57. if (value_rad1 && value_rad1 <= 0)
  58. Blockscad.illegalValue.push(block.inputList[1].connection.targetBlock().id);
  59. if (value_height && value_height <= 0)
  60. Blockscad.illegalValue.push(block.inputList[3].connection.targetBlock().id);
  61. var code = 'cylinder(' + 'r=' + value_rad1 + ', h=' + value_height +', center=' + dropdown_center + ');';
  62. return code;
  63. };
  64. Blockly.OpenSCAD['cube'] = function(block) {
  65. var value_xval = Blockly.OpenSCAD.valueToCode(block, 'XVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  66. var value_yval = Blockly.OpenSCAD.valueToCode(block, 'YVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  67. var value_zval = Blockly.OpenSCAD.valueToCode(block, 'ZVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  68. var dropdown_center = block.getFieldValue('CENTERDROPDOWN');
  69. // missing fields?
  70. if (!value_xval || !value_yval || !value_zval)
  71. Blockscad.missingFields.push(block.id);
  72. // illegal field value?
  73. // console.log(block);
  74. if (value_xval && value_xval <= 0)
  75. Blockscad.illegalValue.push(block.inputList[1].connection.targetBlock().id);
  76. if (value_yval && value_yval <= 0)
  77. Blockscad.illegalValue.push(block.inputList[2].connection.targetBlock().id);
  78. if (value_zval && value_zval <= 0)
  79. Blockscad.illegalValue.push(block.inputList[3].connection.targetBlock().id);
  80. var code = 'cube([' + value_xval + ', ' + value_yval + ', ' + value_zval + '], center=' + dropdown_center + ');';
  81. return code;
  82. };
  83. Blockly.OpenSCAD['torus'] = function(block) {
  84. var value_rad1 = Blockly.OpenSCAD.valueToCode(block, 'RAD1', Blockly.OpenSCAD.ORDER_ATOMIC);
  85. var value_rad2 = Blockly.OpenSCAD.valueToCode(block, 'RAD2', Blockly.OpenSCAD.ORDER_ATOMIC);
  86. var value_sides = Blockly.OpenSCAD.valueToCode(block, 'SIDES', Blockly.OpenSCAD.ORDER_ATOMIC);
  87. var value_faces = Blockly.OpenSCAD.valueToCode(block, 'FACES', Blockly.OpenSCAD.ORDER_ATOMIC);
  88. // missing fields?
  89. if (!value_rad1 || !value_rad2 || !value_sides || !value_faces)
  90. Blockscad.missingFields.push(block.id);
  91. // illegal field value?
  92. // console.log(block);
  93. if (value_rad1 && value_rad1 <= 0)
  94. Blockscad.illegalValue.push(block.inputList[1].connection.targetBlock().id);
  95. if (value_rad2 && value_rad2 <= 0)
  96. Blockscad.illegalValue.push(block.inputList[2].connection.targetBlock().id);
  97. // minimum number of sides and faces that makes sense is 3 (triangle!)
  98. if (value_sides<3) value_sides = 3;
  99. if (value_faces<3) value_faces = 3;
  100. var code = '// torus \nrotate_extrude($fn=' + value_sides + ') {\n translate([' + value_rad1;
  101. code += ', 0, 0]) {\n circle(r=' + value_rad2 + ', $fn=' + value_faces + ');\n }\n}';
  102. return code;
  103. };
  104. Blockly.OpenSCAD['twistytorus'] = function(block) {
  105. console.log("in generator for twistytorus");
  106. var value_rad1 = Blockly.OpenSCAD.valueToCode(block, 'RAD1', Blockly.OpenSCAD.ORDER_ATOMIC);
  107. var value_rad2 = Blockly.OpenSCAD.valueToCode(block, 'RAD2', Blockly.OpenSCAD.ORDER_ATOMIC);
  108. var value_sides = Blockly.OpenSCAD.valueToCode(block, 'SIDES', Blockly.OpenSCAD.ORDER_ATOMIC);
  109. var value_faces = Blockly.OpenSCAD.valueToCode(block, 'FACES', Blockly.OpenSCAD.ORDER_ATOMIC);
  110. var value_twist = Blockly.OpenSCAD.valueToCode(block, 'TWIST', Blockly.OpenSCAD.ORDER_ATOMIC);
  111. console.log("value_twist is : ", value_twist);
  112. // missing fields?
  113. // missing twist is okay - it will just have 0 twist.
  114. if (!value_rad1 || !value_rad2 || !value_sides || !value_faces)
  115. Blockscad.missingFields.push(block.id);
  116. // illegal field value?
  117. // console.log(block);
  118. if (value_rad1 && value_rad1 <= 0)
  119. Blockscad.illegalValue.push(block.inputList[1].connection.targetBlock().id);
  120. if (value_rad2 && value_rad2 <= 0)
  121. Blockscad.illegalValue.push(block.inputList[2].connection.targetBlock().id);
  122. // minimum number of sides and faces that makes sense is 3 (triangle!)
  123. if (value_sides<3) value_sides = 3;
  124. if (value_faces<3) value_faces = 3;
  125. var code = '// torus \n'
  126. code += 'rotate_extrude($fn=' + value_sides + ',twist=' + value_twist + ') {\n translate([' + value_rad1;
  127. code += ', 0, 0]) {\n circle(r=' + value_rad2 + ', $fn=' + value_faces + ');\n }\n}';
  128. return code;
  129. };
  130. Blockly.OpenSCAD['scale'] = function(block) {
  131. var value_xval = Blockly.OpenSCAD.valueToCode(block, 'XVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  132. var value_yval = Blockly.OpenSCAD.valueToCode(block, 'YVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  133. //console.log("in generator for scale",block.previousConnection.check_);
  134. var type = block.previousConnection.check_[0];
  135. var value_zval = Blockly.OpenSCAD.valueToCode(block, 'ZVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  136. var statements_a = Blockly.OpenSCAD.statementToCode(block, 'A');
  137. // missing fields?
  138. if (!value_xval || !value_yval || (!value_zval && type == 'CSG'))
  139. Blockscad.missingFields.push(block.id);
  140. if (statements_a != '') statements_a += '\n';
  141. for (var n = 0; n<= block.plusCount_; n++) {
  142. var statements_b = Blockly.OpenSCAD.statementToCode(block, 'PLUS' + n);
  143. if (statements_b != '') statements_a += statements_b + '\n';
  144. }
  145. var varCode = Blockly.OpenSCAD.returnVarCode(block);
  146. var aC = varCode[0];
  147. var aP = varCode[1];
  148. if (type != 'CAG')
  149. var code = 'scale([' + value_xval + ', ' + value_yval + ', ' + value_zval + ']){\n' + aC + statements_a + aP + '}';
  150. else var code = 'scale([' + value_xval + ', ' + value_yval + ', 1]){\n' + aC + statements_a + aP + '}';
  151. return code;
  152. };
  153. // Blockly.OpenSCAD['resize'] = function(block) {
  154. // var value_xval = Blockly.OpenSCAD.valueToCode(block, 'XVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  155. // var value_yval = Blockly.OpenSCAD.valueToCode(block, 'YVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  156. // var value_zval = Blockly.OpenSCAD.valueToCode(block, 'ZVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  157. // var statements_a = Blockly.OpenSCAD.statementToCode(block, 'A');
  158. // var code = 'resize([' + value_xval + ', ' + value_yval + ', ' + value_zval + ']){\n' + statements_a + '\n}\n';
  159. // return code;
  160. // };
  161. Blockly.OpenSCAD['translate'] = function(block) {
  162. var value_xval = Blockly.OpenSCAD.valueToCode(block, 'XVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  163. var value_yval = Blockly.OpenSCAD.valueToCode(block, 'YVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  164. var value_zval = Blockly.OpenSCAD.valueToCode(block, 'ZVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  165. var type = block.previousConnection.check_[0];
  166. var statements_a = Blockly.OpenSCAD.statementToCode(block, 'A');
  167. // missing fields?
  168. if (!value_xval || !value_yval || (!value_zval && type == 'CSG'))
  169. Blockscad.missingFields.push(block.id);
  170. if (statements_a != '') statements_a += '\n';
  171. for (var n = 0; n<= block.plusCount_; n++) {
  172. var statements_b = Blockly.OpenSCAD.statementToCode(block, 'PLUS' + n);
  173. if (statements_b != '') statements_a += statements_b + '\n';
  174. }
  175. var varCode = Blockly.OpenSCAD.returnVarCode(block);
  176. var aC = varCode[0];
  177. var aP = varCode[1];
  178. if (type != 'CAG')
  179. var code = 'translate([' + value_xval + ', ' + value_yval + ', ' + value_zval + ']){\n' + aC + statements_a + aP + '}';
  180. else var code = 'translate([' + value_xval + ', ' + value_yval + ', 0]){\n' + aC + statements_a + aP + '}';
  181. return code;
  182. };
  183. Blockly.OpenSCAD['color'] = function(block) {
  184. var statements_a = Blockly.OpenSCAD.statementToCode(block, 'A');
  185. if (statements_a != '') statements_a += '\n';
  186. for (var n = 0; n<= block.plusCount_; n++) {
  187. var statements_b = Blockly.OpenSCAD.statementToCode(block, 'PLUS' + n);
  188. if (statements_b != '') statements_a += statements_b + '\n';
  189. }
  190. var value_color = Blockly.OpenSCAD.valueToCode(block, 'COLOR',Blockly.OpenSCAD.ORDER_ATOMIC);
  191. // missing fields?
  192. if (!value_color && Blockscad.stackIsShape(block))
  193. Blockscad.missingFields.push(block.id);
  194. var varCode = Blockly.OpenSCAD.returnVarCode(block);
  195. var aC = varCode[0];
  196. var aP = varCode[1];
  197. var code = '';
  198. if (value_color) {
  199. var R = hexToR(value_color);
  200. var G = hexToG(value_color);
  201. var B = hexToB(value_color);
  202. code += 'color([' + R +',' + G + ',' + B + ']) ';
  203. }
  204. code += '{\n' + aC + statements_a + aP + '}';
  205. return code;
  206. };
  207. Blockly.OpenSCAD['color_rgb'] = function(block) {
  208. var statements_a = Blockly.OpenSCAD.statementToCode(block, 'A');
  209. var scheme = block.getFieldValue('SCHEME');
  210. var red = Blockly.OpenSCAD.valueToCode(block, 'RED',
  211. Blockly.OpenSCAD.ORDER_COMMA) || 0;
  212. var green = Blockly.OpenSCAD.valueToCode(block, 'GREEN',
  213. Blockly.OpenSCAD.ORDER_COMMA) || 0;
  214. var blue = Blockly.OpenSCAD.valueToCode(block, 'BLUE',
  215. Blockly.OpenSCAD.ORDER_COMMA) || 0;
  216. if (statements_a != '') statements_a += '\n';
  217. for (var n = 0; n<= block.plusCount_; n++) {
  218. var statements_b = Blockly.OpenSCAD.statementToCode(block, 'PLUS' + n);
  219. if (statements_b != '') statements_a += statements_b + '\n';
  220. }
  221. var varCode = Blockly.OpenSCAD.returnVarCode(block);
  222. var aC = varCode[0];
  223. var aP = varCode[1];
  224. var code = '';
  225. if (scheme == 'RGB') {
  226. if ($.isNumeric(red)) {
  227. if (red < 0) red = 0;
  228. if (red > 100) red = 100;
  229. }
  230. if ($.isNumeric(blue)) {
  231. if (blue < 0) blue = 0;
  232. if (blue > 100) blue = 100;
  233. }
  234. if ($.isNumeric(green)) {
  235. if (green < 0) green = 0;
  236. if (green > 100) green = 100;
  237. }
  238. code += 'color([ .01 * (' + red + '), .01 * (' + green +'), .01 * (' + blue +')]) ';
  239. code += '{\n' + aC + statements_a + aP + '}';
  240. }
  241. // Thanks to Hypher for the implementation of hsv to rgb in openscad!
  242. // http://forum.openscad.org/An-HSV-HSB-to-RGB-Color-function-in-OpenSCAD-td9835.html
  243. else if (scheme == 'HSV') {
  244. if($.isNumeric(red)) {
  245. // make sure that the mod returns a positive number
  246. red = ((red % 100) + 100) % 100;
  247. }
  248. var hsvHelper = Blockly.OpenSCAD.provideFunction_(
  249. 'doHsvMatrix',
  250. [ 'function ' + Blockly.OpenSCAD.FUNCTION_NAME_PLACEHOLDER_ +
  251. '(h,s,v,p,q,t,a=1)=[h<1?v:h<2?q:h<3?p:h<4?p:h<5?t:v,h<1?t:h<2?v:h<3?v:h<4?q:h<5?p:p,h<1?p:h<2?p:h<3?t:h<4?v:h<5?v:q,a];']);
  252. var hsvFunction = Blockly.OpenSCAD.provideFunction_(
  253. 'hsv',
  254. ['function ' + Blockly.OpenSCAD.FUNCTION_NAME_PLACEHOLDER_ +
  255. '(h, s=1, v=1,a=1)=doHsvMatrix((h%1)*6,s<0?0:s>1?1:s,v<0?0:v>1?1:v,v*(1-s),v*(1-s*((h%1)*6-floor((h%1)*6))),v*(1-s*(1-((h%1)*6-floor((h%1)*6)))),a);\n']);
  256. code += 'color(hsv(.01 * (' + red + '), .01 * (' + green +'), .01 * (' + blue +')))';
  257. code += '{\n' + aC + statements_a + aP + '}';
  258. }
  259. else console.log("got weirdo color scheme?");
  260. return code;
  261. };
  262. Blockly.OpenSCAD['$fn'] = function(block) {
  263. var statements_a = Blockly.OpenSCAD.statementToCode(block, 'A');
  264. var type = block.previousConnection.check_[0];
  265. if (statements_a != '') statements_a += '\n';
  266. for (var n = 0; n<= block.plusCount_; n++) {
  267. var statements_b = Blockly.OpenSCAD.statementToCode(block, 'PLUS' + n);
  268. if (statements_b != '') statements_a += statements_b + '\n';
  269. }
  270. var value_sides = Blockly.OpenSCAD.valueToCode(block, 'SIDES',Blockly.OpenSCAD.ORDER_ATOMIC);
  271. // missing fields?
  272. if (!value_sides) {
  273. Blockscad.missingFields.push(block.id);
  274. }
  275. // if this is a number, make sure it is a reasonable number.
  276. // variables right now are on their own.
  277. else if (!isNaN(value_sides)) {
  278. value_sides = Math.floor(value_sides);
  279. if (value_sides < 3) value_sides = 3;
  280. }
  281. var varCode = Blockly.OpenSCAD.returnVarCode(block);
  282. var aC = varCode[0];
  283. var aP = varCode[1];
  284. // console.log(statements_a);
  285. var code = 'assign($fn=' + value_sides + '){ //set sides to ' + value_sides + '\n' + aC + statements_a + aP + '}';
  286. return code;
  287. };
  288. Blockly.OpenSCAD['assign'] = function(block) {
  289. var statements_a = Blockly.OpenSCAD.statementToCode(block, 'A');
  290. var type = block.previousConnection.check_[0];
  291. if (statements_a != '') statements_a += '\n';
  292. for (var n = 0; n<= block.plusCount_; n++) {
  293. var statements_b = Blockly.OpenSCAD.statementToCode(block, 'PLUS' + n);
  294. if (statements_b != '') statements_a += statements_b + '\n';
  295. }
  296. var name = Blockly.OpenSCAD.valueToCode(block, 'NAME',Blockly.OpenSCAD.ORDER_ATOMIC);
  297. var value = Blockly.OpenSCAD.valueToCode(block,'VALUE', Blockly.OpenSCAD.ORDER_ATOMIC);
  298. var varCode = Blockly.OpenSCAD.returnVarCode(block);
  299. var aC = varCode[0];
  300. var aP = varCode[1];
  301. var code = 'assign(' + name + '=' + value + '){\n' + aC + statements_a + aP + '}';
  302. return code;
  303. };
  304. Blockly.OpenSCAD['fancymirror'] = function(block) {
  305. var value_xval = Blockly.OpenSCAD.valueToCode(block, 'XVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  306. var value_yval = Blockly.OpenSCAD.valueToCode(block, 'YVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  307. var value_zval = Blockly.OpenSCAD.valueToCode(block, 'ZVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  308. var statements_a = Blockly.OpenSCAD.statementToCode(block, 'A');
  309. if (statements_a != '') statements_a += '\n';
  310. for (var n = 0; n<= block.plusCount_; n++) {
  311. var statements_b = Blockly.OpenSCAD.statementToCode(block, 'PLUS' + n);
  312. if (statements_b != '') statements_a += statements_b + '\n';
  313. }
  314. // missing fields?
  315. if (!value_xval || !value_yval || (!value_zval))
  316. Blockscad.missingFields.push(block.id);
  317. var type = block.previousConnection.check_[0];
  318. var varCode = Blockly.OpenSCAD.returnVarCode(block);
  319. var aC = varCode[0];
  320. var aP = varCode[1];
  321. //if (type != 'CAG')
  322. var code = 'mirror([' + value_xval + ', ' + value_yval + ', ' + value_zval + ']){\n' + aC + statements_a + aP + '}';
  323. //else var code = 'mirror([' + value_xval + ', ' + value_yval + ']){\n' + aC + statements_a + aP + '}';
  324. return code;
  325. };
  326. Blockly.OpenSCAD['simplerotate'] = function(block) {
  327. //var angle_xval = block.getFieldValue('XVAL');
  328. var value_xval = Blockly.OpenSCAD.valueToCode(block, 'XVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  329. var value_yval = Blockly.OpenSCAD.valueToCode(block, 'YVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  330. var value_zval = Blockly.OpenSCAD.valueToCode(block, 'ZVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  331. var type = block.previousConnection.check_[0];
  332. var statements_a = Blockly.OpenSCAD.statementToCode(block, 'A');
  333. if (statements_a != '') statements_a += '\n';
  334. for (var n = 0; n<= block.plusCount_; n++) {
  335. var statements_b = Blockly.OpenSCAD.statementToCode(block, 'PLUS' + n);
  336. if (statements_b != '') statements_a += statements_b + '\n';
  337. }
  338. // 2D shapes get to keep all their fields.
  339. // if (type != 'CAG')
  340. // missing fields?
  341. if (!value_xval || !value_yval || (!value_zval))
  342. Blockscad.missingFields.push(block.id);
  343. var varCode = Blockly.OpenSCAD.returnVarCode(block);
  344. var aC = varCode[0];
  345. var aP = varCode[1];
  346. var code = 'rotate([' + value_xval + ', ' + value_yval + ', ' + value_zval + ']){\n' + aC + statements_a + aP + '}';
  347. // else var code = 'rotate([0, 0, ' + value_zval + ']){\n' + statements_a + '}';
  348. return code;
  349. };
  350. Blockly.OpenSCAD['fancyrotate'] = function(block) {
  351. var value_aval = Blockly.OpenSCAD.valueToCode(block, 'AVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  352. var value_xval = Blockly.OpenSCAD.valueToCode(block, 'XVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  353. var value_yval = Blockly.OpenSCAD.valueToCode(block, 'YVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  354. var value_zval = Blockly.OpenSCAD.valueToCode(block, 'ZVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  355. var type = block.previousConnection.check_[0];
  356. var statements_a = Blockly.OpenSCAD.statementToCode(block, 'A');
  357. if (statements_a != '') statements_a += '\n';
  358. for (var n = 0; n<= block.plusCount_; n++) {
  359. var statements_b = Blockly.OpenSCAD.statementToCode(block, 'PLUS' + n);
  360. if (statements_b != '') statements_a += statements_b + '\n';
  361. }
  362. // missing fields?
  363. if (!value_aval || ((!value_xval || !value_yval || !value_zval) && type == 'CSG'))
  364. Blockscad.missingFields.push(block.id);
  365. var varCode = Blockly.OpenSCAD.returnVarCode(block);
  366. var aC = varCode[0];
  367. var aP = varCode[1];
  368. if (type != 'CAG')
  369. var code = 'rotate(a=' + value_aval + ', v=[' + value_xval + ', ' + value_yval + ', ' + value_zval + ']){\n' + aC + statements_a + aP + '}';
  370. else var code = 'rotate([0, 0, '+ value_aval + ']){\n' + aC + statements_a + aP + '}';
  371. return code;
  372. };
  373. Blockly.OpenSCAD['simplemirror_new'] = function(block) {
  374. var statements_a = Blockly.OpenSCAD.statementToCode(block, 'A');
  375. if (statements_a != '') statements_a += '\n';
  376. for (var n = 0; n<= block.plusCount_; n++) {
  377. var statements_b = Blockly.OpenSCAD.statementToCode(block, 'PLUS' + n);
  378. if (statements_b != '') statements_a += statements_b + '\n';
  379. }
  380. var dropdown_mirrorplane = block.getFieldValue('mirrorplane');
  381. var dropdown_mirrorplane_cag = block.getFieldValue('mirrorplane_cag');
  382. var vec;
  383. var type = block.previousConnection.check_[0];
  384. var varCode = Blockly.OpenSCAD.returnVarCode(block);
  385. var aC = varCode[0];
  386. var aP = varCode[1];
  387. if (type != 'CAG') {
  388. if (dropdown_mirrorplane == "XY") {
  389. vec = "[0,0,1]";
  390. }
  391. else if (dropdown_mirrorplane == "YZ") {
  392. vec = "[1,0,0]";
  393. }
  394. else if (dropdown_mirrorplane == "XZ") {
  395. vec = "[0,1,0]";
  396. }
  397. var code = 'mirror(' + vec + '){\n' + aC + statements_a + aP + '}';
  398. }
  399. else {
  400. if (dropdown_mirrorplane_cag == "YZ") {
  401. vec = "[1,0,0]";
  402. }
  403. else if (dropdown_mirrorplane_cag == "XZ") {
  404. vec = "[0,1,0]";
  405. }
  406. var code = 'mirror(' + vec + '){\n' + aC + statements_a + aP + '}';
  407. }
  408. return code;
  409. };
  410. Blockly.OpenSCAD['taper'] = function(block) {
  411. var statements_a = Blockly.OpenSCAD.statementToCode(block, 'A');
  412. if (statements_a != '') statements_a += '\n';
  413. for (var n = 0; n<= block.plusCount_; n++) {
  414. var statements_b = Blockly.OpenSCAD.statementToCode(block, 'PLUS' + n);
  415. if (statements_b != '') statements_a += statements_b + '\n';
  416. }
  417. var dropdown_axis = block.getFieldValue('taperaxis');
  418. var dropdown_axis_cag = block.getFieldValue('taperaxis_cag');
  419. var vec;
  420. var factor = Blockly.OpenSCAD.valueToCode(block, 'FACTOR', Blockly.OpenSCAD.ORDER_ATOMIC);
  421. var type = block.previousConnection.check_[0];
  422. var varCode = Blockly.OpenSCAD.returnVarCode(block);
  423. var aC = varCode[0];
  424. var aP = varCode[1];
  425. // missing the factor field? just set it to one.
  426. if (!factor) factor = 1;
  427. if (type != 'CAG') {
  428. if (dropdown_axis == "Z") {
  429. vec = "[0,0,1]";
  430. }
  431. else if (dropdown_axis == "X") {
  432. vec = "[1,0,0]";
  433. }
  434. else if (dropdown_axis == "Y") {
  435. vec = "[0,1,0]";
  436. }
  437. var code = 'taper(' + vec + ', ' + factor + '){\n' + aC + statements_a + aP + '}';
  438. }
  439. else {
  440. if (dropdown_axis_cag == "X") {
  441. vec = "[1,0,0]";
  442. }
  443. else if (dropdown_axis_cag == "Y") {
  444. vec = "[0,1,0]";
  445. }
  446. var code = 'taper(' + vec + ', ' + factor + '){\n' + aC + statements_a + aP + '}';
  447. }
  448. return code;
  449. };
  450. Blockly.OpenSCAD['simplemirror'] = function(block) {
  451. var statements_a = Blockly.OpenSCAD.statementToCode(block, 'A');
  452. if (statements_a != '') statements_a += '\n';
  453. var dropdown_sign = block.getFieldValue('sign');
  454. var dropdown_mirrorplane = block.getFieldValue('mirrorplane');
  455. var vec;
  456. var type = block.previousConnection.check_[0];
  457. if (dropdown_mirrorplane == "XY") {
  458. if (dropdown_sign == "pos") {
  459. vec = "[0,0,1]";
  460. } else {
  461. vec = "[0,0,-1]";
  462. }
  463. } else if (dropdown_mirrorplane == "YZ") {
  464. if (dropdown_sign == "pos") {
  465. vec = "[1,0,0]";
  466. } else {
  467. vec = "[-1,0,0]";
  468. }
  469. } else if (dropdown_mirrorplane == "XZ") {
  470. if (dropdown_sign == "pos") {
  471. vec = "[0,1,0]";
  472. } else {
  473. vec = "[0,-1,0]";
  474. }
  475. }
  476. var varCode = Blockly.OpenSCAD.returnVarCode(block);
  477. var aC = varCode[0];
  478. var aP = varCode[1];
  479. var code = 'mirror(' + vec + '){\n' + aC + statements_a + aP + '}';
  480. return code;
  481. };
  482. // Blockly.OpenSCAD['shape'] = function(block) {
  483. // var statements_a = Blockly.OpenSCAD.statementToCode(block, 'NAME');
  484. // var code = statements_a;
  485. // return code;
  486. // };
  487. Blockly.OpenSCAD['circle'] = function(block) {
  488. var value_rad = Blockly.OpenSCAD.valueToCode(block, 'RAD', Blockly.OpenSCAD.ORDER_ATOMIC);
  489. // missing fields?
  490. if (!value_rad)
  491. Blockscad.missingFields.push(block.id);
  492. // illegal field value?
  493. if (value_rad && value_rad <= 0) {
  494. Blockscad.illegalValue.push(block.inputList[1].connection.targetBlock().id);
  495. }
  496. var code = 'circle(' + 'r=' + value_rad + ');';
  497. return code;
  498. };
  499. Blockly.OpenSCAD['square'] = function(block) {
  500. var value_xval = Blockly.OpenSCAD.valueToCode(block, 'XVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  501. var value_yval = Blockly.OpenSCAD.valueToCode(block, 'YVAL', Blockly.OpenSCAD.ORDER_ATOMIC);
  502. var dropdown_center = block.getFieldValue('CENTERDROPDOWN');
  503. // missing fields?
  504. if (!value_xval || !value_yval)
  505. Blockscad.missingFields.push(block.id);
  506. // illegal field value?
  507. if (value_xval && value_xval <= 0) {
  508. Blockscad.illegalValue.push(block.inputList[1].connection.targetBlock().id);
  509. }
  510. if (value_yval && value_yval <= 0) {
  511. Blockscad.illegalValue.push(block.inputList[2].connection.targetBlock().id);
  512. }
  513. var code = 'square([' + value_xval + ', ' + value_yval + '], center=' + dropdown_center + ');';
  514. return code;
  515. };
  516. // Blockly.OpenSCAD['colourShape'] = function(block) {
  517. // var value_color = Blockly.OpenSCAD.valueToCode(block, 'C', Blockly.OpenSCAD.ORDER_ATOMIC) || '\'#ff0000\'';
  518. // var statements_a = Blockly.OpenSCAD.statementToCode(block, 'A');
  519. // //value_color is a hex string, '#ff0000' by default, quotes included.
  520. // var red = (value_color.slice(2,4),16);
  521. // var grn = (value_color.slice(4,6),16);
  522. // var blu = (value_color.slice(6,8),16);
  523. // var code = 'color([' + red +'/255, '+ grn +'/255, '+ blu + '/255]){\n' + statements_a + '\n}\n';
  524. // return code;
  525. // };
  526. Blockly.OpenSCAD['linearextrude'] = function(block) {
  527. var value_height = Blockly.OpenSCAD.valueToCode(block, 'HEIGHT', Blockly.OpenSCAD.ORDER_ATOMIC);
  528. var value_twist = Blockly.OpenSCAD.valueToCode(block, 'TWIST', Blockly.OpenSCAD.ORDER_ATOMIC);
  529. var value_xscale = Blockly.OpenSCAD.valueToCode(block, 'XSCALE', Blockly.OpenSCAD.ORDER_ATOMIC);
  530. var value_yscale = Blockly.OpenSCAD.valueToCode(block, 'YSCALE', Blockly.OpenSCAD.ORDER_ATOMIC);
  531. var dropdown_center = block.getFieldValue('CENTERDROPDOWN');
  532. var statements_a = Blockly.OpenSCAD.statementToCode(block, 'A');
  533. if (statements_a != '') statements_a += '\n';
  534. for (var n = 0; n<= block.plusCount_; n++) {
  535. var statements_b = Blockly.OpenSCAD.statementToCode(block, 'PLUS' + n);
  536. if (statements_b != '') statements_a += statements_b + '\n';
  537. }
  538. // missing fields?
  539. if ((!value_height || !value_twist))
  540. Blockscad.missingFields.push(block.id);
  541. // illegal field value?
  542. if (value_height && value_height <= 0) {
  543. Blockscad.illegalValue.push(block.inputList[1].connection.targetBlock().id);
  544. }
  545. // let empty scale fields default to one
  546. if (!value_xscale) value_xscale = 1;
  547. if (!value_yscale) value_yscale = 1;
  548. var varCode = Blockly.OpenSCAD.returnVarCode(block);
  549. var aC = varCode[0];
  550. var aP = varCode[1];
  551. var code = 'linear_extrude( height=' + value_height + ', twist=' + value_twist +
  552. ', scale=[' + value_xscale + ', ' + value_yscale + '], center=' + dropdown_center + '){\n' + aC + statements_a + aP + '}';
  553. return code;
  554. };
  555. Blockly.OpenSCAD['rotateextrude'] = function(block) {
  556. var value_faces = Blockly.OpenSCAD.valueToCode(block, 'FACES', Blockly.OpenSCAD.ORDER_ATOMIC);
  557. var statements_a = Blockly.OpenSCAD.statementToCode(block, 'A');
  558. if (statements_a != '') statements_a += '\n';
  559. for (var n = 0; n<= block.plusCount_; n++) {
  560. var statements_b = Blockly.OpenSCAD.statementToCode(block, 'PLUS' + n);
  561. if (statements_b != '') statements_a += statements_b + '\n';
  562. }
  563. // missing fields?
  564. if (!value_faces)
  565. Blockscad.missingFields.push(block.id);
  566. var varCode = Blockly.OpenSCAD.returnVarCode(block);
  567. var aC = varCode[0];
  568. var aP = varCode[1];
  569. var code = 'rotate_extrude($fn=' + value_faces + '){\n' + aC + statements_a + aP + '}';
  570. return code;
  571. };
  572. Blockly.OpenSCAD['rotateextrudetwist'] = function(block) {
  573. var value_faces = Blockly.OpenSCAD.valueToCode(block, 'FACES', Blockly.OpenSCAD.ORDER_ATOMIC);
  574. var value_r = Blockly.OpenSCAD.valueToCode(block,'RAD',Blockly.OpenSCAD.ORDER_ATOMIC);
  575. var value_twist = Blockly.OpenSCAD.valueToCode(block,'TWIST',Blockly.OpenSCAD.ORDER_ATOMIC);
  576. var value_tsteps = Blockly.OpenSCAD.valueToCode(block,'TSTEPS',Blockly.OpenSCAD.ORDER_ATOMIC);
  577. var statements_a = Blockly.OpenSCAD.statementToCode(block, 'A');
  578. if (statements_a != '') statements_a += '\n';
  579. for (var n = 0; n<= block.plusCount_; n++) {
  580. var statements_b = Blockly.OpenSCAD.statementToCode(block, 'PLUS' + n);
  581. if (statements_b != '') statements_a += statements_b + '\n';
  582. }
  583. // missing fields?
  584. // console.log(block);
  585. if (!value_faces || !value_r)
  586. Blockscad.missingFields.push(block.id);
  587. // illegal field value?
  588. if (value_r && value_r < 0) {
  589. // console.log(block.inputList[1].connection.targetBlock());
  590. Blockscad.illegalValue.push(block.inputList[1].connection.targetBlock().id);
  591. }
  592. if (value_faces && value_faces < 3) value_faces = 3;
  593. var varCode = Blockly.OpenSCAD.returnVarCode(block);
  594. var aC = varCode[0];
  595. var aP = varCode[1];
  596. var code = 'rotate_extrude($fn=' + value_faces + ',radius=' + value_r + ',twist=' +
  597. value_twist + ',tsteps=' + value_tsteps + '){\n' + aC + statements_a + aP + '}';
  598. return code;
  599. };
  600. Blockly.OpenSCAD['stl_import'] = function(block) {
  601. var text_filename = block.getFieldValue('STL_FILENAME');
  602. var code = 'import("' + text_filename + '");\n';
  603. return code;
  604. };
  605. // 2d text block. Named before I knew we would be adding a 3D text block.
  606. Blockly.OpenSCAD['bs_text'] = function(block) {
  607. // var this_text = block.getFieldValue('TEXT');
  608. var this_text = Blockly.OpenSCAD.valueToCode(block,'TEXT', Blockly.OpenSCAD.ORDER_ATOMIC);
  609. var this_font = Blockscad.fontName[parseInt(block.getFieldValue('FONT'))];
  610. var value_size = Blockly.OpenSCAD.valueToCode(block,'SIZE', Blockly.OpenSCAD.ORDER_ATOMIC);
  611. // missing fields?
  612. if (!value_size || !this_text)
  613. Blockscad.missingFields.push(block.id);
  614. // illegal field value?
  615. if (value_size && value_size <= 0) {
  616. Blockscad.illegalValue.push(block.inputList[2].connection.targetBlock().id);
  617. }
  618. if (this_text && (this_text[0] != '"' || this_text[this_text.length - 1] != '"'))
  619. this_text = 'str(' + this_text + ')';
  620. var code = "// size is multiplied by 0.75 because openScad fonts size is in points, not pixels\n";
  621. code += 'text(' + this_text + ', font = "' + this_font +
  622. '", size = ' + value_size + '* 0.75);\n';
  623. return code;
  624. }
  625. Blockly.OpenSCAD['bs_3dtext'] = function(block) {
  626. // var this_text = block.getFieldValue('TEXT');
  627. var this_text = Blockly.OpenSCAD.valueToCode(block,'TEXT', Blockly.OpenSCAD.ORDER_ATOMIC);
  628. var this_font = Blockscad.fontName[parseInt(block.getFieldValue('FONT'))];
  629. var value_size = Blockly.OpenSCAD.valueToCode(block,'SIZE', Blockly.OpenSCAD.ORDER_ATOMIC);
  630. var value_thickness = Blockly.OpenSCAD.valueToCode(block, 'THICKNESS', Blockly.OpenSCAD.ORDER_ATOMIC);
  631. // escape any quote characters in this_text before passing it to the openscad parser
  632. // this_text = this_text.replace(/\"/g,"\\\"");
  633. // this_text = this_text.replace(/\\/g,"\\\\");
  634. // missing fields?
  635. if (!value_size || !value_thickness || !this_text)
  636. Blockscad.missingFields.push(block.id);
  637. // illegal field value?
  638. if (value_size && value_size <= 0) {
  639. Blockscad.illegalValue.push(block.inputList[2].connection.targetBlock().id);
  640. }
  641. if (value_thickness && value_thickness <= 0) {
  642. Blockscad.illegalValue.push(block.inputList[4].connection.targetBlock().id);
  643. }
  644. if (this_text && (this_text[0] != '"' || this_text[this_text.length - 1] != '"'))
  645. this_text = 'str(' + this_text + ')';
  646. var code = "// size is multiplied by 0.75 because openScad fonts size is in points, not pixels\n";
  647. code += 'linear_extrude( height=' + value_thickness + ', twist=0, center=false){\n' +
  648. ' text(' + this_text + ', font = "' + this_font +
  649. '", size = ' + value_size + '*0.75);\n}\n';
  650. return code;
  651. }
  652. Blockly.OpenSCAD['text'] = function(block) {
  653. // Text value.
  654. var code = Blockly.OpenSCAD.quote_(block.getFieldValue('TEXT'));
  655. // var code = '"' + block.getFieldValue('TEXT') + '"';
  656. if (!block.getParent())
  657. return ['//' + code, Blockly.OpenSCAD.ORDER_ATOMIC];
  658. else
  659. return [code,Blockly.OpenSCAD.ORDER_ATOMIC];
  660. }
  661. // OpenSCAD does not implement a text length function. This isn't a problem
  662. // for BlocksCAD, because we can just compute the actual length of the string in
  663. // the code and use that number directly.
  664. // However, it is a problem for someone who is exporting the openscad code to
  665. // run in openscad. What is the best way to accomplish this? A warning at the
  666. // top of the openscad file? A popup warning when you export the openscad code?
  667. // both? Adding a string length function to openscad? (heh)
  668. Blockly.OpenSCAD['bs_text_length'] = function(block) {
  669. // String length.
  670. var argument0 = Blockly.OpenSCAD.valueToCode(block, 'VALUE',
  671. Blockly.OpenSCAD.ORDER_FUNCTION_CALL) || '\'\'';
  672. var code = 'len(' + argument0 + ')';
  673. if (!block.getParent())
  674. return ['//' + code, Blockly.OpenSCAD.ORDER_ATOMIC];
  675. else
  676. return [code,Blockly.OpenSCAD.ORDER_ATOMIC];
  677. }
  678. // hexTo(RGB) take a blockly color string '#00ff88' for example, including the quotes
  679. // and returns RGB values.
  680. function hexToR(h) {
  681. return Math.round(100 * parseInt(h.substring(2,4),16) / 255) / 100;
  682. }
  683. function hexToG(h) {
  684. return Math.round(100 * parseInt(h.substring(4,6),16) / 255) / 100;
  685. }
  686. function hexToB(h) {
  687. return Math.round(100 * parseInt(h.substring(6,8),16) / 255) / 100;
  688. }
  689. Blockly.OpenSCAD.returnVarCode = function(block) {
  690. var assignments = Blockly.OpenSCAD.getVariableCode(block);
  691. // console.log("finished getVariableCode");
  692. var aC = '';
  693. var aP = '';
  694. if (assignments.length) {
  695. aC += ' assign(';
  696. for (var i = 0; i < assignments.length; i++) {
  697. aC += assignments[i] + ',';
  698. }
  699. // trim off the last comma
  700. aC = aC.slice(0, -1);
  701. aC += '){\n';
  702. aP = ' }//end assign\n';
  703. }
  704. return [aC,aP];
  705. }
  706. // given a block: if that block has any children that are varSet blocks, return them.
  707. Blockly.OpenSCAD.returnVarChildren = function(block, array) {
  708. // for (var i = 0; i < block.childBlocks_.length; i++) {
  709. // if (block.childBlocks_[i].type == 'variables_set') {
  710. // // this is a variable_set block. add it to the list, then check the child recursively.
  711. // array.push(block.childBlocks_[i]);
  712. // Blockly.OpenSCAD.returnVarChildren(block.childBlocks_[i], array);
  713. // }
  714. // }
  715. // console.log(block);
  716. for (var i = 0; i < block.childBlocks_.length; i++) {
  717. if (block.childBlocks_[i].type == 'variables_set') {
  718. array.push(block.childBlocks_[i]);
  719. // this is a variable block. It might have two children, with the second being another variable, and so on.
  720. var v = block.childBlocks_[i];
  721. while (v.childBlocks_.length > 1 && v.childBlocks_[1].type == 'variables_set' ){
  722. array.push(v.childBlocks_[1]);
  723. v = v.childBlocks_[1];
  724. }
  725. }
  726. }
  727. }
  728. Blockly.OpenSCAD.returnVarChain = function(block, array) {
  729. var blah = 1;
  730. while (blah) {
  731. if (block.type == "variables_set") {
  732. blah = 0;
  733. array.push(block);
  734. if (block.childBlocks_.length > 1 && block.childBlocks_[1].type == "variables_set") {
  735. block = block.childBlocks_[1];
  736. blah = 1;
  737. }
  738. }
  739. }
  740. }
  741. Blockly.OpenSCAD.getVariableCode = function(block) {
  742. // I have a block. Does this block have any variable setters as children or itself? If so, return an array of the blocks.
  743. var blocks = [];
  744. var codes = [];
  745. // for logic blocks, I may send a variable block here. So push block onto the top of the list.
  746. if (block.type == "variables_set") {
  747. Blockly.OpenSCAD.returnVarChain(block,blocks);
  748. }
  749. else {
  750. Blockly.OpenSCAD.returnVarChildren(block, blocks);
  751. }
  752. for (var i = 0; i < blocks.length; i++) {
  753. // console.log("in getVariableCode. Have a: ",blocks[i].type);
  754. var argument0 = Blockly.OpenSCAD.valueToCode(blocks[i], 'VALUE',
  755. Blockly.OpenSCAD.ORDER_ASSIGNMENT) || '0';
  756. var varName = Blockly.OpenSCAD.variableDB_.getName(
  757. blocks[i].getFieldValue('VAR'), Blockly.Variables.NAME_TYPE);
  758. codes[i] = varName + ' = ' + argument0;
  759. }
  760. return codes;
  761. }