MatchMaster/assets/cloud_rise_home/scripts/CloudRiseCounter.ts
2026-09-21 12:44:48 +08:00

45 lines
2.1 KiB
TypeScript

const { ccclass, property, executeInEditMode } = cc._decorator;
/** Authored number artwork for integer counts and fractions (optional slash frame). */
@ccclass
@executeInEditMode
export default class CloudRiseCounter extends cc.Component {
@property([cc.SpriteFrame]) frames: cc.SpriteFrame[] = [];
@property value = "0/5";
@property glyphHeight = 56;
@property usePrefabLayout = false;
get string(): string { return this.value; }
set string(value: string) { this.value = value; this.render(); }
onEnable(): void { this.render(); }
private render(): void {
if (![10, 11].includes(this.frames.length) || this.frames.some(frame => !frame)) return;
const chars = this.value.split("");
if (chars.some(char => !/^[0-9/]$/.test(char) || char === "/" && !this.frames[10])) return;
if (this.usePrefabLayout) {
// Keep the designer's per-slot positions and Sprite size modes when updating the value.
this.node.children.forEach((node, i) => {
node.active = i < chars.length;
if (node.active) node.getComponent(cc.Sprite).spriteFrame = this.frames[chars[i] === "/" ? 10 : Number(chars[i])];
});
return;
}
const widths = chars.map(char => {
const rect = this.frames[char === "/" ? 10 : Number(char)].getRect();
return this.glyphHeight * rect.width / rect.height;
});
const total = widths.reduce((a, b) => a + b, 0) + Math.max(0, chars.length - 1) * 2;
const scale = Math.min(1, this.node.width / total);
let x = -total / 2;
this.node.children.forEach((node, i) => {
node.active = i < chars.length;
if (!node.active) return;
const sprite = node.getComponent(cc.Sprite);
sprite.spriteFrame = this.frames[chars[i] === "/" ? 10 : Number(chars[i])];
sprite.sizeMode = cc.Sprite.SizeMode.CUSTOM;
node.setContentSize(widths[i] * scale, this.glyphHeight * scale);
node.setPosition((x + widths[i] / 2) * scale, 0);
x += widths[i] + 2;
});
}
}