buff和技能表实现

master
humingxing 2 days ago
parent b9f4a6713f
commit f0f9cf7499
  1. 36
      assets/script/battle/combat/BattleBuffDamageHook.ts
  2. 76
      assets/script/battle/combat/PassiveSkillRuntime.ts
  3. 8
      docs/方案-Battlebuff扩展105-112.md
  4. 12
      preview-template/workbench/css/workbench.css
  5. 275
      preview-template/workbench/js/agent-assets.js
  6. 7
      preview-template/workbench/js/panels/assets.js

@ -1,10 +1,9 @@
import type { BattleSession } from 'db://assets/mx/module/battle';
import type { AbilityContext } from 'db://assets/mx/module/battle/combat/AbilityContext'; import type { AbilityContext } from 'db://assets/mx/module/battle/combat/AbilityContext';
import { import {
setDamagePreCalcHook, setDamagePreCalcHook,
type DamagePreCalcState, type DamagePreCalcState,
} from 'db://assets/mx/module/battle/combat/DamagePipeline'; } from 'db://assets/mx/module/battle/combat/DamagePipeline';
import { AttributeComp } from 'db://assets/mx/module/battle/ecs/Components';
import type { EntityId } from 'db://assets/mx/module/ecs';
import { getBattleBuffDigitStatHost } from './BattleBuffDigitStatHost'; import { getBattleBuffDigitStatHost } from './BattleBuffDigitStatHost';
import { getPassiveSkillHost } from './PassiveSkillRuntime'; import { getPassiveSkillHost } from './PassiveSkillRuntime';
@ -32,26 +31,7 @@ function listHasSkill(ids: readonly number[], skillId: number): boolean {
} }
/** /**
* 目标是否处于减速(move_speed_mul<1 或 debuff_3 / slow 标签)。 * 局内数字 buff + 被动 condition7/8 result21 伤害预调。
* @param ctx 伤害上下文
* @param target 目标
*/
function targetIsSlowed(ctx: AbilityContext, target: EntityId): boolean {
const world = ctx.services.world;
const attr = world.getComponent(target, AttributeComp);
if (attr) {
for (let i = 0; i < attr.modifiers.length; i++) {
const m = attr.modifiers[i];
if (m.attr === 'move_speed_mul' && m.op === 'Mul' && m.value < 1) return true;
}
}
if (ctx.services.buffs.hasTag(target, 'debuff_3')) return true;
if (ctx.services.buffs.hasTag(target, 'slow')) return true;
return false;
}
/**
* 局内数字 buff 伤害预调:107/110/111/112。
*/ */
export class BattleBuffDamageHook { export class BattleBuffDamageHook {
/** 注册到 DamagePipeline */ /** 注册到 DamagePipeline */
@ -72,6 +52,12 @@ export class BattleBuffDamageHook {
* @param state 可调状态 * @param state 可调状态
*/ */
static apply(ctx: AbilityContext, params: Record<string, unknown>, state: DamagePreCalcState): void { static apply(ctx: AbilityContext, params: Record<string, unknown>, state: DamagePreCalcState): void {
const session = ctx.services as unknown as BattleSession;
const target = ctx.targets[0] ?? 0;
if (target > 0) {
getPassiveSkillHost().applyHitDamageMods(session, ctx.caster, target, state);
}
const flags = getBattleBuffDigitStatHost().getFlags(ctx.caster); const flags = getBattleBuffDigitStatHost().getFlags(ctx.caster);
if (!flags) return; if (!flags) return;
const skillId = parseSkillIdFromAbilityId(ctx.abilityId); const skillId = parseSkillIdFromAbilityId(ctx.abilityId);
@ -100,7 +86,6 @@ export class BattleBuffDamageHook {
} }
} }
const target = ctx.targets[0];
if (!(target > 0)) return; if (!(target > 0)) return;
const mode = flags.condCrit; const mode = flags.condCrit;
if (!mode) return; if (!mode) return;
@ -109,12 +94,13 @@ export class BattleBuffDamageHook {
state.critRateToCritDmg = true; state.critRateToCritDmg = true;
return; return;
} }
const host = getPassiveSkillHost();
if (mode === 'poison') { if (mode === 'poison') {
if (getPassiveSkillHost().hasPoison(target)) state.forceCrit = true; if (host.hasPoison(target)) state.forceCrit = true;
return; return;
} }
if (mode === 'slow') { if (mode === 'slow') {
if (targetIsSlowed(ctx, target)) state.forceCrit = true; if (host.isTargetSlowed(session, target)) state.forceCrit = true;
} }
} }
} }

@ -56,6 +56,10 @@ export enum PassiveConditionKind {
OnKill = 5, OnKill = 5,
/** 技能释放次数(含普攻 AbilityCast),参数:次数 */ /** 技能释放次数(含普攻 AbilityCast),参数:次数 */
SkillCastCount = 6, SkillCastCount = 6,
/** 攻击中毒单位造成伤害(伤害预调判定) */
OnPoisonedHit = 7,
/** 攻击减速单位造成伤害(伤害预调判定) */
OnSlowedHit = 8,
} }
/** 被动触发结果类型 */ /** 被动触发结果类型 */
@ -100,6 +104,8 @@ export enum PassiveResultKind {
BehindFan = 19, BehindFan = 19,
/** 击杀叠伤害:加成万分比,最大叠加次数 */ /** 击杀叠伤害:加成万分比,最大叠加次数 */
KillDmgStack = 20, KillDmgStack = 20,
/** 该次伤害必定暴击,暴击率转化成暴击伤害 */
ForceCritConvert = 21,
/** 空 result:按行 atk_type 施放一次 */ /** 空 result:按行 atk_type 施放一次 */
CastAtkRow = 0, CastAtkRow = 0,
} }
@ -646,6 +652,61 @@ export class PassiveSkillHost {
return false; return false;
} }
/**
* 目标是否减速(move_speed_mul&lt;1 或 debuff_3/slow)。
* @param session 会话
* @param target 目标
*/
isTargetSlowed(session: BattleSession, target: EntityId): boolean {
if (!(target > 0) || !session.world.isAlive(target)) return false;
const attr = session.world.getComponent(target, AttributeComp);
if (attr) {
for (let i = 0; i < attr.modifiers.length; i++) {
const m = attr.modifiers[i];
if (m.attr === 'move_speed_mul' && m.op === 'Mul' && m.value < 1) return true;
}
}
if (session.buffs.hasTag(target, 'debuff_3')) return true;
if (session.buffs.hasTag(target, 'slow')) return true;
return false;
}
/**
* 伤害预调:condition 7/8 + result 21(该次伤害必暴+暴击转爆伤)。
* @param session 会话
* @param caster 伤害来源
* @param target 受击目标
* @param state 伤害预调状态
*/
applyHitDamageMods(
session: BattleSession,
caster: EntityId,
target: EntityId,
state: { forceCrit: boolean; critRateToCritDmg: boolean },
): void {
if (!(target > 0)) return;
const idx = this._indexOf(caster);
if (idx < 0) return;
const list = this._binds[idx].list;
for (let i = 0; i < list.length; i++) {
const b = list[i];
if (b.resultKind !== PassiveResultKind.ForceCritConvert) continue;
if (b.conditionKind === PassiveConditionKind.OnPoisonedHit) {
if (this.hasPoison(target)) {
state.forceCrit = true;
state.critRateToCritDmg = true;
}
continue;
}
if (b.conditionKind === PassiveConditionKind.OnSlowedHit) {
if (this.isTargetSlowed(session, target)) {
state.forceCrit = true;
state.critRateToCritDmg = true;
}
}
}
}
/** /**
* 查询实体已绑定被动。 * 查询实体已绑定被动。
* @param entityId 塔实体 * @param entityId 塔实体
@ -796,9 +857,17 @@ export class PassiveSkillHost {
} }
} }
/** 命中判定 condition 1/4 */ /** 命中判定 condition 1/4;7/8+result21 在伤害预调处理,此处跳过 */
private _tryOnHit(session: BattleSession, caster: EntityId, target: EntityId, bind: PassiveSkillBind, amount: number): boolean { private _tryOnHit(session: BattleSession, caster: EntityId, target: EntityId, bind: PassiveSkillBind, amount: number): boolean {
const kind = bind.conditionKind; const kind = bind.conditionKind;
if (kind === PassiveConditionKind.OnPoisonedHit || kind === PassiveConditionKind.OnSlowedHit) {
if (bind.resultKind === PassiveResultKind.ForceCritConvert) return false;
if (bind.cdLeft > 0) return false;
if (kind === PassiveConditionKind.OnPoisonedHit && !this.hasPoison(target)) return false;
if (kind === PassiveConditionKind.OnSlowedHit && !this.isTargetSlowed(session, target)) return false;
this._fire(session, caster, target, bind, amount);
return true;
}
if (kind === PassiveConditionKind.OnDealDamage) { if (kind === PassiveConditionKind.OnDealDamage) {
if (bind.cdLeft > 0) return false; if (bind.cdLeft > 0) return false;
if (!this._rollWan(session, bind.conditionParams[0], bind.skillId)) return false; if (!this._rollWan(session, bind.conditionParams[0], bind.skillId)) return false;
@ -978,6 +1047,9 @@ export class PassiveSkillHost {
case PassiveResultKind.KillDmgStack: case PassiveResultKind.KillDmgStack:
this._applyKillDmgStack(session, caster, bind, p); this._applyKillDmgStack(session, caster, bind, p);
return; return;
case PassiveResultKind.ForceCritConvert:
// 该次伤害修正在 applyHitDamageMods / 伤害预调中处理
return;
case PassiveResultKind.CastAtkRow: case PassiveResultKind.CastAtkRow:
this._applyCastAtkRow(session, caster, target, bind); this._applyCastAtkRow(session, caster, target, bind);
return; return;
@ -2216,7 +2288,7 @@ export class PassiveSkillHost {
const condParts = cond.split(',').map(Number); const condParts = cond.split(',').map(Number);
const resultParts = result ? result.split(',').map(Number) : [PassiveResultKind.CastAtkRow]; const resultParts = result ? result.split(',').map(Number) : [PassiveResultKind.CastAtkRow];
const conditionKind = condParts[0] || 0; const conditionKind = condParts[0] || 0;
if (conditionKind < 1 || conditionKind > 6) { if (conditionKind < 1 || conditionKind > 8) {
console.log(`[PassiveSkill] 未知 condition skill=${skillId} kind=${conditionKind}`); console.log(`[PassiveSkill] 未知 condition skill=${skillId} kind=${conditionKind}`);
} }
return { return {

@ -30,11 +30,19 @@
| 18 | 寒潭减速 | `PassiveSkillHost` 地面区 | | 18 | 寒潭减速 | `PassiveSkillHost` 地面区 |
| 19 | 目标身后扇形 | 向量扇形圈伤 | | 19 | 目标身后扇形 | 向量扇形圈伤 |
| 20 | 击杀叠伤 | `dmg_mul` 叠层 | | 20 | 击杀叠伤 | `dmg_mul` 叠层 |
| 21 | 该次伤害必暴+暴击转爆伤 | 伤害预调(配合 condition 7/8) |
空 `result` + 有 `atk_type`:`CastAtkRow` 注册 `ability_buffskill_*` 后 `tryCast`(冰球术/穿云击/群体加速)。 空 `result` + 有 `atk_type`:`CastAtkRow` 注册 `ability_buffskill_*` 后 `tryCast`(冰球术/穿云击/群体加速)。
`condition=2` 且 `cd>0`:部署触发后按 CD 循环(远攻剑气)。 `condition=2` 且 `cd>0`:部署触发后按 CD 循环(远攻剑气)。
| condition | 含义 |
|----------:|------|
| 7 | 攻击中毒单位造成伤害(预调判定) |
| 8 | 攻击减速单位造成伤害(预调判定) |
> 2026-10-15 导表:`2062/3062` 由 ft=112 改为 ft=105 挂 `206201/306201`(cond 7/8 + result 21)。`4052 霸王之气` 仍为 ft=112。
## 3. 代码入口 ## 3. 代码入口
- `BattleBuffDigitStatHost`:101–112 刷新、挂 Skill、战斗标记 - `BattleBuffDigitStatHost`:101–112 刷新、挂 Skill、战斗标记

@ -1127,6 +1127,18 @@ body {
font-variant-numeric: tabular-nums; font-variant-numeric: tabular-nums;
} }
.pw-assets-tag {
display: inline-block;
margin-left: 4px;
padding: 0 4px;
border-radius: 3px;
font-size: 9px;
line-height: 14px;
background: rgba(47, 111, 237, 0.18);
color: var(--pw-info);
vertical-align: middle;
}
.pw-assets-side { .pw-assets-side {
width: 168px; width: 168px;
flex-shrink: 0; flex-shrink: 0;

@ -85,10 +85,49 @@
} }
/** /**
* 解析资源所属 Bundle。 * 按构建「依赖打入分包」扩展归属:
* 顺序:asset 上的 bundle 字段 → nativeUrl 路径 → bundle.getAssetInfo → cache.has * 包内资源引用到的、且尚未被其它包显式声明的资源,打入同一包。
* 使用 assetManager.dependUtil.getDependsRecursively。
*/ */
function resolveBundleName(uuid, asset, bundleObjs, uuidMap) { function expandOwnershipByDeps(cc, bi) {
var depUtil = cc.assetManager && cc.assetManager.dependUtil;
if (!depUtil || typeof depUtil.getDependsRecursively !== 'function') return;
var uuidMap = bi.uuidMap || {};
var depPacked = bi.depPacked || (bi.depPacked = {});
var roots = [];
for (var u in uuidMap) {
if (Object.prototype.hasOwnProperty.call(uuidMap, u)) roots.push(u);
}
for (var i = 0; i < roots.length; i++) {
var root = roots[i];
var bname = uuidMap[root];
if (!bname) continue;
var deps = null;
try {
deps = depUtil.getDependsRecursively(root);
} catch (e) {
try {
deps = depUtil.getDeps(root);
} catch (e2) {
deps = null;
}
}
if (!deps || !deps.length) continue;
for (var j = 0; j < deps.length; j++) {
var d = String(deps[j]);
if (!d || d === root) continue;
// 已被其它包显式占有则不抢(跨包引用)
if (uuidMap[d] && uuidMap[d] !== bname) continue;
if (!uuidMap[d]) {
uuidMap[d] = bname;
depPacked[d] = true;
}
}
}
}
function resolveBundleName(uuid, asset, bi) {
try { try {
if (asset) { if (asset) {
if (asset.bundle && asset.bundle.name) return asset.bundle.name; if (asset.bundle && asset.bundle.name) return asset.bundle.name;
@ -96,54 +135,52 @@
if (asset.__bundleName) return asset.__bundleName; if (asset.__bundleName) return asset.__bundleName;
} }
} catch (e) { /* */ } } catch (e) { /* */ }
if (bi && bi.uuidMap && uuid && bi.uuidMap[uuid]) return bi.uuidMap[uuid];
if (uuidMap && uuid && uuidMap[uuid]) return uuidMap[uuid];
var url = (asset && (asset.nativeUrl || asset._nativeUrl)) || ''; var url = (asset && (asset.nativeUrl || asset._nativeUrl)) || '';
var m = String(url).match(/\/([A-Za-z0-9_\-]+)\/(?:import|native|js|ohm|chunks)\//i); var m = String(url).match(/\/([A-Za-z0-9_\-]+)\/(?:import|native|js|ohm|chunks)\//i);
if (m && m[1]) return m[1]; if (m && m[1]) return m[1];
if (bundleObjs && bundleObjs.length) { var objs = (bi && bi.bundleObjs) || [];
for (var i = 0; i < bundleObjs.length; i++) { for (var i = 0; i < objs.length; i++) {
var b = bundleObjs[i]; var b = objs[i];
if (!b) continue; if (!b) continue;
var bname = b.__pwName || b.name || ''; var bname = b.__pwName || b.name || '';
try { try {
if (typeof b.getAssetInfo === 'function' && uuid) { if (typeof b.getAssetInfo === 'function' && uuid) {
var info = b.getAssetInfo(uuid); var info = b.getAssetInfo(uuid);
if (info && (info.uuid || info.redirect || info.path != null || info.ext)) { if (info && (info.uuid || info.redirect || info.path != null || info.ext)) return bname;
return bname; }
} } catch (e2) { /* */ }
} try {
} catch (e2) { /* */ } if (b.cache && b.cache.has && uuid && b.cache.has(uuid)) return bname;
try { } catch (e3) { /* */ }
if (b.cache && typeof b.cache.has === 'function' && uuid && b.cache.has(uuid)) {
return bname;
}
} catch (e3) { /* */ }
try {
if (b.cache && b.cache.get && uuid && b.cache.get(uuid)) {
return bname;
}
} catch (e4) { /* */ }
}
} }
return ''; return '';
} }
/** 遍历已加载 bundles,收集对象与 cache uuid 索引 */ /**
* 构建索引:uuid→bundle、uuid→path、pack(自动图集)成员。
* 数据来自 bundle._config(paths / packs)与 cache。
*/
function indexBundles(cc) { function indexBundles(cc) {
var list = []; var list = [];
var uuidMap = {}; var uuidMap = {};
var pathMap = {};
var packOf = {}; // uuid -> packId
var packMembers = {}; // packId -> [uuid]
var bundleObjs = []; var bundleObjs = [];
var addU = function (u, bname) {
if (u != null && bname) uuidMap[String(u)] = bname;
};
try { try {
cc.assetManager.bundles.forEach(function (bundle, name) { cc.assetManager.bundles.forEach(function (bundle, name) {
var n = name || (bundle && bundle.name) || ''; var n = name || (bundle && bundle.name) || '';
if (!n) return; if (!n || !bundle) return;
if (bundle) { bundle.__pwName = n;
bundle.__pwName = n; bundleObjs.push(bundle);
bundleObjs.push(bundle);
}
list.push({ list.push({
name: n, name: n,
assetCount: 0, assetCount: 0,
@ -152,46 +189,108 @@
audioMB: 0, audioMB: 0,
otherMB: 0, otherMB: 0,
status: 'loaded', status: 'loaded',
packCount: 0,
}); });
var add = function (u) {
if (u) uuidMap[String(u)] = n; var cfg = bundle._config;
};
// 1) paths: 路径 → [uuid, type, ...] 或 {uuid}
try {
var paths = cfg && (cfg.paths || cfg._paths);
if (paths && typeof paths === 'object') {
for (var p in paths) {
if (!Object.prototype.hasOwnProperty.call(paths, p)) continue;
var val = paths[p];
if (Array.isArray(val)) {
for (var i = 0; i < val.length; i++) {
var u1 = val[i];
if (typeof u1 === 'string' && /^[0-9a-fA-F-]{8,}/.test(u1)) {
addU(u1, n);
if (!pathMap[u1]) pathMap[u1] = p;
} else if (u1 && u1.uuid) {
addU(u1.uuid, n);
if (!pathMap[u1.uuid]) pathMap[u1.uuid] = p;
}
}
} else if (val && val.uuid) {
addU(val.uuid, n);
if (!pathMap[val.uuid]) pathMap[val.uuid] = p;
}
}
}
} catch (e) { /* */ }
// 2) packs: 自动图集 / 合包
try {
var packs = cfg && (cfg.packs || cfg._packs);
if (packs && typeof packs === 'object') {
var packCount = 0;
for (var packId in packs) {
if (!Object.prototype.hasOwnProperty.call(packs, packId)) continue;
var members = packs[packId];
if (!members) continue;
packCount += 1;
packMembers[packId] = packMembers[packId] || [];
var arr = Array.isArray(members) ? members : [members];
for (var j = 0; j < arr.length; j++) {
var um = arr[j];
if (um && typeof um === 'object') um = um.uuid;
if (!um) continue;
addU(um, n);
packOf[String(um)] = packId;
packMembers[packId].push(String(um));
if (!pathMap[String(um)]) pathMap[String(um)] = packId;
}
}
for (var q = 0; q < list.length; q++) {
if (list[q].name === n) list[q].packCount = packCount;
}
}
} catch (e2) { /* */ }
// 3) cache
try { try {
var cache = bundle.cache || bundle._cache; var cache = bundle.cache || bundle._cache;
if (cache && typeof cache.forEach === 'function') { if (cache && typeof cache.forEach === 'function') {
cache.forEach(function (asset, uuid) { cache.forEach(function (asset, uuid) {
add(uuid); addU(uuid, n);
if (asset) add(asset._uuid); if (asset) addU(asset._uuid, n);
}); });
} }
if (cache && cache._map) { if (cache && cache._map) {
for (var k in cache._map) { for (var k in cache._map) {
if (Object.prototype.hasOwnProperty.call(cache._map, k)) add(k); if (Object.prototype.hasOwnProperty.call(cache._map, k)) addU(k, n);
} }
} }
} catch (e) { /* */ } } catch (e3) { /* */ }
// config.uuids / paths // 4) getAssetInfo 扫一遍 config 里的 uuid
try { try {
var cfg = bundle._config; if (typeof bundle.getAssetInfo === 'function') {
if (cfg) { var keys = Object.keys(uuidMap);
var lists = [cfg.uuids, cfg.uuidList, cfg._uuidList]; for (var s = 0; s < keys.length; s++) {
for (var li = 0; li < lists.length; li++) { if (uuidMap[keys[s]] === n) continue;
var arr = lists[li]; try {
if (!arr) continue; var inf = bundle.getAssetInfo(keys[s]);
if (Array.isArray(arr)) { if (inf && (inf.path != null || inf.redirect)) {
for (var i = 0; i < arr.length; i++) add(arr[i]); addU(keys[s], n);
} else if (typeof arr === 'object') { if (!pathMap[keys[s]] && inf.path) pathMap[keys[s]] = inf.path;
for (var kk in arr) {
if (Object.prototype.hasOwnProperty.call(arr, kk)) add(kk);
} }
} } catch (e4) { /* */ }
} }
} }
} catch (e2) { /* */ } } catch (e5) { /* */ }
}); });
} catch (e3) { /* */ } } catch (e6) { /* */ }
return { list: list, uuidMap: uuidMap, bundleObjs: bundleObjs };
return {
list: list,
uuidMap: uuidMap,
pathMap: pathMap,
packOf: packOf,
packMembers: packMembers,
bundleObjs: bundleObjs,
};
} }
/** /**
@ -220,11 +319,8 @@
var type = fmtType(asset); var type = fmtType(asset);
var mem = assetMem(asset, type, seenTex); var mem = assetMem(asset, type, seenTex);
var bname = resolveBundleName(id, asset, bi.bundleObjs, bi.uuidMap); var bname = resolveBundleName(id, asset, bi);
if (!bname) { if (!bname) bname = 'internal';
var isDefault = /default_|splash|empty|builtin/i.test(String(asset.name || ''));
bname = isDefault ? 'internal' : 'internal';
}
var agg = bundleByName[bname]; var agg = bundleByName[bname];
if (!agg) { if (!agg) {
agg = { agg = {
@ -235,6 +331,7 @@
audioMB: 0, audioMB: 0,
otherMB: 0, otherMB: 0,
status: 'loaded', status: 'loaded',
packCount: 0,
}; };
bundleByName[bname] = agg; bundleByName[bname] = agg;
bi.list.push(agg); bi.list.push(agg);
@ -255,22 +352,38 @@
h = asset.height | 0; h = asset.height | 0;
} }
// 自动图集 / 合包:packId;SpriteFrame 挂到纹理 uuid
var packId = bi.packOf[id] || '';
var texUuid = '';
if (type === 'SpriteFrame') {
var tex = asset.texture || (asset.getTexture && asset.getTexture());
texUuid = String((tex && (tex._uuid || tex.uuid)) || '');
} else if (type === 'Texture2D' || type === 'Texture') {
texUuid = id;
}
var display = asset.name || ''; var display = asset.name || '';
var pathStr = bi.pathMap[id] || '';
if (!display || /^[0-9a-f-]{8,}$/i.test(display)) { if (!display || /^[0-9a-f-]{8,}$/i.test(display)) {
// 可读名:优先 getAssetInfo.path 最后一段 if (pathStr) {
try { var segs = String(pathStr).split('/');
for (var bi2 = 0; bi2 < bi.bundleObjs.length; bi2++) { display = segs[segs.length - 1] || pathStr;
var bb = bi2.bundleObjs[bi2]; }
if (bb && typeof bb.getAssetInfo === 'function') { if (!display) {
var inf = bb.getAssetInfo(id); try {
if (inf && inf.path) { for (var bi2 = 0; bi2 < bi.bundleObjs.length; bi2++) {
var segs = String(inf.path).split('/'); var bb = bi.bundleObjs[bi2];
display = segs[segs.length - 1] || inf.path; if (bb && typeof bb.getAssetInfo === 'function') {
break; var inf = bb.getAssetInfo(id);
if (inf && inf.path) {
var ps = String(inf.path).split('/');
display = ps[ps.length - 1] || inf.path;
break;
}
} }
} }
} } catch (eName) { /* */ }
} catch (eName) { /* */ } }
if (!display) display = id.slice(0, 8) + '…'; if (!display) display = id.slice(0, 8) + '…';
} }
@ -284,6 +397,9 @@
w: w, w: w,
h: h, h: h,
kind: kind, kind: kind,
pack: packId,
texUuid: texUuid,
path: pathStr,
}); });
agg.assetCount += 1; agg.assetCount += 1;
@ -322,7 +438,14 @@
} }
totals.assetCount = rows.length; totals.assetCount = rows.length;
totals.bundleCount = bundles.length; totals.bundleCount = bundles.length;
return { bundles: bundles, rows: rows, totals: totals }; totals.packCount = Object.keys(bi.packMembers || {}).length;
return {
bundles: bundles,
rows: rows,
totals: totals,
packs: bi.packMembers || {},
packOf: bi.packOf || {},
};
} }
function buildPreview(asset, type) { function buildPreview(asset, type) {

@ -200,9 +200,12 @@
} else if (r.type === 'ImageAsset') { } else if (r.type === 'ImageAsset') {
memText = (r.w && r.h) ? (r.w + '×' + r.h) : '源像素'; memText = (r.w && r.h) ? (r.w + '×' + r.h) : '源像素';
} }
var tag = '';
if (r.pack) tag += ' <span class="pw-assets-tag">图集</span>';
if (r.type === 'Texture2D' && r.pack) tag += ' <span class="pw-assets-tag">合包</span>';
out.push( out.push(
'<div class="pw-assets-row' + sel + '" data-uuid="' + escapeAttr(r.uuid) + '" title="' + escapeAttr(r.type + ' · ' + r.bundle) + '">' + '<div class="pw-assets-row' + sel + '" data-uuid="' + escapeAttr(r.uuid) + '" title="' + escapeAttr((r.path || r.type) + ' · ' + r.bundle) + '">' +
'<span class="pw-assets-name">' + escapeHtml(r.name) + '</span>' + '<span class="pw-assets-name">' + escapeHtml(r.name) + tag + '</span>' +
'<span class="pw-assets-type">' + escapeHtml(r.type) + '</span>' + '<span class="pw-assets-type">' + escapeHtml(r.type) + '</span>' +
'<span class="pw-assets-mem">' + escapeHtml(memText) + '</span>' + '<span class="pw-assets-mem">' + escapeHtml(memText) + '</span>' +
'</div>' '</div>'

Loading…
Cancel
Save