Beispiel #1
0
void CSkelMeshViewer::AttachAnimSet()
{
	guard(CSkelMeshViewer::AttachAnimSet);

	FindUE4Animations();

	CSkelMeshInstance *MeshInst = static_cast<CSkelMeshInstance*>(Inst);

	const CAnimSet *PrevAnim = Anim;
	// 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 *NewAnim = GetAnimSet(Obj);
		if (!NewAnim) continue;

		if (NewAnim == PrevAnim)
		{
			if (found) break;					// loop detected
			found = true;
			continue;
		}

		if (found && NewAnim)
		{
			// found desired animation set
			SetAnim(NewAnim);
			AnimIndex = -1;
			appPrintf("Bound %s'%s' to %s'%s'\n", Object->GetClassName(), Object->Name, Obj->GetClassName(), Obj->Name);
			break;
		}
	}

	unguard;
}
Beispiel #2
0
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;
}
Beispiel #3
0
CSkelMeshViewer::CSkelMeshViewer(CSkeletalMesh* Mesh0, CApplication* Window)
:	CMeshViewer(Mesh0->OriginalMesh, Window)
,	Mesh(Mesh0)
,	AnimIndex(-1)
,	IsFollowingMesh(false)
,	ShowSkel(0)
,	ShowLabels(false)
,	ShowAttach(false)
,	ShowUV(false)
{
	CSkelMeshInstance *SkelInst = new CSkelMeshInstance();
	SkelInst->SetMesh(Mesh);
	if (GForceAnimSet)
	{
		CAnimSet *AttachAnim = GetAnimSet(GForceAnimSet);
		if (!AttachAnim)
		{
			appPrintf("WARNING: specified wrong AnimSet (%s class) object to attach\n", GForceAnimSet->GetClassName());
			GForceAnimSet = NULL;
		}
		if (AttachAnim)
			SkelInst->SetAnim(AttachAnim);
	}
	else if (Mesh->OriginalMesh->IsA("SkeletalMesh"))	// UE2 class
	{
		const USkeletalMesh *OriginalMesh = static_cast<USkeletalMesh*>(Mesh->OriginalMesh);
		if (OriginalMesh->Animation)
			SkelInst->SetAnim(OriginalMesh->Animation->ConvertedAnim);
	}
	Inst = SkelInst;
	// compute bounds for the current mesh
	CVec3 Mins, Maxs;
	if (Mesh0->Lods.Num())
	{
		const CSkelMeshLod &Lod = Mesh0->Lods[0];
		ComputeBounds(&Lod.Verts[0].Position, Lod.NumVerts, sizeof(CSkelMeshVertex), Mins, Maxs);
		// ... transform bounds
		SkelInst->BaseTransformScaled.TransformPointSlow(Mins, Mins);
		SkelInst->BaseTransformScaled.TransformPointSlow(Maxs, Maxs);
	}
	else
	{
		Mins = Maxs = nullVec3;
	}
	// extend bounds with additional meshes
	for (int i = 0; i < TaggedMeshes.Num(); i++)
	{
		CSkelMeshInstance* Inst = TaggedMeshes[i];
		if (Inst->pMesh != SkelInst->pMesh)
		{
			const CSkeletalMesh *Mesh2 = Inst->pMesh;
			// the same code for Inst
			CVec3 Bounds2[2];
			const CSkelMeshLod &Lod2 = Mesh2->Lods[0];
			ComputeBounds(&Lod2.Verts[0].Position, Lod2.NumVerts, sizeof(CSkelMeshVertex), Bounds2[0], Bounds2[1]);
			Inst->BaseTransformScaled.TransformPointSlow(Bounds2[0], Bounds2[0]);
			Inst->BaseTransformScaled.TransformPointSlow(Bounds2[1], Bounds2[1]);
			ComputeBounds(Bounds2, 2, sizeof(CVec3), Mins, Maxs, true);	// include Bounds2 into Mins/Maxs
		}
		// reset animation for all meshes
		TaggedMeshes[i]->TweenAnim(NULL, 0);
	}
	InitViewerPosition(Mins, Maxs);

#if HIGHLIGHT_CURRENT
	TimeSinceCreate = -2;		// ignore first 2 frames: 1st frame will be called after mesh changing, 2nd frame could load textures etc
#endif

#if SHOW_BOUNDS
	appPrintf("Bounds.min = %g %g %g\n", FVECTOR_ARG(Mesh->BoundingBox.Min));
	appPrintf("Bounds.max = %g %g %g\n", FVECTOR_ARG(Mesh->BoundingBox.Max));
	appPrintf("Origin     = %g %g %g\n", FVECTOR_ARG(Mesh->MeshOrigin));
	appPrintf("Sphere     = %g %g %g R=%g\n", FVECTOR_ARG(Mesh->BoundingSphere), Mesh->BoundingSphere.R);
	appPrintf("Offset     = %g %g %g\n", VECTOR_ARG(offset));
#endif // SHOW_BOUNDS
}