animation, gathering, deposit, ui
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import { Color, Material, Mesh, Object3D, Vector3 } from "three";
|
||||
import { ResourceScreenFly } from "../Resources/ResourceScreenFly";
|
||||
import {
|
||||
findInteractiveZoneFromMap,
|
||||
getInteractiveZoneCenter,
|
||||
INTERACTIVE_ZONE_NAME,
|
||||
} from "./MapInteractiveZone";
|
||||
|
||||
const FILL_TARGET = 10;
|
||||
const FILL_COLOR = new Color(0x2db83a);
|
||||
|
||||
export class InteractiveZoneC {
|
||||
private static zoneRoot: Object3D | null = null;
|
||||
private static deposited = 0;
|
||||
private static baseColors = new WeakMap<Material, Color>();
|
||||
|
||||
static init(mapObject: Object3D) {
|
||||
const zone = findInteractiveZoneFromMap(mapObject);
|
||||
if (!zone) {
|
||||
console.warn(`Interactive zone not found: ${INTERACTIVE_ZONE_NAME}`);
|
||||
return;
|
||||
}
|
||||
|
||||
this.zoneRoot = zone;
|
||||
this.setupMaterials(zone);
|
||||
}
|
||||
|
||||
static getWorldCenter(out = new Vector3()) {
|
||||
if (!this.zoneRoot) return out.set(0, 0, 0);
|
||||
return getInteractiveZoneCenter(this.zoneRoot, out);
|
||||
}
|
||||
|
||||
static getScreenCenter() {
|
||||
return ResourceScreenFly.worldToScreen(this.getWorldCenter());
|
||||
}
|
||||
|
||||
static addDeposit(amount = 1) {
|
||||
this.deposited += amount;
|
||||
this.refreshFillVisual();
|
||||
}
|
||||
|
||||
static getFillRatio() {
|
||||
return Math.min(this.deposited / FILL_TARGET, 1);
|
||||
}
|
||||
|
||||
private static setupMaterials(zone: Object3D) {
|
||||
zone.traverse((child) => {
|
||||
if (!(child as Mesh).isMesh) return;
|
||||
|
||||
const mesh = child as Mesh;
|
||||
const sourceMaterial = mesh.material;
|
||||
if (Array.isArray(sourceMaterial)) return;
|
||||
|
||||
if (!sourceMaterial) return;
|
||||
|
||||
const cloned = sourceMaterial.clone();
|
||||
if ("color" in cloned) {
|
||||
this.baseColors.set(cloned, (cloned.color as Color).clone());
|
||||
}
|
||||
mesh.material = cloned;
|
||||
});
|
||||
|
||||
this.refreshFillVisual();
|
||||
}
|
||||
|
||||
private static refreshFillVisual() {
|
||||
if (!this.zoneRoot) return;
|
||||
|
||||
const ratio = this.getFillRatio();
|
||||
|
||||
this.zoneRoot.traverse((child) => {
|
||||
if (!(child as Mesh).isMesh) return;
|
||||
|
||||
const material = (child as Mesh).material;
|
||||
if (Array.isArray(material) || !material) return;
|
||||
|
||||
const baseColor = this.baseColors.get(material);
|
||||
if (!baseColor || !("color" in material)) return;
|
||||
|
||||
(material.color as Color).copy(baseColor).lerp(FILL_COLOR, ratio);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user