import { _decorator, Component, Prefab, Node, instantiate, Vec3, UITransform } from 'cc'; import { ViewItemPro } from './ViewItemPro'; import { SplitInfo } from '../ExClass'; const { ccclass, property,menu } = _decorator; @ccclass('Generate') @menu("新组件/Generate") export class Generate extends Component { @property(Prefab) public pre_item: Prefab | Node = null; @property({ tooltip: "第一帧加载个数" }) public first_add_num = 1; @property({ tooltip: "每帧加载个个数" }) public every_frame_add = 1; @property({ tooltip: "每行最多个数" }) public horizontal_num = 1; @property({ tooltip: "是否需要计算子节点位置" }) public auto_align_child = true; @property({ tooltip: "1 高度=item行数*高度\n2:1的基础上宽度=列数*宽度" }) public change_size_mode = 1; @property({ tooltip: "item是否上有脚本" }) public item_have_script = true; @property({ tooltip: "从左往右排" }) public left_to_right = true; @property public split_child = false; private uitrans = null; private m_data: any = null; private item_list: Array = []; private state: number = 0; private have_init = false; private first_node: Node = null; private need_refresh = false; private p: any = null; private item_width: number = 0; private item_height: number = 0; private offset_x: number = 0; private offset_y: number = 0; private offsets: Array = []; private split_infos: Array = []; private size_override: Array = null; protected onLoad() { this.uitrans = this.node.getComponent(UITransform); this.first_node = null; if(!this.pre_item && this.node.children.length > 0){ this.split_child = false; this.pre_item = this.node.children[0]; if(this.item_have_script){ this.item_list.push(this.pre_item.getComponent(ViewItemPro)); } else{ this.item_list.push(this.pre_item.components[0]); } } } protected onEnable(): void { if(this.need_refresh)this.initData(this.m_data, this.p); } public setOverrideSize(size:any){ this.size_override = size; this.have_init = false; } public setPrefab(pre: Prefab) { this.pre_item = pre; this.first_node = instantiate(pre); } public initData(data: any, p: any = null) { this.m_data = data; this.p = p; this.need_refresh = !this.enabled; if(!this.enabled)return; this.initParams(); this.updateSize(); if (!data || data.length == 0) { this.item_list.forEach((element, index) => { element.node.active = false; if(this.split_child)this.split_infos[index].setActive(false); }); return; } if (this.change_size_mode > 0 && this.auto_align_child) { this.updateItemsPos(); } let items_len = this.item_list.length; let need_add = data.length - items_len; if (need_add > 0) { let need_add = data.length - items_len; need_add = Math.min(need_add, this.first_add_num); this.addItems(items_len, items_len + need_add); this.updateItems(0, items_len + need_add); this.state = 1; return; } else if(need_add < 0){ for (let i = items_len + need_add; i < items_len; i++){ this.item_list[i].node.active = false; if(this.split_child)this.split_infos[i].setActive(false); } } this.updateItems(0, this.m_data.length); } private initParams() { if (!this.have_init) { let node = null; if(this.first_node){ node = this.first_node; } else{ if(Node.isNode(this.pre_item)){ node = this.node.children[0]; } else{ node = instantiate(this.pre_item); } this.first_node = node; if (this.split_child) { this.offsets = SplitInfo.getOffsetByNode(node); } } let trans = node.getComponent(UITransform); if(this.size_override){ this.item_width = this.size_override[0]; this.item_height = this.size_override[1]; } else{ this.item_width = trans.width; this.item_height = trans.height; } if(this.left_to_right)this.offset_x = trans.anchorX * this.item_width; else this.offset_x = (trans.anchorX - 1) * this.item_width; this.offset_y = (1 - trans.anchorY) * this.item_height; this.have_init = true; } } private updateSize() { let len = 0; if(this.m_data)len = this.m_data.length; let row = Math.ceil(len / this.horizontal_num); if (this.change_size_mode == 2) { let col = len > this.horizontal_num ? this.horizontal_num : len; this.uitrans.setContentSize(col * this.item_width, row * this.item_height); } else if (this.change_size_mode == 1) { this.uitrans.height = row * this.item_height; } } private addItems(begin: number, end: number) { let begin_x = this.left_to_right ? this._getLeftBoundary() : this._getRightBoundary(); let begin_y = this._getTopBoundary(); let row = 0, col = 0; for (let i = begin; i < end; i++) { let node = i == 0 ? this.first_node : instantiate(this.pre_item) as Node; if(this.item_have_script)this.item_list.push(node.getComponent(ViewItemPro)); else this.item_list.push(node.components[0]); node.setParent(this.node); let flag = this.left_to_right ? 1 : -1; let x = 0 , y = 0; if (this.auto_align_child) { row = Math.floor(i / this.horizontal_num); col = i % this.horizontal_num; x = begin_x + flag * col * this.item_width + this.offset_x; y = begin_y - row * this.item_height - this.offset_y; node.toXY(x, y); } } if (this.split_child) { let com_node = null; let info = null; for (let i = begin; i < end; i++) { com_node = this.item_list[i].node; info = new SplitInfo(com_node); this.split_infos.push(info); com_node.setSiblingIndex(i); info.setSlisByIndex(i); info.moveByOffset(this.offsets); } //console.log(this.node.children) } } private updateItemsPos() { if (this.item_list.length == 0) return; let begin_x = this.left_to_right ? this._getLeftBoundary() : this._getRightBoundary(); let begin_y = this._getTopBoundary(); let row = 0, col = 0; let x = 0 , y = 0; let flag = this.left_to_right ? 1 : -1; for (let i = 0, len = this.item_list.length; i < len; i++) { let node = this.item_list[i].node; row = Math.floor(i / this.horizontal_num); col = i % this.horizontal_num; x = begin_x + flag * col * this.item_width + this.offset_x; y = begin_y - row * this.item_height - this.offset_y; node.toXY(x, y); if(this.split_child){ this.split_infos[i].moveByOffset(this.offsets); } } } private updateItems(begin: number, end: number) { for (let i = begin; i < end; i++) { this.item_list[i].node.active = true; if(this.split_child)this.split_infos[i].setActive(true); if(this.item_have_script){ this.item_list[i].reset(); this.item_list[i].init(this.m_data[i], i, this.p); } else{ this.p(this.item_list[i].node, i); } } } private _getLeftBoundary() { return -this.uitrans.anchorX * this.uitrans.width; } private _getBottomBoundary() { return -this.uitrans.anchorY * this.uitrans.height; } private _getRightBoundary() { return (1 - this.uitrans.anchorX) * this.uitrans.width; } private _getTopBoundary() { return (1 - this.uitrans.anchorY) * this.uitrans.height; } public getValidCount(){ return this.m_data.length; } public getItems() { return this.item_list; } public removeAllItems() { if(!this.isValid)return; for(let i = 0 ; i < this.item_list.length ; i++){ this.node.removeChild(this.item_list[i].node); } this.have_init = false; this.item_list.length = 0; this.first_node = null; } public getItemById(index: number) { return this.item_list[index]; } public getPosById(index:number){ let begin_x = this.left_to_right ? this._getLeftBoundary() : this._getRightBoundary(); let begin_y = this._getTopBoundary(); let row = Math.floor(index / this.horizontal_num); let col = index % this.horizontal_num; let flag = this.left_to_right ? 1 : -1; let x = begin_x + flag * col * this.item_width + this.offset_x; let y = begin_y - row * this.item_height - this.offset_y; return [x, y]; } protected update(dt: number) { if (this.state == 0) return; if (this.item_list.length >= this.m_data.length) { this.state = 0; //console.log(this.node.children) this.node.emit("load_end"); } else { let add = Math.min(this.every_frame_add, this.m_data.length - this.item_list.length); let items_len = this.item_list.length; this.addItems(items_len, items_len + add); this.updateItems(items_len, items_len + add); } } }