UNPKG

@needle-tools/engine

Version:

Needle Engine is a web-based runtime for 3D apps. It runs on your machine for development with great integrations into editors like Unity or Blender - and can be deployed onto any device! It is flexible, extensible and networking and XR are built-in.

127 lines (112 loc) 4.74 kB
import { Color, ColorRepresentation } from "three"; import { Mathf } from "../../engine/engine_math.js"; /** * RGBAColor is a class that represents a color with red, green, blue and alpha components. */ export class RGBAColor extends Color { alpha: number = 1; get isRGBAColor() { return true; } set a(val: number) { this.alpha = val; } get a() { return this.alpha; } constructor(color: ColorRepresentation); /** * Creates a new RGBAColor with the given red, green, blue and alpha components. * Color values should be in the range [0, 1]. */ constructor(r: number, g: number, b: number, a: number); constructor(r: number | ColorRepresentation, g?: number, b?: number, a?: number) { // AMD compilation creates recursive super calls with local function wrappers // Call super() first with the minimum arguments needed super(); if (typeof r === "number" && typeof g === "number" && typeof b === "number") { this.set(r, g, b); this.alpha = typeof a === "number" ? a : 1; } else if (r !== undefined) { this.set(r as ColorRepresentation); this.alpha = 1; } } clone(): this { const cloned = super.clone(); cloned.alpha = this.alpha; return cloned; } copy(col: RGBAColor | Color) { this.r = col.r; this.g = col.g; this.b = col.b; if ("alpha" in col && typeof col.alpha === "number") { this.alpha = col.alpha; } else if (typeof col["a"] === "number") this.alpha = col["a"]; return this; } lerp(color: Color, alpha: number): this { const rgba = color as RGBAColor; if (rgba.alpha != undefined) this.alpha = Mathf.lerp(this.alpha, rgba.alpha, alpha); return super.lerp(color, alpha); } lerpColors(color1: Color, color2: Color, alpha: number): this { const rgba1 = color1 as RGBAColor; const rgba2 = color2 as RGBAColor; if (rgba1.alpha != undefined && rgba2.alpha != undefined) this.alpha = Mathf.lerp(rgba1.alpha, rgba2.alpha, alpha); return super.lerpColors(color1, color2, alpha); } multiply(color: Color): this { const rgba = color as RGBAColor; if (rgba.alpha != undefined) this.alpha = this.alpha * rgba.alpha; return super.multiply(color); } fromArray(array: number[], offset: number = 0): this { this.alpha = array[offset + 3]; return super.fromArray(array, offset); } static fromColorRepresentation(col: ColorRepresentation) { if (typeof col === "string") { if (col.trim() === "transparent") { return new RGBAColor(0, 0, 0, 0); } // handle hex colors with alpha if (col.startsWith("#") && col.length === 9) { const hex = parseInt(col.slice(1, 9), 16); const r = (hex >> 24) & 0xff; const g = (hex >> 16) & 0xff; const b = (hex >> 8) & 0xff; const a = (hex >> 0) & 0xff; return new RGBAColor(r / 255, g / 255, b / 255, a / 255); } // handle hex colors else if (col.startsWith("#")) { const hex = parseInt(col.slice(1), 16); const r = (hex >> 16) & 0xff; const g = (hex >> 8) & 0xff; const b = (hex >> 0) & 0xff; return new RGBAColor(r / 255, g / 255, b / 255, 1); } // handle rgba string else if (col.startsWith("rgba")) { const rgba = col.slice(5, -1).split(",").map(Number); return new RGBAColor(rgba[0] / 255, rgba[1] / 255, rgba[2] / 255, rgba[3]); } // handle rgb string else if (col.startsWith("rgb")) { const rgb = col.slice(4, -1).split(",").map(Number); return new RGBAColor(rgb[0] / 255, rgb[1] / 255, rgb[2] / 255, 1); } } else if (Array.isArray(col)) { // handle rgba colors if (col.length === 4) { return new RGBAColor(col[0], col[1], col[2], col[3]); } // handle rgb colors else if (col.length === 3) { return new RGBAColor(col[0], col[1], col[2], 1); } else { console.error("Invalid color array length. Expected 3 or 4, got " + col.length); } } return new RGBAColor(col); } }