| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- import { AppKernel } from '@scripts/app/AppKernel';
- import { GAME_TABS } from '@scripts/define/Define';
- import { IGameInfo } from '@scripts/store/gameStore/data';
- import { setSpriteFrame } from '@scripts/utils/ResHelper';
- import { addBtnClick, removeBtnClick, setAlpha } from '@scripts/utils/UIHelper';
- import { _decorator, Button, CCBoolean, Color, Component, isValid, Label, Node, Size, Sprite, UITransform, Vec4 } from 'cc';
- const { ccclass, property } = _decorator;
- @ccclass('GameItem')
- export class GameItem extends Component {
- @property(Sprite)
- gameIcon: Sprite;
- @property(Node)
- btnFavo: Node;
- @property(Sprite)
- favoFlag: Sprite;
- @property(Node)
- hotFlag: Node;
- @property(Node)
- newFlag: Node;
- @property(Label)
- lblGameName: Label;
- @property(CCBoolean)
- isPortrait: boolean;
- @property({ tooltip: '配合 sprite-cover 材质,图片居中等比铺满节点区域' })
- coverIcon = false;
- private _data: IGameInfo;
- private _dataIdx: number;
- protected onLoad(): void {
- if (this.coverIcon) {
- this.node.on(Node.EventType.SIZE_CHANGED, this.updateIconCover, this);
- this.updateIconCover();
- }
- addBtnClick(this.gameIcon.node, this.onClick, this);
- addBtnClick(this.btnFavo, this.onBtnFavoClick, this);
- }
- public async updateItem(data: IGameInfo, index: number) {
- this._data = data;
- this._dataIdx = index;
- if (!this.node.active) this.node.active = true;
- if (this.lblGameName) this.lblGameName.string = data.gameName;
- setAlpha(this.favoFlag, data.isFavorite);
- this.setGameFlag(data.tags.map(t => t.tagCode));
- const url = this.isPortrait ? data.coverUrl?.Portrait : data.coverUrl?.Square;
- if (!url) {
- this.gameIcon.spriteFrame = null;
- return;
- }
- const tmpIdx = this._dataIdx;
- const res = await AppKernel.resources.loadRemoteSp(url);
- if (tmpIdx === this._dataIdx && this._data === data && isValid(this.node)) {
- this.gameIcon.spriteFrame = res;
- this.updateIconCover();
- }
- }
- private setGameFlag(tags: string[]) {
- this.newFlag.active = false;
- this.hotFlag.active = false;
- if (tags.includes(GAME_TABS.Hot)) {
- this.hotFlag.active = true;
- return;
- }
- if (tags.includes(GAME_TABS.New)) {
- this.newFlag.active = true;
- }
- }
- private updateIconCover(): void {
- if (!this.coverIcon) return;
- const target = this.node.getComponent(UITransform);
- const icon = this.gameIcon;
- icon.sizeMode = Sprite.SizeMode.CUSTOM;
- icon.getComponent(UITransform).setContentSize(target.contentSize);
- const frame = icon.spriteFrame;
- if (!frame || target.width <= 0 || target.height <= 0) return;
- const { width, height } = frame.rect;
- if (width <= 0 || height <= 0) return;
- const scale = Math.max(target.width / width, target.height / height);
- const sx = target.width / (width * scale);
- const sy = target.height / (height * scale);
- const uv = frame.uv;
- const material = icon.getMaterialInstance(0);
- if (!material) return;
- const nodeInfo = material.getProperty('nodeInfo') as Vec4;
- material.setProperty('nodeInfo', new Vec4(target.width, target.height, nodeInfo?.z ?? 1, 0));
- // Invert the frame UV basis: bottom-left -> bottom-right / top-left.
- // Round corners must follow the node, independently of the cover crop.
- const ux = uv[2] - uv[0];
- const uy = uv[3] - uv[1];
- const vx = uv[4] - uv[0];
- const vy = uv[5] - uv[1];
- const determinant = ux * vy - uy * vx;
- if (Math.abs(determinant) < 1e-12) return;
- material.setProperty('nodeUVRowX', new Vec4(
- vy / determinant, -vx / determinant,
- (vx * uv[1] - vy * uv[0]) / determinant, 0,
- ));
- material.setProperty('nodeUVRowY', new Vec4(
- -uy / determinant, ux / determinant,
- (uy * uv[0] - ux * uv[1]) / determinant, 0,
- ));
- material.setProperty('uvTransform', new Vec4(
- frame.rotated ? sy : sx,
- frame.rotated ? sx : sy,
- (uv[0] + uv[6]) / 2,
- (uv[1] + uv[7]) / 2,
- ));
- }
- protected onDestroy(): void {
- this.node.off(Node.EventType.SIZE_CHANGED, this.updateIconCover, this);
- }
- private onClick() {
- AppKernel.appLobby.openGame(this._data);
- // AppKernel.appLobby.openGame(this._gameConfig.id);
- }
- private async onBtnFavoClick() {
- const gameStore = AppKernel.stores.gameStore;
- if (gameStore.favoriting) return;
- const index = this._dataIdx;
- const data = this._data;
- const isFavorite = data.isFavorite;
- const game = isFavorite ? await gameStore.reqFavoRemove(data.gameID)
- : await gameStore.reqFavoAdd(data.gameID);
- if (!!game && this._dataIdx === index) {
- this.updateItem(game, index);
- }
- }
- }
|