Skip to content

Commit

Permalink
feat(gizmo): custom colors for gizmos (BabylonJS#14525)
Browse files Browse the repository at this point in the history
* feat(gizmo): custom colors for plan-rotation gizmo

* docs(contributing): fix typos

* feat(gizmo): custom colors for axis-drag gizmo

* fix(gizmo): avoid white reflection on hover material

* style: run `npm run format`

* refactor: ensure rgb values always contain '.'

* refactor: getter to avoid breaking change & default hover color

* refactor: set uniform in shader instead of dynamic string
  • Loading branch information
PhilippeMorier authored Nov 17, 2023
1 parent 488287a commit de4fd4b
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 18 deletions.
6 changes: 3 additions & 3 deletions contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ The first golden rule is a really important one because we want our users to tru

### Performance

Babylon.js is a 3D rendering engine. So every piece of code has to be scrutinized to look for potential bottlenecks or slow downs. Ultimately the goal is to render more with less resources.
Babylon.js is a 3D rendering engine. So every piece of code has to be scrutinized to look for potential bottlenecks or slowdowns. Ultimately the goal is to render more with less resources.

### Simplicity

Expand Down Expand Up @@ -58,7 +58,7 @@ If you intend to only update the doc, this [documentation](https://doc.babylonjs

To validate your PR, please follow these steps:

- Run "npm run build:dev" locally and make sure that no error is generated
- Run `npm run build:dev` locally and make sure that no error is generated
- Make sure that all public functions and classes are commented using JSDoc/TSDoc syntax
- Run `npm run test:unit` for unit tests, and check the buildSystem.md file for information regarding the visualization tests.

Expand All @@ -71,4 +71,4 @@ In order to not bloat the core engine with unwanted or unnecessary features (tha
- Is there a general use case for this feature?
- Does this feature already exist in a similar framework?

If your PR is does not fall into the core category you can consider using our [Extensions repo](https://github.com/BabylonJS/Extensions) for more high level features.
If your PR does not fall into the core category you can consider using our [Extensions repo](https://github.com/BabylonJS/Extensions) for more high level features.
36 changes: 31 additions & 5 deletions packages/dev/core/src/Gizmos/axisDragGizmo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type { Scene } from "../scene";
import type { PositionGizmo } from "./positionGizmo";
import { Color3 } from "../Maths/math.color";
import { TmpVectors } from "../Maths/math.vector";

/**
* Interface for axis drag gizmo
*/
Expand Down Expand Up @@ -82,13 +83,32 @@ export class AxisDragGizmo extends Gizmo implements IAxisDragGizmo {
public get disableMaterial() {
return this._disableMaterial;
}

/**
* @internal
*/
public static _CreateArrow(scene: Scene, material: StandardMaterial, thickness: number = 1, isCollider = false): TransformNode {
const arrow = new TransformNode("arrow", scene);
const cylinder = CreateCylinder("cylinder", { diameterTop: 0, height: 0.075, diameterBottom: 0.0375 * (1 + (thickness - 1) / 4), tessellation: 96 }, scene);
const line = CreateCylinder("cylinder", { diameterTop: 0.005 * thickness, height: 0.275, diameterBottom: 0.005 * thickness, tessellation: 96 }, scene);
const cylinder = CreateCylinder(
"cylinder",
{
diameterTop: 0,
height: 0.075,
diameterBottom: 0.0375 * (1 + (thickness - 1) / 4),
tessellation: 96,
},
scene
);
const line = CreateCylinder(
"cylinder",
{
diameterTop: 0.005 * thickness,
height: 0.275,
diameterBottom: 0.005 * thickness,
tessellation: 96,
},
scene
);

// Position arrow pointing in its drag axis
cylinder.parent = arrow;
Expand Down Expand Up @@ -127,13 +147,17 @@ export class AxisDragGizmo extends Gizmo implements IAxisDragGizmo {
* @param gizmoLayer The utility layer the gizmo will be added to
* @param parent
* @param thickness display gizmo axis thickness
* @param hoverColor The color of the gizmo when hovering over and dragging
* @param disableColor The Color of the gizmo when its disabled
*/
constructor(
dragAxis: Vector3,
color: Color3 = Color3.Gray(),
gizmoLayer: UtilityLayerRenderer = UtilityLayerRenderer.DefaultUtilityLayer,
parent: Nullable<PositionGizmo> = null,
thickness: number = 1
thickness: number = 1,
hoverColor: Color3 = Color3.Yellow(),
disableColor: Color3 = Color3.Gray()
) {
super(gizmoLayer);
this._parent = parent;
Expand All @@ -144,10 +168,10 @@ export class AxisDragGizmo extends Gizmo implements IAxisDragGizmo {
this._coloredMaterial.specularColor = color.subtract(new Color3(0.1, 0.1, 0.1));

this._hoverMaterial = new StandardMaterial("", gizmoLayer.utilityLayerScene);
this._hoverMaterial.diffuseColor = Color3.Yellow();
this._hoverMaterial.diffuseColor = hoverColor;

this._disableMaterial = new StandardMaterial("", gizmoLayer.utilityLayerScene);
this._disableMaterial.diffuseColor = Color3.Gray();
this._disableMaterial.diffuseColor = disableColor;
this._disableMaterial.alpha = 0.4;

// Build Mesh + Collider
Expand Down Expand Up @@ -253,6 +277,7 @@ export class AxisDragGizmo extends Gizmo implements IAxisDragGizmo {
this._setGizmoMeshMaterial(cache.gizmoMeshes, newState ? cache.material : cache.disableMaterial);
});
}

protected _attachedNodeChanged(value: Nullable<Node>) {
if (this.dragBehavior) {
this.dragBehavior.enabled = value ? true : false;
Expand All @@ -274,6 +299,7 @@ export class AxisDragGizmo extends Gizmo implements IAxisDragGizmo {
}
}
}

public get isEnabled(): boolean {
return this._isEnabled;
}
Expand Down
6 changes: 5 additions & 1 deletion packages/dev/core/src/Gizmos/planeDragGizmo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export interface IPlaneDragGizmo extends IGizmo {
snapDistance: number;
/**
* Event that fires each time the gizmo snaps to a new location.
* * snapDistance is the the change in distance
* * snapDistance is the change in distance
*/
onSnapObservable: Observable<{ snapDistance: number }>;
/** If the gizmo is enabled */
Expand Down Expand Up @@ -82,6 +82,7 @@ export class PlaneDragGizmo extends Gizmo implements IPlaneDragGizmo {
public get disableMaterial() {
return this._disableMaterial;
}

/**
* @internal
*/
Expand Down Expand Up @@ -205,6 +206,7 @@ export class PlaneDragGizmo extends Gizmo implements IPlaneDragGizmo {
this._setGizmoMeshMaterial(cache.gizmoMeshes, newState ? this._coloredMaterial : this._disableMaterial);
});
}

protected _attachedNodeChanged(value: Nullable<Node>) {
if (this.dragBehavior) {
this.dragBehavior.enabled = value ? true : false;
Expand All @@ -224,9 +226,11 @@ export class PlaneDragGizmo extends Gizmo implements IPlaneDragGizmo {
}
}
}

public get isEnabled(): boolean {
return this._isEnabled;
}

/**
* Disposes of the gizmo
*/
Expand Down
38 changes: 29 additions & 9 deletions packages/dev/core/src/Gizmos/planeRotationGizmo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export interface IPlaneRotationGizmo extends IGizmo {
sensitivity: number;
/**
* Event that fires each time the gizmo snaps to a new location.
* * snapDistance is the the change in distance
* * snapDistance is the change in distance
*/
onSnapObservable: Observable<{ snapDistance: number }>;
/** Accumulated relative angle value for rotation on the axis. */
Expand Down Expand Up @@ -65,7 +65,7 @@ export class PlaneRotationGizmo extends Gizmo implements IPlaneRotationGizmo {
public snapDistance = 0;
/**
* Event that fires each time the gizmo snaps to a new location.
* * snapDistance is the the change in distance
* * snapDistance is the change in distance
*/
public onSnapObservable = new Observable<{ snapDistance: number }>();

Expand Down Expand Up @@ -117,6 +117,7 @@ export class PlaneRotationGizmo extends Gizmo implements IPlaneRotationGizmo {
uniform mat4 worldViewProjection;
varying vec3 vPosition;
varying vec2 vUV;
void main(void) {
gl_Position = worldViewProjection * vec4(position, 1.0);
vUV = uv;
Expand All @@ -127,7 +128,10 @@ export class PlaneRotationGizmo extends Gizmo implements IPlaneRotationGizmo {
varying vec2 vUV;
varying vec3 vPosition;
uniform vec3 angles;
uniform vec3 hoverColor;
#define twopi 6.283185307
void main(void) {
vec2 uv = vUV - vec2(0.5);
float angle = atan(uv.y, uv.x) + 3.141592;
Expand All @@ -148,8 +152,9 @@ export class PlaneRotationGizmo extends Gizmo implements IPlaneRotationGizmo {
intensity += max(step(start, angle) - step(end, angle), 0.);
angle += twopi;
}
gl_FragColor = vec4(1.,1.,0., min(intensity * 0.25, 0.8)) * opacity;
}`;
gl_FragColor = vec4(hoverColor, min(intensity * 0.25, 0.8)) * opacity;
}
`;

protected _rotationShaderMaterial: ShaderMaterial;

Expand All @@ -162,6 +167,8 @@ export class PlaneRotationGizmo extends Gizmo implements IPlaneRotationGizmo {
* @param parent
* @param useEulerRotation Use and update Euler angle instead of quaternion
* @param thickness display gizmo axis thickness
* @param hoverColor The color of the gizmo when hovering over and dragging
* @param disableColor The Color of the gizmo when its disabled
*/
constructor(
planeNormal: Vector3,
Expand All @@ -171,7 +178,9 @@ export class PlaneRotationGizmo extends Gizmo implements IPlaneRotationGizmo {
parent: Nullable<RotationGizmo> = null,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
useEulerRotation = false,
thickness: number = 1
thickness: number = 1,
hoverColor: Color3 = Color3.Yellow(),
disableColor: Color3 = Color3.Gray()
) {
super(gizmoLayer);
this._parent = parent;
Expand All @@ -181,18 +190,26 @@ export class PlaneRotationGizmo extends Gizmo implements IPlaneRotationGizmo {
this._coloredMaterial.specularColor = color.subtract(new Color3(0.1, 0.1, 0.1));

this._hoverMaterial = new StandardMaterial("", gizmoLayer.utilityLayerScene);
this._hoverMaterial.diffuseColor = Color3.Yellow();
this._hoverMaterial.diffuseColor = hoverColor;
this._hoverMaterial.specularColor = hoverColor;

this._disableMaterial = new StandardMaterial("", gizmoLayer.utilityLayerScene);
this._disableMaterial.diffuseColor = Color3.Gray();
this._disableMaterial.diffuseColor = disableColor;
this._disableMaterial.alpha = 0.4;

// Build mesh on root node
this._gizmoMesh = new Mesh("", gizmoLayer.utilityLayerScene);
const { rotationMesh, collider } = this._createGizmoMesh(this._gizmoMesh, thickness, tessellation);

// Setup Rotation Circle
this._rotationDisplayPlane = CreatePlane("rotationDisplay", { size: 0.6, updatable: false }, this.gizmoLayer.utilityLayerScene);
this._rotationDisplayPlane = CreatePlane(
"rotationDisplay",
{
size: 0.6,
updatable: false,
},
this.gizmoLayer.utilityLayerScene
);
this._rotationDisplayPlane.rotation.z = Math.PI * 0.5;
this._rotationDisplayPlane.parent = this._gizmoMesh;
this._rotationDisplayPlane.setEnabled(false);
Expand All @@ -208,10 +225,11 @@ export class PlaneRotationGizmo extends Gizmo implements IPlaneRotationGizmo {
},
{
attributes: ["position", "uv"],
uniforms: ["worldViewProjection", "angles"],
uniforms: ["worldViewProjection", "angles", "hoverColor"],
}
);
this._rotationShaderMaterial.backFaceCulling = false;
this._rotationShaderMaterial.setColor3("hoverColor", hoverColor);

this._rotationDisplayPlane.material = this._rotationShaderMaterial;
this._rotationDisplayPlane.visibility = 0.999;
Expand Down Expand Up @@ -458,9 +476,11 @@ export class PlaneRotationGizmo extends Gizmo implements IPlaneRotationGizmo {
}
}
}

public get isEnabled(): boolean {
return this._isEnabled;
}

/**
* Disposes of the gizmo
*/
Expand Down

0 comments on commit de4fd4b

Please sign in to comment.