From 41c301083dcff1dce69a1b21a9d69b1d508df12a Mon Sep 17 00:00:00 2001 From: chinedu amadi-ndukwe Date: Tue, 9 Apr 2019 15:35:34 -0400 Subject: [PATCH 01/11] working on 2D extrusion --- .idea/CSnap.iml | 13 + .idea/encodings.xml | 4 + .idea/libraries/R_User_Library.xml | 6 + .idea/misc.xml | 7 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + .idea/workspace.xml | 2186 ++++++++++++++++++++++++++++ gui.js | 54 +- 8 files changed, 2274 insertions(+), 10 deletions(-) create mode 100644 .idea/CSnap.iml create mode 100644 .idea/encodings.xml create mode 100644 .idea/libraries/R_User_Library.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml diff --git a/.idea/CSnap.iml b/.idea/CSnap.iml new file mode 100644 index 0000000000..bf708e32be --- /dev/null +++ b/.idea/CSnap.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000000..15a15b218a --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/libraries/R_User_Library.xml b/.idea/libraries/R_User_Library.xml new file mode 100644 index 0000000000..71f5ff7491 --- /dev/null +++ b/.idea/libraries/R_User_Library.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000000..865611434f --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000000..55a74be658 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000000..94a25f7f4c --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000000..6122e0fe61 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,2186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + icos + icosa + config.asset + objl + cloud + saveclou + saveproj + saveProjec + upload + upload_project + saveas + menu.add + 3d + save + sprite.costume.is3D + sprite.costume + menu.additem + init + + + $PROJECT_DIR$ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1142,16 +1088,18 @@ + - - + + - + @@ -1164,8 +1112,8 @@ - - + + @@ -1207,10 +1155,30 @@ + + + + + + + + + + + + + + + + + + + + - - + + @@ -1221,8 +1189,6 @@ - - @@ -1783,8 +1749,6 @@ - - @@ -2151,34 +2115,17 @@ - - - - - - - - - - - + - - + + - - - - - - - - - + + diff --git a/gui.js b/gui.js index 16c2eab638..7ccfee1510 100644 --- a/gui.js +++ b/gui.js @@ -7071,9 +7071,43 @@ ProjectDialogMorph.prototype.fixClassRoomItemColors = function () { }); }; -function doActualExtrusionOfImage(pathToImgWeWantToExtrude) { + +function doActualExtrusionOfImage(pathToImgWeWantToExtrude, x, y) { console.log("inside the extrusion function"); console.log(pathToImgWeWantToExtrude); + console.log("now let's log the height and width of the image"); + console.log(pathToImgWeWantToExtrude.width); + console.log(pathToImgWeWantToExtrude.height); + + // temporary canvas to hold the image and retrieve its data + let tempCanvasToGetImageData = document.createElement('canvas'); + let ctx = tempCanvasToGetImageData.getContext("2d"); + tempCanvasToGetImageData.width = pathToImgWeWantToExtrude.width; + tempCanvasToGetImageData.height = pathToImgWeWantToExtrude.height; + ctx.drawImage(pathToImgWeWantToExtrude, 0, 0); // this should draw the image with its intrinsic size + + let myImageData = ctx.getImageData(x, y, pathToImgWeWantToExtrude.width, pathToImgWeWantToExtrude.height); + console.log(myImageData); + + console.log("my image data data is: "); + console.log(myImageData.data); + console.log(myImageData.width); + console.log(myImageData.height); + + for (let i=0;i Date: Wed, 10 Apr 2019 18:01:32 -0400 Subject: [PATCH 03/11] download is not working yay! Now need to use heightmap to make it 3D --- .idea/workspace.xml | 47 ++++++++++++++++++++++++++++++--------------- gui.js | 8 ++++++++ 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 4eb2ec3f41..ae67262cf6 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,7 +2,6 @@ - - - + + + + + + + - - + + diff --git a/gui.js b/gui.js index 7ccfee1510..36c0e09f52 100644 --- a/gui.js +++ b/gui.js @@ -7109,6 +7109,14 @@ function doActualExtrusionOfImage(pathToImgWeWantToExtrude, x, y) { console.log(myNewImage.width); console.log(myNewImage.height); + let a = document.createElement('a'); + a.href = myNewImage.src; + a.download = "image.png"; + console.log(a); + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + } function extruding2D(myself) { From 712dded6f2c5fdff543afec191d6552be8dc7902 Mon Sep 17 00:00:00 2001 From: chinedu amadi-ndukwe Date: Wed, 10 Apr 2019 18:06:17 -0400 Subject: [PATCH 04/11] added comment, grayscale download now works, just need to use heightmap --- gui.js | 1 + 1 file changed, 1 insertion(+) diff --git a/gui.js b/gui.js index 36c0e09f52..9b406734fd 100644 --- a/gui.js +++ b/gui.js @@ -7109,6 +7109,7 @@ function doActualExtrusionOfImage(pathToImgWeWantToExtrude, x, y) { console.log(myNewImage.width); console.log(myNewImage.height); + // We are creating a temp a tag to hold the image above which we created from our temp canvas above let a = document.createElement('a'); a.href = myNewImage.src; a.download = "image.png"; From 99d8f4a190b887c3e38443c3cdd1285c9dffd806 Mon Sep 17 00:00:00 2001 From: chinedu amadi-ndukwe Date: Thu, 11 Apr 2019 13:29:30 -0400 Subject: [PATCH 05/11] added closure function to get heightMap of given image --- .idea/workspace.xml | 37 +++++++++++++++++++++++- gui.js | 68 ++++++++++++++++++++++++++------------------- 2 files changed, 75 insertions(+), 30 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index ae67262cf6..4d50d107cf 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,7 +2,7 @@ - + +<<<<<<< Updated upstream +<<<<<<< Updated upstream +======= + +>>>>>>> Stashed changes @@ -1120,8 +1141,13 @@ +<<<<<<< Updated upstream +======= + + +>>>>>>> Stashed changes @@ -2139,8 +2165,17 @@ +<<<<<<< Updated upstream +======= + + + + + + +>>>>>>> Stashed changes diff --git a/gui.js b/gui.js index 9b406734fd..4e95f9fb4d 100644 --- a/gui.js +++ b/gui.js @@ -7073,12 +7073,6 @@ ProjectDialogMorph.prototype.fixClassRoomItemColors = function () { function doActualExtrusionOfImage(pathToImgWeWantToExtrude, x, y) { - console.log("inside the extrusion function"); - console.log(pathToImgWeWantToExtrude); - console.log("now let's log the height and width of the image"); - console.log(pathToImgWeWantToExtrude.width); - console.log(pathToImgWeWantToExtrude.height); - // temporary canvas to hold the image and retrieve its data let tempCanvasToGetImageData = document.createElement('canvas'); let ctx = tempCanvasToGetImageData.getContext("2d"); @@ -7087,12 +7081,6 @@ function doActualExtrusionOfImage(pathToImgWeWantToExtrude, x, y) { ctx.drawImage(pathToImgWeWantToExtrude, 0, 0); // this should draw the image with its intrinsic size let myImageData = ctx.getImageData(x, y, pathToImgWeWantToExtrude.width, pathToImgWeWantToExtrude.height); - console.log(myImageData); - - console.log("my image data data is: "); - console.log(myImageData.data); - console.log(myImageData.width); - console.log(myImageData.height); for (let i=0;i Date: Thu, 11 Apr 2019 15:15:40 -0400 Subject: [PATCH 06/11] added option to export the 2d extrusion as stl, still testing --- gui.js | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/gui.js b/gui.js index 4e95f9fb4d..065ab26b80 100644 --- a/gui.js +++ b/gui.js @@ -7072,6 +7072,8 @@ ProjectDialogMorph.prototype.fixClassRoomItemColors = function () { }; +// Everything below will be moved to a different JS but for now, lets leave it here for debugging + function doActualExtrusionOfImage(pathToImgWeWantToExtrude, x, y) { // temporary canvas to hold the image and retrieve its data let tempCanvasToGetImageData = document.createElement('canvas'); @@ -7099,7 +7101,7 @@ function doActualExtrusionOfImage(pathToImgWeWantToExtrude, x, y) { let a = document.createElement('a'); a.href = myNewImage.src; a.download = "image.png"; - console.log(a); + // console.log(a); // Uncomment code below to allow for download of grayscaled image // document.body.appendChild(a); // a.click(); @@ -7136,6 +7138,36 @@ function doActualExtrusionOfImage(pathToImgWeWantToExtrude, x, y) { let heightMapDataForMyImage = heightMap(pathToImgWeWantToExtrude); console.log("Data returned from inner function is: " + heightMapDataForMyImage); + function createPlaneWithHeightMapData(data) { + let geometry = new THREE.PlaneGeometry(10, 10, 9, 9); + console.log(pathToImgWeWantToExtrude.src); + let texture = new THREE.ImageUtils.loadTexture(pathToImgWeWantToExtrude.src); + let material = new THREE.MeshLambertMaterial( {map: texture} ); + let plane = new THREE.Mesh(geometry, material); + + for (let i = 0; i < plane.geometry.vertices.length; i++){ + plane.geometry.vertices[i].z = data[i]; + } + return plane; + } + // Code below will return a three js plane mesh object from our function above + let returnedPlaneFromOurFunction = createPlaneWithHeightMapData(heightMapDataForMyImage); + console.log(returnedPlaneFromOurFunction); + + //TODO Create a Scene and Add the plane to the scene and export the Scene as STL + try { + let scene = new THREE.Scene(); + scene.add(returnedPlaneFromOurFunction); // Adding our returned plane mesh the function above + + let exporter = new THREE.STLExporter(); + let str = exporter.parse(scene); + + let blobbb = new Blob([str], {type: 'text/plain'}); + saveAs(blobbb, '2D.stl'); + console.log("Exported scene successfully"); + } catch (e) { + console.log("Exception from trying to export the 2D.stl file was: " + e); + } } function extruding2D(myself) { From 8eec8ce73141cefd908b8c75def4dbd0e33c0ff2 Mon Sep 17 00:00:00 2001 From: chinedu amadi-ndukwe Date: Mon, 15 Apr 2019 12:22:38 -0400 Subject: [PATCH 07/11] Added Submenu to menus and moved loading costumes into new submenu --- gui.js | 64 +++++++++++++++-------- morphic.js | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 190 insertions(+), 21 deletions(-) diff --git a/gui.js b/gui.js index 065ab26b80..9e9f1c95a1 100644 --- a/gui.js +++ b/gui.js @@ -2681,14 +2681,14 @@ IDE_Morph.prototype.projectMenu = function () { // // - menu.addItem( - 'Export 2D as 3D STL', - function () { - console.log('Export 2D as STL menu option was clicked'); - let myselfToPassToOurFunction = myself; - extruding2D(myselfToPassToOurFunction); - } - ); + // menu.addItem( + // 'Export 2D as 3D STL', + // function () { + // console.log('Export 2D as STL menu option was clicked'); + // let myselfToPassToOurFunction = myself; + // extruding2D(myselfToPassToOurFunction); + // } + // ); menu.addLine(); @@ -2805,9 +2805,24 @@ IDE_Morph.prototype.projectMenu = function () { 'show different default scripts' ); + let submenu = new MenuMorph(myself); + + // submenu.addItem('Testing', + // function () { + // console.log("submenu worked"); + // }, + // 'testing submenu' + // ); + + menu.addHoverItem( + 'Load Costume... >', + submenu + ); + + if (this.currentSprite instanceof SpriteMorph) { // SpriteMorph - menu.addItem( + submenu.addItem( '2D ' + localize(graphicsName) + '...', function () { @@ -2851,7 +2866,7 @@ IDE_Morph.prototype.projectMenu = function () { 'Select a 2D costume from the media library' ); - menu.addItem( + submenu.addItem( '3D ' + localize(graphicsName) + '...', function () { var dir = config.asset_path + graphicsName + '3D', @@ -7072,7 +7087,7 @@ ProjectDialogMorph.prototype.fixClassRoomItemColors = function () { }; -// Everything below will be moved to a different JS but for now, lets leave it here for debugging +// Everything below will be moved to a different JS file but for now, lets leave it here for debugging function doActualExtrusionOfImage(pathToImgWeWantToExtrude, x, y) { // temporary canvas to hold the image and retrieve its data @@ -7108,13 +7123,15 @@ function doActualExtrusionOfImage(pathToImgWeWantToExtrude, x, y) { // document.body.removeChild(a); // Function below gets our heightMap for a specified image passed in as an argument - function heightMap(image) { + function heightMap(image, scale) { let tempCanvasB = document.createElement( "canvas" ); tempCanvasB.width = image.width; tempCanvasB.height = image.height; let contextB = tempCanvasB.getContext("2d"); let size = image.width * image.height; + console.log(size + " = width * height of given image"); + let data = new Float32Array( size ); contextB.drawImage(image,0,0); @@ -7127,16 +7144,17 @@ function doActualExtrusionOfImage(pathToImgWeWantToExtrude, x, y) { let pix = imgdata.data; let j=0; - for (let i = 0, n = pix.length; i < n; i += (4)) { + for (let i = 0, n = pix.length; i < n; i += 4) { let all = pix[i]+pix[i+1]+pix[i+2]; - data[j++] = all/30; + data[j++] = all/(12 * scale); } return data; } + // Get heightMap for our image - let heightMapDataForMyImage = heightMap(pathToImgWeWantToExtrude); - console.log("Data returned from inner function is: " + heightMapDataForMyImage); + let heightMapDataForMyImage = heightMap(pathToImgWeWantToExtrude, 2); + // console.log("Data returned from inner function is: " + heightMapDataForMyImage); function createPlaneWithHeightMapData(data) { let geometry = new THREE.PlaneGeometry(10, 10, 9, 9); @@ -7147,6 +7165,7 @@ function doActualExtrusionOfImage(pathToImgWeWantToExtrude, x, y) { for (let i = 0; i < plane.geometry.vertices.length; i++){ plane.geometry.vertices[i].z = data[i]; + console.log(data[i]); } return plane; } @@ -7159,12 +7178,15 @@ function doActualExtrusionOfImage(pathToImgWeWantToExtrude, x, y) { let scene = new THREE.Scene(); scene.add(returnedPlaneFromOurFunction); // Adding our returned plane mesh the function above - let exporter = new THREE.STLExporter(); - let str = exporter.parse(scene); + // let exporter = new THREE.STLExporter(); + // let str = exporter.parse(scene); + // + // let blobbb = new Blob([str], {type: 'text/plain'}); + // saveAs(blobbb, '2D.stl'); + // console.log("Exported scene successfully"); - let blobbb = new Blob([str], {type: 'text/plain'}); - saveAs(blobbb, '2D.stl'); - console.log("Exported scene successfully"); + // console.log(returnedPlaneFromOurFunction.geometry.vertices); + console.log(scene.children); } catch (e) { console.log("Exception from trying to export the 2D.stl file was: " + e); } diff --git a/morphic.js b/morphic.js index a9e8ad5358..48970f4252 100644 --- a/morphic.js +++ b/morphic.js @@ -10869,3 +10869,150 @@ WorldMorph.prototype.togglePreferences = function () { MorphicPreferences = standardSettings; } }; + +// Adding hover item +MenuMorph.prototype.addHoverItem = function(labelString, action) { + this.items.push(new MenuHoverItemMorph(localize(labelString || 'close'), action, this)); +}; + +MenuMorph.prototype.drawNew = function () { + var myself = this, + item, + fb, + x, + y, + isLine = false; + + this.children.forEach(function (m) { + m.destroy(); + }); + this.children = []; + if (!this.isListContents) { + this.edge = MorphicPreferences.isFlat ? 0 : 5; + this.border = MorphicPreferences.isFlat ? 1 : 2; + } + this.color = new Color(255, 255, 255); + this.borderColor = new Color(60, 60, 60); + this.silentSetExtent(new Point(0, 0)); + + y = 2; + x = this.left() + 4; + if (!this.isListContents) { + if (this.title) { + this.createLabel(); + this.label.setPosition(this.bounds.origin.add(4)); + this.add(this.label); + y = this.label.bottom(); + } else { + y = this.top() + 4; + } + } + y += 1; + this.items.forEach(function (tuple) { + isLine = false; + if (tuple instanceof StringFieldMorph || + tuple instanceof ColorPickerMorph || + tuple instanceof SliderMorph || + tuple instanceof MenuHoverItemMorph) { // added + item = tuple; + } else if (tuple[0] === 0) { + isLine = true; + item = new Morph(); + item.color = myself.borderColor; + item.setHeight(tuple[1]); + } else { + item = new MenuItemMorph( + myself.target, + tuple[1], + tuple[0], + myself.fontSize || MorphicPreferences.menuFontSize, + MorphicPreferences.menuFontName, + myself.environment, + tuple[2], // bubble help hint + tuple[3], // color + tuple[4], // bold + tuple[5], // italic + tuple[6] // doubleclick action + ); + } + if (isLine) { + y += 1; + } + item.setPosition(new Point(x, y)); + myself.add(item); + y = y + item.height(); + if (isLine) { + y += 1; + } + }); + + fb = this.fullBounds(); + this.silentSetExtent(fb.extent().add(4)); + this.adjustWidths(); + MenuMorph.uber.drawNew.call(this); +}; + +var MenuHoverItemMorph; +MenuHoverItemMorph.prototype = new MenuItemMorph(); +MenuHoverItemMorph.prototype.constructor = MenuHoverItemMorph; +MenuHoverItemMorph.uber = MenuItemMorph.prototype; + +function MenuHoverItemMorph(labelString, submenu, parentMenu) { + var myself = this; + + this.submenu = submenu; + this.parentMenu = parentMenu; + + this.init( + parentMenu.target, + myself.revealSubmenu, + labelString, + parentMenu.fontSize, + MorphicPreferences.menuFontName, + parentMenu.environment, + null, + null, + false, + false, + null + ); +}; + +MenuHoverItemMorph.prototype.revealSubmenu = function() { + var myself = this; + + this.image = this.highlightImage; + this.submenu.drawNew(); + this.submenu.setPosition(this.topRight()); + this.submenu.addShadow(new Point(2, 2), 80); + this.submenu.keepWithin(world); + if (this.submenu.items.length < 1 && !this.submenu.title) { // don't show empty menus + return; + } + world.add(this.submenu); + world.activeMenu = this.submenu; + this.submenu.world = world; // optionally enable keyboard support + this.submenu.fullChanged(); + this.changed(); + + this.submenu.mouseLeave = function() { + this.destroy(); + if (!myself.boundingBox().containsPoint(world.hand.position())) { + myself.image = myself.normalImage; + myself.changed(); + } + world.activeMenu = myself.parentMenu; + } +}; + +MenuHoverItemMorph.prototype.mouseEnter = MenuHoverItemMorph.prototype.revealSubmenu; +MenuHoverItemMorph.prototype.mouseClickLeft = MenuHoverItemMorph.prototype.revealSubmenu; + +MenuHoverItemMorph.prototype.mouseLeave = function() { + if (!this.submenu.boundingBox().containsPoint(world.hand.position())) { + this.submenu.destroy(); + this.image = this.normalImage; + this.changed(); + world.activeMenu = this.parentMenu; + } +}; From 5c407bbed730d7cba5904256b732d6e21df68c3a Mon Sep 17 00:00:00 2001 From: chinedu amadi-ndukwe Date: Wed, 24 Apr 2019 07:00:26 -0400 Subject: [PATCH 08/11] removed functions that do extrusion, will run those in a different project before bringing them into CSnap --- gui.js | 115 --------------------------------------------------------- 1 file changed, 115 deletions(-) diff --git a/gui.js b/gui.js index 9e9f1c95a1..8643654e5a 100644 --- a/gui.js +++ b/gui.js @@ -7085,118 +7085,3 @@ ProjectDialogMorph.prototype.fixClassRoomItemColors = function () { item.noticesTransparentClick = true; }); }; - - -// Everything below will be moved to a different JS file but for now, lets leave it here for debugging - -function doActualExtrusionOfImage(pathToImgWeWantToExtrude, x, y) { - // temporary canvas to hold the image and retrieve its data - let tempCanvasToGetImageData = document.createElement('canvas'); - let ctx = tempCanvasToGetImageData.getContext("2d"); - tempCanvasToGetImageData.width = pathToImgWeWantToExtrude.width; - tempCanvasToGetImageData.height = pathToImgWeWantToExtrude.height; - ctx.drawImage(pathToImgWeWantToExtrude, 0, 0); // this should draw the image with its intrinsic size - - let myImageData = ctx.getImageData(x, y, pathToImgWeWantToExtrude.width, pathToImgWeWantToExtrude.height); - - for (let i=0;i Date: Wed, 24 Apr 2019 12:31:14 -0400 Subject: [PATCH 09/11] readded the extruding function, still testing python way of extruding the image with numpy etc --- gui.js | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 129 insertions(+), 16 deletions(-) diff --git a/gui.js b/gui.js index 8643654e5a..8e38df3444 100644 --- a/gui.js +++ b/gui.js @@ -2603,6 +2603,128 @@ IDE_Morph.prototype.settingsMenu = function () { menu.popup(world, pos); }; + +// Everything below will be moved to a different JS file but for now, lets leave it here for debugging +// function doActualExtrusionOfImage(pathToImgWeWantToExtrude, x, y) { +// // temporary canvas to hold the image and retrieve its data +// let tempCanvasToGetImageData = document.createElement('canvas'); +// let ctx = tempCanvasToGetImageData.getContext("2d"); +// tempCanvasToGetImageData.width = pathToImgWeWantToExtrude.width; +// tempCanvasToGetImageData.height = pathToImgWeWantToExtrude.height; +// ctx.drawImage(pathToImgWeWantToExtrude, 0, 0); // this should draw the image with its intrinsic size +// +// let myImageData = ctx.getImageData(x, y, pathToImgWeWantToExtrude.width, pathToImgWeWantToExtrude.height); +// +// for (let i=0;i Date: Mon, 8 Jul 2019 10:35:00 -0400 Subject: [PATCH 10/11] can finally render image (simply use fullImageClassic); need to update journal --- STLExporter.js | 65 +++++++++++++++++++++++++---- gui.js | 111 ++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 145 insertions(+), 31 deletions(-) diff --git a/STLExporter.js b/STLExporter.js index 5c1ddc1ada..dfb2f1fb50 100644 --- a/STLExporter.js +++ b/STLExporter.js @@ -12,6 +12,13 @@ * */ +//this code is last done by Jimmy Ruan +//reach me @ 773-280-1417 +// jiruan@umich.edu (may or may not be reachable after I graduated) + +// Jimmy's note: the original code seems like it's pulled from Three.js's example code +// at https://github.com/mrdoob/three.js/blob/master/examples/js/exporters/STLExporter.js + THREE.STLExporter = function () {}; THREE.STLExporter.prototype = { @@ -19,18 +26,60 @@ THREE.STLExporter.prototype = { constructor: THREE.STLExporter, parse: ( function () { - +/* var vector = new THREE.Vector3(); var normalMatrixWorld = new THREE.Matrix3(); - - return function parse( scene, options ) { - - if ( options === undefined ) options = {}; +*/ + return function parse( image, directory, filename, options ) { + //simply sends the image to the backend to let it process the STL file + //then send a request for the STL file, subsequently saving the resulting received file + //parameter: + // image [required](data URI): the url of the image (converted using toDataURL or the like) + // directory [required](str): the directory the STL file should be saved to + // filename (str): the filename to name the STL file as + // *NOTE: TODO: filename may not be needed as it can be sent via the resulting request + // options: various options specifying parameters to create the STL file with + // TODO: do something with options + + // + //simply prints the string into console + //copy the URL into the address bar itself during debugging + //the url should display the image of the stage by entering it into the address bar + console.log("IMAGE URL:\n" + image); + console.log("\n\nSending image url into " + directory); + + //send post request to backend with data url + //should receive the STL model as a response + fetch(modelURL, + { + method: "POST", + body: image //note to future self: this is the form data + //change the form data however you like to fit backend + //try not to do the other way around + //mode: whatever value gets rid of cors error + //may or may not need to change mode to avoid cross site origin security error + + //add other stuff here + //reference: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch + } + ) + .then(function() { //now we get the resulting STL file + let STLBlob = fetch(directory); + saveAs(STLBlob, filename); //this should download the file + // modelFileName should only contain the end part of the URL; + //TODO: save stl here + }) + .catch(function() { + console.log("Failed to send image to " + directory); + //TODO: insert more error messages as needed + }); + // + +/* + // var binary = options.binary !== undefined ? options.binary : false; - // - var objects = []; var triangles = 0; @@ -158,7 +207,9 @@ THREE.STLExporter.prototype = { return output; } + // +*/ }; }() ) diff --git a/gui.js b/gui.js index 8e38df3444..36a34a4f01 100644 --- a/gui.js +++ b/gui.js @@ -2780,28 +2780,28 @@ IDE_Morph.prototype.projectMenu = function () { menu.addItem('Save As...', 'saveProjectsBrowser'); // // Button to save project as STL for 3D printing - // menu.addItem('Export as STL', - // function (){ - // console.log("Exporting project as STL for 3D printing"); - // // Below we call our costume function and pass in the name of the project + menu.addItem('Export as STL', + function (){ + console.log("Exporting project as STL for 3D printing"); + // Below we call our costume function and pass in the name of the project // console.log("my project name is " + myself.projectName); - // try { - // this.exportProjectAsSTL(); - // } catch (e) { - // console.log("Error trying to export file was " + e); - // } - // }); + try { + this.exportProjectAsSTL(); + } catch (e) { + console.log("Error trying to export file was " + e); + } + }); // - menu.addItem( - 'Export 2D as 3D STL', - function () { - let myselfToPassToOurFunction = myself; - extruding2D(myselfToPassToOurFunction); - } - ); + //menu.addItem( + // 'Export 2D as 3D STL', + // function () { + // let myselfToPassToOurFunction = myself; + // extruding2D(myselfToPassToOurFunction); + // } + //); menu.addLine(); @@ -4346,21 +4346,41 @@ IDE_Morph.prototype.exportProjectAsSTL = function () { console.log(world); try { menu = this.showMessage('Exporting as STL'); - let scene = copy(this.stage.scene); - // console.log("Scene is: " + scene); + + let stage = this.children[4]; + //can't really guarantee that it'll always be the 4th child, but w/e + + console.log("rendering image..."); + let image = stage.fullImageClassic().toDataURL(); + //NOTE: fullImageClassic is what actually renders the image + + let filename = this.projectName; + console.log("filename = " + filename); + + let directory = "" + filename; + console.log("directory set at: " + directory); + //change directory as needed here + + let STL_options = {}; + //TODO: adjust STL conversion options here + + console.log("initializing STL exporter..."); let exporter = new THREE.STLExporter(); - // console.log("Exporter: " + exporter); - let exportedScene = exporter.parse(scene); + console.log("parsing image..."); + let exportedScene = exporter.parse(image, directory, filename, STL_options); + let blob = new Blob( [exportedScene], { type: 'text/plain'}); + + console.log("saving file as " + modelFileName); saveAs(blob, (this.projectName ? this.projectName : '3DCSDT') + '.stl'); menu.destroy(); this.showMessage('Exported!', 1); } catch (err) { this.showMessage('Export failed: ' + err); - console.log(err) + console.log("Export error: " + err); } }; @@ -5912,7 +5932,6 @@ SpriteIconMorph.prototype.init = function (aSprite, aTemplate) { IDE_Morph.prototype.frameColor, IDE_Morph.prototype.frameColor ]; - } action = function () { @@ -6108,12 +6127,56 @@ SpriteIconMorph.prototype.userMenu = function () { menu.addItem( 'pic...', function () { - world.children[0].saveFileAs(myself.object.fullImageClassic().toDataURL(), 'image/png', world.children[0].projetName + ' Stage'); + world.children[0].saveFileAs(myself.object.fullImageClassic().toDataURL(), 'image/png', world.children[0].projectName + ' Stage'); }, 'open a new window\nwith a picture of the stage' ); + +//this code is last done by Jimmy Ruan +//reach me @ 773-280-1417 +// jiruan@umich.edu (may or may not be reachable after I graduated) + + //Adds a menu option to export the stage rendering as an STL + // + menu.addItem( + "export as STL", + function() { + try { + console.log("rendering image..."); + let renderedImageURL = myself.object.fullImageClassic().toDataURL(); + //NOTE: fullImageClassic is what actually renders the image + let modelFileName = world.children[0].projectName + ".stl"; + console.log("filename = " + modelFileName); + + let modelURL = "test.stl"; + //let modelURL = [directory] + modelFileName; //change directory to point to where STL files are stored; + //eg: adinkra.stl if project name is adinkra + console.log("directory set at: " + modelURL); + + let STL_options = {}; + //TODO: adjust STL options here + + console.log("initializing STL exporter..."); + let exporter = new STLExporter(); + + console.log("parsing image..."); + let STLFile = exporter.parse(renderedImageURL, modelURL, modelFileName, STL_options); + } catch (err) { + console.log("Export error: " + err); + } + + let blob = new Blob( [STLFile], { type: 'model/stl'}); + + console.log("saving file as " + modelFileName); + saveAs(blob, modelFileName); + }, + "render the stage and turn it into an STL file" + ); + // + return menu; } + if (!(this.object instanceof SpriteMorph)) {return null; } menu.addItem("show", 'showSpriteOnStage'); menu.addLine(); From b72b0557d81f062ee29bf5fa56e912970c14808e Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 18 Aug 2019 18:59:53 -0400 Subject: [PATCH 11/11] final commit; gui.js has the menu option added to export project to STL, which calls ExportProjectAsSTL(), which then calls the parse() function in the STLExporter object in STLExporter.js. The overall setup will render the image from the stage (via StageMorph), turns it into an image uri, and sends a POST request containing the image uri and some STL optionsto a specified url. Control is then passed to django to render and point the user to the resulting STL file via that specific url. --- STLExporter.js | 17 ++++++++++------- csnap.html | 3 ++- gui.js | 20 +++++++++++++------- morphic.js | 5 ++--- 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/STLExporter.js b/STLExporter.js index dfb2f1fb50..49b34adb4c 100644 --- a/STLExporter.js +++ b/STLExporter.js @@ -50,7 +50,7 @@ THREE.STLExporter.prototype = { //send post request to backend with data url //should receive the STL model as a response - fetch(modelURL, + fetch(directory, { method: "POST", body: image //note to future self: this is the form data @@ -64,14 +64,17 @@ THREE.STLExporter.prototype = { } ) .then(function() { //now we get the resulting STL file - let STLBlob = fetch(directory); - saveAs(STLBlob, filename); //this should download the file - // modelFileName should only contain the end part of the URL; - //TODO: save stl here + fetch(directory) + .then(function(response) { + return response.blob(); + }) + .then(function(STLBlob) { + saveAs(STLBlob, filename); //this should download the file + }); }) - .catch(function() { + .catch(function(errorMessage) { console.log("Failed to send image to " + directory); - //TODO: insert more error messages as needed + console.log("Error: " + errorMessage); }); // diff --git a/csnap.html b/csnap.html index 0d8095ef4d..5c0c4210a3 100644 --- a/csnap.html +++ b/csnap.html @@ -4,6 +4,7 @@ CSnap - Snap! with culture + --> diff --git a/gui.js b/gui.js index 36a34a4f01..df0812f072 100644 --- a/gui.js +++ b/gui.js @@ -4343,7 +4343,7 @@ IDE_Morph.prototype.exportProject = function (name, plain) { IDE_Morph.prototype.exportProjectAsSTL = function () { let menu; // Testing to see what world is - console.log(world); + // console.log(world); try { menu = this.showMessage('Exporting as STL'); @@ -4355,7 +4355,7 @@ IDE_Morph.prototype.exportProjectAsSTL = function () { let image = stage.fullImageClassic().toDataURL(); //NOTE: fullImageClassic is what actually renders the image - let filename = this.projectName; + let filename = this.projectName + ".stl"; console.log("filename = " + filename); let directory = "" + filename; @@ -4368,19 +4368,22 @@ IDE_Morph.prototype.exportProjectAsSTL = function () { console.log("initializing STL exporter..."); let exporter = new THREE.STLExporter(); - console.log("parsing image..."); - let exportedScene = exporter.parse(image, directory, filename, STL_options); + console.log("parsing image..."); //directory, filename + exporter.parse(image, "test.stl", "test.stl", STL_options); +/* + let exportedScene = exporter.parse(image, "test.stl", "test.stl", STL_options); let blob = new Blob( [exportedScene], { type: 'text/plain'}); - console.log("saving file as " + modelFileName); + console.log("saving file as " + filename); saveAs(blob, (this.projectName ? this.projectName : '3DCSDT') + '.stl'); +*/ menu.destroy(); this.showMessage('Exported!', 1); } catch (err) { this.showMessage('Export failed: ' + err); - console.log("Export error: " + err); + console.log("Export error: " + err); } }; @@ -6160,15 +6163,18 @@ SpriteIconMorph.prototype.userMenu = function () { let exporter = new STLExporter(); console.log("parsing image..."); - let STLFile = exporter.parse(renderedImageURL, modelURL, modelFileName, STL_options); + exporter.parse(renderedImageURL, modelURL, modelFileName, STL_options); } catch (err) { console.log("Export error: " + err); } + /* let blob = new Blob( [STLFile], { type: 'model/stl'}); console.log("saving file as " + modelFileName); saveAs(blob, modelFileName); + */ + }, "render the stage and turn it into an STL file" ); diff --git a/morphic.js b/morphic.js index 48970f4252..9b12c647ea 100644 --- a/morphic.js +++ b/morphic.js @@ -2570,7 +2570,7 @@ Morph.prototype.drawNew = function () { this.drawCachedTexture(); } else if (this.texture) { this.drawTexture(this.texture); - } else if (source != undefined && this.isIcon){ + } else if (source != undefined && this.isIcon) { context.drawImage(source, 0, 0); } }; @@ -3449,6 +3449,7 @@ Morph.prototype.developersMenu = function () { }, 'open a new window\nwith a picture of this morph' ); + menu.addLine(); if (this.isDraggable) { menu.addItem( @@ -4043,7 +4044,6 @@ PenMorph.prototype.drawNew = function (facing) { context.lineWidth = 1; context.stroke(); context.fill(); - }; // PenMorph access: @@ -5523,7 +5523,6 @@ SliderButtonMorph.prototype.drawNew = function () { this.color = colorBak; this.image = this.normalImage; - }; SliderButtonMorph.prototype.drawEdges = function () {