void CSkelMeshViewer::Draw2D() { CMeshViewer::Draw2D(); if (!Mesh->Lods.Num()) { DrawTextLeft(S_RED "Mesh has no LODs"); return; } CSkelMeshInstance *MeshInst = static_cast<CSkelMeshInstance*>(Inst); const CSkelMeshLod &Lod = Mesh->Lods[MeshInst->LodNum]; if (ShowUV) { DisplayUV(Lod.Verts, sizeof(CSkelMeshVertex), &Lod, MeshInst->UVIndex); } #if UNREAL4 if (Mesh->OriginalMesh->IsA("SkeletalMesh4")) { USkeletalMesh4* Mesh4 = static_cast<USkeletalMesh4*>(Mesh->OriginalMesh); if (Mesh4->Skeleton) DrawTextLeft(S_GREEN"Skeleton: " S_WHITE "%s", Mesh4->Skeleton->Name); } #endif // UNREAL4 // mesh DrawTextLeft(S_GREEN "LOD : " S_WHITE "%d/%d\n" S_GREEN "Verts : " S_WHITE "%d\n" S_GREEN "Tris : " S_WHITE "%d\n" S_GREEN "UV Set : " S_WHITE "%d/%d\n" S_GREEN "Bones : " S_WHITE "%d", MeshInst->LodNum+1, Mesh->Lods.Num(), Lod.NumVerts, Lod.Indices.Num() / 3, MeshInst->UVIndex+1, Lod.NumTexCoords, Mesh->RefSkeleton.Num()); //!! show MaxInfluences etc // materials if (Inst->bColorMaterials) { for (int i = 0; i < Lod.Sections.Num(); i++) PrintMaterialInfo(i, Lod.Sections[i].Material, Lod.Sections[i].NumFaces); DrawTextLeft(""); } // show extra meshes for (int i = 0; i < TaggedMeshes.Num(); i++) DrawTextLeft("%s%d: %s", (TaggedMeshes[i]->pMesh == MeshInst->pMesh) ? S_RED : S_WHITE, i, TaggedMeshes[i]->pMesh->OriginalMesh->Name); // show animation information const CAnimSet *AnimSet = MeshInst->GetAnim(); if (AnimSet) { DrawTextBottomLeft("\n" S_GREEN "AnimSet : " S_WHITE "%s", AnimSet->OriginalAnim->Name); const char *OnOffStatus = NULL; switch (MeshInst->RotationMode) { case EARO_AnimSet: OnOffStatus = (AnimSet->AnimRotationOnly) ? "on" : "off"; break; case EARO_ForceEnabled: OnOffStatus = S_RED "force on"; break; case EARO_ForceDisabled: OnOffStatus = S_RED "force off"; break; } DrawTextBottomLeft(S_GREEN "RotationOnly:" S_WHITE " %s", OnOffStatus); if (AnimSet->UseAnimTranslation.Num() || AnimSet->ForceMeshTranslation.Num()) { DrawTextBottomLeft(S_GREEN "UseAnimBones:" S_WHITE " %d " S_GREEN "ForceMeshBones:" S_WHITE " %d", AnimSet->UseAnimTranslation.Num(), AnimSet->ForceMeshTranslation.Num()); } const CAnimSequence *Seq = MeshInst->GetAnim(0); if (Seq) { DrawTextBottomLeft(S_GREEN "Anim:" S_WHITE " %d/%d (%s) " S_GREEN "Rate:" S_WHITE " %g " S_GREEN "Frames:" S_WHITE " %d", AnimIndex+1, MeshInst->GetAnimCount(), *Seq->Name, Seq->Rate, Seq->NumFrames); DrawTextBottomRight(S_GREEN "Time:" S_WHITE " %4.1f/%d", MeshInst->GetAnimTime(0), Seq->NumFrames); #if ANIM_DEBUG_INFO const FString& DebugText = Seq->DebugInfo; if (DebugText.Num()) DrawTextBottomLeft(S_RED"Info:" S_WHITE " %s", *DebugText); #endif } else { DrawTextBottomLeft(S_GREEN "Anim:" S_WHITE " 0/%d (none)", MeshInst->GetAnimCount()); } } }
void CSkelMeshViewer::ProcessKey(int key) { guard(CSkelMeshViewer::ProcessKey); #if TEST_ANIMS static float Alpha = -1.0f; //!!!! #endif int i; CSkelMeshInstance *MeshInst = static_cast<CSkelMeshInstance*>(Inst); int NumAnims = MeshInst->GetAnimCount(); //?? use Meshes[] instead ... const char *AnimName; float Frame; float NumFrames; float Rate; MeshInst->GetAnimParams(0, AnimName, Frame, NumFrames, Rate); switch (key) { // animation control case '[': case ']': if (NumAnims) { if (key == '[') { if (--AnimIndex < -1) AnimIndex = NumAnims - 1; } else { if (++AnimIndex >= NumAnims) AnimIndex = -1; } // note: AnimIndex changed now AnimName = MeshInst->GetAnimName(AnimIndex); MeshInst->TweenAnim(AnimName, 0.25); // change animation with tweening for (i = 0; i < TaggedMeshes.Num(); i++) TaggedMeshes[i]->TweenAnim(AnimName, 0.25); } break; case ',': // '<' case '.': // '>' if (NumFrames) { if (key == ',') Frame -= 0.2f; else Frame += 0.2f; Frame = bound(Frame, 0, NumFrames-1); MeshInst->FreezeAnimAt(Frame); for (i = 0; i < TaggedMeshes.Num(); i++) TaggedMeshes[i]->FreezeAnimAt(Frame); } break; case ' ': if (AnimIndex >= 0) { MeshInst->PlayAnim(AnimName); for (i = 0; i < TaggedMeshes.Num(); i++) TaggedMeshes[i]->PlayAnim(AnimName); } break; case 'x': if (AnimIndex >= 0) { MeshInst->LoopAnim(AnimName); for (i = 0; i < TaggedMeshes.Num(); i++) TaggedMeshes[i]->LoopAnim(AnimName); } break; // mesh debug output case 'l': if (++MeshInst->LodNum >= Mesh->Lods.Num()) MeshInst->LodNum = 0; break; case 'u': if (++MeshInst->UVIndex >= Mesh->Lods[MeshInst->LodNum].NumTexCoords) MeshInst->UVIndex = 0; break; case 's': if (++ShowSkel > 2) ShowSkel = 0; break; case 'b': ShowLabels = !ShowLabels; break; case 'a': ShowAttach = !ShowAttach; break; case 'i': DrawFlags ^= DF_SHOW_INFLUENCES; break; case 'b'|KEY_CTRL: MeshInst->DumpBones(); break; #if TEST_ANIMS //!! testing, remove later case 'y': if (Alpha >= 0) { Alpha = -1; MeshInst->ClearSkelAnims(); return; } Alpha = 0; MeshInst->LoopAnim("CrouchF", 1, 0, 2); // MeshInst->LoopAnim("WalkF", 1, 0, 2); // MeshInst->LoopAnim("RunR", 1, 0, 2); // MeshInst->LoopAnim("SwimF", 1, 0, 2); MeshInst->SetSecondaryAnim(2, "RunF"); break; case 'y'|KEY_CTRL: MeshInst->SetBlendParams(0, 1.0f, "b_MF_Forearm_R"); // MeshInst->SetBlendParams(0, 1.0f, "b_MF_Hand_R"); // MeshInst->SetBlendParams(0, 1.0f, "b_MF_ForeTwist2_R"); break; case 'c': Alpha -= 0.02; if (Alpha < 0) Alpha = 0; MeshInst->SetSecondaryBlend(2, Alpha); break; case 'v': Alpha += 0.02; if (Alpha > 1) Alpha = 1; MeshInst->SetSecondaryBlend(2, Alpha); break; /* case 'u'|KEY_CTRL: MeshInst->LoopAnim("Gesture_Taunt02", 1, 0, 1); MeshInst->SetBlendParams(1, 1.0f, "Bip01 Spine1"); MeshInst->LoopAnim("WalkF", 1, 0, 2); MeshInst->SetBlendParams(2, 1.0f, "Bip01 R Thigh"); MeshInst->LoopAnim("AssSmack", 1, 0, 4); MeshInst->SetBlendParams(4, 1.0f, "Bip01 L UpperArm"); break; */ #endif // TEST_ANIMS case 'a'|KEY_CTRL: { const CAnimSet *PrevAnim = MeshInst->GetAnim(); // find next animation set (code is similar to PAGEDOWN handler) int looped = 0; int ObjIndex = -1; bool found = (PrevAnim == NULL); // whether previous AnimSet was found; NULL -> any while (true) { ObjIndex++; if (ObjIndex >= UObject::GObjObjects.Num()) { ObjIndex = 0; looped++; if (looped > 1) break; // no other objects } const UObject *Obj = UObject::GObjObjects[ObjIndex]; const CAnimSet *Anim = GetAnimSet(Obj); if (!Anim) continue; if (Anim == PrevAnim) { if (found) break; // loop detected found = true; continue; } if (found && Anim) { // found desired animation set MeshInst->SetAnim(Anim); // will rebind mesh to new animation set for (int i = 0; i < TaggedMeshes.Num(); i++) TaggedMeshes[i]->SetAnim(Anim); AnimIndex = -1; appPrintf("Bound %s'%s' to %s'%s'\n", Object->GetClassName(), Object->Name, Obj->GetClassName(), Obj->Name); break; } } } break; case 't'|KEY_CTRL: TagMesh(MeshInst); break; case 'r'|KEY_CTRL: { int mode = MeshInst->RotationMode + 1; if (mode > EARO_ForceDisabled) mode = 0; MeshInst->RotationMode = (EAnimRotationOnly)mode; for (int i = 0; i < TaggedMeshes.Num(); i++) TaggedMeshes[i]->RotationMode = (EAnimRotationOnly)mode; } break; case 'u'|KEY_CTRL: ShowUV = !ShowUV; break; case 'f': IsFollowingMesh = true; break; default: CMeshViewer::ProcessKey(key); } unguard; }
void CSkelMeshViewer::ProcessKey(int key) { guard(CSkelMeshViewer::ProcessKey); #if TEST_ANIMS static float Alpha = -1.0f; //!!!! #endif int i; CSkelMeshInstance *MeshInst = static_cast<CSkelMeshInstance*>(Inst); int NumAnims = MeshInst->GetAnimCount(); //?? use Meshes[] instead ... const char *AnimName; float Frame; float NumFrames; float Rate; MeshInst->GetAnimParams(0, AnimName, Frame, NumFrames, Rate); switch (key) { // animation control case '[': case ']': if (NumAnims) { if (key == '[') { if (--AnimIndex < -1) AnimIndex = NumAnims - 1; } else { if (++AnimIndex >= NumAnims) AnimIndex = -1; } // note: AnimIndex changed now AnimName = MeshInst->GetAnimName(AnimIndex); MeshInst->TweenAnim(AnimName, 0.25); // change animation with tweening for (i = 0; i < TaggedMeshes.Num(); i++) TaggedMeshes[i]->TweenAnim(AnimName, 0.25); } break; case ',': // '<' case '.': // '>' if (NumFrames) { if (key == ',') Frame -= 0.2f; else Frame += 0.2f; Frame = bound(Frame, 0, NumFrames-1); MeshInst->FreezeAnimAt(Frame); for (i = 0; i < TaggedMeshes.Num(); i++) TaggedMeshes[i]->FreezeAnimAt(Frame); } break; case ' ': if (AnimIndex >= 0) { MeshInst->PlayAnim(AnimName); for (i = 0; i < TaggedMeshes.Num(); i++) TaggedMeshes[i]->PlayAnim(AnimName); } break; case 'x': if (AnimIndex >= 0) { MeshInst->LoopAnim(AnimName); for (i = 0; i < TaggedMeshes.Num(); i++) TaggedMeshes[i]->LoopAnim(AnimName); } break; // mesh debug output case 'l': if (++MeshInst->LodNum >= Mesh->Lods.Num()) MeshInst->LodNum = 0; break; case 'u': if (++MeshInst->UVIndex >= Mesh->Lods[MeshInst->LodNum].NumTexCoords) MeshInst->UVIndex = 0; break; case 's': if (++ShowSkel > 2) ShowSkel = 0; break; case 'b': ShowLabels = !ShowLabels; break; case 'a': ShowAttach = !ShowAttach; break; case 'i': DrawFlags ^= DF_SHOW_INFLUENCES; break; case 'b'|KEY_CTRL: MeshInst->DumpBones(); break; #if TEST_ANIMS //!! testing, remove later case 'y': if (Alpha >= 0) { Alpha = -1; MeshInst->ClearSkelAnims(); return; } Alpha = 0; MeshInst->LoopAnim("CrouchF", 1, 0, 2); // MeshInst->LoopAnim("WalkF", 1, 0, 2); // MeshInst->LoopAnim("RunR", 1, 0, 2); // MeshInst->LoopAnim("SwimF", 1, 0, 2); MeshInst->SetSecondaryAnim(2, "RunF"); break; case 'y'|KEY_CTRL: MeshInst->SetBlendParams(0, 1.0f, "b_MF_Forearm_R"); // MeshInst->SetBlendParams(0, 1.0f, "b_MF_Hand_R"); // MeshInst->SetBlendParams(0, 1.0f, "b_MF_ForeTwist2_R"); break; case 'c': Alpha -= 0.02; if (Alpha < 0) Alpha = 0; MeshInst->SetSecondaryBlend(2, Alpha); break; case 'v': Alpha += 0.02; if (Alpha > 1) Alpha = 1; MeshInst->SetSecondaryBlend(2, Alpha); break; /* case 'u'|KEY_CTRL: MeshInst->LoopAnim("Gesture_Taunt02", 1, 0, 1); MeshInst->SetBlendParams(1, 1.0f, "Bip01 Spine1"); MeshInst->LoopAnim("WalkF", 1, 0, 2); MeshInst->SetBlendParams(2, 1.0f, "Bip01 R Thigh"); MeshInst->LoopAnim("AssSmack", 1, 0, 4); MeshInst->SetBlendParams(4, 1.0f, "Bip01 L UpperArm"); break; */ #endif // TEST_ANIMS case 'a'|KEY_CTRL: AttachAnimSet(); break; case 't'|KEY_CTRL: TagMesh(MeshInst); break; case 'r'|KEY_CTRL: { int mode = MeshInst->RotationMode + 1; if (mode > EARO_ForceDisabled) mode = 0; MeshInst->RotationMode = (EAnimRotationOnly)mode; for (int i = 0; i < TaggedMeshes.Num(); i++) TaggedMeshes[i]->RotationMode = (EAnimRotationOnly)mode; } break; case 'u'|KEY_CTRL: ShowUV = !ShowUV; break; case 'f': IsFollowingMesh = true; break; default: CMeshViewer::ProcessKey(key); } unguard; }