forked from EXT/VR180-Web-Player
Folder organisation
This commit is contained in:
100
src/vr180player/rendering/three-utils.ts
Normal file
100
src/vr180player/rendering/three-utils.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import * as THREE from 'https://unpkg.com/three/build/three.module.js';
|
||||
import { drawLucideIcon, type LucideIconName } from '../dom/icons.js';
|
||||
|
||||
type Radius = number | {
|
||||
tl?: number;
|
||||
tr?: number;
|
||||
br?: number;
|
||||
bl?: number;
|
||||
};
|
||||
|
||||
export function drawRoundedRect(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
x: number,
|
||||
y: number,
|
||||
width: number,
|
||||
height: number,
|
||||
radius: Radius = 5,
|
||||
fill: boolean | string,
|
||||
stroke: boolean | string = true
|
||||
): void {
|
||||
let corners;
|
||||
if (typeof radius === 'number') {
|
||||
corners = { tl: radius, tr: radius, br: radius, bl: radius };
|
||||
} else {
|
||||
corners = { tl: 0, tr: 0, br: 0, bl: 0, ...radius };
|
||||
}
|
||||
|
||||
if (width < 2 * corners.tl) corners.tl = width / 2;
|
||||
if (width < 2 * corners.tr) corners.tr = width / 2;
|
||||
if (width < 2 * corners.bl) corners.bl = width / 2;
|
||||
if (width < 2 * corners.br) corners.br = width / 2;
|
||||
|
||||
if (height < 2 * corners.tl) corners.tl = height / 2;
|
||||
if (height < 2 * corners.tr) corners.tr = height / 2;
|
||||
if (height < 2 * corners.bl) corners.bl = height / 2;
|
||||
if (height < 2 * corners.br) corners.br = height / 2;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x + corners.tl, y);
|
||||
ctx.lineTo(x + width - corners.tr, y);
|
||||
ctx.quadraticCurveTo(x + width, y, x + width, y + corners.tr);
|
||||
ctx.lineTo(x + width, y + height - corners.br);
|
||||
ctx.quadraticCurveTo(x + width, y + height, x + width - corners.br, y + height);
|
||||
ctx.lineTo(x + corners.bl, y + height);
|
||||
ctx.quadraticCurveTo(x, y + height, x, y + height - corners.bl);
|
||||
ctx.lineTo(x, y + corners.tl);
|
||||
ctx.quadraticCurveTo(x, y, x + corners.tl, y);
|
||||
ctx.closePath();
|
||||
|
||||
if (fill) {
|
||||
if (typeof fill === 'string') ctx.fillStyle = fill;
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
if (stroke) {
|
||||
if (typeof stroke === 'string') ctx.strokeStyle = stroke;
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
export function createLucideButtonTexture(
|
||||
iconName: LucideIconName,
|
||||
color = '#ffffff',
|
||||
textureSize = 128,
|
||||
iconSize = 82,
|
||||
skipLabel?: string
|
||||
) {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = textureSize;
|
||||
canvas.height = textureSize;
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
if (!ctx) {
|
||||
throw new Error('Unable to create 2D canvas context for Lucide button texture.');
|
||||
}
|
||||
|
||||
const iconOffset = (textureSize - iconSize) / 2;
|
||||
drawLucideIcon(ctx, iconName, iconOffset, iconOffset, iconSize, color, 2);
|
||||
|
||||
if (skipLabel) {
|
||||
ctx.fillStyle = color;
|
||||
ctx.font = `700 ${Math.round(textureSize * 0.18)}px Helvetica, Arial, sans-serif`;
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.fillText(skipLabel, textureSize / 2, textureSize / 2);
|
||||
}
|
||||
|
||||
const texture = new THREE.CanvasTexture(canvas);
|
||||
texture.minFilter = THREE.LinearFilter;
|
||||
texture.needsUpdate = true;
|
||||
return texture;
|
||||
}
|
||||
|
||||
export function createVideoTexture(video: HTMLVideoElement) {
|
||||
const texture = new THREE.VideoTexture(video);
|
||||
texture.minFilter = THREE.LinearFilter;
|
||||
texture.magFilter = THREE.LinearFilter;
|
||||
texture.colorSpace = THREE.SRGBColorSpace;
|
||||
return texture;
|
||||
}
|
||||
Reference in New Issue
Block a user