|
1 | | -import { Camera, Entity, Plane, Ray, Vector3, Matrix, MeshRenderer, UnlitMaterial, ModelMesh } from "@galacean/engine"; |
| 1 | +import { Camera, Entity, Plane, Ray, Vector3, Matrix, MeshRenderer, UnlitMaterial, ModelMesh, Shader, ShaderData, Color } from "@galacean/engine"; |
2 | 2 |
|
3 | 3 | import { Axis } from "./Axis"; |
4 | 4 | import { GizmoUtils, X_AXIS_ROTATION, Y_AXIS_ROTATION, Z_AXIS_ROTATION, XY_PLANE_ROTATION, YZ_PLANE_ROTATION, XZ_PLANE_ROTATION, LINE_TRANSLATION, END_TRANSLATION, PLANE_TRANSLATION } from "./constants"; |
@@ -32,15 +32,22 @@ export class TranslateControl extends GizmoComponent { |
32 | 32 | private _tempScale: number = 1; |
33 | 33 |
|
34 | 34 | // Reference line entities and meshes |
35 | | - private _referenceLineEntity: Entity; |
36 | | - private _referenceLineMesh: ModelMesh; |
| 35 | + private _referenceLineEntityX: Entity; |
| 36 | + private _referenceLineEntityY: Entity; |
| 37 | + private _referenceLineEntityZ: Entity; |
| 38 | + private _referenceLineMeshX: ModelMesh; |
| 39 | + private _referenceLineMeshY: ModelMesh; |
| 40 | + private _referenceLineMeshZ: ModelMesh; |
| 41 | + private _referenceLineMaterialX: UnlitMaterial; |
| 42 | + private _referenceLineMaterialY: UnlitMaterial; |
| 43 | + private _referenceLineMaterialZ: UnlitMaterial; |
37 | 44 |
|
38 | 45 | constructor(entity: Entity) { |
39 | 46 | super(entity); |
40 | 47 | this.type = State.translate; |
41 | 48 | this._initAxis(); |
42 | 49 | this._createAxis(entity); |
43 | | - this._createReferenceLine(entity); |
| 50 | + this._createReferenceLines(entity); |
44 | 51 | } |
45 | 52 |
|
46 | 53 | init(camera: Camera, group: Group): void { |
@@ -81,10 +88,10 @@ export class TranslateControl extends GizmoComponent { |
81 | 88 |
|
82 | 89 | this._selectedAxis = null; |
83 | 90 |
|
84 | | - // Hide reference line |
85 | | - if (this._referenceLineEntity) { |
86 | | - this._referenceLineEntity.isActive = false; |
87 | | - } |
| 91 | + // Hide all reference lines |
| 92 | + this._referenceLineEntityX.isActive = false; |
| 93 | + this._referenceLineEntityY.isActive = false; |
| 94 | + this._referenceLineEntityZ.isActive = false; |
88 | 95 | } |
89 | 96 |
|
90 | 97 | onMoveStart(ray: Ray, axisName: string): void { |
@@ -150,10 +157,10 @@ export class TranslateControl extends GizmoComponent { |
150 | 157 | currComponent.recover && currComponent.recover(); |
151 | 158 | } |
152 | 159 |
|
153 | | - // Hide reference line |
154 | | - if (this._referenceLineEntity) { |
155 | | - this._referenceLineEntity.isActive = false; |
156 | | - } |
| 160 | + // Hide all reference lines |
| 161 | + this._referenceLineEntityX.isActive = false; |
| 162 | + this._referenceLineEntityY.isActive = false; |
| 163 | + this._referenceLineEntityZ.isActive = false; |
157 | 164 | } |
158 | 165 |
|
159 | 166 | onUpdate(isModified: boolean = false): void { |
@@ -271,67 +278,140 @@ export class TranslateControl extends GizmoComponent { |
271 | 278 | } |
272 | 279 | } |
273 | 280 |
|
274 | | - private _createReferenceLine(entity: Entity): void { |
275 | | - console.log('_createReferenceLine') |
276 | | - // Create reference line entity |
277 | | - this._referenceLineEntity = entity.createChild("referenceLine"); |
278 | | - this._referenceLineEntity.isActive = false; |
279 | | - |
280 | | - // Create a long line mesh for reference that extends in both directions |
| 281 | + private _createReferenceLines(entity: Entity): void { |
281 | 282 | const lineLength = 1000; // Very long line to appear infinite |
282 | | - const start = new Vector3(-lineLength, 0, 0); // Negative direction |
283 | | - const end = new Vector3(lineLength, 0, 0); // Positive direction |
284 | | - this._referenceLineMesh = GizmoMesh.createLine(this.engine, [start, end]); |
285 | 283 |
|
286 | | - // Add renderer |
287 | | - const renderer = this._referenceLineEntity.addComponent(MeshRenderer); |
288 | | - renderer.receiveShadows = false; |
289 | | - renderer.castShadows = false; |
290 | | - renderer.mesh = this._referenceLineMesh; |
| 284 | + // Create shader for gradient lines if it doesn't exist |
| 285 | + if (!Shader.find("gradientLine")) { |
| 286 | + this._createGradientLineShader(); |
| 287 | + } |
| 288 | + |
| 289 | + // Create X axis reference line |
| 290 | + this._referenceLineEntityX = entity.createChild("referenceLineX"); |
| 291 | + this._referenceLineEntityX.isActive = false; |
| 292 | + const startX = new Vector3(-lineLength, 0, 0); |
| 293 | + const endX = new Vector3(lineLength, 0, 0); |
| 294 | + this._referenceLineMeshX = GizmoMesh.createLine(this.engine, [startX, endX]); |
| 295 | + |
| 296 | + // Create Y axis reference line |
| 297 | + this._referenceLineEntityY = entity.createChild("referenceLineY"); |
| 298 | + this._referenceLineEntityY.isActive = false; |
| 299 | + const startY = new Vector3(0, -lineLength, 0); |
| 300 | + const endY = new Vector3(0, lineLength, 0); |
| 301 | + this._referenceLineMeshY = GizmoMesh.createLine(this.engine, [startY, endY]); |
| 302 | + |
| 303 | + // Create Z axis reference line |
| 304 | + this._referenceLineEntityZ = entity.createChild("referenceLineZ"); |
| 305 | + this._referenceLineEntityZ.isActive = false; |
| 306 | + const startZ = new Vector3(0, 0, -lineLength); |
| 307 | + const endZ = new Vector3(0, 0, lineLength); |
| 308 | + this._referenceLineMeshZ = GizmoMesh.createLine(this.engine, [startZ, endZ]); |
291 | 309 |
|
292 | | - // Create white material for the reference line |
293 | | - const whiteMaterial = new UnlitMaterial(this.engine); |
294 | | - whiteMaterial.isTransparent = true; |
295 | | - whiteMaterial.renderState.depthState.enabled = false; |
296 | | - whiteMaterial.baseColor.set(1, 1, 1, 0.5); // White with some transparency |
297 | | - whiteMaterial.name = "referenceLineMaterial"; |
| 310 | + // Create materials for each line with matching colors |
| 311 | + this._referenceLineMaterialX = this._createGradientMaterial(GizmoUtils.redMaterialTrans.baseColor); |
| 312 | + this._referenceLineMaterialY = this._createGradientMaterial(GizmoUtils.greenMaterialTrans.baseColor); |
| 313 | + this._referenceLineMaterialZ = this._createGradientMaterial(GizmoUtils.blueMaterialTrans.baseColor); |
298 | 314 |
|
299 | | - renderer.setMaterial(whiteMaterial); |
| 315 | + // Add renderers for each line |
| 316 | + const rendererX = this._referenceLineEntityX.addComponent(MeshRenderer); |
| 317 | + rendererX.receiveShadows = false; |
| 318 | + rendererX.castShadows = false; |
| 319 | + rendererX.mesh = this._referenceLineMeshX; |
| 320 | + rendererX.setMaterial(this._referenceLineMaterialX); |
| 321 | + |
| 322 | + const rendererY = this._referenceLineEntityY.addComponent(MeshRenderer); |
| 323 | + rendererY.receiveShadows = false; |
| 324 | + rendererY.castShadows = false; |
| 325 | + rendererY.mesh = this._referenceLineMeshY; |
| 326 | + rendererY.setMaterial(this._referenceLineMaterialY); |
| 327 | + |
| 328 | + const rendererZ = this._referenceLineEntityZ.addComponent(MeshRenderer); |
| 329 | + rendererZ.receiveShadows = false; |
| 330 | + rendererZ.castShadows = false; |
| 331 | + rendererZ.mesh = this._referenceLineMeshZ; |
| 332 | + rendererZ.setMaterial(this._referenceLineMaterialZ); |
300 | 333 | } |
301 | 334 |
|
302 | | - private _showReferenceLine(axisName: string): void { |
303 | | - console.log('_showReferenceLine', axisName, this._referenceLineEntity); |
304 | | - if (!this._referenceLineEntity) return; |
| 335 | + private _createGradientLineShader(): void { |
| 336 | + const vertexSource = ` |
| 337 | + #include <common> |
| 338 | + #include <common_vert> |
| 339 | + |
| 340 | + uniform mat4 u_MVPMat; |
| 341 | + |
| 342 | + attribute vec3 a_Position; |
| 343 | + |
| 344 | + varying float v_Distance; |
| 345 | + |
| 346 | + void main() { |
| 347 | + gl_Position = u_MVPMat * vec4(a_Position, 1.0); |
| 348 | + v_Distance = length(a_Position); |
| 349 | + } |
| 350 | + `; |
305 | 351 |
|
306 | | - // Reset rotation |
307 | | - // this._referenceLineEntity.transform.rotation.set(0, 0, 0); |
| 352 | + const fragmentSource = ` |
| 353 | + #include <common> |
| 354 | + |
| 355 | + uniform vec4 u_LineColor; |
| 356 | + uniform float u_MaxDistance; |
| 357 | + |
| 358 | + varying float v_Distance; |
| 359 | + |
| 360 | + void main() { |
| 361 | + float normalizedDistance = v_Distance / u_MaxDistance; |
| 362 | + float alpha = max(0.0, 1.0 - normalizedDistance); |
| 363 | + gl_FragColor = vec4(u_LineColor.rgb, u_LineColor.a * alpha); |
| 364 | + } |
| 365 | + `; |
308 | 366 |
|
309 | | - // Show the reference line |
| 367 | + Shader.create("gradientLine", vertexSource, fragmentSource); |
| 368 | + } |
| 369 | + |
| 370 | + private _createGradientMaterial(color: Color): UnlitMaterial { |
| 371 | + const material = new UnlitMaterial(this.engine); |
| 372 | + // material.shader = Shader.find("gradientLine") |
| 373 | + |
| 374 | + material.isTransparent = true; |
| 375 | + material.renderState.depthState.enabled = false; |
310 | 376 |
|
311 | | - // Update the scale to match the current gizmo scale |
312 | | - this._referenceLineEntity.transform.scale.set(this._tempScale, this._tempScale, this._tempScale); |
| 377 | + material.shaderData.setColor("u_LineColor", color); |
| 378 | + material.shaderData.setFloat("u_MaxDistance", 50.0); |
313 | 379 |
|
314 | | - // Update the position to match the current gizmo position |
315 | | - // This ensures the reference line follows the gizmo when it moves |
316 | | - this._referenceLineEntity.transform.worldMatrix = this.gizmoEntity.transform.worldMatrix.clone(); |
317 | | - |
318 | | - // Set rotation based on axis |
| 380 | + return material; |
| 381 | + } |
| 382 | + |
| 383 | + private _showReferenceLine(axisName: string): void { |
| 384 | + // Hide all reference lines first |
| 385 | + this._referenceLineEntityX.isActive = false; |
| 386 | + this._referenceLineEntityY.isActive = false; |
| 387 | + this._referenceLineEntityZ.isActive = false; |
| 388 | + |
| 389 | + // Show the appropriate reference line based on the axis |
| 390 | + let referenceLine: Entity; |
319 | 391 | switch (axisName) { |
320 | 392 | case "x": |
321 | | - // X axis is default |
| 393 | + referenceLine = this._referenceLineEntityX; |
322 | 394 | break; |
323 | 395 | case "y": |
324 | | - // Rotate to align with Y axis |
325 | | - this._referenceLineEntity.transform.rotation.set(0, 0, 90); |
| 396 | + referenceLine = this._referenceLineEntityY; |
326 | 397 | break; |
327 | 398 | case "z": |
328 | | - // Rotate to align with Z axis |
329 | | - this._referenceLineEntity.transform.rotation.set(0, -90, 0); |
| 399 | + referenceLine = this._referenceLineEntityZ; |
330 | 400 | break; |
| 401 | + default: |
| 402 | + return; // No reference line for plane controls |
| 403 | + } |
| 404 | + |
| 405 | + if (referenceLine) { |
| 406 | + // Show the reference line |
| 407 | + referenceLine.isActive = true; |
| 408 | + |
| 409 | + // Update the scale to match the current gizmo scale |
| 410 | + referenceLine.transform.scale.set(this._tempScale, this._tempScale, this._tempScale); |
| 411 | + |
| 412 | + // Update the position to match the current gizmo position |
| 413 | + referenceLine.transform.worldMatrix = this.gizmoEntity.transform.worldMatrix.clone(); |
331 | 414 | } |
332 | | - |
333 | | - this._referenceLineEntity.isActive = true; |
334 | | - |
335 | 415 | } |
336 | 416 |
|
337 | 417 | private _getHitPlane(): void { |
@@ -377,8 +457,18 @@ export class TranslateControl extends GizmoComponent { |
377 | 457 | _tempVec0.set(this._tempScale, this._tempScale, this._tempScale) |
378 | 458 | ); |
379 | 459 |
|
380 | | - if (this._referenceLineEntity && this._referenceLineEntity.isActive) { |
381 | | - this._referenceLineEntity.transform.scale.set(this._tempScale, this._tempScale, this._tempScale); |
| 460 | + // Update reference lines if any are active |
| 461 | + if (this._referenceLineEntityX.isActive) { |
| 462 | + this._referenceLineEntityX.transform.scale.set(this._tempScale, this._tempScale, this._tempScale); |
| 463 | + this._referenceLineEntityX.transform.worldMatrix = _tempMat.clone(); |
| 464 | + } |
| 465 | + if (this._referenceLineEntityY.isActive) { |
| 466 | + this._referenceLineEntityY.transform.scale.set(this._tempScale, this._tempScale, this._tempScale); |
| 467 | + this._referenceLineEntityY.transform.worldMatrix = _tempMat.clone(); |
| 468 | + } |
| 469 | + if (this._referenceLineEntityZ.isActive) { |
| 470 | + this._referenceLineEntityZ.transform.scale.set(this._tempScale, this._tempScale, this._tempScale); |
| 471 | + this._referenceLineEntityZ.transform.worldMatrix = _tempMat.clone(); |
382 | 472 | } |
383 | 473 | } |
384 | 474 |
|
|
0 commit comments