Added new pose to blend with the animation

This commit is contained in:
bernatx 2021-10-29 00:08:30 +02:00 committed by bernat
parent b7a1685166
commit 4284ebb0e1
13 changed files with 372 additions and 200 deletions

View File

@ -18,17 +18,25 @@ namespace client {
}
}
void Walker::ApplyControl(const BoneControlIn &bone_control) {
GetEpisode().Lock()->ApplyBoneControlToWalker(*this, bone_control);
}
Walker::Control Walker::GetWalkerControl() const {
return GetEpisode().Lock()->GetActorSnapshot(*this).state.walker_control;
}
// Walker::Control Walker::GetBonesTransform() const {
Walker::BoneControlOut Walker::GetBonesTransform() {
return GetEpisode().Lock()->GetBonesTransform(*this);
}
void Walker::SetBonesTransform(const Walker::BoneControlIn &bones) {
return GetEpisode().Lock()->SetBonesTransform(*this, bones);
}
void Walker::BlendPose(float blend) {
return GetEpisode().Lock()->BlendPose(*this, blend);
}
void Walker::GetPoseFromAnimation() {
return GetEpisode().Lock()->GetPoseFromAnimation(*this);
}
} // namespace client
} // namespace carla

View File

@ -26,16 +26,18 @@ namespace client {
/// Apply @a control to this Walker.
void ApplyControl(const Control &control);
void ApplyControl(const BoneControlIn &bone_control);
/// Return the control last applied to this Walker.
///
/// @note This function does not call the simulator, it returns the Control
/// received in the last tick.
Control GetWalkerControl() const;
// Walker::Control GetBonesTransform() const;
BoneControlOut GetBonesTransform();
void SetBonesTransform(const BoneControlIn &bones);
void BlendPose(float blend);
void ShowPose() { BlendPose(1.0f); };
void HidePose() { BlendPose(0.0f); };
void GetPoseFromAnimation();
private:

View File

@ -436,15 +436,23 @@ namespace detail {
_pimpl->AsyncCall("apply_control_to_walker", walker, control);
}
void Client::ApplyBoneControlToWalker(rpc::ActorId walker, const rpc::WalkerBoneControlIn &control) {
_pimpl->AsyncCall("apply_bone_control_to_walker", walker, control);
}
rpc::WalkerBoneControlOut Client::GetBonesTransform(rpc::ActorId walker) {
auto res = _pimpl->CallAndWait<rpc::WalkerBoneControlOut>("get_bones_transform", walker);
return res;
}
void Client::SetBonesTransform(rpc::ActorId walker, const rpc::WalkerBoneControlIn &bones) {
_pimpl->AsyncCall("set_bones_transform", walker, bones);
}
void Client::BlendPose(rpc::ActorId walker, float blend) {
_pimpl->AsyncCall("blend_pose", walker, blend);
}
void Client::GetPoseFromAnimation(rpc::ActorId walker) {
_pimpl->AsyncCall("get_pose_from_animation", walker);
}
void Client::SetTrafficLightState(
rpc::ActorId traffic_light,
const rpc::TrafficLightState traffic_light_state) {

View File

@ -268,13 +268,20 @@ namespace detail {
rpc::ActorId walker,
const rpc::WalkerControl &control);
void ApplyBoneControlToWalker(
rpc::ActorId walker,
const rpc::WalkerBoneControlIn &control);
rpc::WalkerBoneControlOut GetBonesTransform(
rpc::ActorId walker);
void SetBonesTransform(
rpc::ActorId walker,
const rpc::WalkerBoneControlIn &bones);
void BlendPose(
rpc::ActorId walker,
float blend);
void GetPoseFromAnimation(
rpc::ActorId walker);
void SetTrafficLightState(
rpc::ActorId traffic_light,
const rpc::TrafficLightState trafficLightState);

View File

@ -457,14 +457,22 @@ namespace detail {
_client.ApplyControlToWalker(walker.GetId(), control);
}
void ApplyBoneControlToWalker(Walker &walker, const rpc::WalkerBoneControlIn &control) {
_client.ApplyBoneControlToWalker(walker.GetId(), control);
}
rpc::WalkerBoneControlOut GetBonesTransform(Walker &walker) {
return _client.GetBonesTransform(walker.GetId());
}
void SetBonesTransform(Walker &walker, const rpc::WalkerBoneControlIn &bones) {
return _client.SetBonesTransform(walker.GetId(), bones);
}
void BlendPose(Walker &walker, float blend) {
return _client.BlendPose(walker.GetId(), blend);
}
void GetPoseFromAnimation(Walker &walker) {
return _client.GetPoseFromAnimation(walker.GetId());
}
void ApplyPhysicsControlToVehicle(Vehicle &vehicle, const rpc::VehiclePhysicsControl &physicsControl) {
_client.ApplyPhysicsControlToVehicle(vehicle.GetId(), physicsControl);
}

View File

@ -191,6 +191,11 @@ void export_actor() {
.def("apply_control", &ApplyControl<cr::WalkerBoneControlIn>, (arg("control")))
.def("get_control", &cc::Walker::GetWalkerControl)
.def("get_bones", &cc::Walker::GetBonesTransform)
.def("set_bones", &cc::Walker::SetBonesTransform, (arg("bones")))
.def("blend_pose", &cc::Walker::BlendPose, (arg("blend")))
.def("show_pose", &cc::Walker::ShowPose)
.def("hide_pose", &cc::Walker::HidePose)
.def("get_pose_from_animation", &cc::Walker::GetPoseFromAnimation)
.def(self_ns::str(self_ns::self))
;

View File

@ -1248,29 +1248,6 @@ ECarlaServerResponse FWalkerActor::ApplyControlToWalker(
return ECarlaServerResponse::Success;
}
ECarlaServerResponse FWalkerActor::ApplyBoneControlToWalker(
const FWalkerBoneControlIn& Control)
{
if (IsDormant())
{
}
else
{
auto Pawn = Cast<APawn>(GetActor());
if (Pawn == nullptr)
{
return ECarlaServerResponse::NotAWalker;
}
auto Controller = Cast<AWalkerController>(Pawn->GetController());
if (Controller == nullptr)
{
return ECarlaServerResponse::WalkerIncompatibleController;
}
Controller->ApplyWalkerControl(Control);
}
return ECarlaServerResponse::Success;
}
ECarlaServerResponse FWalkerActor::GetBonesTransform(FWalkerBoneControlOut& Bones)
{
if (IsDormant())
@ -1292,3 +1269,69 @@ ECarlaServerResponse FWalkerActor::GetBonesTransform(FWalkerBoneControlOut& Bone
}
return ECarlaServerResponse::Success;
}
ECarlaServerResponse FWalkerActor::SetBonesTransform(const FWalkerBoneControlIn& Bones)
{
if (IsDormant())
{
}
else
{
auto Pawn = Cast<APawn>(GetActor());
if (Pawn == nullptr)
{
return ECarlaServerResponse::NotAWalker;
}
auto Controller = Cast<AWalkerController>(Pawn->GetController());
if (Controller == nullptr)
{
return ECarlaServerResponse::WalkerIncompatibleController;
}
Controller->SetBonesTransform(Bones);
}
return ECarlaServerResponse::Success;
}
ECarlaServerResponse FWalkerActor::BlendPose(float Blend)
{
if (IsDormant())
{
}
else
{
auto Pawn = Cast<APawn>(GetActor());
if (Pawn == nullptr)
{
return ECarlaServerResponse::NotAWalker;
}
auto Controller = Cast<AWalkerController>(Pawn->GetController());
if (Controller == nullptr)
{
return ECarlaServerResponse::WalkerIncompatibleController;
}
Controller->BlendPose(Blend);
}
return ECarlaServerResponse::Success;
}
ECarlaServerResponse FWalkerActor::GetPoseFromAnimation()
{
if (IsDormant())
{
}
else
{
auto Pawn = Cast<APawn>(GetActor());
if (Pawn == nullptr)
{
return ECarlaServerResponse::NotAWalker;
}
auto Controller = Cast<AWalkerController>(Pawn->GetController());
if (Controller == nullptr)
{
return ECarlaServerResponse::WalkerIncompatibleController;
}
Controller->GetPoseFromAnimation();
}
return ECarlaServerResponse::Success;
}

View File

@ -367,12 +367,22 @@ public:
return ECarlaServerResponse::ActorTypeMismatch;
}
virtual ECarlaServerResponse ApplyBoneControlToWalker(const FWalkerBoneControlIn&)
virtual ECarlaServerResponse GetBonesTransform(FWalkerBoneControlOut&)
{
return ECarlaServerResponse::ActorTypeMismatch;
}
virtual ECarlaServerResponse GetBonesTransform(FWalkerBoneControlOut&)
virtual ECarlaServerResponse SetBonesTransform(const FWalkerBoneControlIn&)
{
return ECarlaServerResponse::ActorTypeMismatch;
}
virtual ECarlaServerResponse BlendPose(float Blend)
{
return ECarlaServerResponse::ActorTypeMismatch;
}
virtual ECarlaServerResponse GetPoseFromAnimation()
{
return ECarlaServerResponse::ActorTypeMismatch;
}
@ -553,9 +563,13 @@ public:
virtual ECarlaServerResponse GetWalkerControl(FWalkerControl&) final;
virtual ECarlaServerResponse ApplyBoneControlToWalker(const FWalkerBoneControlIn&) final;
virtual ECarlaServerResponse GetBonesTransform(FWalkerBoneControlOut&) final;
virtual ECarlaServerResponse SetBonesTransform(const FWalkerBoneControlIn&) final;
virtual ECarlaServerResponse BlendPose(float Blend);
virtual ECarlaServerResponse GetPoseFromAnimation();
};
class FOtherActor : public FCarlaActor

View File

@ -1290,31 +1290,6 @@ void FCarlaServer::FPimpl::BindActions()
return R<void>::Success();
};
BIND_SYNC(apply_bone_control_to_walker) << [this](
cr::ActorId ActorId,
cr::WalkerBoneControlIn Control) -> R<void>
{
REQUIRE_CARLA_EPISODE();
FCarlaActor* CarlaActor = Episode->FindCarlaActor(ActorId);
if (!CarlaActor)
{
return RespondError(
"apply_bone_control_to_walker",
ECarlaServerResponse::ActorNotFound,
" Actor Id: " + FString::FromInt(ActorId));
}
ECarlaServerResponse Response =
CarlaActor->ApplyBoneControlToWalker(Control);
if (Response != ECarlaServerResponse::Success)
{
return RespondError(
"apply_bone_control_to_walker",
Response,
" Actor Id: " + FString::FromInt(ActorId));
}
return R<void>::Success();
};
BIND_SYNC(get_bones_transform) << [this](
cr::ActorId ActorId) -> R<cr::WalkerBoneControlOut>
{
@ -1352,6 +1327,84 @@ void FCarlaServer::FPimpl::BindActions()
return carla::rpc::WalkerBoneControlOut(BoneData);
};
BIND_SYNC(set_bones_transform) << [this](
cr::ActorId ActorId,
carla::rpc::WalkerBoneControlIn Bones) -> R<void>
{
REQUIRE_CARLA_EPISODE();
FCarlaActor* CarlaActor = Episode->FindCarlaActor(ActorId);
if (!CarlaActor)
{
return RespondError(
"set_bones_transform",
ECarlaServerResponse::ActorNotFound,
" Actor Id: " + FString::FromInt(ActorId));
}
FWalkerBoneControlIn Bones2 = FWalkerBoneControlIn(Bones);
ECarlaServerResponse Response = CarlaActor->SetBonesTransform(Bones2);
if (Response != ECarlaServerResponse::Success)
{
return RespondError(
"set_bones_transform",
Response,
" Actor Id: " + FString::FromInt(ActorId));
}
return R<void>::Success();
};
BIND_SYNC(blend_pose) << [this](
cr::ActorId ActorId,
float Blend) -> R<void>
{
REQUIRE_CARLA_EPISODE();
FCarlaActor* CarlaActor = Episode->FindCarlaActor(ActorId);
if (!CarlaActor)
{
return RespondError(
"blend_pose",
ECarlaServerResponse::ActorNotFound,
" Actor Id: " + FString::FromInt(ActorId));
}
ECarlaServerResponse Response = CarlaActor->BlendPose(Blend);
if (Response != ECarlaServerResponse::Success)
{
return RespondError(
"blend_pose",
Response,
" Actor Id: " + FString::FromInt(ActorId));
}
return R<void>::Success();
};
BIND_SYNC(get_pose_from_animation) << [this](
cr::ActorId ActorId) -> R<void>
{
REQUIRE_CARLA_EPISODE();
FCarlaActor* CarlaActor = Episode->FindCarlaActor(ActorId);
if (!CarlaActor)
{
return RespondError(
"get_pose_from_animation",
ECarlaServerResponse::ActorNotFound,
" Actor Id: " + FString::FromInt(ActorId));
}
ECarlaServerResponse Response = CarlaActor->GetPoseFromAnimation();
if (Response != ECarlaServerResponse::Success)
{
return RespondError(
"get_pose_from_animation",
Response,
" Actor Id: " + FString::FromInt(ActorId));
}
return R<void>::Success();
};
BIND_SYNC(set_actor_autopilot) << [this](
cr::ActorId ActorId,
bool bEnabled) -> R<void>

View File

@ -0,0 +1,7 @@
// Copyright (c) 2021 Computer Vision Center (CVC) at the Universitat Autonoma
// de Barcelona (UAB).
//
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#include "WalkerAnim.h"

View File

@ -0,0 +1,26 @@
// Copyright (c) 2021 Computer Vision Center (CVC) at the Universitat Autonoma
// de Barcelona (UAB).
//
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#pragma once
#include "Animation/AnimInstance.h"
#include "WalkerAnim.generated.h"
UCLASS()
class CARLA_API UWalkerAnim : public UAnimInstance
{
GENERATED_BODY()
public:
UPROPERTY(Category="Walker Anim", BlueprintReadWrite, EditAnywhere)
float Blend = 0.0;
UPROPERTY(Category="Walker Anim", BlueprintReadWrite, EditAnywhere)
FPoseSnapshot Snap;
};

View File

@ -6,6 +6,7 @@
#include "Carla.h"
#include "Carla/Walker/WalkerController.h"
#include "Carla/Walker/WalkerAnim.h"
#include "Components/PoseableMeshComponent.h"
#include "Components/PrimitiveComponent.h"
@ -44,141 +45,137 @@ void AWalkerController::OnPossess(APawn *InPawn)
Character->JumpMaxCount = 2;
}
UPoseableMeshComponent *AddNewBoneComponent(AActor *InActor, FVector inLocation, FRotator inRotator)
{
UPoseableMeshComponent *NewComp = NewObject<UPoseableMeshComponent>(InActor,
UPoseableMeshComponent::StaticClass());
if (NewComp)
{
NewComp->RegisterComponent();
NewComp->SetWorldLocation(inLocation);
NewComp->SetWorldRotation(inRotator);
NewComp->AttachToComponent(InActor->GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform);
}
return NewComp;
}
void AWalkerController::ApplyWalkerControl(const FWalkerControl &InControl)
{
Control = InControl;
if (bManualBones)
{
SetManualBones(false);
}
}
void AWalkerController::ApplyWalkerControl(const FWalkerBoneControlIn &InBoneControl)
{
Control = InBoneControl;
if (!bManualBones)
{
SetManualBones(true);
}
}
void AWalkerController::SetManualBones(const bool bIsEnabled)
{
bManualBones = bIsEnabled;
auto *Character = GetCharacter();
TArray<UPoseableMeshComponent *> PoseableMeshes;
TArray<USkeletalMeshComponent *> SkeletalMeshes;
Character->GetComponents<UPoseableMeshComponent>(PoseableMeshes, false);
Character->GetComponents<USkeletalMeshComponent>(SkeletalMeshes, false);
USkeletalMeshComponent *SkeletalMesh = SkeletalMeshes.IsValidIndex(0) ? SkeletalMeshes[0] : nullptr;
if (SkeletalMesh)
{
if (bManualBones)
{
UPoseableMeshComponent *PoseableMesh =
PoseableMeshes.IsValidIndex(0) ? PoseableMeshes[0] : AddNewBoneComponent(Character,
SkeletalMesh->GetRelativeTransform().GetLocation(),
SkeletalMesh->GetRelativeTransform().GetRotation().Rotator());
PoseableMesh->SetSkeletalMesh(SkeletalMesh->SkeletalMesh);
PoseableMesh->SetVisibility(true);
SkeletalMesh->SetVisibility(false);
}
else
{
UPoseableMeshComponent *PoseableMesh = PoseableMeshes.IsValidIndex(0) ? PoseableMeshes[0] : nullptr;
if (PoseableMesh)
PoseableMesh->SetVisibility(false);
SkeletalMesh->SetVisibility(true);
}
}
}
void AWalkerController::GetBonesTransform(FWalkerBoneControlOut &WalkerBones)
{
auto *Character = GetCharacter();
TArray<UPoseableMeshComponent *> PoseableMeshes;
if (!Character) return;
TArray<USkeletalMeshComponent *> SkeletalMeshes;
Character->GetComponents<UPoseableMeshComponent>(PoseableMeshes, false);
Character->GetComponents<USkeletalMeshComponent>(SkeletalMeshes, false);
USkeletalMeshComponent *SkeletalMesh = SkeletalMeshes.IsValidIndex(0) ? SkeletalMeshes[0] : nullptr;
if (!SkeletalMesh) return;
UPoseableMeshComponent *PoseableMesh =
PoseableMeshes.IsValidIndex(0) ? PoseableMeshes[0] : AddNewBoneComponent(Character,
SkeletalMesh->GetRelativeTransform().GetLocation(),
SkeletalMesh->GetRelativeTransform().GetRotation().Rotator());
PoseableMesh->SetSkeletalMesh(SkeletalMesh->SkeletalMesh);
PoseableMesh->SetVisibility(false);
PoseableMesh->CopyPoseFromSkeletalComponent(SkeletalMesh);
FPoseSnapshot Snap;
SkeletalMesh->SnapshotPose(Snap);
for (int i=0; i<Snap.BoneNames.Num(); ++i)
// get the walker animation class
auto *AnimInst = SkeletalMesh->GetAnimInstance();
if (!AnimInst) return;
UWalkerAnim *WalkerAnim = Cast<UWalkerAnim>(AnimInst);
if (!WalkerAnim) return;
// get current pose
FPoseSnapshot TempSnapshot;
SkeletalMesh->SnapshotPose(TempSnapshot);
// copy pose
// WalkerAnim->Snap = TempSnapshot;
for (int i=0; i<TempSnapshot.BoneNames.Num(); ++i)
{
FWalkerBoneControlOutData Transforms;
Transforms.World = PoseableMesh->GetBoneTransformByName(Snap.BoneNames[i], EBoneSpaces::WorldSpace);
Transforms.Component = PoseableMesh->GetBoneTransformByName(Snap.BoneNames[i], EBoneSpaces::ComponentSpace);
Transforms.Relative = Snap.LocalTransforms[i];
WalkerBones.BoneTransforms.Add(Snap.BoneNames[i].ToString(), Transforms);
// FVector Loc = SkeletalMesh->GetBoneLocation(Snap.BoneNames[i], EBoneSpaces::WorldSpace);
// Trans = Snap.LocalTransforms[i];
// Trans.SetLocation(Loc);
// FTransform TransRel = Snap.LocalTransforms[i];
// if (i == 0)
// {
// UE_LOG(LogCarla, Log, TEXT("World (%f, %f, %f), Relative (%f, %f, %f), Component (%f, %f, %f)"), Trans.GetLocation().X, Trans.GetLocation().Y, Trans.GetLocation().Z, TransRel.GetLocation().X, TransRel.GetLocation().Y, TransRel.GetLocation().Z, TransComp.GetLocation().X, TransComp.GetLocation().Y, TransComp.GetLocation().Z);
// UE_LOG(LogCarla, Log, TEXT("World (%f, %f, %f), Relative (%f, %f, %f), Component (%f, %f, %f)"), Trans.GetLocation().X, Trans.GetLocation().Y, Trans.GetLocation().Z, TransRel.GetLocation().X, TransRel.GetLocation().Y, TransRel.GetLocation().Z, TransComp.GetLocation().X, TransComp.GetLocation().Y, TransComp.GetLocation().Z);
// }
Transforms.World = SkeletalMesh->GetSocketTransform(TempSnapshot.BoneNames[i], ERelativeTransformSpace::RTS_World);
Transforms.Component = SkeletalMesh->GetSocketTransform(TempSnapshot.BoneNames[i], ERelativeTransformSpace::RTS_Actor);
Transforms.Relative = SkeletalMesh->GetSocketTransform(TempSnapshot.BoneNames[i], ERelativeTransformSpace::RTS_ParentBoneSpace);
// Transforms.Relative = TempSnapshot.LocalTransforms[i];
WalkerBones.BoneTransforms.Add(TempSnapshot.BoneNames[i].ToString(), Transforms);
}
}
void AWalkerController::SetBonesTransform(const FWalkerBoneControlIn &WalkerBones)
{
auto *Character = GetCharacter();
if (!Character) return;
TArray<USkeletalMeshComponent *> SkeletalMeshes;
Character->GetComponents<USkeletalMeshComponent>(SkeletalMeshes, false);
USkeletalMeshComponent *SkeletalMesh = SkeletalMeshes.IsValidIndex(0) ? SkeletalMeshes[0] : nullptr;
if (!SkeletalMesh) return;
// get the walker animation class
auto *AnimInst = SkeletalMesh->GetAnimInstance();
if (!AnimInst) return;
UWalkerAnim *WalkerAnim = Cast<UWalkerAnim>(AnimInst);
if (!WalkerAnim) return;
// if pose is empty, then get a first version
if (WalkerAnim->Snap.BoneNames.Num() == 0)
{
// get current pose
SkeletalMesh->SnapshotPose(WalkerAnim->Snap);
}
TMap<FName, FTransform> BonesMap;
for (const TPair<FString, FTransform> &pair : WalkerBones.BoneTransforms)
{
FName BoneName = FName(*pair.Key);
BonesMap.Add(BoneName, pair.Value);
}
// assign common bones
for (int i=0; i<WalkerAnim->Snap.BoneNames.Num(); ++i)
{
FTransform *Trans = BonesMap.Find(WalkerAnim->Snap.BoneNames[i]);
if (Trans)
{
WalkerAnim->Snap.LocalTransforms[i] = *Trans;
}
}
}
void AWalkerController::BlendPose(float Blend)
{
auto *Character = GetCharacter();
if (!Character) return;
TArray<USkeletalMeshComponent *> SkeletalMeshes;
Character->GetComponents<USkeletalMeshComponent>(SkeletalMeshes, false);
USkeletalMeshComponent *SkeletalMesh = SkeletalMeshes.IsValidIndex(0) ? SkeletalMeshes[0] : nullptr;
if (!SkeletalMesh) return;
// get the walker animation class
auto *AnimInst = SkeletalMesh->GetAnimInstance();
if (!AnimInst) return;
UWalkerAnim *WalkerAnim = Cast<UWalkerAnim>(AnimInst);
if (!WalkerAnim) return;
// set current pose
WalkerAnim->Blend = Blend;
}
void AWalkerController::GetPoseFromAnimation()
{
auto *Character = GetCharacter();
if (!Character) return;
TArray<USkeletalMeshComponent *> SkeletalMeshes;
Character->GetComponents<USkeletalMeshComponent>(SkeletalMeshes, false);
USkeletalMeshComponent *SkeletalMesh = SkeletalMeshes.IsValidIndex(0) ? SkeletalMeshes[0] : nullptr;
if (!SkeletalMesh) return;
// get the walker animation class
auto *AnimInst = SkeletalMesh->GetAnimInstance();
if (!AnimInst) return;
UWalkerAnim *WalkerAnim = Cast<UWalkerAnim>(AnimInst);
if (!WalkerAnim) return;
// get current pose
SkeletalMesh->SnapshotPose(WalkerAnim->Snap);
}
void AWalkerController::ControlTickVisitor::operator()(const FWalkerControl &WalkerControl)
{
auto *Character = Controller->GetCharacter();
if (Character != nullptr)
{
Character->AddMovementInput(WalkerControl.Direction,
WalkerControl.Speed / Controller->GetMaximumWalkSpeed());
if (WalkerControl.Jump)
{
Character->Jump();
}
}
}
if (!Character) return;
void AWalkerController::ControlTickVisitor::operator()(FWalkerBoneControlIn &WalkerBoneControlIn)
{
auto *Character = Controller->GetCharacter();
if (Character == nullptr)
Character->AddMovementInput(WalkerControl.Direction,
WalkerControl.Speed / Controller->GetMaximumWalkSpeed());
if (WalkerControl.Jump)
{
return;
}
TArray<UPoseableMeshComponent *> PoseableMeshes;
Character->GetComponents<UPoseableMeshComponent>(PoseableMeshes, false);
UPoseableMeshComponent *PoseableMesh = PoseableMeshes.IsValidIndex(0) ? PoseableMeshes[0] : nullptr;
if (PoseableMesh)
{
for (const TPair<FString, FTransform> &pair : WalkerBoneControlIn.BoneTransforms)
{
FName BoneName = FName(*pair.Key);
PoseableMesh->SetBoneTransformByName(BoneName, pair.Value, EBoneSpaces::Type::ComponentSpace);
}
WalkerBoneControlIn.BoneTransforms.Empty();
Character->Jump();
}
}

View File

@ -36,8 +36,6 @@ private:
void operator()(const FWalkerControl &WalkerControl);
void operator()(FWalkerBoneControlIn &WalkerBoneControlIn);
private:
AWalkerController *Controller;
@ -61,29 +59,25 @@ public:
UFUNCTION(BlueprintCallable)
void ApplyWalkerControl(const FWalkerControl &InControl);
void ApplyWalkerControl(const FWalkerBoneControlIn &InBoneControl);
UFUNCTION(BlueprintCallable)
const FWalkerControl GetWalkerControl() const
{
return Control.which() == 0u ? boost::get<FWalkerControl>(Control) : FWalkerControl{};
}
UFUNCTION(BlueprintCallable)
const FWalkerBoneControlIn GetBoneWalkerControl() const
{
return Control.which() == 1u ? boost::get<FWalkerBoneControlIn>(Control) : FWalkerBoneControlIn{};
}
UFUNCTION(BlueprintCallable)
void SetManualBones(const bool bIsEnabled);
UFUNCTION(BlueprintCallable)
void GetBonesTransform(FWalkerBoneControlOut &WalkerBones);
UFUNCTION(BlueprintCallable)
void SetBonesTransform(const FWalkerBoneControlIn &WalkerBones);
UFUNCTION(BlueprintCallable)
void BlendPose(float Blend);
UFUNCTION(BlueprintCallable)
void GetPoseFromAnimation();
private:
boost::variant<FWalkerControl, FWalkerBoneControlIn> Control;
bool bManualBones;
boost::variant<FWalkerControl> Control;
};