Skip to content

Commit c9fbb7d

Browse files
committed
feat: add support of water material
1 parent 8997992 commit c9fbb7d

File tree

6 files changed

+162
-12
lines changed

6 files changed

+162
-12
lines changed

editor/src/editor/dialogs/command-palette/material.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Editor } from "../../main";
22

3-
import { addPBRMaterial, addStandardMaterial, addNodeMaterial, addSkyMaterial, addGridMaterial, addNormalMaterial } from "../../../project/add/material";
3+
import { addPBRMaterial, addStandardMaterial, addNodeMaterial, addSkyMaterial, addGridMaterial, addNormalMaterial, addWaterMaterial } from "../../../project/add/material";
44

55
import { ICommandPaletteType } from "./command-palette";
66

@@ -42,5 +42,11 @@ export function getMaterialCommands(editor?: Editor): ICommandPaletteType[] {
4242
key: "add-normal-material",
4343
action: () => editor && addNormalMaterial(editor.layout.preview.scene),
4444
},
45+
{
46+
text: "Water Material",
47+
label: "Add a new water material to the scene",
48+
key: "add-water-material",
49+
action: () => editor && addWaterMaterial(editor.layout.preview.scene),
50+
},
4551
];
4652
}

editor/src/editor/layout/inspector/light/shadows.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,9 @@ export class EditorLightShadowsInspector extends Component<IEditorLightShadowsIn
221221
]}
222222
/>
223223
)}
224+
225+
<EditorInspectorSwitchField object={generator} property="transparencyShadow" label="Enable Transparency Shadow" />
226+
<EditorInspectorSwitchField object={generator} property="enableSoftTransparentShadow" label="Enable Soft Transparent Shadow" />
224227
</>
225228
);
226229
}
@@ -282,9 +285,6 @@ export class EditorLightShadowsInspector extends Component<IEditorLightShadowsIn
282285
onChange={() => updateLightShadowMapRefreshRate(this.props.light)}
283286
/>
284287
)}
285-
286-
<EditorInspectorSwitchField object={generator} property="transparencyShadow" label="Enable Transparency Shadow" />
287-
<EditorInspectorSwitchField object={generator} property="enableSoftTransparentShadow" label="Enable Soft Transparent Shadow" />
288288
</EditorInspectorSectionField>
289289
);
290290
}
@@ -350,9 +350,6 @@ export class EditorLightShadowsInspector extends Component<IEditorLightShadowsIn
350350
label="Penumbra Darkness"
351351
onChange={() => updateLightShadowMapRefreshRate(this.props.light)}
352352
/>
353-
354-
<EditorInspectorSwitchField object={generator} property="transparencyShadow" label="Enable Transparency Shadow" />
355-
<EditorInspectorSwitchField object={generator} property="enableSoftTransparentShadow" label="Enable Soft Transparent Shadow" />
356353
</>
357354
);
358355
}

editor/src/editor/layout/inspector/material/multi.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { extname } from "path/posix";
22

33
import { Component, DragEvent, ReactNode } from "react";
44

5-
import { SkyMaterial, GridMaterial, NormalMaterial } from "babylonjs-materials";
65
import { Material, MultiMaterial, PBRMaterial, StandardMaterial } from "babylonjs";
6+
import { SkyMaterial, GridMaterial, NormalMaterial, WaterMaterial } from "babylonjs-materials";
77

88
import { Table, TableBody, TableCaption, TableCell, TableRow } from "../../../../ui/shadcn/ui/table";
99

@@ -14,9 +14,10 @@ import { registerUndoRedo } from "../../../../tools/undoredo";
1414
import { EditorInspectorSectionField } from "../fields/section";
1515

1616
import { EditorSkyMaterialInspector } from "./sky";
17+
import { EditorPBRMaterialInspector } from "./pbr";
1718
import { EditorGridMaterialInspector } from "./grid";
19+
import { EditorWaterMaterialInspector } from "./water";
1820
import { EditorNormalMaterialInspector } from "./normal";
19-
import { EditorPBRMaterialInspector } from "./pbr";
2021
import { EditorStandardMaterialInspector } from "./standard";
2122

2223
export interface IEditorPBRMaterialInspectorProps {
@@ -116,14 +117,21 @@ export class EditorMultiMaterialInspector extends Component<IEditorPBRMaterialIn
116117
switch (this.state.material.getClassName()) {
117118
case "PBRMaterial":
118119
return <EditorPBRMaterialInspector key={this.state.material.id} material={this.state.material as PBRMaterial} />;
120+
119121
case "StandardMaterial":
120122
return <EditorStandardMaterialInspector key={this.state.material.id} material={this.state.material as StandardMaterial} />;
123+
121124
case "SkyMaterial":
122125
return <EditorSkyMaterialInspector key={this.state.material.id} material={this.state.material as SkyMaterial} />;
126+
123127
case "GridMaterial":
124128
return <EditorGridMaterialInspector key={this.state.material.id} material={this.state.material as GridMaterial} />;
129+
125130
case "NormalMaterial":
126131
return <EditorNormalMaterialInspector key={this.state.material.id} material={this.state.material as NormalMaterial} />;
132+
133+
case "WaterMaterial":
134+
return <EditorWaterMaterialInspector key={this.state.material.id} material={this.state.material as WaterMaterial} />;
127135
}
128136
}
129137
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import { Component, ReactNode } from "react";
2+
3+
import { AbstractMesh } from "babylonjs";
4+
import { WaterMaterial } from "babylonjs-materials";
5+
6+
import { EditorInspectorColorField } from "../fields/color";
7+
import { EditorInspectorStringField } from "../fields/string";
8+
import { EditorInspectorSwitchField } from "../fields/switch";
9+
import { EditorInspectorNumberField } from "../fields/number";
10+
import { EditorInspectorSectionField } from "../fields/section";
11+
import { EditorInspectorTextureField } from "../fields/texture";
12+
13+
import { EditorMaterialInspectorUtilsComponent } from "./components/utils";
14+
import { Switch } from "../../../../ui/shadcn/ui/switch";
15+
import { EditorInspectorVectorField } from "../fields/vector";
16+
17+
export interface IEditorWaterMaterialInspectorProps {
18+
mesh?: AbstractMesh;
19+
material: WaterMaterial;
20+
}
21+
22+
export interface IEditorWaterMaterialInspectorState {
23+
renderListSearch: string;
24+
}
25+
26+
export class EditorWaterMaterialInspector extends Component<IEditorWaterMaterialInspectorProps, IEditorWaterMaterialInspectorState> {
27+
public constructor(props: IEditorWaterMaterialInspectorProps) {
28+
super(props);
29+
30+
this.state = {
31+
renderListSearch: "",
32+
};
33+
}
34+
35+
public render(): ReactNode {
36+
return (
37+
<>
38+
<EditorInspectorSectionField title="Material" label={this.props.material.getClassName()}>
39+
<EditorInspectorStringField label="Name" object={this.props.material} property="name" />
40+
<EditorInspectorSwitchField label="Back Face Culling" object={this.props.material} property="backFaceCulling" />
41+
42+
<EditorMaterialInspectorUtilsComponent mesh={this.props.mesh} material={this.props.material} />
43+
</EditorInspectorSectionField>
44+
45+
<EditorInspectorSectionField title="Water">
46+
<EditorInspectorTextureField hideLevel object={this.props.material} title="Normal Texture" property="bumpTexture" onChange={() => this.forceUpdate()}>
47+
<EditorInspectorNumberField label="Bump Height" object={this.props.material} property="bumpHeight" />
48+
</EditorInspectorTextureField>
49+
</EditorInspectorSectionField>
50+
51+
{this.props.material.bumpTexture && (
52+
<>
53+
<EditorInspectorSectionField title="Colors">
54+
<EditorInspectorColorField label={<div className="w-14">Color 1</div>} object={this.props.material} property="waterColor" />
55+
<EditorInspectorColorField label={<div className="w-14">Color 2</div>} object={this.props.material} property="waterColor2" />
56+
<EditorInspectorNumberField label="Color Blend Factor" object={this.props.material} property="colorBlendFactor" min={0} max={1} />
57+
<EditorInspectorNumberField label="Color Blend Factor 2" object={this.props.material} property="colorBlendFactor2" min={0} max={1} />
58+
59+
<EditorInspectorColorField label={<div className="w-14">Diffuse</div>} object={this.props.material} property="diffuseColor" />
60+
<EditorInspectorColorField label={<div className="w-14">Specular</div>} object={this.props.material} property="specularColor" />
61+
</EditorInspectorSectionField>
62+
63+
<EditorInspectorSectionField title="Reflection">
64+
<input
65+
type="text"
66+
placeholder="Search..."
67+
value={this.state.renderListSearch}
68+
onChange={(e) => this.setState({ renderListSearch: e.currentTarget.value })}
69+
className="px-5 py-2 rounded-lg bg-primary-foreground outline-none w-full"
70+
/>
71+
72+
<div className="flex flex-col w-full max-h-96 p-2 rounded-lg bg-card overflow-x-hidden overflow-y-auto">
73+
{this.props.material
74+
.getScene()
75+
.meshes.filter((mesh) => mesh.name.toLowerCase().includes(this.state.renderListSearch.toLowerCase()))
76+
.map((mesh) => this._getRenderListItem(mesh))}
77+
</div>
78+
</EditorInspectorSectionField>
79+
</>
80+
)}
81+
82+
<EditorInspectorSectionField title="Options">
83+
<EditorInspectorNumberField label="Wave Length" object={this.props.material} property="waveLength" />
84+
85+
<EditorInspectorNumberField label="Wind Force" object={this.props.material} property="windForce" />
86+
<EditorInspectorVectorField label="Wind Direction" object={this.props.material} property="windDirection" step={0.1} />
87+
88+
<EditorInspectorSwitchField label="Bump Super Impose" object={this.props.material} property="bumpSuperimpose" />
89+
<EditorInspectorSwitchField label="Fresnel Separate" object={this.props.material} property="fresnelSeparate" />
90+
<EditorInspectorSwitchField label="Bump Affects Reflection" object={this.props.material} property="bumpAffectsReflection" />
91+
</EditorInspectorSectionField>
92+
93+
<EditorInspectorSectionField title="Misc">
94+
<EditorInspectorSwitchField label="Disable Lighting" object={this.props.material} property="disableLighting" />
95+
<EditorInspectorSwitchField label="Separate Culling Pass" object={this.props.material} property="separateCullingPass" />
96+
<EditorInspectorNumberField label="Z Offset" object={this.props.material} property="zOffset" />
97+
<EditorInspectorNumberField label="Z Offset Units" object={this.props.material} property="zOffsetUnits" />
98+
<EditorInspectorSwitchField label="Fog Enabled" object={this.props.material} property="fogEnabled" />
99+
</EditorInspectorSectionField>
100+
</>
101+
);
102+
}
103+
104+
private _getRenderListItem(mesh: AbstractMesh): ReactNode {
105+
if (mesh === this.props.mesh) {
106+
return undefined;
107+
}
108+
109+
return (
110+
<div key={mesh.id} className="flex items-center gap-2 hover:bg-muted transition-all duration-300 ease-in-out p-2 rounded-lg">
111+
<Switch
112+
defaultChecked={this.props.material.reflectionTexture?.renderList?.includes(mesh)}
113+
onCheckedChange={(checked) => {
114+
if (checked) {
115+
this.props.material.addToRenderList(mesh);
116+
} else {
117+
this.props.material.removeFromRenderList(mesh);
118+
}
119+
}}
120+
/>
121+
<div>{mesh.name}</div>
122+
</div>
123+
);
124+
}
125+
}

editor/src/editor/layout/inspector/mesh/mesh.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { FaCopy, FaLink } from "react-icons/fa6";
55
import { IoAddSharp, IoCloseOutline } from "react-icons/io5";
66
import { AiOutlinePlus } from "react-icons/ai";
77

8-
import { SkyMaterial, GridMaterial, NormalMaterial } from "babylonjs-materials";
8+
import { SkyMaterial, GridMaterial, NormalMaterial, WaterMaterial } from "babylonjs-materials";
99
import { AbstractMesh, InstancedMesh, Material, Mesh, MorphTarget, MultiMaterial, Node, Observer, PBRMaterial, StandardMaterial, NodeMaterial } from "babylonjs";
1010

1111
import { CollisionMesh } from "../../../nodes/collision";
@@ -40,9 +40,10 @@ import { IEditorInspectorImplementationProps } from "../inspector";
4040
import { EditorPBRMaterialInspector } from "../material/pbr";
4141
import { EditorSkyMaterialInspector } from "../material/sky";
4242
import { EditorGridMaterialInspector } from "../material/grid";
43-
import { EditorNormalMaterialInspector } from "../material/normal";
4443
import { EditorNodeMaterialInspector } from "../material/node";
4544
import { EditorMultiMaterialInspector } from "../material/multi";
45+
import { EditorWaterMaterialInspector } from "../material/water";
46+
import { EditorNormalMaterialInspector } from "../material/normal";
4647
import { EditorStandardMaterialInspector } from "../material/standard";
4748

4849
import { MeshDecalInspector } from "./decal";
@@ -310,6 +311,9 @@ export class EditorMeshInspector extends Component<IEditorInspectorImplementatio
310311

311312
case "NormalMaterial":
312313
return <EditorNormalMaterialInspector mesh={this.props.object} material={this.props.object.material as NormalMaterial} />;
314+
315+
case "WaterMaterial":
316+
return <EditorWaterMaterialInspector mesh={this.props.object} material={this.props.object.material as WaterMaterial} />;
313317
}
314318
}
315319

editor/src/project/add/material.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { SkyMaterial, GridMaterial, NormalMaterial } from "babylonjs-materials";
21
import { Scene, Tools, PBRMaterial, StandardMaterial, NodeMaterial } from "babylonjs";
2+
import { SkyMaterial, GridMaterial, NormalMaterial, WaterMaterial } from "babylonjs-materials";
33

44
import { UniqueNumber } from "../../tools/tools";
55

@@ -51,3 +51,13 @@ export function addNormalMaterial(scene: Scene) {
5151

5252
return material;
5353
}
54+
55+
export function addWaterMaterial(scene: Scene) {
56+
const material = new WaterMaterial("New Water Material", scene);
57+
material.id = Tools.RandomId();
58+
material.uniqueId = UniqueNumber.Get();
59+
material.waveCount = 1;
60+
material.waveHeight = 0;
61+
62+
return material;
63+
}

0 commit comments

Comments
 (0)