Skip to content

Commit

Permalink
Merge pull request #137 from vircadia/engine
Browse files Browse the repository at this point in the history
Add sitting, clapping, and salute emote actions.
  • Loading branch information
Gigabyte5671 authored Feb 26, 2023
2 parents 2e55e2e + 8b87096 commit 4be1750
Show file tree
Hide file tree
Showing 16 changed files with 649 additions and 302 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/build_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ jobs:
uses: actions/checkout@v2

- uses: actions/setup-node@master
with:
node-version: 16.x

- name: 📥 Install project dependencies
run: npm install
Expand Down
Binary file modified public/assets/AnimationsBasic.glb
Binary file not shown.
6 changes: 2 additions & 4 deletions src/components/overlays/avatar/Avatar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -566,10 +566,8 @@ export default defineComponent({
}
for (let i = 0; i < newAvatarListLength; i++) {
const key = storeModelsList[i][0];
if (key !== fallbackAvatarModel()) { // Don't show the fallback model in the list.
const value = storeModelsList[i][1];
this.avatarList[key] = { avatar: value, showMoreOptions: false };
}
const value = storeModelsList[i][1];
this.avatarList[key] = { avatar: value, showMoreOptions: false };
}
},
async selectAvatar(modelId: string | number, reload?: boolean): Promise<void> {
Expand Down
18 changes: 16 additions & 2 deletions src/layouts/MainLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@
clickable
v-ripple
class="non-selectable"
@click="openUrl(menuItem.link)"
@click="menuItem.action ? menuItem.action() : openUrl(menuItem.link)"
>
<q-item-section avatar dense>
<q-icon :name="menuItem.icon" />
Expand Down Expand Up @@ -509,7 +509,13 @@ import { openURL } from "quasar";
import MainScene from "@Components/MainScene.vue";
import OverlayManager from "@Components/overlays/OverlayManager.vue";

import { Store, Mutations as StoreMutations, Actions as StoreActions, JitsiRoomInfo } from "@Store/index";
import {
Store,
Mutations as StoreMutations,
Actions as StoreActions,
JitsiRoomInfo,
clearStoreAndPersistentStorage
} from "@Store/index";
import { Utility } from "@Modules/utility";
import { Account } from "@Modules/account";
import { AudioMgr } from "@Modules/scene/audio";
Expand Down Expand Up @@ -604,6 +610,14 @@ export default defineComponent({
icon: "support",
label: "User Documentation",
link: "https://docs.vircadia.com/"
},
{
icon: "delete_sweep",
label: "Clear All Settings",
action: () => {
clearStoreAndPersistentStorage();
window.location.reload();
}
}
],
helpMenuState: false,
Expand Down
22 changes: 14 additions & 8 deletions src/modules/avatar/animator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
Mesh
} from "@babylonjs/core";

import { AnimationMap } from "@Modules/avatar/controller/avatarState";


/* eslint-disable @typescript-eslint/no-magic-numbers */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
Expand All @@ -44,12 +46,8 @@ export class Animator {
}, false);

animGroups.forEach((animGroup : AnimationGroup) => {
let loopAnimation = true;
if (animGroup.name === "jumping_temp" || animGroup.name === "sitting_crosslegged"
|| animGroup.name === "jump_standing_land_settle_all" || animGroup.name === "jump_standing_launch_all"
|| animGroup.name === "jump_standing_apex_all") {
loopAnimation = false;
}
const animationLoopData = [...AnimationMap.values()].find((value) => value.name === animGroup.name);
const loopAnimation = animationLoopData?.loop ?? true;
const newAnimGroup = Animator._cloneAnimGroup(animGroup, nodes, loopAnimation);
this._animGroups.set(animGroup.name, newAnimGroup);
});
Expand Down Expand Up @@ -78,8 +76,16 @@ export class Animator {
public update():void {
if (this._nextAnim && this._nextAnim !== this._currentAnim) {
this._prevAnim?.stop();
this._nextAnim.start(this._nextAnim.loopAnimation, 1.0,
this._nextAnim.from, this._nextAnim.to, false);
const animationFramerate = 30;
const engineTimestep = 1000 / this._mesh.getEngine().getTimeStep();
const animLoopData = [...AnimationMap.values()].find((animMapValue) => animMapValue.name === this._nextAnim?.name);
this._nextAnim.start(
this._nextAnim.loopAnimation,
1.0,
animLoopData?.loopStart ? animLoopData.loopStart * (engineTimestep / animationFramerate) : this._nextAnim.from,
animLoopData?.loopEnd ? animLoopData.loopEnd * (engineTimestep / animationFramerate) : this._nextAnim.to,
false
);

this._prevAnim = this._currentAnim;
this._currentAnim = this._nextAnim;
Expand Down
46 changes: 38 additions & 8 deletions src/modules/avatar/controller/avatarState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ export enum State {
Jump,
Fly,
Teleport,
Stop
Stop,
Pose
}

export enum JumpSubState {
Expand All @@ -45,23 +46,52 @@ export enum Action {
Fly,
FlyFast,
Sit,
SitBeanbag,
SitChair,
SitAuditorium,
Clap,
Salute,
RunForward
}

export type AnimationName =
"idle02" | "walk_fwd" | "walk_bwd" | "walk_left" | "walk_right" |
"turn_left" | "turn_right" | "jumping_temp" | "sitting_crosslegged" |
"jump_standing_land_settle_all" | "jump_standing_launch_all" | "jump_standing_apex_all" |
"run_bwd" | "run_fast_fwd" | "run_fast_left" | "run_fast_right" | "fly";
interface AnimationLoopData {
name: string,
loop: boolean,
loopStart?: number,
loopEnd?: number
}

/* eslint-disable no-multi-spaces */
export const AnimationMap = new Map([
[Action.Idle, { name: "idle02", loop: true }],
[Action.WalkForward, { name: "walk_fwd", loop: true }],
[Action.RunForward, { name: "run_fast_fwd", loop: true }],
[Action.WalkBackward, { name: "walk_bwd", loop: true }],
[Action.WalkLeft, { name: "walk_left", loop: true }],
[Action.WalkRight, { name: "walk_right", loop: true }],
[Action.TurnLeft, { name: "turn_left", loop: true }],
[Action.TurnRight, { name: "turn_right", loop: true }],
[Action.Jump, { name: "jump_standing_apex_all", loop: false }],
[Action.Land, { name: "jump_standing_land_settle_all", loop: false }],
[Action.Fly, { name: "fly", loop: true }],
[Action.FlyFast, { name: "fly", loop: true }],
[Action.Sit, { name: "sitting_idle", loop: false }],
[Action.SitBeanbag, { name: "sitting_beanbag", loop: false }],
[Action.SitChair, { name: "sitting_chair", loop: false }],
[Action.SitAuditorium, { name: "sitting_auditorium", loop: false }],
[Action.Clap, { name: "emote_clap01_all", loop: true, loopStart: 17, loopEnd: 111 }],
[Action.Salute, { name: "salute", loop: true, loopStart: 10, loopEnd: 30 }]
]) as Map<Action, AnimationLoopData>;
/* eslint-enable no-multi-spaces */

export class AvatarState {
public walkSpeed = 2.4;
public walkSpeed = 1.8;
public runSpeed = 5.2;
public landSpeed = 4;
public flySpeed = 8; // Flying on the X-Z plane.
public fastFlySpeed = 27;
public ascendSpeed = 0.05; // Flying on the Y axis.
public fastAscendSpeed = 0.1;
public fastAscendSpeed = 0.14;
public currentSpeed = 0;

public rotationSpeed = 40 * Math.PI / 180;
Expand Down
93 changes: 43 additions & 50 deletions src/modules/avatar/controller/inputController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ import {
import { Animator } from "../animator";
import { GameObject, MeshComponent } from "@Modules/object";
import { ScriptComponent, inspector, inspectorAccessor } from "@Modules/script";
import { AvatarState, Action, JumpSubState, State } from "./avatarState";
import { AvatarState, Action, JumpSubState, State, AnimationMap } from "./avatarState";
import { InputState, CameraMode } from "./inputState";
import { IInputHandler } from "./inputs/inputHandler";
import { KeyboardInput } from "./inputs/keyboardInput";
import { VirtualJoystickInput } from "./inputs/virtualJoystickInput";
import { Store } from "@Store/index";
import type { SceneController } from "@Modules/scene/controllers";
import { MouseSettingsController } from "@Base/modules/avatar/controller/inputs/mouseSettings";

// General Modules
Expand Down Expand Up @@ -343,13 +344,26 @@ export class InputController extends ScriptComponent {
this._gameObject as GameObject,
this._animGroups as AnimationGroup[]);

// Jump animation-end handler.
const jumpAnim = this._animator.getAnimationGroup("jump_standing_land_settle_all");
if (jumpAnim) {
jumpAnim.onAnimationGroupEndObservable.add(() => {
this._avatarState.state = State.Idle;
this._avatarState.action = Action.Idle;
});
}
jumpAnim?.onAnimationGroupEndObservable.add(() => {
this._avatarState.state = State.Idle;
this._avatarState.action = Action.Idle;
});

// Clap animation-end handler.
const clapAnim = this._animator.getAnimationGroup("emote_clap01_all");
clapAnim?.onAnimationGroupEndObservable.add(() => {
this._avatarState.state = State.Idle;
this._avatarState.action = Action.Idle;
});

// Salute animation-end handler.
const saluteAnim = this._animator.getAnimationGroup("salute");
saluteAnim?.onAnimationGroupEndObservable.add(() => {
this._avatarState.state = State.Idle;
this._avatarState.action = Action.Idle;
});

this._avatarState.state = State.Idle;
this._avatarState.action = Action.Idle;
Expand Down Expand Up @@ -424,6 +438,9 @@ export class InputController extends ScriptComponent {
case State.Teleport:
this._doTeleport(delta);
break;
case State.Pose:
this._doPose(delta);
break;
case State.Stop:
this._doStop(delta);
break;
Expand Down Expand Up @@ -466,6 +483,19 @@ export class InputController extends ScriptComponent {
}
}

private _doPose(delta : number) {
this._avatarState.duration += delta;
if (this._avatarState.duration > 0.5) {
if (this._avatarState.moveDir.x === 0 && this._avatarState.moveDir.z === 0) {
return;
}
this._avatarState.state = State.Idle;
const sceneManager = this._scene.rootNodes.find((node) => node.id === "SceneManager") as GameObject;
const sceneController = sceneManager.components.get("SceneController") as SceneController | undefined;
sceneController?.applyGravity();
}
}

private _doTeleport(delta : number) {
this._avatarState.duration += delta;
if (this._avatarState.duration > 1) {
Expand Down Expand Up @@ -508,6 +538,10 @@ export class InputController extends ScriptComponent {
this._gameObject.rotationQuaternion.z = 0;
}

const sceneManager = this._scene.rootNodes.find((node) => node.id === "SceneManager") as GameObject;
const sceneController = sceneManager.components.get("SceneController") as SceneController | undefined;
sceneController?.applyGravity();

this._avatarState.duration += delta;

switch (this._avatarState.jumpSubstate) {
Expand Down Expand Up @@ -665,49 +699,8 @@ export class InputController extends ScriptComponent {
return;
}

let anim = "idle02";
switch (this._avatarState.action) {
case Action.WalkForward:
anim = "walk_fwd";
break;
case Action.RunForward:
anim = "run_fast_fwd";
break;
case Action.WalkBackward:
anim = "walk_bwd";
break;
case Action.WalkLeft:
anim = "walk_left";
break;
case Action.WalkRight:
anim = "walk_right";
break;
case Action.TurnLeft:
anim = "turn_left";
break;
case Action.TurnRight:
anim = "turn_right";
break;
case Action.Jump:
anim = "jump_standing_apex_all";
break;
case Action.Land:
anim = "jump_standing_land_settle_all";
break;
case Action.Fly:
anim = "fly";
break;
case Action.FlyFast:
anim = "fly";
break;
case Action.Sit:
anim = "sitting_crosslegged";
break;
default:
anim = "idle02";
}

this._animator.play(anim);
const anim = AnimationMap.get(this._avatarState.action);
this._animator.play(anim?.name ?? "idle02");
this._animator.update();
}

Expand Down
Loading

0 comments on commit 4be1750

Please sign in to comment.