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.

95 lines 3.46 kB
import { Color } from "three"; import { WaitForSeconds } from "../engine/engine_coroutine.js"; import { RoomEvents } from "../engine/engine_networking.js"; import { PlayerState } from "../engine-components-experimental/networking/PlayerSync.js"; import { Behaviour, GameObject } from "./Component.js"; import { AvatarMarker } from "./webxr/WebXRAvatar.js"; /** * PlayerColor assigns a unique color for each user in the room to the object it is attached to. * The color is generated based on the user's ID. * @category Networking * @group Components */ export class PlayerColor extends Behaviour { _didAssignPlayerColor = false; onEnable() { this.context.connection.beginListen(RoomEvents.JoinedRoom, this.tryAssignColor); if (!this._didAssignPlayerColor) this.startCoroutine(this.waitForConnection()); } onDisable() { this.context.connection.stopListen(RoomEvents.JoinedRoom, this.tryAssignColor); } *waitForConnection() { while (!this.destroyed && this.activeAndEnabled) { yield WaitForSeconds(.2); if (this.tryAssignColor()) break; } } tryAssignColor = () => { const marker = GameObject.getComponentInParent(this.gameObject, PlayerState); if (marker && marker.owner) { this._didAssignPlayerColor = true; this.assignUserColor(marker.owner); return true; } const avatar = GameObject.getComponentInParent(this.gameObject, AvatarMarker); if (avatar?.connectionId) { this._didAssignPlayerColor = true; this.assignUserColor(avatar.connectionId); return true; } return false; }; assignUserColor(id) { // console.log(this.name, id, this); const hash = PlayerColor.hashCode(id); const color = PlayerColor.colorFromHashCode(hash); if (this.gameObject.type === "Mesh") { const mesh = this.gameObject; this.assignColor(color, id, mesh); } else if (this.gameObject.children) { for (const ch of this.gameObject.children) { const obj = ch; if (obj.material && obj.material.color) { this.assignColor(color, id, obj); } } } } assignColor(col, id, mesh) { let mat = mesh.material; if (!mat) return; if (mat["_playerMaterial"] !== id) { // console.log("ORIG", mat); mat = mat.clone(); mat["_playerMaterial"] = id; mesh.material = mat; // console.log("CLONE", mat); } // else console.log("DONT CLONE", mat); mat["color"] = col; } static hashCode(str) { var hash = 0, i, chr; if (str.length === 0) return hash; for (i = 0; i < str.length; i++) { chr = str.charCodeAt(i); hash = ((hash << 5) - hash) + chr; hash |= 0; // Convert to 32bit integer } return hash; } ; static colorFromHashCode(hash) { const r = (hash & 0xFF0000) >> 16; const g = (hash & 0x00FF00) >> 8; const b = hash & 0x0000FF; return new Color(r / 255, g / 255, b / 255); } } //# sourceMappingURL=PlayerColor.js.map