diff --git a/src/editor/KubikonEditor.jsx b/src/editor/KubikonEditor.jsx index 62980b7..f090f6f 100644 --- a/src/editor/KubikonEditor.jsx +++ b/src/editor/KubikonEditor.jsx @@ -786,8 +786,9 @@ const KubikonEditor = () => { if (cam && fwd) { px = cam.position.x + fwd.x * 6; pz = cam.position.z + fwd.z * 6; } } catch (e) { /* ignore */ } - // 1) Создаём примитивы кита. Запоминаем id первого — для on-target скрипта. + // 1) Создаём примитивы кита. Запоминаем все id (первый — для on-target скрипта). let firstPrimId = null; + const createdIds = []; if (Array.isArray(kit.prims)) { for (const p of kit.prims) { const newId = s.primitiveManager?.addInstance(p.type || 'cube', { @@ -797,7 +798,19 @@ const KubikonEditor = () => { canCollide: p.canCollide !== false, visible: true, anchored: true, name: p.name, }); - if (firstPrimId == null && newId != null) firstPrimId = newId; + if (newId != null) { + createdIds.push(newId); + if (firstPrimId == null) firstPrimId = newId; + } + } + } + // Если кит состоит из НЕСКОЛЬКИХ частей — кладём их в общую папку + // (объекты из нескольких частей всегда сгруппированы). + let kitFolderId = null; + if (createdIds.length > 1 && s.folderManager) { + kitFolderId = s.folderManager.createFolder(kit.name); + for (const pid of createdIds) { + s.folderManager.assignToFolder('primitive', pid, kitFolderId); } } @@ -817,14 +830,18 @@ const KubikonEditor = () => { markDirty(); setScriptsList(s.getScripts?.() || []); - // Выделим созданный объект и наведём на него камеру (видно, куда добавилось). - if (firstPrimId != null) { - try { - setActiveTool('select'); + if (s.folderManager) setFoldersList(s.folderManager.getAll()); + // Выделим созданное и наведём камеру (видно, куда добавилось). + try { + setActiveTool('select'); + if (kitFolderId != null) { + s.selection?.selectFolder?.(kitFolderId); // группа из нескольких частей + setGizmoMode('move'); + } else if (firstPrimId != null) { s.selection?.selectPrimitiveById(firstPrimId); - s.focusOnSelection?.(); - } catch (e) {} - } + } + s.focusOnSelection?.(); + } catch (e) {} // Тост-уведомление. try { showToast?.(`Механика «${kit.name}» добавлена`); } catch (e) {} }, []); diff --git a/src/editor/engine/GameplayKits.js b/src/editor/engine/GameplayKits.js index 096aec4..387f471 100644 --- a/src/editor/engine/GameplayKits.js +++ b/src/editor/engine/GameplayKits.js @@ -75,9 +75,16 @@ game.onMessage('coins', (m) => { coins += (m && m.add) ? m.add : 1; show(); });` { id: 'start-pad', name: 'Стартовая площадка', - desc: 'Светящаяся платформа-постамент для оформления зоны старта (точка спавна в проекте уже есть по умолчанию).', + desc: 'Светящаяся платформа — игрок появляется НА ней в начале игры (задаёт точку старта).', icon: 'flag', category: 'world', prims: [{ type: 'cylinder', x: 0, y: 0.15, z: 0, sx: 3, sy: 0.3, sz: 3, color: '#36d57a', material: 'neon', name: 'Стартовая площадка' }], + scripts: [{ attachTo: 'on-target', code: +`// Игрок появляется на этой площадке в начале игры. +// Небольшая задержка — чтобы позиция объекта и игрок успели проинициализироваться. +game.after(0.1, () => { + const p = game.self.position; + game.player.teleport(p.x, p.y + 1.5, p.z); +});` }], }, { id: 'checkpoint',