lib.c.cc.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. import { AssetManager, assetManager, Canvas, Component, director, game, Node, resources, Size, Sprite, UITransform, v2, v3, v4, Vec2, Vec3, Vec4, view, warn } from "cc";
  2. // 检测全局命名空间是否存在
  3. const __Global__ = window ?? globalThis;
  4. if(!Reflect.has(__Global__, 'mtec')){
  5. Reflect.set(__Global__, 'mtec', {});
  6. Reflect.set(mtec, '__mtec__', 'Many technologies');
  7. }
  8. // 初始化子命名空间
  9. ['sp', 'size', 'vector', 'cc']
  10. .forEach(space_name=>{
  11. if(!Reflect.has(mtec, space_name)){
  12. Reflect.set(mtec, space_name, {});
  13. Reflect.set(Reflect.get(mtec, space_name), '__space_description__', 'This is a mtec subnamespace for ' + space_name);
  14. }
  15. });
  16. Reflect.defineProperty(mtec.cc, 'initTime', {
  17. get() {
  18. return Reflect.get(game, '_initTime');
  19. },
  20. enumerable: true,
  21. configurable: false,
  22. });
  23. Reflect.defineProperty(mtec.cc, 'totalTime', {
  24. get() {
  25. return game.totalTime;
  26. },
  27. enumerable: true,
  28. configurable: false,
  29. });
  30. Reflect.defineProperty(mtec.cc, 'frameStartTime', {
  31. get() {
  32. return game.frameStartTime - mtec.cc.initTime;
  33. },
  34. enumerable: true,
  35. configurable: false,
  36. });
  37. Reflect.defineProperty(mtec.cc, 'residueTime', {
  38. get() {
  39. return mtec.cc.frameStartTime+mtec.cc.frameTime-mtec.cc.totalTime;
  40. },
  41. enumerable: true,
  42. configurable: false,
  43. });
  44. Reflect.defineProperty(mtec.cc, 'frameTime', {
  45. get() {
  46. return game.frameTime;
  47. },
  48. enumerable: true,
  49. configurable: false,
  50. });
  51. Reflect.defineProperty(mtec.cc, 'is_long_screen', {
  52. get(){
  53. let [R, r] = [mtec.size.canvasSize, mtec.size.designSize].map(s=>s.width/s.height);
  54. return r > R;
  55. },
  56. enumerable: true,
  57. configurable: false,
  58. });
  59. if(typeof requestIdleCallback !== 'undefined'){
  60. mtec.cc.IdleCallback = function(call, args, complete, options){
  61. if(options){
  62. if(!Reflect.has(options, 'start_stamp')) options.start_stamp = performance.now();
  63. if(!Reflect.has(options, 'timeout')) options.timeout = 100;
  64. }else options = {start_stamp: performance.now(), timeout: 100};
  65. requestIdleCallback(()=>{
  66. if(mtec.cc.residueTime>0 || performance.now()-options.start_stamp >= options.timeout){
  67. Promise.resolve(call(...args)).then(r=> typeof complete == 'function' ? complete(r, args) : void 0);
  68. }else mtec.cc.IdleCallback(call, args, complete, options);
  69. });
  70. }
  71. }else if(typeof requestAnimationFrame !== 'undefined'){
  72. mtec.cc.IdleCallback = function(call, args, complete, options){
  73. if(options){
  74. if(!Reflect.has(options, 'start_stamp')) options.start_stamp = performance.now();
  75. if(!Reflect.has(options, 'timeout')) options.timeout = 100;
  76. }else options = {start_stamp: performance.now(), timeout: 100};
  77. requestAnimationFrame(()=>{
  78. if(mtec.cc.residueTime>0 || performance.now()-options.start_stamp >= options.timeout){
  79. Promise.resolve(call(...args)).then(r=> typeof complete == 'function' ? complete(r, args) : void 0);
  80. }else mtec.cc.IdleCallback(call, args, complete, options);
  81. });
  82. }
  83. }else{
  84. mtec.cc.IdleCallback = function(call, args, complete, options){
  85. if(options){
  86. if(!Reflect.has(options, 'start_stamp')) options.start_stamp = performance.now();
  87. if(!Reflect.has(options, 'timeout')) options.timeout = 100;
  88. }else options = {start_stamp: performance.now(), timeout: 100};
  89. setTimeout(()=>{
  90. if(mtec.cc.residueTime>0 || performance.now()-options.start_stamp >= options.timeout){
  91. Promise.resolve(call(...args)).then(r=> typeof complete == 'function' ? complete(r, args) : void 0);
  92. }else mtec.cc.IdleCallback(call, args, complete, options);
  93. }, 0);
  94. }
  95. }
  96. mtec.cc.frameWhile = function(list, call){
  97. if(!list || !Array.isArray(list) || list.length<=0) return Promise.resolve(0);
  98. let np = new mtec.NudityPromise<0>();
  99. list.forEach((el, i)=> mtec.cc.IdleCallback(call, [el, i, list], ()=>(i==list.length-1) ? np.resolve(0) : void 0) );
  100. return np.promise;
  101. }
  102. mtec.cc.loadBundle = function(bundle_name){
  103. return new Promise<AssetManager.Bundle>((s, j)=>{
  104. assetManager.loadBundle(bundle_name, null, (err, bundle)=>{
  105. if(err) s(undefined);
  106. else if(bundle) s(bundle);
  107. else s(undefined);
  108. });
  109. });
  110. };
  111. mtec.cc.loadRes = function(path, type, bundle, call){
  112. //@ts-ignore
  113. [bundle, call] = mtec.pickValueByType([bundle, call], [['object', resources], ['function', undefined]]);
  114. let asset = bundle.get(path, type);
  115. if(!asset){
  116. bundle.load(path, type, (err, a)=>{
  117. if(a) call && call(a);
  118. else warn('资源加载失败:', path, type, err);
  119. });
  120. }else if(call) call(asset);
  121. }
  122. mtec.cc.loadResAsync = function(path, type, bundle){
  123. bundle = bundle??resources;
  124. return new Promise((s, j)=>{
  125. let asset = bundle.get(path, type);
  126. if(asset) s(asset);
  127. else{
  128. bundle.load(path, type, (err, a)=>{
  129. if(a) s(a);
  130. else warn('资源加载失败:', path, type, err);
  131. });
  132. }
  133. });
  134. }
  135. mtec.cc.creatEventHandle = function(options){
  136. return Object.assign(new Component.EventHandler(), options);
  137. }
  138. mtec.cc.VecAssist = class{
  139. private inner: UITransform;
  140. private container: UITransform;
  141. private __vec__: Vec3;
  142. constructor(node: Node, ref: Node){
  143. if (!node.parent){
  144. mtec.log.tag(`node<${node.name}> 不在场景中,无法使用坐标辅助类的功能!: red`);
  145. return void 0;
  146. }
  147. ref = ref&&ref.isValid ? ref : node.parent;
  148. [this.inner, this.container] = [node, ref].map(n=>n.getComponent(UITransform));
  149. this.__vec__ = v3();
  150. }
  151. private get container_upper(){
  152. return this.container.height * (1 - this.container.anchorY);
  153. }
  154. private get container_bottom(){
  155. return this.container.height * this.container.anchorY;
  156. }
  157. private get container_left(){
  158. return this.container.width * this.container.anchorX;
  159. }
  160. private get container_right(){
  161. return this.container.width * (1 - this.container.anchorX);
  162. }
  163. private get inner_upper(){
  164. return this.inner.height * (1 - this.inner.anchorY);
  165. }
  166. private get inner_bottom(){
  167. return this.inner.height * this.inner.anchorY;
  168. }
  169. private get inner_left(){
  170. return this.inner.width * this.inner.anchorX;
  171. }
  172. private get inner_right(){
  173. return this.inner.width * (1 - this.inner.anchorX);
  174. }
  175. public get top(){
  176. return this.container_upper - this.inner_upper;
  177. }
  178. public get bottom(){
  179. return this.inner_bottom - this.container_bottom;
  180. }
  181. public get left(){
  182. return this.inner_left - this.container_left;
  183. }
  184. public get right(){
  185. return this.container_right - this.inner_right;
  186. }
  187. public get over_top(){
  188. return this.container_upper + this.inner_bottom;
  189. }
  190. public get over_bottom(){
  191. return -this.container_bottom - this.inner_upper;
  192. }
  193. public get over_left(){
  194. return -this.container_left - this.inner_right;
  195. }
  196. public get over_right(){
  197. return this.container_right + this.inner_left;
  198. }
  199. public get center(){
  200. let x = (0.5 - this.container.anchorX) * this.container.width + (this.inner.anchorX - 0.5) * this.inner.width;
  201. let y = (0.5 - this.container.anchorY) * this.container.height + (this.inner.anchorY - 0.5) * this.inner.height;
  202. return v3(x, y, this.inner.node.position.z);
  203. }
  204. public get vec(){
  205. return this.__vec__;
  206. }
  207. public getPosition(x: 'center'|`${''|'over_'}${'left'|'right'|'bottom'|'top'}`, y?:'center'|`${''|'over_'}${'top'|'bottom'}`){
  208. if(x.includes('top') || x.includes('bottom')){
  209. let _t = y;
  210. y = <typeof y>x;
  211. x = _t;
  212. _t = undefined;
  213. }
  214. this.vec.set(
  215. x ? x=='center' ? this.center.x : Reflect.get(this, x) : this.inner.node.position.x,
  216. y ? y=='center' ? this.center.y : Reflect.get(this, y) : this.inner.node.position.y,
  217. this.inner.node.position.z
  218. );
  219. return this.vec;
  220. }
  221. public static getPosition<Dx extends 'center'|`${''|'over_'}${'left'|'right'|'bottom'|'top'}`, Dy extends 'center'|`${''|'over_'}${'top'|'bottom'}`>(node: Node, ref?: Node|Dx, x?: Dx|Dy, y?: Dy){
  222. if(typeof ref == 'string'){
  223. [x, y as typeof x] = [ref, x];
  224. ref = undefined;
  225. }
  226. let va = new mtec.cc.VecAssist(node, ref as Node);
  227. let vec = va.getPosition(x??'center', y);
  228. va = null;
  229. return vec;
  230. }
  231. }
  232. mtec.cc.skinPeeler = function(node, sframe, inner){
  233. let uitrans = node.getComponent(UITransform);
  234. let node_size = uitrans.contentSize.clone();
  235. let sfrm_size = sframe.originalSize.clone();
  236. let sprite = node.getComponent(Sprite);
  237. if(!sprite) sprite = node.addComponent(Sprite);
  238. sprite.spriteFrame = sframe;
  239. let ratio: number;
  240. inner = inner ?? true;
  241. if(typeof inner=='boolean' || inner.width===inner.height){
  242. if(typeof inner!='boolean') inner = inner.width;
  243. ratio = Math[inner ? 'min' : 'max'](node_size.width / sfrm_size.width, node_size.height / sfrm_size.height);
  244. }else{
  245. let side = inner.width ? 'width' : 'height';
  246. ratio = node_size[side] / sfrm_size[side];
  247. }
  248. uitrans.setContentSize(sfrm_size.width * ratio, sfrm_size.height * ratio);
  249. }
  250. mtec.cc.getWorldPosition = function(node, out){
  251. if(!node || !node.isValid) return void 0;
  252. return node.getWorldPosition(out??v3());
  253. }
  254. mtec.cc.getLocalPosition = function(local: Node, node: Vec3|Node, out?: Vec3){
  255. if([local && local.isValid, node instanceof Vec3 ? true : (node && node.isValid)].includes(false)) return void 0;
  256. return local.getComponent(UITransform).convertToNodeSpaceAR(node instanceof Vec3 ? node : mtec.cc.getWorldPosition(node), out??v3());
  257. };
  258. mtec.cc.v2 = function(__x__, y){
  259. if(__x__ instanceof Vec2) return __x__;
  260. let x: number;
  261. if(typeof __x__ == 'number'){
  262. x = __x__;
  263. y = y??x;
  264. }else ({x, y} = __x__);
  265. return v2(x, y);
  266. }
  267. mtec.cc.v3 = function(__x__, y, z){
  268. if(__x__ instanceof Vec3) return __x__;
  269. let x: number;
  270. if(typeof __x__ == 'number'){
  271. x = __x__;
  272. y = y??x;
  273. z = z??y;
  274. }else if(__x__ instanceof Vec2){
  275. z = y??0;
  276. ({x, y} = __x__);
  277. }else if(__x__ instanceof Vec4){
  278. ({x, y, z} = __x__);
  279. }
  280. return v3(x, y, z);
  281. }
  282. mtec.cc.v4 = function(__x__, y, z, w){
  283. if(__x__ instanceof Vec4) return __x__;
  284. let x: number;
  285. if(typeof __x__ == 'number'){
  286. x = __x__;
  287. y = y??x;
  288. z = z??y;
  289. w = w??z;
  290. }else if(__x__ instanceof Vec2){
  291. w = z??0;
  292. z = y??0;
  293. ({x, y} = __x__);
  294. }else if(__x__ instanceof Vec3){
  295. w = z??0;
  296. ({x, y, z} = __x__);
  297. }
  298. return v4(x, y, z, w);
  299. }
  300. mtec.cc.adaptBackgroundNode = function(node, container){
  301. container = container ?? node.parent;
  302. if(!container || ![node, container].every(n=>n.isValid)) return void 0;
  303. let [ui_container, ui_node] = [container, node].map(n=>{
  304. let ui = n.getComponent(UITransform);
  305. if(!ui) ui = n.addComponent(UITransform);
  306. return ui;
  307. });
  308. let node_size: Size;
  309. if(node.getComponent(Sprite)) node_size = node.getComponent(Sprite).spriteFrame.originalSize;
  310. else node_size = ui_node.contentSize;
  311. let [R, r] = [ui_container, node_size].map($=>$.width / $.height);
  312. let ratio: number;
  313. if(R > r) ratio = ui_container.width / node_size.width;
  314. else ratio = ui_container.height / node_size.height;
  315. ui_node.setContentSize(node_size.width * ratio, node_size.height * ratio);
  316. }
  317. Reflect.defineProperty(mtec.cc, 'canvas', {
  318. get(){
  319. return director.getScene().getComponentInChildren(Canvas);
  320. },
  321. enumerable: true,
  322. configurable: false,
  323. });
  324. Reflect.defineProperty(mtec.size, 'designSize', {
  325. get() {
  326. return view.getDesignResolutionSize();
  327. },
  328. enumerable: true,
  329. configurable: false,
  330. });
  331. Reflect.defineProperty(mtec.size, 'canvasSize', {
  332. get() {
  333. return mtec.cc.canvas.getComponent(UITransform).contentSize;
  334. },
  335. enumerable: true,
  336. configurable: false,
  337. });
  338. mtec.size.innerRatio = function(target, container){
  339. let [R, r] = [container, target].map(s=>s.width / s.height);
  340. /** @type {number} */
  341. let ratio: number;
  342. if(r > R) ratio = container.width / target.width;
  343. else ratio = container.height / target.height;
  344. return ratio;
  345. }
  346. mtec.size.exterRatio = function(target, filler){
  347. let [R, r] = [target, filler].map(s=>s.width / s.height);
  348. /** @type {number} */
  349. let ratio: number;
  350. if(R > r) ratio = filler.height / target.height;
  351. else ratio = filler.width / target.width;
  352. return ratio;
  353. }
  354. mtec.vector.distance = function(a, b){
  355. if([a, b].map(v=>v instanceof Vec2).includes(true)) return Vec2.subtract(v2(), mtec.cc.v2(a), mtec.cc.v2(b)).length();
  356. if([a, b].map(v=>v instanceof Vec3).includes(true)) return Vec3.subtract(v3(), mtec.cc.v3(a), mtec.cc.v3(b)).length();
  357. return Vec4.subtract(v4(), mtec.cc.v4(a), mtec.cc.v4(b)).length();
  358. }