diff --git a/Source/SenseGloveEditor/Private/SGEditor/SGContentBrowserExtension_SKeleton.cpp b/Source/SenseGloveEditor/Private/SGEditor/SGContentBrowserExtension_SKeleton.cpp new file mode 100644 index 00000000..cdf8c7ab --- /dev/null +++ b/Source/SenseGloveEditor/Private/SGEditor/SGContentBrowserExtension_SKeleton.cpp @@ -0,0 +1,152 @@ +/** + * @file + * + * @author Mamadou Babaei + * + * @section LICENSE + * + * (The MIT License) + * + * Copyright (c) 2020 - 2023 SenseGlove + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * @section DESCRIPTION + * + * + */ + + +#include "SGEditor/SGContentBrowserExtension_SKeleton.h" + +#include "AssetRegistry/AssetData.h" +#include "ContentBrowserDelegates.h" +#include "ContentBrowserModule.h" +#include "Framework/MultiBox/MultiBoxBuilder.h" +#include "Framework/MultiBox/MultiBoxExtender.h" +#include "Math/Transform.h" +#include "ReferenceSkeleton.h" + +#include "SGLog/SGLog.h" + +#define LOCTEXT_NAMESPACE "SGContentBrowserExtension_Skeleton" + +void FSGContentBrowserExtension_Skeleton::Register() +{ + FContentBrowserModule& ContentBrowserModule{ + FModuleManager::LoadModuleChecked(TEXT("ContentBrowser")) + }; + + TArray& ContextMenuDelegates{ + ContentBrowserModule.GetAllAssetViewContextMenuExtenders() + }; + + ContextMenuDelegates.Add(FContentBrowserMenuExtender_SelectedAssets::CreateStatic(&OnExtendAssetSelectionMenu)); +} + +TSharedRef FSGContentBrowserExtension_Skeleton::OnExtendAssetSelectionMenu( + const TArray& SelectedAssets) +{ + TSharedRef Extender{MakeShared()}; + Extender->AddMenuExtension( + "CommonAssetActions", + EExtensionHook::After, + nullptr, + FMenuExtensionDelegate::CreateStatic(&AssetExtenderCallback, SelectedAssets) + ); + return MoveTemp(Extender); +} + +void FSGContentBrowserExtension_Skeleton::AssetExtenderCallback( + FMenuBuilder& MenuBuilder, const TArray SelectedAssets) +{ + MenuBuilder.BeginSection("SenseGloveContext", LOCTEXT("SENSEGLOVE_CONTEXT", "SenseGlove")); + { + for (const FAssetData& Asset: SelectedAssets) + { + if (!Asset.IsRedirector() && +#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION >= 1 + FName(*Asset.AssetClassPath.ToString()) +#else + Asset.AssetClass +#endif + != NAME_Class && !(Asset.PackageFlags & PKG_FilterEditorOnly)) + { + if (Asset.GetClass()->IsChildOf(USkeleton::StaticClass())) + { + MenuBuilder.AddMenuEntry( + LOCTEXT("UpdateSkeletonReferencePose", "Use Current Pose As SenseGlove Reference Pose"), + LOCTEXT( + "Apply the current pose as the reference pose!" + " This will modify and update the skeleton's reference pose transforms.", + "Apply the current pose as the reference pose!" + " This will modify and update the skeleton's reference pose transforms."), + FSlateIcon( +#if ENGINE_MAJOR_VERSION >= 5 + FAppStyle::GetAppStyleSetName() +#else + FEditorStyle::GetStyleSetName() +#endif /* ENGINE_MAJOR_VERSION >= 5 */ + , ""), + FUIAction(FExecuteAction::CreateLambda([SelectedAssets]()-> void + { + for (const FAssetData& Asset: SelectedAssets) + { + USkeleton* Skeleton{Cast(Asset.GetAsset())}; + + if (!IsValid(Skeleton)) + { + continue; + } + + UpdateRefPoseTransform(Skeleton); + } + })), + NAME_None, + EUserInterfaceActionType::Button); + } + } + } + } + MenuBuilder.EndSection(); +} + +void FSGContentBrowserExtension_Skeleton::UpdateRefPoseTransform(USkeleton* Skeleton) +{ + FReferenceSkeleton ReferenceSkeleton{Skeleton->GetReferenceSkeleton()}; + FReferenceSkeletonModifier SkeletonModifier{ReferenceSkeleton, Skeleton}; + + const TArray& RefBoneInfo{ReferenceSkeleton.GetRefBoneInfo()}; + const TArray& RefBonePose{ReferenceSkeleton.GetRefBonePose()}; + + for (const FMeshBoneInfo& BoneInfo : RefBoneInfo) + { + SGLOG(FString::Printf(TEXT("Modifying reference pose transform on '%s'..."), *BoneInfo.Name.ToString())); + + const FName& BoneName{BoneInfo.Name}; + const int32 BoneIndex = ReferenceSkeleton.FindBoneIndex(BoneName); + const FTransform& BoneTransform{RefBonePose[BoneIndex]}; + + SGLOG(BoneName, BoneIndex, BoneTransform); + + SkeletonModifier.UpdateRefPoseTransform(BoneIndex, BoneTransform); + } +} + +#undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/Source/SenseGloveEditor/Private/SenseGloveEditorModule.cpp b/Source/SenseGloveEditor/Private/SenseGloveEditorModule.cpp index 4a6db3a2..3aa93cd9 100644 --- a/Source/SenseGloveEditor/Private/SenseGloveEditorModule.cpp +++ b/Source/SenseGloveEditor/Private/SenseGloveEditorModule.cpp @@ -35,6 +35,7 @@ #include "SenseGloveEditorModule.h" +#include "SGEditor/SGContentBrowserExtension_SKeleton.h" #include "SGLog/SGLog.h" #define LOCTEXT_NAMESPACE "FSenseGloveEditorModule" @@ -43,9 +44,7 @@ void FSenseGloveEditorModule::StartupModule() { SGLOG("Starting up SenseGloveEditor module..."); - SkeletonEditor = MakeShared(); - SkeletonEditor->ExtendToolbar(); - SkeletonEditor->RegisterAssetTypeActions(); + FSGContentBrowserExtension_Skeleton::Register(); } void FSenseGloveEditorModule::PreUnloadCallback() diff --git a/Source/SenseGloveEditor/Private/SenseGloveEditorModule.h b/Source/SenseGloveEditor/Private/SenseGloveEditorModule.h index 695dc5ff..3f222571 100644 --- a/Source/SenseGloveEditor/Private/SenseGloveEditorModule.h +++ b/Source/SenseGloveEditor/Private/SenseGloveEditorModule.h @@ -37,15 +37,10 @@ #include "Modules/ModuleInterface.h" -#include "SGEditor/SGSkeletonEditor.h" - #define LOCTEXT_NAMESPACE "SenseGloveEditor" class FSenseGloveEditorModule : public IModuleInterface { -private: - TSharedPtr SkeletonEditor; - public: virtual void StartupModule() override; virtual void PreUnloadCallback() override; diff --git a/Source/SenseGloveEditor/Public/SGEditor/SGContentBrowserExtension_SKeleton.h b/Source/SenseGloveEditor/Public/SGEditor/SGContentBrowserExtension_SKeleton.h new file mode 100644 index 00000000..d0ef4a61 --- /dev/null +++ b/Source/SenseGloveEditor/Public/SGEditor/SGContentBrowserExtension_SKeleton.h @@ -0,0 +1,58 @@ +/** + * @file + * + * @author Mamadou Babaei + * + * @section LICENSE + * + * (The MIT License) + * + * Copyright (c) 2020 - 2023 SenseGlove + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * @section DESCRIPTION + * + * + */ + + +#pragma once + +#include "Containers/Array.h" +#include "Templates/SharedPointer.h" + +struct FAssetData; +class FMenuBuilder; +class USkeleton; + +class FSGContentBrowserExtension_Skeleton +{ +public: + static void Register(); + + static TSharedRef OnExtendAssetSelectionMenu(const TArray& SelectedAssets); + static void AssetExtenderCallback(FMenuBuilder& MenuBuilder, const TArray SelectedAssets); + + static void UpdateRefPoseTransform(USkeleton* Skeleton); + +private: + FSGContentBrowserExtension_Skeleton() = delete; + virtual ~FSGContentBrowserExtension_Skeleton() = delete; +}; \ No newline at end of file