├── .gitignore ├── AUTHORS ├── CHANGELOG.txt ├── Haste.uplugin ├── LICENSE ├── README.md ├── Resources └── Icon128.png └── Source └── HasteEditor ├── HasteEditor.Build.cs ├── Private ├── HasteEdMode.cpp ├── HasteEdMode.h ├── HasteEdModeSettings.cpp ├── HasteEdModeSettings.h ├── HasteEdModeToolkit.cpp ├── HasteEdModeToolkit.h ├── HasteEditorModule.cpp ├── HasteEditorPrivatePCH.h └── Transformer │ ├── HasteTransformLogic.cpp │ ├── HasteTransformLogic.h │ ├── HasteTransformLogicRandomZ.cpp │ └── HasteTransformLogicRandomZ.h └── Public └── HasteEditorModule.h /.gitignore: -------------------------------------------------------------------------------- 1 | DerivedDataCache 2 | Intermediate 3 | Saved 4 | Binaries 5 | Deploy 6 | Build 7 | *.sdf 8 | *.opensdf 9 | *.v12.suo -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # Haste Plugin Authors 2 | Ali Akbar Vathi 3 | VorGhan <@codergoblin> 4 | -------------------------------------------------------------------------------- /CHANGELOG.txt: -------------------------------------------------------------------------------- 1 | CHANGELOG: Haste - Rapid Mesh Placement Plugin for UE4 2 | ====================================================== 3 | Ver 1.1.3 4 | --------- 5 | * Cursor rotation is visible without having to move the mouse. Cursor tracing is now done on every frame, instead of a mouse move event 6 | 7 | Ver 1.1.2 8 | --------- 9 | * Fixed breaking changes for 4.14 10 | 11 | Ver 1.1.1 12 | --------- 13 | * Added a flag to control the rotation of the mesh cursor using the mouse wheel 14 | 15 | Ver 1.1.0 16 | --------- 17 | * Fixed breaking changes for 4.12 18 | * Mesh names in the world outliner now reflect the static mesh they were created from (@VorGhan) 19 | * Added Transformer logics. The user can control the transform of the placed mesh using blueprints (e.g. random rotation, or some user defined pattern) 20 | 21 | Ver 1.0.0 22 | --------- 23 | Initial Version -------------------------------------------------------------------------------- /Haste.uplugin: -------------------------------------------------------------------------------- 1 | { 2 | "FileVersion" : 3, 3 | 4 | "FriendlyName" : "Haste", 5 | "Version" : 14, 6 | "VersionName" : "1.1.3", 7 | "CreatedBy" : "Ali Akbar Vathi", 8 | "CreatedByURL" : "http://coderespawn.com", 9 | "EngineVersion" : "4.14.0", 10 | "Description" : "Quickly place meshes all over your scene with point and click", 11 | "Category" : "Productivity", 12 | "EnabledByDefault" : true, 13 | 14 | "Modules" : 15 | [ 16 | { 17 | "Name" : "HasteEditor", 18 | "Type" : "Editor" 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015, Code Respawn Technologies Pvt Ltd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Haste Plugin - UE4 Editor Mode for Rapid Mesh Placement 2 | 3 | **Haste** is a Custom Unreal Engine 4 Editor Mode that lets you place static meshes all over your map with point and click 4 | 5 | ## Usage 6 | 1. Enter **Haste Edit Mode** by selecting the Haste tab in the editor 7 | ![Imgur](http://i.imgur.com/QfR5pNH.png) 8 | 9 | 2. Select one or more meshes from the content browser that you would like to place on the map 10 | ![Imgur](http://i.imgur.com/QZiyLC9.png) 11 | 12 | 3. Hover the mouse over the viewport and click to place the mesh 13 | ![Imgur](http://i.imgur.com/cpbft6Y.png) 14 | 15 | 4. Use the mouse wheel to rotate the mesh cursor 16 | 17 | ## Installation 18 | * Create a folder named Plugins in your UE4 game root directory 19 | * Extract the contents of this repository into a directory named Haste 20 | * The final directory structure should look like this 21 | 22 | ![Imgur](http://i.imgur.com/SWjVGg2.png) 23 | 24 | 25 | ### Example 26 |
27 | cd ShooterGame
28 | mkdir Plugins
29 | cd Plugins
30 | git clone https://github.com/coderespawn/haste-plugin-ue4.git Haste
31 | 
32 | 33 | This would create a folder named Haste inside the Plugins folder and clone the repository into it 34 | 35 | ### Example (if your main game code is already in git) 36 | You can clone the plugin into your game's existing git repository as a sub module 37 |
38 | cd ShooterGame
39 | mkdir Plugins
40 | git submodule add https://github.com/coderespawn/haste-plugin-ue4.git Plugins/Haste
41 | 
42 | 43 | -------------------------------------------------------------------------------- /Resources/Icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderespawn/haste-plugin-ue4/c4cd415804a2b9f20257bca978cd42a8eca7f4bc/Resources/Icon128.png -------------------------------------------------------------------------------- /Source/HasteEditor/HasteEditor.Build.cs: -------------------------------------------------------------------------------- 1 | // Copyright 1998-2015 Epic Games, Inc. All Rights Reserved. 2 | 3 | namespace UnrealBuildTool.Rules 4 | { 5 | public class HasteEditor : ModuleRules 6 | { 7 | public HasteEditor(TargetInfo Target) 8 | { 9 | PublicIncludePaths.AddRange( 10 | new string[] { 11 | // ... add public include paths required here ... 12 | } 13 | ); 14 | 15 | PrivateIncludePaths.AddRange( 16 | new string[] { 17 | "HasteEditor/Private", 18 | "Editor/GraphEditor/Private", 19 | "Editor/GraphEditor/Private/KismetNodes", 20 | "Editor/GraphEditor/Private/KismetPins", 21 | // ... add other private include paths required here ... 22 | } 23 | ); 24 | 25 | PrivateIncludePathModuleNames.AddRange( 26 | new string[] { 27 | "Settings", 28 | "IntroTutorials", 29 | "AssetTools" 30 | } 31 | ); 32 | 33 | PublicDependencyModuleNames.AddRange( 34 | new string[] 35 | { 36 | "Core", 37 | "CoreUObject", 38 | "Engine", 39 | "Slate", 40 | "EditorStyle", 41 | "UnrealEd", 42 | "KismetWidgets", 43 | "GraphEditor", 44 | "Kismet", // for FWorkflowCentricApplication 45 | // ... add other public dependencies that you statically link with here ... 46 | } 47 | ); 48 | 49 | PrivateDependencyModuleNames.AddRange( 50 | new string[] 51 | { 52 | "InputCore", 53 | "SlateCore", 54 | "RenderCore", 55 | "PropertyEditor", 56 | "WorkspaceMenuStructure", 57 | "LevelEditor", 58 | "EditorStyle", 59 | "ContentBrowser" 60 | // ... add private dependencies that you statically link with here ... 61 | } 62 | ); 63 | 64 | DynamicallyLoadedModuleNames.AddRange( 65 | new string[] 66 | { 67 | // ... add any modules that your module loads dynamically here ... 68 | } 69 | ); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /Source/HasteEditor/Private/HasteEdMode.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Code Respawn Technologies. MIT License 2 | 3 | #include "HasteEditorPrivatePCH.h" 4 | #include "HasteEdMode.h" 5 | #include "UnrealEd.h" 6 | #include "StaticMeshResources.h" 7 | #include "ObjectTools.h" 8 | #include "ScopedTransaction.h" 9 | 10 | #include "ModuleManager.h" 11 | #include "Editor/LevelEditor/Public/LevelEditor.h" 12 | #include "Toolkits/ToolkitManager.h" 13 | 14 | #include "Runtime/AssetRegistry/Public/AssetRegistryModule.h" 15 | 16 | //Slate dependencies 17 | #include "Editor/LevelEditor/Public/LevelEditor.h" 18 | #include "Editor/LevelEditor/Public/SLevelViewport.h" 19 | #include "ContentBrowserModule.h" 20 | #include "HasteEdModeToolkit.h" 21 | #include "HasteEdModeSettings.h" 22 | #include "Transformer/HasteTransformLogic.h" 23 | 24 | FEditorModeID FEdModeHaste::EM_Haste(TEXT("EM_Haste")); 25 | 26 | 27 | #define LOCTEXT_NAMESPACE "HasteEdMode" 28 | #define HASTE_SNAP_TRACE (10000.f) 29 | 30 | DEFINE_LOG_CATEGORY(LogHasteMode); 31 | 32 | #define BRUSH_RADIUS 100 33 | // 34 | // FEdModeHaste 35 | // 36 | 37 | const float ROTATION_SPEED = 10; 38 | 39 | /** Constructor */ 40 | FEdModeHaste::FEdModeHaste() 41 | : FEdMode() 42 | , bToolActive(false) 43 | , bCanAltDrag(false) 44 | , bMeshRotating(false) 45 | , RotationOffset(FVector::ZeroVector) 46 | , UISettings(nullptr) 47 | { 48 | // Load resources and construct brush component 49 | UMaterial* BrushMaterial = nullptr; 50 | if (!IsRunningCommandlet()) 51 | { 52 | BrushMaterial = LoadObject(nullptr, TEXT("/Engine/EditorLandscapeResources/FoliageBrushSphereMaterial.FoliageBrushSphereMaterial"), nullptr, LOAD_None, nullptr); 53 | DefaultBrushMesh = LoadObject(nullptr, TEXT("/Engine/EngineMeshes/Sphere.Sphere"), nullptr, LOAD_None, nullptr); 54 | ActiveBrushMesh = nullptr; 55 | } 56 | 57 | BrushMeshComponent = NewObject(); 58 | BrushMeshComponent->SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName); 59 | BrushMeshComponent->SetCollisionObjectType(ECC_WorldDynamic); 60 | BrushMeshComponent->SetStaticMesh(DefaultBrushMesh); 61 | BrushMeshComponent->OverrideMaterials.Add(BrushMaterial); 62 | BrushMeshComponent->SetAbsolute(true, true, true); 63 | BrushMeshComponent->CastShadow = false; 64 | 65 | bBrushTraceValid = false; 66 | BrushLocation = FVector::ZeroVector; 67 | BrushScale = FVector(1); 68 | BrushRotation = FQuat::Identity; 69 | LastMousePosition = FIntVector::ZeroValue; 70 | 71 | ResetBrushMesh(); 72 | } 73 | 74 | 75 | /** Destructor */ 76 | FEdModeHaste::~FEdModeHaste() 77 | { 78 | // Save UI settings to config file 79 | FEditorDelegates::MapChange.RemoveAll(this); 80 | } 81 | 82 | 83 | /** FGCObject interface */ 84 | void FEdModeHaste::AddReferencedObjects(FReferenceCollector& Collector) 85 | { 86 | // Call parent implementation 87 | FEdMode::AddReferencedObjects(Collector); 88 | 89 | Collector.AddReferencedObject(BrushMeshComponent); 90 | Collector.AddReferencedObject(UISettings); 91 | } 92 | 93 | /** FEdMode: Called when the mode is entered */ 94 | void FEdModeHaste::Enter() 95 | { 96 | FEdMode::Enter(); 97 | 98 | // Clear any selection 99 | GEditor->SelectNone(false, true); 100 | 101 | if (!UISettings) { 102 | UISettings = NewObject(); 103 | } 104 | 105 | // Bind to editor callbacks 106 | FEditorDelegates::NewCurrentLevel.AddSP(this, &FEdModeHaste::NotifyNewCurrentLevel); 107 | 108 | // Force real-time viewports. We'll back up the current viewport state so we can restore it when the 109 | // user exits this mode. 110 | const bool bWantRealTime = true; 111 | const bool bRememberCurrentState = true; 112 | ForceRealTimeViewports(bWantRealTime, bRememberCurrentState); 113 | 114 | 115 | if (!Toolkit.IsValid()) 116 | { 117 | TSharedPtr HasteToolkit = MakeShareable(new FHasteEdModeToolkit); 118 | TSharedPtr HasteEditor = SNew(SHasteEditor); 119 | HasteEditor->SetSettingsObject(UISettings); 120 | HasteToolkit->SetInlineContent(HasteEditor); 121 | Toolkit = HasteToolkit; 122 | Toolkit->Init(Owner->GetToolkitHost()); 123 | } 124 | 125 | // Listen for asset selection change events in the content browser 126 | { 127 | FContentBrowserModule& ContentBrowserModule = FModuleManager::GetModuleChecked(TEXT("ContentBrowser")); 128 | ContentBrowserSelectionChangeDelegate = ContentBrowserModule.GetOnAssetSelectionChanged().AddRaw(this, &FEdModeHaste::OnContentBrowserSelectionChanged); 129 | } 130 | } 131 | 132 | 133 | /** FEdMode: Called when the mode is exited */ 134 | void FEdModeHaste::Exit() 135 | { 136 | if (Toolkit.IsValid()) { 137 | FToolkitManager::Get().CloseToolkit(Toolkit.ToSharedRef()); 138 | Toolkit.Reset(); 139 | } 140 | 141 | // 142 | FEditorDelegates::NewCurrentLevel.RemoveAll(this); 143 | 144 | // Remove the brush 145 | BrushMeshComponent->UnregisterComponent(); 146 | 147 | // Restore real-time viewport state if we changed it 148 | const bool bWantRealTime = false; 149 | const bool bRememberCurrentState = false; 150 | ForceRealTimeViewports(bWantRealTime, bRememberCurrentState); 151 | 152 | // Unregister from the content browser 153 | { 154 | FContentBrowserModule& ContentBrowserModule = FModuleManager::GetModuleChecked(TEXT("ContentBrowser")); 155 | ContentBrowserModule.GetOnAssetSelectionChanged().Remove(ContentBrowserSelectionChangeDelegate); 156 | } 157 | 158 | // Call base Exit method to ensure proper cleanup 159 | FEdMode::Exit(); 160 | } 161 | 162 | void FEdModeHaste::OnContentBrowserSelectionChanged(const TArray& NewSelectedAssets, bool bIsPrimaryBrowser) { 163 | if (!bIsPrimaryBrowser) return; 164 | UE_LOG(LogHasteMode, Log, TEXT("Content Browser Selection Changed")); 165 | 166 | SelectedBrushMeshes.Reset(); 167 | 168 | // Select the first static mesh we find from the list of selected assets 169 | for (const FAssetData& Asset : NewSelectedAssets) { 170 | UObject* AssetObj = Asset.GetAsset(); 171 | if (UStaticMesh* StaticMesh = Cast(AssetObj)) { 172 | SelectedBrushMeshes.Add(StaticMesh); 173 | } 174 | } 175 | RotationOffset = FVector::ZeroVector; 176 | ResetBrushMesh(); 177 | } 178 | 179 | void FEdModeHaste::ResetBrushMesh() 180 | { 181 | 182 | // Select a random brush mesh from the list 183 | UStaticMesh* RandomMesh = nullptr; 184 | if (SelectedBrushMeshes.Num() > 0) { 185 | int32 index = FMath::RandRange(0, SelectedBrushMeshes.Num() - 1); 186 | RandomMesh = SelectedBrushMeshes[index]; 187 | } 188 | BrushMeshComponent->SetStaticMesh(RandomMesh ? RandomMesh : DefaultBrushMesh); 189 | ActiveBrushMesh = RandomMesh; 190 | } 191 | 192 | void FEdModeHaste::PostUndo() 193 | { 194 | FEdMode::PostUndo(); 195 | 196 | //StaticCastSharedPtr(Toolkit)->RefreshFullList(); 197 | } 198 | 199 | /** When the user changes the active streaming level with the level browser */ 200 | void FEdModeHaste::NotifyNewCurrentLevel() 201 | { 202 | 203 | } 204 | 205 | /** When the user changes the current tool in the UI */ 206 | void FEdModeHaste::NotifyToolChanged() 207 | { 208 | 209 | } 210 | 211 | bool FEdModeHaste::DisallowMouseDeltaTracking() const 212 | { 213 | // We never want to use the mouse delta tracker while painting 214 | return bToolActive; 215 | } 216 | 217 | /** FEdMode: Called once per frame */ 218 | void FEdModeHaste::Tick(FEditorViewportClient* ViewportClient, float DeltaTime) 219 | { 220 | if (bToolActive) 221 | { 222 | //ApplyBrush(ViewportClient); 223 | } 224 | 225 | FEdMode::Tick(ViewportClient, DeltaTime); 226 | 227 | // Trace the brush 228 | HasteBrushTrace(ViewportClient, LastMousePosition.X, LastMousePosition.Y); 229 | 230 | 231 | // Update the position and size of the brush component 232 | if (bBrushTraceValid) 233 | { 234 | // Scale adjustment is due to default sphere SM size. 235 | BrushMeshComponent->SetRelativeTransform(BrushCursorTransform); 236 | 237 | if (!BrushMeshComponent->IsRegistered()) 238 | { 239 | BrushMeshComponent->RegisterComponentWithWorld(ViewportClient->GetWorld()); 240 | } 241 | } 242 | else 243 | { 244 | if (BrushMeshComponent->IsRegistered()) 245 | { 246 | BrushMeshComponent->UnregisterComponent(); 247 | } 248 | } 249 | } 250 | 251 | static bool HasteTrace(UWorld* InWorld, FHitResult& OutHit, FVector InStart, FVector InEnd, FName InTraceTag, bool InbReturnFaceIndex = false) 252 | { 253 | FCollisionQueryParams QueryParams(InTraceTag, true); 254 | QueryParams.bReturnFaceIndex = InbReturnFaceIndex; 255 | 256 | bool bResult = true; 257 | while (true) 258 | { 259 | bResult = InWorld->LineTraceSingleByChannel(OutHit, InStart, InEnd, ECC_WorldStatic, QueryParams); 260 | if (bResult) 261 | { 262 | // In the editor traces can hit "No Collision" type actors, so ugh. 263 | FBodyInstance* BodyInstance = OutHit.Component->GetBodyInstance(); 264 | if (BodyInstance->GetCollisionEnabled() != ECollisionEnabled::QueryAndPhysics || BodyInstance->GetResponseToChannel(ECC_WorldStatic) != ECR_Block) 265 | { 266 | AActor* Actor = OutHit.Actor.Get(); 267 | if (Actor) 268 | { 269 | QueryParams.AddIgnoredActor(Actor); 270 | } 271 | InStart = OutHit.ImpactPoint; 272 | continue; 273 | } 274 | } 275 | break; 276 | } 277 | return bResult; 278 | } 279 | 280 | FVector PerformLocationSnap(const FVector& Location) { 281 | //ULevelEditorViewportSettings* ViewportSettings = GetMutableDefault(); 282 | //int32 SnapWidth = ViewportSettings->GridEnabled; 283 | int32 SnapWidth = GEditor->GetGridSize(); 284 | if (SnapWidth <= 0) { 285 | return Location; 286 | } 287 | float X = Location.X / SnapWidth; 288 | float Y = Location.Y / SnapWidth; 289 | float Z = Location.Z / SnapWidth; 290 | 291 | X = FMath::RoundToInt(X) * SnapWidth; 292 | Y = FMath::RoundToInt(Y) * SnapWidth; 293 | Z = FMath::RoundToInt(Z) * SnapWidth; 294 | return FVector(X, Y, Z); 295 | } 296 | 297 | /** Trace under the mouse cursor and update brush position */ 298 | void FEdModeHaste::HasteBrushTrace(FEditorViewportClient* ViewportClient, int32 MouseX, int32 MouseY) 299 | { 300 | bBrushTraceValid = false; 301 | if (!ViewportClient->IsMovingCamera()) 302 | { 303 | // Compute a world space ray from the screen space mouse coordinates 304 | FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues( 305 | ViewportClient->Viewport, 306 | ViewportClient->GetScene(), 307 | ViewportClient->EngineShowFlags) 308 | .SetRealtimeUpdate(ViewportClient->IsRealtime())); 309 | FSceneView* View = ViewportClient->CalcSceneView(&ViewFamily); 310 | FViewportCursorLocation MouseViewportRay(View, ViewportClient, MouseX, MouseY); 311 | 312 | FVector Start = MouseViewportRay.GetOrigin(); 313 | BrushTraceDirection = MouseViewportRay.GetDirection(); 314 | FVector End = Start + WORLD_MAX * BrushTraceDirection; 315 | 316 | FHitResult Hit; 317 | UWorld* World = ViewportClient->GetWorld(); 318 | static FName NAME_HasteBrush = FName(TEXT("HasteBrush")); 319 | if (HasteTrace(World, Hit, Start, End, NAME_HasteBrush)) 320 | { 321 | // Adjust the sphere brush 322 | BrushLocation = PerformLocationSnap(Hit.Location); 323 | 324 | // Find the rotation based on the normal 325 | LastHitImpact = Hit.ImpactNormal; 326 | UpdateBrushRotation(); 327 | 328 | bBrushTraceValid = true; 329 | } 330 | } 331 | 332 | if (bBrushTraceValid) { 333 | BrushCursorTransform = FTransform(BrushRotation, BrushLocation, BrushScale); 334 | BrushCursorTransform = ApplyTransformers(BrushCursorTransform); 335 | } 336 | } 337 | 338 | float SnapRotation(float Value, float SnapWidth) { 339 | return FMath::RoundToInt(Value / SnapWidth) * SnapWidth; 340 | } 341 | 342 | void FEdModeHaste::UpdateBrushRotation() 343 | { 344 | BrushRotation = FQuat::FindBetween(FVector(0, 0, 1), LastHitImpact); 345 | 346 | // Append the brush rotation 347 | if (UISettings->bRotateOnScroll) { 348 | float RotSnapWidth = GEditor->GetRotGridSize().Yaw; 349 | float SnappedOffsetX = SnapRotation(RotationOffset.X, RotSnapWidth); 350 | float SnappedOffsetY = SnapRotation(RotationOffset.Y, RotSnapWidth); 351 | float SnappedOffsetZ = SnapRotation(RotationOffset.Z, RotSnapWidth); 352 | BrushRotation = BrushRotation * FQuat(FVector(0, 0, 1), SnappedOffsetZ * PI / 180.0f); 353 | } 354 | } 355 | 356 | 357 | /** 358 | * Called when the mouse is moved over the viewport 359 | * 360 | * @param InViewportClient Level editor viewport client that captured the mouse input 361 | * @param InViewport Viewport that captured the mouse input 362 | * @param InMouseX New mouse cursor X coordinate 363 | * @param InMouseY New mouse cursor Y coordinate 364 | * 365 | * @return true if input was handled 366 | */ 367 | bool FEdModeHaste::MouseMove(FEditorViewportClient* ViewportClient, FViewport* Viewport, int32 MouseX, int32 MouseY) 368 | { 369 | FIntVector CurrentMousePosition(MouseX, MouseY, 0); 370 | if (LastMousePosition != CurrentMousePosition) { 371 | //UE_LOG(LogHasteMode, Log, TEXT("MouseMove (%d, %d)"), MouseX, MouseY); 372 | LastMousePosition = CurrentMousePosition; 373 | //HasteBrushTrace(ViewportClient, MouseX, MouseY); 374 | return bBrushTraceValid; 375 | } 376 | 377 | return false; 378 | } 379 | 380 | /** 381 | * Called when the mouse is moved while a window input capture is in effect 382 | * 383 | * @param InViewportClient Level editor viewport client that captured the mouse input 384 | * @param InViewport Viewport that captured the mouse input 385 | * @param InMouseX New mouse cursor X coordinate 386 | * @param InMouseY New mouse cursor Y coordinate 387 | * 388 | * @return true if input was handled 389 | */ 390 | bool FEdModeHaste::CapturedMouseMove(FEditorViewportClient* ViewportClient, FViewport* Viewport, int32 MouseX, int32 MouseY) 391 | { 392 | FIntVector CurrentMousePosition(MouseX, MouseY, 0); 393 | if (LastMousePosition != CurrentMousePosition && !bMeshRotating) { 394 | //UE_LOG(LogHasteMode, Log, TEXT("CapturedMouseMove (%d, %d)"), MouseX, MouseY); 395 | LastMousePosition = CurrentMousePosition; 396 | //HasteBrushTrace(ViewportClient, MouseX, MouseY); 397 | return bBrushTraceValid; 398 | } 399 | 400 | return false; 401 | } 402 | 403 | void FEdModeHaste::GetRandomVectorInBrush(FVector& OutStart, FVector& OutEnd) 404 | { 405 | // Find Rx and Ry inside the unit circle 406 | float Ru = (2.f * FMath::FRand() - 1.f); 407 | float Rv = (2.f * FMath::FRand() - 1.f) * FMath::Sqrt(1.f - FMath::Square(Ru)); 408 | 409 | // find random point in circle thru brush location parallel to screen surface 410 | FVector U, V; 411 | BrushTraceDirection.FindBestAxisVectors(U, V); 412 | FVector Point = Ru * U + Rv * V; 413 | 414 | // find distance to surface of sphere brush from this point 415 | float Rw = FMath::Sqrt(1.f - (FMath::Square(Ru) + FMath::Square(Rv))); 416 | 417 | OutStart = BrushLocation + BRUSH_RADIUS * (Ru * U + Rv * V - Rw * BrushTraceDirection); 418 | OutEnd = BrushLocation + BRUSH_RADIUS * (Ru * U + Rv * V + Rw * BrushTraceDirection); 419 | } 420 | 421 | void FEdModeHaste::ApplyBrush(FEditorViewportClient* ViewportClient) 422 | { 423 | if (!bBrushTraceValid) 424 | { 425 | return; 426 | } 427 | } 428 | 429 | 430 | /** FEdMode: Called when a key is pressed */ 431 | bool FEdModeHaste::InputKey(FEditorViewportClient* ViewportClient, FViewport* Viewport, FKey Key, EInputEvent Event) 432 | { 433 | // Rotate if mouse wheel is scrolled 434 | if (Key == EKeys::MouseScrollUp || Key == EKeys::MouseScrollDown) { 435 | int32 WheelDelta = (Key == EKeys::MouseScrollUp) ? 1 : -1; 436 | const float ScrollSpeed = 1; 437 | float AngleDelta = WheelDelta * ROTATION_SPEED * ScrollSpeed; 438 | 439 | bool bShiftDown = IsShiftDown(Viewport); 440 | bool bCtrlDown = IsCtrlDown(Viewport); 441 | if (bCtrlDown) { 442 | RotationOffset.X += AngleDelta; 443 | } 444 | else if (bShiftDown) { 445 | RotationOffset.Y += AngleDelta; 446 | } 447 | else { 448 | RotationOffset.Z += AngleDelta; 449 | } 450 | return true; 451 | } 452 | return false; 453 | } 454 | 455 | /** FEdMode: Render the haste edit mode */ 456 | void FEdModeHaste::Render(const FSceneView* View, FViewport* Viewport, FPrimitiveDrawInterface* PDI) 457 | { 458 | /** Call parent implementation */ 459 | FEdMode::Render(View, Viewport, PDI); 460 | } 461 | 462 | 463 | /** FEdMode: Render HUD elements for this tool */ 464 | void FEdModeHaste::DrawHUD(FEditorViewportClient* ViewportClient, FViewport* Viewport, const FSceneView* View, FCanvas* Canvas) 465 | { 466 | } 467 | 468 | /** FEdMode: Check to see if an actor can be selected in this mode - no side effects */ 469 | bool FEdModeHaste::IsSelectionAllowed(AActor* InActor, bool bInSelection) const 470 | { 471 | return false; 472 | } 473 | 474 | /** FEdMode: Handling SelectActor */ 475 | bool FEdModeHaste::Select(AActor* InActor, bool bInSelected) 476 | { 477 | // return true if you filter that selection 478 | // however - return false if we are trying to deselect so that it will infact do the deselection 479 | if (bInSelected == false) 480 | { 481 | return false; 482 | } 483 | return true; 484 | } 485 | 486 | /** FEdMode: Called when the currently selected actor has changed */ 487 | void FEdModeHaste::ActorSelectionChangeNotify() 488 | { 489 | } 490 | 491 | 492 | /** Forces real-time perspective viewports */ 493 | void FEdModeHaste::ForceRealTimeViewports(const bool bEnable, const bool bStoreCurrentState) 494 | { 495 | FLevelEditorModule& LevelEditorModule = FModuleManager::GetModuleChecked("LevelEditor"); 496 | TSharedPtr< ILevelViewport > ViewportWindow = LevelEditorModule.GetFirstActiveViewport(); 497 | if (ViewportWindow.IsValid()) 498 | { 499 | FEditorViewportClient &Viewport = ViewportWindow->GetLevelViewportClient(); 500 | if (Viewport.IsPerspective()) 501 | { 502 | if (bEnable) 503 | { 504 | Viewport.SetRealtime(bEnable, bStoreCurrentState); 505 | } 506 | else 507 | { 508 | const bool bAllowDisable = true; 509 | Viewport.RestoreRealtime(bAllowDisable); 510 | } 511 | 512 | } 513 | } 514 | } 515 | 516 | bool FEdModeHaste::HandleClick(FEditorViewportClient* InViewportClient, HHitProxy *HitProxy, const FViewportClick &Click) 517 | { 518 | if (ActiveBrushMesh && !bMeshRotating) { 519 | AStaticMeshActor* MeshActor = GetWorld()->SpawnActor(AStaticMeshActor::StaticClass()); 520 | 521 | // Rename the display name of the new actor in the editor to reflect the mesh that is being created from. 522 | FActorLabelUtilities::SetActorLabelUnique(MeshActor, ActiveBrushMesh->GetName()); 523 | 524 | MeshActor->GetStaticMeshComponent()->SetStaticMesh(ActiveBrushMesh); 525 | MeshActor->ReregisterAllComponents(); 526 | MeshActor->SetActorTransform(BrushCursorTransform); 527 | 528 | // Switch to another mesh from the list 529 | ResetBrushMesh(); 530 | } 531 | 532 | return FEdMode::HandleClick(InViewportClient, HitProxy, Click); 533 | } 534 | 535 | FTransform FEdModeHaste::ApplyTransformers(const FTransform& BaseTransform) 536 | { 537 | FTransform Transform = BaseTransform; 538 | 539 | if (UISettings) { 540 | for (UHasteTransformLogic* TransformLogic : UISettings->Transformers) { 541 | if (!TransformLogic) continue; 542 | FTransform Offset; 543 | TransformLogic->TransformObject(Transform, Offset); 544 | Transform = Offset * Transform; 545 | } 546 | } 547 | 548 | return Transform; 549 | } 550 | 551 | FVector FEdModeHaste::GetWidgetLocation() const 552 | { 553 | return FEdMode::GetWidgetLocation(); 554 | } 555 | 556 | /** FEdMode: Called when a mouse button is pressed */ 557 | bool FEdModeHaste::StartTracking(FEditorViewportClient* InViewportClient, FViewport* InViewport) 558 | { 559 | bMeshRotating = IsCtrlDown(InViewport) || IsShiftDown(InViewport); 560 | 561 | return FEdMode::StartTracking(InViewportClient, InViewport); 562 | } 563 | 564 | /** FEdMode: Called when the a mouse button is released */ 565 | bool FEdModeHaste::EndTracking(FEditorViewportClient* InViewportClient, FViewport* InViewport) 566 | { 567 | bMeshRotating = false; 568 | 569 | return FEdMode::EndTracking(InViewportClient, InViewport); 570 | } 571 | 572 | /** FEdMode: Called when mouse drag input it applied */ 573 | bool FEdModeHaste::InputDelta(FEditorViewportClient* InViewportClient, FViewport* InViewport, FVector& InDrag, FRotator& InRot, FVector& InScale) 574 | { 575 | if (bMeshRotating) { 576 | bool bShiftDown = IsShiftDown(InViewport); 577 | bool bCtrlDown = IsCtrlDown(InViewport); 578 | 579 | float AngleDelta = FMath::Sign(InDrag.X) * ROTATION_SPEED; 580 | if (bShiftDown && bCtrlDown) { 581 | RotationOffset.Y += AngleDelta; 582 | } 583 | else if (bShiftDown) { 584 | RotationOffset.Z += AngleDelta; 585 | } 586 | else if (bCtrlDown) { 587 | RotationOffset.X += AngleDelta; 588 | } 589 | UpdateBrushRotation(); 590 | return true; 591 | } 592 | return FEdMode::InputDelta(InViewportClient, InViewport, InDrag, InRot, InScale); 593 | } 594 | 595 | bool FEdModeHaste::AllowWidgetMove() 596 | { 597 | return ShouldDrawWidget(); 598 | } 599 | 600 | bool FEdModeHaste::UsesTransformWidget() const 601 | { 602 | return ShouldDrawWidget(); 603 | } 604 | 605 | bool FEdModeHaste::ShouldDrawWidget() const 606 | { 607 | return true; 608 | } 609 | 610 | EAxisList::Type FEdModeHaste::GetWidgetAxisToDraw(FWidget::EWidgetMode InWidgetMode) const 611 | { 612 | switch (InWidgetMode) 613 | { 614 | case FWidget::WM_Translate: 615 | case FWidget::WM_Rotate: 616 | case FWidget::WM_Scale: 617 | return EAxisList::XYZ; 618 | default: 619 | return EAxisList::None; 620 | } 621 | } 622 | 623 | #undef LOCTEXT_NAMESPACE -------------------------------------------------------------------------------- /Source/HasteEditor/Private/HasteEdMode.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Code Respawn Technologies. MIT License 2 | 3 | #pragma once 4 | #include "EdMode.h" 5 | 6 | DECLARE_LOG_CATEGORY_EXTERN(LogHasteMode, Log, All); 7 | 8 | /** 9 | * Haste editor mode 10 | */ 11 | class FEdModeHaste : public FEdMode 12 | { 13 | public: 14 | 15 | /** Constructor */ 16 | FEdModeHaste(); 17 | 18 | /** Destructor */ 19 | virtual ~FEdModeHaste(); 20 | 21 | /** FGCObject interface */ 22 | virtual void AddReferencedObjects(FReferenceCollector& Collector) override; 23 | 24 | /** FEdMode: Called when the mode is entered */ 25 | virtual void Enter() override; 26 | 27 | /** FEdMode: Called when the mode is exited */ 28 | virtual void Exit() override; 29 | 30 | /** FEdMode: Called after an Undo operation */ 31 | virtual void PostUndo() override; 32 | 33 | /** 34 | * Called when the mouse is moved over the viewport 35 | * 36 | * @param InViewportClient Level editor viewport client that captured the mouse input 37 | * @param InViewport Viewport that captured the mouse input 38 | * @param InMouseX New mouse cursor X coordinate 39 | * @param InMouseY New mouse cursor Y coordinate 40 | * 41 | * @return true if input was handled 42 | */ 43 | virtual bool MouseMove(FEditorViewportClient* ViewportClient, FViewport* Viewport, int32 x, int32 y) override; 44 | 45 | /** 46 | * FEdMode: Called when the mouse is moved while a window input capture is in effect 47 | * 48 | * @param InViewportClient Level editor viewport client that captured the mouse input 49 | * @param InViewport Viewport that captured the mouse input 50 | * @param InMouseX New mouse cursor X coordinate 51 | * @param InMouseY New mouse cursor Y coordinate 52 | * 53 | * @return true if input was handled 54 | */ 55 | virtual bool CapturedMouseMove(FEditorViewportClient* InViewportClient, FViewport* InViewport, int32 InMouseX, int32 InMouseY) override; 56 | 57 | /** FEdMode: Called when a mouse button is pressed */ 58 | virtual bool StartTracking(FEditorViewportClient* InViewportClient, FViewport* InViewport) override; 59 | 60 | /** FEdMode: Called when a mouse button is released */ 61 | virtual bool EndTracking(FEditorViewportClient* InViewportClient, FViewport* InViewport) override; 62 | 63 | /** FEdMode: Called once per frame */ 64 | virtual void Tick(FEditorViewportClient* ViewportClient, float DeltaTime) override; 65 | 66 | /** FEdMode: Called when a key is pressed */ 67 | virtual bool InputKey(FEditorViewportClient* InViewportClient, FViewport* InViewport, FKey InKey, EInputEvent InEvent) override; 68 | 69 | /** FEdMode: Called when mouse drag input it applied */ 70 | virtual bool InputDelta(FEditorViewportClient* InViewportClient, FViewport* InViewport, FVector& InDrag, FRotator& InRot, FVector& InScale) override; 71 | 72 | /** FEdMode: Render elements for the Haste tool */ 73 | virtual void Render(const FSceneView* View, FViewport* Viewport, FPrimitiveDrawInterface* PDI) override; 74 | 75 | /** FEdMode: Render HUD elements for this tool */ 76 | virtual void DrawHUD(FEditorViewportClient* ViewportClient, FViewport* Viewport, const FSceneView* View, FCanvas* Canvas) override; 77 | 78 | /** FEdMode: Handling SelectActor */ 79 | virtual bool Select(AActor* InActor, bool bInSelected) override; 80 | 81 | /** FEdMode: Check to see if an actor can be selected in this mode - no side effects */ 82 | virtual bool IsSelectionAllowed(AActor* InActor, bool bInSelection) const override; 83 | 84 | /** FEdMode: Called when the currently selected actor has changed */ 85 | virtual void ActorSelectionChangeNotify() override; 86 | 87 | /** Notifies all active modes of mouse click messages. */ 88 | bool HandleClick(FEditorViewportClient* InViewportClient, HHitProxy *HitProxy, const FViewportClick &Click); 89 | 90 | /** Called when the current level changes */ 91 | void NotifyNewCurrentLevel(); 92 | 93 | /** Called when the user changes the current tool in the UI */ 94 | void NotifyToolChanged(); 95 | 96 | void OnContentBrowserSelectionChanged(const TArray& NewSelectedAssets, bool bIsPrimaryBrowser); 97 | 98 | /** FEdMode: widget handling */ 99 | virtual FVector GetWidgetLocation() const override; 100 | virtual bool AllowWidgetMove(); 101 | virtual bool ShouldDrawWidget() const override; 102 | virtual bool UsesTransformWidget() const override; 103 | virtual EAxisList::Type GetWidgetAxisToDraw(FWidget::EWidgetMode InWidgetMode) const override; 104 | 105 | virtual bool DisallowMouseDeltaTracking() const override; 106 | 107 | /** Forces real-time perspective viewports */ 108 | void ForceRealTimeViewports(const bool bEnable, const bool bStoreCurrentState); 109 | 110 | /** Trace under the mouse cursor and update brush position */ 111 | void HasteBrushTrace(FEditorViewportClient* ViewportClient, int32 MouseX, int32 MouseY); 112 | 113 | /** Generate start/end points for a random trace inside the sphere brush. 114 | returns a line segment inside the sphere parallel to the view direction */ 115 | void GetRandomVectorInBrush(FVector& OutStart, FVector& OutEnd); 116 | 117 | /** Apply brush */ 118 | void ApplyBrush(FEditorViewportClient* ViewportClient); 119 | 120 | void ResetBrushMesh(); 121 | 122 | void UpdateBrushRotation(); 123 | 124 | static FEditorModeID EM_Haste; 125 | 126 | private: 127 | FTransform ApplyTransformers(const FTransform& BaseTransform); 128 | 129 | private: 130 | bool bBrushTraceValid; 131 | FVector BrushLocation; 132 | FVector BrushScale; 133 | FQuat BrushRotation; 134 | FTransform BrushCursorTransform; 135 | FIntVector LastMousePosition; 136 | 137 | FVector BrushTraceDirection; 138 | TArray SelectedBrushMeshes; 139 | UStaticMesh* ActiveBrushMesh; 140 | UStaticMesh* DefaultBrushMesh; 141 | UStaticMeshComponent* BrushMeshComponent; 142 | 143 | FVector LastHitImpact; 144 | 145 | bool bToolActive; 146 | bool bCanAltDrag; 147 | bool bMeshRotating; 148 | 149 | FVector RotationOffset; 150 | 151 | FDelegateHandle ContentBrowserSelectionChangeDelegate; 152 | 153 | class UHasteEdModeSettings* UISettings; 154 | }; -------------------------------------------------------------------------------- /Source/HasteEditor/Private/HasteEdModeSettings.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Code Respawn Technologies. MIT License 2 | #include "HasteEditorPrivatePCH.h" 3 | #include "HasteEdModeSettings.h" 4 | 5 | UHasteEdModeSettings::UHasteEdModeSettings(const FObjectInitializer& ObjectInitializer) 6 | : Super(ObjectInitializer) 7 | { 8 | bRotateOnScroll = true; 9 | } 10 | -------------------------------------------------------------------------------- /Source/HasteEditor/Private/HasteEdModeSettings.h: -------------------------------------------------------------------------------- 1 | //$ Copyright 2015 Ali Akbar, Code Respawn Technologies Pvt Ltd - All Rights Reserved $// 2 | #pragma once 3 | #include "Transformer/HasteTransformLogic.h" 4 | #include "HasteEdModeSettings.generated.h" 5 | 6 | UCLASS() 7 | class UHasteEdModeSettings : public UObject { 8 | GENERATED_UCLASS_BODY() 9 | 10 | public: 11 | 12 | /** Rules to transform your object when it is placed in the map */ 13 | UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, SimpleDisplay, Category = Haste) 14 | TArray Transformers; 15 | 16 | 17 | /** Lets you emit your own markers into the scene */ 18 | UPROPERTY(EditAnywhere, Category = Haste) 19 | bool bRotateOnScroll; 20 | }; 21 | -------------------------------------------------------------------------------- /Source/HasteEditor/Private/HasteEdModeToolkit.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Code Respawn Technologies. MIT License 2 | #include "HasteEditorPrivatePCH.h" 3 | #include "HasteEdModeToolkit.h" 4 | #include "HasteEdMode.h" 5 | #include "PropertyEditorModule.h" 6 | #include "ModuleManager.h" 7 | #include "IDetailsView.h" 8 | 9 | #define LOCTEXT_NAMESPACE "HasteEditMode" 10 | 11 | void FHasteEdModeToolkit::Init(const TSharedPtr< class IToolkitHost >& InitToolkitHost) 12 | { 13 | FModeToolkit::Init(InitToolkitHost); 14 | } 15 | 16 | FName FHasteEdModeToolkit::GetToolkitFName() const 17 | { 18 | return FName("HasteEditMode"); 19 | } 20 | 21 | FText FHasteEdModeToolkit::GetBaseToolkitName() const 22 | { 23 | return LOCTEXT("ToolkitName", "Haste Edit Mode"); 24 | } 25 | 26 | FEdMode* FHasteEdModeToolkit::GetEditorMode() const 27 | { 28 | return GLevelEditorModeTools().GetActiveMode(FEdModeHaste::EM_Haste); 29 | } 30 | 31 | TSharedPtr FHasteEdModeToolkit::GetInlineContent() const 32 | { 33 | return HasteEdWidget; 34 | } 35 | 36 | void FHasteEdModeToolkit::SetInlineContent(TSharedPtr Widget) 37 | { 38 | HasteEdWidget = Widget; 39 | } 40 | 41 | void SHasteEditor::Construct(const FArguments& InArgs) 42 | { 43 | FPropertyEditorModule& PropertyEditorModule = FModuleManager::LoadModuleChecked("PropertyEditor"); 44 | FDetailsViewArgs DetailsViewArgs(false, false, false, FDetailsViewArgs::HideNameArea); 45 | 46 | DetailsPanel = PropertyEditorModule.CreateDetailView(DetailsViewArgs); 47 | 48 | this->ChildSlot 49 | [ 50 | SNew(SVerticalBox) 51 | 52 | + SVerticalBox::Slot() 53 | .AutoHeight() 54 | [ 55 | DetailsPanel.ToSharedRef() 56 | ] 57 | ]; 58 | } 59 | 60 | void SHasteEditor::SetSettingsObject(UObject* Object, bool bForceRefresh /*= false*/) 61 | { 62 | if (DetailsPanel.IsValid()) { 63 | DetailsPanel->SetObject(Object, bForceRefresh); 64 | } 65 | } 66 | 67 | #undef LOCTEXT_NAMESPACE -------------------------------------------------------------------------------- /Source/HasteEditor/Private/HasteEdModeToolkit.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Code Respawn Technologies. MIT License 2 | #pragma once 3 | 4 | #include "Toolkits/BaseToolkit.h" 5 | 6 | class SWidget; 7 | class FEdMode; 8 | 9 | class FHasteEdModeToolkit : public FModeToolkit 10 | { 11 | public: 12 | /** Initializes the dungeon mode toolkit */ 13 | virtual void Init(const TSharedPtr< class IToolkitHost >& InitToolkitHost); 14 | 15 | /** IToolkit interface */ 16 | virtual FName GetToolkitFName() const override; 17 | virtual FText GetBaseToolkitName() const override; 18 | virtual FEdMode* GetEditorMode() const override; 19 | virtual TSharedPtr GetInlineContent() const override; 20 | 21 | void SetInlineContent(TSharedPtr Widget); 22 | 23 | private: 24 | TSharedPtr HasteEdWidget; 25 | }; 26 | 27 | 28 | class SHasteEditor : public SCompoundWidget { 29 | public: 30 | SLATE_BEGIN_ARGS(SHasteEditor) {} 31 | SLATE_END_ARGS() 32 | 33 | 34 | public: 35 | /** SCompoundWidget functions */ 36 | void Construct(const FArguments& InArgs); 37 | 38 | void SetSettingsObject(UObject* Object, bool bForceRefresh = false); 39 | 40 | private: 41 | TSharedPtr DetailsPanel; 42 | 43 | }; -------------------------------------------------------------------------------- /Source/HasteEditor/Private/HasteEditorModule.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Code Respawn Technologies. MIT License 2 | 3 | #include "HasteEditorPrivatePCH.h" 4 | 5 | #include "AssetToolsModule.h" 6 | #include "PropertyEditorModule.h" 7 | #include "LevelEditor.h" 8 | #include "LevelEditorActions.h" 9 | 10 | #include "ModuleManager.h" 11 | #include "HasteEdMode.h" 12 | 13 | #define LOCTEXT_NAMESPACE "HasteEditorModule" 14 | 15 | class FHasteEditorModule : public IHasteEditorModule 16 | { 17 | /** IModuleInterface implementation */ 18 | virtual void StartupModule() override { 19 | FEditorModeRegistry::Get().RegisterMode( 20 | FEdModeHaste::EM_Haste, 21 | NSLOCTEXT("EditorModes", "HasteMode", "Haste"), 22 | FSlateIcon(FEditorStyle::GetStyleSetName(), "LevelEditor.FoliageMode", "LevelEditor.FoliageMode.Small"), 23 | true, 400 24 | ); 25 | } 26 | 27 | 28 | virtual void ShutdownModule() override { 29 | FEditorModeRegistry::Get().UnregisterMode(FEdModeHaste::EM_Haste); 30 | } 31 | }; 32 | 33 | IMPLEMENT_MODULE(FHasteEditorModule, HasteEditorModule) 34 | 35 | 36 | #undef LOCTEXT_NAMESPACE -------------------------------------------------------------------------------- /Source/HasteEditor/Private/HasteEditorPrivatePCH.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Code Respawn Technologies. MIT License 2 | 3 | #include "CoreUObject.h" 4 | 5 | // You should place include statements to your module's private header files here. You only need to 6 | // add includes for headers that are used in most of your module's source files though. 7 | #include "HasteEditorModule.h" 8 | #include "Engine.h" 9 | #include "UnrealEd.h" 10 | 11 | 12 | -------------------------------------------------------------------------------- /Source/HasteEditor/Private/Transformer/HasteTransformLogic.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Code Respawn Technologies. MIT License 2 | #include "HasteEditorPrivatePCH.h" 3 | #include "HasteTransformLogic.h" 4 | 5 | 6 | void UHasteTransformLogic::TransformObject_Implementation(const FTransform& CurrentTransform, FTransform& Offset) 7 | { 8 | Offset = FTransform::Identity; 9 | } 10 | -------------------------------------------------------------------------------- /Source/HasteEditor/Private/Transformer/HasteTransformLogic.h: -------------------------------------------------------------------------------- 1 | //$ Copyright 2015 Ali Akbar, Code Respawn Technologies Pvt Ltd - All Rights Reserved $// 2 | #pragma once 3 | #include "HasteTransformLogic.generated.h" 4 | 5 | UCLASS(EditInlineNew, DefaultToInstanced, BlueprintType, Blueprintable, HideDropDown, abstract) 6 | class UHasteTransformLogic : public UObject 7 | { 8 | GENERATED_BODY() 9 | 10 | public: 11 | UFUNCTION(BlueprintNativeEvent, Category = "Dungeon") 12 | void TransformObject(const FTransform& CurrentTransform, FTransform& Offset); 13 | virtual void TransformObject_Implementation(const FTransform& CurrentTransform, FTransform& Offset); 14 | 15 | }; 16 | -------------------------------------------------------------------------------- /Source/HasteEditor/Private/Transformer/HasteTransformLogicRandomZ.cpp: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Code Respawn Technologies. MIT License 2 | #include "HasteEditorPrivatePCH.h" 3 | #include "HasteTransformLogicRandomZ.h" 4 | 5 | void UHasteTransformLogicRandomZ::TransformObject_Implementation(const FTransform& CurrentTransform, FTransform& Offset) 6 | { 7 | FQuat Rotation = FQuat::MakeFromEuler(FVector(0, 0, FMath::FRandRange(0, 360))); 8 | Offset = FTransform::Identity; 9 | Offset.SetRotation(Rotation); 10 | } 11 | -------------------------------------------------------------------------------- /Source/HasteEditor/Private/Transformer/HasteTransformLogicRandomZ.h: -------------------------------------------------------------------------------- 1 | //$ Copyright 2015 Ali Akbar, Code Respawn Technologies Pvt Ltd - All Rights Reserved $// 2 | #pragma once 3 | #include "HasteTransformLogicRandomZ.generated.h" 4 | 5 | UCLASS(EditInlineNew, DefaultToInstanced, BlueprintType, Blueprintable) 6 | class UHasteTransformLogicRandomZ : public UHasteTransformLogic 7 | { 8 | GENERATED_BODY() 9 | 10 | public: 11 | virtual void TransformObject_Implementation(const FTransform& CurrentTransform, FTransform& Offset) override; 12 | }; 13 | -------------------------------------------------------------------------------- /Source/HasteEditor/Public/HasteEditorModule.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2016 Code Respawn Technologies. MIT License 2 | 3 | #pragma once 4 | 5 | #include "UnrealEd.h" 6 | #include "ModuleManager.h" 7 | #include "ModuleInterface.h" 8 | 9 | 10 | /** 11 | * The public interface to this module 12 | */ 13 | class IHasteEditorModule : public IModuleInterface 14 | { 15 | 16 | public: 17 | 18 | /** 19 | * Singleton-like access to this module's interface. This is just for convenience! 20 | * Beware of calling this during the shutdown phase, though. Your module might have been unloaded already. 21 | * 22 | * @return Returns singleton instance, loading the module on demand if needed 23 | */ 24 | static inline IHasteEditorModule& Get() 25 | { 26 | return FModuleManager::LoadModuleChecked< IHasteEditorModule >("HasteEditorModule"); 27 | } 28 | 29 | /** 30 | * Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true. 31 | * 32 | * @return True if the module is loaded and ready to use 33 | */ 34 | static inline bool IsAvailable() 35 | { 36 | return FModuleManager::Get().IsModuleLoaded( "HasteEditorModule" ); 37 | } 38 | }; 39 | 40 | --------------------------------------------------------------------------------