diff --git a/editor/electron/api/handlers.ts b/editor/electron/api/handlers.ts
new file mode 100644
index 00000000..452db51f
--- /dev/null
+++ b/editor/electron/api/handlers.ts
@@ -0,0 +1,11 @@
+import vnscene from './vnscene';
+
+export const API_HANDLERS:{
+ [key:string]:(...args:any)=>any
+} = {};
+
+const addHandlers = (handlers:{[key:string]:(...args:any)=>any}) => {
+ Object.keys(handlers).forEach(key => API_HANDLERS[key] = handlers[key]);
+}
+
+addHandlers(vnscene);
diff --git a/editor/electron/api/vnscene.ts b/editor/electron/api/vnscene.ts
new file mode 100644
index 00000000..5b63ced2
--- /dev/null
+++ b/editor/electron/api/vnscene.ts
@@ -0,0 +1,6 @@
+export default {
+ "vnscene:test": (bruh1:string, bruh2:string) => {
+ console.log("vnscene:test", bruh1, bruh2);
+ return 'test?';
+ }
+};
\ No newline at end of file
diff --git a/editor/electron/main.ts b/editor/electron/main.ts
new file mode 100644
index 00000000..b55103b4
--- /dev/null
+++ b/editor/electron/main.ts
@@ -0,0 +1,64 @@
+import { app, BrowserWindow, ipcMain } from 'electron';
+import * as path from 'path';
+import installExtension, { REACT_DEVELOPER_TOOLS } from "electron-devtools-installer";
+import { API_HANDLERS } from './api/handlers';
+
+function createWindow() {
+ const win = new BrowserWindow({
+ width: 800,
+ height: 600,
+ webPreferences: {
+ // contextIsolation: false,
+ preload: path.join(__dirname, 'preload.js')
+ }
+ })
+
+ if (app.isPackaged) {
+ // 'build/index.html'
+ win.loadURL(`file://${__dirname}/../index.html`);
+ } else {
+ win.loadURL('http://localhost:3000/index.html');
+
+ win.webContents.openDevTools();
+
+ // Hot Reloading on 'node_modules/.bin/electronPath'
+ require('electron-reload')(__dirname, {
+ electron: path.join(__dirname,
+ '..',
+ '..',
+ 'node_modules',
+ '.bin',
+ 'electron' + (process.platform === "win32" ? ".cmd" : "")),
+ forceHardReset: true,
+ hardResetMethod: 'exit'
+ });
+ }
+}
+
+app.whenReady().then(() => {
+ // DevTools
+ installExtension(REACT_DEVELOPER_TOOLS)
+ .then((name) => console.log(`Added Extension: ${name}`))
+ .catch((err) => console.log('An error occurred: ', err));
+
+ createWindow();
+
+ app.on('activate', () => {
+ if (BrowserWindow.getAllWindows().length === 0) {
+ createWindow();
+ }
+ });
+
+ app.on('window-all-closed', () => {
+ if (process.platform !== 'darwin') {
+ app.quit();
+ }
+ });
+
+ // Add API Handlers
+ Object.entries(API_HANDLERS).forEach(entry => {
+ ipcMain.handle(entry[0], (event:any, ...args:any) => {
+ return entry[1](...args);
+ });
+ })
+});
diff --git a/editor/electron/preload.ts b/editor/electron/preload.ts
new file mode 100644
index 00000000..d6f98ffb
--- /dev/null
+++ b/editor/electron/preload.ts
@@ -0,0 +1,13 @@
+import { contextBridge, ipcRenderer } from 'electron';
+
+const API_HANDLERS = [
+ "vnscene:test"
+];
+
+contextBridge.exposeInMainWorld(
+ 'dawnapi',
+ API_HANDLERS.reduce((acc, key) => {
+ acc[key] = (...args:any) => ipcRenderer.invoke(key, ...args);
+ return acc;
+ }, {} as {[key:string]:()=>any})
+);
\ No newline at end of file
diff --git a/editor/electron/tsconfig.json b/editor/electron/tsconfig.json
new file mode 100644
index 00000000..d97a2c34
--- /dev/null
+++ b/editor/electron/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "module": "commonjs",
+ "sourceMap": true,
+ "strict": true,
+ "outDir": "../build",
+ "rootDir": "../",
+ "noEmitOnError": true,
+ "typeRoots": [
+ "node_modules/@types"
+ ]
+ }
+}
diff --git a/editor/package.json b/editor/package.json
new file mode 100644
index 00000000..2292a0fd
--- /dev/null
+++ b/editor/package.json
@@ -0,0 +1,63 @@
+{
+ "main": "build/electron/main.js",
+ "dependencies": {
+ "@testing-library/jest-dom": "^5.16.5",
+ "@testing-library/react": "^13.4.0",
+ "@testing-library/user-event": "^14.4.3",
+ "@types/electron-devtools-installer": "^2.2.2",
+ "@types/jest": "^29.4.0",
+ "@types/node": "^18.13.0",
+ "@types/react": "^18.0.28",
+ "@types/react-dom": "^18.0.11",
+ "electron-devtools-installer": "^3.2.0",
+ "electron-reload": "^1.5.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0",
+ "react-scripts": "5.0.1",
+ "typescript": "^4.9.5",
+ "web-vitals": "^3.1.1"
+ },
+ "scripts": {
+ "start": "react-scripts start",
+ "build": "react-scripts build",
+ "test": "react-scripts test",
+ "postinstall": "electron-builder install-app-deps",
+ "electron:dev": "concurrently \"cross-env BROWSER=none yarn start\" \"wait-on http://127.0.0.1:3000 && tsc -p electron -w\" \"wait-on http://127.0.0.1:3000 && tsc -p electron && electron .\"",
+ "electron:build": "yarn build && tsc -p electron && electron-builder",
+ "eject": "react-scripts eject"
+ },
+ "build": {
+ "extends": null,
+ "files": [
+ "build/**/*"
+ ],
+ "directories": {
+ "buildResources": "assets"
+ }
+ },
+ "eslintConfig": {
+ "extends": [
+ "react-app",
+ "react-app/jest"
+ ]
+ },
+ "browserslist": {
+ "production": [
+ ">0.2%",
+ "not dead",
+ "not op_mini all"
+ ],
+ "development": [
+ "last 1 chrome version",
+ "last 1 firefox version",
+ "last 1 safari version"
+ ]
+ },
+ "devDependencies": {
+ "concurrently": "^7.6.0",
+ "cross-env": "^7.0.3",
+ "electron": "^23.1.0",
+ "electron-builder": "^23.6.0",
+ "wait-on": "^7.0.1"
+ }
+}
diff --git a/editor/public/favicon.ico b/editor/public/favicon.ico
new file mode 100644
index 00000000..c2c86b85
Binary files /dev/null and b/editor/public/favicon.ico differ
diff --git a/editor/public/index.html b/editor/public/index.html
new file mode 100644
index 00000000..a146b6fd
--- /dev/null
+++ b/editor/public/index.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ React App
+
+
+
+
+
+
+
diff --git a/editor/public/logo192.png b/editor/public/logo192.png
new file mode 100644
index 00000000..fa313abf
Binary files /dev/null and b/editor/public/logo192.png differ
diff --git a/editor/public/logo512.png b/editor/public/logo512.png
new file mode 100644
index 00000000..bd5d4b5e
Binary files /dev/null and b/editor/public/logo512.png differ
diff --git a/editor/public/manifest.json b/editor/public/manifest.json
new file mode 100644
index 00000000..080d6c77
--- /dev/null
+++ b/editor/public/manifest.json
@@ -0,0 +1,25 @@
+{
+ "short_name": "React App",
+ "name": "Create React App Sample",
+ "icons": [
+ {
+ "src": "favicon.ico",
+ "sizes": "64x64 32x32 24x24 16x16",
+ "type": "image/x-icon"
+ },
+ {
+ "src": "logo192.png",
+ "type": "image/png",
+ "sizes": "192x192"
+ },
+ {
+ "src": "logo512.png",
+ "type": "image/png",
+ "sizes": "512x512"
+ }
+ ],
+ "start_url": ".",
+ "display": "standalone",
+ "theme_color": "#000000",
+ "background_color": "#ffffff"
+}
diff --git a/editor/public/robots.txt b/editor/public/robots.txt
new file mode 100644
index 00000000..01b0f9a1
--- /dev/null
+++ b/editor/public/robots.txt
@@ -0,0 +1,2 @@
+# https://www.robotstxt.org/robotstxt.html
+User-agent: *
diff --git a/editor/src/App.tsx b/editor/src/App.tsx
new file mode 100644
index 00000000..62f8f900
--- /dev/null
+++ b/editor/src/App.tsx
@@ -0,0 +1,19 @@
+import { VNSceneEditor } from "./views/VNSceneEditor";
+
+export const App = () => {
+ return (
+ <>
+
+
+
+
+
+
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/editor/src/api/base.ts b/editor/src/api/base.ts
new file mode 100644
index 00000000..b5aa6193
--- /dev/null
+++ b/editor/src/api/base.ts
@@ -0,0 +1,4 @@
+//@ts-ignore
+const wdawnapi = (globalThis['dawnapi'] as any);
+
+export const API_BASE = wdawnapi;
\ No newline at end of file
diff --git a/editor/src/api/index.ts b/editor/src/api/index.ts
new file mode 100644
index 00000000..452aca22
--- /dev/null
+++ b/editor/src/api/index.ts
@@ -0,0 +1 @@
+export * from './vnscene';
\ No newline at end of file
diff --git a/editor/src/api/vnscene.ts b/editor/src/api/vnscene.ts
new file mode 100644
index 00000000..cedfe6cf
--- /dev/null
+++ b/editor/src/api/vnscene.ts
@@ -0,0 +1,3 @@
+import { API_BASE } from "./base";
+
+export const doVnTest = API_BASE['vnscene:test'] as (bruh1:string, bruh2:string) => Promise;
\ No newline at end of file
diff --git a/editor/src/index.css b/editor/src/index.css
new file mode 100644
index 00000000..d80b7c71
--- /dev/null
+++ b/editor/src/index.css
@@ -0,0 +1,4 @@
+html,body {
+ margin: 0;
+ padding: 0;
+}
\ No newline at end of file
diff --git a/editor/src/index.tsx b/editor/src/index.tsx
new file mode 100644
index 00000000..b071fc2d
--- /dev/null
+++ b/editor/src/index.tsx
@@ -0,0 +1,17 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import './index.css';
+import { App } from './App';
+import reportWebVitals from './reportWebVitals';
+
+const root = ReactDOM.createRoot(document.getElementById('root')!);
+root.render(
+
+
+
+);
+
+// If you want to start measuring performance in your app, pass a function
+// to log results (for example: reportWebVitals(console.log))
+// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
+reportWebVitals();
diff --git a/editor/src/react-app-env.d.ts b/editor/src/react-app-env.d.ts
new file mode 100644
index 00000000..6431bc5f
--- /dev/null
+++ b/editor/src/react-app-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/editor/src/reportWebVitals.ts b/editor/src/reportWebVitals.ts
new file mode 100644
index 00000000..49a2a16e
--- /dev/null
+++ b/editor/src/reportWebVitals.ts
@@ -0,0 +1,15 @@
+import { ReportHandler } from 'web-vitals';
+
+const reportWebVitals = (onPerfEntry?: ReportHandler) => {
+ if (onPerfEntry && onPerfEntry instanceof Function) {
+ import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
+ getCLS(onPerfEntry);
+ getFID(onPerfEntry);
+ getFCP(onPerfEntry);
+ getLCP(onPerfEntry);
+ getTTFB(onPerfEntry);
+ });
+ }
+};
+
+export default reportWebVitals;
diff --git a/editor/src/setupTests.ts b/editor/src/setupTests.ts
new file mode 100644
index 00000000..8f2609b7
--- /dev/null
+++ b/editor/src/setupTests.ts
@@ -0,0 +1,5 @@
+// jest-dom adds custom jest matchers for asserting on DOM nodes.
+// allows you to do things like:
+// expect(element).toHaveTextContent(/react/i)
+// learn more: https://github.com/testing-library/jest-dom
+import '@testing-library/jest-dom';
diff --git a/editor/src/views/VNSceneEditor.tsx b/editor/src/views/VNSceneEditor.tsx
new file mode 100644
index 00000000..5cdbc0d9
--- /dev/null
+++ b/editor/src/views/VNSceneEditor.tsx
@@ -0,0 +1,16 @@
+import React, { useState } from 'react';
+import { doVnTest } from '../api';
+
+export const VNSceneEditor = () => {
+ const [ test, setTest ] = useState('');
+
+ return (
+
+ VN Scene Editor
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/editor/tsconfig.json b/editor/tsconfig.json
new file mode 100644
index 00000000..a273b0cf
--- /dev/null
+++ b/editor/tsconfig.json
@@ -0,0 +1,26 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "noFallthroughCasesInSwitch": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx"
+ },
+ "include": [
+ "src"
+ ]
+}