diff --git a/nexus/components/spatial-memory.js b/nexus/components/spatial-memory.js index 87e3e770..ab7a5fd5 100644 --- a/nexus/components/spatial-memory.js +++ b/nexus/components/spatial-memory.js @@ -734,13 +734,86 @@ const SpatialMemory = (() => { }); } + + // ─── SPATIAL SEARCH (issue #1170) ──────────────────── + let _searchOriginalState = {}; // memId -> { emissiveIntensity, opacity } for restore + + function searchContent(query) { + if (!query || !query.trim()) return []; + const q = query.toLowerCase().trim(); + const matches = []; + + Object.values(_memoryObjects).forEach(obj => { + const d = obj.data; + const searchable = [ + d.content || '', + d.id || '', + d.category || '', + d.source || '', + ...(d.connections || []) + ].join(' ').toLowerCase(); + + if (searchable.includes(q)) { + matches.push(d.id); + } + }); + + return matches; + } + + function highlightSearchResults(matchIds) { + // Save original state and apply search highlighting + _searchOriginalState = {}; + const matchSet = new Set(matchIds); + + Object.entries(_memoryObjects).forEach(([id, obj]) => { + const mat = obj.mesh.material; + _searchOriginalState[id] = { + emissiveIntensity: mat.emissiveIntensity, + opacity: mat.opacity + }; + + if (matchSet.has(id)) { + // Match: bright white glow + mat.emissive.setHex(0xffffff); + mat.emissiveIntensity = 5.0; + mat.opacity = 1.0; + } else { + // Non-match: dim to 10% opacity + mat.opacity = 0.1; + mat.emissiveIntensity = 0.2; + } + }); + } + + function clearSearch() { + Object.entries(_memoryObjects).forEach(([id, obj]) => { + const mat = obj.mesh.material; + const saved = _searchOriginalState[id]; + if (saved) { + // Restore original emissive color from region + const region = REGIONS[obj.region] || REGIONS.working; + mat.emissive.copy(region.color); + mat.emissiveIntensity = saved.emissiveIntensity; + mat.opacity = saved.opacity; + } + }); + _searchOriginalState = {}; + } + + function getSearchMatchPosition(matchId) { + const obj = _memoryObjects[matchId]; + return obj ? obj.mesh.position.clone() : null; + } + return { init, placeMemory, removeMemory, update, getMemoryAtPosition, getRegionAtPosition, getMemoriesInRegion, getAllMemories, getCrystalMeshes, getMemoryFromMesh, highlightMemory, clearHighlight, getSelectedId, exportIndex, importIndex, exportToFile, importFromFile, searchNearby, REGIONS, saveToStorage, loadFromStorage, clearStorage, - runGravityLayout + runGravityLayout, + searchContent, highlightSearchResults, clearSearch, getSearchMatchPosition }; })();