From 3ff809351a612070f9709a7f95dfa3b593ac572d Mon Sep 17 00:00:00 2001 From: Dustin Oprea Date: Mon, 15 Apr 2019 13:44:12 -0400 Subject: [PATCH 1/2] poly-client/app.js: Move embedded functions out of start() - Implemented a context object that can be passed around. --- poly-client/src/app.js | 283 ++++++++++++++++++++--------------------- 1 file changed, 140 insertions(+), 143 deletions(-) diff --git a/poly-client/src/app.js b/poly-client/src/app.js index e9da3e5..76fd918 100644 --- a/poly-client/src/app.js +++ b/poly-client/src/app.js @@ -10,173 +10,170 @@ let log = (...args) => { console.log(...args); }; +async function doQuery (context) { + for await (let data of query(context.value)) { + let { assets } = data; + await renderGrid(context, assets); + print('RenderGrid is done'); + // TODO: don't auto load + // loadModel(context, assets[0]); + break; + } +} + +function clear (context) { + if (context.grid || context.transform) { + context.layout.removeItem(1); + context.grid = null; + context.transform = null; + } +} + +async function renderGrid (context, assets) { + clear(context); + let grid = UiGridLayout.Create(context.prism); + grid.setAlignment(Alignment.CENTER_CENTER); + context.layout.addItemAt(1, grid); + grid.setColumns(3); + grid.setRows(3); + + context.grid = grid; + + let promises = []; + let i = 0; + for (let asset of assets) { + let { + formats: [{ resources }], + displayName, + thumbnail: { url, relativePath } + } = asset; + + // Skip resources that don't have a png. + let hasPng = false; + for (let { relativePath } of resources) { + if (/\.png$/.test(relativePath)) { + hasPng = true; + break; + } + } + if (!hasPng) continue; + + let filePath = context.writablePath + i + '-' + relativePath; + print('Downloading...', displayName, url, filePath); + let index = i++; + promises.push(download(url, filePath).then(() => { + let img = UiImage.Create(context.prism, filePath, 0.266666, 0.2, true, true); + img.onActivateSub(async () => { + await loadModel(context, asset); + }); + print('Loaded', displayName, img); + context.grid.addItemAt(index, img); + })); + if (i >= 9) break; + } + await Promise.all(promises); + print('All loaded'); +} + +async function loadModel (context, asset) { + clear(context); + let { + root: { url: rootUrl, relativePath: rootName }, + resources + } = asset.formats[0]; + let rootPath = context.writablePath + rootName; + let resourcePaths = []; + await Promise.all([ + download(rootUrl, rootPath), + Promise.all(resources.map(({ url: resourceUrl, relativePath: resourceName }) => { + let resourcePath = context.writablePath + resourceName; + resourcePaths.push(resourcePath); + return download(resourceUrl, resourcePath); + })) + ]); + print('All files saved...', rootPath, resourcePaths); + for (let resourcePath of resourcePaths) { + if (/\.mtl$/i.test(resourcePath)) { + let id = context.prism.createObjMtlResourceId(resourcePath, true); + print('MTL', id, resourcePath); + } else { + let id = context.prism.createTextureResourceId(Desc2d.DEFAULT, resourcePath, true); + print('Texture', id, resourcePath); + } + } + let id = context.prism.createModelResourceId(rootPath, 1, true); + print('model id', id); + let model = context.prism.createModelNode(id); + fit(context, model, 0.6); + + let transform = context.prism.createTransformNode(MAT4_IDENTITY); + transform.addChild(model); + + context.transform = transform; + + context.value = ''; + context.layout.addItemAt(1, context.transform); +} + +function fit (context, node, size = 1) { + let aabb = node.getLocalAABB(); + print(aabb); + let [x, y, z] = aabb.getCenter(); + let [w, h, d] = aabb.getExtents(); + let scale = size / 2 / Math.max(w, h, d); + node.setLocalPosition([-x * scale, -y * scale, -z * scale]); + node.setLocalScale([scale, scale, scale]); +} + +async function download (url, file) { + print('Downloading...', url); + let res = await fetch(url); + return fetch('file://' + file, { method: 'PUT', body: res.body }); +} + export default async function start (app) { - let base = app.getWritablePath(); let prism = app.requestNewPrism([1.0, 0.8, 0.8]); let layout = UiLinearLayout.Create(prism); layout.setSize([0.8, 0.7]); layout.setAlignment(Alignment.CENTER_CENTER); layout.setDefaultItemAlignment(Alignment.CENTER_CENTER); prism.getRootNode().addChild(layout); - let value = 'fox'; - let grid; - let transform; + // let value = 'fox'; + // let grid; + // let transform; + + let context = { + writablePath: app.getWritablePath(), + layout: layout, + prism: prism, + value: "fox" + } setInterval(() => { - if (!transform) return; + if (!context.transform) return; let quat = eulerToQuaternion(Date.now() / 1000, 0, 0); - transform.setLocalRotation(quat); + context.transform.setLocalRotation(quat); }, 33); - let searchBar = UiTextEdit.Create(prism, value, 0.8, 0.1); + let searchBar = UiTextEdit.Create(context.prism, context.value, 0.8, 0.1); searchBar.setAlignment(Alignment.TOP_CENTER); searchBar.setTextSize(0.1); - layout.addItemAt(0, searchBar); - doQuery(value); + context.layout.addItemAt(0, searchBar); + doQuery(context); let timeout; searchBar.onKeyboardEventSub(() => { let newValue = searchBar.getText(); - if (newValue === value) { return; } - value = newValue; + if (newValue === context.value) { return; } + context.value = newValue; if (timeout) { clearTimeout(timeout); } timeout = setTimeout(async () => { timeout = null; - doQuery(value); + doQuery(context); }, 2500); }); - async function doQuery (value) { - for await (let data of query(value)) { - let { assets } = data; - await renderGrid(assets); - print('RenderGrid is done'); - // TODO: don't auto load - // loadModel(assets[0]); - break; - } - } - - function clear () { - if (grid || transform) { - layout.removeItem(1); - grid = null; - transform = null; - } - } - - async function renderGrid (assets) { - clear(); - grid = UiGridLayout.Create(prism); - grid.setAlignment(Alignment.CENTER_CENTER); - layout.addItemAt(1, grid); - grid.setColumns(3); - grid.setRows(3); - let promises = []; - let i = 0; - for (let asset of assets) { - let { - formats: [{ resources }], - displayName, thumbnail: { url, relativePath } - } = asset; - - // Skip resources that don't have a png. - let hasPng = false; - for (let { relativePath } of resources) { - if (/\.png$/.test(relativePath)) { - hasPng = true; - break; - } - } - if (!hasPng) continue; - - let filePath = base + i + '-' + relativePath; - print('Downloading...', displayName, url, filePath); - let index = i++; - promises.push(download(url, filePath).then(() => { - let img = UiImage.Create(prism, filePath, 0.266666, 0.2, true, true); - img.onActivateSub(async () => { - await loadModel(asset); - }); - print('Loaded', displayName, img); - grid.addItemAt(index, img); - })); - if (i >= 9) break; - } - await Promise.all(promises); - print('All loaded'); - } - - async function loadModel (asset) { - clear(); - let { - root: { url: rootUrl, relativePath: rootName }, - resources - } = asset.formats[0]; - let rootPath = base + rootName; - let resourcePaths = []; - await Promise.all([ - download(rootUrl, rootPath), - Promise.all(resources.map(({ url: resourceUrl, relativePath: resourceName }) => { - let resourcePath = base + resourceName; - resourcePaths.push(resourcePath); - return download(resourceUrl, resourcePath); - })) - ]); - print('All files saved...', rootPath, resourcePaths); - for (let resourcePath of resourcePaths) { - if (/\.mtl$/i.test(resourcePath)) { - let id = prism.createObjMtlResourceId(resourcePath, true); - print('MTL', id, resourcePath); - } else { - let id = prism.createTextureResourceId(Desc2d.DEFAULT, resourcePath, true); - print('Texture', id, resourcePath); - } - } - let id = prism.createModelResourceId(rootPath, 1, true); - print('model id', id); - let model = prism.createModelNode(id); - fit(model, 0.6); - transform = prism.createTransformNode(MAT4_IDENTITY); - transform.addChild(model); - value = ''; - layout.addItemAt(1, transform); - } - - function fit (node, size = 1) { - let aabb = node.getLocalAABB(); - print(aabb); - let [x, y, z] = aabb.getCenter(); - let [w, h, d] = aabb.getExtents(); - let scale = size / 2 / Math.max(w, h, d); - node.setLocalPosition([-x * scale, -y * scale, -z * scale]); - node.setLocalScale([scale, scale, scale]); - } - - async function download (url, file) { - print('Downloading...', url); - let res = await fetch(url); - return fetch('file://' + file, { method: 'PUT', body: res.body }); - } - - /** - let response = await fetch("http://placehold.jp/99ccff/003366/250x150.png"); - if (!response.ok) { - throw new Error("HTTP error, status = " + response.status); - } - let path = app.getWritablePath(); - let name = "img.png"; - let full_name = path + name; - await fetch("file://" + full_name, { method: "PUT", body: response.body }); - - let string = "basicFetch - Success:\n"; - text.setText(string); - - const { UiImage } = ui; - - let image = UiImage.Create(prism, full_name, 0.4, 0.3, true); - */ - return prism; + return context.prism; } From 800c529291075db4d4eeddcc75ee77dadc612c9c Mon Sep 17 00:00:00 2001 From: Dustin Oprea Date: Tue, 16 Apr 2019 17:59:19 -0400 Subject: [PATCH 2/2] app.js: Only download if not already present --- poly-client/src/app.js | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/poly-client/src/app.js b/poly-client/src/app.js index 76fd918..4043be7 100644 --- a/poly-client/src/app.js +++ b/poly-client/src/app.js @@ -2,6 +2,8 @@ import query from './GooglePolyApi.js'; import { eulerToQuaternion } from './math.js'; import { ui, Desc2d, MAT4_IDENTITY } from 'lumin'; +import { stat } from "magic-script-polyfills/src/fs.js" + const { UiTextEdit, Alignment, UiLinearLayout, UiGridLayout, UiImage } = ui; // Log to both `mldb log` and chrome inspector. @@ -59,7 +61,7 @@ async function renderGrid (context, assets) { if (!hasPng) continue; let filePath = context.writablePath + i + '-' + relativePath; - print('Downloading...', displayName, url, filePath); + print('Initiating download...', displayName, url, filePath); let index = i++; promises.push(download(url, filePath).then(() => { let img = UiImage.Create(context.prism, filePath, 0.266666, 0.2, true, true); @@ -126,9 +128,29 @@ function fit (context, node, size = 1) { } async function download (url, file) { - print('Downloading...', url); - let res = await fetch(url); - return fetch('file://' + file, { method: 'PUT', body: res.body }); + let exists = false; + + try { + await stat(file); + exists = true; + } catch (e) { + if (/^ENOENT:/.test(e.message) == false) { + throw e; + } + } + + if (exists == false) { + // File doesn't exist locally, yet. + + print("File needs to be downloaded: " + file); + + let res = await fetch(url); + return fetch(file, { method: 'PUT', body: res.body }); + } + + // File already downloaded. + + print("File previously downloaded: " + file); } export default async function start (app) {