[!!!!!!!!!!!!!!!] Remove new-home
This commit is contained in:
@@ -14,10 +14,8 @@
|
|||||||
"emoji-regex": "^10.2.1",
|
"emoji-regex": "^10.2.1",
|
||||||
"linkify-urls": "^4.0.0",
|
"linkify-urls": "^4.0.0",
|
||||||
"marked": "^4.2.12",
|
"marked": "^4.2.12",
|
||||||
"meshline": "^3.1.6",
|
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"tg-blog": "^1.1.0",
|
"tg-blog": "^1.1.0",
|
||||||
"three": "^0.150.1",
|
|
||||||
"vue": "^3.2.47",
|
"vue": "^3.2.47",
|
||||||
"vue-i18n": "^9.2.2",
|
"vue-i18n": "^9.2.2",
|
||||||
"vue-router": "^4.1.6",
|
"vue-router": "^4.1.6",
|
||||||
@@ -28,7 +26,6 @@
|
|||||||
"@types/jqueryui": "^1.12.16",
|
"@types/jqueryui": "^1.12.16",
|
||||||
"@types/marked": "^4.0.7",
|
"@types/marked": "^4.0.7",
|
||||||
"@types/node": "^18.14.5",
|
"@types/node": "^18.14.5",
|
||||||
"@types/three": "^0.149.0",
|
|
||||||
"@vitejs/plugin-vue": "^4.0.0",
|
"@vitejs/plugin-vue": "^4.0.0",
|
||||||
"eslint": "^8.35.0",
|
"eslint": "^8.35.0",
|
||||||
"sass": "^1.58.3",
|
"sass": "^1.58.3",
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
import {Color} from "three";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Configurations
|
|
||||||
*/
|
|
||||||
export const config = {
|
|
||||||
|
|
||||||
// Field of vision and cutoff frustum for near and far
|
|
||||||
cam: {fov: 50, near: 1, far: 5000},
|
|
||||||
|
|
||||||
// Smooth movements (speeds are in terms of pixels per ms)
|
|
||||||
smooth: {mouseSpeed: 10 * window.devicePixelRatio},
|
|
||||||
|
|
||||||
// Cursor
|
|
||||||
cursor: {radius: 2, width: 0.3, color: new Color('#333')},
|
|
||||||
|
|
||||||
// Debug mode
|
|
||||||
debug: false,
|
|
||||||
|
|
||||||
// Edit mode
|
|
||||||
editMode: true,
|
|
||||||
|
|
||||||
// Editor config
|
|
||||||
editor: {zMin: 70, zMax: 90}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const colors = {
|
|
||||||
sky: {
|
|
||||||
top: new Color('#3284ff'),
|
|
||||||
bottom: new Color('#ffffff'),
|
|
||||||
ground: new Color('#ffc87f'),
|
|
||||||
dirLight: new Color('#fff4e5')
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
import * as THREE from 'three'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a 3D box geometry made out of dashed lines
|
|
||||||
* @param width
|
|
||||||
* @param height
|
|
||||||
* @param depth
|
|
||||||
*/
|
|
||||||
export function box(width: number, height: number, depth: number): THREE.BufferGeometry
|
|
||||||
{
|
|
||||||
width = width * 0.5
|
|
||||||
height = height * 0.5
|
|
||||||
depth = depth * 0.5
|
|
||||||
|
|
||||||
const geometry = new THREE.BufferGeometry();
|
|
||||||
const position = [];
|
|
||||||
|
|
||||||
for (const x of [-1, 1])
|
|
||||||
for (const y of [-1, 1])
|
|
||||||
for (const z of [-1, 1])
|
|
||||||
{
|
|
||||||
const rx = x * width, ry = y * height, rz = z * depth
|
|
||||||
position.push(rx, ry, rz)
|
|
||||||
position.push(rx * -x, ry, rz)
|
|
||||||
position.push(rx, ry, rz)
|
|
||||||
position.push(rx, ry * -y, rz)
|
|
||||||
position.push(rx, ry, rz)
|
|
||||||
position.push(rx, ry, rz * -z)
|
|
||||||
}
|
|
||||||
|
|
||||||
geometry.setAttribute('position', new THREE.Float32BufferAttribute(position, 3))
|
|
||||||
return geometry
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a 2D circle
|
|
||||||
* @param color
|
|
||||||
* @param z
|
|
||||||
* @param r
|
|
||||||
* @param hollow
|
|
||||||
*/
|
|
||||||
export function circle(color: THREE.Color | number | string, z: number, r: number): THREE.Mesh
|
|
||||||
{
|
|
||||||
const geometry = new THREE.CircleGeometry(r, 64)
|
|
||||||
const material = new THREE.MeshBasicMaterial({color})
|
|
||||||
const circle = new THREE.Mesh(geometry, material)
|
|
||||||
circle.position.z = z
|
|
||||||
return circle
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ignore depth https://stackoverflow.com/a/62818553/7346633
|
|
||||||
* @param obj
|
|
||||||
* @param material
|
|
||||||
*/
|
|
||||||
export function alwaysOnTop(obj: THREE.Object3D, material: THREE.Material): void
|
|
||||||
{
|
|
||||||
obj.renderOrder = 999
|
|
||||||
material.depthTest = false
|
|
||||||
material.depthWrite = false
|
|
||||||
obj.onBeforeRender = (r) => r.clearDepth()
|
|
||||||
}
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
import * as THREE from 'three'
|
|
||||||
import {Color} from 'three'
|
|
||||||
import * as helper from "@/animation/Helpers"
|
|
||||||
import {initMouseTracker} from "@/animation/Trackers"
|
|
||||||
import {addDirLight, addGround, addHemiLight, addSky} from "@/animation/Shaders"
|
|
||||||
import {config} from "@/animation/Config"
|
|
||||||
import Cursor from "@/animation/components/Cursor";
|
|
||||||
import IUpdatable from "@/animation/components/IUpdatable";
|
|
||||||
import Grid from "@/animation/components/Grid";
|
|
||||||
import Editor from "@/animation/components/Editor";
|
|
||||||
|
|
||||||
export let renderer: THREE.WebGLRenderer, scene: THREE.Scene, camera: THREE.PerspectiveCamera
|
|
||||||
export let editor: Editor
|
|
||||||
const clock = new THREE.Clock()
|
|
||||||
export const objects: { [id: string]: THREE.Object3D } = {}
|
|
||||||
const updatable: IUpdatable[] = []
|
|
||||||
|
|
||||||
// ////////////////////
|
|
||||||
// Three.js scene code
|
|
||||||
|
|
||||||
function init(): void
|
|
||||||
{
|
|
||||||
const geometryBox = helper.box(50, 50, 1000)
|
|
||||||
|
|
||||||
const lineSegments = new THREE.LineSegments(geometryBox, new THREE.LineDashedMaterial({
|
|
||||||
color: "#420000",
|
|
||||||
dashSize: 3,
|
|
||||||
gapSize: 1
|
|
||||||
}))
|
|
||||||
lineSegments.computeLineDistances()
|
|
||||||
|
|
||||||
updatable.push(new Cursor(scene, config.cursor, camera))
|
|
||||||
updatable.push(new Grid(), editor = new Editor())
|
|
||||||
|
|
||||||
objects.box = lineSegments
|
|
||||||
scene.add(lineSegments)
|
|
||||||
|
|
||||||
// scene.add(circle(0xffff00, 0, 5))
|
|
||||||
// scene.add(circle(0xff00ff, 1, 4))
|
|
||||||
// scene.add(circle(0x0000ff, 2, 3))
|
|
||||||
// scene.add(circle(0x00ffff, 3, 2))
|
|
||||||
// scene.add(circle(0xff0000, 4, 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Buffer for smooth update
|
|
||||||
const smoothBuffer = {cam: {x: 0, y: 0}}
|
|
||||||
|
|
||||||
function pn(b: boolean): number
|
|
||||||
{
|
|
||||||
return b ? 1 : -1
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update frame
|
|
||||||
*
|
|
||||||
* @param dt delta time in ms
|
|
||||||
*/
|
|
||||||
function update(dt: number): void
|
|
||||||
{
|
|
||||||
// objects['cursor'].position.set(moused.x, moused.y, 150)
|
|
||||||
|
|
||||||
// smoothBuffer.cam.x = moused.x * config.mouseFactor
|
|
||||||
// smoothBuffer.cam.y = moused.y * config.mouseFactor
|
|
||||||
// smoothUpdate()
|
|
||||||
|
|
||||||
// const time = Date.now() * 0.001
|
|
||||||
// objects.box.rotation.x = 0.25 * time
|
|
||||||
// objects.box.rotation.y = 0.25 * time
|
|
||||||
|
|
||||||
function smoothUpdate(): void
|
|
||||||
{
|
|
||||||
// Pixels moved = speed * time
|
|
||||||
const delta = config.smooth.mouseSpeed * dt
|
|
||||||
// Current position
|
|
||||||
const cp = camera.position
|
|
||||||
// Target position
|
|
||||||
const tp = smoothBuffer.cam
|
|
||||||
|
|
||||||
if (Math.abs(cp.x - tp.x) > delta)
|
|
||||||
{
|
|
||||||
cp.x = cp.x + delta * pn(cp.x < tp.x)
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
cp.x = tp.x
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Math.abs(cp.y - tp.y) > delta)
|
|
||||||
{
|
|
||||||
cp.y = cp.y + delta * pn(cp.y < tp.y)
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
cp.y = tp.y
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ///////////////////
|
|
||||||
// Three.js meta code
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start the three.js rendering engine
|
|
||||||
*
|
|
||||||
* @param id: Canvas element id
|
|
||||||
*/
|
|
||||||
export function start(id: string): void
|
|
||||||
{
|
|
||||||
scene = new THREE.Scene()
|
|
||||||
scene.background = new Color('#f9f2e0')
|
|
||||||
// Create camera
|
|
||||||
camera = new THREE.PerspectiveCamera(config.cam.fov, window.innerWidth / window.innerHeight,
|
|
||||||
config.cam.near, config.cam.far)
|
|
||||||
camera.position.set(0, 0, 200)
|
|
||||||
camera.lookAt(0, 0, 0)
|
|
||||||
|
|
||||||
// @ts-ignore Create WebGL Renderer
|
|
||||||
renderer = new THREE.WebGLRenderer({canvas: document.getElementById(id), antialias: true})
|
|
||||||
onWindowResize()
|
|
||||||
window.addEventListener('resize', onWindowResize)
|
|
||||||
|
|
||||||
addLights()
|
|
||||||
|
|
||||||
init()
|
|
||||||
initMouseTracker()
|
|
||||||
animate()
|
|
||||||
}
|
|
||||||
|
|
||||||
function addLights(): void
|
|
||||||
{
|
|
||||||
objects.hemiLight = addHemiLight(scene)
|
|
||||||
objects.dirLight = addDirLight(scene)
|
|
||||||
objects.ground = addGround(scene)
|
|
||||||
objects.sky = addSky(scene)
|
|
||||||
objects.sky.visible = false
|
|
||||||
objects.ground.visible = false
|
|
||||||
|
|
||||||
renderer.outputEncoding = THREE.sRGBEncoding
|
|
||||||
renderer.shadowMap.enabled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
function onWindowResize()
|
|
||||||
{
|
|
||||||
camera.aspect = window.innerWidth / window.innerHeight
|
|
||||||
camera.updateProjectionMatrix()
|
|
||||||
|
|
||||||
renderer.setPixelRatio(window.devicePixelRatio)
|
|
||||||
renderer.setSize(window.innerWidth, window.innerHeight)
|
|
||||||
}
|
|
||||||
|
|
||||||
function animate(): void
|
|
||||||
{
|
|
||||||
requestAnimationFrame(animate)
|
|
||||||
const dt = clock.getDelta()
|
|
||||||
update(dt)
|
|
||||||
for (const o of updatable) o.update(dt)
|
|
||||||
renderer.render(scene, camera)
|
|
||||||
}
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
import * as THREE from 'three'
|
|
||||||
import {DirectionalLight, HemisphereLight, Mesh} from 'three'
|
|
||||||
import {colors, config} from "@/animation/Config";
|
|
||||||
|
|
||||||
export const vertexShader = `
|
|
||||||
varying vec3 vWorldPosition;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec4 worldPosition = modelMatrix * vec4( position, 1.0 );
|
|
||||||
vWorldPosition = worldPosition.xyz;
|
|
||||||
|
|
||||||
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
||||||
}`;
|
|
||||||
|
|
||||||
export const fragmentShader = `
|
|
||||||
uniform vec3 topColor;
|
|
||||||
uniform vec3 bottomColor;
|
|
||||||
uniform float offset;
|
|
||||||
uniform float exponent;
|
|
||||||
|
|
||||||
varying vec3 vWorldPosition;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
float h = normalize( vWorldPosition + offset ).y;
|
|
||||||
gl_FragColor = vec4( mix( bottomColor, topColor, max( pow( max( h , 0.0), exponent ), 0.0 ) ), 1.0 );
|
|
||||||
}`;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create sky dome
|
|
||||||
* @param scene
|
|
||||||
*/
|
|
||||||
export function addSky(scene: THREE.Scene): Mesh
|
|
||||||
{
|
|
||||||
const uniforms = {
|
|
||||||
"topColor": { value: colors.sky.top },
|
|
||||||
"bottomColor": { value: colors.sky.bottom },
|
|
||||||
"offset": { value: 33 },
|
|
||||||
"exponent": { value: 0.6 }
|
|
||||||
}
|
|
||||||
|
|
||||||
const skyGeo = new THREE.SphereGeometry( 4000, 32, 15 );
|
|
||||||
const skyMat = new THREE.ShaderMaterial({
|
|
||||||
uniforms: uniforms,
|
|
||||||
vertexShader: vertexShader,
|
|
||||||
fragmentShader: fragmentShader,
|
|
||||||
side: THREE.BackSide
|
|
||||||
});
|
|
||||||
|
|
||||||
const sky = new THREE.Mesh(skyGeo, skyMat)
|
|
||||||
scene.add(sky)
|
|
||||||
scene.fog = new THREE.Fog(colors.sky.bottom, 1, 5000)
|
|
||||||
|
|
||||||
return sky
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create ground
|
|
||||||
* @param scene
|
|
||||||
*/
|
|
||||||
export function addGround(scene: THREE.Scene): Mesh
|
|
||||||
{
|
|
||||||
const groundGeo = new THREE.PlaneGeometry(10000, 10000)
|
|
||||||
const groundMat = new THREE.MeshLambertMaterial({color: colors.sky.ground})
|
|
||||||
const ground = new THREE.Mesh(groundGeo, groundMat)
|
|
||||||
ground.position.y = -33
|
|
||||||
ground.rotation.x = -Math.PI / 2
|
|
||||||
ground.receiveShadow = true
|
|
||||||
scene.add(ground)
|
|
||||||
|
|
||||||
return ground
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add hemisphere light
|
|
||||||
* @param scene
|
|
||||||
*/
|
|
||||||
export function addHemiLight(scene: THREE.Scene): HemisphereLight
|
|
||||||
{
|
|
||||||
const hemiLight = new THREE.HemisphereLight(colors.sky.top, colors.sky.ground, 0.6)
|
|
||||||
hemiLight.position.set(0, 50, 0)
|
|
||||||
scene.add(hemiLight)
|
|
||||||
|
|
||||||
if (config.debug) scene.add(new THREE.HemisphereLightHelper(hemiLight, 10))
|
|
||||||
|
|
||||||
return hemiLight
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add directional light
|
|
||||||
* @param scene
|
|
||||||
*/
|
|
||||||
export function addDirLight(scene: THREE.Scene): DirectionalLight
|
|
||||||
{
|
|
||||||
// Directional light
|
|
||||||
const dirLight = new THREE.DirectionalLight(colors.sky.dirLight, 1)
|
|
||||||
dirLight.position.set(-1, 1.75, 1)
|
|
||||||
dirLight.position.multiplyScalar(30)
|
|
||||||
scene.add(dirLight)
|
|
||||||
|
|
||||||
dirLight.castShadow = true
|
|
||||||
|
|
||||||
dirLight.shadow.mapSize.width = 2048
|
|
||||||
dirLight.shadow.mapSize.height = 2048
|
|
||||||
|
|
||||||
const d = 50
|
|
||||||
|
|
||||||
dirLight.shadow.camera.left = -d
|
|
||||||
dirLight.shadow.camera.right = d
|
|
||||||
dirLight.shadow.camera.top = d
|
|
||||||
dirLight.shadow.camera.bottom = -d
|
|
||||||
|
|
||||||
dirLight.shadow.camera.far = 3500
|
|
||||||
dirLight.shadow.bias = -0.0001
|
|
||||||
|
|
||||||
if (config.debug) scene.add(new THREE.DirectionalLightHelper(dirLight, 10))
|
|
||||||
|
|
||||||
return dirLight
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
import * as THREE from 'three'
|
|
||||||
import {Vector3} from 'three'
|
|
||||||
import {camera} from "@/animation/Home";
|
|
||||||
|
|
||||||
export let mouse: MouseEvent
|
|
||||||
export const moused = {x: 0, y: 0, pos: new Vector3()}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize mouse tracker
|
|
||||||
*/
|
|
||||||
export function initMouseTracker(): void
|
|
||||||
{
|
|
||||||
document.onmousemove = (e: MouseEvent) =>
|
|
||||||
{
|
|
||||||
mouse = e
|
|
||||||
moused.x = e.clientX / window.innerWidth * 2 - 1
|
|
||||||
moused.y = -(e.clientY / window.innerHeight * 2 - 1)
|
|
||||||
moused.pos = projectTo3D(moused.x, moused.y, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Project to 3D position
|
|
||||||
* https://www.reddit.com/r/threejs/comments/eba9l3/3d_cursor_using_threejs_html_css/
|
|
||||||
* https://jsfiddle.net/atwfxdpd/10/
|
|
||||||
*
|
|
||||||
* @param screenX X position on 2D canvas
|
|
||||||
* @param screenY Y position on 2D canvas
|
|
||||||
* @param z Z position in 3D
|
|
||||||
*/
|
|
||||||
export function projectTo3D(screenX: number, screenY: number, z: number): Vector3
|
|
||||||
{
|
|
||||||
const vector = new THREE.Vector3(screenX, screenY, 0.5)
|
|
||||||
vector.unproject(camera)
|
|
||||||
const dir = vector.sub(camera.position).normalize()
|
|
||||||
const distance = (-camera.position.z + z) / dir.z
|
|
||||||
const pos = camera.position.clone().add(dir.multiplyScalar(distance))
|
|
||||||
// console.log('Dir:', dir)
|
|
||||||
// console.log('Pos:', pos)
|
|
||||||
return pos
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
import * as THREE from "three";
|
|
||||||
import {Color, Material} from "three";
|
|
||||||
import {MeshLineGeometry, MeshLineMaterial} from 'meshline';
|
|
||||||
import IUpdatable from "@/animation/components/IUpdatable";
|
|
||||||
import {moused} from "@/animation/Trackers";
|
|
||||||
import {alwaysOnTop, circle} from "@/animation/Helpers";
|
|
||||||
|
|
||||||
type CursorConfig = {radius: number, color: Color, width: number}
|
|
||||||
|
|
||||||
export default class Cursor implements IUpdatable
|
|
||||||
{
|
|
||||||
camera: THREE.Camera
|
|
||||||
circle: CursorCircle
|
|
||||||
dot: THREE.Mesh
|
|
||||||
|
|
||||||
constructor(scene: THREE.Scene, conf: CursorConfig, camera: THREE.Camera)
|
|
||||||
{
|
|
||||||
this.camera = camera
|
|
||||||
this.circle = new CursorCircle(conf, camera)
|
|
||||||
scene.add(this.circle)
|
|
||||||
|
|
||||||
this.dot = circle('#000', 0, 0.3)
|
|
||||||
alwaysOnTop(this.dot, this.dot.material as Material)
|
|
||||||
scene.add(this.dot)
|
|
||||||
|
|
||||||
this.circle.visible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
update(dt: number): void
|
|
||||||
{
|
|
||||||
this.circle.update(dt)
|
|
||||||
this.dot.position.copy(moused.pos)
|
|
||||||
this.circle.position.copy(moused.pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CursorCircle extends THREE.Mesh implements IUpdatable
|
|
||||||
{
|
|
||||||
camera: THREE.Camera
|
|
||||||
|
|
||||||
constructor(conf: CursorConfig, camera: THREE.Camera)
|
|
||||||
{
|
|
||||||
// https://discourse.threejs.org/t/shift-vertices-of-circle-geometry-not-working/26664
|
|
||||||
const pts = new THREE.Path().absarc(0, 0, conf.radius, 0, Math.PI * 2, true).getPoints(90)
|
|
||||||
const geometry = new MeshLineGeometry()
|
|
||||||
geometry.setFromPoints(pts)
|
|
||||||
|
|
||||||
// MeshLine: https://stackoverflow.com/a/25759280/7346633
|
|
||||||
const material = new MeshLineMaterial({color: conf.color, lineWidth: conf.width,
|
|
||||||
resolution: new THREE.Vector2(window.innerWidth, window.innerHeight)})
|
|
||||||
super(geometry, material)
|
|
||||||
|
|
||||||
this.camera = camera
|
|
||||||
|
|
||||||
alwaysOnTop(this, material)
|
|
||||||
}
|
|
||||||
|
|
||||||
update(dt: number): void
|
|
||||||
{
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
import {Mesh, MeshBasicMaterial, Vector3} from "three";
|
|
||||||
import IUpdatable from "@/animation/components/IUpdatable";
|
|
||||||
import {circle} from "@/animation/Helpers";
|
|
||||||
import {scene} from "@/animation/Home";
|
|
||||||
import {moused, projectTo3D} from "@/animation/Trackers";
|
|
||||||
import {config} from "@/animation/Config";
|
|
||||||
import {minMax} from "@/scripts/utils";
|
|
||||||
|
|
||||||
type DisplayCircle = {x: number, y: number, z: number, radius: number, color: string}
|
|
||||||
|
|
||||||
export default class Editor implements IUpdatable
|
|
||||||
{
|
|
||||||
hand: Mesh
|
|
||||||
radius = 3
|
|
||||||
scale = 1
|
|
||||||
z = config.editor.zMax
|
|
||||||
data: DisplayCircle[] = []
|
|
||||||
circles: Mesh[] = []
|
|
||||||
|
|
||||||
constructor()
|
|
||||||
{
|
|
||||||
this.hand = circle('#ffffff', 0, this.radius)
|
|
||||||
scene.add(this.hand)
|
|
||||||
|
|
||||||
window.addEventListener('mousedown', (e) =>
|
|
||||||
{
|
|
||||||
console.log('clicked', e)
|
|
||||||
this.addCirc(this.radius * this.scale, this.hand.position, this.color)
|
|
||||||
})
|
|
||||||
|
|
||||||
window.addEventListener('wheel', (e) =>
|
|
||||||
{
|
|
||||||
let direction = (e.detail < 0 || e.deltaY > 0) ? 1 : -1;
|
|
||||||
|
|
||||||
// Shift to micro-adjust
|
|
||||||
if (e.shiftKey) direction /= 10
|
|
||||||
|
|
||||||
// Ctrl + Alt to shift the entire plane
|
|
||||||
if (e.altKey && e.ctrlKey)
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scroll to adjust z, alt + scroll to adjust radius
|
|
||||||
if (e.altKey)
|
|
||||||
{
|
|
||||||
this.scale -= direction / 10
|
|
||||||
this.hand.scale.set(this.scale, this.scale, this.scale)
|
|
||||||
}
|
|
||||||
else this.z = minMax(this.z - direction * 2, config.editor.zMin, config.editor.zMax)
|
|
||||||
|
|
||||||
}, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
addCirc(radius: number, pos: Vector3, color: string): void
|
|
||||||
{
|
|
||||||
const data = {...pos, radius, color}
|
|
||||||
data.z -= config.editor.zMax
|
|
||||||
this.data.push(data)
|
|
||||||
this.displayCirc(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
displayCirc(params: DisplayCircle): void
|
|
||||||
{
|
|
||||||
const circ = circle(params.color, 0, params.radius)
|
|
||||||
circ.position.x = params.x
|
|
||||||
circ.position.y = params.y
|
|
||||||
circ.position.z = params.z + config.editor.zMax
|
|
||||||
scene.add(circ)
|
|
||||||
this.circles.push(circ)
|
|
||||||
}
|
|
||||||
|
|
||||||
update(dt: number): void
|
|
||||||
{
|
|
||||||
const pos = projectTo3D(moused.x, moused.y, this.z)
|
|
||||||
this.hand.position.copy(pos)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
get color(): string
|
|
||||||
{
|
|
||||||
return '#' + this.handMaterial.color.getHexString()
|
|
||||||
}
|
|
||||||
|
|
||||||
set color(value: string)
|
|
||||||
{
|
|
||||||
this.handMaterial.color.setStyle(value.substr(0, 7))
|
|
||||||
}
|
|
||||||
|
|
||||||
get handMaterial(): MeshBasicMaterial { return (this.hand.material as MeshBasicMaterial) }
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
import * as THREE from "three";
|
|
||||||
import {GridHelper} from "three";
|
|
||||||
import {scene} from "@/animation/Home";
|
|
||||||
import IUpdatable from "@/animation/components/IUpdatable";
|
|
||||||
|
|
||||||
export default class Grid implements IUpdatable
|
|
||||||
{
|
|
||||||
lines = []
|
|
||||||
grid: GridHelper[] = []
|
|
||||||
|
|
||||||
constructor()
|
|
||||||
{
|
|
||||||
const size = 100
|
|
||||||
const divisions = 20
|
|
||||||
|
|
||||||
let color = new THREE.Color('#7a0c0c')
|
|
||||||
let grid = new THREE.GridHelper(size, divisions, color, color)
|
|
||||||
grid.rotation.x = Math.PI / 2
|
|
||||||
grid.position.z = 90
|
|
||||||
this.grid.push(grid)
|
|
||||||
|
|
||||||
color = new THREE.Color('#a4a4a4')
|
|
||||||
grid = new THREE.GridHelper(size, divisions, color, color)
|
|
||||||
grid.rotation.x = Math.PI / 2
|
|
||||||
grid.position.z = 70
|
|
||||||
this.grid.push(grid)
|
|
||||||
|
|
||||||
this.grid.forEach(it => scene.add(it))
|
|
||||||
}
|
|
||||||
|
|
||||||
update(dt: number): void
|
|
||||||
{
|
|
||||||
// this.grid.rotation.x = 0.25 * Date.now() * 0.001
|
|
||||||
// console.log(this.grid.rotation.x)
|
|
||||||
// this.grid.position.z += dt * 10
|
|
||||||
// console.log(this.grid.position.z)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export default interface IUpdatable
|
|
||||||
{
|
|
||||||
update: (dt: number) => void
|
|
||||||
}
|
|
||||||
@@ -8,12 +8,6 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
meta: {title: 'Home', nav: true},
|
meta: {title: 'Home', nav: true},
|
||||||
component: Home
|
component: Home
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/new-home',
|
|
||||||
name: 'New Home',
|
|
||||||
meta: {title: 'Home'},
|
|
||||||
component: () => import('../views/NewHome.vue')
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/about',
|
path: '/about',
|
||||||
name: 'About',
|
name: 'About',
|
||||||
|
|||||||
@@ -1,161 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="NewHome">
|
|
||||||
<canvas id="three"></canvas>
|
|
||||||
|
|
||||||
<!-- Editor controls -->
|
|
||||||
<div id="editor-controls">
|
|
||||||
<div>Editor</div>
|
|
||||||
|
|
||||||
<div class="separator"/>
|
|
||||||
|
|
||||||
<div>New</div>
|
|
||||||
<div>Save</div>
|
|
||||||
|
|
||||||
<div class="separator"/>
|
|
||||||
|
|
||||||
<div id="colors" class="fbox-h">
|
|
||||||
<div class="color" v-for="(c, i) in colors" :key="i" :style="{'background-color': c ?? '#333'}"
|
|
||||||
@click="e => openPicker(e, c)">
|
|
||||||
<div>{{(i + 1) % 10}}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="f-grow1"></div>
|
|
||||||
|
|
||||||
<div class="separator"/>
|
|
||||||
|
|
||||||
<div @click="_ => toggle('sky')">Sky</div>
|
|
||||||
</div>
|
|
||||||
<MyColorPicker v-if="pickerColor" :color="pickerColor" style="z-index: 3"
|
|
||||||
@close="pickerColor = ''" :initial-pos="initialPos"
|
|
||||||
@updatePalette="p => colors = p[0]"/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import {Options} from 'vue-class-component';
|
|
||||||
import {camera, editor, objects, start} from "@/animation/Home";
|
|
||||||
import {config} from "@/animation/Config";
|
|
||||||
import {KeyHandler, range} from "@/scripts/utils";
|
|
||||||
import MyColorPicker from "@/components/color/ColorPicker.vue";
|
|
||||||
|
|
||||||
@Options({components: {MyColorPicker}})
|
|
||||||
export default class NewHome extends KeyHandler
|
|
||||||
{
|
|
||||||
editMode = config.editMode
|
|
||||||
|
|
||||||
colors = localStorage.getItem('palette') ? JSON.parse(localStorage.getItem('palette') as string)[0] :
|
|
||||||
range(10).map(_ => '#ffa8a8')
|
|
||||||
|
|
||||||
pickerColor = ''
|
|
||||||
initialPos = {x: 0, y: 0}
|
|
||||||
started = false
|
|
||||||
|
|
||||||
created(): void
|
|
||||||
{
|
|
||||||
// Escape to close picker
|
|
||||||
this.keybinds.Escape = _ => this.pickerColor = ''
|
|
||||||
|
|
||||||
// Pick colors
|
|
||||||
range(10).forEach(i => this.keybinds[((i + 1) % 10)+''] = _ => editor.color = this.colors[i])
|
|
||||||
|
|
||||||
// Camera position binds
|
|
||||||
this.keybinds.ArrowLeft = _ => camera.position.x -= 1
|
|
||||||
this.keybinds.ArrowRight = _ => camera.position.x += 1
|
|
||||||
this.keybinds.ArrowUp = _ => camera.position.y += 1
|
|
||||||
this.keybinds.ArrowDown = _ => camera.position.y -= 1
|
|
||||||
this.keybinds.J = _ => camera.rotateY(Math.PI / 60)
|
|
||||||
this.keybinds.L = _ => camera.rotateY(-Math.PI / 60)
|
|
||||||
this.keybinds.I = _ => camera.rotateX(Math.PI / 60)
|
|
||||||
this.keybinds.K = _ => camera.rotateX(-Math.PI / 60)
|
|
||||||
this.keybinds.Ctrl0 = _ =>
|
|
||||||
{
|
|
||||||
camera.position.set(0, 0, 200)
|
|
||||||
camera.lookAt(0, 0, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mounted(): void
|
|
||||||
{
|
|
||||||
if (!this.started)
|
|
||||||
{
|
|
||||||
start('three')
|
|
||||||
this.started = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toggle(s: string): void
|
|
||||||
{
|
|
||||||
if (s == 'sky')
|
|
||||||
{
|
|
||||||
objects.hemiLight.visible = !objects.hemiLight.visible
|
|
||||||
objects.dirLight.visible = !objects.dirLight.visible
|
|
||||||
objects.sky.visible = !objects.sky.visible
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
openPicker(e: MouseEvent, c: string): void
|
|
||||||
{
|
|
||||||
this.pickerColor = c
|
|
||||||
this.initialPos = {x: e.clientX - 150, y: e.clientY + 50}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="sass" scoped>
|
|
||||||
#three
|
|
||||||
width: 100vw
|
|
||||||
height: 100vh
|
|
||||||
position: absolute
|
|
||||||
top: 0
|
|
||||||
left: 0
|
|
||||||
z-index: 1
|
|
||||||
cursor: none
|
|
||||||
|
|
||||||
#editor-controls
|
|
||||||
position: absolute
|
|
||||||
z-index: 2
|
|
||||||
user-select: none
|
|
||||||
|
|
||||||
// Positioning
|
|
||||||
top: 20px
|
|
||||||
left: 50px
|
|
||||||
height: 50px
|
|
||||||
width: calc(100vw - 100px - 40px)
|
|
||||||
padding: 0 20px
|
|
||||||
border-radius: 50px
|
|
||||||
|
|
||||||
// Flex center
|
|
||||||
display: flex
|
|
||||||
align-items: center
|
|
||||||
|
|
||||||
// Colors
|
|
||||||
color: #ffeedb
|
|
||||||
background-image: linear-gradient(180deg, #000000 0%, #434343 100%)
|
|
||||||
|
|
||||||
// Separator
|
|
||||||
.separator
|
|
||||||
width: 1px
|
|
||||||
height: 50%
|
|
||||||
border-radius: 100px
|
|
||||||
background-color: rgba(255, 238, 219, 0.37)
|
|
||||||
|
|
||||||
#colors
|
|
||||||
align-items: center
|
|
||||||
|
|
||||||
.color
|
|
||||||
width: 12px
|
|
||||||
height: 12px
|
|
||||||
|
|
||||||
div
|
|
||||||
margin-top: -10px
|
|
||||||
font-size: 8px
|
|
||||||
color: #8f8f8f
|
|
||||||
|
|
||||||
+ .color
|
|
||||||
margin-left: 5px
|
|
||||||
|
|
||||||
#editor-controls > * + *
|
|
||||||
margin-left: 10px
|
|
||||||
|
|
||||||
</style>
|
|
||||||
@@ -298,23 +298,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.3.tgz#ff5e2f1902969d305225a047c8a0fd5c915cebef"
|
resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.3.tgz#ff5e2f1902969d305225a047c8a0fd5c915cebef"
|
||||||
integrity sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==
|
integrity sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==
|
||||||
|
|
||||||
"@types/three@^0.149.0":
|
|
||||||
version "0.149.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/three/-/three-0.149.0.tgz#f48c03ffcf35b2d196f3532b51bc845e96f6090e"
|
|
||||||
integrity sha512-fgNBm9LWc65ER/W0cvoXdC0iMy7Ke9e2CONmEr6Jt8sDSY3sw4DgOubZfmdZ747dkPhbQrgRQAWwDEr2S/7IEg==
|
|
||||||
dependencies:
|
|
||||||
"@types/webxr" "*"
|
|
||||||
|
|
||||||
"@types/web-bluetooth@^0.0.16":
|
"@types/web-bluetooth@^0.0.16":
|
||||||
version "0.0.16"
|
version "0.0.16"
|
||||||
resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz#1d12873a8e49567371f2a75fe3e7f7edca6662d8"
|
resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz#1d12873a8e49567371f2a75fe3e7f7edca6662d8"
|
||||||
integrity sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==
|
integrity sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==
|
||||||
|
|
||||||
"@types/webxr@*":
|
|
||||||
version "0.5.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/webxr/-/webxr-0.5.1.tgz#4908349419104bd476a4252d04e4c3abb496748d"
|
|
||||||
integrity sha512-xlFXPfgJR5vIuDefhaHuUM9uUgvPaXB6GKdXy2gdEh8gBWQZ2ul24AJz3foUd8NNKlSTQuWYJpCb1/pL81m1KQ==
|
|
||||||
|
|
||||||
"@vitejs/plugin-vue@^4.0.0":
|
"@vitejs/plugin-vue@^4.0.0":
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-4.0.0.tgz#93815beffd23db46288c787352a8ea31a0c03e5e"
|
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-4.0.0.tgz#93815beffd23db46288c787352a8ea31a0c03e5e"
|
||||||
@@ -1249,11 +1237,6 @@ memoize-one@^6.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045"
|
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045"
|
||||||
integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==
|
integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==
|
||||||
|
|
||||||
meshline@^3.1.6:
|
|
||||||
version "3.1.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/meshline/-/meshline-3.1.6.tgz#eee67d9b0fd9841652cc1dc2d3833093ae8e68ca"
|
|
||||||
integrity sha512-8JZJOdaL5oz3PI/upG8JvP/5FfzYUOhrkJ8np/WKvXzl0/PZ2V9pqTvCIjSKv+w9ccg2xb+yyBhXAwt6ier3ug==
|
|
||||||
|
|
||||||
minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||||
version "3.1.2"
|
version "3.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||||
@@ -1584,11 +1567,6 @@ tg-blog@^1.1.0:
|
|||||||
url-join "^5.0.0"
|
url-join "^5.0.0"
|
||||||
vue "^3.2.33"
|
vue "^3.2.33"
|
||||||
|
|
||||||
three@^0.150.1:
|
|
||||||
version "0.150.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/three/-/three-0.150.1.tgz#870d324a4d2daf1c7d55be97f3f73d83783e28be"
|
|
||||||
integrity sha512-5C1MqKUWaHYo13BX0Q64qcdwImgnnjSOFgBscOzAo8MYCzEtqfQqorEKMcajnA3FHy1yVlIe9AmaMQ0OQracNA==
|
|
||||||
|
|
||||||
tinycolor2@^1.4.2:
|
tinycolor2@^1.4.2:
|
||||||
version "1.6.0"
|
version "1.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e"
|
resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e"
|
||||||
|
|||||||
Reference in New Issue
Block a user