Generate.ts 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. import { _decorator, Component, Prefab, Node, instantiate, Vec3, UITransform } from 'cc';
  2. import { ViewItemPro } from './ViewItemPro';
  3. import { SplitInfo } from '../ExClass';
  4. const { ccclass, property,menu } = _decorator;
  5. @ccclass('Generate')
  6. @menu("新组件/Generate")
  7. export class Generate extends Component {
  8. @property(Prefab)
  9. public pre_item: Prefab | Node = null;
  10. @property({ tooltip: "第一帧加载个数" })
  11. public first_add_num = 1;
  12. @property({ tooltip: "每帧加载个个数" })
  13. public every_frame_add = 1;
  14. @property({ tooltip: "每行最多个数" })
  15. public horizontal_num = 1;
  16. @property({ tooltip: "是否需要计算子节点位置" })
  17. public auto_align_child = true;
  18. @property({ tooltip: "1 高度=item行数*高度\n2:1的基础上宽度=列数*宽度" })
  19. public change_size_mode = 1;
  20. @property({ tooltip: "item是否上有脚本" })
  21. public item_have_script = true;
  22. @property({ tooltip: "从左往右排" })
  23. public left_to_right = true;
  24. @property
  25. public split_child = false;
  26. private uitrans = null;
  27. private m_data: any = null;
  28. private item_list: Array<any> = [];
  29. private state: number = 0;
  30. private have_init = false;
  31. private first_node: Node = null;
  32. private need_refresh = false;
  33. private p: any = null;
  34. private item_width: number = 0;
  35. private item_height: number = 0;
  36. private offset_x: number = 0;
  37. private offset_y: number = 0;
  38. private offsets: Array<any> = [];
  39. private split_infos: Array<SplitInfo> = [];
  40. private size_override: Array<number> = null;
  41. protected onLoad() {
  42. this.uitrans = this.node.getComponent(UITransform);
  43. this.first_node = null;
  44. if(!this.pre_item && this.node.children.length > 0){
  45. this.split_child = false;
  46. this.pre_item = this.node.children[0];
  47. if(this.item_have_script){
  48. this.item_list.push(this.pre_item.getComponent(ViewItemPro));
  49. }
  50. else{
  51. this.item_list.push(this.pre_item.components[0]);
  52. }
  53. }
  54. }
  55. protected onEnable(): void {
  56. if(this.need_refresh)this.initData(this.m_data, this.p);
  57. }
  58. public setOverrideSize(size:any){
  59. this.size_override = size;
  60. this.have_init = false;
  61. }
  62. public setPrefab(pre: Prefab) {
  63. this.pre_item = pre;
  64. this.first_node = instantiate(pre);
  65. }
  66. public initData(data: any, p: any = null) {
  67. this.m_data = data;
  68. this.p = p;
  69. this.need_refresh = !this.enabled;
  70. if(!this.enabled)return;
  71. this.initParams();
  72. this.updateSize();
  73. if (!data || data.length == 0) {
  74. this.item_list.forEach((element, index) => {
  75. element.node.active = false;
  76. if(this.split_child)this.split_infos[index].setActive(false);
  77. });
  78. return;
  79. }
  80. if (this.change_size_mode > 0 && this.auto_align_child) {
  81. this.updateItemsPos();
  82. }
  83. let items_len = this.item_list.length;
  84. let need_add = data.length - items_len;
  85. if (need_add > 0) {
  86. let need_add = data.length - items_len;
  87. need_add = Math.min(need_add, this.first_add_num);
  88. this.addItems(items_len, items_len + need_add);
  89. this.updateItems(0, items_len + need_add);
  90. this.state = 1;
  91. return;
  92. }
  93. else if(need_add < 0){
  94. for (let i = items_len + need_add; i < items_len; i++){
  95. this.item_list[i].node.active = false;
  96. if(this.split_child)this.split_infos[i].setActive(false);
  97. }
  98. }
  99. this.updateItems(0, this.m_data.length);
  100. }
  101. private initParams() {
  102. if (!this.have_init) {
  103. let node = null;
  104. if(this.first_node){
  105. node = this.first_node;
  106. }
  107. else{
  108. if(Node.isNode(this.pre_item)){
  109. node = this.node.children[0];
  110. }
  111. else{
  112. node = instantiate(this.pre_item);
  113. }
  114. this.first_node = node;
  115. if (this.split_child) {
  116. this.offsets = SplitInfo.getOffsetByNode(node);
  117. }
  118. }
  119. let trans = node.getComponent(UITransform);
  120. if(this.size_override){
  121. this.item_width = this.size_override[0];
  122. this.item_height = this.size_override[1];
  123. }
  124. else{
  125. this.item_width = trans.width;
  126. this.item_height = trans.height;
  127. }
  128. if(this.left_to_right)this.offset_x = trans.anchorX * this.item_width;
  129. else this.offset_x = (trans.anchorX - 1) * this.item_width;
  130. this.offset_y = (1 - trans.anchorY) * this.item_height;
  131. this.have_init = true;
  132. }
  133. }
  134. private updateSize() {
  135. let len = 0;
  136. if(this.m_data)len = this.m_data.length;
  137. let row = Math.ceil(len / this.horizontal_num);
  138. if (this.change_size_mode == 2) {
  139. let col = len > this.horizontal_num ? this.horizontal_num : len;
  140. this.uitrans.setContentSize(col * this.item_width, row * this.item_height);
  141. }
  142. else if (this.change_size_mode == 1) {
  143. this.uitrans.height = row * this.item_height;
  144. }
  145. }
  146. private addItems(begin: number, end: number) {
  147. let begin_x = this.left_to_right ? this._getLeftBoundary() : this._getRightBoundary();
  148. let begin_y = this._getTopBoundary();
  149. let row = 0, col = 0;
  150. for (let i = begin; i < end; i++) {
  151. let node = i == 0 ? this.first_node : instantiate(this.pre_item) as Node;
  152. if(this.item_have_script)this.item_list.push(node.getComponent(ViewItemPro));
  153. else this.item_list.push(node.components[0]);
  154. node.setParent(this.node);
  155. let flag = this.left_to_right ? 1 : -1;
  156. let x = 0 , y = 0;
  157. if (this.auto_align_child) {
  158. row = Math.floor(i / this.horizontal_num);
  159. col = i % this.horizontal_num;
  160. x = begin_x + flag * col * this.item_width + this.offset_x;
  161. y = begin_y - row * this.item_height - this.offset_y;
  162. node.toXY(x, y);
  163. }
  164. }
  165. if (this.split_child) {
  166. let com_node = null;
  167. let info = null;
  168. for (let i = begin; i < end; i++) {
  169. com_node = this.item_list[i].node;
  170. info = new SplitInfo(com_node);
  171. this.split_infos.push(info);
  172. com_node.setSiblingIndex(i);
  173. info.setSlisByIndex(i);
  174. info.moveByOffset(this.offsets);
  175. }
  176. //console.log(this.node.children)
  177. }
  178. }
  179. private updateItemsPos() {
  180. if (this.item_list.length == 0) return;
  181. let begin_x = this.left_to_right ? this._getLeftBoundary() : this._getRightBoundary();
  182. let begin_y = this._getTopBoundary();
  183. let row = 0, col = 0;
  184. let x = 0 , y = 0;
  185. let flag = this.left_to_right ? 1 : -1;
  186. for (let i = 0, len = this.item_list.length; i < len; i++) {
  187. let node = this.item_list[i].node;
  188. row = Math.floor(i / this.horizontal_num);
  189. col = i % this.horizontal_num;
  190. x = begin_x + flag * col * this.item_width + this.offset_x;
  191. y = begin_y - row * this.item_height - this.offset_y;
  192. node.toXY(x, y);
  193. if(this.split_child){
  194. this.split_infos[i].moveByOffset(this.offsets);
  195. }
  196. }
  197. }
  198. private updateItems(begin: number, end: number) {
  199. for (let i = begin; i < end; i++) {
  200. this.item_list[i].node.active = true;
  201. if(this.split_child)this.split_infos[i].setActive(true);
  202. if(this.item_have_script){
  203. this.item_list[i].reset();
  204. this.item_list[i].init(this.m_data[i], i, this.p);
  205. }
  206. else{
  207. this.p(this.item_list[i].node, i);
  208. }
  209. }
  210. }
  211. private _getLeftBoundary() {
  212. return -this.uitrans.anchorX * this.uitrans.width;
  213. }
  214. private _getBottomBoundary() {
  215. return -this.uitrans.anchorY * this.uitrans.height;
  216. }
  217. private _getRightBoundary() {
  218. return (1 - this.uitrans.anchorX) * this.uitrans.width;
  219. }
  220. private _getTopBoundary() {
  221. return (1 - this.uitrans.anchorY) * this.uitrans.height;
  222. }
  223. public getValidCount(){
  224. return this.m_data.length;
  225. }
  226. public getItems() {
  227. return this.item_list;
  228. }
  229. public removeAllItems() {
  230. if(!this.isValid)return;
  231. for(let i = 0 ; i < this.item_list.length ; i++){
  232. this.node.removeChild(this.item_list[i].node);
  233. }
  234. this.have_init = false;
  235. this.item_list.length = 0;
  236. this.first_node = null;
  237. }
  238. public getItemById(index: number) {
  239. return this.item_list[index];
  240. }
  241. public getPosById(index:number){
  242. let begin_x = this.left_to_right ? this._getLeftBoundary() : this._getRightBoundary();
  243. let begin_y = this._getTopBoundary();
  244. let row = Math.floor(index / this.horizontal_num);
  245. let col = index % this.horizontal_num;
  246. let flag = this.left_to_right ? 1 : -1;
  247. let x = begin_x + flag * col * this.item_width + this.offset_x;
  248. let y = begin_y - row * this.item_height - this.offset_y;
  249. return [x, y];
  250. }
  251. protected update(dt: number) {
  252. if (this.state == 0) return;
  253. if (this.item_list.length >= this.m_data.length) {
  254. this.state = 0;
  255. //console.log(this.node.children)
  256. this.node.emit("load_end");
  257. } else {
  258. let add = Math.min(this.every_frame_add, this.m_data.length - this.item_list.length);
  259. let items_len = this.item_list.length;
  260. this.addItems(items_len, items_len + add);
  261. this.updateItems(items_len, items_len + add);
  262. }
  263. }
  264. }