From 7ce9019afb67f78f36e335be11ffc3b59b71e47b Mon Sep 17 00:00:00 2001 From: RebornOfc Date: Wed, 27 Dec 2023 16:47:36 +0000 Subject: [PATCH 1/2] Automated Extension submission for issue #1130 --- extensions/community/UploadDownloadImageFile.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 extensions/community/UploadDownloadImageFile.json diff --git a/extensions/community/UploadDownloadImageFile.json b/extensions/community/UploadDownloadImageFile.json new file mode 100644 index 000000000..0e0843abc --- /dev/null +++ b/extensions/community/UploadDownloadImageFile.json @@ -0,0 +1 @@ +{"author":"","category":"Advanced","extensionNamespace":"","fullName":"Upload Download Image File","helpPath":"","iconUrl":"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyMy4wLjMsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iSWNvbnMiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgMzIgMzIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDMyIDMyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCS5zdDB7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9DQoJLnN0MXtmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjI7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO30NCgkuc3Qye2ZpbGw6bm9uZTtzdHJva2U6IzAwMDAwMDtzdHJva2Utd2lkdGg6MjtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLWRhc2hhcnJheTo2LDY7fQ0KCS5zdDN7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtZGFzaGFycmF5OjQsNDt9DQoJLnN0NHtmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjI7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7fQ0KCS5zdDV7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1kYXNoYXJyYXk6My4xMDgxLDMuMTA4MTt9DQoJDQoJCS5zdDZ7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2UtZGFzaGFycmF5OjQsMzt9DQo8L3N0eWxlPg0KPHBhdGggY2xhc3M9InN0MCIgZD0iTTI3LDIzLjJWOC44YzEuMi0wLjQsMi0xLjUsMi0yLjhjMC0xLjctMS4zLTMtMy0zYy0xLjMsMC0yLjQsMC44LTIuOCwySDguOEM4LjQsMy44LDcuMywzLDYsM0M0LjMsMywzLDQuMywzLDYNCgljMCwxLjMsMC44LDIuNCwyLDIuOHYxNC40Yy0xLjIsMC40LTIsMS41LTIsMi44YzAsMS43LDEuMywzLDMsM2MxLjMsMCwyLjQtMC44LDIuOC0yaDE0LjRjMC40LDEuMiwxLjUsMiwyLjgsMmMxLjcsMCwzLTEuMywzLTMNCglDMjksMjQuNywyOC4yLDIzLjYsMjcsMjMuMnoiLz4NCjxyZWN0IHg9IjkiIHk9IjkiIGNsYXNzPSJzdDAiIHdpZHRoPSIxNCIgaGVpZ2h0PSIxNCIvPg0KPGNpcmNsZSBjbGFzcz0ic3QwIiBjeD0iMTMiIGN5PSIxMyIgcj0iMSIvPg0KPHBvbHlsaW5lIGNsYXNzPSJzdDAiIHBvaW50cz0iOSwyMCAxNiwxNiAyMCwxOSAyMywxNyAiLz4NCjwvc3ZnPg0K","name":"UploadDownloadImageFile","previewIconUrl":"https://asset-resources.gdevelop.io/public-resources/Icons/Line Hero Pack/Master/SVG/Graphic Design/4090f6ed8baf469e1d3c78b1bc636e52e6a9dd9f47d0eb78865a4f659c2f917a_Graphic Design_picture.svg","shortDescription":"Allows the upload of an image from the gallery, from a base64 encoded image, and the download of images.","version":"0.0.0","description":["Allows the upload of an image from the gallery, from a base64 string, and the download of images.","","Content:","- The action **Upload image from gallery**.","- The action **Load a base64 encoded image**.","- The action **Download object image**.","","Do note that the object's resource is replaced with the picture, meaning that every object sharing the same resource as the receiver one will also display the picture."],"tags":["upload","download","image","gallery","file","manager","picture","photo"],"authorIds":["OaVzVu7cuKhv5Qj0i3vRZYFttl72"],"dependencies":[],"eventsFunctions":[{"description":"Upload an image from the device to an object.","fullName":"Upload an image from device","functionType":"Action","group":"Image Tools","name":"UploadImageFile","sentence":"Upload an image from the device to _PARAM1_ (update size: _PARAM2_, save as base64 in _PARAM3_, width in _PARAM4_ and height in _PARAM5_)","events":[{"type":"BuiltinCommonInstructions::JsCode","inlineCode":["//Create a place to store the images somewhere, because we need to know if the user wants to upload the same image, or a new one.","if (!gdjs._ExtensionUploadedImages) {"," gdjs._ExtensionUploadedImages = new Map();","}","","//Save the old proportions.","const oldWidth = objects[0].getWidth();","const oldHeight = objects[0].getHeight();","","//Check if want to modify the object size to match the image.","const modifySize = eventsFunctionContext.getArgument(\"ModifySize\");","","//Create a image upload element and simulate a click on it.","const inputElement = document.createElement('input');","inputElement.type = \"file\";","inputElement.accept = \"image/*\"","inputElement.addEventListener(\"change\", handleFiles, false);","inputElement.click();","","//Handle the image upload.","async function handleFiles() {"," const files = this.files;"," "," if (!files.length) {} else {"," // Create a FileReader object to read the file as a data URL."," const reader = new FileReader();"," reader.onload = async function(e) {"," // Get the base64 string from the data URL, and store it in a scene variable if intended."," const base64 = e.target.result;"," if (eventsFunctionContext.getArgument(\"StoreBase\")) {"," eventsFunctionContext.getArgument(\"StoreBase\").setString(base64)"," }",""," // Create a PIXI texture from the base64 string if one doesn't exist yet."," if (!gdjs._ExtensionUploadedImages.has(base64)) {"," let newTexture = PIXI.Texture.from(base64);"," // Use a callback function that runs after the image is loaded, to ensure that it is properly stored."," newTexture.on(\"update\", function() {"," gdjs._ExtensionUploadedImages.set(base64,[newTexture,newTexture.width,newTexture.height]);"," //Change the object image, and optionally its proportions."," const savedTexture = gdjs._ExtensionUploadedImages.get(base64);"," objects[0].getRendererObject().texture.baseTexture = newTexture;",""," if (modifySize == true) {"," objects[0].setWidth(newTexture.orig.width);"," objects[0].setHeight(newTexture.orig.height);"," }"," "," if (modifySize == false) {"," objects[0].setWidth(oldWidth);"," objects[0].setHeight(oldHeight);"," }",""," //Store the proportions in scene variables if intended."," if (eventsFunctionContext.getArgument(\"ImageWidth\")) {"," eventsFunctionContext.getArgument(\"ImageWidth\").setNumber(newTexture.width);"," }",""," if (eventsFunctionContext.getArgument(\"ImageHeight\")) {"," eventsFunctionContext.getArgument(\"ImageHeight\").setNumber(newTexture.height);"," }"," });"," } else {"," //Change the object image, and optionally its proportions."," const savedTexture = gdjs._ExtensionUploadedImages.get(base64);"," objects[0].getRendererObject().texture.baseTexture = savedTexture[0];"," "," if (modifySize == true) {"," objects[0].setWidth(savedTexture[1]);"," objects[0].setHeight(savedTexture[2]);"," }",""," if (modifySize == false) {"," objects[0].setWidth(oldWidth);"," objects[0].setHeight(oldHeight);"," }",""," //Store the proportions in scene variables if intended."," if (eventsFunctionContext.getArgument(\"ImageWidth\")) {"," eventsFunctionContext.getArgument(\"ImageWidth\").setNumber(savedTexture[1]);"," }",""," if (eventsFunctionContext.getArgument(\"ImageHeight\")) {"," eventsFunctionContext.getArgument(\"ImageHeight\").setNumber(savedTexture[2]);"," }"," }"," }"," reader.readAsDataURL(files[0]);"," }"," inputElement.remove();","}"],"parameterObjects":"Object","useStrict":true,"eventsSheetExpanded":false}],"parameters":[{"description":"Object to recieve the image","name":"Object","type":"objectList"},{"defaultValue":"yes","description":"Modify the size of the object to match the image?","name":"ModifySize","optional":true,"supplementaryInformation":"Lighting::LightObject","type":"yesorno"},{"description":"(Optional) Scene variable to save the image encoded as base64","longDescription":"Leave empty to ignore, use this if you want to storage the image in a save and load system.","name":"StoreBase","type":"scenevar"},{"description":"(Optional) Scene variable to save the image width","name":"ImageWidth","type":"scenevar"},{"description":"(Optional) Scene variable to save the image height","name":"ImageHeight","type":"scenevar"}],"objectGroups":[]},{"description":"Load a base64 encoded image to an object.\n\nIts recommended to keep the base64 string stored in a string variable, otherwise you will have a bad experience navigating the eventsheet.","fullName":"Load a base64 encoded image","functionType":"Action","group":"Image Tools","name":"LoadBase64Image","sentence":"Load the base64 image from the string _PARAM3_ to _PARAM1_ (update size: _PARAM2_, save width in _PARAM4_ and height in _PARAM5_)","events":[{"type":"BuiltinCommonInstructions::JsCode","inlineCode":["//Create a place to store the images somewhere, because we need to know if the user wants to upload the same image, or a new one.","if (!gdjs._ExtensionUploadedImages) {"," gdjs._ExtensionUploadedImages = new Map();","}","","//Store old width and height of object.","const oldWidth = objects[0].getWidth();","const oldHeight = objects[0].getHeight();","","//Check if want to modify the object size to match the image.","const modifySize = eventsFunctionContext.getArgument(\"ModifySize\");","","// Get the base64 string.","const base64 = eventsFunctionContext.getArgument(\"Base64\");","","// Create a function that returns a promise that resolves when the image is loaded","function loadImage(base64) {"," return new Promise((resolve, reject) => {"," // Create a PIXI texture from the base64 string if one doesn't exist."," if (!gdjs._ExtensionUploadedImages.has(base64)) {"," let newTexture = PIXI.Texture.from(base64);"," // Create an image object from the texture"," let image = new Image();"," // Set the image source to the texture baseTexture"," image.src = newTexture.baseTexture.resource.url;"," // Use the onload event to resolve the promise"," image.onload = () => {"," // Save the texture and its dimensions in the map"," gdjs._ExtensionUploadedImages.set(base64,[newTexture,image.width,image.height]);"," // Resolve the promise with the texture"," resolve(newTexture);"," };"," // Use the onerror event to reject the promise"," image.onerror = () => {"," reject(new Error(\"Failed to load image\"));"," };"," } else {"," // Resolve the promise with the existing texture"," resolve(gdjs._ExtensionUploadedImages.get(base64)[0]);"," }"," });","}","","// Call the loadImage function and use the then and catch methods to handle the promise","loadImage(base64).then((newTexture) => {",""," objects[0].getRendererObject().texture.baseTexture = newTexture;"," "," //Change the object image, and optionally its proportions."," if (modifySize == true) {"," objects[0].setWidth(newTexture.orig.width);"," objects[0].setHeight(newTexture.orig.height);"," }"," "," if (modifySize == false) {"," objects[0].setWidth(oldWidth);"," objects[0].setHeight(oldHeight);"," }",""," //Store the proportions in scene variables if intended."," if (eventsFunctionContext.getArgument(\"ImageWidth\")) {"," eventsFunctionContext.getArgument(\"ImageWidth\").setNumber(newTexture.width);"," }",""," if (eventsFunctionContext.getArgument(\"ImageHeight\")) {"," eventsFunctionContext.getArgument(\"ImageHeight\").setNumber(newTexture.height);"," }","","}).catch((error) => {"," // Handle the error"," console.error(error);","});",""],"parameterObjects":"Object","useStrict":true,"eventsSheetExpanded":true}],"parameters":[{"description":"Object","name":"Object","type":"objectList"},{"defaultValue":"yes","description":"Modify the size of the object to match the image?","name":"ModifySize","optional":true,"supplementaryInformation":"Lighting::LightObject","type":"yesorno"},{"description":"Image encoded as base64","name":"Base64","type":"string"},{"description":"(Optional) Scene variable to save the image width","name":"ImageWidth","type":"scenevar"},{"description":"(Optional) Scene variable to save the image height","name":"ImageHeight","type":"scenevar"}],"objectGroups":[]},{"description":"Download the current displayed image of an object as a png file.","fullName":"Download image","functionType":"Action","group":"Image Tools","name":"DownloadImage","sentence":"Download an image out of _PARAM1_","events":[{"type":"BuiltinCommonInstructions::JsCode","inlineCode":["const renderer = runtimeScene.getGame().getRenderer().getPIXIRenderer();","const sprite = objects[0].getRendererObject();","const fileName = \"test\";","","renderer.extract.canvas(sprite).toBlob(function(b){","\t\tvar a = document.createElement('a');","\t\tdocument.body.append(a);","\t\ta.download = fileName;","\t\ta.href = URL.createObjectURL(b);","\t\ta.click();","\t\ta.remove();","\t}, 'image/png');","",""],"parameterObjects":"Object","useStrict":true,"eventsSheetExpanded":false}],"parameters":[{"description":"Object","name":"Object","type":"objectList"}],"objectGroups":[]}],"eventsBasedBehaviors":[],"eventsBasedObjects":[]} \ No newline at end of file From fcc5611ed20ad055c33ba2c1a002a8179042dae4 Mon Sep 17 00:00:00 2001 From: RebornOfc Date: Fri, 26 Jan 2024 18:43:38 +0000 Subject: [PATCH 2/2] Updated extension --- .../community/UploadDownloadImageFile.json | 582 +++++++++++++++++- 1 file changed, 581 insertions(+), 1 deletion(-) diff --git a/extensions/community/UploadDownloadImageFile.json b/extensions/community/UploadDownloadImageFile.json index 0e0843abc..10a33b623 100644 --- a/extensions/community/UploadDownloadImageFile.json +++ b/extensions/community/UploadDownloadImageFile.json @@ -1 +1,581 @@ -{"author":"","category":"Advanced","extensionNamespace":"","fullName":"Upload Download Image File","helpPath":"","iconUrl":"data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyMy4wLjMsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iSWNvbnMiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgMzIgMzIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDMyIDMyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCS5zdDB7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9DQoJLnN0MXtmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjI7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO30NCgkuc3Qye2ZpbGw6bm9uZTtzdHJva2U6IzAwMDAwMDtzdHJva2Utd2lkdGg6MjtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLWRhc2hhcnJheTo2LDY7fQ0KCS5zdDN7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtZGFzaGFycmF5OjQsNDt9DQoJLnN0NHtmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjI7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7fQ0KCS5zdDV7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1kYXNoYXJyYXk6My4xMDgxLDMuMTA4MTt9DQoJDQoJCS5zdDZ7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2UtZGFzaGFycmF5OjQsMzt9DQo8L3N0eWxlPg0KPHBhdGggY2xhc3M9InN0MCIgZD0iTTI3LDIzLjJWOC44YzEuMi0wLjQsMi0xLjUsMi0yLjhjMC0xLjctMS4zLTMtMy0zYy0xLjMsMC0yLjQsMC44LTIuOCwySDguOEM4LjQsMy44LDcuMywzLDYsM0M0LjMsMywzLDQuMywzLDYNCgljMCwxLjMsMC44LDIuNCwyLDIuOHYxNC40Yy0xLjIsMC40LTIsMS41LTIsMi44YzAsMS43LDEuMywzLDMsM2MxLjMsMCwyLjQtMC44LDIuOC0yaDE0LjRjMC40LDEuMiwxLjUsMiwyLjgsMmMxLjcsMCwzLTEuMywzLTMNCglDMjksMjQuNywyOC4yLDIzLjYsMjcsMjMuMnoiLz4NCjxyZWN0IHg9IjkiIHk9IjkiIGNsYXNzPSJzdDAiIHdpZHRoPSIxNCIgaGVpZ2h0PSIxNCIvPg0KPGNpcmNsZSBjbGFzcz0ic3QwIiBjeD0iMTMiIGN5PSIxMyIgcj0iMSIvPg0KPHBvbHlsaW5lIGNsYXNzPSJzdDAiIHBvaW50cz0iOSwyMCAxNiwxNiAyMCwxOSAyMywxNyAiLz4NCjwvc3ZnPg0K","name":"UploadDownloadImageFile","previewIconUrl":"https://asset-resources.gdevelop.io/public-resources/Icons/Line Hero Pack/Master/SVG/Graphic Design/4090f6ed8baf469e1d3c78b1bc636e52e6a9dd9f47d0eb78865a4f659c2f917a_Graphic Design_picture.svg","shortDescription":"Allows the upload of an image from the gallery, from a base64 encoded image, and the download of images.","version":"0.0.0","description":["Allows the upload of an image from the gallery, from a base64 string, and the download of images.","","Content:","- The action **Upload image from gallery**.","- The action **Load a base64 encoded image**.","- The action **Download object image**.","","Do note that the object's resource is replaced with the picture, meaning that every object sharing the same resource as the receiver one will also display the picture."],"tags":["upload","download","image","gallery","file","manager","picture","photo"],"authorIds":["OaVzVu7cuKhv5Qj0i3vRZYFttl72"],"dependencies":[],"eventsFunctions":[{"description":"Upload an image from the device to an object.","fullName":"Upload an image from device","functionType":"Action","group":"Image Tools","name":"UploadImageFile","sentence":"Upload an image from the device to _PARAM1_ (update size: _PARAM2_, save as base64 in _PARAM3_, width in _PARAM4_ and height in _PARAM5_)","events":[{"type":"BuiltinCommonInstructions::JsCode","inlineCode":["//Create a place to store the images somewhere, because we need to know if the user wants to upload the same image, or a new one.","if (!gdjs._ExtensionUploadedImages) {"," gdjs._ExtensionUploadedImages = new Map();","}","","//Save the old proportions.","const oldWidth = objects[0].getWidth();","const oldHeight = objects[0].getHeight();","","//Check if want to modify the object size to match the image.","const modifySize = eventsFunctionContext.getArgument(\"ModifySize\");","","//Create a image upload element and simulate a click on it.","const inputElement = document.createElement('input');","inputElement.type = \"file\";","inputElement.accept = \"image/*\"","inputElement.addEventListener(\"change\", handleFiles, false);","inputElement.click();","","//Handle the image upload.","async function handleFiles() {"," const files = this.files;"," "," if (!files.length) {} else {"," // Create a FileReader object to read the file as a data URL."," const reader = new FileReader();"," reader.onload = async function(e) {"," // Get the base64 string from the data URL, and store it in a scene variable if intended."," const base64 = e.target.result;"," if (eventsFunctionContext.getArgument(\"StoreBase\")) {"," eventsFunctionContext.getArgument(\"StoreBase\").setString(base64)"," }",""," // Create a PIXI texture from the base64 string if one doesn't exist yet."," if (!gdjs._ExtensionUploadedImages.has(base64)) {"," let newTexture = PIXI.Texture.from(base64);"," // Use a callback function that runs after the image is loaded, to ensure that it is properly stored."," newTexture.on(\"update\", function() {"," gdjs._ExtensionUploadedImages.set(base64,[newTexture,newTexture.width,newTexture.height]);"," //Change the object image, and optionally its proportions."," const savedTexture = gdjs._ExtensionUploadedImages.get(base64);"," objects[0].getRendererObject().texture.baseTexture = newTexture;",""," if (modifySize == true) {"," objects[0].setWidth(newTexture.orig.width);"," objects[0].setHeight(newTexture.orig.height);"," }"," "," if (modifySize == false) {"," objects[0].setWidth(oldWidth);"," objects[0].setHeight(oldHeight);"," }",""," //Store the proportions in scene variables if intended."," if (eventsFunctionContext.getArgument(\"ImageWidth\")) {"," eventsFunctionContext.getArgument(\"ImageWidth\").setNumber(newTexture.width);"," }",""," if (eventsFunctionContext.getArgument(\"ImageHeight\")) {"," eventsFunctionContext.getArgument(\"ImageHeight\").setNumber(newTexture.height);"," }"," });"," } else {"," //Change the object image, and optionally its proportions."," const savedTexture = gdjs._ExtensionUploadedImages.get(base64);"," objects[0].getRendererObject().texture.baseTexture = savedTexture[0];"," "," if (modifySize == true) {"," objects[0].setWidth(savedTexture[1]);"," objects[0].setHeight(savedTexture[2]);"," }",""," if (modifySize == false) {"," objects[0].setWidth(oldWidth);"," objects[0].setHeight(oldHeight);"," }",""," //Store the proportions in scene variables if intended."," if (eventsFunctionContext.getArgument(\"ImageWidth\")) {"," eventsFunctionContext.getArgument(\"ImageWidth\").setNumber(savedTexture[1]);"," }",""," if (eventsFunctionContext.getArgument(\"ImageHeight\")) {"," eventsFunctionContext.getArgument(\"ImageHeight\").setNumber(savedTexture[2]);"," }"," }"," }"," reader.readAsDataURL(files[0]);"," }"," inputElement.remove();","}"],"parameterObjects":"Object","useStrict":true,"eventsSheetExpanded":false}],"parameters":[{"description":"Object to recieve the image","name":"Object","type":"objectList"},{"defaultValue":"yes","description":"Modify the size of the object to match the image?","name":"ModifySize","optional":true,"supplementaryInformation":"Lighting::LightObject","type":"yesorno"},{"description":"(Optional) Scene variable to save the image encoded as base64","longDescription":"Leave empty to ignore, use this if you want to storage the image in a save and load system.","name":"StoreBase","type":"scenevar"},{"description":"(Optional) Scene variable to save the image width","name":"ImageWidth","type":"scenevar"},{"description":"(Optional) Scene variable to save the image height","name":"ImageHeight","type":"scenevar"}],"objectGroups":[]},{"description":"Load a base64 encoded image to an object.\n\nIts recommended to keep the base64 string stored in a string variable, otherwise you will have a bad experience navigating the eventsheet.","fullName":"Load a base64 encoded image","functionType":"Action","group":"Image Tools","name":"LoadBase64Image","sentence":"Load the base64 image from the string _PARAM3_ to _PARAM1_ (update size: _PARAM2_, save width in _PARAM4_ and height in _PARAM5_)","events":[{"type":"BuiltinCommonInstructions::JsCode","inlineCode":["//Create a place to store the images somewhere, because we need to know if the user wants to upload the same image, or a new one.","if (!gdjs._ExtensionUploadedImages) {"," gdjs._ExtensionUploadedImages = new Map();","}","","//Store old width and height of object.","const oldWidth = objects[0].getWidth();","const oldHeight = objects[0].getHeight();","","//Check if want to modify the object size to match the image.","const modifySize = eventsFunctionContext.getArgument(\"ModifySize\");","","// Get the base64 string.","const base64 = eventsFunctionContext.getArgument(\"Base64\");","","// Create a function that returns a promise that resolves when the image is loaded","function loadImage(base64) {"," return new Promise((resolve, reject) => {"," // Create a PIXI texture from the base64 string if one doesn't exist."," if (!gdjs._ExtensionUploadedImages.has(base64)) {"," let newTexture = PIXI.Texture.from(base64);"," // Create an image object from the texture"," let image = new Image();"," // Set the image source to the texture baseTexture"," image.src = newTexture.baseTexture.resource.url;"," // Use the onload event to resolve the promise"," image.onload = () => {"," // Save the texture and its dimensions in the map"," gdjs._ExtensionUploadedImages.set(base64,[newTexture,image.width,image.height]);"," // Resolve the promise with the texture"," resolve(newTexture);"," };"," // Use the onerror event to reject the promise"," image.onerror = () => {"," reject(new Error(\"Failed to load image\"));"," };"," } else {"," // Resolve the promise with the existing texture"," resolve(gdjs._ExtensionUploadedImages.get(base64)[0]);"," }"," });","}","","// Call the loadImage function and use the then and catch methods to handle the promise","loadImage(base64).then((newTexture) => {",""," objects[0].getRendererObject().texture.baseTexture = newTexture;"," "," //Change the object image, and optionally its proportions."," if (modifySize == true) {"," objects[0].setWidth(newTexture.orig.width);"," objects[0].setHeight(newTexture.orig.height);"," }"," "," if (modifySize == false) {"," objects[0].setWidth(oldWidth);"," objects[0].setHeight(oldHeight);"," }",""," //Store the proportions in scene variables if intended."," if (eventsFunctionContext.getArgument(\"ImageWidth\")) {"," eventsFunctionContext.getArgument(\"ImageWidth\").setNumber(newTexture.width);"," }",""," if (eventsFunctionContext.getArgument(\"ImageHeight\")) {"," eventsFunctionContext.getArgument(\"ImageHeight\").setNumber(newTexture.height);"," }","","}).catch((error) => {"," // Handle the error"," console.error(error);","});",""],"parameterObjects":"Object","useStrict":true,"eventsSheetExpanded":true}],"parameters":[{"description":"Object","name":"Object","type":"objectList"},{"defaultValue":"yes","description":"Modify the size of the object to match the image?","name":"ModifySize","optional":true,"supplementaryInformation":"Lighting::LightObject","type":"yesorno"},{"description":"Image encoded as base64","name":"Base64","type":"string"},{"description":"(Optional) Scene variable to save the image width","name":"ImageWidth","type":"scenevar"},{"description":"(Optional) Scene variable to save the image height","name":"ImageHeight","type":"scenevar"}],"objectGroups":[]},{"description":"Download the current displayed image of an object as a png file.","fullName":"Download image","functionType":"Action","group":"Image Tools","name":"DownloadImage","sentence":"Download an image out of _PARAM1_","events":[{"type":"BuiltinCommonInstructions::JsCode","inlineCode":["const renderer = runtimeScene.getGame().getRenderer().getPIXIRenderer();","const sprite = objects[0].getRendererObject();","const fileName = \"test\";","","renderer.extract.canvas(sprite).toBlob(function(b){","\t\tvar a = document.createElement('a');","\t\tdocument.body.append(a);","\t\ta.download = fileName;","\t\ta.href = URL.createObjectURL(b);","\t\ta.click();","\t\ta.remove();","\t}, 'image/png');","",""],"parameterObjects":"Object","useStrict":true,"eventsSheetExpanded":false}],"parameters":[{"description":"Object","name":"Object","type":"objectList"}],"objectGroups":[]}],"eventsBasedBehaviors":[],"eventsBasedObjects":[]} \ No newline at end of file +{ + "author": "", + "category": "Advanced", + "extensionNamespace": "", + "fullName": "Upload Download Image File", + "helpPath": "", + "iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCjwhLS0gR2VuZXJhdG9yOiBBZG9iZSBJbGx1c3RyYXRvciAyMy4wLjMsIFNWRyBFeHBvcnQgUGx1Zy1JbiAuIFNWRyBWZXJzaW9uOiA2LjAwIEJ1aWxkIDApICAtLT4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iSWNvbnMiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgMzIgMzIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDMyIDMyOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KCS5zdDB7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbWl0ZXJsaW1pdDoxMDt9DQoJLnN0MXtmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjI7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO30NCgkuc3Qye2ZpbGw6bm9uZTtzdHJva2U6IzAwMDAwMDtzdHJva2Utd2lkdGg6MjtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLWRhc2hhcnJheTo2LDY7fQ0KCS5zdDN7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtZGFzaGFycmF5OjQsNDt9DQoJLnN0NHtmaWxsOm5vbmU7c3Ryb2tlOiMwMDAwMDA7c3Ryb2tlLXdpZHRoOjI7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7fQ0KCS5zdDV7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1kYXNoYXJyYXk6My4xMDgxLDMuMTA4MTt9DQoJDQoJCS5zdDZ7ZmlsbDpub25lO3N0cm9rZTojMDAwMDAwO3N0cm9rZS13aWR0aDoyO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2UtbWl0ZXJsaW1pdDoxMDtzdHJva2UtZGFzaGFycmF5OjQsMzt9DQo8L3N0eWxlPg0KPHBhdGggY2xhc3M9InN0MCIgZD0iTTI3LDIzLjJWOC44YzEuMi0wLjQsMi0xLjUsMi0yLjhjMC0xLjctMS4zLTMtMy0zYy0xLjMsMC0yLjQsMC44LTIuOCwySDguOEM4LjQsMy44LDcuMywzLDYsM0M0LjMsMywzLDQuMywzLDYNCgljMCwxLjMsMC44LDIuNCwyLDIuOHYxNC40Yy0xLjIsMC40LTIsMS41LTIsMi44YzAsMS43LDEuMywzLDMsM2MxLjMsMCwyLjQtMC44LDIuOC0yaDE0LjRjMC40LDEuMiwxLjUsMiwyLjgsMmMxLjcsMCwzLTEuMywzLTMNCglDMjksMjQuNywyOC4yLDIzLjYsMjcsMjMuMnoiLz4NCjxyZWN0IHg9IjkiIHk9IjkiIGNsYXNzPSJzdDAiIHdpZHRoPSIxNCIgaGVpZ2h0PSIxNCIvPg0KPGNpcmNsZSBjbGFzcz0ic3QwIiBjeD0iMTMiIGN5PSIxMyIgcj0iMSIvPg0KPHBvbHlsaW5lIGNsYXNzPSJzdDAiIHBvaW50cz0iOSwyMCAxNiwxNiAyMCwxOSAyMywxNyAiLz4NCjwvc3ZnPg0K", + "name": "UploadDownloadImageFile", + "previewIconUrl": "https://asset-resources.gdevelop.io/public-resources/Icons/Line Hero Pack/Master/SVG/Graphic Design/4090f6ed8baf469e1d3c78b1bc636e52e6a9dd9f47d0eb78865a4f659c2f917a_Graphic Design_picture.svg", + "shortDescription": "Allows the upload of an image from the device, from a base64 encoded image, the extraction of a base64 string out of an image, and the download of images.", + "version": "0.0.0", + "description": [ + "Allows the upload of an image from the device, from a base64 encoded image, the extraction of a base64 string out of an image, and the download of images.", + "", + "Warning:", + "- Works on desktop, browsers and *partially* at mobile devices.", + "- With this extension, you can not **download** files to a mobile device, but you can **upload** an image from their device.", + "", + "Content:", + "- The action **Load base64 string**.", + "- The action **Extract base64 string**.", + "- The action **Download base64 encoded image**.", + "- The action **Write base64 encoded image** (Desktop builds only).", + "- The action **Upload device image**.", + "- The action **Download image**.", + "- The action **Write image** (Desktop builds only).", + "", + "The object that will recieve the image will have their resource replaced, meaning that every object sharing the same resource will also display the image." + ], + "tags": [ + "write", + "upload", + "download", + "image", + "gallery", + "file", + "manager", + "picture", + "photo", + "base", + "64", + "base64", + "javascript" + ], + "authorIds": [ + "OaVzVu7cuKhv5Qj0i3vRZYFttl72" + ], + "dependencies": [], + "eventsFunctions": [ + { + "async": true, + "description": "Upload an image from the device to a sprite.", + "fullName": "Upload device image", + "functionType": "Action", + "group": "Image Tools", + "name": "UploadImageFile", + "sentence": "Upload a _PARAM6_ image from the device to _PARAM1_ (update size: _PARAM2_, save as base64 in _PARAM3_, width in _PARAM4_ and height in _PARAM5_)", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const { task } = eventsFunctionContext;", + "if (objects.length > 0) {", + " const input = document.createElement('input');", + " const instance = objects[0];", + " const acceptedExtensions = eventsFunctionContext.getArgument(\"AcceptedExtensions\") || '*';", + " const saveBase64 = eventsFunctionContext.getArgument(\"SaveBase64\");", + " const modifySize = eventsFunctionContext.getArgument(\"ModifySize\");", + " const saveWidth = eventsFunctionContext.getArgument(\"ImageWidth\");", + " const saveHeight = eventsFunctionContext.getArgument(\"ImageHeight\");", + " ", + " input.type = 'file';", + " input.accept = `image/${acceptedExtensions}`;", + " input.addEventListener(\"change\", handleFiles, false);", + " input.click();", + "", + " async function handleFiles() {", + " const { files } = this;", + " //const files = this.files;", + "", + " if (!files.length) {", + " const logger = new gdjs.Logger();", + " logger.error('Error loading image from device, user did not choose an image.')", + " task.resolve();", + " } else {", + " const reader = new FileReader();", + " reader.onload = async function(e) {", + " const base64 = e.target.result;", + " if (saveBase64) {", + " saveBase64.setString(base64);", + " }", + " const sprite = instance.getRendererObject();", + " const oldWidth = instance.getWidth();", + " const oldHeight = instance.getHeight();", + " ", + " const callback = function() {", + "", + " const { width, height } = baseTexture;", + "", + " if (saveWidth) {", + " saveWidth.setNumber(width);", + " }", + " ", + " if (saveHeight) {", + " saveHeight.setNumber(height);", + " }", + "", + " instance.setWidth(width);", + " instance.setHeight(height);", + "", + " sprite.texture.baseTexture = baseTexture;", + "", + " if (modifySize === false) {", + " instance.setWidth(oldWidth);", + " instance.setHeight(oldHeight);", + " }", + "", + " task.resolve();", + " };", + "", + " const baseTexture = new PIXI.BaseTexture(base64);", + "", + " baseTexture.once('loaded', () => {", + " callback();", + " });", + " }", + " reader.readAsDataURL(files[0]);", + " }", + " input.remove();", + " }", + "} else {", + " const logger = new gdjs.Logger();", + " logger.error('Error loading image from device, no objects were found.')", + " task.resolve(); ", + "}" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Sprite", + "name": "Object", + "supplementaryInformation": "Sprite", + "type": "objectList" + }, + { + "defaultValue": "yes", + "description": "Modify the size of the object to match the image?", + "name": "ModifySize", + "optional": true, + "supplementaryInformation": "Lighting::LightObject", + "type": "yesorno" + }, + { + "description": "(Optional) Scene variable to save the image encoded as base64", + "name": "SaveBase64", + "type": "scenevar" + }, + { + "description": "(Optional) Scene variable to save the image width", + "name": "ImageWidth", + "type": "scenevar" + }, + { + "description": "(Optional) Scene variable to save the image height", + "name": "ImageHeight", + "type": "scenevar" + }, + { + "description": "File extensions to accept (* = any)", + "name": "AcceptedExtensions", + "supplementaryInformation": "[\"*\",\"png\",\"jpg\",\"jpeg\",\"webp\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "async": true, + "description": "Extract a base64 string out of the current displayed image of a sprite, and store in the specified scene variable when finished.", + "fullName": "Extract base64 string", + "functionType": "Action", + "group": "Image Tools", + "name": "SaveBase64Image", + "sentence": "Extract to _PARAM2_ a base64 string out of _PARAM1_ with format _PARAM3_ and quality _PARAM4_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const { task } = eventsFunctionContext;", + "if (objects.length > 0) {", + "\tconst renderer = runtimeScene.getGame().getRenderer().getPIXIRenderer();", + "\tconst sprite = objects[0].getRendererObject();", + "\tconst format = eventsFunctionContext.getArgument(\"Format\") || 'png';", + "\tconst quality = eventsFunctionContext.getArgument(\"Quality\") || 0.92;", + "\tlet str;", + "", + "\tasync function extractBase(){", + "\t\tstr = await renderer.extract.base64(sprite,'image/'+format,quality);", + "\t\teventsFunctionContext.getArgument(\"Variable\").setString(str);", + "\t\ttask.resolve();", + "\t}", + "", + "\textractBase();", + "} else {", + "\tconst logger = new gdjs.Logger();", + "\tlogger.error('Error extracting base64 string, no objects were found.');", + "\ttask.resolve();", + "}" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Sprite", + "name": "Object", + "supplementaryInformation": "Sprite", + "type": "objectList" + }, + { + "description": "Scene variable to save the image encoded as base64", + "name": "Variable", + "type": "scenevar" + }, + { + "description": "Format (default: png)", + "name": "Format", + "supplementaryInformation": "[\"png\",\"jpg\",\"jpeg\",\"webp\"]", + "type": "stringWithSelector" + }, + { + "description": "Quality (default: 0.92)", + "name": "Quality", + "type": "expression" + } + ], + "objectGroups": [] + }, + { + "async": true, + "description": "Load a base64 encoded image to a sprite.\n\nIts recommended to keep the base64 string stored in a string variable, otherwise you will have a bad experience navigating the eventsheet.", + "fullName": "Load base64 string", + "functionType": "Action", + "group": "Image Tools", + "name": "LoadBase64Image", + "sentence": "Load to _PARAM1_ a base64 image from the string _PARAM3_ (update size: _PARAM2_, save width in _PARAM4_ and height in _PARAM5_)", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const { task } = eventsFunctionContext;", + "", + "if (objects.length > 0) {", + " const instance = objects[0];", + " const modifySize = eventsFunctionContext.getArgument(\"ModifySize\");", + " const saveWidth = eventsFunctionContext.getArgument(\"ImageWidth\");", + " const saveHeight = eventsFunctionContext.getArgument(\"ImageHeight\");", + "", + " async function load() {", + " const sprite = instance.getRendererObject();", + "", + " const callback = function() {", + " sprite.texture.baseTexture = baseTexture;", + "", + " const { width, height } = baseTexture;", + "", + " if (saveWidth) {", + " saveWidth.setNumber(width);", + " }", + " ", + " if (saveHeight) {", + " saveHeight.setNumber(height);", + " }", + "", + " if (modifySize === true) {", + " instance.setWidth(width);", + " instance.setHeight(height);", + " }", + " task.resolve();", + " };", + "", + " const baseTexture = new PIXI.BaseTexture(", + " eventsFunctionContext.getArgument(\"Base64\")", + " );", + "", + " baseTexture.once('loaded', () => {", + " callback();", + " });", + " }", + "", + " load();", + "} else {", + " const logger = new gdjs.Logger();", + " logger.error('Error loading base64 string, no objects were found.');", + " task.resolve();", + "}", + "" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Sprite", + "name": "Object", + "supplementaryInformation": "Sprite", + "type": "objectList" + }, + { + "defaultValue": "yes", + "description": "Modify the size of the object to match the image?", + "name": "ModifySize", + "optional": true, + "supplementaryInformation": "Lighting::LightObject", + "type": "yesorno" + }, + { + "description": "Image encoded as base64", + "name": "Base64", + "type": "string" + }, + { + "description": "(Optional) Scene variable to save the image width", + "name": "ImageWidth", + "type": "scenevar" + }, + { + "description": "(Optional) Scene variable to save the image height", + "name": "ImageHeight", + "type": "scenevar" + } + ], + "objectGroups": [] + }, + { + "description": "Download a base64 encoded image as a png file.", + "fullName": "Download base64 encoded image", + "functionType": "Action", + "group": "Image Tools", + "name": "DownloadBase64Image", + "sentence": "Download an image out of the base64 string _PARAM1_ as _PARAM2_._PARAM3_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const fileName = eventsFunctionContext.getArgument(\"ImageName\");", + "const fileExtension = eventsFunctionContext.getArgument(\"ImageExtension\") || png;", + "const base = eventsFunctionContext.getArgument(\"Base64\")", + " .replace('data:image/png;base64,','');", + "", + "", + "var a = document.createElement('a');", + "document.body.append(a);", + "a.download = fileName+\".\"+fileExtension;", + "a.href = 'data:image/png;base64,'+base;", + "a.click();", + "a.remove();" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Image encoded as base64", + "name": "Base64", + "type": "string" + }, + { + "description": "Image name (without the file extension)", + "name": "ImageName", + "type": "string" + }, + { + "description": "Image extension", + "name": "ImageExtension", + "supplementaryInformation": "[\"png\",\"jpg\",\"jpeg\",\"webp\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "description": "Write a base64 encoded image as a png file to the storage without the user prompt. Only works at desktop builds.", + "fullName": "Write base64 encoded image", + "functionType": "Action", + "group": "Image Tools", + "name": "WriteBase64Image", + "sentence": "Write to _PARAM2_ an image out of the base64 string _PARAM1_ (store result in _PARAM3_)", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "const fs = typeof require !== 'undefined' ? require('fs') : null;", + "if (fs) {", + "\tconst variable = eventsFunctionContext.getArgument(\"Variable\");", + "\tlet filePath = eventsFunctionContext.getArgument(\"SavePath\");", + "\tconst file = eventsFunctionContext.getArgument(\"Base64\")", + "\t\t.replace('data:image/png;base64,', '');", + "\tfilePath.indexOf('.') === -1 && (filePath+'.png')", + "\tif (filePath.indexOf('.') !== -1) {", + "\t\tif (filePath.indexOf('.') === 0) {", + "\t\t\tfilePath = 'Image'+filePath;", + "\t\t}", + "\t\t", + "\t\tif (filePath.indexOf('.') === filePath.length - 1) {", + "\t\t\tfilePath = filePath+'png';", + "\t\t}", + "\t};", + "", + "\tfs.writeFile(filePath, file, 'base64', (err) => {", + " if (err) {", + "\t\t\tvariable.setString('error');", + " \tlogger.error(", + " \t'Unable to save the image at path: ' + filePath", + " );", + " } else {", + "\t\t\tvariable.setString('ok');", + "\t\t}", + "\t});", + "}" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Image encoded as base64", + "name": "Base64", + "type": "string" + }, + { + "description": "Save path (with file name and extension)", + "name": "SavePath", + "type": "string" + }, + { + "description": "(Optional) Variable to store the result. 'ok': task was successful, 'error': an error occurred", + "name": "Variable", + "type": "scenevar" + } + ], + "objectGroups": [] + }, + { + "description": "Download the current displayed image of a sprite as a png file.", + "fullName": "Download image", + "functionType": "Action", + "group": "Image Tools", + "name": "DownloadImage", + "sentence": "Download an image out of _PARAM1_ as _PARAM2_._PARAM3_", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "if (objects.length > 0) {", + "\tconst renderer = runtimeScene.getGame().getRenderer().getPIXIRenderer();", + "\tconst sprite = objects[0].getRendererObject();", + "\tconst fileName = eventsFunctionContext.getArgument(\"ImageName\");", + "\tconst fileExtension = eventsFunctionContext.getArgument(\"ImageExtension\") || 'png';", + "", + "\trenderer.extract.canvas(sprite).toBlob(function(b){", + "\t\tvar a = document.createElement('a');", + "\t\tdocument.body.append(a);", + "\t\ta.download = fileName+\".\"+fileExtension;", + "\t\ta.href = URL.createObjectURL(b);", + "\t\ta.click();", + "\t\ta.remove();", + "\t}, 'image/png')", + "} else {", + "\tconst logger = new gdjs.Logger();", + "\tlogger.error('Error downloading image, no objects were found.');", + "} " + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Sprite", + "name": "Object", + "supplementaryInformation": "Sprite", + "type": "objectList" + }, + { + "description": "Image name (without the file extension)", + "name": "ImageName", + "type": "string" + }, + { + "description": "Image extension", + "name": "ImageExtension", + "supplementaryInformation": "[\"png\",\"jpg\",\"jpeg\",\"webp\"]", + "type": "stringWithSelector" + } + ], + "objectGroups": [] + }, + { + "description": "Write the current displayed image of a sprite as a png file to the storage without the user prompt. Only works at desktop builds.", + "fullName": "Write image", + "functionType": "Action", + "group": "Image Tools", + "name": "WriteImage", + "sentence": "Write to _PARAM2_ an image out of _PARAM1_ (store result in _PARAM3_)", + "events": [ + { + "type": "BuiltinCommonInstructions::JsCode", + "inlineCode": [ + "if (objects.length > 0) {", + "\tconst fs = typeof require !== 'undefined' ? require('fs') : null;", + "\tif (fs) {", + "\t\tconst variable = eventsFunctionContext.getArgument(\"Variable\");\t\t", + "\t\tconst savePath = eventsFunctionContext.getArgument(\"SavePath\");", + "\t\tconst renderer = runtimeScene.getGame().getRenderer().getPIXIRenderer();", + "\t\tconst sprite = objects[0].getRendererObject();", + "\t\tconst fileName = eventsFunctionContext.getArgument(\"ImageName\");", + "\t\tconst file = renderer", + "\t\t\t\t\t\t.extract", + "\t\t\t\t\t\t.canvas(sprite)", + "\t\t\t\t\t\t.toDataURL('image/png')", + "\t\t\t\t\t\t.replace('data:image/png;base64,', '');", + "", + "\t\tfs.writeFile(savePath, file, 'base64', (err) => {", + " \tif (err) {", + "\t\t\t\tvariable.setString('error');", + " \t\tlogger.error(", + " \t\t'Unable to save the image at path: ' + savePath", + "\t );", + " \t} else {", + "\t\t\t\tvariable.setString('ok');", + "\t\t\t}", + "\t\t});", + "\t}", + "} else {", + "\tconst logger = new gdjs.Logger();", + "\tlogger.error('Error writing image, no objects were found');", + "}" + ], + "parameterObjects": "Object", + "useStrict": true, + "eventsSheetExpanded": false + } + ], + "parameters": [ + { + "description": "Sprite", + "name": "Object", + "supplementaryInformation": "Sprite", + "type": "objectList" + }, + { + "description": "Save path (with file name and extension)", + "name": "SavePath", + "type": "string" + }, + { + "description": "(Optional) Variable to store the result. 'ok': task was successful, 'error': an error occurred", + "name": "Variable", + "type": "scenevar" + } + ], + "objectGroups": [] + } + ], + "eventsBasedBehaviors": [], + "eventsBasedObjects": [] +} \ No newline at end of file