Skip to content

Commit 640fb62

Browse files
committed
feat: clipping plane autoscale
1 parent 2d96042 commit 640fb62

File tree

3 files changed

+71
-4
lines changed

3 files changed

+71
-4
lines changed

packages/core/src/core/Clipper/example.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,13 +201,25 @@ const panel = BUI.Component.create<BUI.PanelSection>(() => {
201201
}}">
202202
</bim-number-input>
203203
204-
<bim-number-input
204+
<bim-number-input
205205
slider step="0.1" label="Planes Size" value="5" min="2" max="10"
206206
@change="${({ target }: { target: BUI.NumberInput }) => {
207207
clipper.config.size = target.value;
208208
}}">
209209
</bim-number-input>
210-
210+
211+
<bim-checkbox label="Auto Scale Planes" checked
212+
@change="${({ target }: { target: BUI.Checkbox }) => {
213+
clipper.autoScalePlanes = target.value;
214+
for (const [, plane] of clipper.list) {
215+
plane.autoScale = target.value;
216+
if (!target.value) {
217+
plane.size = clipper.size;
218+
}
219+
}
220+
}}">
221+
</bim-checkbox>
222+
211223
<bim-button
212224
label="Toggle Clippings"
213225
@click=${toggleClippings}>

packages/core/src/core/Clipper/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ export class Clipper
9898
*/
9999
toleranceOrthogonalY = 0.7;
100100

101+
/**
102+
* Whether clipping planes should automatically scale based on
103+
* camera distance. When true, the plane surface stays proportional
104+
* to the arrow gizmo as you zoom in/out. Default is true.
105+
*/
106+
autoScalePlanes = true;
107+
101108
/**
102109
* The type of clipping plane to be created.
103110
* Default is {@link SimplePlane}.
@@ -401,6 +408,7 @@ export class Clipper
401408
normal,
402409
this._material,
403410
);
411+
plane.autoScale = this.autoScalePlanes;
404412
plane.onDraggingStarted.add(this._onStartDragging);
405413
plane.onDraggingEnded.add(this._onEndDragging);
406414
const id = UUID.create();

packages/core/src/core/Clipper/src/simple-plane.ts

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,21 @@ export class SimplePlane implements Disposable, Hideable {
6969
visible: false,
7070
});
7171

72+
private _sizeMultiplier = 5;
73+
74+
private _autoScale = true;
75+
76+
get autoScale() {
77+
return this._autoScale;
78+
}
79+
80+
set autoScale(value: boolean) {
81+
this._autoScale = value;
82+
if (value) {
83+
this.updateScale();
84+
}
85+
}
86+
7287
/**
7388
* Getter for the enabled state of the clipping plane.
7489
* @returns {boolean} The current enabled state.
@@ -136,12 +151,17 @@ export class SimplePlane implements Disposable, Hideable {
136151

137152
/** The size of the clipping plane representation. */
138153
get size() {
139-
return this._planeMesh.scale.x;
154+
return this._sizeMultiplier;
140155
}
141156

142157
/** Sets the size of the clipping plane representation. */
143158
set size(size: number) {
144-
this._planeMesh.scale.set(size, size, size);
159+
this._sizeMultiplier = size;
160+
if (this.autoScale) {
161+
this.updateScale();
162+
} else {
163+
this._planeMesh.scale.set(size, size, size);
164+
}
145165
}
146166

147167
/**
@@ -183,6 +203,7 @@ export class SimplePlane implements Disposable, Hideable {
183203

184204
this.normal = normal;
185205
this.origin = origin;
206+
this._sizeMultiplier = size;
186207

187208
world.renderer.setPlane(true, this.three);
188209

@@ -194,6 +215,11 @@ export class SimplePlane implements Disposable, Hideable {
194215
if (activateControls) {
195216
this.toggleControls(true);
196217
}
218+
219+
this.updateScale();
220+
if (world.camera?.controls) {
221+
world.camera.controls.addEventListener("update", this.updateScale);
222+
}
197223
}
198224

199225
private notifyManager = () => {
@@ -231,11 +257,32 @@ export class SimplePlane implements Disposable, Hideable {
231257
this.normal,
232258
this._helper.position,
233259
);
260+
this.updateScale();
261+
};
262+
263+
private updateScale = () => {
264+
if (!this.autoScale) return;
265+
const camera = this.world.camera?.three;
266+
if (!camera) return;
267+
if (!(camera instanceof THREE.PerspectiveCamera)) return;
268+
const cameraPosition = new THREE.Vector3();
269+
camera.getWorldPosition(cameraPosition);
270+
const distance = cameraPosition.distanceTo(this._helper.position);
271+
const scale = (distance / 7) * this._sizeMultiplier;
272+
this._planeMesh.scale.set(scale, scale, scale);
234273
};
235274

236275
/** {@link Disposable.dispose} */
237276
dispose() {
238277
this._enabled = false;
278+
279+
if (this.world.camera?.controls) {
280+
this.world.camera.controls.removeEventListener(
281+
"update",
282+
this.updateScale,
283+
);
284+
}
285+
239286
this.onDraggingStarted.reset();
240287
this.onDraggingEnded.reset();
241288
this._helper.removeFromParent();

0 commit comments

Comments
 (0)