diff --git a/src/editor/engine/GameRuntime.js b/src/editor/engine/GameRuntime.js index 0c9c3a7..7a53415 100644 --- a/src/editor/engine/GameRuntime.js +++ b/src/editor/engine/GameRuntime.js @@ -185,7 +185,12 @@ export class GameRuntime { sb.setOnCommand(({ cmd, payload }) => { if (cmd === 'partSet' || cmd === 'partVel' || cmd === 'sceneCreate' || cmd === 'sceneDelete') { - try { handleLuaCommand(null, cmd, payload, this); } catch (_) {} + try { + handleLuaCommand(null, cmd, payload, this); + } catch (e) { + // eslint-disable-next-line no-console + console.error('[GameRuntime] handleLuaCommand failed:', cmd, payload, e); + } } else { this._handleCommand(null, cmd, payload); } diff --git a/src/editor/engine/PrimitiveManager.js b/src/editor/engine/PrimitiveManager.js index 8a50c0c..9e6a556 100644 --- a/src/editor/engine/PrimitiveManager.js +++ b/src/editor/engine/PrimitiveManager.js @@ -689,7 +689,16 @@ export class PrimitiveManager { const data = this.instances.get(id); if (!data) return; - // Позиция + // Позиция / поворот / размер — нужно расфризить world matrix, + // иначе freezeStaticPrimitives() сделает mesh.position.set бессмысленным. + const positionChanged = patch.x !== undefined || patch.y !== undefined || patch.z !== undefined; + const transformChanged = positionChanged + || patch.rotationX !== undefined || patch.rotationY !== undefined || patch.rotationZ !== undefined + || patch.sx !== undefined || patch.sy !== undefined || patch.sz !== undefined; + if (transformChanged && data._worldMatrixFrozen) { + try { data.mesh.unfreezeWorldMatrix?.(); } catch (_) {} + data._worldMatrixFrozen = false; + } if (patch.x !== undefined) data.x = patch.x; if (patch.y !== undefined) data.y = patch.y; if (patch.z !== undefined) data.z = patch.z; diff --git a/src/editor/engine/lua/RobloxShim.js b/src/editor/engine/lua/RobloxShim.js index 097402a..6f4d276 100644 --- a/src/editor/engine/lua/RobloxShim.js +++ b/src/editor/engine/lua/RobloxShim.js @@ -279,7 +279,6 @@ function newPart(primData, sendFn) { }; // Setter'ы шлют partSet → BabylonScene.primitiveManager через handleLuaCommand. - // Формат payload должен соответствовать rbxl-lua-integration.js#handleLuaCommand. const send = (prop, value) => { try { sendFn('partSet', { primId: p.__primId, prop, value }); } catch (_) {} }; diff --git a/src/editor/engine/rbxl-lua-integration.js b/src/editor/engine/rbxl-lua-integration.js index 4d8c24d..057941d 100644 --- a/src/editor/engine/rbxl-lua-integration.js +++ b/src/editor/engine/rbxl-lua-integration.js @@ -122,29 +122,34 @@ export function handleLuaCommand(_scriptId, cmd, payload, runtime) { return; } if (cmd === 'partSet') { + const pm = runtime.scene3d?.primitiveManager; + if (!pm) { + console.warn('[partSet] no primitiveManager. scene3d=', !!runtime.scene3d); + return; + } + const primId = payload?.primId; + const prop = payload?.prop; + const value = payload?.value; + const patch = {}; + if (prop === 'position' && value) { + patch.x = value.x; patch.y = value.y; patch.z = value.z; + } else if (prop === 'cframe' && value) { + patch.x = value.x; patch.y = value.y; patch.z = value.z; + patch.rotationX = value.rx; patch.rotationY = value.ry; patch.rotationZ = value.rz; + } else if (prop === 'size' && value) { + patch.sx = value.sx; patch.sy = value.sy; patch.sz = value.sz; + } else if (prop === 'color') patch.color = value; + else if (prop === 'material') patch.material = value; + else if (prop === 'anchored') patch.anchored = value; + else if (prop === 'canCollide') patch.canCollide = value; + else if (prop === 'opacity') patch.opacity = value; try { - const pm = runtime.scene3d?.primitiveManager; - if (!pm) return; - const primId = payload?.primId; - const prop = payload?.prop; - const value = payload?.value; - const patch = {}; - if (prop === 'position' && value) { - patch.x = value.x; patch.y = value.y; patch.z = value.z; - } else if (prop === 'cframe' && value) { - patch.x = value.x; patch.y = value.y; patch.z = value.z; - patch.rotationX = value.rx; patch.rotationY = value.ry; patch.rotationZ = value.rz; - } else if (prop === 'size' && value) { - patch.sx = value.sx; patch.sy = value.sy; patch.sz = value.sz; - } else if (prop === 'color') patch.color = value; - else if (prop === 'material') patch.material = value; - else if (prop === 'anchored') patch.anchored = value; - else if (prop === 'canCollide') patch.canCollide = value; - else if (prop === 'opacity') patch.opacity = value; if (typeof pm.updateInstance === 'function') pm.updateInstance(primId, patch); else if (typeof pm.applyPatch === 'function') pm.applyPatch(primId, patch); else if (typeof pm.update === 'function') pm.update(primId, patch); - } catch (e) {} + } catch (e) { + console.error('[partSet] updateInstance failed:', e); + } return; } if (cmd === 'sceneCreate') {