Skip to content

Commit

Permalink
Merge pull request #708 from vcync/next
Browse files Browse the repository at this point in the history
Release
  • Loading branch information
TimPietrusky authored Mar 9, 2022
2 parents 8119c88 + 34b4826 commit a30b860
Show file tree
Hide file tree
Showing 10 changed files with 404 additions and 88 deletions.
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@
},
"main": "background.js",
"dependencies": {
"@electron/remote": "^2.0.4",
"animated-gif-detector": "^1.2.0",
"animejs": "3.2.0",
"aws-sdk": "^2.580.0",
"aws-sdk": "^2.814.0",
"canvas-text-wrapper": "github:cyberj/canvas-text-wrapper#master",
"color": "^3.1.2",
"dotenv": "^8.2.0",
Expand All @@ -53,6 +54,7 @@
"recursive-deps": "^1.1.1",
"stream-to-blob": "^2.0.0",
"tap-tempo": "^0.1.1",
"three": "^0.131.3",
"uuid": "^3.3.3",
"vue": "^2.6.10",
"vue-class-component": "^7.2.3",
Expand All @@ -77,7 +79,7 @@
"@vue/eslint-config-prettier": "^4.0.1",
"babel-eslint": "^10.0.3",
"core-js": "^3.19.1",
"electron": "^11.2.0",
"electron": "^17.0.0",
"electron-builder": "^22.9.1",
"electron-notarize": "^1.0.0",
"eslint": "^5.16.0",
Expand Down
5 changes: 3 additions & 2 deletions src/application/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import use from "./use";

import PromiseWorker from "promise-worker-transferable";
import Vue from "vue";
import { ipcRenderer, remote } from "electron";
import { ipcRenderer } from "electron";
import { app } from "@electron/remote";

let imageBitmap;
const imageBitmapQueue = [];
Expand Down Expand Up @@ -58,7 +59,7 @@ export default class ModV {

this.$worker.postMessage({
type: "__dirname",
payload: remote.app.getAppPath()
payload: app.getAppPath()
});

this.$worker.addEventListener("message", e => {
Expand Down
115 changes: 115 additions & 0 deletions src/application/renderers/three.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import store from "../worker/store";
import * as THREE from "three/build/three.module.js";

const threeCanvas = new OffscreenCanvas(300, 300);
const threeContext = threeCanvas.getContext("webgl2", {
antialias: true,
desynchronized: true,
powerPreference: "high-performance",
premultipliedAlpha: false
});

store.dispatch("outputs/addAuxillaryOutput", {
name: "three-buffer",
context: threeContext,
group: "buffer"
});

const renderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true,
canvas: threeCanvas
});
renderer.setPixelRatio(1);

const inputTextureCanvas = new OffscreenCanvas(300, 300);
const inputTextureContext = inputTextureCanvas.getContext("2d");
store.dispatch("outputs/addAuxillaryOutput", {
name: "three-inputTexture-buffer",
context: inputTextureContext,
group: "buffer"
});

const inputTexture = new THREE.CanvasTexture(inputTextureCanvas);

/**
* Called each frame to update the Module
* @param {Object} Module A three Module
* @param {HTMLCanvas} canvas The Canvas to draw to
* @param {WebGL2RenderingContext} context The Context of the Canvas
* @param {HTMLVideoElement} video The video stream requested by modV
* @param {Array<MeydaFeatures>} features Requested Meyda features
* @param {Meyda} meyda The Meyda instance
* (for Windowing functions etc.)
*
* @param {DOMHighResTimeStamp} delta Timestamp returned by requestAnimationFrame
* @param {Number} bpm The detected or tapped BPM
* @param {Boolean} kick Indicates if BeatDetektor detected a kick in
* the audio stream
*/
function render({
module,
canvas,
context,
video,
features,
meyda,
delta,
bpm,
kick,
props,
data,
fftCanvas,
pipeline
}) {
inputTextureContext.drawImage(canvas, 0, 0, canvas.width, canvas.height);
inputTexture.image = inputTextureCanvas.transferToImageBitmap();
inputTexture.needsUpdate = true;

const { scene, camera } = module.draw({
THREE,
inputTexture,
canvas,
video,
features,
meyda,
delta,
bpm,
kick,
props,
data,
fftCanvas
});

renderer.render(scene, camera);

// clear context if we're in pipeline mode
if (pipeline) {
context.clearRect(0, 0, canvas.width, canvas.height);
}

// Copy three Canvas to Main Canvas
context.drawImage(threeCanvas, 0, 0, canvas.width, canvas.height);
}

function setupModule(module) {
const moduleData = module.setupThree({
THREE,
inputTexture,
data: module.data || {},
width: renderer.domElement.width,
height: renderer.domElement.height
});

module.data = moduleData;

return module;
}

function resize({ width, height }) {
inputTextureCanvas.width = width;
inputTextureCanvas.height = height;
renderer.setSize(width, height, false);
}

export default { render, resize, setupModule };
125 changes: 125 additions & 0 deletions src/application/sample-modules/Cube.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
export default {
meta: {
name: "Cube",
author: "2xAA",
type: "three"
},

props: {
rotation: {
type: "vec3",
default: [0, 0, 0],
min: 0,
max: 1
},

scale: {
type: "vec3",
default: [1, 1, 1],
min: 0,
max: 1
},

position: {
type: "vec3",
default: [0, 0, 0],
min: 0,
max: 1
},

color: {
type: "color",
default: {
r: 1,
g: 1,
b: 1,
a: 1
}
},

useMap: {
type: "bool",
default: false
}
},

data: {
camera: null,
scene: null,
cubeMesh: null
},

setupThree({ THREE, data, width, height, inputTexture }) {
const camera = new THREE.PerspectiveCamera(40, width / height, 1, 1000);
camera.position.z = 5;

const scene = new THREE.Scene();
scene.background = null;

const light = new THREE.AmbientLight(0xffffff);
scene.add(light);

const pointLight = new THREE.PointLight(0xffffff, 1, 100);
pointLight.position.set(50, 50, 50);
scene.add(pointLight);

const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({
color: "#ffffff",
roughness: 0.351,
map: inputTexture
});
const cubeMesh = new THREE.Mesh(geometry, material);

scene.add(cubeMesh);

return { ...data, camera, scene, cubeMesh };
},

resize({ canvas: { width, height }, data }) {
data.camera.aspect = width / height;
data.camera.updateProjectionMatrix();

return { ...data };
},

draw({
THREE,
data,
data: { scene, camera },
props: {
scale,
position,
rotation,
color: { r, g, b },
useMap
},
inputTexture
}) {
data.cubeMesh.position.x = position[0];
data.cubeMesh.position.y = position[1];
data.cubeMesh.position.z = position[2];

data.cubeMesh.scale.x = scale[0];
data.cubeMesh.scale.y = scale[1];
data.cubeMesh.scale.z = scale[2];

data.cubeMesh.rotation.x = rotation[0] * 360 * THREE.Math.DEG2RAD;
data.cubeMesh.rotation.y = rotation[1] * 360 * THREE.Math.DEG2RAD;
data.cubeMesh.rotation.z = rotation[2] * 360 * THREE.Math.DEG2RAD;

if (useMap && !data.cubeMesh.material.map) {
data.cubeMesh.material.map = inputTexture;
data.cubeMesh.material.needsUpdate = true;
} else if (!useMap && data.cubeMesh.material.map) {
data.cubeMesh.material.map = undefined;
data.cubeMesh.material.needsUpdate = true;
}

data.cubeMesh.material.color.r = r;
data.cubeMesh.material.color.g = g;
data.cubeMesh.material.color.b = b;

return { scene, camera };
}
};
4 changes: 2 additions & 2 deletions src/application/worker/store/modules/dataTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ const state = {
const { path } = options;
let id;
try {
id = await store.dispatch("images/createImageFromPath", {
({ id } = await store.dispatch("images/createImageFromPath", {
path
}).id;
}));
} catch (e) {
console.error(e);
}
Expand Down
2 changes: 2 additions & 0 deletions src/background/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { APP_SCHEME } from "./background-constants";
import { openFile } from "./open-file";
import { createWindow } from "./windows";

require("@electron/remote/main").initialize();

const isDevelopment = process.env.NODE_ENV !== "production";

// Scheme must be registered before the app is ready
Expand Down
13 changes: 10 additions & 3 deletions src/background/menu-bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,10 +217,17 @@ export function generateMenuTemplate() {
role: "help",
submenu: [
{
label: "Learn More",
click: async () => {
label: "Learn modV",
click() {
const { shell } = require("electron");
await shell.openExternal("https://modv.js.org");
shell.openExternal("https://modv.js.org");
}
},
{
label: "Search or ask a question",
click() {
const { shell } = require("electron");
shell.openExternal("https://github.com/vcync/modV/discussions");
}
}
]
Expand Down
5 changes: 5 additions & 0 deletions src/background/window-prefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ const windowPrefs = {
show: isDevelopment,
webPreferences: {
enableRemoteModule: true,
// electron 12 sets contextIsolation to true by default, this breaks modV
contextIsolation: false,
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
Expand All @@ -60,6 +62,8 @@ const windowPrefs = {
},

async create(window) {
require("@electron/remote/main").enable(window.webContents);

// Configure child windows to open without a menubar (windows/linux)
window.webContents.on(
"new-window",
Expand Down Expand Up @@ -198,6 +202,7 @@ const windowPrefs = {
console.error(e);
}

windows["mainWindow"].maximize();
windows["mainWindow"].show();
});
}
Expand Down
3 changes: 2 additions & 1 deletion vue.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ module.exports = {
"This app requires camera access to record video.",
NSMicrophoneUsageDescription:
"This app requires microphone access to record audio."
}
},
target: ["dmg"]
},

dmg: {
Expand Down
Loading

0 comments on commit a30b860

Please sign in to comment.