Skip to content

Commit 2209a6b

Browse files
committed
Merge branch 'release/1.0'
2 parents 738b1c0 + bd9ec56 commit 2209a6b

28 files changed

+2228
-18
lines changed

ActorLocker.uplugin

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@
22
"FileVersion": 3,
33
"Version": 1,
44
"VersionName": "1.0",
5-
"FriendlyName": "ActorLocker",
6-
"Description": "",
7-
"Category": "Other",
5+
"FriendlyName": "Actor Locker",
6+
"Description": "World Outliner and Level Editor extension to lock actors in the editor viewport",
7+
"Category": "Editor",
88
"CreatedBy": "Gradess Games",
99
"CreatedByURL": "https://stepantrofimov.com",
10-
"DocsURL": "",
10+
"DocsURL": "https://github.com/Gradess2019/Actor-Locker",
1111
"MarketplaceURL": "",
12-
"SupportURL": "",
13-
"CanContainContent": true,
14-
"IsBetaVersion": true,
12+
"SupportURL": "https://github.com/Gradess2019/Actor-Locker/issues",
13+
"CanContainContent": false,
14+
"IsBetaVersion": false,
1515
"IsExperimentalVersion": false,
1616
"Installed": false,
1717
"Modules": [
1818
{
1919
"Name": "ActorLocker",
20-
"Type": "Runtime",
20+
"Type": "Editor",
2121
"LoadingPhase": "Default"
2222
}
2323
]

Config/FilterPlugin.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[FilterPlugin]
2+
/LICENSE.txt
3+
/README.md

LICENSE.txt

Lines changed: 674 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Actor Locker
2+
3+
## Description
4+
Simple plugin that lets you lock actor in the Level Editor so you can't move or select it.
5+
6+
## How to install
7+
1. Download [latest release](https://github.com/Gradess2019/Actor-Locker/releases/latest) for your Unreal Engine version
8+
2. Unzip into: **\<ProjectDirectory\>/Plugins** (create Plugins directory if it doesn't exist)
9+
3. If you are using C++: Right Mouse Button on your **.uproject** file -> Generate Visual Studio project files
10+
4. Launch project
11+
5. If it's not enabled: Go to Edit -> Plugins -> "Project" category -> Editor -> Enable "Actor Locker" and restart the editor
12+
7. Done
13+
14+
## How to use
15+
You can manipulate selected actor using **hotkeys**, **World Outliner** or **Context Menu**
16+
17+
### Hotkeys (Default)
18+
- **Alt + Comma** - Lock selection
19+
- **Alt + Period** - Unlock selection
20+
- **Alt + Shift + Comma** - Lock all actors
21+
- **Alt + Shift + Period** - Unlock all actors
22+
- **Alt + Slash** - Temporary toggle lock state of locked actors
23+
24+
### World Outliner
25+
You will see additional column with **Lock** icon. Just click on it and it will lock itself and all children as well.
26+
27+
![image](https://user-images.githubusercontent.com/38568823/212566043-07a552ef-09df-490f-beed-20489ae4adb3.png)
28+
29+
### Context Menu
30+
Click Right Mouse Button on selected actors and you will see 2 additional actions in the bottom:
31+
- Lock / Unlock selection
32+
- Toggle lock
33+
34+
![image](https://user-images.githubusercontent.com/38568823/212566344-e70dda49-d6ae-4704-8dab-92d5a48b3253.png)

Resources/Icon128.png

-10 KB
Loading

Resources/Lock.png

301 Bytes
Loading

Resources/Unlock.png

332 Bytes
Loading

Source/ActorLocker/ActorLocker.Build.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ public ActorLocker(ReadOnlyTargetRules Target) : base(Target)
3838
"Engine",
3939
"Slate",
4040
"SlateCore",
41+
"Projects",
42+
"SceneOutliner",
43+
"UnrealEd",
44+
"InputCore",
45+
"LevelEditor"
4146
// ... add private dependencies that you statically link with here ...
4247
}
4348
);
Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,81 @@
11
// Copyright Epic Games, Inc. All Rights Reserved.
22

33
#include "ActorLocker.h"
4-
5-
#define LOCTEXT_NAMESPACE "FActorLockerModule"
4+
#include "ActorLockerCommandManager.h"
5+
#include "ActorLockerManager.h"
6+
#include "ActorLockerMenuExtender.h"
7+
#include "ActorLockerSettings.h"
8+
#include "ActorLockerStyle.h"
9+
#include "ISettingsModule.h"
10+
#include "SceneOutlinerActorLocker.h"
11+
#include "SceneOutlinerModule.h"
12+
#include "Selection.h"
613

714
void FActorLockerModule::StartupModule()
815
{
9-
// This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
16+
FActorLockerStyle::Initialize();
17+
FActorLockerStyle::ReloadTextures();
18+
19+
FSceneOutlinerModule& SceneOutlinerModule = FModuleManager::LoadModuleChecked<FSceneOutlinerModule>("SceneOutliner");
20+
21+
const auto ColumnVisibility = ESceneOutlinerColumnVisibility::Visible;
22+
const auto PriorityIndex = 9;
23+
const auto Factory = FCreateSceneOutlinerColumn::CreateLambda([](ISceneOutliner& SceneOutliner){ return MakeShareable(new FSceneOutlinerActorLocker(SceneOutliner)); });
24+
const auto bCanBeHidden = false;
25+
const auto FillSize = TOptional<float>();
26+
const auto ColumnLabel = FSceneOutlinerActorLocker::Lock_Localized();
27+
const auto ColumnInfo = FSceneOutlinerColumnInfo(ColumnVisibility, PriorityIndex, Factory, bCanBeHidden, FillSize, ColumnLabel);
28+
SceneOutlinerModule.RegisterDefaultColumnType<FSceneOutlinerActorLocker>(ColumnInfo);
29+
30+
if (const auto SettingsModule = FModuleManager::GetModulePtr<ISettingsModule>("Settings"))
31+
{
32+
SettingsModule->RegisterSettings("Editor", "Plugins", "ActorLocker",
33+
NSLOCTEXT("ActorLocker", "ActorLockerSettingsDisplayName", "Actor Locker"),
34+
NSLOCTEXT("ActorLocker", "ActorLockerSettingsDescription", "Configure the Actor Locker plugin (needs restart)"),
35+
GetMutableDefault<UActorLockerSettings>()
36+
);
37+
}
38+
39+
UActorLockerCommandManager::RegisterCommands();
40+
41+
CreateActorLockerMenuExtender();
42+
43+
FEditorDelegates::OnMapOpened.AddRaw(this, &FActorLockerModule::CreateActorLockerManager);
1044
}
1145

1246
void FActorLockerModule::ShutdownModule()
1347
{
14-
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
15-
// we call this function before unloading the module.
48+
FSceneOutlinerModule& SceneOutlinerModule = FModuleManager::LoadModuleChecked<FSceneOutlinerModule>("SceneOutliner");
49+
SceneOutlinerModule.UnRegisterColumnType<FSceneOutlinerActorLocker>();
50+
51+
DestroyActorLockerMenuExtender();
52+
53+
UActorLockerCommandManager::UnregisterCommands();
54+
55+
FActorLockerStyle::Shutdown();
1656
}
1757

18-
#undef LOCTEXT_NAMESPACE
58+
void FActorLockerModule::CreateActorLockerManager(const FString& Filename, bool bAsTemplate)
59+
{
60+
if (ActorLockerManager.IsValid())
61+
{
62+
ActorLockerManager->RemoveFromRoot();
63+
ActorLockerManager->MarkAsGarbage();
64+
}
1965

20-
IMPLEMENT_MODULE(FActorLockerModule, ActorLocker)
66+
ActorLockerManager = NewObject<UActorLockerManager>();
67+
ActorLockerManager->AddToRoot();
68+
}
69+
70+
void FActorLockerModule::CreateActorLockerMenuExtender()
71+
{
72+
MenuExtender = MakeShareable(new FActorLockerMenuExtender());
73+
MenuExtender->AddLevelViewportMenuExtender();
74+
}
75+
76+
void FActorLockerModule::DestroyActorLockerMenuExtender()
77+
{
78+
MenuExtender.Reset();
79+
}
80+
81+
IMPLEMENT_MODULE(FActorLockerModule, ActorLocker)
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
// Copyright Gradess Games. All Rights Reserved.
2+
3+
#include "ActorLockerCommandManager.h"
4+
#include "ActorLockerCommands.h"
5+
#include "ActorLockerManager.h"
6+
#include "EngineUtils.h"
7+
#include "LevelEditor.h"
8+
#include "Selection.h"
9+
10+
TSharedRef<FUICommandList> UActorLockerCommandManager::RegisterCommands()
11+
{
12+
FActorLockerCommands::Register();
13+
14+
const auto& LevelEditorModule = FModuleManager::Get().LoadModuleChecked<FLevelEditorModule>("LevelEditor");
15+
16+
const auto& Commands = FActorLockerCommands::Get();
17+
const auto CommandList = LevelEditorModule.GetGlobalLevelEditorActions();
18+
19+
CommandList->MapAction(
20+
Commands.LockObject,
21+
FExecuteAction::CreateStatic(&UActorLockerCommandManager::LockObject),
22+
FCanExecuteAction::CreateStatic(&UActorLockerCommandManager::CanLockObject)
23+
);
24+
25+
CommandList->MapAction(
26+
Commands.UnlockObject,
27+
FExecuteAction::CreateStatic(&UActorLockerCommandManager::UnlockObject),
28+
FCanExecuteAction::CreateStatic(&UActorLockerCommandManager::CanUnlockObject)
29+
);
30+
31+
CommandList->MapAction(
32+
Commands.LockAllObjects,
33+
FExecuteAction::CreateStatic(&UActorLockerCommandManager::LockAllObjects),
34+
FCanExecuteAction::CreateStatic(&UActorLockerCommandManager::CanLockAllObjects)
35+
);
36+
37+
CommandList->MapAction(
38+
Commands.UnlockAllObjects,
39+
FExecuteAction::CreateStatic(&UActorLockerCommandManager::UnlockAllObjects),
40+
FCanExecuteAction::CreateStatic(&UActorLockerCommandManager::CanUnlockAllObjects)
41+
);
42+
43+
CommandList->MapAction(
44+
Commands.ToggleLockedObjects,
45+
FExecuteAction::CreateStatic(&UActorLockerCommandManager::ToggleLockedObjects),
46+
FCanExecuteAction::CreateStatic(&UActorLockerCommandManager::CanToggleLockedObjects)
47+
);
48+
49+
return CommandList;
50+
}
51+
52+
void UActorLockerCommandManager::UnregisterCommands()
53+
{
54+
FActorLockerCommands::Unregister();
55+
}
56+
57+
void UActorLockerCommandManager::LockObject()
58+
{
59+
GEditor->BeginTransaction(FText::FromString(TEXT("Lock object")));
60+
SetLockActors(true);
61+
GEditor->EndTransaction();
62+
}
63+
64+
void UActorLockerCommandManager::UnlockObject()
65+
{
66+
GEditor->BeginTransaction(FText::FromString(TEXT("Unlock object")));
67+
SetLockActors(false);
68+
GEditor->EndTransaction();
69+
}
70+
71+
void UActorLockerCommandManager::LockAllObjects()
72+
{
73+
GEditor->BeginTransaction(FText::FromString(TEXT("Lock all objects")));
74+
SetLockAllActors(true);
75+
GEditor->EndTransaction();
76+
}
77+
78+
void UActorLockerCommandManager::UnlockAllObjects()
79+
{
80+
GEditor->BeginTransaction(FText::FromString(TEXT("Unlock all objects")));
81+
SetLockAllActors(false);
82+
GEditor->EndTransaction();
83+
}
84+
85+
void UActorLockerCommandManager::ToggleLockedObjects()
86+
{
87+
GEditor->BeginTransaction(FText::FromString(TEXT("Toggle locked objects")));
88+
89+
const auto ActorLockerManager = UActorLockerManager::GetActorLockerManager();
90+
91+
SaveToTransactionBuffer(ActorLockerManager, false);
92+
ActorLockerManager->ToggleLockedActors();
93+
94+
GEditor->EndTransaction();
95+
}
96+
97+
bool UActorLockerCommandManager::CanLockObject()
98+
{
99+
return IsValidActorLockerManager();
100+
}
101+
102+
bool UActorLockerCommandManager::CanUnlockObject()
103+
{
104+
return IsValidActorLockerManager();
105+
}
106+
107+
bool UActorLockerCommandManager::CanLockAllObjects()
108+
{
109+
return IsValidActorLockerManager() && IsValidEditorWorld();
110+
}
111+
112+
bool UActorLockerCommandManager::CanUnlockAllObjects()
113+
{
114+
return IsValidActorLockerManager() && IsValidEditorWorld();
115+
}
116+
117+
bool UActorLockerCommandManager::CanToggleLockedObjects()
118+
{
119+
return IsValidActorLockerManager();
120+
}
121+
122+
void UActorLockerCommandManager::SetLockActors(const bool bInLock)
123+
{
124+
auto ActorLockerManager = UActorLockerManager::GetActorLockerManager();
125+
SaveToTransactionBuffer(ActorLockerManager, false);
126+
127+
if (const auto Selection = GEditor->GetSelectedActors())
128+
{
129+
TArray<AActor*> SelectedActors;
130+
Selection->GetSelectedObjects<AActor>(SelectedActors);
131+
132+
for (const auto SelectedActor : SelectedActors)
133+
{
134+
ActorLockerManager->SetLockActor(SelectedActor, bInLock);
135+
}
136+
}
137+
}
138+
139+
void UActorLockerCommandManager::SetLockAllActors(const bool bInLock)
140+
{
141+
const auto ActorLockerManager = UActorLockerManager::GetActorLockerManager();
142+
const auto World = GEditor->GetEditorWorldContext().World();
143+
144+
SaveToTransactionBuffer(ActorLockerManager, false);
145+
146+
for (TActorIterator<AActor> ActorIterator(World); ActorIterator; ++ActorIterator)
147+
{
148+
ActorLockerManager->SetLockActor(*ActorIterator, bInLock);
149+
}
150+
}
151+
152+
bool UActorLockerCommandManager::IsValidActorLockerManager()
153+
{
154+
const auto ActorLockerManager = UActorLockerManager::GetActorLockerManager();
155+
return IsValid(ActorLockerManager);
156+
}
157+
158+
bool UActorLockerCommandManager::IsValidEditorWorld()
159+
{
160+
const auto World = GEditor->GetEditorWorldContext().World();
161+
return IsValid(World);
162+
}

0 commit comments

Comments
 (0)