Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transform controls #151

Closed
wants to merge 1 commit into from
Closed
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
131 changes: 92 additions & 39 deletions packages/jupytercad-extension/src/mainview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
disposeBoundsTree
} from 'three-mesh-bvh';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { TransformControls } from 'three/examples/jsm/controls/TransformControls.js';
import { v4 as uuid } from 'uuid';

import {
Expand Down Expand Up @@ -230,7 +231,7 @@ export class MainView extends React.Component<IProps, IStates> {
DEFAULT_EDGE_COLOR.set(getCSSVariableColor(DEFAULT_EDGE_COLOR_CSS));
SELECTED_MESH_COLOR.set(getCSSVariableColor(SELECTED_MESH_COLOR_CSS));

this._camera = new THREE.PerspectiveCamera(90, 2, 0.1, 1000);
this._camera = new THREE.PerspectiveCamera(45, 2, 0.1, 1000);
this._camera.position.set(8, 8, 8);
this._camera.up.set(0, 0, 1);

Expand Down Expand Up @@ -321,6 +322,23 @@ export class MainView extends React.Component<IProps, IStates> {
);
}, 100)
);

this._transformControls = new TransformControls(
this._camera,
this._renderer.domElement
);
this._transformControls.addEventListener('dragging-changed', event => {
this._transforming = event.value;
this._controls.enabled = !event.value;

if (this._transforming && this._pointer3D) {
this._pointer3D.mesh.visible = false;
}
});
this._scene.add(this._transformControls);
this._transformControls.addEventListener('objectChange', function () {
console.log('object changed!');
});
}
};

Expand Down Expand Up @@ -452,6 +470,13 @@ export class MainView extends React.Component<IProps, IStates> {
}

private _onPointerMove(e: MouseEvent) {
if (this._transforming) {
return;
}

e.preventDefault();
e.stopPropagation();

const rect = this._renderer.domElement.getBoundingClientRect();

this._pointer.x = ((e.clientX - rect.left) / rect.width) * 2 - 1;
Expand Down Expand Up @@ -499,6 +524,13 @@ export class MainView extends React.Component<IProps, IStates> {
}

private _onClick(e: MouseEvent) {
if (this._transforming) {
return;
}

e.preventDefault();
e.stopPropagation();

const selection = this._pick();
const selectedMeshesNames = new Set(
this._selectedMeshes.map(sel => sel.name)
Expand Down Expand Up @@ -535,6 +567,7 @@ export class MainView extends React.Component<IProps, IStates> {
}

private _shapeToMesh = (payload: IDisplayShape['payload']) => {
console.log('shapetomesh!');
if (this._meshGroup !== null) {
this._scene.remove(this._meshGroup);
}
Expand Down Expand Up @@ -615,6 +648,12 @@ export class MainView extends React.Component<IProps, IStates> {
new THREE.Float32BufferAttribute(normals, 3)
);
geometry.computeBoundingBox();

// Get the old center of the object and center its vertices to the scene
const center = new THREE.Vector3();
geometry.boundingBox?.getCenter(center);
geometry.center();

if (vertices.length > 0) {
geometry.computeBoundsTree();
}
Expand All @@ -623,6 +662,7 @@ export class MainView extends React.Component<IProps, IStates> {
mesh.castShadow = true;
mesh.name = objName;
mesh.visible = visible;
mesh.position.copy(center);

if (visible) {
this._boundingGroup.expandByObject(mesh);
Expand All @@ -644,8 +684,19 @@ export class MainView extends React.Component<IProps, IStates> {
);
const edgeGeometry = new THREE.BufferGeometry();
edgeGeometry.setAttribute('position', edgeVertices);
const edgeCenter = new THREE.Vector3();
edgeGeometry.computeBoundingBox();
edgeGeometry.boundingBox?.getCenter(edgeCenter);
edgeGeometry.center();

const edgePosition = new THREE.Vector3();
edgePosition.copy(center);
edgePosition.multiplyScalar(-1);
edgePosition.add(edgeCenter);

const edgesMesh = new THREE.Line(edgeGeometry, edgeMaterial);
edgesMesh.name = 'edge';
edgesMesh.position.copy(edgePosition);

mesh.add(edgesMesh);
});
Expand Down Expand Up @@ -736,6 +787,8 @@ export class MainView extends React.Component<IProps, IStates> {
}

private _updateSelected(names: string[]) {
this._transformControls.detach();

// Reset original color for old selection
for (const selectedMesh of this._selectedMeshes) {
let originalColor = DEFAULT_MESH_COLOR;
Expand Down Expand Up @@ -765,6 +818,10 @@ export class MainView extends React.Component<IProps, IStates> {
this._selectedMeshes.push(selected);
selected.material.color = SELECTED_MESH_COLOR;
}

if (this._selectedMeshes.length === 1) {
this._transformControls.attach(this._selectedMeshes[0]);
}
}

private _onSharedMetadataChanged = (
Expand Down Expand Up @@ -974,43 +1031,37 @@ export class MainView extends React.Component<IProps, IStates> {
}

private _setupExplodedView() {
if (this._explodedView.enabled) {
const center = new THREE.Vector3();
this._boundingGroup.getCenter(center);

this._explodedViewLinesHelperGroup?.removeFromParent();
this._explodedViewLinesHelperGroup = new THREE.Group();

for (const mesh of this._meshGroup?.children as BasicMesh[]) {
const explodedState = this._computeExplodedState(mesh);

mesh.position.set(0, 0, 0);
mesh.translateOnAxis(explodedState.vector, explodedState.distance);

// Draw lines
const material = new THREE.LineBasicMaterial({
color: DEFAULT_EDGE_COLOR,
linewidth: 2
});
const geometry = new THREE.BufferGeometry().setFromPoints([
explodedState.oldGeometryCenter,
explodedState.newGeometryCenter
]);
const line = new THREE.Line(geometry, material);
line.name = mesh.name;
line.visible = mesh.visible;

this._explodedViewLinesHelperGroup.add(line);
}

this._scene.add(this._explodedViewLinesHelperGroup);
} else {
// Exploded view is disabled, we reset the initial positions
for (const mesh of this._meshGroup?.children as BasicMesh[]) {
mesh.position.set(0, 0, 0);
}
this._explodedViewLinesHelperGroup?.removeFromParent();
}
// if (this._explodedView.enabled) {
// const center = new THREE.Vector3();
// this._boundingGroup.getCenter(center);
// this._explodedViewLinesHelperGroup?.removeFromParent();
// this._explodedViewLinesHelperGroup = new THREE.Group();
// for (const mesh of this._meshGroup?.children as BasicMesh[]) {
// const explodedState = this._computeExplodedState(mesh);
// mesh.position.set(0, 0, 0);
// mesh.translateOnAxis(explodedState.vector, explodedState.distance);
// // Draw lines
// const material = new THREE.LineBasicMaterial({
// color: DEFAULT_EDGE_COLOR,
// linewidth: 2
// });
// const geometry = new THREE.BufferGeometry().setFromPoints([
// explodedState.oldGeometryCenter,
// explodedState.newGeometryCenter
// ]);
// const line = new THREE.Line(geometry, material);
// line.name = mesh.name;
// line.visible = mesh.visible;
// this._explodedViewLinesHelperGroup.add(line);
// }
// this._scene.add(this._explodedViewLinesHelperGroup);
// } else {
// // Exploded view is disabled, we reset the initial positions
// for (const mesh of this._meshGroup?.children as BasicMesh[]) {
// mesh.position.set(0, 0, 0);
// }
// this._explodedViewLinesHelperGroup?.removeFromParent();
// }
}

private _computeExplodedState(mesh: BasicMesh) {
Expand Down Expand Up @@ -1173,7 +1224,9 @@ export class MainView extends React.Component<IProps, IStates> {
private _geometry: THREE.BufferGeometry; // Threejs BufferGeometry
private _refLength: number | null = null; // Length of bounding box of current object
private _sceneAxe: THREE.Object3D | null; // Array of X, Y and Z axe
private _controls: OrbitControls; // Threejs control
private _controls: OrbitControls; // Threejs orbit control
private _transformControls: TransformControls; // Threejs transform control
private _transforming = false;
private _pointer3D: IPointer | null = null;
private _collaboratorPointers: IDict<IPointer>;
private _pointerGeometry: THREE.SphereGeometry;
Expand Down
2 changes: 0 additions & 2 deletions packages/jupytercad-extension/src/panelview/objecttree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,6 @@ class ObjectTreeReact extends React.Component<IProps, IStates> {
return;
}

console.log('toggle selected', id);

if (id && id.length > 0) {
const names: string[] = [];
for (const subid of id) {
Expand Down