Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions apps/web/app/components/ContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ interface NodeMenuItem {
label: string;
description: string;
category: string;
categoryIcon: string;
color: string;
icon?: string | React.ComponentType<any>;
}
Expand Down Expand Up @@ -98,6 +99,7 @@ export default function ContextMenu({ position, onClose, onAddNode, onOpenCustom
label: definition.name,
description: definition.description,
category: categoryMeta?.description || definition.category,
categoryIcon: categoryMeta?.icon || '⚫',
color: `bg-${categoryMeta?.color || 'gray'}-600`,
icon: definition.ui?.icon || categoryMeta?.icon
};
Expand Down Expand Up @@ -162,11 +164,14 @@ export default function ContextMenu({ position, onClose, onAddNode, onOpenCustom
// Group filtered items by category
const categories = filteredItems.reduce((acc, item) => {
if (!acc[item.category]) {
acc[item.category] = [];
acc[item.category] = {
items: [],
icon: item.categoryIcon
};
}
acc[item.category].push(item);
acc[item.category].items.push(item);
return acc;
}, {} as Record<string, NodeMenuItem[]>);
}, {} as Record<string, { items: NodeMenuItem[]; icon: string }>);

// Don't render anything if position is null
if (!position) {
Expand Down Expand Up @@ -255,12 +260,13 @@ export default function ContextMenu({ position, onClose, onAddNode, onOpenCustom
scrollbarColor: 'rgba(75, 85, 99, 0.6) transparent'
}}
>
{Object.entries(categories).map(([category, items]) => (
{Object.entries(categories).map(([category, categoryData]) => (
<div key={category}>
<div className="px-4 py-2 text-xs font-medium text-gray-200 bg-gray-800/90 backdrop-blur-sm sticky top-0 z-10 border-b border-gray-600/30">
{category}
<div className="px-4 py-2 text-xs font-medium text-gray-200 bg-gray-800/90 backdrop-blur-sm sticky top-0 z-10 border-b border-gray-600/30 flex items-center gap-2">
<span className="text-sm">{categoryData.icon}</span>
<span>{category}</span>
</div>
{items.map((item, index) => (
{categoryData.items.map((item, index) => (
<button
key={`${item.type}-${index}`}
onClick={() => handleAddNode(item)}
Expand Down
4 changes: 2 additions & 2 deletions apps/web/app/components/GenericNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -418,10 +418,10 @@ export default function GenericNode({

{/* Parameters (Third row and beyond) */}
{(mainParameters.length > 0 || advancedParameters.length > 0) && (
<div className="px-3 py-2 space-y-2">
<div className="px-3 py-2 space-y-1">
{/* Group parameters by category */}
{Object.entries(groupedParameters).map(([category, params]) => (
<div key={category} className="space-y-1">
<div key={category} className="space-y-0.5">
{/* Category header for non-main categories */}
{category !== 'main' && (
<div className="text-xs font-medium text-gray-400 border-b border-gray-600/30 pb-1">
Expand Down
4 changes: 2 additions & 2 deletions apps/web/app/components/ParameterRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export default function ParameterRenderer({
<select
value={value || definition.defaultValue}
onChange={(e) => onChange(e.target.value)}
className="w-full px-2 py-1 text-xs bg-gray-700 border border-gray-600 rounded text-white focus:border-orange-400 focus:outline-none"
className="w-full px-2 py-0.5 text-xs bg-gray-700 border border-gray-600 rounded text-white focus:border-orange-400 focus:outline-none"
>
{definition.options?.map(option => (
<option key={option} value={option}>{option}</option>
Expand Down Expand Up @@ -159,7 +159,7 @@ export default function ParameterRenderer({
};

return (
<div className="flex items-center justify-between relative">
<div className="flex items-center justify-between relative py-0.5">
{/* Input Handle for parameters that can be connected */}
{(definition.type === 'number' || definition.type === 'integer' || definition.type === 'vector') && (
<Handle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const DropdownWidget: React.FC<DropdownWidgetProps> = ({
<select
value={currentValue}
onChange={handleChange}
className="w-full px-2 py-1 text-xs bg-gray-700 border border-gray-600 rounded text-white focus:border-blue-400 focus:outline-none min-w-0"
className="w-full px-2 py-0.5 text-xs bg-gray-700 border border-gray-600 rounded text-white focus:border-blue-400 focus:outline-none min-w-0"
style={{ minWidth: '80px' }}
>
{options.length === 0 ? (
Expand Down
76 changes: 75 additions & 1 deletion apps/web/app/registry/NodeRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,39 @@ import {
timeNodeDefinition,
cubeNodeDefinition,
mathNodeDefinition,
mapRangeNodeDefinition,
clampNodeDefinition,
randomValueNodeDefinition,
smoothStepNodeDefinition,
switchNodeDefinition,
compareNodeDefinition,
ifElseNodeDefinition,
sineWaveNodeDefinition,
cosineWaveNodeDefinition,
noiseWaveNodeDefinition,
timeOffsetNodeDefinition,
bendNodeDefinition,
twistNodeDefinition,
taperNodeDefinition,
mirrorNodeDefinition,
arrayNodeDefinition,
scatterNodeDefinition,
instanceNodeDefinition,
meshToPointsNodeDefinition,
pointsToMeshNodeDefinition,
sampleGeometryNodeDefinition,
transformNodeDefinition,
outputNodeDefinition,
sphereNodeDefinition,
planeNodeDefinition,
torusNodeDefinition,
coneNodeDefinition,
gridNodeDefinition,
floatNodeDefinition,
integerNodeDefinition,
booleanNodeDefinition,
cylinderNodeDefinition,
capsuleNodeDefinition,
vectorMathNodeDefinition,
joinNodeDefinition,
subdivideMeshNodeDefinition,
Expand Down Expand Up @@ -39,7 +68,14 @@ import {
setMaterialNodeDefinition,
materialMixerNodeDefinition,
waterMaterialNodeDefinition,
hologramMaterialNodeDefinition
hologramMaterialNodeDefinition,
getAttributeFloatNodeDefinition,
getAttributeVectorNodeDefinition,
getAttributeColorNodeDefinition,
setAttributeFloatNodeDefinition,
setAttributeVectorNodeDefinition,
setAttributeColorNodeDefinition,
attributeCaptureNodeDefinition
} from './nodes';

export class NodeRegistry {
Expand Down Expand Up @@ -103,10 +139,39 @@ export class NodeRegistry {
// Register all default nodes
private registerDefaultNodes() {
this.register(timeNodeDefinition);
this.register(floatNodeDefinition);
this.register(integerNodeDefinition);
this.register(booleanNodeDefinition);
this.register(cubeNodeDefinition);
this.register(sphereNodeDefinition);
this.register(planeNodeDefinition);
this.register(torusNodeDefinition);
this.register(coneNodeDefinition);
this.register(gridNodeDefinition);
this.register(cylinderNodeDefinition);
this.register(capsuleNodeDefinition);
this.register(mathNodeDefinition);
this.register(mapRangeNodeDefinition);
this.register(clampNodeDefinition);
this.register(randomValueNodeDefinition);
this.register(smoothStepNodeDefinition);
this.register(switchNodeDefinition);
this.register(compareNodeDefinition);
this.register(ifElseNodeDefinition);
this.register(sineWaveNodeDefinition);
this.register(cosineWaveNodeDefinition);
this.register(noiseWaveNodeDefinition);
this.register(timeOffsetNodeDefinition);
this.register(bendNodeDefinition);
this.register(twistNodeDefinition);
this.register(taperNodeDefinition);
this.register(mirrorNodeDefinition);
this.register(arrayNodeDefinition);
this.register(scatterNodeDefinition);
this.register(instanceNodeDefinition);
this.register(meshToPointsNodeDefinition);
this.register(pointsToMeshNodeDefinition);
this.register(sampleGeometryNodeDefinition);
this.register(vectorMathNodeDefinition);
this.register(transformNodeDefinition);
this.register(joinNodeDefinition);
Expand Down Expand Up @@ -146,6 +211,15 @@ export class NodeRegistry {
this.register(hologramMaterialNodeDefinition);
// Note: lava-material is now provided by server nodes only

// Register Attribute System nodes
this.register(getAttributeFloatNodeDefinition);
this.register(getAttributeVectorNodeDefinition);
this.register(getAttributeColorNodeDefinition);
this.register(setAttributeFloatNodeDefinition);
this.register(setAttributeVectorNodeDefinition);
this.register(setAttributeColorNodeDefinition);
this.register(attributeCaptureNodeDefinition);

// Register template-generated nodes
const templateNodes = templateSystem.generateAllNodes();
templateNodes.forEach(node => this.register(node));
Expand Down
Loading