trois
trois copied to clipboard
TransformControls directive
One of the most time-consuming parts of creating a new scene from scratch is placing items in the scene, so I'd love to add in an optional directive (v-transform-control
or similar) to allow easy placement, rotation, scaling, and copying items directly from the scene using TransformControls. I'll take a look at this when I have some more time - let me know if there are any other features you'd like to see!
I was looking around for transformcontrols and found none that I could see. So I work on it and It took a while as there no select object add but mesh to move around the transform control handler. Well it can be convert to other format. Had to dig into the code to see how the component work in troisjs.
Added way to search using the scene uuid search and assign the transform control. It a lot testing to see if the script worked.
<script setup>
import { TransformControls } from 'three/examples/jsm/controls/TransformControls';
import {RendererInjectionKey, SceneInjectionKey, Mesh } from 'troisjs';
import { inject, onMounted, onUnmounted, ref, watch } from 'vue';
const props = defineProps({
selectObjectID:String
})
const emit = defineEmits(['updateTransform']);
const renderer = inject(RendererInjectionKey);
const scene = inject(SceneInjectionKey);
//watch props changes params
watch(props,()=>{
if(props.selectObjectID){
let obj3d = scene.getObjectByProperty('uuid',props.selectObjectID)
if(obj3d){
transControls.attach(obj3d);
}else{
transControls.detach();
}
}
})
const transformControls = ref();
const refBox = ref();
let transControls;
function detectTransformHandle ( event ) {
//console.log(event);
//console.log(renderer.three.cameraCtrl)//okay
renderer.three.cameraCtrl.enabled = !event.value;
if(event.value==false){
emit('updateTransform',transformControls.value.mode)
}
}
//does not work as renderer is not setup yet
onMounted(() => {
transControls = new TransformControls(renderer.three.camera, renderer.three.renderer.domElement)
transformControls.value = transControls;
transformControls.value.addEventListener('dragging-changed', detectTransformHandle);
transControls.attach( refBox.value.mesh );
scene.add(transControls)
//scene.add(transformControls.value) //nope, error proxy
window.addEventListener( 'keydown', controlTransform);
})
onUnmounted(() =>{
transControls.detach();
scene.remove(transControls)
transformControls.value.removeEventListener( 'keydown', detectTransformHandle);
window.removeEventListener( 'keydown', controlTransform);
});
function controlTransform(e){
console.log(e.code)
switch ( e.code ) {
case 'KeyQ': //
transformControls.value.setSpace( transformControls.value.space === 'local' ? 'world' : 'local' );
break;
case 'KeyW': // W
transformControls.value.setMode( 'translate' );
break;
case 'KeyE': // E
transformControls.value.setMode( 'rotate' );
break;
case 'KeyR': // R
transformControls.value.setMode( 'scale' );
break;
case 'NumpadSubtract': //
transformControls.value.setSize( Math.max( transformControls.value.size - 0.1, 0.1 ) );
break;
case 'NumpadAdd': //
transformControls.value.setSize( transformControls.value.size + 0.1 );
break;
case 'Space': //
transformControls.value.enabled = ! transformControls.value.enabled;
break;
case 'Escape': // Esc
transformControls.value.reset();
break;
}
}
</script>
<template>
<Mesh ref="refBox"/>
</template>
Example.
const renderer = ref();
function updateTransform(mode){
//let obj3d = renderer.value.scene.getObjectByProperty('uuid',selectObjectUUID.value)
if(mode == "translate"){//position
}
if(mode == "rotate"){
}
if(mode == "scale"){
}
}
<EntityTransformControl :selectObjectID="selectObjectUUID" @update-transform="updateTransform"/>
Added the event for transformcontrol event for object update.