(function (global) { 'use strict'; /** * 属性面板(壳侧):通过 Bridge 读写节点属性;标签优先使用 displayName。 * @constructor */ function InspectorPanel() { this.el = null; this.body = null; this._bridge = null; this._uuid = ''; this._props = null; } InspectorPanel.prototype.setBridge = function (bridge) { this._bridge = bridge; }; InspectorPanel.prototype.mount = function () { var root = document.createElement('div'); root.className = 'pw-panel-inner pw-inspector'; root.style.height = '100%'; root.style.display = 'flex'; root.style.flexDirection = 'column'; root.innerHTML = '
' + '
未选中节点
'; this.el = root; this.body = root.querySelector('#pw-inspector-body'); return root; }; InspectorPanel.prototype.loadUuid = function (uuid) { var self = this; this._uuid = uuid || ''; if (!this._uuid || !this._bridge) { this._props = null; if (this.body) this.body.innerHTML = '
未选中节点
'; return; } this._bridge.call('node.get', { uuid: this._uuid }).then(function (props) { self._props = props; self.render(); }).catch(function () { if (self.body) self.body.innerHTML = '
读取失败
'; }); }; InspectorPanel.prototype.render = function () { var body = this.body; var p = this._props; if (!body) return; if (!p) { body.innerHTML = '
未选中节点
'; return; } var html = []; html.push('
'); html.push('
节点
'); html.push('
'); html.push(rowText('名称', 'name', p.name)); html.push(rowCheck('激活', 'active', !!p.active)); html.push(rowNum('Layer', 'layer', p.layer)); html.push(rowVec3('位置', ['px', 'py', 'pz'], [p.pos.x, p.pos.y, p.pos.z])); html.push(rowVec3('旋转', ['rx', 'ry', 'rz'], [p.euler.x, p.euler.y, p.euler.z])); html.push(rowVec3('缩放', ['sx', 'sy', 'sz'], [p.scale.x, p.scale.y, p.scale.z])); html.push('
'); var comps = p.comps || []; for (var i = 0; i < comps.length; i++) { var c = comps[i]; html.push('
'); html.push('
' + escapeHtml(c.name) + '
'); html.push('
'); var fields = c.fields || []; if (!fields.length) html.push('
无可编辑公开字段
'); for (var f = 0; f < fields.length; f++) { html.push(renderField(c.index, fields[f])); } html.push('
'); } body.innerHTML = html.join(''); this._bindFields(); this._bindSections(); }; /** * @param {number} compIndex * @param {object} field * @returns {string} */ function renderField(compIndex, field) { var label = field.label || field.key; var fid = 'c' + compIndex + '_' + field.key; var type = field.type; if (field.readOnly || type === 'ref') { return rowRef(label, field.value); } if (type === 'boolean') return rowCheck(label, fid, !!field.value); if (type === 'number') return rowNum(label, fid, field.value); if (type === 'string') return rowText(label, fid, field.value); if (type === 'enum') return rowEnum(label, fid, field.value, field.enumOptions || []); if (type === 'vec2') { return rowVec2(label, [fid + '_x', fid + '_y'], [field.value.x, field.value.y], ['X', 'Y']); } if (type === 'vec3') { return rowVec3(label, [fid + '_x', fid + '_y', fid + '_z'], [field.value.x, field.value.y, field.value.z]); } if (type === 'size') { return rowVec2(label, [fid + '_w', fid + '_h'], [field.value.width, field.value.height], ['W', 'H']); } if (type === 'color') return rowColor(label, fid, field.value); return rowText(label, fid, field.value == null ? '' : String(field.value)); } InspectorPanel.prototype._bindSections = function () { var heads = this.body.querySelectorAll('.pw-insp-sec-head[data-toggle]'); for (var i = 0; i < heads.length; i++) { heads[i].addEventListener('click', function (ev) { var sec = ev.currentTarget.parentNode; if (sec) sec.classList.toggle('open'); }); } }; InspectorPanel.prototype._bindFields = function () { var self = this; var body = this.body; if (!body || !this._bridge || !this._uuid) return; var inputs = body.querySelectorAll('[data-fid]'); for (var i = 0; i < inputs.length; i++) { (function (el) { var run = function () { var fid = el.getAttribute('data-fid'); var value; if (el.tagName === 'SELECT') value = parseEnumValue(el); else if (el.type === 'checkbox') value = !!el.checked; else if (el.type === 'color') value = el.value; else if (el.type === 'number') value = parseFloat(el.value); else value = el.value; self._bridge.call('node.set', { uuid: self._uuid, fid: fid, value: value }); if (el.getAttribute('data-color-pair')) { var siblings = el.parentNode ? el.parentNode.querySelectorAll('[data-fid="' + fid + '"]') : []; for (var si = 0; si < siblings.length; si++) { if (siblings[si] === el) continue; var nv = String(value); if (nv.charAt(0) !== '#' && siblings[si].type === 'color') nv = '#' + nv; if (siblings[si].type === 'color') siblings[si].value = nv.slice(0, 7); else siblings[si].value = nv; } } }; el.addEventListener('change', run); if (el.type !== 'checkbox' && el.tagName !== 'SELECT') el.addEventListener('input', run); })(inputs[i]); } }; function parseEnumValue(el) { var opt = el.options[el.selectedIndex]; if (!opt) return el.value; var raw = opt.getAttribute('data-num'); if (raw != null && raw !== '') return Number(raw); return el.value; } function labelHtml(label) { var text = label == null ? '' : String(label); return ''; } function rowText(label, id, value) { return '
' + labelHtml(label) + '
'; } function rowNum(label, id, value) { return '
' + labelHtml(label) + '
'; } function rowCheck(label, id, value) { return '
' + labelHtml(label) + '
'; } function rowEnum(label, id, value, options) { var opts = []; for (var i = 0; i < options.length; i++) { var o = options[i]; var selected = o.value === value || String(o.value) === String(value); opts.push(''); } return '
' + labelHtml(label) + '
'; } function rowRef(label, value) { var v = value || {}; var text = (v.kind ? v.kind + ' · ' : '') + (v.name || '(空)'); return '
' + labelHtml(label) + '
' + '' + escapeHtml(v.kind || 'Object') + '' + '' + escapeHtml(v.name || '(空)') + '
'; } function rowColor(label, id, value) { var r = (value && value.r) || 0; var g = (value && value.g) || 0; var b = (value && value.b) || 0; var hex = '#' + toHex2(r) + toHex2(g) + toHex2(b); return '
' + labelHtml(label) + '
' + '' + '' + '
'; } function rowVec3(label, ids, values) { return '
' + labelHtml(label) + '
' + axis('X', ids[0], values[0]) + axis('Y', ids[1], values[1]) + axis('Z', ids[2], values[2]) + '
'; } function rowVec2(label, ids, values, axisNames) { return '
' + labelHtml(label) + '
' + axis(axisNames[0], ids[0], values[0]) + axis(axisNames[1], ids[1], values[1]) + '
'; } function axis(name, id, value) { return '
' + name + '
'; } function toHex2(n) { var s = Math.max(0, Math.min(255, n | 0)).toString(16); return s.length < 2 ? '0' + s : s; } function escapeHtml(s) { return String(s).replace(/&/g, '&').replace(//g, '>'); } function escapeAttr(s) { return escapeHtml(s).replace(/"/g, '"'); } global.PWInspectorPanel = InspectorPanel; })(window);