From f5a48c5d9e943ed050b8185249be3ec66d60fa51 Mon Sep 17 00:00:00 2001 From: Mamadou Babaei Date: Tue, 11 Jun 2024 23:53:21 +0200 Subject: [PATCH] add the editor user interface for adding the senseglove sockets --- .../SGAssetTypeActions_SkeletalMesh.cpp | 116 +++++++++ .../SGEditor/SGAssetTypeActions_Skeleton.cpp | 116 +++++++++ ...SGContentBrowserExtension_SkeletalMesh.cpp | 178 +++++++++++++ .../SGContentBrowserExtension_Skeleton.cpp | 131 ++++++++++ .../Private/SGEditor/SGPluginStyle.cpp | 169 +++++++++++++ .../Private/SGEditor/SGSkeletalMeshEditor.cpp | 239 ++++++++++++++++++ .../SGEditor/SGSkeletalMeshEditorCommands.cpp | 91 +++++++ .../Private/SGEditor/SGSkeletonEditor.cpp | 239 ++++++++++++++++++ .../SGEditor/SGSkeletonEditorCommands.cpp | 91 +++++++ .../Private/SenseGloveEditor.cpp | 2 +- .../Private/SenseGloveEditor.h | 2 +- .../Private/SenseGloveEditorModule.cpp | 23 +- .../Private/SenseGloveEditorModule.h | 2 +- .../SGAssetTypeActions_SkeletalMesh.h | 66 +++++ .../SGEditor/SGAssetTypeActions_Skeleton.h | 66 +++++ .../SGContentBrowserExtension_SkeletalMesh.h | 58 +++++ .../SGContentBrowserExtension_Skeleton.h | 58 +++++ .../Public/SGEditor/SGPluginStyle.h | 87 +++++++ .../Public/SGEditor/SGSkeletalMeshEditor.h | 73 ++++++ .../SGEditor/SGSkeletalMeshEditorCommands.h | 54 ++++ .../Public/SGEditor/SGSkeletonEditor.h | 73 ++++++ .../SGEditor/SGSkeletonEditorCommands.h | 54 ++++ .../SenseGloveEditor.Build.cs | 6 + 23 files changed, 1987 insertions(+), 7 deletions(-) create mode 100644 Source/SenseGloveEditor/Private/SGEditor/SGAssetTypeActions_SkeletalMesh.cpp create mode 100644 Source/SenseGloveEditor/Private/SGEditor/SGAssetTypeActions_Skeleton.cpp create mode 100644 Source/SenseGloveEditor/Private/SGEditor/SGContentBrowserExtension_SkeletalMesh.cpp create mode 100644 Source/SenseGloveEditor/Private/SGEditor/SGContentBrowserExtension_Skeleton.cpp create mode 100644 Source/SenseGloveEditor/Private/SGEditor/SGPluginStyle.cpp create mode 100644 Source/SenseGloveEditor/Private/SGEditor/SGSkeletalMeshEditor.cpp create mode 100644 Source/SenseGloveEditor/Private/SGEditor/SGSkeletalMeshEditorCommands.cpp create mode 100644 Source/SenseGloveEditor/Private/SGEditor/SGSkeletonEditor.cpp create mode 100644 Source/SenseGloveEditor/Private/SGEditor/SGSkeletonEditorCommands.cpp create mode 100644 Source/SenseGloveEditor/Public/SGEditor/SGAssetTypeActions_SkeletalMesh.h create mode 100644 Source/SenseGloveEditor/Public/SGEditor/SGAssetTypeActions_Skeleton.h create mode 100644 Source/SenseGloveEditor/Public/SGEditor/SGContentBrowserExtension_SkeletalMesh.h create mode 100644 Source/SenseGloveEditor/Public/SGEditor/SGContentBrowserExtension_Skeleton.h create mode 100644 Source/SenseGloveEditor/Public/SGEditor/SGPluginStyle.h create mode 100644 Source/SenseGloveEditor/Public/SGEditor/SGSkeletalMeshEditor.h create mode 100644 Source/SenseGloveEditor/Public/SGEditor/SGSkeletalMeshEditorCommands.h create mode 100644 Source/SenseGloveEditor/Public/SGEditor/SGSkeletonEditor.h create mode 100644 Source/SenseGloveEditor/Public/SGEditor/SGSkeletonEditorCommands.h diff --git a/Source/SenseGloveEditor/Private/SGEditor/SGAssetTypeActions_SkeletalMesh.cpp b/Source/SenseGloveEditor/Private/SGEditor/SGAssetTypeActions_SkeletalMesh.cpp new file mode 100644 index 00000000..13af91db --- /dev/null +++ b/Source/SenseGloveEditor/Private/SGEditor/SGAssetTypeActions_SkeletalMesh.cpp @@ -0,0 +1,116 @@ +/** + * @file + * + * @author Mamadou Babaei + * + * @section LICENSE + * + * (The MIT License) + * + * Copyright (c) 2020 - 2024 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/SGAssetTypeActions_SkeletalMesh.h" + +#include "Toolkits/IToolkitHost.h" +#include "ToolMenuSection.h" +#include "UObject/Class.h" +#include "UObject/Object.h" + +FText FSGAssetTypeActions_SkeletalMesh::GetName() const +{ + return NSLOCTEXT("AssetTypeActions", "SGAssetTypeActions_SkeletalMesh", "SGSkeletalMesh"); +} + +FColor FSGAssetTypeActions_SkeletalMesh::GetTypeColor() const +{ + return FColor(105, 181, 205); +} + +UClass* FSGAssetTypeActions_SkeletalMesh::GetSupportedClass() const +{ + return USkeletalMesh::StaticClass(); +} + +bool FSGAssetTypeActions_SkeletalMesh::HasActions(const TArray& InObjects) const +{ + return true; +} + +void FSGAssetTypeActions_SkeletalMesh::GetActions(const TArray& InObjects, FMenuBuilder& MenuBuilder) +{ + const FAssetToolsModule& AssetToolsModule{FModuleManager::LoadModuleChecked(TEXT("AssetTools"))}; + const TSharedPtr EngineActions{ + AssetToolsModule.Get().GetAssetTypeActionsForClass(GetSupportedClass()->GetSuperClass()).Pin() + }; + if (EngineActions.IsValid()) + { + EngineActions->GetActions(InObjects, MenuBuilder); + } + MenuBuilder.AddMenuEntry( + FText::FromString("Show Message"), + FText::FromString("Show a message box"), + FSlateIcon{FAppStyle::GetAppStyleSetName(), "LevelEditor.ViewOptions"}, + FUIAction{ + FExecuteAction::CreateLambda( + [&](TArray)-> void + { + }, InObjects) + }, + NAME_None, + EUserInterfaceActionType::Button, + NAME_None); +} + +void FSGAssetTypeActions_SkeletalMesh::GetActions(const TArray& InObjects, FToolMenuSection& Section) +{ + const FAssetToolsModule& AssetToolsModule{FModuleManager::LoadModuleChecked(TEXT("AssetTools"))}; + const TSharedPtr EngineActions{ + AssetToolsModule.Get().GetAssetTypeActionsForClass(GetSupportedClass()->GetSuperClass()).Pin() + }; + if (EngineActions.IsValid()) + { + EngineActions->GetActions(InObjects, Section); + } +} + +void FSGAssetTypeActions_SkeletalMesh::OpenAssetEditor(const TArray& InObjects, + TSharedPtr EditWithinLevelEditor) +{ + const FAssetToolsModule& AssetToolsModule{FModuleManager::LoadModuleChecked(TEXT("AssetTools"))}; + const TSharedPtr EngineActions{ + AssetToolsModule.Get().GetAssetTypeActionsForClass(GetSupportedClass()->GetSuperClass()).Pin() + }; + if (EngineActions.IsValid()) + { + EngineActions->OpenAssetEditor(InObjects, EditWithinLevelEditor); + } +} + +uint32 FSGAssetTypeActions_SkeletalMesh::GetCategories() +{ + return EAssetTypeCategories::Animation; +} \ No newline at end of file diff --git a/Source/SenseGloveEditor/Private/SGEditor/SGAssetTypeActions_Skeleton.cpp b/Source/SenseGloveEditor/Private/SGEditor/SGAssetTypeActions_Skeleton.cpp new file mode 100644 index 00000000..196df2b4 --- /dev/null +++ b/Source/SenseGloveEditor/Private/SGEditor/SGAssetTypeActions_Skeleton.cpp @@ -0,0 +1,116 @@ +/** + * @file + * + * @author Mamadou Babaei + * + * @section LICENSE + * + * (The MIT License) + * + * Copyright (c) 2020 - 2024 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/SGAssetTypeActions_Skeleton.h" + +#include "Toolkits/IToolkitHost.h" +#include "ToolMenuSection.h" +#include "UObject/Class.h" +#include "UObject/Object.h" + +FText FSGAssetTypeActions_Skeleton::GetName() const +{ + return NSLOCTEXT("AssetTypeActions", "SGAssetTypeActions_Skeleton", "SGSkeleton"); +} + +FColor FSGAssetTypeActions_Skeleton::GetTypeColor() const +{ + return FColor(105, 181, 205); +} + +UClass* FSGAssetTypeActions_Skeleton::GetSupportedClass() const +{ + return USkeleton::StaticClass(); +} + +bool FSGAssetTypeActions_Skeleton::HasActions(const TArray& InObjects) const +{ + return true; +} + +void FSGAssetTypeActions_Skeleton::GetActions(const TArray& InObjects, FMenuBuilder& MenuBuilder) +{ + const FAssetToolsModule& AssetToolsModule{FModuleManager::LoadModuleChecked(TEXT("AssetTools"))}; + const TSharedPtr EngineActions{ + AssetToolsModule.Get().GetAssetTypeActionsForClass(GetSupportedClass()->GetSuperClass()).Pin() + }; + if (EngineActions.IsValid()) + { + EngineActions->GetActions(InObjects, MenuBuilder); + } + MenuBuilder.AddMenuEntry( + FText::FromString("Show Message"), + FText::FromString("Show a message box"), + FSlateIcon{FAppStyle::GetAppStyleSetName(), "LevelEditor.ViewOptions"}, + FUIAction{ + FExecuteAction::CreateLambda( + [&](TArray)-> void + { + }, InObjects) + }, + NAME_None, + EUserInterfaceActionType::Button, + NAME_None); +} + +void FSGAssetTypeActions_Skeleton::GetActions(const TArray& InObjects, FToolMenuSection& Section) +{ + const FAssetToolsModule& AssetToolsModule{FModuleManager::LoadModuleChecked(TEXT("AssetTools"))}; + const TSharedPtr EngineActions{ + AssetToolsModule.Get().GetAssetTypeActionsForClass(GetSupportedClass()->GetSuperClass()).Pin() + }; + if (EngineActions.IsValid()) + { + EngineActions->GetActions(InObjects, Section); + } +} + +void FSGAssetTypeActions_Skeleton::OpenAssetEditor(const TArray& InObjects, + TSharedPtr EditWithinLevelEditor) +{ + const FAssetToolsModule& AssetToolsModule{FModuleManager::LoadModuleChecked(TEXT("AssetTools"))}; + const TSharedPtr EngineActions{ + AssetToolsModule.Get().GetAssetTypeActionsForClass(GetSupportedClass()->GetSuperClass()).Pin() + }; + if (EngineActions.IsValid()) + { + EngineActions->OpenAssetEditor(InObjects, EditWithinLevelEditor); + } +} + +uint32 FSGAssetTypeActions_Skeleton::GetCategories() +{ + return EAssetTypeCategories::Animation; +} \ No newline at end of file diff --git a/Source/SenseGloveEditor/Private/SGEditor/SGContentBrowserExtension_SkeletalMesh.cpp b/Source/SenseGloveEditor/Private/SGEditor/SGContentBrowserExtension_SkeletalMesh.cpp new file mode 100644 index 00000000..f9a7acb0 --- /dev/null +++ b/Source/SenseGloveEditor/Private/SGEditor/SGContentBrowserExtension_SkeletalMesh.cpp @@ -0,0 +1,178 @@ +/** + * @file + * + * @author Mamadou Babaei + * + * @section LICENSE + * + * (The MIT License) + * + * Copyright (c) 2020 - 2024 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_SkeletalMesh.h" + +#include "AssetRegistry/AssetData.h" +#include "AssetRegistry/AssetRegistryModule.h" +#include "ContentBrowserDelegates.h" +#include "ContentBrowserModule.h" +#include "Editor.h" +#include "Engine/SkeletalMeshSocket.h" +#include "Framework/MultiBox/MultiBoxBuilder.h" +#include "Framework/MultiBox/MultiBoxExtender.h" +#include "Math/Transform.h" +#include "ReferenceSkeleton.h" + +#include "SGEditor/SGPluginStyle.h" +#include "SGLog/SGLog.h" + +#define LOCTEXT_NAMESPACE "SGContentBrowserExtension_SkeletalMesh" + +void FSGContentBrowserExtension_SkeletalMesh::Register() +{ + FContentBrowserModule& ContentBrowserModule{ + FModuleManager::LoadModuleChecked(TEXT("ContentBrowser")) + }; + + TArray& ContextMenuDelegates{ + ContentBrowserModule.GetAllAssetViewContextMenuExtenders() + }; + + ContextMenuDelegates.Add(FContentBrowserMenuExtender_SelectedAssets::CreateStatic(&OnExtendAssetSelectionMenu)); +} + +TSharedRef FSGContentBrowserExtension_SkeletalMesh::OnExtendAssetSelectionMenu( + const TArray& SelectedAssets) +{ + TSharedRef Extender{MakeShared()}; + Extender->AddMenuExtension( + "CommonAssetActions", + EExtensionHook::After, + nullptr, + FMenuExtensionDelegate::CreateStatic(&AssetExtenderCallback, SelectedAssets) + ); + return MoveTemp(Extender); +} + +void FSGContentBrowserExtension_SkeletalMesh::AssetExtenderCallback( + FMenuBuilder& MenuBuilder, const TArray SelectedAssets) +{ + MenuBuilder.BeginSection(FName{TEXT("SenseGloveSection")}, LOCTEXT("SenseGloveHeading", "SenseGlove")); + { + for (const FAssetData& Asset: SelectedAssets) + { + if (!Asset.IsRedirector() + && FName{*Asset.AssetClassPath.ToString()} != NAME_Class + && !(Asset.PackageFlags & PKG_FilterEditorOnly)) + { + if (Asset.GetClass()->IsChildOf(USkeletalMesh::StaticClass())) + { + MenuBuilder.AddMenuEntry( + LOCTEXT("AddSenseGloveSocketsLabel", "Add SenseGlove Sockets"), + LOCTEXT( + "AddSenseGloveSocketsToolTip", "Adds and sets up the SenseGlove grab and touch sockets"), + FSGPluginStyle::GetStyleSetIcon(), + FUIAction{ + FExecuteAction::CreateLambda([SelectedAssets]()-> void + { + for (const FAssetData& Asset: SelectedAssets) + { + USkeletalMesh* SkeletalMesh{Cast(Asset.GetAsset())}; + + if (!IsValid(SkeletalMesh)) + { + continue; + } + + AddSenseGloveSockets(SkeletalMesh); + } + }) + }, + NAME_None, + EUserInterfaceActionType::Button, + NAME_None); + } + } + } + } + MenuBuilder.EndSection(); +} + +void FSGContentBrowserExtension_SkeletalMesh::AddSenseGloveSockets(USkeletalMesh* SkeletalMesh) +{ + if (!ensureAlwaysMsgf(IsValid(SkeletalMesh), TEXT("Invalid SkeletalMesh!"))) + { + return; + } + + const USkeleton* Skeleton{SkeletalMesh->GetSkeleton()}; + if (!ensureAlwaysMsgf(IsValid(Skeleton), TEXT("Invalid Skeleton!"))) + { + return; + } + + USkeletalMeshSocket* GrabSocket{NewObject()}; + if (!IsValid(GrabSocket)) + { + // show proper messages + SGLOG("Failed to create new socket!"); + } + + GrabSocket->SocketName = FName(TEXT("CodeGrabSocket")); + GrabSocket->BoneName = FName(TEXT("hand_l")); + GrabSocket->RelativeLocation = FVector(0.0f, 0.0f, 0.0f); + GrabSocket->RelativeRotation = FRotator(0.0f, 0.0f, 0.0f); + GrabSocket->RelativeScale = FVector(1.0f, 1.0f, 1.0f); + + SkeletalMesh->AddSocket(GrabSocket, true); + + const bool bMarkedSkeletalMeshPackageDirty = SkeletalMesh->MarkPackageDirty(); + const bool bMarkedSkeletonPackageDirty = Skeleton->MarkPackageDirty(); + + SGLOG("Socket added to hand_l?", bMarkedSkeletalMeshPackageDirty, bMarkedSkeletonPackageDirty); + + if (bMarkedSkeletalMeshPackageDirty && bMarkedSkeletonPackageDirty) + { + FAssetRegistryModule::AssetCreated(GrabSocket); + + FEditorDelegates::RefreshEditor.Broadcast(); + + // Log success + SGLOG("Create new socket!"); + } + else + { + // Log errors + SGLOG("Failed to create new socket 2!"); + } + + // Maybe we try to add them to this? + FReferenceSkeleton ReferenceSkeleton{Skeleton->GetReferenceSkeleton()}; + FReferenceSkeletonModifier SkeletonModifier{ReferenceSkeleton, Skeleton}; + +} + +#undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/Source/SenseGloveEditor/Private/SGEditor/SGContentBrowserExtension_Skeleton.cpp b/Source/SenseGloveEditor/Private/SGEditor/SGContentBrowserExtension_Skeleton.cpp new file mode 100644 index 00000000..c6d4fff5 --- /dev/null +++ b/Source/SenseGloveEditor/Private/SGEditor/SGContentBrowserExtension_Skeleton.cpp @@ -0,0 +1,131 @@ +/** + * @file + * + * @author Mamadou Babaei + * + * @section LICENSE + * + * (The MIT License) + * + * Copyright (c) 2020 - 2024 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 "Engine/SkeletalMeshSocket.h" +#include "Framework/MultiBox/MultiBoxBuilder.h" +#include "Framework/MultiBox/MultiBoxExtender.h" +#include "Math/Transform.h" +#include "ReferenceSkeleton.h" + +#include "SGEditor/SGPluginStyle.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(FName{TEXT("SenseGlove")}, LOCTEXT("SenseGloveHeading", "SenseGlove")); + { + for (const FAssetData& Asset: SelectedAssets) + { + if (!Asset.IsRedirector() + && FName{*Asset.AssetClassPath.ToString()} != NAME_Class + && !(Asset.PackageFlags & PKG_FilterEditorOnly)) + { + if (Asset.GetClass()->IsChildOf(USkeleton::StaticClass())) + { + MenuBuilder.AddMenuEntry( + LOCTEXT("AddSenseGloveSocketsLabel", "Add SenseGlove Sockets"), + LOCTEXT( + "AddSenseGloveSocketsToolTip", "Adds and sets up the SenseGlove grab and touch sockets"), + FSGPluginStyle::GetStyleSetIcon(), + FUIAction{ + FExecuteAction::CreateLambda([SelectedAssets]()-> void + { + for (const FAssetData& Asset: SelectedAssets) + { + USkeleton* Skeleton{Cast(Asset.GetAsset())}; + + if (!IsValid(Skeleton)) + { + continue; + } + + AddSenseGloveSockets(Skeleton); + } + }) + }, + NAME_None, + EUserInterfaceActionType::Button, + NAME_None); + } + } + } + } + MenuBuilder.EndSection(); +} + +void FSGContentBrowserExtension_Skeleton::AddSenseGloveSockets(USkeleton* Skeleton) +{ + if (!ensureAlwaysMsgf(IsValid(Skeleton), TEXT("Invalid Skeleton!"))) + { + return; + } + +} + +#undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/Source/SenseGloveEditor/Private/SGEditor/SGPluginStyle.cpp b/Source/SenseGloveEditor/Private/SGEditor/SGPluginStyle.cpp new file mode 100644 index 00000000..576f85b2 --- /dev/null +++ b/Source/SenseGloveEditor/Private/SGEditor/SGPluginStyle.cpp @@ -0,0 +1,169 @@ +/** + * @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/SGPluginStyle.h" + +#include "Interfaces/IPluginManager.h" +#include "Styling/SlateStyleRegistry.h" + +#define LOCTEXT_NAMESPACE "SGPluginStyle" + +struct FSGPluginStyle::FImpl +{ + /************************ + * Static methods + ************************/ + + static FString GetPluginName(); + static FString GetPluginBaseDir(); + static FString GetPluginResourcesDir(); + static FString GetPluginIconPath(); + + /************************ + * Member variables + ************************/ + + /************************ + * Owner object + ************************/ + + FSGPluginStyle* Owner; + + /************************ + * Constructor / Destructor + ************************/ + + explicit FImpl(FSGPluginStyle* InOwner); + ~FImpl(); + + /************************ + * Default copy constructor & copy assignment operator + ************************/ + + FImpl(const FImpl& Rhs) = default; + FImpl& operator=(const FImpl& Rhs) = default; + + /************************ + * Methods + ************************/ + + void RegisterIcon(); + void Register(); + void Unregister(); +}; + +FString FSGPluginStyle::FImpl::GetPluginName() +{ + static const FString PluginName{"SenseGlove"}; + return PluginName; +} + +FString FSGPluginStyle::FImpl::GetPluginBaseDir() +{ + const FString PluginName{FImpl::GetPluginName()}; + const FString BaseDir{IPluginManager::Get().FindPlugin(PluginName)->GetBaseDir()}; + return BaseDir; +} + +FString FSGPluginStyle::FImpl::GetPluginResourcesDir() +{ + const FString BaseDir{GetPluginBaseDir()}; + const FString ResourcesDir{FPaths::Combine(BaseDir, "Resources")}; + return ResourcesDir; + +} + +FString FSGPluginStyle::FImpl::GetPluginIconPath() +{ + const FString ResourcesDir{GetPluginResourcesDir()}; + const FString IconPath{FPaths::Combine(ResourcesDir, "Icon128.png")}; + return IconPath; +} + +FSGPluginStyle::FSGPluginStyle() + : FSlateStyleSet{FName{TEXT("SenseGlove")}}, + Pimpl(TUniquePtr(new FImpl{this}, PimplDeleter)) +{ +} + +FSGPluginStyle::~FSGPluginStyle() = default; + +void FSGPluginStyle::Initialize() const +{ + Pimpl->Register(); +} + +void FSGPluginStyle::Deinitialize() const +{ + Pimpl->Unregister(); +} + +FSGPluginStyle::FImpl::FImpl(FSGPluginStyle* InOwner) + : Owner(InOwner) +{ +} + +FSGPluginStyle::FImpl::~FImpl() = default; + +void FSGPluginStyle::FImpl::RegisterIcon() +{ + FName IconName{FSGPluginStyle::GetStyleSetIconName()}; + FString IconPath{GetPluginIconPath()}; + FVector2d IconSize{128.0f, 128.0f}; + + Owner->Set(MoveTemp(IconName), + new FSlateImageBrush{ + MoveTemp(IconPath), MoveTemp(IconSize) + }); +} + +void FSGPluginStyle::FImpl::Register() +{ + RegisterIcon(); + + FSlateStyleRegistry::RegisterSlateStyle(*Owner); +} + +void FSGPluginStyle::FImpl::Unregister() +{ + FSlateStyleRegistry::UnRegisterSlateStyle(*Owner); +} + +void FSGPluginStyle::FImplDeleter::operator()(const FImpl* P) const +{ + delete P; +} + +#undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/Source/SenseGloveEditor/Private/SGEditor/SGSkeletalMeshEditor.cpp b/Source/SenseGloveEditor/Private/SGEditor/SGSkeletalMeshEditor.cpp new file mode 100644 index 00000000..3b436c88 --- /dev/null +++ b/Source/SenseGloveEditor/Private/SGEditor/SGSkeletalMeshEditor.cpp @@ -0,0 +1,239 @@ +/** + * @file + * + * @author Mamadou Babaei + * + * @section LICENSE + * + * (The MIT License) + * + * Copyright (c) 2020 - 2024 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/SGSkeletalMeshEditor.h" + +#include "Framework/MultiBox/MultiBoxExtender.h" +#include "ISkeletalMeshEditor.h" +#include "ISkeletalMeshEditorModule.h" +#include "Modules/ModuleManager.h" + +#include "SGEditor/SGAssetTypeActions_SkeletalMesh.h" +#include "SGEditor/SGPluginStyle.h" +#include "SGEditor/SGSkeletalMeshEditorCommands.h" + +#define LOCTEXT_NAMESPACE "SkeletalMeshEditor" + +struct FSGSkeletalMeshEditor::FImpl +{ + /************************ + * Member variables + ************************/ + + TSharedPtr AssetActions; + TSharedPtr EditorCommands; + TSharedPtr MenuExtender; + TSharedPtr ToolbarExtender; + + /************************ + * Owner object + ************************/ + + FSGSkeletalMeshEditor* Owner; + + /************************ + * Constructor / Destructor + ************************/ + + explicit FImpl(FSGSkeletalMeshEditor* InOwner); + ~FImpl(); + + /************************ + * Default copy constructor & copy assignment operator + ************************/ + + FImpl(const FImpl& Rhs) = default; + FImpl& operator=(const FImpl& Rhs) = default; +}; + +TSharedRef FSGSkeletalMeshEditor::GetInstance() +{ + static TSharedPtr Instance{MakeShared()}; + return Instance.ToSharedRef(); +} + +FSGSkeletalMeshEditor::FSGSkeletalMeshEditor() + : Pimpl(TUniquePtr(new FImpl{this}, PimplDeleter)) +{ +} + +FSGSkeletalMeshEditor::~FSGSkeletalMeshEditor() = default; + +void FSGSkeletalMeshEditor::Initialize() const +{ + //RegisterAssetTypeActions(); + RegisterCommands(); + ExtendMenu(); + ExtendToolbar(); +} + +void FSGSkeletalMeshEditor::Deinitialize() const +{ + UnregisterCommands(); +} + +void FSGSkeletalMeshEditor::RegisterAssetTypeActions() const +{ + if (Pimpl->AssetActions.IsValid()) + { + Pimpl->AssetActions.Reset(); + } + Pimpl->AssetActions = MakeShared(); + + IAssetTools& AssetTools = FModuleManager::LoadModuleChecked("AssetTools").Get(); + + AssetTools.RegisterAssetTypeActions(Pimpl->AssetActions.ToSharedRef()); +} + +void FSGSkeletalMeshEditor::RegisterCommands() const +{ + if (Pimpl->EditorCommands.IsValid()) + { + Pimpl->EditorCommands.Reset(); + } + Pimpl->EditorCommands = MakeShared(); + Pimpl->EditorCommands->RegisterCommands(); +} + +void FSGSkeletalMeshEditor::UnregisterCommands() const +{ + if (!Pimpl->EditorCommands.IsValid()) + { + return; + } + Pimpl->EditorCommands->Unregister(); +} + +void FSGSkeletalMeshEditor::ExtendMenu() const +{ + if (Pimpl->MenuExtender.IsValid()) + { + Pimpl->MenuExtender.Reset(); + } + Pimpl->MenuExtender = MakeShared(); + + ISkeletalMeshEditorModule& SkeletonEditorModule{ + FModuleManager::LoadModuleChecked("SkeletalMeshEditor") + }; + const TSharedPtr ExtensibilityManager{ + SkeletonEditorModule.GetMenuExtensibilityManager() + }; + + if (!ensureAlwaysMsgf(ExtensibilityManager.IsValid(), TEXT("Invalid ExtensibilityManager!"))) + { + return; + } + + Pimpl->MenuExtender->AddMenuExtension( + FName{TEXT("AssetEditorActions")}, + EExtensionHook::After, + Pimpl->EditorCommands->CommandList, + FMenuExtensionDelegate::CreateLambda([&](FMenuBuilder MenuBuilder)-> void + { + MenuBuilder.BeginSection(FName{TEXT("SenseGlove")}, LOCTEXT("SenseGloveHeading", "SenseGlove")); + { + MenuBuilder.AddMenuEntry( + Pimpl->EditorCommands->AddSenseGloveSockets, + NAME_None, + LOCTEXT("AddSenseGloveSocketsLabel", "Add SenseGlove Sockets"), + LOCTEXT( + "AddSenseGloveSocketsToolTip", "Adds and sets up the SenseGlove grab and touch sockets"), + FSlateIcon{FSGPluginStyle::GetStyleSetIcon()}, + NAME_None); + } + MenuBuilder.EndSection(); + })); + + ExtensibilityManager->AddExtender(Pimpl->MenuExtender); +} + +void FSGSkeletalMeshEditor::ExtendToolbar() const +{ + if (Pimpl->ToolbarExtender.IsValid()) + { + Pimpl->ToolbarExtender.Reset(); + } + Pimpl->ToolbarExtender = MakeShared(); + + ISkeletalMeshEditorModule& SkeletalMeshEditorModule{ + FModuleManager::LoadModuleChecked("SkeletalMeshEditor") + }; + const TSharedPtr ExtensibilityManager{ + SkeletalMeshEditorModule.GetToolBarExtensibilityManager() + }; + + if (!ensureAlwaysMsgf(ExtensibilityManager.IsValid(), TEXT("Invalid ExtensibilityManager!"))) + { + return; + } + + Pimpl->ToolbarExtender->AddToolBarExtension( + FName{TEXT("SkeletalMesh")}, + EExtensionHook::After, + Pimpl->EditorCommands->CommandList, + FToolBarExtensionDelegate::CreateLambda([&](FToolBarBuilder& ToolbarBuilder)-> void + { + ToolbarBuilder.BeginSection(FName{TEXT("SenseGlove")}); + { + ToolbarBuilder.AddToolBarButton( + Pimpl->EditorCommands->AddSenseGloveSockets, + NAME_None, + LOCTEXT("AddSenseGloveSocketsLabel", "Add SenseGlove Sockets"), + LOCTEXT( + "AddSenseGloveSocketsToolTip", "Adds and sets up the SenseGlove grab and touch sockets"), + FSGPluginStyle::GetStyleSetIcon(), + NAME_None, + FNewMenuDelegate{} + ); + } + ToolbarBuilder.EndSection(); + })); + + ExtensibilityManager->AddExtender(Pimpl->ToolbarExtender); +} + +FSGSkeletalMeshEditor::FImpl::FImpl(FSGSkeletalMeshEditor* InOwner) + : Owner(InOwner) +{ +} + +FSGSkeletalMeshEditor::FImpl::~FImpl() = default; + +void FSGSkeletalMeshEditor::FImplDeleter::operator()(const FImpl* P) const +{ + delete P; +} + +#undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/Source/SenseGloveEditor/Private/SGEditor/SGSkeletalMeshEditorCommands.cpp b/Source/SenseGloveEditor/Private/SGEditor/SGSkeletalMeshEditorCommands.cpp new file mode 100644 index 00000000..48229d50 --- /dev/null +++ b/Source/SenseGloveEditor/Private/SGEditor/SGSkeletalMeshEditorCommands.cpp @@ -0,0 +1,91 @@ +/** + * @file + * + * @author Mamadou Babaei + * + * @section LICENSE + * + * (The MIT License) + * + * Copyright (c) 2020 - 2024 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/SGSkeletalMeshEditorCommands.h" + +#include "Framework/Notifications/NotificationManager.h" +#include "Widgets/Notifications/SNotificationList.h" + +#include "SGEditor/SGPluginStyle.h" + +#define LOCTEXT_NAMESPACE "SkeletalMeshEditorCommands" + +FSGSkeletalMeshEditorCommands::FSGSkeletalMeshEditorCommands() + : TCommands{ + TEXT("SGSkeletalMeshEditor"), + NSLOCTEXT("Contexts", "SGSkeletalMeshEditor", "SenseGlove SkeletalMesh Editor"), + NAME_None, + FSGPluginStyle::GetInstance()->GetStyleSetName() + } +{ +} + +FSGSkeletalMeshEditorCommands::~FSGSkeletalMeshEditorCommands() = default; + +void FSGSkeletalMeshEditorCommands::RegisterCommands() +{ + if (AddSenseGloveSockets.IsValid()) + { + AddSenseGloveSockets.Reset(); + } + UI_COMMAND(AddSenseGloveSockets, + "Add SenseGlove Sockets", + "Adds and sets up the SenseGlove grab and touch sockets", + EUserInterfaceActionType::Button, + FInputChord{}); + + if (CommandList.IsValid()) + { + CommandList.Reset(); + } + CommandList = MakeShared(); + CommandList->MapAction(AddSenseGloveSockets, + FExecuteAction::CreateLambda([&]()-> void + { + FMessageDialog::Open( + EAppMsgType::Ok, FText::FromString( + FString{ + "The SenseGlove grab and touch sockets have been added." + " If you wish the changes to persist, save the asset now!" + })); + }), + FCanExecuteAction::CreateLambda([&]()-> bool + { + return true; + }), + EUIActionRepeatMode::RepeatDisabled); +} + +#undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/Source/SenseGloveEditor/Private/SGEditor/SGSkeletonEditor.cpp b/Source/SenseGloveEditor/Private/SGEditor/SGSkeletonEditor.cpp new file mode 100644 index 00000000..6e8415b9 --- /dev/null +++ b/Source/SenseGloveEditor/Private/SGEditor/SGSkeletonEditor.cpp @@ -0,0 +1,239 @@ +/** + * @file + * + * @author Mamadou Babaei + * + * @section LICENSE + * + * (The MIT License) + * + * Copyright (c) 2020 - 2024 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/SGSkeletonEditor.h" + +#include "Framework/MultiBox/MultiBoxExtender.h" +#include "ISkeletonEditor.h" +#include "ISkeletonEditorModule.h" +#include "Modules/ModuleManager.h" + +#include "SGEditor/SGAssetTypeActions_Skeleton.h" +#include "SGEditor/SGPluginStyle.h" +#include "SGEditor/SGSkeletonEditorCommands.h" + +#define LOCTEXT_NAMESPACE "SkeletonEditor" + +struct FSGSkeletonEditor::FImpl +{ + /************************ + * Member variables + ************************/ + + TSharedPtr AssetActions; + TSharedPtr EditorCommands; + TSharedPtr MenuExtender; + TSharedPtr ToolbarExtender; + + /************************ + * Owner object + ************************/ + + FSGSkeletonEditor* Owner; + + /************************ + * Constructor / Destructor + ************************/ + + explicit FImpl(FSGSkeletonEditor* InOwner); + ~FImpl(); + + /************************ + * Default copy constructor & copy assignment operator + ************************/ + + FImpl(const FImpl& Rhs) = default; + FImpl& operator=(const FImpl& Rhs) = default; +}; + +TSharedRef FSGSkeletonEditor::GetInstance() +{ + static TSharedPtr Instance{MakeShared()}; + return Instance.ToSharedRef(); +} + +FSGSkeletonEditor::FSGSkeletonEditor() + : Pimpl(TUniquePtr(new FImpl{this}, PimplDeleter)) +{ +} + +FSGSkeletonEditor::~FSGSkeletonEditor() = default; + +void FSGSkeletonEditor::Initialize() const +{ + //RegisterAssetTypeActions(); + RegisterCommands(); + ExtendMenu(); + ExtendToolbar(); +} + +void FSGSkeletonEditor::Deinitialize() const +{ + UnregisterCommands(); +} + +void FSGSkeletonEditor::RegisterAssetTypeActions() const +{ + if (Pimpl->AssetActions.IsValid()) + { + Pimpl->AssetActions.Reset(); + } + Pimpl->AssetActions = MakeShared(); + + IAssetTools& AssetTools = FModuleManager::LoadModuleChecked("AssetTools").Get(); + + AssetTools.RegisterAssetTypeActions(Pimpl->AssetActions.ToSharedRef()); +} + +void FSGSkeletonEditor::RegisterCommands() const +{ + if (Pimpl->EditorCommands.IsValid()) + { + Pimpl->EditorCommands.Reset(); + } + Pimpl->EditorCommands = MakeShared(); + Pimpl->EditorCommands->RegisterCommands(); +} + +void FSGSkeletonEditor::UnregisterCommands() const +{ + if (!Pimpl->EditorCommands.IsValid()) + { + return; + } + Pimpl->EditorCommands->Unregister(); +} + +void FSGSkeletonEditor::ExtendMenu() const +{ + if (Pimpl->MenuExtender.IsValid()) + { + Pimpl->MenuExtender.Reset(); + } + Pimpl->MenuExtender = MakeShared(); + + ISkeletonEditorModule& SkeletonEditorModule{ + FModuleManager::LoadModuleChecked("SkeletonEditor") + }; + const TSharedPtr ExtensibilityManager{ + SkeletonEditorModule.GetMenuExtensibilityManager() + }; + + if (!ensureAlwaysMsgf(ExtensibilityManager.IsValid(), TEXT("Invalid ExtensibilityManager!"))) + { + return; + } + + Pimpl->MenuExtender->AddMenuExtension( + FName{TEXT("AssetEditorActions")}, + EExtensionHook::After, + Pimpl->EditorCommands->CommandList, + FMenuExtensionDelegate::CreateLambda([&](FMenuBuilder MenuBuilder)-> void + { + MenuBuilder.BeginSection(FName{TEXT("SenseGlove")}, LOCTEXT("SenseGloveHeading", "SenseGlove")); + { + MenuBuilder.AddMenuEntry( + Pimpl->EditorCommands->AddSenseGloveSockets, + NAME_None, + LOCTEXT("AddSenseGloveSocketsLabel", "Add SenseGlove Sockets"), + LOCTEXT( + "AddSenseGloveSocketsToolTip", "Adds and sets up the SenseGlove grab and touch sockets"), + FSGPluginStyle::GetStyleSetIcon(), + NAME_None); + } + MenuBuilder.EndSection(); + })); + + ExtensibilityManager->AddExtender(Pimpl->MenuExtender); +} + +void FSGSkeletonEditor::ExtendToolbar() const +{ + if (Pimpl->ToolbarExtender.IsValid()) + { + Pimpl->ToolbarExtender.Reset(); + } + Pimpl->ToolbarExtender = MakeShared(); + + ISkeletonEditorModule& SkeletonEditorModule{ + FModuleManager::LoadModuleChecked("SkeletonEditor") + }; + const TSharedPtr ExtensibilityManager{ + SkeletonEditorModule.GetToolBarExtensibilityManager() + }; + + if (!ensureAlwaysMsgf(ExtensibilityManager.IsValid(), TEXT("Invalid ExtensibilityManager!"))) + { + return; + } + + Pimpl->ToolbarExtender->AddToolBarExtension( + FName{TEXT("Skeleton")}, + EExtensionHook::After, + Pimpl->EditorCommands->CommandList, + FToolBarExtensionDelegate::CreateLambda([&](FToolBarBuilder& ToolbarBuilder)-> void + { + ToolbarBuilder.BeginSection(FName{TEXT("SenseGlove")}); + { + ToolbarBuilder.AddToolBarButton( + Pimpl->EditorCommands->AddSenseGloveSockets, + NAME_None, + LOCTEXT("AddSenseGloveSocketsLabel", "Add SenseGlove Sockets"), + LOCTEXT( + "AddSenseGloveSocketsToolTip", "Adds and sets up the SenseGlove grab and touch sockets"), + FSGPluginStyle::GetStyleSetIcon(), + NAME_None, + FNewMenuDelegate{} + ); + } + ToolbarBuilder.EndSection(); + })); + + ExtensibilityManager->AddExtender(Pimpl->ToolbarExtender); +} + +FSGSkeletonEditor::FImpl::FImpl(FSGSkeletonEditor* InOwner) + : Owner(InOwner) +{ +} + +FSGSkeletonEditor::FImpl::~FImpl() = default; + +void FSGSkeletonEditor::FImplDeleter::operator()(const FImpl* P) const +{ + delete P; +} + +#undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/Source/SenseGloveEditor/Private/SGEditor/SGSkeletonEditorCommands.cpp b/Source/SenseGloveEditor/Private/SGEditor/SGSkeletonEditorCommands.cpp new file mode 100644 index 00000000..39ecd65d --- /dev/null +++ b/Source/SenseGloveEditor/Private/SGEditor/SGSkeletonEditorCommands.cpp @@ -0,0 +1,91 @@ +/** + * @file + * + * @author Mamadou Babaei + * + * @section LICENSE + * + * (The MIT License) + * + * Copyright (c) 2020 - 2024 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/SGSkeletonEditorCommands.h" + +#include "Framework/Notifications/NotificationManager.h" +#include "Widgets/Notifications/SNotificationList.h" + +#include "SGEditor/SGPluginStyle.h" + +#define LOCTEXT_NAMESPACE "SkeletonEditorCommands" + +FSGSkeletonEditorCommands::FSGSkeletonEditorCommands() + : TCommands{ + TEXT("SGSkeletonEditor"), + NSLOCTEXT("Contexts", "SGSkeletonEditor", "SenseGlove Skeleton Editor"), + NAME_None, + FSGPluginStyle::GetInstance()->GetStyleSetName() + } +{ +} + +FSGSkeletonEditorCommands::~FSGSkeletonEditorCommands() = default; + +void FSGSkeletonEditorCommands::RegisterCommands() +{ + if (AddSenseGloveSockets.IsValid()) + { + AddSenseGloveSockets.Reset(); + } + UI_COMMAND(AddSenseGloveSockets, + "Add SenseGlove Sockets", + "Adds and sets up the SenseGlove grab and touch sockets", + EUserInterfaceActionType::Button, + FInputChord{}); + + if (CommandList.IsValid()) + { + CommandList.Reset(); + } + CommandList = MakeShared(); + CommandList->MapAction(AddSenseGloveSockets, + FExecuteAction::CreateLambda([&]()-> void + { + FMessageDialog::Open( + EAppMsgType::Ok, FText::FromString( + FString{ + "The SenseGlove grab and touch sockets have been added." + " If you wish the changes to persist, save the asset now!" + })); + }), + FCanExecuteAction::CreateLambda([&]()-> bool + { + return true; + }), + EUIActionRepeatMode::RepeatDisabled); +} + +#undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/Source/SenseGloveEditor/Private/SenseGloveEditor.cpp b/Source/SenseGloveEditor/Private/SenseGloveEditor.cpp index 6d2f4f8c..f9b1f755 100644 --- a/Source/SenseGloveEditor/Private/SenseGloveEditor.cpp +++ b/Source/SenseGloveEditor/Private/SenseGloveEditor.cpp @@ -7,7 +7,7 @@ * * (The MIT License) * - * Copyright (c) 2020 - 2024 SenseGlove + * 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 diff --git a/Source/SenseGloveEditor/Private/SenseGloveEditor.h b/Source/SenseGloveEditor/Private/SenseGloveEditor.h index 5e097228..60871018 100644 --- a/Source/SenseGloveEditor/Private/SenseGloveEditor.h +++ b/Source/SenseGloveEditor/Private/SenseGloveEditor.h @@ -7,7 +7,7 @@ * * (The MIT License) * - * Copyright (c) 2020 - 2024 SenseGlove + * 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 diff --git a/Source/SenseGloveEditor/Private/SenseGloveEditorModule.cpp b/Source/SenseGloveEditor/Private/SenseGloveEditorModule.cpp index f5ef12c9..7587fff8 100644 --- a/Source/SenseGloveEditor/Private/SenseGloveEditorModule.cpp +++ b/Source/SenseGloveEditor/Private/SenseGloveEditorModule.cpp @@ -7,7 +7,7 @@ * * (The MIT License) * - * Copyright (c) 2020 - 2024 SenseGlove + * 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 @@ -35,18 +35,29 @@ #include "SenseGloveEditorModule.h" +#include "SGEditor/SGContentBrowserExtension_SkeletalMesh.h" +#include "SGEditor/SGContentBrowserExtension_Skeleton.h" +#include "SGEditor/SGPluginStyle.h" +#include "SGEditor/SGSkeletalMeshEditor.h" +#include "SGEditor/SGSkeletonEditor.h" #include "SGLog/SGLog.h" #define LOCTEXT_NAMESPACE "FSenseGloveEditorModule" void FSenseGloveEditorModule::StartupModule() { - SGLOG("Starting up the SenseGloveEditor module..."); + SGLOG("Starting up SenseGloveEditor module..."); + + FSGPluginStyle::GetInstance()->Initialize(); + FSGContentBrowserExtension_SkeletalMesh::Register(); + FSGContentBrowserExtension_Skeleton::Register(); + FSGSkeletalMeshEditor::GetInstance()->Initialize(); + FSGSkeletonEditor::GetInstance()->Initialize(); } void FSenseGloveEditorModule::PreUnloadCallback() { - SGLOG("Unloading the SenseGloveEditor module..."); + SGLOG("Unloading SenseGloveEditor module..."); } void FSenseGloveEditorModule::PostLoadCallback() @@ -56,7 +67,11 @@ void FSenseGloveEditorModule::PostLoadCallback() void FSenseGloveEditorModule::ShutdownModule() { - SGLOG("Shutting down the SenseGloveEditor module..."); + SGLOG("Shutting down SenseGloveEditor module..."); + + FSGSkeletalMeshEditor::GetInstance()->Deinitialize(); + FSGSkeletonEditor::GetInstance()->Deinitialize(); + FSGPluginStyle::GetInstance()->Deinitialize(); } #undef LOCTEXT_NAMESPACE \ No newline at end of file diff --git a/Source/SenseGloveEditor/Private/SenseGloveEditorModule.h b/Source/SenseGloveEditor/Private/SenseGloveEditorModule.h index 0006b357..3f222571 100644 --- a/Source/SenseGloveEditor/Private/SenseGloveEditorModule.h +++ b/Source/SenseGloveEditor/Private/SenseGloveEditorModule.h @@ -7,7 +7,7 @@ * * (The MIT License) * - * Copyright (c) 2020 - 2024 SenseGlove + * 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 diff --git a/Source/SenseGloveEditor/Public/SGEditor/SGAssetTypeActions_SkeletalMesh.h b/Source/SenseGloveEditor/Public/SGEditor/SGAssetTypeActions_SkeletalMesh.h new file mode 100644 index 00000000..3b224d6e --- /dev/null +++ b/Source/SenseGloveEditor/Public/SGEditor/SGAssetTypeActions_SkeletalMesh.h @@ -0,0 +1,66 @@ +/** + * @file + * + * @author Mamadou Babaei + * + * @section LICENSE + * + * (The MIT License) + * + * Copyright (c) 2020 - 2024 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 "AssetTypeActions_Base.h" +#include "Containers/Array.h" +#include "Internationalization/Text.h" +#include "Math/Color.h" +#include "HAL/Platform.h" +#include "Templates/SharedPointer.h" +#include "Toolkits/IToolkit.h" +#include "ToolMenuSection.h" +#include "UObject/Object.h" + +class FMenuBuilder; +class IToolkitHost; +class UClass; +class UObject; + +class FSGAssetTypeActions_SkeletalMesh : public FAssetTypeActions_Base +{ +public: + virtual FText GetName() const override; + virtual FColor GetTypeColor() const override; + virtual UClass* GetSupportedClass() const override; + virtual bool HasActions(const TArray& InObjects) const override; + virtual void GetActions(const TArray& InObjects, FMenuBuilder& MenuBuilder) override; + virtual void GetActions(const TArray& InObjects, FToolMenuSection& Section) override; + virtual void OpenAssetEditor( + const TArray& InObjects, + TSharedPtr EditWithinLevelEditor = TSharedPtr()) override; + virtual uint32 GetCategories() override; +}; \ No newline at end of file diff --git a/Source/SenseGloveEditor/Public/SGEditor/SGAssetTypeActions_Skeleton.h b/Source/SenseGloveEditor/Public/SGEditor/SGAssetTypeActions_Skeleton.h new file mode 100644 index 00000000..7a6279e7 --- /dev/null +++ b/Source/SenseGloveEditor/Public/SGEditor/SGAssetTypeActions_Skeleton.h @@ -0,0 +1,66 @@ +/** + * @file + * + * @author Mamadou Babaei + * + * @section LICENSE + * + * (The MIT License) + * + * Copyright (c) 2020 - 2024 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 "AssetTypeActions_Base.h" +#include "Containers/Array.h" +#include "Internationalization/Text.h" +#include "Math/Color.h" +#include "HAL/Platform.h" +#include "Templates/SharedPointer.h" +#include "Toolkits/IToolkit.h" +#include "ToolMenuSection.h" +#include "UObject/Object.h" + +class FMenuBuilder; +class IToolkitHost; +class UClass; +class UObject; + +class FSGAssetTypeActions_Skeleton : public FAssetTypeActions_Base +{ +public: + virtual FText GetName() const override; + virtual FColor GetTypeColor() const override; + virtual UClass* GetSupportedClass() const override; + virtual bool HasActions(const TArray& InObjects) const override; + virtual void GetActions(const TArray& InObjects, FMenuBuilder& MenuBuilder) override; + virtual void GetActions(const TArray& InObjects, FToolMenuSection& Section) override; + virtual void OpenAssetEditor( + const TArray& InObjects, + TSharedPtr EditWithinLevelEditor = TSharedPtr()) override; + virtual uint32 GetCategories() override; +}; \ No newline at end of file diff --git a/Source/SenseGloveEditor/Public/SGEditor/SGContentBrowserExtension_SkeletalMesh.h b/Source/SenseGloveEditor/Public/SGEditor/SGContentBrowserExtension_SkeletalMesh.h new file mode 100644 index 00000000..9c64d3ec --- /dev/null +++ b/Source/SenseGloveEditor/Public/SGEditor/SGContentBrowserExtension_SkeletalMesh.h @@ -0,0 +1,58 @@ +/** + * @file + * + * @author Mamadou Babaei + * + * @section LICENSE + * + * (The MIT License) + * + * Copyright (c) 2020 - 2024 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 USkeletalMesh; + +class FSGContentBrowserExtension_SkeletalMesh +{ +public: + static void Register(); + + static TSharedRef OnExtendAssetSelectionMenu(const TArray& SelectedAssets); + static void AssetExtenderCallback(FMenuBuilder& MenuBuilder, const TArray SelectedAssets); + + static void AddSenseGloveSockets(USkeletalMesh* SkeletalMesh); + +private: + FSGContentBrowserExtension_SkeletalMesh() = delete; + virtual ~FSGContentBrowserExtension_SkeletalMesh() = delete; +}; \ No newline at end of file diff --git a/Source/SenseGloveEditor/Public/SGEditor/SGContentBrowserExtension_Skeleton.h b/Source/SenseGloveEditor/Public/SGEditor/SGContentBrowserExtension_Skeleton.h new file mode 100644 index 00000000..f4fa0c98 --- /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 - 2024 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 AddSenseGloveSockets(USkeleton* Skeleton); + +private: + FSGContentBrowserExtension_Skeleton() = delete; + virtual ~FSGContentBrowserExtension_Skeleton() = delete; +}; \ No newline at end of file diff --git a/Source/SenseGloveEditor/Public/SGEditor/SGPluginStyle.h b/Source/SenseGloveEditor/Public/SGEditor/SGPluginStyle.h new file mode 100644 index 00000000..61ec8e09 --- /dev/null +++ b/Source/SenseGloveEditor/Public/SGEditor/SGPluginStyle.h @@ -0,0 +1,87 @@ +/** + * @file + * + * @author Mamadou Babaei + * + * @section LICENSE + * + * (The MIT License) + * + * Copyright (c) 2020 - 2024 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 "Templates/SharedPointer.h" + +class ISlateStyle; + +class FSGPluginStyle final : public FSlateStyleSet +{ +public: + FORCEINLINE static TSharedRef GetInstance() + { + static TSharedPtr Instance{MakeShared()}; + return Instance.ToSharedRef(); + } + + FORCEINLINE static const FSlateStyleSet& GetStyleSet() + { + const FSlateStyleSet& StyleSet{GetInstance()->GetStyleSet()}; + return StyleSet; + } + + FORCEINLINE static const FName& GetStyleSetIconName() + { + static const FName IconName{TEXT("SenseGlove.Icon")}; + return IconName; + } + + FORCEINLINE static const FSlateIcon& GetStyleSetIcon() + { + static FSlateIcon Icon{GetInstance()->GetStyleSetName(), GetStyleSetIconName()}; + return Icon; + } + +private: + struct FImpl; + + struct FImplDeleter + { + void operator()(const FImpl* P) const; + }; + + TUniquePtr Pimpl; + FImplDeleter PimplDeleter; + +public: + FSGPluginStyle(); + virtual ~FSGPluginStyle(); + +public: + void Initialize() const; + void Deinitialize() const; +}; \ No newline at end of file diff --git a/Source/SenseGloveEditor/Public/SGEditor/SGSkeletalMeshEditor.h b/Source/SenseGloveEditor/Public/SGEditor/SGSkeletalMeshEditor.h new file mode 100644 index 00000000..02add114 --- /dev/null +++ b/Source/SenseGloveEditor/Public/SGEditor/SGSkeletalMeshEditor.h @@ -0,0 +1,73 @@ +/** + * @file + * + * @author Mamadou Babaei + * + * @section LICENSE + * + * (The MIT License) + * + * Copyright (c) 2020 - 2024 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 "Framework/MultiBox/MultiBoxExtender.h" +#include "Templates/SharedPointer.h" + +class FSGSkeletalMeshEditor +{ +public: + static TSharedRef GetInstance(); + +private: + struct FImpl; + + struct FImplDeleter + { + void operator()(const FImpl* P) const; + }; + + TUniquePtr Pimpl; + FImplDeleter PimplDeleter; + +public: + FSGSkeletalMeshEditor(); + virtual ~FSGSkeletalMeshEditor(); + +public: + void Initialize() const; + void Deinitialize() const; + + void RegisterAssetTypeActions() const; + + void RegisterCommands() const; + void UnregisterCommands() const; + + void ExtendMenu() const; + + void ExtendToolbar() const; +}; \ No newline at end of file diff --git a/Source/SenseGloveEditor/Public/SGEditor/SGSkeletalMeshEditorCommands.h b/Source/SenseGloveEditor/Public/SGEditor/SGSkeletalMeshEditorCommands.h new file mode 100644 index 00000000..f7cce0ee --- /dev/null +++ b/Source/SenseGloveEditor/Public/SGEditor/SGSkeletalMeshEditorCommands.h @@ -0,0 +1,54 @@ +/** + * @file + * + * @author Mamadou Babaei + * + * @section LICENSE + * + * (The MIT License) + * + * Copyright (c) 2020 - 2024 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 "Framework/Commands/Commands.h" +#include "Framework/Commands/UICommandList.h" +#include "Templates/SharedPointer.h" + +class FSGSkeletalMeshEditorCommands final : public TCommands +{ +public: + TSharedPtr CommandList; + TSharedPtr AddSenseGloveSockets; + +public: + FSGSkeletalMeshEditorCommands(); + virtual ~FSGSkeletalMeshEditorCommands() override; + +public: + virtual void RegisterCommands() override; +}; \ No newline at end of file diff --git a/Source/SenseGloveEditor/Public/SGEditor/SGSkeletonEditor.h b/Source/SenseGloveEditor/Public/SGEditor/SGSkeletonEditor.h new file mode 100644 index 00000000..6e6e1b71 --- /dev/null +++ b/Source/SenseGloveEditor/Public/SGEditor/SGSkeletonEditor.h @@ -0,0 +1,73 @@ +/** + * @file + * + * @author Mamadou Babaei + * + * @section LICENSE + * + * (The MIT License) + * + * Copyright (c) 2020 - 2024 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 "Framework/MultiBox/MultiBoxExtender.h" +#include "Templates/SharedPointer.h" + +class FSGSkeletonEditor +{ +public: + static TSharedRef GetInstance(); + +private: + struct FImpl; + + struct FImplDeleter + { + void operator()(const FImpl* P) const; + }; + + TUniquePtr Pimpl; + FImplDeleter PimplDeleter; + +public: + FSGSkeletonEditor(); + virtual ~FSGSkeletonEditor(); + +public: + void Initialize() const; + void Deinitialize() const; + + void RegisterAssetTypeActions() const; + + void RegisterCommands() const; + void UnregisterCommands() const; + + void ExtendMenu() const; + + void ExtendToolbar() const; +}; \ No newline at end of file diff --git a/Source/SenseGloveEditor/Public/SGEditor/SGSkeletonEditorCommands.h b/Source/SenseGloveEditor/Public/SGEditor/SGSkeletonEditorCommands.h new file mode 100644 index 00000000..d069c0b6 --- /dev/null +++ b/Source/SenseGloveEditor/Public/SGEditor/SGSkeletonEditorCommands.h @@ -0,0 +1,54 @@ +/** + * @file + * + * @author Mamadou Babaei + * + * @section LICENSE + * + * (The MIT License) + * + * Copyright (c) 2020 - 2024 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 "Framework/Commands/Commands.h" +#include "Framework/Commands/UICommandList.h" +#include "Templates/SharedPointer.h" + +class FSGSkeletonEditorCommands final : public TCommands +{ +public: + TSharedPtr CommandList; + TSharedPtr AddSenseGloveSockets; + +public: + FSGSkeletonEditorCommands(); + virtual ~FSGSkeletonEditorCommands() override; + +public: + virtual void RegisterCommands() override; +}; \ No newline at end of file diff --git a/Source/SenseGloveEditor/SenseGloveEditor.Build.cs b/Source/SenseGloveEditor/SenseGloveEditor.Build.cs index c2caec3a..6df406cb 100644 --- a/Source/SenseGloveEditor/SenseGloveEditor.Build.cs +++ b/Source/SenseGloveEditor/SenseGloveEditor.Build.cs @@ -49,6 +49,12 @@ public class SenseGloveEditor : ModuleRules "Core", "CoreUObject", "Engine", + "InputCore", + "Projects", + "SkeletalMeshEditor", + "SkeletonEditor", + "Slate", + "SlateCore", "UnrealEd", "SenseGloveLog", }