Effects / Spark AR "ERROR: undefined is not a function" - object

I'm trying to make a JS effect on Spark AR with a code and Native UI and also face mesh.
The effect have bottons to choose the effect, one of them have a face mesh where the texture is not recognize and the another one have a simple texture.
----- My code to script of two objects / two bottons:
const Materials = require('Materials');
const Scene = require('Scene');
const NativeUI = require('NativeUI');
const Textures = require('Textures');
const plane = Scene.root.find('plane0');
const index = 0;
const configuration = {
selectedIndex: index,
items: [
{image_texture: Textures.get('N1')},
{image_texture: Textures.get('N2')},
],
mats: [
{material: Materials.get("N1")},
{material: Materials.get("N2")},
]
};
const picker = NativeUI.picker;
picker.configure(configuration);
picker.visible = true;
picker.selectedIndex.monitor().subscribe(function(val) {
plane.material = configuration.mats[val.newValue].material;
;
});
----- The error message that shows when I open Spark AR Studio:
ERROR: undefined is not a function
{ "line": 6,
<br> "column": 30,
<br> "sourceURL": "scrip2obj.js"
}
I would like to know... what can I do to make this run and make the face mesh shows in the effect?

Starting from v85 of Spark AR Studio the current JavaScript APIs are deprecated in favor of asynchronous APIs.
This means some APIs will be deprecated and will need to be replaced in your projects. When creating new projects, new APIs should be used instead.
You can learn more about it here
Scripting Javascript Promise In Spark AR For Beginners
Try the following code to implement Native UI Picker
const Materials = require('Materials');
const NativeUI = require('NativeUI');
const Textures = require('Textures');
const Scene = require('Scene');
(async function () { // Enables async/await in JS [part 1]
// To access scene objects
const [plane0, n1, n2, n1Material] = await Promise.all([
Scene.root.findFirst('plane0'),
Textures.findFirst('N1'),
Textures.findFirst('N2'),
Materials.findFirst("N1"),
]);
const index = 0;
const configuration = {
selectedIndex: index,
items: [
{ image_texture: n1 },
{ image_texture: n2 },
]
};
const picker = NativeUI.picker;
picker.configure(configuration);
picker.visible = true;
picker.selectedIndex.monitor().subscribe(function (val) {
plane.material = configuration.mats[val.newValue].material;
});
})(); // Enables async/await in JS [part 2]

Related

'document is not defined' canvas/discord

I'm trying make a animated banner to discord server, but I have some problems with that. I don't know why document is not defined. I tried a bunch of ways, but none of them worked.
try {
let guild = await client.guilds.cache.get(guildId.id);
const voiceChannels = guild.channels.cache.filter((c) => c.type === "GUILD_VOICE");
let count = 0;
for (const [, voiceChannel] of voiceChannels) count += voiceChannel.members.size;
var canvas = createCanvas(420, 236);
var ctx = canvas.getContext('2d');
ctx.textAlign = "center"
ctx.font = "20px Kanit Black"
ctx.fillStyle = '000001'
const encoder = new GIFEncoder(420, 236, {emptyColor: true, dynamicColors: true})
encoder.setRepeat(0);
encoder.setQuality(10)
await gifFrames({ url: `${__dirname}/banner-beta.gif`, frames: 'all', outputType: 'canvas', cumulative: false}).then((frameData) => {
for(let i = 0; i < frameData.length; i++) {
encoder.setDelay(frameData[i].frameInfo.delay * 15);
console.log(frameData[0])
console.log(frameData[i])
ctx.drawImage((frameData[i]).getImage(), 0, 0, 420, 236)
ctx.fillText(`${count}`, 50, 90)
console.log(ctx)
encoder.addFrame(ctx);
}
encoder.finish();
console.log(encoder.out.getData())
var attachment = new MessageAttachment(encoder.out.getData(), 'banner.gif');
guild.channels.cache.get("909860310171648050").send({ files: [attachment] }).catch(console.log);
})
//guild.setBanner(canvas.toBuffer()).catch(console.error);
} catch (e) {
console.log(e)
}
error:
ReferenceError: document is not defined
at savePixels (C:\Users\hotab\Desktop\Root\node_modules\save-pixels-jpeg-js-upgrade\save-pixels.js:127:20)
at Object.getImage (C:\Users\hotab\Desktop\Root\node_modules\gif-frames\gif-frames.js:105:20)
at C:\Users\hotab\Desktop\Root\utils\banner.js:31:34
TL;DR:
Your code runs in NodeJS, in which there is no document object because it does not make sense on a backend server. So using document results in an exception.
More details
You are using the node module gif-frames that depends on another node module called save-pixels-jpeg-js-upgrade which tries to access the document object that only exists in a browser context (see code here).
Either the documentation of gif-frames stating that it can run in both Node and browsers contexts is incorrect or there are some restrictions to some APIs, which you are facing here. Based on the node module code, it seems to be limited to the CANVAS case, but I can't help you any further...

can not get cascade DDS value for SharedObjectSequence

I have a test like this, but i can not get the 'sharedMap' in 'sharedSeq1' value, i don't know how to get the 'remoteFluidObjectHandle' value.
import {MockContainerRuntimeFactory, MockFluidDataStoreRuntime, MockStorage} from "#fluidframework/test-runtime-utils";
import {SharedObjectSequence, SharedObjectSequenceFactory} from "#fluidframework/sequence";
import * as mocks from "#fluidframework/test-runtime-utils";
import {SharedMap} from "#fluidframework/map";
import {IFluidHandle} from "#fluidframework/core-interfaces";
const mockRuntime: mocks.MockFluidDataStoreRuntime = new mocks.MockFluidDataStoreRuntime();
describe('ShredObjectSequence', function () {
it('should get synchronization data from another shared object', async function () {
const dataStoreRuntime1 = new MockFluidDataStoreRuntime();
const sharedSeq1: SharedObjectSequence<IFluidHandle<SharedMap>> = new SharedObjectSequence(mockRuntime, 'shareObjectSeq1', SharedObjectSequenceFactory.Attributes,)
const containerRuntimeFactory = new MockContainerRuntimeFactory();
dataStoreRuntime1.local = false;
const containerRuntime1 = containerRuntimeFactory.createContainerRuntime(
dataStoreRuntime1,
);
const services1 = {
deltaConnection: containerRuntime1.createDeltaConnection(),
objectStorage: new MockStorage(),
};
sharedSeq1.initializeLocal();
sharedSeq1.connect(services1);
const dataStoreRuntime2 = new MockFluidDataStoreRuntime();
const containerRuntime2 = containerRuntimeFactory.createContainerRuntime(
dataStoreRuntime2,
);
const services2 = {
deltaConnection: containerRuntime2.createDeltaConnection(),
objectStorage: new MockStorage(),
};
const sharedSeq2: SharedObjectSequence<IFluidHandle<SharedMap>> = new SharedObjectSequence(mockRuntime, 'shareObjectSeq2', SharedObjectSequenceFactory.Attributes,)
sharedSeq2.initializeLocal();
sharedSeq2.connect(services2);
// insert a node into sharedSeq2, it will sync to sharedSeq1
sharedSeq2.insert(0, [<IFluidHandle<SharedMap>>new SharedMap('sharedMapId', mockRuntime, SharedMap.getFactory().attributes).handle])
containerRuntimeFactory.processAllMessages();
// next case is passed, it show we got the sharedSeq2 changed
expect(sharedSeq1.getLength()).toBe(1)
const remoteFluidObjectHandle = await sharedSeq1.getRange(0, 1)[0];
// at here, i get error: Cannot read property 'mimeType' of null, it cause by remoteFluidObjectHandle.ts:51:30
const sharedMap = await remoteFluidObjectHandle.get()
expect(sharedMap).not.toBeUndefined()
});
});
run this test will get 'Cannot read property 'mimeType' of null' error, it caused by 'remoteFluidObjectHandle.ts:51:30'
The fluid mocks have very limited and specific behaviors, it looks like you are hitting the limits of them. You'll have better luck with an end-to-end test, see packages\test\end-to-end-tests. These use the same in-memory server as our as the playground on fluidframework dot com. The in-memory server uses the same code as tinylicious, our single process server and routerlicious, our docker based reference implementation.

Passed function is not well-serializable

I am using Puppeteer to scrape the web from a file template that contains the data of an order.
For this, I am using a puppeteer evaluation function, which works correctly while the file is in .js
However, when the "pkg" package is used to compile the .exe file or evaluate to execute and initiate a return or error: "The passed function is not quite serializable!"
Below is the code:
const dados = {name: 'foo', year: 1}
await page.evaluate(dados => {
let dom = document.querySelector('body');
const tags = Object.keys(dados);
for (let i = 0; i < tags.length; i++) {
const tag = tags[i];
dom.innerHTML = dom.innerHTML.split(`{{${tag}}}`).join(dados[tag]);
}
}, dados);
I try to add --public argument with pkg.
Like: pkg start.js -t node14-win-x64 --public
Then I can freely use ElementHandle.evaluate( (elem)=> elem.textContent );
With the manual of pkg, the --public means that : speed up and disclose the sources of top-level project.
BTW
To fixup cannot find chrome binary file
browser = await puppeteer.launch({
executablePath: "node_modules/puppeteer/.local-chromium/win64-782078/chrome-win/chrome.exe"
});
(The path above can set anywhere as you like.)
To fixup start.exe cannot run
Sometime the output binary exe cannot executable. It
always popup a new cmd prompt window when we enter start.exe. (or just double click.)
Just delete the output exe then rerun pkg
Check the code whether is runnable with node start.js or not
The easiest solution for me is to wrap it with eval() :
async getText(selector: string) {
await this.page.waitForSelector(selector);
let text = await eval(`this.page.$eval('${selector}', el => el.textContent)`)
return text;
}
or this:
await eval(`this.page.evaluate(
(selector) => { (document.querySelector(selector).value = ''); },
selector);`);
I had this exact issue relating to puppeteer and pkg. For some reason pkg doesn't correctly interpret the contents of the callback. The solution that worked for me was to pass a string to evaluate rather than a function:
Change:
const dados = {name: 'foo', year: 1}
await page.evaluate(dados => {
let dom = document.querySelector('body');
const tags = Object.keys(dados);
for (let i = 0; i < tags.length; i++) {
const tag = tags[i];
dom.innerHTML = dom.innerHTML.split(`{{${tag}}}`).join(dados[tag]);
}
}, dados);
to
await page.evaluate(`
(() => {
const dados = {name: 'foo', year: 1};
let dom = document.querySelector('body');
const tags = Object.keys(dados);
for (let i = 0; i < tags.length; i++) {
const tag = tags[i];
dom.innerHTML = dom.innerHTML.split(`{{${tag}}}`).join(dados[tag]);
}
// return dom to do something with the data in node
return dom.innerHTML
})()`);
This answer on github suggests an alternative solution - using the pkg api to inject the callback at compile time, however it didn't work for me.

select a region of desktop screen with Electron

I'm trying to write an application that allow the user to select a region of the screen (like selecting to take a screen shot).
Is that even possible?
To specifically take a full screen shot, use the following code (example pulled from Electron Demo App). You can build off of this example, and use the screen, desktopCapturer and rectangle modules in the electron api to customize the code to get a specific screen/display, or select a specific bounding box (x/y coordinates and pixel area).
const electron = require('electron')
const desktopCapturer = electron.desktopCapturer
const electronScreen = electron.screen
const shell = electron.shell
const fs = require('fs')
const os = require('os')
const path = require('path')
const screenshot = document.getElementById('screen-shot')
const screenshotMsg = document.getElementById('screenshot-path')
screenshot.addEventListener('click', function (event) {
screenshotMsg.textContent = 'Gathering screens...'
const thumbSize = determineScreenShotSize()
let options = { types: ['screen'], thumbnailSize: thumbSize }
desktopCapturer.getSources(options, function (error, sources) {
if (error) return console.log(error)
sources.forEach(function (source) {
if (source.name === 'Entire screen' || source.name === 'Screen 1') {
const screenshotPath = path.join(os.tmpdir(), 'screenshot.png')
fs.writeFile(screenshotPath, source.thumbnail.toPng(), function (error) {
if (error) return console.log(error)
shell.openExternal('file://' + screenshotPath)
const message = `Saved screenshot to: ${screenshotPath}`
screenshotMsg.textContent = message
})
}
})
})
})
function determineScreenShotSize () {
const screenSize = electronScreen.getPrimaryDisplay().workAreaSize
const maxDimension = Math.max(screenSize.width, screenSize.height)
return {
width: maxDimension * window.devicePixelRatio,
height: maxDimension * window.devicePixelRatio
}
}
Other ways you could go about this are:
Use object.getClientRects() in the DOM to specify specific elements you want to capture, although this would require foreknowledge of what they are.
Add event listeners in your view to 'draw' the shape of what you want with mouseClick, mouseMove, etc. This stack overflow question has answers which could be adapted to fit what you want to do.
I doubt you are still looking for a solution to this, but after digging i have found a way to do it using a combination of shelljs and clipboard.
const userDataPath = (app).getPath(
'userData'
)
const useP = path.join(userDataPath, 'uploads')
let randomTmpfile = uniqueFilename(useP, 'prefix')
shelljs.exec(`screencapture -ic ${randomTmpfile}.png`, function (res) {
const image = clipboard.readImage('png').toDataURL()
})

Cycling images in a live tile

I have a winJS app that is a working launcher for a steam game. I'd like to get it to cycle through 5 images even while not running.
It uses only the small tile — there are no wide tiles images for this app.
Here's the code:
(function () {
"use strict";
WinJS.Namespace.define("Steam", {
launch: function launch(url) {
var uri = new Windows.Foundation.Uri(url);
Windows.System.Launcher.launchUriAsync(uri).then(
function (success) {
if (success) {
// File launched
window.close();
} else {
// File launch failed
}
}
);
}
});
WinJS.Namespace.define("Tile", {
enqueue: function initialize() {
var updaterHandle = Windows.UI.Notifications.TileUpdateManager.createTileUpdaterForApplication();
updaterHandle.enableNotificationQueue(true);
return updaterHandle;
},
update: function update () {
var template = Windows.UI.Notifications.TileTemplateType.tileSquareImage;
var tileXml = Windows.UI.Notifications.TileUpdateManager.getTemplateContent(template);
var randIndx = Math.floor(Math.random() * 5);
var randUpdatetime = 1000 * 3 * (((randIndx == 0) ? 1 : 0) + 1); // let the base image stay longer
var tileImageAttributes = tileXml.getElementsByTagName("image");
tileImageAttributes[0].setAttribute("src", "ms-appx:///images/Borderlands2/borderlands_2_" + randIndx + "_sidyseven.png");
tileImageAttributes[0].setAttribute("alt", "Borderlands 2");
var tileNotification = new Windows.UI.Notifications.TileNotification(tileXml);
var currentTime = new Date();
tileNotification.expirationTime = new Date(currentTime.getTime() + randUpdatetime);
tileNotification.tag = "newTile";
var updater = Tile.enqueue();
updater.update(tileNotification);
setTimeout('Tile.update();', randUpdatetime);
}
});
WinJS.Binding.optimizeBindingReferences = true;
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
app.onactivated = function (args) {
if (args.detail.kind === activation.ActivationKind.launch) {
setTimeout('Steam.launch("steam://rungameid/49520");', 800);
args.setPromise(WinJS.UI.processAll().then(function () {
return WinJS.Navigation.navigate("/default.html", args).then(function () {
Tile.update();
});
}));
}
};
app.start();
})();
Notes:
The code currently does not cycle the image, instead either
apparently never changing, or after launch replacing the application
name text with a tiny view of the default image. This reverts to the
text after a short time, and the cycle may repeat. It never shows a
different image (neither in the small image it erroneously shows, nor
in the main tile).
When I run in debug and set a breakpoint at the
TileUpdater.update(TileNotification) stage, I can verify in the
console that the image src attribute is set to a random image
just as I wanted:
>>>>tileNotification.content.getElementsByTagName("image")[0].getAttribute("src")
"ms-appx:///images/Borderlands2/borderlands_2_4_sidyseven.png"
But this never actually displays on the tile.
These image files are included in the solution, and they appear in the proper directory in the Solution Explorer.
If the image src attribute is set properly in debug then the image may not have the proper "Build Action".
In the 'Properties' of each image, set "Build Action" to "Resource".

Resources