Provide a place in the advanced avatar section of preferences in which users can specify a different animation graph spec.

Takes effect when you save (if you have enabled the anim graph under developer->avatar).
An empty string gives you the default behavior.
This commit is contained in:
Howard Stearns 2015-09-21 10:26:04 -07:00
parent 4fadf986e4
commit 8b701b8a5b
5 changed files with 668 additions and 2 deletions

View file

@ -0,0 +1,587 @@
{
"version": "1.0",
"root": {
"id": "ikOverlay",
"type": "overlay",
"data": {
"alpha": 1.0,
"boneSet": "fullBody"
},
"children": [
{
"id": "ik",
"type": "inverseKinematics",
"data": {
"targets": [
{
"jointName": "RightHand",
"positionVar": "rightHandPosition",
"rotationVar": "rightHandRotation"
},
{
"jointName": "LeftHand",
"positionVar": "leftHandPosition",
"rotationVar": "leftHandRotation"
},
{
"jointName": "Head",
"positionVar": "headPosition",
"rotationVar": "headRotation"
}
]
},
"children": []
},
{
"id": "manipulatorOverlay",
"type": "overlay",
"data": {
"alpha": 1.0,
"boneSet": "spineOnly"
},
"children": [
{
"id": "spineLean",
"type": "manipulator",
"data": {
"alpha": 1.0,
"joints": [
{ "var": "lean", "jointName": "Spine" }
]
},
"children": []
},
{
"id": "rightHandOverlay",
"type": "overlay",
"data": {
"alpha": 1.0,
"boneSet": "rightHand",
"alphaVar": "rightHandOverlayAlpha"
},
"children": [
{
"id": "rightHandStateMachine",
"type": "stateMachine",
"data": {
"currentState": "rightHandIdle",
"states": [
{
"id": "rightHandIdle",
"interpTarget": 3,
"interpDuration": 3,
"transitions": [
{ "var": "isRightHandPoint", "state": "rightHandPointIntro" },
{ "var": "isRightHandGrab", "state": "rightHandGrab" }
]
},
{
"id": "rightHandPointIntro",
"interpTarget": 3,
"interpDuration": 3,
"transitions": [
{ "var": "isRightHandIdle", "state": "rightHandIdle" },
{ "var": "isRightHandPointIntroOnDone", "state": "rightHandPointHold" },
{ "var": "isRightHandGrab", "state": "rightHandGrab" }
]
},
{
"id": "rightHandPointHold",
"interpTarget": 3,
"interpDuration": 3,
"transitions": [
{ "var": "isRightHandIdle", "state": "rightHandPointOutro" },
{ "var": "isRightHandGrab", "state": "rightHandGrab" }
]
},
{
"id": "rightHandPointOutro",
"interpTarget": 3,
"interpDuration": 3,
"transitions": [
{ "var": "isRightHandPointOutroOnDone", "state": "rightHandIdle" },
{ "var": "isRightHandGrab", "state": "rightHandGrab" },
{ "var": "isRightHandPoint", "state": "rightHandPointHold" }
]
},
{
"id": "rightHandGrab",
"interpTarget": 3,
"interpDuration": 3,
"transitions": [
{ "var": "isRightHandIdle", "state": "rightHandIdle" },
{ "var": "isRightHandPoint_DISABLED", "state": "rightHandPointHold" }
]
}
]
},
"children": [
{
"id": "rightHandIdle",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_right_hand.fbx",
"startFrame": 0.0,
"endFrame": 0.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
},
{
"id": "rightHandPointHold",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_right_hand.fbx",
"startFrame": 12.0,
"endFrame": 12.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
},
{
"id": "rightHandPointIntro",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_right_hand.fbx",
"startFrame": 0.0,
"endFrame": 12.0,
"timeScale": 1.0,
"loopFlag": false
},
"children": []
},
{
"id": "rightHandPointOutro",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_right_hand.fbx",
"startFrame": 0.0,
"endFrame": 65.0,
"timeScale": 1.0,
"loopFlag": false
},
"children": []
},
{
"id": "rightHandGrab",
"type": "blendLinear",
"data": {
"alpha": 0.0,
"alphaVar": "rightHandGrabBlend"
},
"children": [
{
"id": "rightHandOpen",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_right_hand.fbx",
"startFrame": 0.0,
"endFrame": 0.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
},
{
"id": "rightHandClose",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/squeeze_hands/right_hand_anim.fbx",
"startFrame": 15.0,
"endFrame": 15.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
}
]
}
]
},
{
"id": "leftHandOverlay",
"type": "overlay",
"data": {
"alpha": 1.0,
"boneSet": "leftHand",
"alphaVar" : "leftHandOverlay"
},
"children": [
{
"id": "leftHandStateMachine",
"type": "stateMachine",
"data": {
"currentState": "leftHandIdle",
"states": [
{
"id": "leftHandIdle",
"interpTarget": 3,
"interpDuration": 3,
"transitions": [
{ "var": "isLeftHandPoint", "state": "leftHandPointIntro" },
{ "var": "isLeftHandGrab", "state": "leftHandGrab" }
]
},
{
"id": "leftHandPointIntro",
"interpTarget": 3,
"interpDuration": 3,
"transitions": [
{ "var": "isLeftHandIdle", "state": "leftHandIdle" },
{ "var": "isLeftHandPointIntroOnDone", "state": "leftHandPointHold" },
{ "var": "isLeftHandGrab", "state": "leftHandGrab" }
]
},
{
"id": "leftHandPointHold",
"interpTarget": 3,
"interpDuration": 3,
"transitions": [
{ "var": "isLeftHandIdle", "state": "leftHandPointOutro" },
{ "var": "isLeftHandGrab", "state": "leftHandGrab" }
]
},
{
"id": "leftHandPointOutro",
"interpTarget": 3,
"interpDuration": 3,
"transitions": [
{ "var": "isLeftHandPointOutroOnDone", "state": "leftHandIdle" },
{ "var": "isLeftHandGrab", "state": "leftHandGrab" },
{ "var": "isLeftHandPoint", "state": "leftHandPointHold" }
]
},
{
"id": "leftHandGrab",
"interpTarget": 3,
"interpDuration": 3,
"transitions": [
{ "var": "isLeftHandIdle", "state": "leftHandIdle" },
{ "var": "isLeftHandPoint_DISABLED", "state": "leftHandPointHold" }
]
}
]
},
"children": [
{
"id": "leftHandIdle",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_left_hand.fbx",
"startFrame": 0.0,
"endFrame": 0.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
},
{
"id": "leftHandPointHold",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_left_hand.fbx",
"startFrame": 12.0,
"endFrame": 12.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
},
{
"id": "leftHandPointIntro",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_left_hand.fbx",
"startFrame": 0.0,
"endFrame": 12.0,
"timeScale": 1.0,
"loopFlag": false
},
"children": []
},
{
"id": "leftHandPointOutro",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_left_hand.fbx",
"startFrame": 0.0,
"endFrame": 65.0,
"timeScale": 1.0,
"loopFlag": false
},
"children": []
},
{
"id": "leftHandGrab",
"type": "blendLinear",
"data": {
"alpha": 0.0,
"alphaVar": "leftHandGrabBlend"
},
"children": [
{
"id": "leftHandOpen",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/hand_anims/point_left_hand.fbx",
"startFrame": 0.0,
"endFrame": 0.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
},
{
"id": "leftHandClose",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/squeeze_hands/left_hand_anim.fbx",
"startFrame": 15.0,
"endFrame": 15.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
}
]
}
]
},
{
"id": "mainStateMachine",
"type": "stateMachine",
"data": {
"currentState": "idle",
"states": [
{
"id": "idle",
"interpTarget": 6,
"interpDuration": 6,
"transitions": [
{ "var": "isMovingForward", "state": "walkFwd" },
{ "var": "isMovingBackward", "state": "walkBwd" },
{ "var": "isMovingRight", "state": "strafeRight" },
{ "var": "isMovingLeft", "state": "strafeLeft" },
{ "var": "isTurningRight", "state": "turnRight" },
{ "var": "isTurningLeft", "state": "turnLeft" }
]
},
{
"id": "walkFwd",
"interpTarget": 6,
"interpDuration": 6,
"transitions": [
{ "var": "isNotMoving", "state": "idle" },
{ "var": "isMovingBackward", "state": "walkBwd" },
{ "var": "isMovingRight", "state": "strafeRight" },
{ "var": "isMovingLeft", "state": "strafeLeft" },
{ "var": "isTurningRight", "state": "turnRight" },
{ "var": "isTurningLeft", "state": "turnLeft" }
]
},
{
"id": "walkBwd",
"interpTarget": 6,
"interpDuration": 6,
"transitions": [
{ "var": "isNotMoving", "state": "idle" },
{ "var": "isMovingForward", "state": "walkFwd" },
{ "var": "isMovingRight", "state": "strafeRight" },
{ "var": "isMovingLeft", "state": "strafeLeft" },
{ "var": "isTurningRight", "state": "turnRight" },
{ "var": "isTurningLeft", "state": "turnLeft" }
]
},
{
"id": "strafeRight",
"interpTarget": 6,
"interpDuration": 6,
"transitions": [
{ "var": "isNotMoving", "state": "idle" },
{ "var": "isMovingForward", "state": "walkFwd" },
{ "var": "isMovingBackward", "state": "walkBwd" },
{ "var": "isMovingLeft", "state": "strafeLeft" },
{ "var": "isTurningRight", "state": "turnRight" },
{ "var": "isTurningLeft", "state": "turnLeft" }
]
},
{
"id": "strafeLeft",
"interpTarget": 6,
"interpDuration": 6,
"transitions": [
{ "var": "isNotMoving", "state": "idle" },
{ "var": "isMovingForward", "state": "walkFwd" },
{ "var": "isMovingBackward", "state": "walkBwd" },
{ "var": "isMovingRight", "state": "strafeRight" },
{ "var": "isTurningRight", "state": "turnRight" },
{ "var": "isTurningLeft", "state": "turnLeft" }
]
},
{
"id": "turnRight",
"interpTarget": 6,
"interpDuration": 6,
"transitions": [
{ "var": "isNotTurning", "state": "idle" },
{ "var": "isMovingForward", "state": "walkFwd" },
{ "var": "isMovingBackward", "state": "walkBwd" },
{ "var": "isMovingRight", "state": "strafeRight" },
{ "var": "isMovingLeft", "state": "strafeLeft" },
{ "var": "isTurningLeft", "state": "turnLeft" }
]
},
{
"id": "turnLeft",
"interpTarget": 6,
"interpDuration": 6,
"transitions": [
{ "var": "isNotTurning", "state": "idle" },
{ "var": "isMovingForward", "state": "walkFwd" },
{ "var": "isMovingBackward", "state": "walkBwd" },
{ "var": "isMovingRight", "state": "strafeRight" },
{ "var": "isMovingLeft", "state": "strafeLeft" },
{ "var": "isTurningRight", "state": "turnRight" }
]
}
]
},
"children": [
{
"id": "idle",
"type": "stateMachine",
"data": {
"currentState": "idleStand",
"states": [
{
"id": "idleStand",
"interpTarget": 6,
"interpDuration": 6,
"transitions": [
{ "var": "isTalking", "state": "idleTalk" }
]
},
{
"id": "idleTalk",
"interpTarget": 6,
"interpDuration": 6,
"transitions": [
{ "var": "notIsTalking", "state": "idleStand" }
]
}
]
},
"children": [
{
"id": "idleStand",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/idle.fbx",
"startFrame": 0.0,
"endFrame": 90.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
},
{
"id": "idleTalk",
"type": "clip",
"data": {
"url": "http://hifi-public.s3.amazonaws.com/ozan/anim/talk/talk.fbx",
"startFrame": 0.0,
"endFrame": 801.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
}
]
},
{
"id": "walkFwd",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_fwd.fbx",
"startFrame": 0.0,
"endFrame": 35.0,
"timeScale": 1.0,
"loopFlag": true,
"timeScaleVar": "walkTimeScale"
},
"children": []
},
{
"id": "walkBwd",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_bwd.fbx",
"startFrame": 0.0,
"endFrame": 37.0,
"timeScale": 1.0,
"loopFlag": true,
"timeScaleVar": "walkTimeScale"
},
"children": []
},
{
"id": "turnLeft",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/turn_left.fbx",
"startFrame": 0.0,
"endFrame": 28.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
},
{
"id": "turnRight",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/turn_right.fbx",
"startFrame": 0.0,
"endFrame": 30.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
},
{
"id": "strafeLeft",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/strafe_left.fbx",
"startFrame": 0.0,
"endFrame": 31.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
},
{
"id": "strafeRight",
"type": "clip",
"data": {
"url": "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/strafe_right.fbx",
"startFrame": 0.0,
"endFrame": 31.0,
"timeScale": 1.0,
"loopFlag": true
},
"children": []
}
]
}
]
}
]
}
]
}
]
}
}

View file

@ -1305,7 +1305,9 @@ void MyAvatar::initAnimGraph() {
// or run a local web-server
// python -m SimpleHTTPServer&
//auto graphUrl = QUrl("http://localhost:8000/avatar.json");
auto graphUrl = QUrl("https://gist.githubusercontent.com/hyperlogic/d951c78532e7a20557ad/raw/8275a99a859bbb9b42530c1c7ebfd024e63ba250/ik-avatar-hands-idle.json");
auto graphUrl = QUrl(_animGraphUrl.isEmpty() ?
QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_full/avatar-animation.json") :
_animGraphUrl);
_rig->initAnimGraph(graphUrl, _skeletonModel.getGeometry()->getFBXGeometry());
}

View file

@ -195,10 +195,12 @@ public slots:
bool getEnableRigAnimations() const { return _rig->getEnableRig(); }
void setEnableRigAnimations(bool isEnabled);
bool getEnableAnimGraph() const { return _rig->getEnableAnimGraph(); }
const QString& getAnimGraphUrl() const { return _animGraphUrl; }
void setEnableAnimGraph(bool isEnabled);
void setEnableDebugDrawBindPose(bool isEnabled);
void setEnableDebugDrawAnimPose(bool isEnabled);
void setEnableMeshVisible(bool isEnabled);
void setAnimGraphUrl(const QString& url) { _animGraphUrl = url; }
signals:
void transformChanged();
@ -298,6 +300,7 @@ private:
// Avatar Preferences
QUrl _fullAvatarURLFromPreferences;
QString _fullAvatarModelName;
QString _animGraphUrl {""};
// cache of the current HMD sensor position and orientation
// in sensor space.

View file

@ -190,6 +190,7 @@ void PreferencesDialog::loadPreferences() {
ui.leanScaleSpin->setValue(myAvatar->getLeanScale());
ui.avatarScaleSpin->setValue(myAvatar->getScale());
ui.avatarAnimationEdit->setText(myAvatar->getAnimGraphUrl());
ui.maxOctreePPSSpin->setValue(qApp->getMaxOctreePacketsPerSecond());
@ -248,7 +249,15 @@ void PreferencesDialog::savePreferences() {
myAvatar->getHead()->setPupilDilation(ui.pupilDilationSlider->value() / (float)ui.pupilDilationSlider->maximum());
myAvatar->setLeanScale(ui.leanScaleSpin->value());
myAvatar->setClampedTargetScale(ui.avatarScaleSpin->value());
if (myAvatar->getAnimGraphUrl() != ui.avatarAnimationEdit->text()) { // If changed, destroy the old and start with the new
bool isEnabled = myAvatar->getEnableAnimGraph();
myAvatar->setEnableAnimGraph(false);
myAvatar->setAnimGraphUrl(ui.avatarAnimationEdit->text());
if (isEnabled) {
myAvatar->setEnableAnimGraph(true);
}
}
DependencyManager::get<AvatarManager>()->getMyAvatar()->setRealWorldFieldOfView(ui.realWorldFieldOfViewSpin->value());
qApp->setFieldOfView(ui.fieldOfViewSpin->value());

View file

@ -1587,6 +1587,71 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_anim">
<property name="spacing">
<number>0</number>
</property>
<property name="topMargin">
<number>7</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>7</number>
</property>
<item>
<widget class="QLabel" name="label_anim">
<property name="font">
<font>
<family>Arial</family>
</font>
</property>
<property name="text">
<string>Avatar Animation JSON</string>
</property>
<property name="buddy">
<cstring>avatarAnimationEdit</cstring>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_anim">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>5</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLineEdit" name="avatarAnimationEdit">
<property name="font">
<font>
<family>Arial</family>
</font>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="placeholderText">
<string>default</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_9">
<property name="orientation">