You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
506 lines
20 KiB
506 lines
20 KiB
import { Color, EventTouch, Label, Node, Sorting2D, UIRenderer, UITransform, Vec3 } from 'cc';
|
|
import { SpriteLoad } from 'db://assets/mx/components/SpriteLoad';
|
|
import { GBundle, GPath } from '../../game/ConfigRes';
|
|
import { DailyShopKind, DailyShopParsed } from '../../manager/DailyShopTypes';
|
|
|
|
/** 道具名称描边色(按品质) */
|
|
const NAME_OUTLINE_HEX: Record<number, string> = {
|
|
1: '#386c42',
|
|
2: '#285c6d',
|
|
3: '#623073',
|
|
4: '#734930',
|
|
};
|
|
|
|
/** 抽奖弹窗:shopSkill 品质框与图标 */
|
|
export class DailyShopLotteryIcon {
|
|
/** 抽奖格品质框:skill_lottery{quality} */
|
|
static lotteryQualityFrame(quality: number): string {
|
|
const q = Math.max(1, Math.floor(Number(quality) || 0));
|
|
return `skill_lottery${q}`;
|
|
}
|
|
|
|
/** 被动槽品质框:skill_square_small_{quality} */
|
|
static passiveQualityFrame(quality: number): string {
|
|
const q = Math.max(1, Math.floor(Number(quality) || 0));
|
|
return `skill_square_small_${q}`;
|
|
}
|
|
|
|
/** 主动槽品质框:skill_circle_small{quality} */
|
|
static activeQualityFrame(quality: number): string {
|
|
const q = Math.max(1, Math.floor(Number(quality) || 0));
|
|
return `skill_circle_small${q}`;
|
|
}
|
|
|
|
/** 槽位品质框 */
|
|
static slotQualityFrame(kind: DailyShopKind, quality: number): string {
|
|
return kind === DailyShopKind.Active
|
|
? this.activeQualityFrame(quality)
|
|
: this.passiveQualityFrame(quality);
|
|
}
|
|
|
|
/** 货架品质框:主动 skill_circle_big{q},被动 skill_square_big_{q} */
|
|
static shopQualityFrame(kind: DailyShopKind, quality: number): string {
|
|
const q = Math.max(1, Math.floor(Number(quality) || 0));
|
|
return kind === DailyShopKind.Active
|
|
? `skill_circle_big${q}`
|
|
: `skill_square_big_${q}`;
|
|
}
|
|
|
|
/** 货架名称品质底:nameQuality{q} */
|
|
static shopNameQualityFrame(quality: number): string {
|
|
const q = Math.max(1, Math.floor(Number(quality) || 0));
|
|
return `nameQuality${q}`;
|
|
}
|
|
|
|
/** 替换弹窗新道具品质框:skill_square_big_{q} */
|
|
static replaceNewQualityFrame(quality: number): string {
|
|
const q = Math.max(1, Math.floor(Number(quality) || 0));
|
|
return `skill_square_big_${q}`;
|
|
}
|
|
|
|
/** 替换弹窗列表项品质框:skill_square_small_{q} */
|
|
static replaceListQualityFrame(quality: number): string {
|
|
const q = Math.max(1, Math.floor(Number(quality) || 0));
|
|
return `skill_square_small_${q}`;
|
|
}
|
|
|
|
/** Battlebuff 表描述 */
|
|
static battleBuffDesc(parsed: DailyShopParsed): string {
|
|
const row = parsed.row as ITableBattlebuff;
|
|
return String(row?.desc ?? '');
|
|
}
|
|
|
|
/** 名称 Label 按品质设置描边色 */
|
|
static applyNameOutline(label: Label | null | undefined, quality: number): void {
|
|
if (!label) return;
|
|
const hex = NAME_OUTLINE_HEX[Math.max(1, Math.floor(Number(quality) || 0))];
|
|
if (!hex) return;
|
|
label.enableOutline = true;
|
|
label.outlineColor = Color.fromHEX(new Color(), hex);
|
|
}
|
|
|
|
/** 道具图标名(优先 parsed.icon,其次表 icon,最后 name) */
|
|
static itemIconName(parsed: DailyShopParsed): string {
|
|
if (parsed.icon) return String(parsed.icon);
|
|
const row = parsed.row as { icon?: string; name?: string } | null | undefined;
|
|
const tableIcon = row?.icon != null ? String(row.icon).trim() : '';
|
|
if (tableIcon) return tableIcon;
|
|
return String(parsed.name ?? row?.name ?? '');
|
|
}
|
|
|
|
/** 对已挂载 SpriteLoad 的节点设图;缺失组件时 warn */
|
|
private static _setNodeSprite(node: Node | null | undefined, assetName: string): void {
|
|
if (!node?.isValid) return;
|
|
const sl = node.getComponent(SpriteLoad);
|
|
if (!sl) {
|
|
console.log('[DailyShop] 节点缺少 SpriteLoad', node.name);
|
|
return;
|
|
}
|
|
sl.setSprite(GPath.ShopSkill(assetName), GBundle.Items);
|
|
}
|
|
|
|
/**
|
|
* 绑定品质框 + 图标
|
|
* @param root 根节点(含 quality / icon 子节点)
|
|
* @param frameName 品质框图名
|
|
* @param iconName 图标图名
|
|
*/
|
|
static bindFrameAndIcon(root: Node, frameName: string, iconName: string): void {
|
|
const qualityNode = root.getChildByName('quality') ?? root;
|
|
this._setNodeSprite(qualityNode, frameName);
|
|
const icon = qualityNode.getChildByName('icon') ?? root.getChildByName('icon');
|
|
this._setNodeSprite(icon, iconName);
|
|
}
|
|
|
|
/** 绑定携带槽道具;品质框按槽位类型(ui_skillMain 圆框 / ui_skillPassive 方框) */
|
|
static bindSlotItem(root: Node, parsed: DailyShopParsed, slotKind: DailyShopKind): void {
|
|
const q = Math.max(1, Math.floor(Number(parsed.quality) || 0));
|
|
this.bindFrameAndIcon(
|
|
root,
|
|
this.slotQualityFrame(slotKind, q),
|
|
this.itemIconName(parsed),
|
|
);
|
|
}
|
|
|
|
/** 绑定抽奖格道具 */
|
|
static bindLotteryItem(root: Node, parsed: DailyShopParsed): void {
|
|
const q = Math.max(1, Math.floor(Number(parsed.quality) || 0));
|
|
this.bindFrameAndIcon(
|
|
root,
|
|
this.lotteryQualityFrame(q),
|
|
this.itemIconName(parsed),
|
|
);
|
|
}
|
|
|
|
/** 货架 icon 节点(quality/icon) */
|
|
static resolveShopIcon(root: Node): Node | null {
|
|
const qualityNode = root.getChildByName('quality');
|
|
const icon = qualityNode?.getChildByName('icon') ?? root.getChildByName('icon');
|
|
return icon?.isValid ? icon : null;
|
|
}
|
|
|
|
/** 绑定货架商品格(quality / quality.icon / nameQuality / main) */
|
|
static bindShopItem(root: Node, parsed: DailyShopParsed): void {
|
|
const q = Math.max(1, Math.floor(Number(parsed.quality) || 0));
|
|
const iconName = this.itemIconName(parsed);
|
|
const qualityNode = root.getChildByName('quality');
|
|
if (qualityNode?.isValid) {
|
|
this._setNodeSprite(qualityNode, this.shopQualityFrame(parsed.kind, q));
|
|
this._setNodeSprite(qualityNode.getChildByName('icon'), iconName);
|
|
} else {
|
|
this.bindFrameAndIcon(
|
|
root,
|
|
this.shopQualityFrame(parsed.kind, q),
|
|
iconName,
|
|
);
|
|
}
|
|
this._setNodeSprite(root.getChildByName('nameQuality'), this.shopNameQualityFrame(q));
|
|
const main = root.getChildByName('main');
|
|
if (main?.isValid) {
|
|
main.active = parsed.kind === DailyShopKind.Active;
|
|
}
|
|
}
|
|
|
|
/** 绑定替换弹窗新道具 ui_getQuality(品质框在根节点) */
|
|
static bindReplaceNewItem(root: Node, parsed: DailyShopParsed): void {
|
|
const q = Math.max(1, Math.floor(Number(parsed.quality) || 0));
|
|
const iconName = this.itemIconName(parsed);
|
|
this._setNodeSprite(root, this.replaceNewQualityFrame(q));
|
|
this._setNodeSprite(root.getChildByName('icon'), iconName);
|
|
const main = root.getChildByName('main');
|
|
if (main?.isValid) {
|
|
main.active = parsed.kind === DailyShopKind.Active;
|
|
}
|
|
}
|
|
|
|
/** 绑定替换弹窗列表项 ui_item */
|
|
static bindReplaceListItem(root: Node, parsed: DailyShopParsed): void {
|
|
const q = Math.max(1, Math.floor(Number(parsed.quality) || 0));
|
|
const iconName = this.itemIconName(parsed);
|
|
const qualityNode = root.getChildByName('quality') ?? root;
|
|
this._setNodeSprite(qualityNode, this.replaceListQualityFrame(q));
|
|
const icon = qualityNode.getChildByName('icon') ?? root.getChildByName('icon');
|
|
this._setNodeSprite(icon, iconName);
|
|
}
|
|
}
|
|
|
|
/** 描述浮层 Y 偏移配置 */
|
|
export type DailyShopOwnedDescOpts = {
|
|
/** 主动槽:相对技能格中心的世界 Y 偏移 */
|
|
activeYOffset?: number;
|
|
/** 被动槽:相对技能格中心的世界 Y 偏移 */
|
|
passiveYOffset?: number;
|
|
};
|
|
|
|
/** 携带槽描述浮层(PopDailyShopBuy / PopDailyShopLottery 共用) */
|
|
export class DailyShopOwnedDesc {
|
|
/** 默认主动槽描述框 Y 偏移(我方 ui_desc) */
|
|
private static readonly DEFAULT_ACTIVE_Y_OFFSET = 40;
|
|
/** 默认被动槽描述框 Y 偏移(我方 ui_desc) */
|
|
private static readonly DEFAULT_PASSIVE_Y_OFFSET = 30;
|
|
/** 与字块 canUpEff 同 Sorting2D 层 */
|
|
private static readonly DESC_SORT_LAYER = 3;
|
|
/** 高于 canUpEff(4) / buff 特效(5) / 营地血条(20) */
|
|
private static readonly DESC_SORT_ORDER = 30;
|
|
|
|
private readonly _uiDescLeft: Node | null;
|
|
private readonly _uiDescRight: Node | null;
|
|
private readonly _activeYOffset: number;
|
|
private readonly _passiveYOffset: number;
|
|
private _peerDesc: DailyShopOwnedDesc | null = null;
|
|
|
|
/**
|
|
* @param uiDescLeft 点击 X<0 时显示的描述根节点
|
|
* @param uiDescRight 点击 X>=0 时显示的描述根节点
|
|
* @param opts Y 偏移;敌方 ui_otherDesc 使用 -66 / -35
|
|
*/
|
|
constructor(uiDescLeft: Node | null, uiDescRight: Node | null, opts?: DailyShopOwnedDescOpts) {
|
|
this._uiDescLeft = uiDescLeft;
|
|
this._uiDescRight = uiDescRight;
|
|
this._activeYOffset = opts?.activeYOffset ?? DailyShopOwnedDesc.DEFAULT_ACTIVE_Y_OFFSET;
|
|
this._passiveYOffset = opts?.passiveYOffset ?? DailyShopOwnedDesc.DEFAULT_PASSIVE_Y_OFFSET;
|
|
}
|
|
|
|
/** 互斥显示:打开本浮层前先关闭对方(我方/敌方 skill 描述) */
|
|
setPeerDesc(peer: DailyShopOwnedDesc | null): void {
|
|
this._peerDesc = peer;
|
|
}
|
|
|
|
/** 初始化:默认隐藏,并置于父节点最上层 */
|
|
init(): void {
|
|
if (this._uiDescLeft?.isValid) this._uiDescLeft.active = false;
|
|
if (this._uiDescRight?.isValid) this._uiDescRight.active = false;
|
|
this._raiseDescLayer(this._uiDescLeft);
|
|
this._raiseDescLayer(this._uiDescRight);
|
|
}
|
|
|
|
/** 注册点击描述层关闭 */
|
|
bindDismiss(): void {
|
|
this._bindDismissOnRoot(this._uiDescLeft);
|
|
this._bindDismissOnRoot(this._uiDescRight);
|
|
}
|
|
|
|
/** 注销关闭监听并隐藏 */
|
|
unbindDismiss(): void {
|
|
this._unbindDismissOnRoot(this._uiDescLeft);
|
|
this._unbindDismissOnRoot(this._uiDescRight);
|
|
this.hide();
|
|
}
|
|
|
|
/** 绑定携带槽点击显示描述 */
|
|
bindSlotItem(item: Node, parsed: DailyShopParsed, slotKind: DailyShopKind): void {
|
|
if (!item?.isValid) return;
|
|
item['dailyShopOwnedParsed'] = parsed;
|
|
item['dailyShopOwnedSlotKind'] = slotKind;
|
|
item.targetOff(Node.EventType.TOUCH_END);
|
|
item.on(Node.EventType.TOUCH_END, this._onClickOwnedSlot, this);
|
|
}
|
|
|
|
/**
|
|
* 绑定战斗 skill 格点击描述(仅移除本类监听,不影响拖拽等其它 TOUCH_END)。
|
|
* @param item skill 格根节点
|
|
* @param parsed buff
|
|
* @param slotKind 主动/被动
|
|
*/
|
|
bindBattleSkillItem(item: Node, parsed: DailyShopParsed, slotKind: DailyShopKind): void {
|
|
if (!item?.isValid) return;
|
|
item['dailyShopOwnedParsed'] = parsed;
|
|
item['dailyShopOwnedSlotKind'] = slotKind;
|
|
item.off(Node.EventType.TOUCH_END, this._onClickOwnedSlot, this);
|
|
item.on(Node.EventType.TOUCH_END, this._onClickOwnedSlot, this);
|
|
}
|
|
|
|
/** 注销战斗 skill 格描述点击 */
|
|
unbindBattleSkillItem(item: Node): void {
|
|
if (!item?.isValid) return;
|
|
item.off(Node.EventType.TOUCH_END, this._onClickOwnedSlot, this);
|
|
}
|
|
|
|
/** 绑定抽奖格点击显示描述(锚点为格子中心) */
|
|
bindLotteryItem(item: Node, parsed: DailyShopParsed): void {
|
|
if (!item?.isValid) return;
|
|
item['dailyShopLotteryParsed'] = parsed;
|
|
item.targetOff(Node.EventType.TOUCH_END);
|
|
item.on(Node.EventType.TOUCH_END, this._onClickLotteryItem, this);
|
|
}
|
|
|
|
/** 绑定货架商品点击显示描述(锚点为商品格中心;含售罄) */
|
|
bindShopItem(item: Node, parsed: DailyShopParsed): void {
|
|
if (!item?.isValid) return;
|
|
item['dailyShopGoodsParsed'] = parsed;
|
|
item.targetOff(Node.EventType.TOUCH_END);
|
|
item.on(Node.EventType.TOUCH_END, this._onClickShopItem, this);
|
|
}
|
|
|
|
/** 隐藏描述浮层 */
|
|
hide(): void {
|
|
if (this._uiDescLeft?.isValid) this._uiDescLeft.active = false;
|
|
if (this._uiDescRight?.isValid) this._uiDescRight.active = false;
|
|
}
|
|
|
|
/** 点击描述层关闭 */
|
|
private _onClickUiDesc(): void {
|
|
this.hide();
|
|
}
|
|
|
|
/** 点击携带槽显示描述 */
|
|
private _onClickOwnedSlot(event: EventTouch): void {
|
|
const target = event.target as Node;
|
|
if (this._isDeleteBtnTouch(target)) return;
|
|
const item = event.currentTarget as Node;
|
|
const parsed = item?.['dailyShopOwnedParsed'] as DailyShopParsed | undefined;
|
|
const slotKind = Number(item?.['dailyShopOwnedSlotKind']) as DailyShopKind | undefined;
|
|
if (!parsed || !item?.isValid) return;
|
|
this.show(item, parsed, slotKind ?? parsed.kind);
|
|
}
|
|
|
|
/** 点击抽奖格:描述框锚在格子中心 */
|
|
private _onClickLotteryItem(event: EventTouch): void {
|
|
const item = event.currentTarget as Node;
|
|
const parsed = item?.['dailyShopLotteryParsed'] as DailyShopParsed | undefined;
|
|
if (!parsed || !item?.isValid) return;
|
|
this.showAtWorld(this._resolveNodeCenterWorld(item), parsed);
|
|
}
|
|
|
|
/** 点击货架商品:描述框锚在商品格中心(跳过购买/售罄标记) */
|
|
private _onClickShopItem(event: EventTouch): void {
|
|
const target = event.target as Node;
|
|
if (this._isShopActionTouch(target)) return;
|
|
const item = event.currentTarget as Node;
|
|
const parsed = item?.['dailyShopGoodsParsed'] as DailyShopParsed | undefined;
|
|
if (!parsed || !item?.isValid) return;
|
|
this.showAtWorld(this._resolveNodeCenterWorld(item), parsed);
|
|
}
|
|
|
|
/** 在锚点上方显示描述浮层(按 X 正负选左/右模板,避免超出屏幕) */
|
|
show(anchor: Node, parsed: DailyShopParsed, slotKind?: DailyShopKind): void {
|
|
if (!anchor?.isValid) return;
|
|
const world = anchor.getWorldPosition();
|
|
const kind = slotKind ?? parsed.kind;
|
|
const yOffset = kind === DailyShopKind.Active
|
|
? this._activeYOffset
|
|
: this._passiveYOffset;
|
|
this.showAtWorld(new Vec3(world.x, world.y + yOffset, world.z), parsed);
|
|
}
|
|
|
|
/**
|
|
* 在指定世界坐标显示描述(按 X 正负选左/右模板)。
|
|
* @param world 锚点世界坐标(通常为点击中心)
|
|
* @param parsed 商品
|
|
*/
|
|
showAtWorld(world: Readonly<Vec3>, parsed: DailyShopParsed): void {
|
|
this._peerDesc?.hide();
|
|
const refUt = this._resolveRefTransform();
|
|
if (!refUt) {
|
|
console.log('[DailyShop] ui_descLeft/ui_descRight 缺少 UITransform');
|
|
return;
|
|
}
|
|
|
|
const anchorPos = refUt.convertToNodeSpaceAR(new Vec3(world.x, world.y, world.z));
|
|
const useLeft = anchorPos.x < 0;
|
|
const descRoot = useLeft ? this._uiDescLeft : this._uiDescRight;
|
|
if (!descRoot?.isValid) {
|
|
console.log('[DailyShop] ui_desc 缺失', useLeft ? 'Left' : 'Right');
|
|
return;
|
|
}
|
|
const descBg = descRoot.getChildByName('descBg');
|
|
if (!descBg?.isValid) {
|
|
console.log('[DailyShop] ui_desc 缺少 descBg', descRoot.name);
|
|
return;
|
|
}
|
|
const descUt = descRoot.getComponent(UITransform);
|
|
if (!descUt) {
|
|
console.log('[DailyShop] ui_desc 缺少 UITransform', descRoot.name);
|
|
return;
|
|
}
|
|
|
|
this.hide();
|
|
const bgPos = descUt.convertToNodeSpaceAR(new Vec3(world.x, world.y, world.z));
|
|
descBg.setPosition(bgPos);
|
|
const nameNode = descBg.getChildByName('name');
|
|
this._setLabel(nameNode, parsed.name);
|
|
DailyShopLotteryIcon.applyNameOutline(nameNode?.getComponent(Label), parsed.quality);
|
|
this._setDescLabel(descBg, DailyShopLotteryIcon.battleBuffDesc(parsed));
|
|
this._raiseDescLayer(descRoot);
|
|
descRoot.active = true;
|
|
}
|
|
|
|
/** 描述层 sibling + Sorting2D 置顶(战斗字块 canUpEff 走 Sorting2D,仅 sibling 不够) */
|
|
private _raiseDescLayer(descRoot: Node | null): void {
|
|
if (!descRoot?.isValid) return;
|
|
const parent = descRoot.parent;
|
|
if (parent?.isValid) {
|
|
descRoot.setSiblingIndex(parent.children.length - 1);
|
|
}
|
|
this._applyDescSortingTree(descRoot);
|
|
}
|
|
|
|
/** 为描述层所有 UIRenderer 节点设置更高 Sorting2D */
|
|
private _applyDescSortingTree(root: Node): void {
|
|
if (!root?.isValid) return;
|
|
if (root.getComponent(UIRenderer)) {
|
|
let sorting = root.getComponent(Sorting2D);
|
|
if (!sorting) sorting = root.addComponent(Sorting2D);
|
|
sorting.sortingLayer = DailyShopOwnedDesc.DESC_SORT_LAYER;
|
|
sorting.sortingOrder = DailyShopOwnedDesc.DESC_SORT_ORDER;
|
|
}
|
|
const kids = root.children;
|
|
for (let i = 0; i < kids.length; i++) {
|
|
this._applyDescSortingTree(kids[i]);
|
|
}
|
|
}
|
|
|
|
/** 取左/右描述层共用的坐标参照 UITransform */
|
|
private _resolveRefTransform(): UITransform | null {
|
|
if (this._uiDescLeft?.isValid) {
|
|
const ut = this._uiDescLeft.getComponent(UITransform);
|
|
if (ut) return ut;
|
|
}
|
|
if (this._uiDescRight?.isValid) {
|
|
return this._uiDescRight.getComponent(UITransform) ?? null;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* 节点中心世界坐标。
|
|
* @param node 目标节点
|
|
*/
|
|
private _resolveNodeCenterWorld(node: Node): Vec3 {
|
|
const ut = node.getComponent(UITransform);
|
|
if (ut) return ut.convertToWorldSpaceAR(new Vec3(0, 0, 0));
|
|
return node.getWorldPosition();
|
|
}
|
|
|
|
/** 注册单个描述根节点关闭 */
|
|
private _bindDismissOnRoot(root: Node | null): void {
|
|
if (!root?.isValid) return;
|
|
root.on(Node.EventType.TOUCH_END, this._onClickUiDesc, this);
|
|
}
|
|
|
|
/** 注销单个描述根节点关闭 */
|
|
private _unbindDismissOnRoot(root: Node | null): void {
|
|
if (!root?.isValid) return;
|
|
root.off(Node.EventType.TOUCH_END, this._onClickUiDesc, this);
|
|
}
|
|
|
|
/** 是否点在 deleteBtn 上 */
|
|
private _isDeleteBtnTouch(node: Node | null): boolean {
|
|
let cur = node;
|
|
while (cur?.isValid) {
|
|
if (cur.name === 'deleteBtn') return true;
|
|
cur = cur.parent;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/** 是否点在货架购买/售罄控件上 */
|
|
private _isShopActionTouch(node: Node | null): boolean {
|
|
let cur = node;
|
|
while (cur?.isValid) {
|
|
const name = cur.name;
|
|
if (name === 'buyBtn' || name === 'buyBtnAd' || name === 'complete') return true;
|
|
cur = cur.parent;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/** 设置 Label 文本 */
|
|
private _setLabel(node: Node | null | undefined, text: string): void {
|
|
if (!node?.isValid) return;
|
|
const lb = node.getComponent(Label);
|
|
if (lb) lb.string = text;
|
|
}
|
|
|
|
/**
|
|
* 描述文案:固定宽度、按行增高,避免预制体 CLAMP+矮框裁切多行。
|
|
* @param descBg 描述底板
|
|
* @param text 描述全文
|
|
*/
|
|
private _setDescLabel(descBg: Node, text: string): void {
|
|
const descNode = descBg.getChildByName('desc');
|
|
if (!descNode?.isValid) {
|
|
console.log('[DailyShop] descBg 缺少 desc');
|
|
return;
|
|
}
|
|
const lb = descNode.getComponent(Label);
|
|
const ut = descNode.getComponent(UITransform);
|
|
if (!lb || !ut) {
|
|
console.log('[DailyShop] desc 缺少 Label/UITransform');
|
|
return;
|
|
}
|
|
const width = ut.contentSize.width;
|
|
if (!(width > 0)) {
|
|
console.log('[DailyShop] desc 宽度无效', width);
|
|
return;
|
|
}
|
|
lb.overflow = Label.Overflow.RESIZE_HEIGHT;
|
|
lb.enableWrapText = true;
|
|
if (!(lb.lineHeight > lb.fontSize)) {
|
|
lb.lineHeight = lb.fontSize + 6;
|
|
}
|
|
ut.setContentSize(width, ut.contentSize.height);
|
|
lb.string = text;
|
|
lb.updateRenderData(true);
|
|
}
|
|
}
|
|
|