index.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. System.register("chunks:///_virtual/MultTextures.ts", ['cc', './env'], function (exports) {
  2. var cclegacy, gfx, Material, Component, ImageAsset, Texture2D, game, Game, director, Director, StencilManager, assert, resources, renderer, murmurhash2_32_gc, Label, BitmapFont, Sprite, MotionStreak, TiledLayer, JSB;
  3. return {
  4. setters: [function (module) {
  5. cclegacy = module.cclegacy;
  6. gfx = module.gfx;
  7. Material = module.Material;
  8. Component = module.Component;
  9. ImageAsset = module.ImageAsset;
  10. Texture2D = module.Texture2D;
  11. game = module.game;
  12. Game = module.Game;
  13. director = module.director;
  14. Director = module.Director;
  15. StencilManager = module.StencilManager;
  16. assert = module.assert;
  17. resources = module.resources;
  18. renderer = module.renderer;
  19. murmurhash2_32_gc = module.murmurhash2_32_gc;
  20. Label = module.Label;
  21. BitmapFont = module.BitmapFont;
  22. Sprite = module.Sprite;
  23. MotionStreak = module.MotionStreak;
  24. TiledLayer = module.TiledLayer;
  25. }, function (module) {
  26. JSB = module.JSB;
  27. }],
  28. execute: function () {
  29. cclegacy._RF.push({}, "bd7e7vtojdMUJODlbuIb/Yi", "MultTextures", undefined);
  30. //最大纹理,固定8张
  31. var MAX_TEX = 8;
  32. //原生开关,根据需要开启或关闭
  33. var SUPPORT_NATIVE = true;
  34. //@ts-ignore
  35. gfx.Texture.prototype.texID = -1; //当前纹理id
  36. //@ts-ignore
  37. Material.prototype.isMult = false; //多纹理材质的标记
  38. //@ts-ignore
  39. Component.prototype.useMult = false; //组件多纹理开关
  40. var MultBatch2D = exports('MultBatch2D', {
  41. "native": !SUPPORT_NATIVE,
  42. enable: false,
  43. parent: null,
  44. incID: 0,
  45. count: 0,
  46. hash: 0,
  47. reset: function reset() {
  48. this.incID += this.count;
  49. this.count = 0;
  50. }
  51. });
  52. var _image = new ImageAsset({
  53. width: 1,
  54. height: 1,
  55. _compressed: false,
  56. format: gfx.Format.RGBA32F,
  57. _data: new Float32Array(4).fill(0)
  58. });
  59. var Texture = new Texture2D();
  60. Texture.setFilters(1, 1);
  61. Texture.image = _image;
  62. Texture.addRef();
  63. //预加载多纹理材质
  64. var loadMultTextures = function loadMultTextures() {
  65. MultBatch2D.enable = false;
  66. resources.load("multTextures/Mult-material", Material, function (err, material) {
  67. if (!err) {
  68. var mat = cclegacy.builtinResMgr.get('ui-sprite-material');
  69. if (mat) {
  70. mat._hash = MultBatch2D.hash = Material.getHash(mat);
  71. MultBatch2D.parent = material;
  72. MultBatch2D.enable = true;
  73. material.addRef();
  74. }
  75. }
  76. });
  77. };
  78. //多纹理材质缓存队列
  79. var _cacheUseCount = 0;
  80. var _cacheMaterials = [];
  81. var getMultMaterial = function getMultMaterial(oldMat, rd) {
  82. if (rd === void 0) {
  83. rd = null;
  84. }
  85. var MB = MultBatch2D;
  86. MB.reset();
  87. if (!MB.enable || !oldMat || !rd || !rd.isMult) {
  88. return oldMat;
  89. }
  90. if (!MB.parent || !MB.parent.isValid) {
  91. loadMultTextures();
  92. return oldMat;
  93. }
  94. var newMat = _cacheMaterials[_cacheUseCount++];
  95. if (!newMat || !newMat.isValid) {
  96. var material = {
  97. parent: MB.parent
  98. };
  99. newMat = new renderer.MaterialInstance(material);
  100. _cacheMaterials[_cacheUseCount - 1] = newMat;
  101. newMat['cacheTextures'] = [];
  102. newMat['isMult'] = true;
  103. newMat.addRef();
  104. }
  105. return newMat;
  106. };
  107. //游戏启动前,务必加载多纹理材质
  108. game.once(Game.EVENT_GAME_INITED, function () {
  109. if (MultBatch2D["native"]) return; //|| JSB
  110. loadMultTextures();
  111. });
  112. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  113. // 多纹理合批,sprite , label , renderdata ,等其他组件的重写和监听
  114. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  115. var inject_Renderdata = function inject_Renderdata() {
  116. var RenderData = cclegacy.UI.RenderData.prototype;
  117. RenderData.texID = -1;
  118. RenderData.isMult = false;
  119. RenderData.matDirty = true;
  120. RenderData.texDirty = true;
  121. RenderData.dataDirty = 0x0;
  122. //兼容多纹理hash计算
  123. RenderData.updateHash = function () {
  124. if (this.isMult && MultBatch2D.enable) {
  125. var bid = this.chunk ? this.chunk.bufferId : -1;
  126. var hashString = "" + bid + this.layer + '98k';
  127. this.dataHash = murmurhash2_32_gc(hashString, 666);
  128. this.hashDirty = false;
  129. } else {
  130. var _bid = this.chunk ? this.chunk.bufferId : -1;
  131. var _hashString = "" + _bid + this.layer + " " + this.textureHash;
  132. this.dataHash = murmurhash2_32_gc(_hashString, 666);
  133. this.hashDirty = false;
  134. }
  135. this.matDirty = false;
  136. };
  137. //监听纹理的变更
  138. Object.defineProperty(RenderData, "textureDirty", {
  139. get: function get() {
  140. return this.texDirty;
  141. },
  142. set: function set(val) {
  143. this.texDirty = val;
  144. if (val === true) {
  145. this.texID = -1;
  146. }
  147. }
  148. });
  149. //检测是否支持多纹理合批
  150. var isMultTextures = function isMultTextures(rd, uir) {
  151. rd.isMult = false;
  152. var material = uir.getRenderMaterial(0);
  153. if (!material || !MultBatch2D.enable) return;
  154. //@ts-ignore
  155. //组件控制开关 useMult: 可以开启自定义组件参与多纹理
  156. //|| uir instanceof Sprite || uir instanceof Label
  157. if (uir.useMult) {
  158. material._hash = material.hash || material._hash;
  159. if (!material._hash) {
  160. material._hash = Material.getHash(material);
  161. }
  162. rd.isMult = MultBatch2D.hash == material._hash;
  163. }
  164. };
  165. //监听pass变更,检测是否多纹理支持
  166. var updatePass = RenderData.updatePass;
  167. RenderData.updatePass = function (comp) {
  168. isMultTextures(this, comp);
  169. updatePass.call(this, comp);
  170. };
  171. //监听pass变更,检测是否多纹理支持
  172. var updateRenderData = RenderData.updateRenderData;
  173. RenderData.updateRenderData = function (comp, frame) {
  174. if (this.passDirty) {
  175. isMultTextures(this, comp);
  176. }
  177. //isMultTextures(this, comp);
  178. updateRenderData.call(this, comp, frame);
  179. };
  180. };
  181. var inject_Label = function inject_Label() {
  182. //@ts-ignore
  183. Label.prototype.useMult = true;
  184. //监听 Label 的 uv 变更
  185. var label = Label.Assembler;
  186. if (label) {
  187. var getAssembler = label.getAssembler;
  188. label.getAssembler = function (comp) {
  189. var assembler = getAssembler.call(this, comp);
  190. if (assembler.changeUV == undefined) {
  191. assembler.changeUV = function (s) {
  192. var rd = s.renderData;
  193. rd && (rd.dataDirty = 1);
  194. };
  195. var UVs = assembler.updateUVs;
  196. if (UVs) {
  197. if (comp.font instanceof BitmapFont) {
  198. assembler.updateUVs = function (comp) {
  199. UVs.call(this, comp);
  200. this.changeUV(comp);
  201. };
  202. } else if (comp.cacheMode === Label.CacheMode.CHAR) {
  203. assembler.updateUVs = function (comp) {
  204. UVs.call(this, comp);
  205. this.changeUV(comp);
  206. };
  207. } else {
  208. assembler.updateUVs = function (comp) {
  209. UVs.call(this, comp);
  210. var renderData = comp.renderData;
  211. if (!renderData || !comp.ttfSpriteFrame) {
  212. return;
  213. }
  214. this.changeUV(comp);
  215. };
  216. }
  217. }
  218. }
  219. return assembler;
  220. };
  221. }
  222. };
  223. var inject_Sprite = function inject_Sprite() {
  224. //@ts-ignore
  225. Sprite.prototype.useMult = true;
  226. //监听 sprite 的 uv 变更
  227. var sprite = Sprite.Assembler;
  228. if (sprite) {
  229. var getAssembler = sprite.getAssembler;
  230. sprite.getAssembler = function (comp) {
  231. var assembler = getAssembler.call(this, comp);
  232. if (assembler.changeUV == undefined) {
  233. assembler.changeUV = function (s) {
  234. var rd = s.renderData;
  235. rd && (rd.dataDirty = 1);
  236. };
  237. var UVs = assembler.updateUVs;
  238. if (UVs) {
  239. if (comp.type == Sprite.Type.FILLED) {
  240. if (comp.fillType != Sprite.FillType.RADIAL) {
  241. assembler.updateUVs = function (s, f0, f1) {
  242. UVs.call(this, s, f0, f1);
  243. this.changeUV(s);
  244. };
  245. }
  246. } else {
  247. if (comp.type != Sprite.Type.TILED) {
  248. assembler.updateUVs = function (s) {
  249. UVs.call(this, s);
  250. if (s.spriteFrame) this.changeUV(s);
  251. };
  252. }
  253. }
  254. }
  255. var verUV = assembler.updateWorldVertexAndUVData;
  256. if (verUV) {
  257. assembler.updateWorldVertexAndUVData = function (s, c) {
  258. verUV.call(this, s, c);
  259. this.changeUV(s);
  260. };
  261. }
  262. }
  263. return assembler;
  264. };
  265. }
  266. };
  267. var inject_MotionStreak = function inject_MotionStreak() {
  268. if (MotionStreak) {
  269. var motionStreak = MotionStreak.prototype;
  270. motionStreak.useMult = true; //参与多纹理合批
  271. var lateUpdate = motionStreak.lateUpdate;
  272. motionStreak.lateUpdate = function (dt) {
  273. lateUpdate.call(this, dt);
  274. if (this._assembler) {
  275. if (this.points.length >= 2) {
  276. var rd = this.renderData;
  277. //全局标记刷新纹理uv
  278. rd && (rd.dataDirty = 1);
  279. }
  280. }
  281. };
  282. }
  283. };
  284. var inject_TiledLayer = function inject_TiledLayer() {
  285. if (TiledLayer && !JSB) {
  286. var Tiled = TiledLayer.prototype;
  287. Tiled.useMult = true; //参与多纹理合批
  288. Tiled.dataDirty = false; //全局标记刷新纹理uv
  289. var setUserNodeDirty = Tiled.setUserNodeDirty;
  290. Tiled.setUserNodeDirty = function (dirty) {
  291. setUserNodeDirty.call(this, dirty);
  292. if (!dirty) {
  293. //全局标记刷新纹理uv
  294. this.dataDirty = true;
  295. }
  296. };
  297. Tiled._render = function (ui) {
  298. var _this = this;
  299. var layer = this.node.layer;
  300. var _loop = function _loop(_j) {
  301. _this._tiledDataArrayIdx = i;
  302. var m = _this._tiledDataArray[i];
  303. var info = _this._drawInfoList[_j];
  304. if (m.subNodes) {
  305. // 提前处理 User Nodes
  306. m.subNodes.forEach(function (c) {
  307. if (c) {
  308. ui.walk(c.node);
  309. _j++;
  310. }
  311. });
  312. } else {
  313. var td = m;
  314. if (td.texture) {
  315. var isDirty = false;
  316. var rd = td.renderData;
  317. rd.material = _this.getRenderMaterial(0);
  318. if (rd.texture !== td.texture) {
  319. rd.texture = td.texture;
  320. // isDirty = true;
  321. }
  322. if (rd.layer !== layer) {
  323. rd.layer = layer;
  324. isDirty = true;
  325. }
  326. rd.isMult = true; //强制参与多纹理
  327. // if (JSB) rd._renderDrawInfo = info;
  328. //更新renderdata hash
  329. isDirty && rd.updateHash();
  330. if (_this.dataDirty) rd.dataDirty = 1;
  331. // NOTE: 由于 commitComp 只支持单张纹理, 故分多次提交
  332. ui.commitComp(_this, td.renderData, td.texture, _this._assembler, null);
  333. _j++;
  334. }
  335. }
  336. j = _j;
  337. };
  338. for (var i = 0, j = 0; i < this._tiledDataArray.length; i++) {
  339. _loop(j);
  340. }
  341. this.dataDirty = false;
  342. this.node._static = true;
  343. };
  344. }
  345. };
  346. game.once(Game.EVENT_ENGINE_INITED, function () {
  347. if (MultBatch2D["native"]) return; //|| JSB
  348. inject_Label();
  349. inject_Sprite();
  350. inject_Renderdata();
  351. inject_TiledLayer();
  352. inject_MotionStreak();
  353. director.on(Director.EVENT_AFTER_DRAW, function (dt) {
  354. MultBatch2D.reset();
  355. _cacheUseCount = 0;
  356. });
  357. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  358. // 多纹理合批,合批核心过程修改
  359. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  360. var Batcher2D = cclegacy.internal.Batcher2D.prototype;
  361. Batcher2D.isMult = false; //多纹理标记
  362. Batcher2D.isNative = JSB; //原生的开关
  363. Batcher2D.cacheTextures = []; //纹理缓存数据
  364. Batcher2D.currMaterial = null; //当前指定材质
  365. Object.defineProperty(Batcher2D, "_currMaterial", {
  366. get: function get() {
  367. return this.currMaterial;
  368. },
  369. set: function set(material) {
  370. // if (this.currMaterial === material) return;
  371. //检测多纹理材质,接替 _currMaterial
  372. var rd = this._currRenderData; //重置检测
  373. if (material == this._emptyMaterial) rd = null;
  374. this.currMaterial = getMultMaterial(material, rd);
  375. this.isMult = false;
  376. if (MultBatch2D.enable) {
  377. if (this.currMaterial && this.currMaterial.isMult) {
  378. this.cacheTextures = this.currMaterial.cacheTextures;
  379. this.isMult = true; //当前 batcher 多纹理标记
  380. }
  381. }
  382. }
  383. });
  384. var Stage_ENTER_LEVEL = 2;
  385. var Stage_ENTER_LEVEL_INVERTED = 6;
  386. //@ts-ignore
  387. Batcher2D.commitComp = function (comp, renderData, frame, assembler, transform) {
  388. var dataHash = 0;
  389. var mat = null;
  390. var bufferID = -1;
  391. if (renderData && renderData.chunk) {
  392. if (!renderData.isValid()) return;
  393. dataHash = renderData.dataHash;
  394. mat = renderData.material;
  395. bufferID = renderData.chunk.bufferId;
  396. }
  397. // Notice: A little hack, if it is for mask, not need update here, while control by stencilManger
  398. if (comp.stencilStage === Stage_ENTER_LEVEL || comp.stencilStage === Stage_ENTER_LEVEL_INVERTED) {
  399. this._insertMaskBatch(comp);
  400. } else {
  401. comp.stencilStage = StencilManager.sharedManager.stage;
  402. }
  403. var depthStencilStateStage = comp.stencilStage;
  404. var texID = -1;
  405. var texture = null;
  406. var MB = MultBatch2D;
  407. var flushBatch = false;
  408. var isNative = this.isNative;
  409. //@ts-ignore
  410. if (MB.enable && renderData && renderData.isMult) {
  411. if (frame && frame.isValid) texture = frame.getGFXTexture();
  412. if (texture) {
  413. //@ts-ignore
  414. if (texture.texID === undefined) texture.texID = -1;
  415. //@ts-ignore
  416. texID = texture.texID - MB.incID;
  417. flushBatch = texID < 0 && MB.count >= MAX_TEX;
  418. if (this.isMult) mat = this._currMaterial;
  419. }
  420. }
  421. if (flushBatch || this._currHash !== dataHash || dataHash === 0 || this._currMaterial !== mat || this._currDepthStencilStateStage !== depthStencilStateStage) {
  422. // Merge all previous data to a render batch, and update buffer for next render data
  423. this.autoMergeBatches(this._currComponent);
  424. if (!isNative && renderData && !renderData._isMeshBuffer) {
  425. this.updateBuffer(renderData.vertexFormat, bufferID);
  426. }
  427. this._currRenderData = renderData;
  428. this._currHash = renderData ? renderData.dataHash : 0;
  429. this._currComponent = comp;
  430. this._currTransform = transform;
  431. this._currMaterial = comp.getRenderMaterial(0);
  432. this._currDepthStencilStateStage = depthStencilStateStage;
  433. this._currLayer = comp.node.layer;
  434. if (frame) {
  435. {
  436. assert(frame.isValid, 'frame should not be invalid, it may have been released');
  437. }
  438. this._currTexture = frame.getGFXTexture();
  439. this._currSampler = frame.getGFXSampler();
  440. this._currTextureHash = frame.getHash();
  441. this._currSamplerHash = this._currSampler.hash;
  442. } else {
  443. this._currTexture = null;
  444. this._currSampler = null;
  445. this._currTextureHash = 0;
  446. this._currSamplerHash = 0;
  447. }
  448. }
  449. if (!isNative) assembler.fillBuffers(comp, this);
  450. if (texture) {
  451. if (texID < 0 || MB.count === 0) {
  452. texID = MB.count++;
  453. //@ts-ignore
  454. //let id = texture.objectID;
  455. //@ts-ignore
  456. texture.texID = texID + MB.incID;
  457. var caches = this.cacheTextures;
  458. if (caches[texID] !== texture) {
  459. caches[texID] = texture;
  460. //@ts-ignore
  461. texture = frame.texture;
  462. if (!texture) texture = frame;
  463. this._currMaterial.setProperty("texture" + texID, texture);
  464. }
  465. }
  466. this.fillTextureID(renderData, texID);
  467. if (isNative) {
  468. renderData.renderDrawInfo.setMaterial(this._currMaterial);
  469. }
  470. }
  471. };
  472. //填充多纹理 id 到顶点数据
  473. Batcher2D.fillTextureID = function (renderData, texID) {
  474. // if (!renderData) return;
  475. var vbuf = renderData.chunk.vb;
  476. var uvX = 0,
  477. length = vbuf.length;
  478. if (renderData.dataDirty === 1) {
  479. for (var i = 0; i < length; i += 9) {
  480. uvX = ~~(vbuf[i + 3] * 100000);
  481. vbuf[i + 3] = uvX * 10 + texID;
  482. }
  483. } else {
  484. if (renderData.texID !== texID) {
  485. for (var _i = 0; _i < length; _i += 9) {
  486. uvX = ~~(vbuf[_i + 3] * 0.1);
  487. vbuf[_i + 3] = uvX * 10 + texID;
  488. }
  489. }
  490. }
  491. renderData.dataDirty = 0;
  492. renderData.texID = texID;
  493. };
  494. });
  495. //*/
  496. cclegacy._RF.pop();
  497. }
  498. };
  499. });
  500. System.register("chunks:///_virtual/resources", ['./MultTextures.ts'], function () {
  501. return {
  502. setters: [null],
  503. execute: function () {}
  504. };
  505. });
  506. (function(r) {
  507. r('virtual:///prerequisite-imports/resources', 'chunks:///_virtual/resources');
  508. })(function(mid, cid) {
  509. System.register(mid, [cid], function (_export, _context) {
  510. return {
  511. setters: [function(_m) {
  512. var _exportObj = {};
  513. for (var _key in _m) {
  514. if (_key !== "default" && _key !== "__esModule") _exportObj[_key] = _m[_key];
  515. }
  516. _export(_exportObj);
  517. }],
  518. execute: function () { }
  519. };
  520. });
  521. });