Skip to content

Commit

Permalink
Merge pull request #35 from M3-org/enable-disable-mouse-look
Browse files Browse the repository at this point in the history
Enable disable mouse look
  • Loading branch information
madjin authored Oct 18, 2023
2 parents 9635dea + 26e7228 commit cada918
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 19 deletions.
2 changes: 1 addition & 1 deletion src/components/Editor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export default function Editor({confirmDialog,animationManager, blinkManager, lo
</div>
</div>
<Selector confirmDialog = {confirmDialog} animationManager={animationManager} templateInfo={templateInfo} blinkManager = {blinkManager} lookatManager = {lookatManager} effectManager = {effectManager}/>
<TraitInformation currentVRM={currentVRM} animationManager={animationManager}/>
<TraitInformation currentVRM={currentVRM} animationManager={animationManager} lookatManager={lookatManager}/>
</Fragment>
)
}
27 changes: 26 additions & 1 deletion src/components/TraitInformation.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { SceneContext } from "../context/SceneContext";
import Slider from "./Slider";
import { cullHiddenMeshes } from "../library/utils";

export default function TraitInformation({currentVRM, animationManager}){
export default function TraitInformation({currentVRM, animationManager, lookatManager}){
const {
displayTraitOption,
avatar
Expand All @@ -15,6 +15,7 @@ export default function TraitInformation({currentVRM, animationManager}){
const [cullInDistance, setCullInDistance] = useState(0);
const [cullLayer, setCullLayer] = useState(0);
const [animationName, setAnimationName] = useState(animationManager.getCurrentAnimationName());
const [hasMouseLook, setHasMouseLook] = useState(lookatManager.enabled);

useEffect(() => {
if (currentVRM != null){
Expand Down Expand Up @@ -47,6 +48,7 @@ export default function TraitInformation({currentVRM, animationManager}){
};

const handleCullLayerChange = (event) => {
console.log(lookatManager.enabled);
if (currentVRM?.data){
setCullLayer(event.target.value);
currentVRM.data.cullingLayer = event.target.value;
Expand All @@ -62,6 +64,12 @@ export default function TraitInformation({currentVRM, animationManager}){
await animationManager.loadPreviousAnimation();
setAnimationName(animationManager.getCurrentAnimationName());
}
const handleMouseLookEnable = (event) => {
setHasMouseLook(event.target.checked);
lookatManager.setActive(event.target.checked);
animationManager.enableMouseLook(event.target.checked);
// Perform any additional actions or logic based on the checkbox state change
};

return (
displayTraitOption != null ? (
Expand Down Expand Up @@ -131,6 +139,23 @@ export default function TraitInformation({currentVRM, animationManager}){
onClick={nextAnimation}
></div>
</div>
<div className={styles["traitInfoText"]}>
<div className={styles["checkboxHolder"]}>
<div>

Mouse Follow
</div>
<label className={styles["custom-checkbox"]}>
<input
type="checkbox"
checked={hasMouseLook}
onChange={handleMouseLookEnable}
/>
<div className={styles["checkbox-container"]}></div>
</label>
</div>
</div>

</div>

</div>
Expand Down
41 changes: 41 additions & 0 deletions src/components/TraitInformation.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,45 @@

.anim-button:hover {
opacity: 1;
}

/* Hide the default checkbox */
.custom-checkbox input[type="checkbox"] {
display: none;
}

/* Style the custom checkbox */
.custom-checkbox .checkbox-container {
display: inline-block;
width: 20px;
height: 20px;
border: 2px solid #284b39; /* Change border color as needed */
border-radius: 5px;
cursor: pointer;
}

.custom-checkbox .checkbox-container.checked {
background-color: #5eb086; /* Change background color when checked */
}

.custom-checkbox .checkbox-container .checkmark {
display: none;
}

/* Style the checkmark when the checkbox is checked */
.custom-checkbox input[type="checkbox"]:checked + .checkbox-container {
background-color: #5eb086; /* Change background color when checked */
}

.custom-checkbox input[type="checkbox"]:checked + .checkbox-container .checkmark {
display: block;
}

.checkboxHolder {
display: flex;
gap: 30px;
align-items: center;
justify-content: center;
align-content: center;
height: 40px;
}
85 changes: 71 additions & 14 deletions src/library/animationManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ class AnimationControl {
this.vrm = vrm;
this.animationManager = null;
this.animationManager = animationManager;
this.mixamoModel = null;

this.fadeOutActions = null;
this.newAnimationWeight = 1;

this.neckBone = vrm?.humanoid?.humanBones?.neck;
this.spineBone = vrm?.humanoid?.humanBones?.spine;


this.setAnimations(animations);

Expand All @@ -42,27 +50,72 @@ class AnimationControl {
this.actions[curIdx].time = animationManager.getToActionTime();
this.actions[curIdx].play();
}
setAnimations(animations, mixamoModel){
this.mixer.stopAllAction();

setMouseLookEnabled(mouseLookEnabled){
this.setAnimations(this.animations, this.mixamoModel, mouseLookEnabled);
}

setAnimations(animations, mixamoModel, mouseLookEnabled = null){
mouseLookEnabled = mouseLookEnabled == null ? this.animationManager.mouseLookEnabled : mouseLookEnabled;
this.animations = animations;
//this.mixer.stopAllAction();
if (mixamoModel != null){
if (this.vrm != null)
animations = [getMixamoAnimation(animations, mixamoModel , this.vrm)]
// modify animations
}
animations[0].tracks.map((track, index) => {
if(track.name === "neck.quaternion" || track.name === "spine.quaternion"){
animations[0].tracks.splice(index, 1)
if (this.vrm != null){
const mixamoAnimation = getMixamoAnimation(animations, mixamoModel , this.vrm);
if (mixamoAnimation){
animations = [mixamoAnimation]
this.mixamoModel = mixamoModel;
}
}
})
} else{
const cloneAnims = [];
animations.forEach(animation => {
cloneAnims.push(animation.clone());
});
animations = cloneAnims;
}
// modify animations
if (mouseLookEnabled){
animations[0].tracks.map((track, index) => {
if(track.name === "neck.quaternion" || track.name === "spine.quaternion"){
animations[0].tracks.splice(index, 1)
}
})
}

this.fadeOutActions = this.actions;

this.actions = [];
this.newAnimationWeight = 0;
for (let i =0; i < animations.length;i++){
this.actions.push(this.mixer.clipAction(animations[i]));
}
this.actions[0].weight = 0;
this.actions[0].play();
}

update(weightIn,weightOut){
if (this.fadeOutActions != null){
this.newAnimationWeight += 1/5;
this.fadeOutActions.forEach(action => {
action.weight = 1 - this.newAnimationWeight;
});

if (this.newAnimationWeight >= 1){
this.newAnimationWeight = 1;
this.fadeOutActions.forEach(action => {
action.weight = 0;
action.stop();
});
this.fadeOutActions = null;
}

this.actions.forEach(action => {
action.weight = this.newAnimationWeight;
});

}

if (this.from != null) {
this.from.weight = weightOut;
}
Expand Down Expand Up @@ -106,6 +159,7 @@ export class AnimationManager{
this.curAnimID = 0;
this.animationControls = [];
this.started = false;
this.mouseLookEnabled = true;

this.mixamoModel = null;
this.mixamoAnimations = null;
Expand All @@ -122,14 +176,17 @@ export class AnimationManager{
}, 1000/30);
}


enableMouseLook(enable){
this.mouseLookEnabled = enable;
this.animationControls.forEach(animControls => {
animControls.setMouseLookEnabled(enable);
});
}

async loadAnimation(paths, isfbx = true, pathBase = "", name = ""){
console.log(paths)
const path = pathBase + (pathBase != "" ? "/":"") + getAsArray(paths)[0];
name = name == "" ? getFileNameWithoutExtension(path) : name;
this.currentAnimationName = name;
console.log(this.currentAnimationName);
const loader = isfbx ? fbxLoader : gltfLoader;
const animationModel = await loader.loadAsync(path);
// if we have mixamo animations store the model
Expand All @@ -153,7 +210,7 @@ export class AnimationManager{
else{
//cons
this.animationControls.forEach(animationControl => {
animationControl.setAnimations(animationModel.animations, this.mixamoModel)
animationControl.setAnimations(animationModel.animations, this.mixamoModel, this.mouseLookEnabled)
});
}

Expand Down
4 changes: 2 additions & 2 deletions src/library/loadMixamoAnimation.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import { VRMRigMapMixamo } from './VRMRigMapMixamo.js';
*/
export function getMixamoAnimation( animations, model, vrm ) {
const clip = THREE.AnimationClip.findByName( animations, 'mixamo.com' ); // extract the AnimationClip

if (clip == null)
return null;
const tracks = []; // KeyframeTracks compatible with VRM will be added here

const restRotationInverse = new THREE.Quaternion();
Expand All @@ -24,7 +25,6 @@ export function getMixamoAnimation( animations, model, vrm ) {
const vrmRootY = vrm.scene.getWorldPosition( _vec3 ).y;
const vrmHipsHeight = Math.abs( vrmHipsY - vrmRootY );
const hipsPositionScale = vrmHipsHeight / motionHipsHeight;

clip.tracks.forEach( ( origTrack ) => {
const track = origTrack.clone();
// Convert each tracks for VRM use, and push to `tracks`
Expand Down
6 changes: 5 additions & 1 deletion src/library/lookatManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export class LookAtManager {
this.leftEyeBones = []
this.rightEyesBones = []
this.curMousePos = new THREE.Vector2()
this.enabled = true;

this.hotzoneSection = getHotzoneSection()
this.enabled = true
Expand Down Expand Up @@ -56,6 +57,9 @@ export class LookAtManager {
// this.update();
// }, 1000/60);
}
setActive(active){
this.enabled = active;
}
setCamera(camera){
this.camera = camera
}
Expand Down Expand Up @@ -127,7 +131,7 @@ export class LookAtManager {
const cameraRotationThreshold = localVector.z > 0.; // if camera rotation is not larger than 90
if (this.curMousePos.x > this.hotzoneSection.xStart && this.curMousePos.x < this.hotzoneSection.xEnd &&
this.curMousePos.y > this.hotzoneSection.yStart && this.curMousePos.y < this.hotzoneSection.yEnd &&
cameraRotationThreshold) {
cameraRotationThreshold && this.enabled) {
this.neckBones.forEach(neck => {
this._moveJoint(neck, this.maxLookPercent.neck)
})
Expand Down

0 comments on commit cada918

Please sign in to comment.