@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
JavaScript
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