You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown Nick.Penwarden ========================== MAJOR FEATURES + CHANGES ========================== Change 3072953 on 2016/08/01 by Uriel.Doyon Texture GUIDs are now included in cooked builds, as they are required by the texture streamer to link build data to in game textures. #jira UE-34045 Change 3072915 on 2016/08/01 by Nick.Whiting Fixing Google VR Preview being distorted by fixing merge error specifying number of verts per distortion mesh #jira UE-34044 Change 3072891 on 2016/08/01 by Nick.Whiting Integrating fix from DevVR to force GameGetsMouseControl to on when using VR PIE, since you always need focus for motion controllers #jira UE-33579 Change 3072885 on 2016/08/01 by Nick.Darnell UMG/Slate - Moving the SlateTextureAtlasInterface to engine, and redoing the parameters so that we can properly calculate the UV start and size information with full knowledge inside the texture so that we can deal with problems like squaring that happens on PVRTC textures. Also moving the interface to engine so that dependent plugins/other consumers don't need to load their modules extremely early to deal with the RHIRenderers need to load early for the shaders, also wanted to avoid loading it when Paper2D is needed on servers. Continued - adding missing file. #jira UE-32876 Change 3072869 on 2016/08/01 by Ori.Cohen Fix CIS #jira UE-3402 Change 3072862 on 2016/08/01 by Josh.Adams - Fixed case issue for Linux #jira UE-34020 Change 3072818 on 2016/08/01 by Nick.Darnell UMG/Slate - Moving the SlateTextureAtlasInterface to engine, and redoing the parameters so that we can properly calculate the UV start and size information with full knowledge inside the texture so that we can deal with problems like squaring that happens on PVRTC textures. Also moving the interface to engine so that dependent plugins/other consumers don't need to load their modules extremely early to deal with the RHIRenderers need to load early for the shaders, also wanted to avoid loading it when Paper2D is needed on servers. #jira UE-32876 Change 3072756 on 2016/08/01 by John.Billon Fixed crash when setting a composite texture on a render target cube. #Jira UE-33885 Change 3072755 on 2016/08/01 by John.Billon Exposed GPUMorphTargets (r.MorphTarget.Mode) as a project setting. #Jira UE-33574 Change 3072753 on 2016/08/01 by John.Billon Fixed a possible null dereference in distrubutions that was causing crashes when changing particle parameters. #Jira UE-32565 #Jira UE-29528 Change 3072665 on 2016/08/01 by Ben.Marsh Fix parse errors in BuildGraph example script. Change 3072664 on 2016/08/01 by Mike.Beach Mirrors CL 3072620 from Dev-Blueprints. Reverting a presumptive (guessed-at) fix from CL 2830752 (UE-22075). This was preventing REINST classes from retaining certain UObject references (specifically data/objects stored in Actor's "CurrentTransactionAnnotation" member). Those objects would be GC'd during the reinstancing process, and when we copied that data over later, towards the end of reinstancing, we'd be copying bad object pointers to the new actors. #jira UE-29631 Change 3072656 on 2016/08/01 by Mike.Beach Mirrors CL 3072614 from Dev-Blueprints. Fixing an issue where hot-reloading a Blueprint parent class was not reinstancing skeleton CDOs. This caused problems later where the skel class layout didn't reflect the CDO object. #jira UE-29613 Change 3072649 on 2016/08/01 by Mike.Beach Mirrors CL 3071292 from Dev-Blueprints. Preventing the Blueprint reinstancer's Function/PropertyMap from being GC'd during compile. This was causing issues where new functions/properties were being allocated in the same pointer location, and UpdateBytecodeReferences() was replacing those references as well (specifically in unrelated class's Children->Next chain, linking in functions/properties that did not belong to that class). This was causing a multitude of problems (mainly bad property offset read/writes and endless field iterator loops). #jira UE-29631 Change 3072568 on 2016/08/01 by Phillip.Kavan Blueprints: Prevent a crash on load in RemoveNodeAndPromoteChildren when removing a corrupted SCS node if it has no parent link (the children are moved to the root node instead) Mirrored from //Orion/Dev-General (CLs# 3065749/3065868). #jira UE-32780 Change 3072565 on 2016/08/01 by Rolando.Caloca UE4.13 - More info to track down crash with missing Primitive uniform buffer #jira UE-33418 Change 3072526 on 2016/08/01 by Matt.Kuhlenschmidt Fix hovering broken in the details panel #jira UE-20903 Change 3072509 on 2016/08/01 by Matt.Kuhlenschmidt Removed nested list views in a details panel customization which caused the scrollbar in the details panel to become unusable #jira UE-20903 Change 3072479 on 2016/08/01 by Ori.Cohen Fix potential crash when calling SetSkeletalMesh on a skeletal mesh component that's using per poly collision #JIRA UE-34023 Change 3072438 on 2016/08/01 by Chris.Wood Fixed ICU dll loading logic so that monolithic tools like CRC don't try to load them. [UE-33943] - Crash Report Client window not opening in a packaged build #jira UE-33943 #test Editor, run Packaged QAGame, crash Packaged QAGame, runs CrashReportClient, run SlateViewer, run EpicGamesLauncher Change 3072360 on 2016/08/01 by Chris.Babcock Enable Google Play Games for ARM64 on Android #jira UE-34031 #ue4 #android Change 3072337 on 2016/08/01 by Mitchell.Wilson Saving multiple files from VR template to resolve empty engine version warnings. #jira UE-33937 Change 3072302 on 2016/08/01 by Lina.Halper Fix issue where weight doesn't update correctly while updating list #jira: UE-33023 Change 3072250 on 2016/08/01 by Lina.Halper Add error message when rename failed #jira: UE-33661 Change 3072103 on 2016/08/01 by Lina.Halper - Undid previous propagating change of morphtarget - Refresh function - Made sure whatever happening, the buffer size remains sane and render thread will always get the same size #code review: Rolando.Caloca #jira: UE-33923 Change 3072062 on 2016/08/01 by Jurre.deBaare Static Mesh Editor and Persona viewport are very dark #fix Added same default config value for the directional light rotation as in FPreviewScene (otherwise would result in nulled rotator) #jira UE-33945 Change 3072061 on 2016/08/01 by Jurre.deBaare Incorrect importing of morph target weights when setting the percentage bases option on import #fix use original number of singular values to index into the weights array (otherwise we would be reading incorrect data if NumUsedSingularValues != the original number #jira UE-34003 Change3072052on 2016/08/01 by Chris.Babcock Vulkan extension fixes for Android #jira UE-32943 #ue4 #android Change 3072039 on 2016/08/01 by Mitchell.Wilson Adding blueprint child of Paper2D character to the 2DSideScrollerExampleMap. #jira UE-33843 Change 3072003 on 2016/08/01 by Rob.Cannaday Change category of OnlineSubsystem, OnlineFramework from "TODO" to "Online Platform" to match other online subsystems. #jira UE-34008 Change 3071942 on 2016/08/01 by Matthew.Griffin Adding feature pack for TP_VirtualRealityBP Change 3071937 on 2016/08/01 by Max.Chen Sequence Recorder: Fix a bug where transforms wouldn't be captured if an anim recorder exists but the skeletal mesh that the anim recorder is supposed to capture doesn't exist. This fixes the first person template character not getting recorded. #jira UE-32918 Change 3071932 on 2016/08/01 by Dmitry.Rekman Linux: fix launch on (UE-33934) #tests Tested launching on a native host. #jira UE-33934 (Edigrating CL 3071928 //UE4/Dev-Platform/... to //UE4/Release-4.13/...) Change 3071926 on 2016/08/01 by Andrew.Rodham Sequencer: Fixed exponential slowdown when restoring selection states #jira UE-33918 Change 3071917 on 2016/08/01 by Mitchell.Wilson Disabled shadow casting on RTS_Env_Ice_Fort_Trim pieces that are placed along the path in TowerDefenseMap and rebuilt lighting. #jira UE-15196 Change 3071914 on 2016/08/01 by Allan.Bentham Fix for incorrect feature level when using networked PIE. #jira UE-25807 Change 3071894 on 2016/08/01 by Andrew.Rodham Sequence Recorder: CIS fix #jira UE-31277 Change 3071884 on 2016/08/01 by phillip.patterson Updated UMG_Invalidation.uasset to Include Combo Box Test #jira UE-29618 Change 3071869 on 2016/08/01 by Mitchell.Wilson Changed LPF Freq Max on example 1.5 to bettery demonstrate Loww Pass Filter feature. #jira UE-33714 Change 3071868 on 2016/08/01 by phillip.patterson Added UMG_Invalidation.uasset for a test case #jira UE-29618 Change 3071855 on 2016/08/01 by Jurre.deBaare Engine fails to compile in Alembic with DebugBuildsActuallyUseDebugCRT enabled #fix Recompiled zlib to be correct debug version #jira UE-27576 Change 3071853 on 2016/08/01 by Jurre.deBaare Fix issue with debug asserts not compiling correctly #fix Debug build will use a different macro path in DetourAssert/RecastAssert in which there is a , instead of a ; which the compiler complains about #jira UE-33989 Change 3071851 on 2016/08/01 by Matt.Kuhlenschmidt Added guards against force deleting objects garbage collecting objects while they are being deleted. This will still ensure in an attempt to isolate the actual issue. #jira UE-33013 Change 3071849 on 2016/08/01 by Tom.Looman Resaved content files with engine version for VR Template #jira ue-33325 Change 3071822 on 2016/08/01 by Mitchell.Wilson Adding crosshair to WeapLauncher when not sighted in. #jira UE-30617 Change 3071798 on 2016/08/01 by Andrew.Rodham Sequencer: Fixed various issues to do with recording attached components There were several edge cases where attached components would be recorded with incorrect animation, transforms, or not recorded at all. #jira UE-30574 #jira UE-31277 Change 3071789 on 2016/08/01 by Tom.Looman Fixed warning of missing gamemode in VR Template. #jira ue-33325 Change 3071787 on 2016/08/01 by Mitchell.Wilson Cleared material interface on Neutral.uasset to resolve a warning. #jira UE-33957 Change 3071784 on 2016/08/01 by Robert.Manuszewski Making sure UMediaPlayer objects are not added to any GC clusters because they can load additional assets after they had PostLoad called on them and that results in Disregard For GC assumptions being violated. #jira UE-33692 #jira UE-33814 Change 3071746 on 2016/08/01 by Tom.Looman Added config.ini for Feature Pack creation to VR Template #jira ue-33325 Change 3071694 on 2016/08/01 by Robert.Manuszewski Fixing crash after opening edit config data for remote build then packaging #jira UE-33719 Change 3071660 on 2016/08/01 by Dmitriy.Dyomin Fixed: Nexus 5, Android 4.4.4 has inverted R/B color channels with r.TonemapperFilm enabled (replaced usage of LinearToSrgbBranching with LinearToSrgbBranchless for mobile) Also removed "OutputDevice" branches that are not used on mobile, otherwise generated LUT pixel shader has more than 2k lines and device refuses to compile it #jira UE-30104 Change 3071657 on 2016/08/01 by Matthew.Griffin Excluded TP_VirtualRealityBP Template from Mac Binary builds. Change 3071651 on 2016/08/01 by Tom.Looman Removed config.ini ref from content.txt #jira UE-33325 Change 3071645 on 2016/08/01 by Jurre.deBaare Merge Actor Tool missing option to deselect Export Specific LOD #fix Added the ability to export a specific LOD or all LODs for the selected objects #jira UE-33100 Non wrapped UVs in static mesh cause incorrect UVs on (HLOD) merged static mesh #fix force to generate unique UVs for baking out the material to ensure we get the correct texture data #jira UE-29976 Change 3071608 on 2016/08/01 by Thomas.Sarkanen Bringing hitch tracking fix over from Orion. Engine: Properly resetting the hitch buckets at the start of each FPS chart, so hitch time isn't accumulated across multiple runs #jira UE-33911 - Time spent in hitch tracking buckets is not reset between fps chart captures (so it grows each capture in a session) Change 3071606 on 2016/08/01 by Matthew.Griffin Added TP_VirtualRealityBP to list of templates to make feature packs from, build DDC for and include in binary build. #jira UE-33959 Change 3071584 on 2016/08/01 by Matthew.Griffin Added support for per file Intellisense PCH settings, to improve its startup speed - disabled by default due to crashes. Split GetDirectIncludeDependencies function so that part of it could be used without having a build target. #jira UE-23720 Change 3071479 on 2016/07/31 by Dmitriy.Dyomin Fixed FAssetPtr remapping issues for duplicated packages (level Save As, level Duplicate). This fixes issue with broken foliage base cache. Hardened code in foliage base cache and removed asserts, so maps with broken cache can still load Merged from Dev-Mobile CL# 3057039 #jira UE-32774 Change 3071478 on 2016/07/31 by Uriel.Doyon Fixed UnbuiltInstanceBoundsList not being reset correctly, creating broken rendered primitives. #jira UE-32585 Change 3071282 on 2016/07/30 by Max.Chen Cine Camera Actor: CIS fix #jira UE-33805 Change 3071272 on 2016/07/30 by Max.Chen Cine Camera Actor: Fix debug focus plane not getting updated when animated. Refactor UpdateDebugFocusPlane so that it's called from the actor tick instead of just in GetCameraView. #jira UE-33805 Change 3071229 on 2016/07/30 by Ben.Marsh Fix static analysis warning. Change 3071077 on 2016/07/29 by Max.Chen Sequencer: Set relative location, rotation, scale explicitly to identity instead of calling ResetRelativeTransform because we don't want overlaps to fire until after the update pass. #jira UE-33432 Change 3071076 on 2016/07/29 by Max.Chen Sequencer: Set event track eval order to fire first. This fixes some ambiguity and also a bug where transform tracks don't evaluate pre/post if the eval position is changed in the middle of evaluation. #jira UE-33078 Change 3071070 on 2016/07/29 by Max.Chen Sequence Recorder: Record actors as possessables Added GetWorld() check when resolving bindings in case the world is being torn down. Copy from Dev-Sequencer #jira UE-33969 Change 3071069 on 2016/07/29 by Max.Chen Sequencer: Add Convert to Possessable Copy from Dev-Sequencer #jira UE-32139 Change 3071058 on 2016/07/29 by Max.Chen Sequencer: Tweak track colors Audio track brighter Transform, bool, event tracks less saturated Recording subsection more saturated Fade track gradient Copy from Dev-Sequencer #jira UE-33968 Change 3071057 on 2016/07/29 by Max.Chen Sequencer: Remove curve editor visibility as a toggleable config. It's now just a toggleable state that defaults to false. This fixes unexpected behavior of staying in the curve editor when restarting the editor or switching to a different level sequence asset. Copy from Dev-Sequencer #jira UE-33967 Change 3071004 on 2016/07/29 by Lauren.Ridge Fix for crash on color picker summon due to null SWindow #rb chris.gagnon #jira UE-33966 Change 3070956 on 2016/07/29 by Chris.Babcock Disable Oculus stress tests on Android(for now) to remove shader dependency unhandled on Mac editor #jira UE-33607 #ue4 #android Change 3070807 on 2016/07/29 by Nick.Darnell Slate - Disabling thickness calculation in slate lines, the underlying code doesn't properly handle the edge cases that causes a breakdown and the lines become flipped/twisted, or have zero width. #jira UE-30481 Change 3070779 on 2016/07/29 by Rob.Cannaday Re-add bCompileSteamOSS as deprecated with a notice on how to use OnlineSubsystemSteam Remove reference to bCompileSteamOSS from GameModule.Build.cs.template, replacing it with a comment of how to include OnlineSubsystemSteam #jira UE-33922 Change 3070766 on 2016/07/29 by Matt.Kuhlenschmidt Make sure richtooltips are not generated for hidden enum items so that there is not a mismatch between rich tooltips and enum items (causing a crash) #jira UE-33914 Change 3070764 on 2016/07/29 by Phillip.Kavan [UE-20581] Optimize BP auto-recompile on PIE startup for BPs with multiple dependencies. Mirrored from CL# 3065278. (resubmitted as edit) #jira UE-20581 Change 3070757 on 2016/07/29 by Nick.Darnell Slate - Anything that requests a CreateUpdatableTexture from the SlateRHIRenderer and later releaseses it, the renderer now keeps those releases around for an extra frame on the game thread to avoid deleting a pointer that may have already been queued up on the CPU side of the renderer to be used in an element batch. Which is what happens if you remove a widget in it's own tick, that happens to also contain a web browser widget. #jira UE-33450 Change 3070741 on 2016/07/29 by Phillip.Kavan Back out previous submit (forgot to convert to edit). #jira UE-20581 Change 3070737 on 2016/07/29 by Phillip.Kavan [UE-20581] Optimize BP auto-recompile on PIE startup for BPs with multiple dependencies. Mirrored from CL# 3065278. #jira UE-20581 Change 3070695 on 2016/07/29 by Ryan.Vance #jira UE-32145 We were using the wrong texture format for the rift ogl bridge. Removed derived ogl bridge destructor to fix assert. Based on CL 3069701 from Oculus Change 3070632 on 2016/07/29 by Mitchell.Wilson Rebuilt lighting for SubwaySequencer #jira UE-33564 Change 3070620 on 2016/07/29 by Chris.Babcock Fast ASTC texture compression, using ISPC. #jira UE-32308 Change 3070586 on 2016/07/29 by phillip.patterson Updating Sequencer_Focus for test case #jira UE-29618 Change 3070539 on 2016/07/29 by Jon.Nabozny Fix PhysX error where CCD is enabled on a Kinematic body. (This is copied from 3061370) #jira UE-33463 Change 3070538 on 2016/07/29 by Mitchell.Wilson Resaving TowerDefenseMap_Effects, TowerDefenseMap_Lights, and TowerDefenseMap_M to resolve MikkTSpace warnings. #jira UE-29730 Change 3070467 on 2016/07/29 by Lauren.Ridge Making the Color Picker accessible in VR Editing mode, hiding the eyedropper in VR mode. #rb mike.fricker #jira UE-33920 #jira UE-33769 Change 3070460 on 2016/07/29 by Lauren.Ridge Changing VR Screenshot mode to use direct capture of the mirrored view on the monitor #rb mike.fricker #jira UE-32413 Change 3070455 on 2016/07/29 by Lauren.Ridge Fixes for auto-entry to VR mode. Adding HMD validity checks, Steam VR only switches to not worn after being in the worn state, adding default setting to ini file. #rb mike.fricker #jira UE-33635 Change 3070404 on 2016/07/29 by John.Pollard Fix: Console command "Open" crashes with dedicated server settings #jira UE-32511 Change 3070380 on 2016/07/29 by Matt.Kuhlenschmidt Fix incorrect tooltip for the lerp instruction in the material editor #jira UE-33896 Change 3070376 on 2016/07/29 by Ryan.Vance #jira UEVR-32 Support base and neo multi-view vertex shaders on ps4. Compile both base and neo versions of the multi-view enabled vertex shaders. Pack them together in the resulting shader code. Unpack them and load the correct version when creating the vertex shader instance. Change 3070345 on 2016/07/29 by James.Cobbett #jira UE-29618 Submitting test assets for Alembic Importer Change 3070315 on 2016/07/29 by Ben.Woodhouse (cherry picked from dev-rendering) Fix for cooker crash with BC6H textures (XB1, but may affect other platforms). Also fixes corruption issue with texture slices not being a multiple of 4 pixels (expanding as necessary), courtesy of Stu McKenna at the Coalition Tested fix on xbox, PC and PS4, using QAGame #jira UE-28592 Change 3070314 on 2016/07/29 by Ben.Woodhouse (cherry picked from dev-rendering) Fix div 0 in motion blur. This caused artifacts in some fairly common cases #jira UE-32331 Change 3070272 on 2016/07/29 by Jon.Nabozny Fix CIS by removing unused (and deprecated) call to GetMovementInputVector() in ShooterCharacter. #jira UE-33944 Change 3070235 on 2016/07/29 by Mitchell.Wilson Hid Camera_Movement effects when the user is interacting with the sand in BP_RakeStuff. #jira UE-32742 Change 3070221 on 2016/07/29 by Jurre.deBaare HLOD: The forced viewing level slider does not stay in sync after building a cluster #fix The minimum drawing distance was being set to the original instead of the current value which would make it behaviour as normal (not being forced) #jira UE-32187 Change 3070218 on 2016/07/29 by Jurre.deBaare HLOD: Shadow logic in ALODActor is messed up #fix Moved shadow determination logic #jira UE-31753 Change 3070212 on 2016/07/29 by Jurre.deBaare HLOD Outliner scrolls back to the top when generating proxy meshes #fix Not refreshing the HLOD Outliner (not needed), and force scroll into view the first selected cluster #jira UE-30384 Change 3070176 on 2016/07/29 by Jurre.deBaare Some post processing features in Preview Scene Settings do not update immediately #fix Vector values as properties were not getting picked up due to their outer not being the struct but an FVector :D #jira UE-33895 Change 3070175 on 2016/07/29 by Jurre.deBaare Static Mesh Editor does not display Vertex Colors in Lit mode #fix Caused by not disabling advanced features which used to happen for preview scenes by default :/ #jira UE-32977 Change 3070163 on 2016/07/29 by Chris.Wood Changed log warnings to info when WinSAT assessment unavailable [UE-30198] - WinSAT assessment unavailable when running Hardware Survey #jira UE-30198 trivial change Change 3070154 on 2016/07/29 by Matthew.Griffin Removed exceptions for IOS .a files now we are building code projects Additional inclusions for Android/IOS that cannot be determined via Build Products/Runtime Dependencies #jira UE-33868 Change 3070124 on 2016/07/29 by Alex.Delesky #jira UE-32911 - Fixing an issue where thumbnail preview scenes would spawn an additional instance of its preview actor even if one was already in the scene. Also fixes a crash on shutdown due to cached thumbnail scenes not being released when thumbnail renderers begin destruction. Change 3070060 on 2016/07/29 by Chris.Wood Fixed command line argument saved to crash reports and used to restart crash processes [UE-30665] - CrashReporterClient send and restart does not reopen the project #jira UE-30665 trivial re-add of a line lost in a confusing merge. Change 3070035 on 2016/07/29 by Allan.Bentham Add cvars 'r.Android.DisableVulkanSupport' and 'r.Android.DisableOpenGLES31Support' Allows device profiles to disable vulkan and/or ES3.1. #jira UE-33379 Change 3070027 on 2016/07/29 by Tom.Looman Added fresh VR Template BP (origin: //depot/usr/Tom.Looman/VRTemplate/) #jira UE-33325 Change 3070009 on 2016/07/29 by James.Golding Disable 'convert proc mesh to static mesh' when template is selected. Also don't create static mesh if procmesh generate no geom. #jira UE-32395 Change 3070007 on 2016/07/29 by James.Golding Fix highlight when searching Anim Curves #jira UE-33073 Change 3070002 on 2016/07/29 by James.Golding Fix complex collision drawing in StaticMesh Editor #jira UE-33062 Change 3069998 on 2016/07/29 by Jon.Nabozny Fix AShooterCharacter heavy breathing even when running but not moving. #jira UE-32398 Change 3069980 on 2016/07/29 by James.Golding Add UV support to ProcMeshComp collision Fix bUseComplexAsSimpleCollision not being applied because ProcMeshBodySetup was transient, so setting was lost Move ProceduralMeshComponent out of 'experimental' #jira UE-29850, UE-33003 Change 3069970 on 2016/07/29 by James.Golding Add #if WITH_PHYSX around ISimEventCallbackFactory at Ori#s suggestion (forgot to do this in initial checkin CL 3053969) #jira UE-32819 Change 3069969 on 2016/07/29 by Andrew.Porter Adding movie test content to NotForLicensee. #jira UE-29618 Change 3069962 on 2016/07/29 by Chris.Wood Writing CrashReportClient config section from Engine config in crashing app to crash report folder. Crash Report Client reads new file and sets project-specific settings. [UE-31820] - CrashReportClient config is getting merged between streams and projects containing project-specific settings #jira UE-31820 Affects Core and CrashReportClient. Removes existing values from CRC's own engine config file because they are project-specific and the file is agnostic. Added project-specific values to engine config with defaults set in BaseEngine.ini. Added overrides to Orion config. Change 3069908 on 2016/07/29 by Jurre.deBaare Saving assets with UGS build, fixes build warnings #jira UE-123 Change 3069889 on 2016/07/29 by Jurre.deBaare Build fix for -game builds (missing WITH_EDITOR ifdef) #jira UE-123 Change 3069877 on 2016/07/29 by Allan.Bentham Add Android ES3.1, vulkan and iOS Metal material quality settings to project settings. Fixed issue that prevented settings editor saving out array property changes. #jira UE-33379 Change 3069872 on 2016/07/29 by Jurre.deBaare Added option to disable post processing option in preview scene Inverted normals on the sky sphere (asset change) Bad performance when changing (slider) values for the advanced preview scene #fix Small optimizations and now only save the data on closing of the preview scene tab #jira UE-33496 Persona floor offset not being correct #fix Re-added floor offsetting mechanism (even though I find it very ugly), which now sets the advanced preview scene's floor offset #jira UE-32278 Add a shortcut for hiding/showing the sky (and maybe the floor) in asset viewers #fix I will now hide the environment and O the floor #jira UE-33498 Directional light rotation not saved with advanced preview scene profiles #fix Now does :) #jira UE-33619 Change 3069838 on 2016/07/29 by Luke.Thatcher Fix crash in ShooterGame when running the server. Paper2D plugin now has a dependency on the SlateRHIRenderer module, which needs to be loaded in PostConfigInit phase, otherwise shader types in the slate renderer module are not initialized in time. #jira UE-33671 Change 3069440 on 2016/07/28 by patrickr.donovan #jira UE-29618 Test content for AA and materials with tessellation enabled and absolute world position material function. Change 3069148 on 2016/07/28 by Lina.Halper Morphtarget deletion crash #jira: UE-33851 #code review: Roalndo.caloca Change 3069144 on 2016/07/28 by Michael.Trepka Check if UnrealBuildTool.csproj exists before trying to compile it in Mac GenerateProjectFiles.sh. Fixes a problem in binary distribution where the script would show an error (but still succeed) due to missing UnrealBuildTool.csproj #jira UE-31863 Change 3069021 on 2016/07/28 by Dmitry.Rekman Linux: a number of small fixes from pull requests. - Includes PR #1905 (UE-24848) by madsystem (arch installation: changed from clang to clang35) - Includes PR #2120 (UE-27742) by ABeekhub (mono-mvc for opensuse) - Includes PR #2131 (UE-27894) by vityafx (QMake build problem (no c++11 standard)) - Includes PR #2305 (UE-29781) by salamanderrake (MakefileGenerator.cs small changes) - Includes PR #2361 (UE-30452) by salamanderrake (QMakefileProjectGenerator.cs fix for missing Includes paths and removal of duplicates) #tests Generated cmake, qmake, make projects and tested them (using ueprojectdirs and not standalone projects). No tests done for arch/suse changes. #jira UE-24848 #jira UE-27742 #jira UE-27894 #jira UE-29781 #jira UE-30452 (Edigrating CL 3069016 from //UE4/Dev-Platform/... to //UE4/Release-4.13/...) Change 3068867 on 2016/07/28 by Mike.Fricker Mesh Paint: Fixed various bugs - Fixed brush preview not rendered for lasers/mouse when not actively painting (UE-33554) - Fixed 'full press' over actors preventing UI from being clickable (UE-33550) - Fixed brush cursor displayed when hovering over UI (including selection bar/close button) (UE-33551) - Fixed VR transform gizmo getting in the way of everything while painting (it is now hidden while in mesh paint mode) - Fixed not being able to interact with UIs after messing around with mesh paint (UE-33621) #jira UE-33554 #jira UE-33550 #jira UE-33551 #jira UE-33621 Change 3068758 on 2016/07/28 by Mitchell.Wilson Minor update to BP_RakeStuff to solve issue with sand turning black when raking the same spot. #jira UE-33684 Change 3068733 on 2016/07/28 by Ori.Cohen Temp fix to make sure that deferred bodies that add angular impulse do not crash (From Benn.G) #JIRA UE-32630 Change 3068713 on 2016/07/28 by Lina.Halper #Checking in Benn G's fix Fixed crash when adding a section to a zero length montage. Fixed nullptr deref in montage handling code and disabled menu option to add a section when zero length (makes no sense to do that). #jira UE-33633 #code review: Benn.Gallagher Change 3068580 on 2016/07/28 by John.Pollard Disable hot reloading when using single process MP PIE Fixes UE-30516 - Crash in FObjectReplicator::StartReplicating when removing replicated uproperty and hot reloading with two players #jira UE-30516 Change 3068550 on 2016/07/28 by Jurre.deBaare Merge Actors: "Bake Vertex Data" is incorrectly listed underm materials #fix Added another flag and renamed the old one + added tooltips :) This also required some changes to the merge path just to make sure we end up with the correct data #jira UE-31886 Change 3068549 on 2016/07/28 by Jurre.deBaare Merged static meshes stop reaction to the Trace Complex on Move flag. #fix merge physics now defaults to true in the actor merging settings (people assumed the system didn't work and hadn't seen the option) #jira UE-30403 Change 3068548 on 2016/07/28 by Jurre.deBaare Merge Actor tool can no longer merge just materials for an actor #fix removed requirement of more than one static mesh component (left code in to renable later on once we add a bake materials button for actors in the world) #jira UE-32797 Change 3068547 on 2016/07/28 by Jurre.deBaare Make sure the advanced preview scene tab is shown by default #fix Made the tab spawn by default in all possible situations (as part of the existing UI layout) #jira UE-33499 Change 3068546 on 2016/07/28 by Jurre.deBaare Textures created from generating proxy meshes have incorrect compression format on tooltip #fix Required a PostEditChange call for the UTextures to correctly propogate the compression type #jira UE-30365 Change 3068543 on 2016/07/28 by Danny.Bouimad #jira UE-29618 Made useability changes to the Phsyical Animation Profile Map Change 3068407 on 2016/07/28 by Mitchell.Wilson Set delete index variable to 0 on reset in BP_RakeStuff to fix an issue with sand turning black when raking repeatedly in one place #jira UE-33684 Change 3068403 on 2016/07/28 by Ben.Marsh Add warnings and ignore entries in .uprojectdirs files which reference directories outside the root directory. #jira UE-33459 Change 3068358 on 2016/07/28 by Martin.Wilson Set default compression to NoClear as None is not a valid compression #jira UE-31958 Change 3068346 on 2016/07/28 by Benjamin.Hyder Updating TM-ContactShadows to include static meshes #jira UE-29618 Change 3068336 on 2016/07/28 by Martin.Wilson Added a new mode to Montage_Play so that we can choose what value we return (either length of the montage or the play time duration). #jira UE-32101 Change 3068321 on 2016/07/28 by Martin.Wilson Export bone selection widgets so that other modules can use them #Jira UE-30361 Change 3068316 on 2016/07/28 by Martin.Wilson Expose Root Motion Mode #jira UE-14431 Change 3068307 on 2016/07/28 by Benjamin.Hyder Rebuilding lighting in QA-Materials #jira UE-29618 Change 3068299 on 2016/07/28 by Benjamin.Hyder Renaming TM_Noise to TM-Noise #jira UE-29618 Change 3068285 on 2016/07/28 by Martin.Wilson Remove option to clear compression on animation sequences #jira UE-31957 Change 3068282 on 2016/07/28 by Benjamin.Hyder Re-Saving QA-Materials to remove log spam #jira UE-29618 Change 3068271 on 2016/07/28 by Martin.Wilson Add check to highlight recursion issue caused by game code #jira UE-31417 Change 3068259 on 2016/07/28 by Jamie.Dale Fixed UObject churn caused by re-use of a single thumbnail scene for BP and class types #jira UE-31709 Change 3068257 on 2016/07/28 by Jamie.Dale Removed some code that was no longer needed and could cause a crash #jira UE-33342 Change 3068204 on 2016/07/28 by Nick.Darnell Slate - Reverting the SMenuAnchor to a previous version, there was no reason afterall to need to use the last painted window as the host for menus, ended up solving it a lower level by properly supporting the deferral groups on the SVirtualWindow under different conditions. Slate - The hit test grid now properly records the hit test path for the invalidation box, so that when input is recieved, a widget path containing only one instance of the invalidation box is created, premitting things like mouse capture to properly work. UMG - Further refinements and improvements to the Widget Interaction Component. This completes the documentation and a fixes several bugs with it that were found after the integration to main occured. #jira UE-33845 Change 3068197 on 2016/07/28 by Martin.Wilson Fix abstract notify state classes showing up in create menu #jira UE-33864 Fix copy paste notifies introducing cross animation references #jira UE-32801 Change 3068183 on 2016/07/28 by Matthew.Griffin Remove hard coded staging for Crash Reporter and use its receipt instead #jira UE-33800 Change 3068097 on 2016/07/28 by Dmitriy.Dyomin Fixed: Decals don't render on Zenfone 2 (Added proper detection of FP16 render target support) #jira UE-22679 Change 3068074 on 2016/07/28 by Matthew.Griffin Added DDC nodes to list of content/shader modifiers for notifications Change 3068053 on 2016/07/28 by Jack.Porter After resampling or changing landscape component size, delete any new components that are entirely in regions that correspond to previously deleted components #jira UE-5335 Change 3068043 on 2016/07/28 by Jack.Porter Fix crash in mobile preview when selecting objects during shader compilation #jira UE-33862 Change 3068031 on 2016/07/28 by Gareth.Martin Fix hang when changing material which is used on landscape and "LogMaterial: 0.03 seconds spent updating 1 materials, 1 interfaces, 0 instances, 1 with static permutations." log spam #jira UE-33708 Change 3068030 on 2016/07/28 by Gareth.Martin Fix "Max Pitch Angle" and "Random Yaw" foliage options being ignored in procedural foliage. #jira UE-20476 Change 3068029 on 2016/07/28 by Gareth.Martin Fixed landscape "continuous" sculpting not working in multiple viewports - the editor would tick with another viewport which didn't have the mouse down, ending the stroke. Now only the "active" viewport can end the stroke. #jira UE-32347 Change 3068013 on 2016/07/28 by Thomas.Sarkanen Added a tick dependency for slave components Ensures that slave components always get ticked after master components. Prevents potential main thread stall updating morph targets in slave components. #jira UE-23045 - Slave components could benefit from a tick dependency on master components Change 3068011 on 2016/07/28 by Thomas.Sarkanen Added space bar as a shortcut to play/pause animation playback in Persona #jira UE-26788 - Framework - Animation - Add Hotkeys to the Viewport for Play/Pause Change 3068009 on 2016/07/28 by Thomas.Sarkanen Multi-arg console commands now accept string commands with or without quotes Pre-parsed out each token prior to calling ImportText() rather than relying on ImportText's internal logic. This allows us to properly parse out quoted and non-quoted values as well as being robust to escape sequences etc. Removed old legacy code designed to fix trailing string params not being parsed correctly. Updated some NULLs to nullptr. #jira UE-23661 - Multi-arg console commands that take string params don't accept string params without quotation marks Change 3067854 on 2016/07/28 by Dmitriy.Dyomin Fixed: World composition tiles that have child actor inside will become mdified if any other tile is unloaded #jira UE-33440 Change 3067831 on 2016/07/28 by Dmitriy.Dyomin Fixed: Landscape GrassType does not have the option to exclude Decals #jira UE-26669 Change 3067826 on 2016/07/28 by Dmitriy.Dyomin Fixed: Deleting foliage actor from foliage menu does not remove actors from PIE until editor is restarted Also fixed Replace foliage type case #jira UE-32010 Change 3067824 on 2016/07/28 by Dmitriy.Dyomin Fixed: The Empty Level is named "NewWorld" in the World Outliner as opposed to "Untitled" #jira UE-24767 Change 3067794 on 2016/07/27 by Jack.Porter Expose Lighting Channels to Foliage and Landscape Grass #jira UE-32794 Change 3067782 on 2016/07/27 by Jack.Porter Fixed crash on device when playing sounds when packaged using Android_Multi #jira UE-31981 Change 3067760 on 2016/07/27 by Jack.Porter Fixed issue where landscape flatten target grid preview is displayed on wrong landscape when switching landscape target #jira UE-11756 Change 3067748 on 2016/07/27 by Dmitry.Rekman Linux: fix packaged projects not being runnable (UE-33608). - Added a shell script to run the binary. #jira UE-33608 (Edigrating 3067587 from //UE4/Dev-Platform/... to //UE4/Release-4.13/...) Change 3067512 on 2016/07/27 by Jeff.Fisher UEVR-13 PSVR: TCR Requirements (first two items) https://udn.unrealengine.com/questions/301886/trying-to-use-vrheadsetlost-and-vrheadsetreconnect.html https://udn.unrealengine.com/questions/302238/how-to-handle-morpheus-disconnection-event.html#answer-303803 https://udn.unrealengine.com/questions/300748/psvr-trc-compliance.html Unshelved from pending changelist '3065760 (UE4/Dev-VR) -Implements HMD connect/disconnect/reconnect handling along the lines of sony sample tutorial_vr/basic_setup. -Known issue: some tracker location popping during reconnect. I will try to fix that next. #jira UEVR-13 #review-3066558 @chad.taylor Change 3067511 on 2016/07/27 by Jeff.Fisher Duplicating 3058093 (UE4/Dev-VR) Linking SceHmdSetupDialog_stub_weak so one can easily use the sceHmdSetup library to pop up the system hmd setup dialog, if one wishes (someone did, we probably will soon). #jira UEVR-13 Change 3067488 on 2016/07/27 by Ori.Cohen Make the UI more clear for which physical animation is currently being editted. #JIRA UE-33332 Change 3067481 on 2016/07/27 by Chris.Babcock AAR support and updating libraries: - Google Play Games native C++ SDK 2.1 - Google Play Services 9.2.0 - android-support-v4.jar 23.0.0 #jira UEPLAT-1251 #jira UE-19190 #ue4 #android Change 3067478 on 2016/07/27 by Ori.Cohen Fix it so renaming of physical animation profiles (and constraint profiles) do not lose previous settings #JIRA UE-33276, UE-33331 Change 3067474 on 2016/07/27 by Ori.Cohen Make it so property index comes in on reset of array value and duplication (From Matt.K) #JIRA UE-33276 Change 3067457 on 2016/07/27 by Ori.Cohen Fix currently highlighted text in physics profiles being copied over when chaing current profile #JIRA UE-33282 Change 3067451 on 2016/07/27 by Ori.Cohen Fix the case where objects welded together (even though they're simulating) do not re-weld when being detached in a long chain #JIRA UE-32531 Change 3067443 on 2016/07/27 by Ori.Cohen Make skeletalMeshComponent a property of physical animation component so things can be setup in the construction script. Mark the component as experimental and only expose valid functions into construction script #JIRA UE-33656 Change 3067439 on 2016/07/27 by Ori.Cohen Added more logging info for potential fixed framerate negative delta time crash #JIRA UE-32219 Change 3067348 on 2016/07/27 by mason.seay Updating map to have hit events test. #jira UE-29618 Change 3067342 on 2016/07/27 by Mitchell.Wilson Updating collision on TwinStickUFO to resolve issue with the ship getting stuck when rotating due to collision being offset slightly #jira UE-15698 Change 3067332 on 2016/07/27 by Dmitry.Rekman Fix for libstdc++ problems (UE-33584). #tests Built UE4Editor/UE4Game on Ubuntu 16.04 and 15.10. #JIRA UE-33584 (Redoing CL 3065551 from Dev-Platform). Change 3067262 on 2016/07/27 by Lina.Halper DUPEFIX: Fix compile issue of non-editor build due to - Reduce functions is not editoronly #tests: PIE/compile editor build/noneditor #jira: UE-33477 Change 3067228 on 2016/07/27 by Lina.Halper This fixes crash where mesh has changed hierarchy but hasn't been remapped yet. #jira: UE-29880 Change 3067168 on 2016/07/27 by Lina.Halper DUPEFIX: Smartname guid will be discarded during cooking, and once it's cooked, it's trusted to have correct name. #code review:Martin.Wilson, Benn.Gallagher #tests: cooked test map, run test map, PIE, saving content, loading standalone game #jira: UE-33454 Change 3067162 on 2016/07/27 by Lina.Halper pose asset source animation/animation asset preview pose now have proper skeleton filter #jira: UE-32607 Change 3067160 on 2016/07/27 by Lina.Halper Fix issue with preview curve not working when no asset #jira: UE-33402 Change 3067138 on 2016/07/27 by Lina.Halper DUPEFIX: Fix the guid keep generated by adding to the database. - This caused worse problem with non-deterministic cooking - This doesn't fix UE-33454 for 100%, but this was the main reason why this was so visible #jira: UE-33772, UE-33454 #tests: cooked AI_Test map, editor rename curves Change 3067129 on 2016/07/27 by Lina.Halper DUPEFIX- Fix additive issue with remove linear key and built the new animation DDC #tests: Jump_Recovery_Additive, PIE #jira: UE-33477 Change 3067128 on 2016/07/27 by Michael.Trepka Copy of CL 3062046 PRAGMA_DISABLE_OPTIMIZATION_ACTUAL and PRAGMA_ENABLE_OPTIMIZATION_ACTUAL defines for iOS #jira UE-33683 Change3067104on 2016/07/27 by Lina.Halper DUPEFIX: Support different samplerate for reimport with set range #jira: UE-16027 Change 3067093 on 2016/07/27 by Lina.Halper DUPE FIX: Fix baking is applied twice in the new created animation #jira: UE-31120 Change 3067088 on 2016/07/27 by Lina.Halper Fix issues with rename/delete of the curves #jira: UE-33663, UE-33730, UE-33661, UE-33662 Change 3066795 on 2016/07/27 by Mark.Satterthwaite Fix a race-condition in FMetalBlendState's constructor that could lead to crashes or use of the incorrect blend-state. This is a partial fix for UE-33778 which appears to have several causes. #jira UE-33778 Change 3066788 on 2016/07/27 by Mark.Satterthwaite Duplicate CL #3066338: Handle releasing an SRV/UAV & the source object within a single Metal command-buffer. #jira UE-33779 Change 3066786 on 2016/07/27 by Mark.Satterthwaite Duplicate CL #3064743: Proper fix for FORT-27685 - on Metal it is invalid to fail to set uniform parameters on a shader - if you don't set the parameter the buffer binding may be nil or too small for the data accessed in the shader and the GPU will then crash. #jira UE-33827 #jira FORT-27685 Change 3066768 on 2016/07/27 by samuel.proctor Updated child blueprint used for profiler testing #jira UE-29618 Change 3066733 on 2016/07/27 by samuel.proctor Refreshed broken node in profiler test asset #jira UE-29618 Change 3066670 on 2016/07/27 by Sam.Deiter #Jira UEDOC-3139 Adding the blending tool tip images. Change 3066669 on 2016/07/27 by Mark.Satterthwaite Duplicate CL #3063329: CL #3046743 was breaking other samples in unexpected ways after a recent Main merge, so make a Metal-specific change to the shader instead and amend the MetalBackend to better match HLSL's handling of NaN/inf with common single-precision float intrinsics. This is sufficient to fix the AtmosphericFog and the recent regressions. #jira UE-33600 #jira UE-33028 #jira UE-27879 #jira UE-25802 Change 3066668 on 2016/07/27 by Mark.Satterthwaite Duplicate CL #3063327: Added FSpeedTreeWindNullUniformBuffer as a global resource to bind to shaders that require a SpeedTreeData uniform but don't yet have data available as a nil binding is invalid on Metal. #jira UE-32068 Change 3066625 on 2016/07/27 by Mark.Satterthwaite Duplicate CL #3062160: Fix the fix for handling RHISetStreamSource overriding stride on Metal - not all MTLVertexDescriptors are equally hashable so do this ourselves. #jira UE-33355 Change3066624on 2016/07/27 by Mark.Satterthwaite Duplicate CL #3063328: Mac Metal DXT/BC textures can have mip-levels smaller than the block size (they switch to uncompressed data). #jira UE-33820 Change 3066589 on 2016/07/27 by Mark.Satterthwaite Duplicate CL #3060590 to fix UE-33819: Fix FORT-27340: Mac Metal cannot natively support PF_G8 + sRGB as not all Mac GPUs have single-channel sRGB formats (according to Apple) so we must manually pack & unpack to RGBA8_sRGB - the code to do this was missing from UpdateTexture2D. #jira UE-33819 Change 3066588 on 2016/07/27 by Matt.Kuhlenschmidt Fixed Reset to default not updating when selecting new assets #jira UE-33817 Change 3066509 on 2016/07/27 by mason.seay Phys material needed for TM-SliceProcMesh #jira UE-29618 Change 3066500 on 2016/07/27 by mason.seay Rebuilt lighting #jira UE-29618 Change 3066499 on 2016/07/27 by Jurre.deBaare Map build should not generate empty HLOD folder in Editor #fix Asset outer (hlod folder/asset) was created regardless of whether or not it was needed, now checks first :) #jira UE-29564 Change 3066498 on 2016/07/27 by Jurre.deBaare HLOD outliner drag and drop operation can cause log spam #fix Found the log spam was coming from the scene outliner itself, caused by Formatting call receiving incorrect argument names which is now fixed #jira UE-32106 Change 3066485 on 2016/07/27 by Alan.Noon Resubmitting fixes for Puzzle Templates. Rebuilt in 4.13 via UGS #jira UE-30564 Change 3066470 on 2016/07/27 by mason.seay Test map and updating blueprint for slicing proc mesh #jira UE-29618 Change 3066367 on 2016/07/27 by Matthew.Griffin Switch UE4 Binary Release to be the job that runs nightly instead of the Full Build we use in main Change 3066337 on 2016/07/27 by Matthew.Griffin Remaking CL 3066327 by Matthew.Griffin@Matthew.Griffin_G5772_MainStream on 2016-07-27 15:39 Adding ArchiveDir parameter to Fortnite build command as it ignores StagingDir and has been filling up network drive Change 3066158 on 2016/07/27 by Ben.Marsh Reverting assets causing warning, via integration from //UE4/Main. Change 3065651 on 2016/07/26 by Ben.Marsh Remaking CL 3065267 by Alan.Noon@Alan.Noon_Z3739_Main_9938 on 2016/07/26 16:35:14 Updated Puzzle Template (BP and C++) to mimic each other in terms of content, labelling and setup. Change 3065650 on 2016/07/26 by Ben.Marsh Remaking CL 3065358 by James.Brinkerhoff@James.Brinkerhoff_Z2862_Ocean-Staging on 2016/07/26 17:31:04 Hotfix for Ocean from CL 3065311: Fixes the load/apply order when applying customizations to characters in the editor Change 3065649 on 2016/07/26 by Ben.Marsh Remaking CL 3065268 by Max.Chen@Max.Chen_T4664_UE4_Main on 2016/07/26 16:35:18 Sequencer: Revert 3057233 because it breaks sequence recording. Copy from Dev-Sequencer #jira UE-33569 Change 3065308 on 2016/07/26 by Ben.Marsh Fix failure to parse EC settings for 4.13 branch. Change 3065235 on 2016/07/26 by Ben.Marsh Set the IsReleaseBranch flag to true for builds in the Release-4.13 branch. [CL 3079611 by Matthew Griffin in Main branch]
3212 lines
131 KiB
C++
3212 lines
131 KiB
C++
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
|
|
|
|
|
|
#include "LevelEditor.h"
|
|
#include "Matinee/MatineeActor.h"
|
|
#include "Engine/LevelScriptBlueprint.h"
|
|
#include "LightingBuildOptions.h"
|
|
#include "EditorSupportDelegates.h"
|
|
#include "SLevelEditor.h"
|
|
#include "LevelEditorActions.h"
|
|
#include "SLevelViewport.h"
|
|
#include "EditorBuildUtils.h"
|
|
#include "Toolkits/AssetEditorManager.h"
|
|
#include "ScopedTransaction.h"
|
|
#include "Editor/Kismet/Public/BlueprintEditorModule.h"
|
|
#include "Editor/PropertyEditor/Public/PropertyEditorModule.h"
|
|
#include "Editor/ContentBrowser/Public/ContentBrowserModule.h"
|
|
#include "Editor/MainFrame/Public/MainFrame.h"
|
|
#include "Editor/UnrealEd/Private/GeomFitUtils.h"
|
|
#include "Editor/UnrealEd/Public/BSPOps.h"
|
|
#include "Editor/LevelEditor/Public/DlgDeltaTransform.h"
|
|
#include "Runtime/Engine/Classes/PhysicsEngine/BodySetup.h"
|
|
#include "Editor/NewLevelDialog/Public/NewLevelDialogModule.h"
|
|
#include "DelegateFilter.h"
|
|
#include "BlueprintUtilities.h"
|
|
#include "MRUFavoritesList.h"
|
|
#include "Editor/SceneOutliner/Private/SSocketChooser.h"
|
|
#include "SnappingUtils.h"
|
|
#include "Layers/ILayers.h"
|
|
#include "IPlacementModeModule.h"
|
|
#include "AssetSelection.h"
|
|
#include "IDocumentation.h"
|
|
#include "SourceCodeNavigation.h"
|
|
#include "Dialogs/DlgPickAssetPath.h"
|
|
#include "AssetToolsModule.h"
|
|
#include "BlueprintEditorUtils.h"
|
|
#include "KismetEditorUtilities.h"
|
|
#include "DesktopPlatformModule.h"
|
|
#include "EngineAnalytics.h"
|
|
#include "AnalyticsEventAttribute.h"
|
|
#include "IAnalyticsProvider.h"
|
|
#include "ReferenceViewer.h"
|
|
#include "ISizeMapModule.h"
|
|
#include "Developer/MeshUtilities/Public/MeshUtilities.h"
|
|
#include "EditorClassUtils.h"
|
|
#include "ComponentEditorUtils.h"
|
|
|
|
#include "EditorActorFolders.h"
|
|
#include "ActorPickerMode.h"
|
|
#include "EngineBuildSettings.h"
|
|
#include "HotReloadInterface.h"
|
|
#include "ISourceControlModule.h"
|
|
#include "SourceControlWindows.h"
|
|
#include "NotificationManager.h"
|
|
#include "SNotificationList.h"
|
|
#include "Engine/Selection.h"
|
|
#include "EngineUtils.h"
|
|
#include "Engine/StaticMeshActor.h"
|
|
#include "Engine/Polys.h"
|
|
#include "Components/LightComponent.h"
|
|
#include "Engine/StaticMesh.h"
|
|
#include "Engine/Light.h"
|
|
#include "Animation/SkeletalMeshActor.h"
|
|
#include "Animation/AnimSequence.h"
|
|
#include "Editor/KismetWidgets/Public/CreateBlueprintFromActorDialog.h"
|
|
#include "EditorProjectSettings.h"
|
|
#include "HierarchicalLODUtilities.h"
|
|
#include "HierarchicalLODUtilitiesModule.h"
|
|
#include "Engine/LODActor.h"
|
|
#include "AsyncResult.h"
|
|
#include "IPortalApplicationWindow.h"
|
|
#include "IPortalServiceLocator.h"
|
|
#include "MaterialShaderQualitySettings.h"
|
|
#include "IVREditorModule.h"
|
|
|
|
DEFINE_LOG_CATEGORY_STATIC(LevelEditorActions, Log, All);
|
|
|
|
#define LOCTEXT_NAMESPACE "LevelEditorActions"
|
|
|
|
const FName HotReloadModule("HotReload");
|
|
|
|
namespace LevelEditorActionsHelpers
|
|
{
|
|
/**
|
|
* If the passed in class is generated by a Blueprint, it will open that Blueprint, otherwise it will help the user create a Blueprint based on that class
|
|
*
|
|
* @param InWindowTitle The window title if the Blueprint needs to be created
|
|
* @param InBlueprintClass The class to create a Blueprint based on or to open if it is a Blueprint
|
|
* @param InLevelEditor When opening the Blueprint, this level editor is the parent window
|
|
* @param InNewBPName If we have to create a new BP, this is the suggested name
|
|
*/
|
|
UBlueprint* OpenOrCreateBlueprintFromClass(FText InWindowTitle, UClass* InBlueprintClass, TWeakPtr< SLevelEditor > InLevelEditor, FString InNewBPName = TEXT(""))
|
|
{
|
|
UBlueprint* Blueprint = NULL;
|
|
|
|
// If the current set class is not a Blueprint, we need to allow the user to create one to edit
|
|
if(!InBlueprintClass->ClassGeneratedBy)
|
|
{
|
|
Blueprint = FKismetEditorUtilities::CreateBlueprintFromClass(InWindowTitle, InBlueprintClass, InNewBPName);
|
|
}
|
|
else
|
|
{
|
|
Blueprint = Cast<UBlueprint>(InBlueprintClass->ClassGeneratedBy);
|
|
}
|
|
|
|
if(Blueprint)
|
|
{
|
|
// @todo Re-enable once world centric works
|
|
const bool bOpenWorldCentric = false;
|
|
FAssetEditorManager::Get().OpenEditorForAsset(
|
|
Blueprint,
|
|
bOpenWorldCentric ? EToolkitMode::WorldCentric : EToolkitMode::Standalone,
|
|
InLevelEditor.Pin() );
|
|
}
|
|
|
|
return Blueprint;
|
|
}
|
|
|
|
/** Check to see whether this world is a persistent world with a valid file on disk */
|
|
bool IsPersistentWorld(UWorld* InWorld)
|
|
{
|
|
UPackage* Pkg = InWorld ? InWorld->GetOutermost() : nullptr;
|
|
if (Pkg && FPackageName::IsValidLongPackageName(Pkg->GetName()))
|
|
{
|
|
FString FileName;
|
|
return FPackageName::DoesPackageExist(Pkg->GetName(), nullptr, &FileName);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::DefaultCanExecuteAction()
|
|
{
|
|
return FSlateApplication::Get().IsNormalExecution();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::BrowseDocumentation()
|
|
{
|
|
IDocumentation::Get()->OpenHome(FDocumentationSourceInfo(TEXT("help_menu")));
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::BrowseAPIReference()
|
|
{
|
|
IDocumentation::Get()->OpenAPIHome();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::BrowseCVars()
|
|
{
|
|
GEditor->Exec(GetWorld(), TEXT("help"));
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::BrowseViewportControls()
|
|
{
|
|
FString URL;
|
|
if (FUnrealEdMisc::Get().GetURL(TEXT("ViewportControlsURL"), URL))
|
|
{
|
|
FPlatformProcess::LaunchURL(*URL, NULL, NULL);
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::NewLevel()
|
|
{
|
|
if (GUnrealEd->WarnIfLightingBuildIsCurrentlyRunning())
|
|
{
|
|
return;
|
|
}
|
|
|
|
IMainFrameModule& MainFrameModule = FModuleManager::GetModuleChecked<IMainFrameModule>("MainFrame");
|
|
|
|
FString TemplateMapPackageName;
|
|
FNewLevelDialogModule& NewLevelDialogModule = FModuleManager::LoadModuleChecked<FNewLevelDialogModule>("NewLevelDialog");
|
|
if (NewLevelDialogModule.CreateAndShowNewLevelDialog(MainFrameModule.GetParentWindow(), TemplateMapPackageName))
|
|
{
|
|
// The new map screen will return a blank TemplateName if the user has selected to begin a new blank map
|
|
if (TemplateMapPackageName.IsEmpty())
|
|
{
|
|
GEditor->CreateNewMapForEditing();
|
|
}
|
|
else
|
|
{
|
|
// New map screen returned a non-empty TemplateName, so the user has selected to begin from a template map
|
|
bool TemplateFound = false;
|
|
|
|
// Search all template map folders for a match with TemplateName
|
|
const bool bIncludeReadOnlyRoots = true;
|
|
if ( FPackageName::IsValidLongPackageName(TemplateMapPackageName, bIncludeReadOnlyRoots) )
|
|
{
|
|
const FString MapPackageFilename = FPackageName::LongPackageNameToFilename(TemplateMapPackageName, FPackageName::GetMapPackageExtension());
|
|
if ( FPaths::FileExists(MapPackageFilename) )
|
|
{
|
|
// File found because the size check came back non-zero
|
|
TemplateFound = true;
|
|
|
|
// If there are any unsaved changes to the current level, see if the user wants to save those first.
|
|
bool bPromptUserToSave = true;
|
|
bool bSaveMapPackages = true;
|
|
bool bSaveContentPackages = false;
|
|
if ( FEditorFileUtils::SaveDirtyPackages(bPromptUserToSave, bSaveMapPackages, bSaveContentPackages) )
|
|
{
|
|
// Load the template map file - passes LoadAsTemplate==true making the
|
|
// level load into an untitled package that won't save over the template
|
|
FEditorFileUtils::LoadMap(*MapPackageFilename, /*bLoadAsTemplate=*/true);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!TemplateFound)
|
|
{
|
|
UE_LOG( LevelEditorActions, Warning, TEXT("Couldn't find template map package %s"), *TemplateMapPackageName);
|
|
GEditor->CreateNewMapForEditing();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::NewLevel_CanExecute()
|
|
{
|
|
return FSlateApplication::Get().IsNormalExecution() && !GLevelEditorModeTools().IsTracking();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OpenLevel()
|
|
{
|
|
FEditorFileUtils::LoadMap();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OpenLevel_CanExecute()
|
|
{
|
|
return FSlateApplication::Get().IsNormalExecution() && !GLevelEditorModeTools().IsTracking();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::DeltaTransform()
|
|
{
|
|
if (GUnrealEd->WarnIfLightingBuildIsCurrentlyRunning())
|
|
{
|
|
return;
|
|
}
|
|
|
|
FDlgDeltaTransform DeltaDialog;
|
|
|
|
const FDlgDeltaTransform::EResult MoveDialogResult = DeltaDialog.ShowModal();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OpenRecentFile( int32 RecentFileIndex )
|
|
{
|
|
IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>( "MainFrame" );
|
|
FMainMRUFavoritesList* RecentsAndFavorites = MainFrameModule.GetMRUFavoritesList();
|
|
|
|
// Save the name of the file we are attempting to load as VerifyFile/AskSaveChanges might rearrange the MRU list on us
|
|
const FString NewPackageName = RecentsAndFavorites->GetMRUItem( RecentFileIndex );
|
|
|
|
if( RecentsAndFavorites->VerifyMRUFile( RecentFileIndex ) )
|
|
{
|
|
// Prompt the user to save any outstanding changes.
|
|
if( FEditorFileUtils::SaveDirtyPackages(true, true, false) )
|
|
{
|
|
FString NewFilename;
|
|
if (FPackageName::TryConvertLongPackageNameToFilename(NewPackageName, NewFilename, FPackageName::GetMapPackageExtension()))
|
|
{
|
|
// Load the requested level.
|
|
FEditorFileUtils::LoadMap(NewFilename);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// something went wrong or the user pressed cancel. Return to the editor so the user doesn't lose their changes
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::OpenFavoriteFile( int32 FavoriteFileIndex )
|
|
{
|
|
IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>( "MainFrame" );
|
|
FMainMRUFavoritesList* MRUFavoritesList = MainFrameModule.GetMRUFavoritesList();
|
|
|
|
const FString PackageName = MRUFavoritesList->GetFavoritesItem( FavoriteFileIndex );
|
|
|
|
if( MRUFavoritesList->VerifyFavoritesFile( FavoriteFileIndex ) )
|
|
{
|
|
// Prompt the user to save any outstanding changes
|
|
if( FEditorFileUtils::SaveDirtyPackages(true, true, false) )
|
|
{
|
|
FString FileName;
|
|
if (FPackageName::TryConvertLongPackageNameToFilename(PackageName, FileName, FPackageName::GetMapPackageExtension()))
|
|
{
|
|
// Load the requested level.
|
|
FEditorFileUtils::LoadMap(FileName);
|
|
}
|
|
|
|
// Move the item to the head of the list
|
|
MRUFavoritesList->MoveFavoritesItemToHead(PackageName);
|
|
}
|
|
else
|
|
{
|
|
// something went wrong or the user pressed cancel. Return to the editor so the user doesn't lose their changes
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::ToggleFavorite()
|
|
{
|
|
IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>( "MainFrame" );
|
|
FMainMRUFavoritesList* MRUFavoritesList = MainFrameModule.GetMRUFavoritesList();
|
|
check( MRUFavoritesList );
|
|
|
|
if (LevelEditorActionsHelpers::IsPersistentWorld(GetWorld()))
|
|
{
|
|
const FString PackageName = GetWorld()->GetOutermost()->GetName();
|
|
|
|
// If the map was already favorited, remove it from the favorites
|
|
if ( MRUFavoritesList->ContainsFavoritesItem(PackageName) )
|
|
{
|
|
MRUFavoritesList->RemoveFavoritesItem(PackageName);
|
|
}
|
|
// If the map was not already favorited, add it to the favorites
|
|
else
|
|
{
|
|
MRUFavoritesList->AddFavoritesItem(PackageName);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::RemoveFavorite( int32 FavoriteFileIndex )
|
|
{
|
|
IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>( "MainFrame" );
|
|
FMainMRUFavoritesList* MRUFavoritesList = MainFrameModule.GetMRUFavoritesList();
|
|
|
|
const FString PackageName = MRUFavoritesList->GetFavoritesItem( FavoriteFileIndex );
|
|
|
|
if( MRUFavoritesList->VerifyFavoritesFile( FavoriteFileIndex ) )
|
|
{
|
|
if ( MRUFavoritesList->ContainsFavoritesItem(PackageName) )
|
|
{
|
|
MRUFavoritesList->RemoveFavoritesItem(PackageName);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::ToggleFavorite_CanExecute()
|
|
{
|
|
// Disable the favorites button if the map isn't associated to a file yet (new map, never before saved, etc.)
|
|
return LevelEditorActionsHelpers::IsPersistentWorld(GetWorld());
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::ToggleFavorite_IsChecked()
|
|
{
|
|
bool bIsChecked = false;
|
|
|
|
if (LevelEditorActionsHelpers::IsPersistentWorld(GetWorld()))
|
|
{
|
|
const FString PackageName = GetWorld()->GetOutermost()->GetName();
|
|
|
|
IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>( "MainFrame" );
|
|
bIsChecked = MainFrameModule.GetMRUFavoritesList()->ContainsFavoritesItem(PackageName);
|
|
}
|
|
|
|
return bIsChecked;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanSaveWorld()
|
|
{
|
|
return FSlateApplication::Get().IsNormalExecution() && (!GUnrealEd || !GUnrealEd->GetPackageAutoSaver().IsAutoSaving());
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::Save()
|
|
{
|
|
FEditorFileUtils::SaveCurrentLevel();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SaveAs()
|
|
{
|
|
FString SavedFilename;
|
|
bool bSaved = FEditorFileUtils::SaveLevelAs( GetWorld()->PersistentLevel, &SavedFilename );
|
|
if (bSaved)
|
|
{
|
|
FEditorFileUtils::LoadMap(SavedFilename);
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SaveAllLevels()
|
|
{
|
|
const bool bPromptUserToSave = false;
|
|
const bool bSaveMapPackages = true;
|
|
const bool bSaveContentPackages = false;
|
|
const bool bFastSave = false;
|
|
FEditorFileUtils::SaveDirtyPackages( bPromptUserToSave, bSaveMapPackages, bSaveContentPackages, bFastSave );
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::ImportScene_Clicked()
|
|
{
|
|
FEditorFileUtils::Import();
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::ExportAll_Clicked()
|
|
{
|
|
const bool bExportSelectedActorsOnly = false;
|
|
FEditorFileUtils::Export( bExportSelectedActorsOnly );
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::ExportSelected_Clicked()
|
|
{
|
|
const bool bExportSelectedActorsOnly = true;
|
|
FEditorFileUtils::Export( bExportSelectedActorsOnly );
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::ExportSelected_CanExecute()
|
|
{
|
|
// Only enable the option if at least one thing is selected and its not a worldsettings
|
|
return GEditor->GetSelectedActors()->Num() > 0 && !GEditor->IsWorldSettingsSelected();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::AttachToActor(AActor* ParentActorPtr)
|
|
{
|
|
USceneComponent* ComponentWithSockets = NULL;
|
|
|
|
//@TODO: Should create a menu for each component that contains sockets, or have some form of disambiguation within the menu (like a fully qualified path)
|
|
// Instead, we currently only display the sockets on the root component
|
|
if (ParentActorPtr != NULL)
|
|
{
|
|
if (USceneComponent* RootComponent = Cast<USceneComponent>(ParentActorPtr->GetRootComponent()))
|
|
{
|
|
if (RootComponent->HasAnySockets())
|
|
{
|
|
ComponentWithSockets = RootComponent;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Show socket chooser if we have sockets to select
|
|
if (ComponentWithSockets != NULL)
|
|
{
|
|
FLevelEditorModule& LevelEditorModule = FModuleManager::GetModuleChecked<FLevelEditorModule>( "LevelEditor");
|
|
TSharedPtr< ILevelEditor > LevelEditor = LevelEditorModule.GetFirstLevelEditor();
|
|
|
|
// Create as context menu
|
|
FSlateApplication::Get().PushMenu(
|
|
LevelEditor.ToSharedRef(),
|
|
FWidgetPath(),
|
|
SNew(SSocketChooserPopup)
|
|
.SceneComponent( ComponentWithSockets )
|
|
.OnSocketChosen_Static( &FLevelEditorActionCallbacks::AttachToSocketSelection, ParentActorPtr ),
|
|
FSlateApplication::Get().GetCursorPos(),
|
|
FPopupTransitionEffect( FPopupTransitionEffect::ContextMenu )
|
|
);
|
|
}
|
|
else
|
|
{
|
|
AttachToSocketSelection( NAME_None, ParentActorPtr );
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::AttachToSocketSelection(const FName SocketName, AActor* ParentActorPtr)
|
|
{
|
|
FSlateApplication::Get().DismissAllMenus();
|
|
|
|
if(ParentActorPtr != NULL)
|
|
{
|
|
// Attach each child
|
|
FScopedTransaction Transaction(LOCTEXT("AttachActors", "Attach actors"));
|
|
bool bAttached = false;
|
|
|
|
for ( FSelectionIterator It( GEditor->GetSelectedActorIterator() ) ; It ; ++It )
|
|
{
|
|
AActor* Actor = Cast<AActor>( *It );
|
|
if (GEditor->CanParentActors(ParentActorPtr, Actor))
|
|
{
|
|
bAttached = true;
|
|
GEditor->ParentActors(ParentActorPtr, Actor, SocketName);
|
|
}
|
|
}
|
|
|
|
if (!bAttached)
|
|
{
|
|
Transaction.Cancel();
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetMaterialQualityLevel( EMaterialQualityLevel::Type NewQualityLevel )
|
|
{
|
|
auto* Settings = GetMutableDefault<UEditorPerProjectUserSettings>();
|
|
Settings->MaterialQualityLevel = NewQualityLevel;
|
|
Settings->PostEditChange();
|
|
|
|
//Ensure the material quality cvar is also set.
|
|
static IConsoleVariable* MaterialQualityLevelVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.MaterialQualityLevel"));
|
|
MaterialQualityLevelVar->Set(NewQualityLevel, ECVF_SetByScalability);
|
|
|
|
GUnrealEd->RedrawAllViewports();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsMaterialQualityLevelChecked( EMaterialQualityLevel::Type TestQualityLevel )
|
|
{
|
|
static const auto MaterialQualityLevelVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.MaterialQualityLevel"));
|
|
EMaterialQualityLevel::Type MaterialQualityLevel = (EMaterialQualityLevel::Type)FMath::Clamp(MaterialQualityLevelVar->GetValueOnGameThread(), 0, (int32)EMaterialQualityLevel::Num-1);
|
|
return TestQualityLevel == MaterialQualityLevel;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetPreviewPlatform(FName MaterialQualityPlatform)
|
|
{
|
|
UMaterialShaderQualitySettings::Get()->SetPreviewPlatform(MaterialQualityPlatform);
|
|
|
|
SetFeatureLevelPreview(ERHIFeatureLevel::ES2);
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsPreviewPlatformChecked(FName MaterialQualityPlatform)
|
|
{
|
|
const FName& PreviewPlatform = UMaterialShaderQualitySettings::Get()->GetPreviewPlatform();
|
|
return PreviewPlatform == MaterialQualityPlatform && ERHIFeatureLevel::ES2 == GetWorld()->FeatureLevel;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetFeatureLevelPreview(ERHIFeatureLevel::Type InPreviewFeatureLevel)
|
|
{
|
|
// Record this feature level as we want to use it for all subsequent level creation and loading
|
|
GEditor->DefaultWorldFeatureLevel = InPreviewFeatureLevel;
|
|
|
|
GetWorld()->ChangeFeatureLevel(InPreviewFeatureLevel);
|
|
|
|
// Update any currently running PIE sessions.
|
|
for (TObjectIterator<UWorld> It; It; ++It)
|
|
{
|
|
UWorld* ItWorld = *It;
|
|
if (ItWorld->WorldType == EWorldType::PIE)
|
|
{
|
|
ItWorld->ChangeFeatureLevel(InPreviewFeatureLevel);
|
|
}
|
|
}
|
|
|
|
GUnrealEd->RedrawAllViewports();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsFeatureLevelPreviewChecked(ERHIFeatureLevel::Type InPreviewFeatureLevel)
|
|
{
|
|
return InPreviewFeatureLevel == GetWorld()->FeatureLevel;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::ConfigureLightingBuildOptions( const FLightingBuildOptions& Options )
|
|
{
|
|
GConfig->SetBool( TEXT("LightingBuildOptions"), TEXT("OnlyBuildSelected"), Options.bOnlyBuildSelected, GEditorPerProjectIni );
|
|
GConfig->SetBool( TEXT("LightingBuildOptions"), TEXT("OnlyBuildCurrentLevel"), Options.bOnlyBuildCurrentLevel, GEditorPerProjectIni );
|
|
GConfig->SetBool( TEXT("LightingBuildOptions"), TEXT("OnlyBuildSelectedLevels"),Options.bOnlyBuildSelectedLevels, GEditorPerProjectIni );
|
|
GConfig->SetBool( TEXT("LightingBuildOptions"), TEXT("OnlyBuildVisibility"), Options.bOnlyBuildVisibility, GEditorPerProjectIni );
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::Build_Execute()
|
|
{
|
|
// Reset build options
|
|
ConfigureLightingBuildOptions( FLightingBuildOptions() );
|
|
|
|
// Build everything!
|
|
FEditorBuildUtils::EditorBuild( GetWorld(), FBuildOptions::BuildAll );
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::BuildAndSubmitToSourceControl_Execute()
|
|
{
|
|
FLevelEditorModule& LevelEditorModule = FModuleManager::GetModuleChecked<FLevelEditorModule>( TEXT("LevelEditor") );
|
|
LevelEditorModule.SummonBuildAndSubmit();
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::BuildLightingOnly_Execute()
|
|
{
|
|
// Reset build options
|
|
ConfigureLightingBuildOptions( FLightingBuildOptions() );
|
|
|
|
// Build lighting!
|
|
const bool bAllowLightingDialog = false;
|
|
FEditorBuildUtils::EditorBuild( GetWorld(), FBuildOptions::BuildLighting, bAllowLightingDialog );
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::BuildLighting_CanExecute()
|
|
{
|
|
static const auto AllowStaticLightingVar = IConsoleManager::Get().FindTConsoleVariableDataInt(TEXT("r.AllowStaticLighting"));
|
|
const bool bAllowStaticLighting = (!AllowStaticLightingVar || AllowStaticLightingVar->GetValueOnGameThread() != 0);
|
|
return bAllowStaticLighting;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::BuildReflectionCapturesOnly_Execute()
|
|
{
|
|
GEditor->UpdateReflectionCaptures();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::BuildLightingOnly_VisibilityOnly_Execute()
|
|
{
|
|
// Configure build options
|
|
FLightingBuildOptions LightingBuildOptions;
|
|
LightingBuildOptions.bOnlyBuildVisibility = true;
|
|
ConfigureLightingBuildOptions( LightingBuildOptions );
|
|
|
|
// Build lighting!
|
|
const bool bAllowLightingDialog = false;
|
|
FEditorBuildUtils::EditorBuild( GetWorld(), FBuildOptions::BuildLighting, bAllowLightingDialog );
|
|
|
|
// Reset build options
|
|
ConfigureLightingBuildOptions( FLightingBuildOptions() );
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::LightingBuildOptions_UseErrorColoring_IsChecked()
|
|
{
|
|
bool bUseErrorColoring = false;
|
|
GConfig->GetBool(TEXT("LightingBuildOptions"), TEXT("UseErrorColoring"), bUseErrorColoring, GEditorPerProjectIni);
|
|
return bUseErrorColoring;
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::LightingBuildOptions_UseErrorColoring_Toggled()
|
|
{
|
|
bool bUseErrorColoring = false;
|
|
GConfig->GetBool( TEXT("LightingBuildOptions"), TEXT("UseErrorColoring"), bUseErrorColoring, GEditorPerProjectIni );
|
|
GConfig->SetBool( TEXT("LightingBuildOptions"), TEXT("UseErrorColoring"), !bUseErrorColoring, GEditorPerProjectIni );
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::LightingBuildOptions_ShowLightingStats_IsChecked()
|
|
{
|
|
bool bShowLightingBuildInfo = false;
|
|
GConfig->GetBool(TEXT("LightingBuildOptions"), TEXT("ShowLightingBuildInfo"), bShowLightingBuildInfo, GEditorPerProjectIni);
|
|
return bShowLightingBuildInfo;
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::LightingBuildOptions_ShowLightingStats_Toggled()
|
|
{
|
|
bool bShowLightingBuildInfo = false;
|
|
GConfig->GetBool( TEXT("LightingBuildOptions"), TEXT("ShowLightingBuildInfo"), bShowLightingBuildInfo, GEditorPerProjectIni );
|
|
GConfig->SetBool( TEXT("LightingBuildOptions"), TEXT("ShowLightingBuildInfo"), !bShowLightingBuildInfo, GEditorPerProjectIni );
|
|
}
|
|
|
|
|
|
|
|
void FLevelEditorActionCallbacks::BuildGeometryOnly_Execute()
|
|
{
|
|
// Build geometry!
|
|
FEditorBuildUtils::EditorBuild( GetWorld(), FBuildOptions::BuildVisibleGeometry );
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::BuildGeometryOnly_OnlyCurrentLevel_Execute()
|
|
{
|
|
// Build geometry (current level)!
|
|
FEditorBuildUtils::EditorBuild( GetWorld(), FBuildOptions::BuildGeometry );
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::BuildPathsOnly_Execute()
|
|
{
|
|
// Build paths!
|
|
FEditorBuildUtils::EditorBuild( GetWorld(), FBuildOptions::BuildAIPaths );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::BuildLODsOnly_Execute()
|
|
{
|
|
// Build HLOD
|
|
FEditorBuildUtils::EditorBuild(GetWorld(), FBuildOptions::BuildHierarchicalLOD);
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::BuildTextureStreamingOnly_Execute()
|
|
{
|
|
FEditorBuildUtils::EditorBuildTextureStreaming(GetWorld());
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsLightingQualityChecked( ELightingBuildQuality TestQuality )
|
|
{
|
|
int32 CurrentQualityLevel;
|
|
GConfig->GetInt(TEXT("LightingBuildOptions"), TEXT("QualityLevel"), CurrentQualityLevel, GEditorPerProjectIni);
|
|
return TestQuality == CurrentQualityLevel;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingQuality( ELightingBuildQuality NewQuality )
|
|
{
|
|
GConfig->SetInt(TEXT("LightingBuildOptions"), TEXT("QualityLevel"), (int32)NewQuality, GEditorPerProjectIni);
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetLightingDensityIdeal()
|
|
{
|
|
return ( GEngine->IdealLightMapDensity );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingDensityIdeal( float Value )
|
|
{
|
|
GEngine->IdealLightMapDensity = Value;
|
|
|
|
// We need to make sure that Maximum is always slightly larger than ideal...
|
|
if (GEngine->IdealLightMapDensity >= GEngine->MaxLightMapDensity - 0.01f)
|
|
{
|
|
SetLightingDensityMaximum( GEngine->IdealLightMapDensity + 0.01f );
|
|
}
|
|
|
|
FEditorSupportDelegates::RedrawAllViewports.Broadcast();
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetLightingDensityMaximum()
|
|
{
|
|
return ( GEngine->MaxLightMapDensity );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingDensityMaximum( float Value )
|
|
{
|
|
GEngine->MaxLightMapDensity = Value;
|
|
|
|
// We need to make sure that Maximum is always slightly larger than ideal...
|
|
if (GEngine->MaxLightMapDensity <= GEngine->IdealLightMapDensity + 0.01f)
|
|
{
|
|
GEngine->MaxLightMapDensity = GEngine->IdealLightMapDensity + 0.01f;
|
|
}
|
|
|
|
FEditorSupportDelegates::RedrawAllViewports.Broadcast();
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetLightingDensityColorScale()
|
|
{
|
|
return ( GEngine->RenderLightMapDensityColorScale );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingDensityColorScale( float Value )
|
|
{
|
|
GEngine->RenderLightMapDensityColorScale = Value;
|
|
|
|
FEditorSupportDelegates::RedrawAllViewports.Broadcast();
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetLightingDensityGrayscaleScale()
|
|
{
|
|
return ( GEngine->RenderLightMapDensityGrayscaleScale );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingDensityGrayscaleScale( float Value )
|
|
{
|
|
GEngine->RenderLightMapDensityGrayscaleScale = Value;
|
|
|
|
FEditorSupportDelegates::RedrawAllViewports.Broadcast();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingDensityRenderGrayscale()
|
|
{
|
|
GEngine->bRenderLightMapDensityGrayscale = !GEngine->bRenderLightMapDensityGrayscale;
|
|
GEngine->SaveConfig();
|
|
FEditorSupportDelegates::RedrawAllViewports.Broadcast();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsLightingDensityRenderGrayscaleChecked()
|
|
{
|
|
return GEngine->bRenderLightMapDensityGrayscale;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionStaticMeshes( ECheckBoxState NewCheckedState )
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
Settings.bStaticMeshes = ( NewCheckedState == ECheckBoxState::Checked );
|
|
}
|
|
|
|
ECheckBoxState FLevelEditorActionCallbacks::IsLightingResolutionStaticMeshesChecked()
|
|
{
|
|
return ( FLightmapResRatioAdjustSettings::Get().bStaticMeshes ? ECheckBoxState::Checked : ECheckBoxState::Unchecked );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionBSPSurfaces( ECheckBoxState NewCheckedState )
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
Settings.bBSPSurfaces = ( NewCheckedState == ECheckBoxState::Checked );
|
|
}
|
|
|
|
ECheckBoxState FLevelEditorActionCallbacks::IsLightingResolutionBSPSurfacesChecked()
|
|
{
|
|
return ( FLightmapResRatioAdjustSettings::Get().bBSPSurfaces ? ECheckBoxState::Checked : ECheckBoxState::Unchecked );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionLevel( FLightmapResRatioAdjustSettings::AdjustLevels NewLevel )
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
Settings.LevelOptions = NewLevel;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsLightingResolutionLevelChecked( FLightmapResRatioAdjustSettings::AdjustLevels TestLevel )
|
|
{
|
|
return ( FLightmapResRatioAdjustSettings::Get().LevelOptions == TestLevel );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionSelectedObjectsOnly()
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
Settings.bSelectedObjectsOnly = !Settings.bSelectedObjectsOnly;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsLightingResolutionSelectedObjectsOnlyChecked()
|
|
{
|
|
return FLightmapResRatioAdjustSettings::Get().bSelectedObjectsOnly;
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetLightingResolutionMinSMs()
|
|
{
|
|
return static_cast<float>( FLightmapResRatioAdjustSettings::Get().Min_StaticMeshes );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionMinSMs( float Value )
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
Settings.Min_StaticMeshes = static_cast<int32>( Value );
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetLightingResolutionMaxSMs()
|
|
{
|
|
return static_cast<float>( FLightmapResRatioAdjustSettings::Get().Max_StaticMeshes );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionMaxSMs( float Value )
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
Settings.Max_StaticMeshes = static_cast<int32>( Value );
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetLightingResolutionMinBSPs()
|
|
{
|
|
return static_cast<float>( FLightmapResRatioAdjustSettings::Get().Min_BSPSurfaces );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionMinBSPs( float Value )
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
Settings.Min_BSPSurfaces = static_cast<int32>( Value );
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetLightingResolutionMaxBSPs()
|
|
{
|
|
return static_cast<float>( FLightmapResRatioAdjustSettings::Get().Max_BSPSurfaces );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionMaxBSPs( float Value )
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
Settings.Max_BSPSurfaces = static_cast<int32>( Value );
|
|
}
|
|
|
|
int32 FLevelEditorActionCallbacks::GetLightingResolutionRatio()
|
|
{
|
|
return FMath::RoundToInt(FLightmapResRatioAdjustSettings::Get().Ratio * 100.0f);
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionRatio( int32 Value )
|
|
{
|
|
FLightmapResRatioAdjustSettings& Settings = FLightmapResRatioAdjustSettings::Get();
|
|
const float NewValue = Value / 100.0f;
|
|
if ( Settings.Ratio != NewValue )
|
|
{
|
|
Settings.Ratio = NewValue;
|
|
Settings.ApplyRatioAdjustment();
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetLightingResolutionRatioCommit( int32 Value, ETextCommit::Type CommitInfo)
|
|
{
|
|
if ((CommitInfo == ETextCommit::OnEnter) || (CommitInfo == ETextCommit::OnUserMovedFocus))
|
|
{
|
|
SetLightingResolutionRatio( Value );
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::ShowLightingStaticMeshInfo()
|
|
{
|
|
if (GUnrealEd)
|
|
{
|
|
GUnrealEd->ShowLightingStaticMeshInfoWindow();
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::ShowSceneStats()
|
|
{
|
|
if (GUnrealEd)
|
|
{
|
|
GUnrealEd->OpenSceneStatsWindow();
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::ShowTextureStats()
|
|
{
|
|
if (GUnrealEd)
|
|
{
|
|
GUnrealEd->OpenTextureStatsWindow();
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::MapCheck_Execute()
|
|
{
|
|
GEditor->Exec( GetWorld(), TEXT("MAP CHECK") );
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanShowSourceCodeActions()
|
|
{
|
|
if (GEditor)
|
|
{
|
|
// Don't allow hot reloading if we're running networked PIE instances
|
|
// The reason, is it's fairly complicated to handle the re-wiring that needs to happen when we re-instance objects like player controllers, possessed pawns, etc...
|
|
const TIndirectArray<FWorldContext>& WorldContextList = GEditor->GetWorldContexts();
|
|
|
|
for (const FWorldContext& WorldContext : WorldContextList)
|
|
{
|
|
if (WorldContext.World() && WorldContext.World()->WorldType == EWorldType::PIE && WorldContext.World()->NetDriver)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
IHotReloadInterface& HotReloadSupport = FModuleManager::LoadModuleChecked<IHotReloadInterface>(HotReloadModule);
|
|
// If there is at least one loaded game module, source code actions should be available.
|
|
return HotReloadSupport.IsAnyGameModuleLoaded();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::RecompileGameCode_Clicked()
|
|
{
|
|
// Don't allow a recompile while already compiling!
|
|
IHotReloadInterface& HotReloadSupport = FModuleManager::LoadModuleChecked<IHotReloadInterface>(HotReloadModule);
|
|
if( !HotReloadSupport.IsCurrentlyCompiling() )
|
|
{
|
|
// Don't wait -- we want compiling to happen asynchronously
|
|
const bool bWaitForCompletion = false;
|
|
HotReloadSupport.DoHotReloadFromEditor(bWaitForCompletion);
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Recompile_CanExecute()
|
|
{
|
|
// We're not able to recompile if a compile is already in progress!
|
|
|
|
IHotReloadInterface& HotReloadSupport = FModuleManager::LoadModuleChecked<IHotReloadInterface>(HotReloadModule);
|
|
return !HotReloadSupport.IsCurrentlyCompiling() && !(FApp::GetEngineIsPromotedBuild() && FEngineBuildSettings::IsPerforceBuild());
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::ConnectToSourceControl_Clicked()
|
|
{
|
|
// Show login window regardless of current status - its useful as a shortcut to change settings.
|
|
ISourceControlModule& SourceControlModule = ISourceControlModule::Get();
|
|
SourceControlModule.ShowLoginDialog(FSourceControlLoginClosed(), ELoginWindowMode::Modeless, EOnLoginWindowStartup::PreserveProvider);
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CheckOutModifiedFiles_CanExecute()
|
|
{
|
|
ISourceControlModule& SourceControlModule = ISourceControlModule::Get();
|
|
if (ISourceControlModule::Get().IsEnabled() &&
|
|
ISourceControlModule::Get().GetProvider().IsAvailable())
|
|
{
|
|
TArray<UPackage*> PackagesToSave;
|
|
FEditorFileUtils::GetDirtyWorldPackages(PackagesToSave);
|
|
FEditorFileUtils::GetDirtyContentPackages(PackagesToSave);
|
|
|
|
return PackagesToSave.Num() > 0;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::CheckOutModifiedFiles_Clicked()
|
|
{
|
|
TArray<UPackage*> PackagesToSave;
|
|
FEditorFileUtils::GetDirtyWorldPackages(PackagesToSave);
|
|
FEditorFileUtils::GetDirtyContentPackages(PackagesToSave);
|
|
|
|
const bool bCheckDirty = true;
|
|
const bool bPromptUserToSave = false;
|
|
FEditorFileUtils::PromptForCheckoutAndSave(PackagesToSave, bCheckDirty, bPromptUserToSave);
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::SubmitToSourceControl_CanExecute()
|
|
{
|
|
ISourceControlModule& SourceControlModule = ISourceControlModule::Get();
|
|
return ISourceControlModule::Get().IsEnabled() &&
|
|
ISourceControlModule::Get().GetProvider().IsAvailable() &&
|
|
FSourceControlWindows::CanChoosePackagesToCheckIn();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SubmitToSourceControl_Clicked()
|
|
{
|
|
FSourceControlWindows::ChoosePackagesToCheckIn();
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::GoToCodeForActor_Clicked()
|
|
{
|
|
const auto& SelectedActorInfo = AssetSelectionUtils::GetSelectedActorInfo();
|
|
if( SelectedActorInfo.SelectionClass != nullptr )
|
|
{
|
|
FString ClassHeaderPath;
|
|
if( FSourceCodeNavigation::FindClassHeaderPath( SelectedActorInfo.SelectionClass, ClassHeaderPath ) && IFileManager::Get().FileSize( *ClassHeaderPath ) != INDEX_NONE )
|
|
{
|
|
FString AbsoluteHeaderPath = IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*ClassHeaderPath);
|
|
FSourceCodeNavigation::OpenSourceFile( AbsoluteHeaderPath );
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::GoToDocsForActor_Clicked()
|
|
{
|
|
const auto& SelectedActorInfo = AssetSelectionUtils::GetSelectedActorInfo();
|
|
if( SelectedActorInfo.SelectionClass != nullptr )
|
|
{
|
|
FString DocumentationLink = FEditorClassUtils::GetDocumentationLink(SelectedActorInfo.SelectionClass);
|
|
if (!DocumentationLink.IsEmpty())
|
|
{
|
|
IDocumentation::Get()->Open( DocumentationLink, FDocumentationSourceInfo(TEXT("rightclick_viewdoc")) );
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::FindInContentBrowser_Clicked()
|
|
{
|
|
GEditor->SyncToContentBrowser();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::ViewReferences_Execute()
|
|
{
|
|
if( GEditor->GetSelectedActorCount() > 0 )
|
|
{
|
|
TArray< UObject* > ReferencedAssets;
|
|
GEditor->GetReferencedAssetsForEditorSelection( ReferencedAssets );
|
|
|
|
if (ReferencedAssets.Num() > 0)
|
|
{
|
|
TArray< FName > ViewableObjects;
|
|
for( auto ObjectIter = ReferencedAssets.CreateConstIterator(); ObjectIter; ++ObjectIter )
|
|
{
|
|
// Don't allow user to perform certain actions on objects that aren't actually assets (e.g. Level Script blueprint objects)
|
|
const auto EditingObject = *ObjectIter;
|
|
if( EditingObject != NULL && EditingObject->IsAsset() )
|
|
{
|
|
ViewableObjects.Add( EditingObject->GetOuter()->GetFName());
|
|
}
|
|
}
|
|
|
|
IReferenceViewerModule::Get().InvokeReferenceViewerTab(ViewableObjects);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanViewReferences()
|
|
{
|
|
TArray< UObject* > ReferencedAssets;
|
|
GEditor->GetReferencedAssetsForEditorSelection(ReferencedAssets);
|
|
return ReferencedAssets.Num() > 0;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::ViewSizeMap_Execute()
|
|
{
|
|
if( GEditor->GetSelectedActorCount() > 0 )
|
|
{
|
|
TArray< UObject* > ReferencedAssets;
|
|
GEditor->GetReferencedAssetsForEditorSelection( ReferencedAssets );
|
|
|
|
if (ReferencedAssets.Num() > 0)
|
|
{
|
|
TArray< FName > ViewableObjects;
|
|
for( auto ObjectIter = ReferencedAssets.CreateConstIterator(); ObjectIter; ++ObjectIter )
|
|
{
|
|
// Don't allow user to perform certain actions on objects that aren't actually assets (e.g. Level Script blueprint objects)
|
|
const auto EditingObject = *ObjectIter;
|
|
if( EditingObject != NULL && EditingObject->IsAsset() )
|
|
{
|
|
ViewableObjects.Add( EditingObject->GetOuter()->GetFName());
|
|
}
|
|
}
|
|
|
|
ISizeMapModule::Get().InvokeSizeMapTab(ViewableObjects);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanViewSizeMap()
|
|
{
|
|
TArray< UObject* > ReferencedAssets;
|
|
GEditor->GetReferencedAssetsForEditorSelection(ReferencedAssets);
|
|
return ReferencedAssets.Num() > 0;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::EditAsset_Clicked( const EToolkitMode::Type ToolkitMode, TWeakPtr< SLevelEditor > LevelEditor, bool bConfirmMultiple )
|
|
{
|
|
if( GEditor->GetSelectedActorCount() > 0 )
|
|
{
|
|
TArray< UObject* > ReferencedAssets;
|
|
const bool bIgnoreOtherAssetsIfBPReferenced = true;
|
|
GEditor->GetReferencedAssetsForEditorSelection( ReferencedAssets, bIgnoreOtherAssetsIfBPReferenced );
|
|
|
|
bool bShouldOpenEditors = (ReferencedAssets.Num() == 1);
|
|
|
|
if (ReferencedAssets.Num() > 1)
|
|
{
|
|
if (bConfirmMultiple)
|
|
{
|
|
int32 Response = FMessageDialog::Open(
|
|
EAppMsgType::YesNo,
|
|
LOCTEXT("OpenAllAssetEditors", "There is more than one referenced asset in the selection. Do you want to open them all for editing?")
|
|
);
|
|
|
|
bShouldOpenEditors = (Response == EAppReturnType::Yes);
|
|
}
|
|
else
|
|
{
|
|
bShouldOpenEditors = true;
|
|
}
|
|
}
|
|
|
|
if (bShouldOpenEditors)
|
|
{
|
|
// Clear focus so the level viewport can receive its focus lost call (and clear pending keyup events which wouldn't arrive)
|
|
FSlateApplication::Get().ClearKeyboardFocus(EFocusCause::WindowActivate);
|
|
|
|
auto LevelEditorSharedPtr = LevelEditor.Pin();
|
|
|
|
if (LevelEditorSharedPtr.IsValid())
|
|
{
|
|
for (auto Asset : ReferencedAssets)
|
|
{
|
|
FAssetEditorManager::Get().OpenEditorForAsset(Asset, ToolkitMode, LevelEditorSharedPtr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::LockActorMovement_Clicked()
|
|
{
|
|
GEditor->ToggleSelectedActorMovementLock();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::DetachActor_Clicked()
|
|
{
|
|
GEditor->DetachSelectedActors();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::AttachSelectedActors()
|
|
{
|
|
GUnrealEd->AttachSelectedActors();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::AttachActorIteractive()
|
|
{
|
|
if(GUnrealEd->GetSelectedActorCount())
|
|
{
|
|
FActorPickerModeModule& ActorPickerMode = FModuleManager::Get().GetModuleChecked<FActorPickerModeModule>("ActorPickerMode");
|
|
|
|
ActorPickerMode.BeginActorPickingMode(
|
|
FOnGetAllowedClasses(),
|
|
FOnShouldFilterActor::CreateStatic(&FLevelEditorActionCallbacks::IsAttachableActor),
|
|
FOnActorSelected::CreateStatic(&FLevelEditorActionCallbacks::AttachToActor)
|
|
);
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsAttachableActor( const AActor* const ParentActor )
|
|
{
|
|
for ( FSelectionIterator It( GEditor->GetSelectedActorIterator() ) ; It ; ++It )
|
|
{
|
|
AActor* Actor = static_cast<AActor*>( *It );
|
|
if (!GEditor->CanParentActors(ParentActor, Actor))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
USceneComponent* ChildRoot = Actor->GetRootComponent();
|
|
USceneComponent* ParentRoot = ParentActor->GetRootComponent();
|
|
|
|
if (ChildRoot != nullptr && ParentRoot != nullptr && ChildRoot->IsAttachedTo(ParentRoot))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::CreateNewOutlinerFolder_Clicked()
|
|
{
|
|
const FName NewFolderName = FActorFolders::Get().GetDefaultFolderNameForSelection(*GetWorld());
|
|
FActorFolders::Get().CreateFolderContainingSelection(*GetWorld(), NewFolderName);
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::GoHere_Clicked( const FVector* Point )
|
|
{
|
|
if( GCurrentLevelEditingViewportClient )
|
|
{
|
|
FVector ZoomToPoint;
|
|
if( !Point )
|
|
{
|
|
FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues(
|
|
GCurrentLevelEditingViewportClient->Viewport,
|
|
GCurrentLevelEditingViewportClient->GetWorld()->Scene,
|
|
GCurrentLevelEditingViewportClient->EngineShowFlags)
|
|
.SetRealtimeUpdate(true));
|
|
|
|
|
|
FSceneView* SceneView = GCurrentLevelEditingViewportClient->CalcSceneView(&ViewFamily);
|
|
|
|
if(SceneView)
|
|
{
|
|
FIntPoint MousePosition;
|
|
FVector WorldOrigin;
|
|
FVector WorldDirection;
|
|
GCurrentLevelEditingViewportClient->Viewport->GetMousePos(MousePosition);
|
|
|
|
SceneView->DeprojectFVector2D(MousePosition, WorldOrigin, WorldDirection);
|
|
|
|
FHitResult HitResult;
|
|
|
|
static FName FocusOnPoint = FName(TEXT("FocusOnPoint"));
|
|
FCollisionQueryParams LineParams(FocusOnPoint, true);
|
|
|
|
if(GCurrentLevelEditingViewportClient->GetWorld()->LineTraceSingleByObjectType(HitResult, WorldOrigin, WorldOrigin + WorldDirection * HALF_WORLD_MAX, FCollisionObjectQueryParams(ECC_WorldStatic), LineParams))
|
|
{
|
|
ZoomToPoint = HitResult.ImpactPoint;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ZoomToPoint = *Point;
|
|
}
|
|
|
|
const float PushOutSize = 500;
|
|
FBox BoundingBox(ZoomToPoint-PushOutSize, ZoomToPoint+PushOutSize);
|
|
|
|
GCurrentLevelEditingViewportClient->FocusViewportOnBox(BoundingBox);
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::LockActorMovement_IsChecked()
|
|
{
|
|
return GEditor->HasLockedActors();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::AddActor_Clicked( UActorFactory* ActorFactory, FAssetData AssetData, bool bUsePlacement )
|
|
{
|
|
UObject* Object = AssetData.GetAsset();
|
|
if(bUsePlacement && IPlacementModeModule::IsAvailable() && Object != NULL)
|
|
{
|
|
FLevelEditorModule& LevelEditorModule = FModuleManager::LoadModuleChecked<FLevelEditorModule>("LevelEditor");
|
|
LevelEditorModule.FocusViewport();
|
|
|
|
// Make sure we're in actor placement mode
|
|
GLevelEditorModeTools().ActivateMode(FBuiltinEditorModes::EM_Placement);
|
|
|
|
TArray<UObject*> AssetsToPlace;
|
|
AssetsToPlace.Add(Object);
|
|
|
|
auto* PlacementMode = GLevelEditorModeTools().GetActiveModeTyped<IPlacementMode>(FBuiltinEditorModes::EM_Placement);
|
|
PlacementMode->StartPlacing(AssetsToPlace, ActorFactory);
|
|
}
|
|
else
|
|
{
|
|
FLevelEditorActionCallbacks::AddActor(ActorFactory, AssetData, NULL);
|
|
}
|
|
}
|
|
|
|
AActor* FLevelEditorActionCallbacks::AddActor( UActorFactory* ActorFactory, const FAssetData& AssetData, const FTransform* ActorTransform )
|
|
{
|
|
AActor* NewActor = GEditor->UseActorFactory( ActorFactory, AssetData, ActorTransform );
|
|
|
|
if ( NewActor != NULL && IPlacementModeModule::IsAvailable() )
|
|
{
|
|
IPlacementModeModule::Get().AddToRecentlyPlaced( AssetData.GetAsset(), ActorFactory );
|
|
}
|
|
|
|
return NewActor;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::AddActorFromClass_Clicked( UClass* ActorClass )
|
|
{
|
|
FLevelEditorActionCallbacks::AddActorFromClass(ActorClass);
|
|
}
|
|
|
|
AActor* FLevelEditorActionCallbacks::AddActorFromClass( UClass* ActorClass )
|
|
{
|
|
AActor* NewActor = NULL;
|
|
|
|
if ( ActorClass )
|
|
{
|
|
// Look for an actor factory capable of creating actors of that type.
|
|
UActorFactory* ActorFactory = GEditor->FindActorFactoryForActorClass( ActorClass );
|
|
if( ActorFactory )
|
|
{
|
|
NewActor = GEditor->UseActorFactoryOnCurrentSelection( ActorFactory, nullptr );
|
|
|
|
if ( NewActor != NULL && IPlacementModeModule::IsAvailable() )
|
|
{
|
|
IPlacementModeModule::Get().AddToRecentlyPlaced( ActorClass, ActorFactory );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// No actor factory was found; use SpawnActor instead.
|
|
GUnrealEd->Exec( GetWorld(), *FString::Printf( TEXT("ACTOR ADD CLASS=%s"), *ActorClass->GetName() ) );
|
|
}
|
|
}
|
|
|
|
return NewActor;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::ReplaceActors_Clicked( UActorFactory* ActorFactory, FAssetData AssetData )
|
|
{
|
|
FLevelEditorActionCallbacks::ReplaceActors(ActorFactory, AssetData);
|
|
}
|
|
|
|
AActor* FLevelEditorActionCallbacks::ReplaceActors( UActorFactory* ActorFactory, const FAssetData& AssetData )
|
|
{
|
|
AActor* NewActor = NULL;
|
|
|
|
// Have a first stab at filling in the factory properties.
|
|
FText ErrorMessage;
|
|
if( ActorFactory->CanCreateActorFrom( AssetData, ErrorMessage ) )
|
|
{
|
|
// Replace all selected actors with actors created from the specified factory
|
|
GEditor->ReplaceSelectedActors( ActorFactory, AssetData );
|
|
|
|
if ( IPlacementModeModule::IsAvailable() )
|
|
{
|
|
IPlacementModeModule::Get().AddToRecentlyPlaced( AssetData.GetAsset(), ActorFactory );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FNotificationInfo ErrorNotification( ErrorMessage );
|
|
ErrorNotification.Image = FEditorStyle::GetBrush(TEXT("MessageLog.Error"));
|
|
ErrorNotification.bFireAndForget = true;
|
|
ErrorNotification.ExpireDuration = 3.0f; // Need this message to last a little longer than normal since the user may want to "Show Log"
|
|
ErrorNotification.bUseThrobber = true;
|
|
|
|
FSlateNotificationManager::Get().AddNotification(ErrorNotification);
|
|
}
|
|
|
|
return NewActor;
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::ReplaceActorsFromClass_Clicked( UClass* ActorClass )
|
|
{
|
|
if ( ActorClass )
|
|
{
|
|
// Look for an actor factory capable of creating actors of that type.
|
|
UActorFactory* ActorFactory = GEditor->FindActorFactoryForActorClass( ActorClass );
|
|
if( ActorFactory )
|
|
{
|
|
// Replace all selected actors with actors created from the specified factory
|
|
UObject* TargetAsset = GEditor->GetSelectedObjects()->GetTop<UObject>();
|
|
|
|
FText ErrorMessage;
|
|
FText UnusedErrorMessage;
|
|
const FAssetData NoAssetData;
|
|
const FAssetData TargetAssetData(TargetAsset);
|
|
if( ActorFactory->CanCreateActorFrom( TargetAssetData, ErrorMessage ) )
|
|
{
|
|
// Replace all selected actors with actors created from the specified factory
|
|
GEditor->ReplaceSelectedActors( ActorFactory, TargetAssetData );
|
|
}
|
|
else if ( ActorFactory->CanCreateActorFrom( NoAssetData, UnusedErrorMessage ) )
|
|
{
|
|
// Replace all selected actors with actors created from the specified factory
|
|
GEditor->ReplaceSelectedActors( ActorFactory, NoAssetData );
|
|
}
|
|
else
|
|
{
|
|
FNotificationInfo ErrorNotification( ErrorMessage );
|
|
ErrorNotification.Image = FEditorStyle::GetBrush(TEXT("MessageLog.Error"));
|
|
ErrorNotification.bFireAndForget = true;
|
|
ErrorNotification.ExpireDuration = 3.0f; // Need this message to last a little longer than normal since the user may want to "Show Log"
|
|
ErrorNotification.bUseThrobber = true;
|
|
|
|
FSlateNotificationManager::Get().AddNotification(ErrorNotification);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// No actor factory was found; use SpawnActor instead.
|
|
GUnrealEd->Exec( GetWorld(), *FString::Printf( TEXT("ACTOR REPLACE CLASS=%s"), *ActorClass->GetName() ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Duplicate_CanExecute()
|
|
{
|
|
TArray<FEdMode*> ActiveModes;
|
|
GLevelEditorModeTools().GetActiveModes( ActiveModes );
|
|
for( int32 ModeIndex = 0; ModeIndex < ActiveModes.Num(); ++ModeIndex )
|
|
{
|
|
const EEditAction::Type CanProcess = ActiveModes[ModeIndex]->GetActionEditDuplicate();
|
|
if (CanProcess == EEditAction::Process)
|
|
{
|
|
return true;
|
|
}
|
|
else if (CanProcess == EEditAction::Halt)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// If we can copy, we can duplicate
|
|
bool bCanCopy = false;
|
|
if (GEditor->GetSelectedComponentCount() > 0)
|
|
{
|
|
TArray<UActorComponent*> SelectedComponents;
|
|
for (FSelectionIterator It(GEditor->GetSelectedComponentIterator()); It; ++It)
|
|
{
|
|
SelectedComponents.Add(CastChecked<UActorComponent>(*It));
|
|
}
|
|
|
|
bCanCopy = FComponentEditorUtils::CanCopyComponents(SelectedComponents);
|
|
}
|
|
else
|
|
{
|
|
bCanCopy = GUnrealEd->CanCopySelectedActorsToClipboard(GetWorld());
|
|
}
|
|
|
|
return bCanCopy;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Delete_CanExecute()
|
|
{
|
|
TArray<FEdMode*> ActiveModes;
|
|
GLevelEditorModeTools().GetActiveModes( ActiveModes );
|
|
for( int32 ModeIndex = 0; ModeIndex < ActiveModes.Num(); ++ModeIndex )
|
|
{
|
|
const EEditAction::Type CanProcess = ActiveModes[ModeIndex]->GetActionEditDelete();
|
|
if (CanProcess == EEditAction::Process)
|
|
{
|
|
return true;
|
|
}
|
|
else if (CanProcess == EEditAction::Halt)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool bCanDelete = false;
|
|
if (GEditor->GetSelectedComponentCount() > 0)
|
|
{
|
|
TArray<UActorComponent*> SelectedComponents;
|
|
for (FSelectionIterator It(GEditor->GetSelectedComponentIterator()); It; ++It)
|
|
{
|
|
SelectedComponents.Add(CastChecked<UActorComponent>(*It));
|
|
}
|
|
|
|
bCanDelete = FComponentEditorUtils::CanDeleteComponents(SelectedComponents);
|
|
}
|
|
else
|
|
{
|
|
bCanDelete = GUnrealEd->CanDeleteSelectedActors(GetWorld(), true, false);
|
|
}
|
|
|
|
return bCanDelete;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::Rename_Execute()
|
|
{
|
|
UActorComponent* Component = Cast<UActorComponent>(*GEditor->GetSelectedComponentIterator());
|
|
if (Component)
|
|
{
|
|
GEditor->BroadcastLevelComponentRequestRename(Component);
|
|
}
|
|
else
|
|
{
|
|
AActor* Actor = Cast<AActor>(*GEditor->GetSelectedActorIterator());
|
|
if (Actor)
|
|
{
|
|
GEditor->BroadcastLevelActorRequestRename(Actor);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Rename_CanExecute()
|
|
{
|
|
bool bCanRename = false;
|
|
if (GEditor->GetSelectedComponentCount() == 1)
|
|
{
|
|
if (UActorComponent* ComponentToRename = GEditor->GetSelectedComponents()->GetTop<UActorComponent>())
|
|
{
|
|
// We can't edit non-instance components or the default scene root
|
|
bCanRename = ComponentToRename->CreationMethod == EComponentCreationMethod::Instance && ComponentToRename->GetFName() != USceneComponent::GetDefaultSceneRootVariableName();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bCanRename = GEditor->GetSelectedActorCount() == 1;
|
|
}
|
|
|
|
return bCanRename;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Cut_CanExecute()
|
|
{
|
|
TArray<FEdMode*> ActiveModes;
|
|
GLevelEditorModeTools().GetActiveModes( ActiveModes );
|
|
for( int32 ModeIndex = 0; ModeIndex < ActiveModes.Num(); ++ModeIndex )
|
|
{
|
|
const EEditAction::Type CanProcess = ActiveModes[ModeIndex]->GetActionEditCut();
|
|
if (CanProcess == EEditAction::Process)
|
|
{
|
|
return true;
|
|
}
|
|
else if (CanProcess == EEditAction::Halt)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool bCanCut = false;
|
|
if (GEditor->GetSelectedComponentCount() > 0)
|
|
{
|
|
// Make sure the components can be copied and deleted
|
|
TArray<UActorComponent*> SelectedComponents;
|
|
for (FSelectionIterator It(GEditor->GetSelectedComponentIterator()); It; ++It)
|
|
{
|
|
SelectedComponents.Add(CastChecked<UActorComponent>(*It));
|
|
}
|
|
|
|
bCanCut = FComponentEditorUtils::CanCopyComponents(SelectedComponents) && FComponentEditorUtils::CanDeleteComponents(SelectedComponents);
|
|
}
|
|
else
|
|
{
|
|
// For actors, if we can copy, we can cut
|
|
bCanCut = GUnrealEd->CanCopySelectedActorsToClipboard(GetWorld());
|
|
}
|
|
|
|
return bCanCut;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Copy_CanExecute()
|
|
{
|
|
TArray<FEdMode*> ActiveModes;
|
|
GLevelEditorModeTools().GetActiveModes( ActiveModes );
|
|
for( int32 ModeIndex = 0; ModeIndex < ActiveModes.Num(); ++ModeIndex )
|
|
{
|
|
const EEditAction::Type CanProcess = ActiveModes[ModeIndex]->GetActionEditCopy();
|
|
if (CanProcess == EEditAction::Process)
|
|
{
|
|
return true;
|
|
}
|
|
else if (CanProcess == EEditAction::Halt)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool bCanCopy = false;
|
|
if (GEditor->GetSelectedComponentCount() > 0)
|
|
{
|
|
TArray<UActorComponent*> SelectedComponents;
|
|
for (FSelectionIterator It(GEditor->GetSelectedComponentIterator()); It; ++It)
|
|
{
|
|
SelectedComponents.Add(CastChecked<UActorComponent>(*It));
|
|
}
|
|
|
|
bCanCopy = FComponentEditorUtils::CanCopyComponents(SelectedComponents);
|
|
}
|
|
else
|
|
{
|
|
bCanCopy = GUnrealEd->CanCopySelectedActorsToClipboard(GetWorld());
|
|
}
|
|
|
|
return bCanCopy;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::Paste_CanExecute()
|
|
{
|
|
TArray<FEdMode*> ActiveModes;
|
|
GLevelEditorModeTools().GetActiveModes( ActiveModes );
|
|
for( int32 ModeIndex = 0; ModeIndex < ActiveModes.Num(); ++ModeIndex )
|
|
{
|
|
const EEditAction::Type CanProcess = ActiveModes[ModeIndex]->GetActionEditPaste();
|
|
if (CanProcess == EEditAction::Process)
|
|
{
|
|
return true;
|
|
}
|
|
else if (CanProcess == EEditAction::Halt)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool bCanPaste = false;
|
|
if (GEditor->GetSelectedComponentCount() > 0)
|
|
{
|
|
check(GEditor->GetSelectedActorCount() == 1);
|
|
auto SelectedActor = CastChecked<AActor>(*GEditor->GetSelectedActorIterator());
|
|
bCanPaste = FComponentEditorUtils::CanPasteComponents(SelectedActor->GetRootComponent());
|
|
}
|
|
else
|
|
{
|
|
bCanPaste = GUnrealEd->CanPasteSelectedActorsFromClipboard(GetWorld());
|
|
}
|
|
|
|
return bCanPaste;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::PasteHere_CanExecute()
|
|
{
|
|
return Paste_CanExecute(); // For now, just do the same check as Paste
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::ExecuteExecCommand( FString Command )
|
|
{
|
|
UWorld* OldWorld = nullptr;
|
|
|
|
// The play world needs to be selected if it exists
|
|
if (GIsEditor && GEditor->PlayWorld && !GIsPlayInEditorWorld)
|
|
{
|
|
OldWorld = SetPlayInEditorWorld(GEditor->PlayWorld);
|
|
}
|
|
|
|
GUnrealEd->Exec(GetWorld(), *Command);
|
|
|
|
// Restore the old world if there was one
|
|
if (OldWorld)
|
|
{
|
|
RestoreEditorWorld(OldWorld);
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSelectAllActorsOfClass( bool bArchetype )
|
|
{
|
|
GEditor->SelectAllActorsWithClass( bArchetype );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSelectComponentOwnerActor()
|
|
{
|
|
auto ComponentOwner = Cast<AActor>(*GEditor->GetSelectedActorIterator());
|
|
check(ComponentOwner);
|
|
|
|
GEditor->SelectNone(true, true, false);
|
|
GEditor->SelectActor(ComponentOwner, true, true, true);
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanSelectComponentOwnerActor()
|
|
{
|
|
return GEditor->GetSelectedComponentCount() > 0;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSelectAllActorsControlledByMatinee()
|
|
{
|
|
GEditor->SelectAllActorsControlledByMatinee();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSelectOwningHLODCluster()
|
|
{
|
|
if (GEditor->GetSelectedActorCount() > 0)
|
|
{
|
|
AActor* Actor = Cast<AActor>(GEditor->GetSelectedActors()->GetSelectedObject(0));
|
|
|
|
FHierarchicalLODUtilitiesModule& Module = FModuleManager::LoadModuleChecked<FHierarchicalLODUtilitiesModule>("HierarchicalLODUtilities");
|
|
IHierarchicalLODUtilities* Utilities = Module.GetUtilities();
|
|
|
|
ALODActor* ParentActor = Utilities->GetParentLODActor(Actor);
|
|
if (Actor && ParentActor)
|
|
{
|
|
GEditor->SelectNone(false, true);
|
|
GEditor->SelectActor(ParentActor, true, false);
|
|
GEditor->NoteSelectionChange();
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSelectMatineeActor( AMatineeActor * ActorToSelect )
|
|
{
|
|
GEditor->SelectNone( false, true );
|
|
GEditor->SelectActor(ActorToSelect, true, false, true);
|
|
|
|
GEditor->NoteSelectionChange();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSelectMatineeGroup( AActor* Actor )
|
|
{
|
|
if( GLevelEditorModeTools().IsModeActive( FBuiltinEditorModes::EM_InterpEdit ) )
|
|
{
|
|
FEdModeInterpEdit* InterpEditMode = (FEdModeInterpEdit*)GLevelEditorModeTools().GetActiveMode( FBuiltinEditorModes::EM_InterpEdit );
|
|
|
|
if ( InterpEditMode && InterpEditMode->MatineeActor )
|
|
{
|
|
InterpEditMode->UpdateSelectedActor();
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnApplyMaterialToSurface()
|
|
{
|
|
FEditorDelegates::LoadSelectedAssetsIfNeeded.Broadcast();
|
|
|
|
GUnrealEd->Exec( GetWorld(), TEXT("POLY SETMATERIAL") );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSelectAllLights()
|
|
{
|
|
GEditor->GetSelectedActors()->BeginBatchSelectOperation();
|
|
// Select all light actors.
|
|
for( ALight* Light : TActorRange<ALight>(GetWorld()) )
|
|
{
|
|
GUnrealEd->SelectActor( Light, true, false, false );
|
|
}
|
|
|
|
GEditor->GetSelectedActors()->EndBatchSelectOperation();
|
|
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSelectStationaryLightsExceedingOverlap()
|
|
{
|
|
GEditor->SelectNone( true, true );
|
|
for( FActorIterator It(GetWorld()); It; ++It )
|
|
{
|
|
AActor* Actor = *It;
|
|
|
|
TInlineComponentArray<ULightComponent*> Components;
|
|
Actor->GetComponents(Components);
|
|
|
|
for (int32 ComponentIndex = 0; ComponentIndex < Components.Num(); ComponentIndex++)
|
|
{
|
|
ULightComponent* LightComponent = Components[ComponentIndex];
|
|
|
|
if (LightComponent->GetOwner()
|
|
// Use the component's lighting properties to determine if this is a stationary light, instead of checking the actor type
|
|
// Because blueprint lights may be operating as stationary lights
|
|
&& LightComponent->HasStaticShadowing()
|
|
&& !LightComponent->HasStaticLighting()
|
|
&& LightComponent->bAffectsWorld
|
|
&& LightComponent->CastShadows
|
|
&& LightComponent->CastStaticShadows
|
|
&& LightComponent->PreviewShadowMapChannel == INDEX_NONE)
|
|
{
|
|
GUnrealEd->SelectActor( LightComponent->GetOwner(), true, true, false );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSurfaceAlignment( ETexAlign AlignmentMode )
|
|
{
|
|
GTexAlignTools.GetAligner( AlignmentMode )->Align( GetWorld(), AlignmentMode );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::RegroupActor_Clicked()
|
|
{
|
|
GUnrealEd->edactRegroupFromSelected();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::UngroupActor_Clicked()
|
|
{
|
|
GUnrealEd->edactUngroupFromSelected();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::LockGroup_Clicked()
|
|
{
|
|
GUnrealEd->edactLockSelectedGroups();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::UnlockGroup_Clicked()
|
|
{
|
|
GUnrealEd->edactUnlockSelectedGroups();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::AddActorsToGroup_Clicked()
|
|
{
|
|
GUnrealEd->edactAddToGroup();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::RemoveActorsFromGroup_Clicked()
|
|
{
|
|
GUnrealEd->edactRemoveFromGroup();
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::LocationGridSnap_Clicked()
|
|
{
|
|
GUnrealEd->Exec( GetWorld(), *FString::Printf( TEXT("MODE GRID=%d"), !GetDefault<ULevelEditorViewportSettings>()->GridEnabled ? 1 : 0 ) );
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::LocationGridSnap_IsChecked()
|
|
{
|
|
return GetDefault<ULevelEditorViewportSettings>()->GridEnabled;
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::RotationGridSnap_Clicked()
|
|
{
|
|
GUnrealEd->Exec( GetWorld(), *FString::Printf( TEXT("MODE ROTGRID=%d"), !GetDefault<ULevelEditorViewportSettings>()->RotGridEnabled ? 1 : 0 ) );
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::RotationGridSnap_IsChecked()
|
|
{
|
|
return GetDefault<ULevelEditorViewportSettings>()->RotGridEnabled;
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::ScaleGridSnap_Clicked()
|
|
{
|
|
GUnrealEd->Exec( GetWorld(), *FString::Printf( TEXT("MODE SCALEGRID=%d"), !GetDefault<ULevelEditorViewportSettings>()->SnapScaleEnabled ? 1 : 0 ) );
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::ScaleGridSnap_IsChecked()
|
|
{
|
|
return GetDefault<ULevelEditorViewportSettings>()->SnapScaleEnabled;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::SaveAnimationFromSkeletalMeshComponent(AActor * EditorActor, AActor * SimActor, TArray<class USkeletalMeshComponent*> & OutEditorComponents)
|
|
{
|
|
FLevelEditorModule& LevelEditorModule = FModuleManager::GetModuleChecked<FLevelEditorModule>( TEXT("LevelEditor") );
|
|
|
|
// currently blueprint actors don't work because their property can't get copied over.
|
|
if (Cast<UBlueprintGeneratedClass>(EditorActor->GetClass()) != nullptr)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// find all skel components
|
|
TInlineComponentArray<class USkeletalMeshComponent *> SimSkelComponents;
|
|
SimActor->GetComponents<USkeletalMeshComponent>(SimSkelComponents);
|
|
|
|
if(SimSkelComponents.Num() > 0)
|
|
{
|
|
// see if simulating,
|
|
bool bSimulating = false;
|
|
for (auto & Comp : SimSkelComponents)
|
|
{
|
|
bSimulating |= (Comp->SkeletalMesh && Comp->SkeletalMesh->Skeleton && Comp->IsSimulatingPhysics());
|
|
}
|
|
|
|
// if any of them are legitimately simulating
|
|
if (bSimulating)
|
|
{
|
|
// ask users if you'd like to make an animation
|
|
FFormatNamedArguments Args;
|
|
Args.Add(TEXT("ActorName"), FText::FromString(GetNameSafe(EditorActor)));
|
|
FText AskQuestion = FText::Format(LOCTEXT("KeepSimulationChanges_AskSaveAnimation", "Would you like to save animations from simulation for {ActorName} actor"), Args);
|
|
if(EAppReturnType::Yes == FMessageDialog::Open(EAppMsgType::YesNo, AskQuestion))
|
|
{
|
|
for (auto & Comp : SimSkelComponents)
|
|
{
|
|
if (Comp->SkeletalMesh && Comp->SkeletalMesh->Skeleton && Comp->IsSimulatingPhysics())
|
|
{
|
|
// now record to animation
|
|
class UAnimSequence* Sequence = LevelEditorModule.OnCaptureSingleFrameAnimSequence().IsBound() ? LevelEditorModule.OnCaptureSingleFrameAnimSequence().Execute(Comp) : nullptr;
|
|
if(Sequence)
|
|
{
|
|
Comp->SetAnimationMode(EAnimationMode::AnimationSingleNode);
|
|
Comp->AnimationData.AnimToPlay = Sequence;
|
|
Comp->SetAnimation(Sequence);
|
|
Comp->SetSimulatePhysics(false);
|
|
|
|
// add the matching component to EditorCompoennts
|
|
class USkeletalMeshComponent * MatchingComponent = Cast<USkeletalMeshComponent>(EditorUtilities::FindMatchingComponentInstance(Comp, EditorActor));
|
|
if (MatchingComponent)
|
|
{
|
|
OutEditorComponents.Add(MatchingComponent);
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LevelEditorActions, Warning, TEXT("Matching component could not be found %s(%s)"), *GetNameSafe(Comp), *GetNameSafe(EditorActor));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnKeepSimulationChanges()
|
|
{
|
|
// @todo simulate: There are lots of types of changes that can't be "kept", like attachment or newly-spawned actors. This
|
|
// feature currently only supports propagating changes to regularly-editable properties on an instance of a PIE actor
|
|
// that still exists in the editor world.
|
|
|
|
// Make sure we have some actors selected, and PIE is running
|
|
if( GEditor->GetSelectedActorCount() > 0 && GEditor->PlayWorld != NULL )
|
|
{
|
|
int32 UpdatedActorCount = 0;
|
|
int32 TotalCopiedPropertyCount = 0;
|
|
FString FirstUpdatedActorLabel;
|
|
{
|
|
const FScopedTransaction Transaction( NSLOCTEXT( "LevelEditorCommands", "KeepSimulationChanges", "Keep Simulation Changes" ) );
|
|
|
|
TArray<class USkeletalMeshComponent*> ComponentsToReinitialize;
|
|
|
|
for( auto ActorIt( GEditor->GetSelectedActorIterator() ); ActorIt; ++ActorIt )
|
|
{
|
|
auto* SimWorldActor = CastChecked<AActor>( *ActorIt );
|
|
|
|
// Find our counterpart actor
|
|
AActor* EditorWorldActor = EditorUtilities::GetEditorWorldCounterpartActor( SimWorldActor );
|
|
if( EditorWorldActor != NULL )
|
|
{
|
|
SaveAnimationFromSkeletalMeshComponent(EditorWorldActor, SimWorldActor, ComponentsToReinitialize);
|
|
|
|
// We only want to copy CPF_Edit properties back, or properties that are set through editor manipulation
|
|
// NOTE: This needs to match what we're doing in the BuildSelectedActorInfo() function
|
|
const auto CopyOptions = ( EditorUtilities::ECopyOptions::Type )(
|
|
EditorUtilities::ECopyOptions::CallPostEditChangeProperty |
|
|
EditorUtilities::ECopyOptions::CallPostEditMove |
|
|
EditorUtilities::ECopyOptions::OnlyCopyEditOrInterpProperties |
|
|
EditorUtilities::ECopyOptions::FilterBlueprintReadOnly);
|
|
const int32 CopiedPropertyCount = EditorUtilities::CopyActorProperties( SimWorldActor, EditorWorldActor, CopyOptions );
|
|
|
|
if( CopiedPropertyCount > 0 )
|
|
{
|
|
++UpdatedActorCount;
|
|
TotalCopiedPropertyCount += CopiedPropertyCount;
|
|
|
|
if( FirstUpdatedActorLabel.IsEmpty() )
|
|
{
|
|
FirstUpdatedActorLabel = EditorWorldActor->GetActorLabel();
|
|
}
|
|
}
|
|
}
|
|
|
|
// need to reinitialize animation
|
|
for (auto MeshComp : ComponentsToReinitialize)
|
|
{
|
|
if(MeshComp->SkeletalMesh)
|
|
{
|
|
MeshComp->InitAnim(true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Let the user know what happened
|
|
{
|
|
FNotificationInfo NotificationInfo( FText::GetEmpty() );
|
|
NotificationInfo.bFireAndForget = true;
|
|
NotificationInfo.FadeInDuration = 0.25f;
|
|
NotificationInfo.FadeOutDuration = 1.0f;
|
|
NotificationInfo.ExpireDuration = 1.0f;
|
|
NotificationInfo.bUseLargeFont = false;
|
|
NotificationInfo.bUseSuccessFailIcons = true;
|
|
NotificationInfo.bAllowThrottleWhenFrameRateIsLow = false; // Don't throttle as it causes distracting hitches in Simulate mode
|
|
SNotificationItem::ECompletionState CompletionState;
|
|
if( UpdatedActorCount > 0 )
|
|
{
|
|
if( UpdatedActorCount > 1 )
|
|
{
|
|
FFormatNamedArguments Args;
|
|
Args.Add( TEXT("UpdatedActorCount"), UpdatedActorCount );
|
|
Args.Add( TEXT("TotalCopiedPropertyCount"), TotalCopiedPropertyCount );
|
|
NotificationInfo.Text = FText::Format( NSLOCTEXT( "LevelEditorCommands", "KeepSimulationChanges_MultipleActorsUpdatedNotification", "Saved state for {UpdatedActorCount} actors ({TotalCopiedPropertyCount} properties)" ), Args );
|
|
}
|
|
else
|
|
{
|
|
FFormatNamedArguments Args;
|
|
Args.Add( TEXT("FirstUpdatedActorLabel"), FText::FromString( FirstUpdatedActorLabel ) );
|
|
Args.Add( TEXT("TotalCopiedPropertyCount"), TotalCopiedPropertyCount );
|
|
NotificationInfo.Text = FText::Format( NSLOCTEXT( "LevelEditorCommands", "KeepSimulationChanges_ActorUpdatedNotification", "Saved state for {FirstUpdatedActorLabel} ({TotalCopiedPropertyCount} properties)" ), Args );
|
|
}
|
|
CompletionState = SNotificationItem::CS_Success;
|
|
}
|
|
else
|
|
{
|
|
NotificationInfo.Text = NSLOCTEXT( "LevelEditorCommands", "KeepSimulationChanges_NoActorsUpdated", "No properties were copied" );
|
|
CompletionState = SNotificationItem::CS_Fail;
|
|
}
|
|
const auto Notification = FSlateNotificationManager::Get().AddNotification( NotificationInfo );
|
|
Notification->SetCompletionState( CompletionState );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::CanExecuteKeepSimulationChanges()
|
|
{
|
|
return AssetSelectionUtils::GetSelectedActorInfo().NumSimulationChanges > 0;
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::OnMakeSelectedActorLevelCurrent()
|
|
{
|
|
GUnrealEd->MakeSelectedActorsLevelCurrent();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnMoveSelectedToCurrentLevel()
|
|
{
|
|
GEditor->MoveSelectedActorsToLevel( GetWorld()->GetCurrentLevel() );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnFindActorLevelInContentBrowser()
|
|
{
|
|
GEditor->SyncActorLevelsToContentBrowser();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanExecuteFindActorLevelInContentBrowser()
|
|
{
|
|
return GEditor->CanSyncActorLevelsToContentBrowser();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnFindLevelsInLevelBrowser()
|
|
{
|
|
const bool bDeselectOthers = true;
|
|
GEditor->SelectLevelInLevelBrowser( bDeselectOthers );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnSelectLevelInLevelBrowser()
|
|
{
|
|
const bool bDeselectOthers = false;
|
|
GEditor->SelectLevelInLevelBrowser( bDeselectOthers );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnDeselectLevelInLevelBrowser()
|
|
{
|
|
GEditor->DeselectLevelInLevelBrowser();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnFindActorInLevelScript()
|
|
{
|
|
GUnrealEd->FindSelectedActorsInLevelScript();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnShowWorldProperties( TWeakPtr< SLevelEditor > LevelEditor )
|
|
{
|
|
FLevelEditorModule& LevelEditorModule = FModuleManager::GetModuleChecked<FLevelEditorModule>( TEXT("LevelEditor") );
|
|
LevelEditorModule.GetLevelEditorTabManager()->InvokeTab(FName("WorldSettingsTab"));
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OpenContentBrowser()
|
|
{
|
|
FContentBrowserModule& ContentBrowserModule = FModuleManager::LoadModuleChecked<FContentBrowserModule>("ContentBrowser");
|
|
ContentBrowserModule.Get().FocusPrimaryContentBrowser(true);
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OpenMarketplace()
|
|
{
|
|
auto Service = GEditor->GetServiceLocator()->GetServiceRef<IPortalApplicationWindow>();
|
|
if (Service->IsAvailable())
|
|
{
|
|
TAsyncResult<bool> Result = Service->NavigateTo(TEXT("/ue/marketplace"));
|
|
if (FEngineAnalytics::IsAvailable())
|
|
{
|
|
FEngineAnalytics::GetProvider().RecordEvent(TEXT("Editor.Usage.OpenMarketplace"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
IDesktopPlatform* DesktopPlatform = FDesktopPlatformModule::Get();
|
|
|
|
if (DesktopPlatform != nullptr)
|
|
{
|
|
TArray<FAnalyticsEventAttribute> EventAttributes;
|
|
|
|
FOpenLauncherOptions OpenOptions(TEXT("ue/marketplace"));
|
|
if ( DesktopPlatform->OpenLauncher(OpenOptions) )
|
|
{
|
|
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("OpenSucceeded"), TEXT("TRUE")));
|
|
}
|
|
else
|
|
{
|
|
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("OpenSucceeded"), TEXT("FALSE")));
|
|
|
|
if (EAppReturnType::Yes == FMessageDialog::Open(EAppMsgType::YesNo, LOCTEXT("InstallMarketplacePrompt", "The Marketplace requires the Epic Games Launcher, which does not seem to be installed on your computer. Would you like to install it now?")))
|
|
{
|
|
FOpenLauncherOptions InstallOptions(true, TEXT("ue/marketplace"));
|
|
if (!DesktopPlatform->OpenLauncher(InstallOptions))
|
|
{
|
|
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("InstallSucceeded"), TEXT("FALSE")));
|
|
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(TEXT("Sorry, there was a problem installing the Launcher.\nPlease try to install it manually!")));
|
|
}
|
|
else
|
|
{
|
|
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("InstallSucceeded"), TEXT("TRUE")));
|
|
}
|
|
}
|
|
}
|
|
|
|
EventAttributes.Add(FAnalyticsEventAttribute(TEXT("Source"), TEXT("EditorToolbar")));
|
|
|
|
if( FEngineAnalytics::IsAvailable() )
|
|
{
|
|
FEngineAnalytics::GetProvider().RecordEvent(TEXT("Editor.Usage.OpenMarketplace"), EventAttributes);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::ToggleVR()
|
|
{
|
|
IVREditorModule& VREditorModule = IVREditorModule::Get();
|
|
VREditorModule.EnableVREditor( !VREditorModule.IsVREditorEnabled() );
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::ToggleVR_CanExecute()
|
|
{
|
|
IVREditorModule& VREditorModule = IVREditorModule::Get();
|
|
return VREditorModule.IsVREditorAvailable();
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::ToggleVR_IsChecked()
|
|
{
|
|
IVREditorModule& VREditorModule = IVREditorModule::Get();
|
|
return VREditorModule.IsVREditorEnabled();
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::ToggleVR_IsVisible()
|
|
{
|
|
return GetDefault<UEditorExperimentalSettings>()->bEnableVREditing;
|
|
}
|
|
|
|
|
|
bool FLevelEditorActionCallbacks::CanSelectGameModeBlueprint()
|
|
{
|
|
bool bCheckOutNeeded = false;
|
|
|
|
FString ConfigFilePath = FPaths::ConvertRelativePathToFull(FString::Printf(TEXT("%sDefaultEngine.ini"), *FPaths::SourceConfigDir()));
|
|
if(ISourceControlModule::Get().IsEnabled())
|
|
{
|
|
// note: calling QueueStatusUpdate often does not spam status updates as an internal timer prevents this
|
|
//ISourceControlModule::Get().QueueStatusUpdate(ConfigFilePath);
|
|
|
|
ISourceControlProvider& SourceControlProvider = ISourceControlModule::Get().GetProvider();
|
|
FSourceControlStatePtr SourceControlState = SourceControlProvider.GetState(ConfigFilePath, EStateCacheUsage::Use);
|
|
bCheckOutNeeded = SourceControlState.IsValid() && SourceControlState->CanCheckout();
|
|
}
|
|
else
|
|
{
|
|
bCheckOutNeeded = (FPaths::FileExists(ConfigFilePath) && IFileManager::Get().IsReadOnly(*ConfigFilePath));
|
|
}
|
|
return !bCheckOutNeeded;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OpenLevelBlueprint( TWeakPtr< SLevelEditor > LevelEditor )
|
|
{
|
|
if( LevelEditor.Pin()->GetWorld()->GetCurrentLevel() )
|
|
{
|
|
ULevelScriptBlueprint* LevelScriptBlueprint = LevelEditor.Pin()->GetWorld()->PersistentLevel->GetLevelScriptBlueprint();
|
|
if (LevelScriptBlueprint)
|
|
{
|
|
// @todo Re-enable once world centric works
|
|
const bool bOpenWorldCentric = false;
|
|
FAssetEditorManager::Get().OpenEditorForAsset(
|
|
LevelScriptBlueprint,
|
|
bOpenWorldCentric ? EToolkitMode::WorldCentric : EToolkitMode::Standalone,
|
|
LevelEditor.Pin() );
|
|
}
|
|
else
|
|
{
|
|
FMessageDialog::Open( EAppMsgType::Ok, NSLOCTEXT("UnrealEd", "UnableToCreateLevelScript", "Unable to find or create a level blueprint for this level.") );
|
|
}
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::CreateBlankBlueprintClass()
|
|
{
|
|
// Use the BlueprintFactory to allow the user to pick a parent class for the new Blueprint class
|
|
UBlueprintFactory* NewFactory = Cast<UBlueprintFactory>(NewObject<UFactory>(GetTransientPackage(), UBlueprintFactory::StaticClass()));
|
|
FEditorDelegates::OnConfigureNewAssetProperties.Broadcast(NewFactory);
|
|
if ( NewFactory->ConfigureProperties() )
|
|
{
|
|
UClass* SelectedClass = NewFactory->ParentClass;
|
|
|
|
// Now help the user pick a path and name for the new Blueprint
|
|
UBlueprint* Blueprint = FKismetEditorUtilities::CreateBlueprintFromClass(NSLOCTEXT("LevelEditorCommands", "CreateBlankBlueprintClass_Title", "Create Blank Blueprint Class"), SelectedClass);
|
|
|
|
if( Blueprint )
|
|
{
|
|
// @todo Re-enable once world centric works
|
|
const bool bOpenWorldCentric = false;
|
|
FAssetEditorManager::Get().OpenEditorForAsset(
|
|
Blueprint,
|
|
bOpenWorldCentric ? EToolkitMode::WorldCentric : EToolkitMode::Standalone);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanHarvestSelectedActorsIntoBlueprintClass()
|
|
{
|
|
return GEditor->GetSelectedActorCount() > 0;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::HarvestSelectedActorsIntoBlueprintClass()
|
|
{
|
|
const bool bHarvest = true;
|
|
FCreateBlueprintFromActorDialog::OpenDialog(bHarvest);
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanSubclassSelectedActorIntoBlueprintClass()
|
|
{
|
|
bool bCanSubclass = GEditor->GetSelectedActorCount() == 1;
|
|
if (bCanSubclass)
|
|
{
|
|
AActor* Actor = Cast<AActor>(*GEditor->GetSelectedActorIterator());
|
|
bCanSubclass = FKismetEditorUtilities::CanCreateBlueprintOfClass(Actor->GetClass());
|
|
}
|
|
return bCanSubclass;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SubclassSelectedActorIntoBlueprintClass()
|
|
{
|
|
const bool bHarvest = false;
|
|
FCreateBlueprintFromActorDialog::OpenDialog(bHarvest);
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::CheckOutProjectSettingsConfig( )
|
|
{
|
|
FString ConfigFilePath = FPaths::ConvertRelativePathToFull(FString::Printf(TEXT("%sDefaultEngine.ini"), *FPaths::SourceConfigDir()));
|
|
if(ISourceControlModule::Get().IsEnabled())
|
|
{
|
|
SourceControlHelpers::CheckOutFile(ConfigFilePath);
|
|
}
|
|
else
|
|
{
|
|
FPlatformFileManager::Get().GetPlatformFile().SetReadOnly(*ConfigFilePath, false);
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnShowOnlySelectedActors()
|
|
{
|
|
const FScopedTransaction Transaction( NSLOCTEXT( "LevelEditorCommands", "ShowOnlySelectedActors", "Show Only Selected Actors" ) );
|
|
// First hide unselected as this will also hide group actor members
|
|
GUnrealEd->edactHideUnselected( GetWorld() );
|
|
// Then unhide selected to ensure that everything that's selected will be unhidden
|
|
GUnrealEd->edactUnhideSelected(GetWorld());
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleTransformWidgetVisibility()
|
|
{
|
|
GLevelEditorModeTools().SetShowWidget( !GLevelEditorModeTools().GetShowWidget() );
|
|
GUnrealEd->RedrawAllViewports();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnGetTransformWidgetVisibility()
|
|
{
|
|
return GLevelEditorModeTools().GetShowWidget();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnAllowTranslucentSelection()
|
|
{
|
|
auto* Settings = GetMutableDefault<UEditorPerProjectUserSettings>();
|
|
|
|
// Toggle 'allow select translucent'
|
|
Settings->bAllowSelectTranslucent = !Settings->bAllowSelectTranslucent;
|
|
Settings->PostEditChange();
|
|
|
|
// Need to refresh hit proxies as we changed what should be rendered into them
|
|
GUnrealEd->RedrawAllViewports();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsAllowTranslucentSelectionEnabled()
|
|
{
|
|
return GetDefault<UEditorPerProjectUserSettings>()->bAllowSelectTranslucent == true;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnAllowGroupSelection()
|
|
{
|
|
AGroupActor::ToggleGroupMode();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsAllowGroupSelectionEnabled()
|
|
{
|
|
return GUnrealEd->bGroupingActive;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleStrictBoxSelect()
|
|
{
|
|
ULevelEditorViewportSettings* ViewportSettings = GetMutableDefault<ULevelEditorViewportSettings>();
|
|
ViewportSettings->bStrictBoxSelection = !ViewportSettings->bStrictBoxSelection;
|
|
ViewportSettings->PostEditChange();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsStrictBoxSelectEnabled()
|
|
{
|
|
return GetDefault<ULevelEditorViewportSettings>()->bStrictBoxSelection;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleTransparentBoxSelect()
|
|
{
|
|
ULevelEditorViewportSettings* ViewportSettings = GetMutableDefault<ULevelEditorViewportSettings>();
|
|
ViewportSettings->bTransparentBoxSelection = !ViewportSettings->bTransparentBoxSelection;
|
|
ViewportSettings->PostEditChange();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsTransparentBoxSelectEnabled()
|
|
{
|
|
return GetDefault<ULevelEditorViewportSettings>()->bTransparentBoxSelection;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnDrawBrushMarkerPolys()
|
|
{
|
|
GEditor->Exec( GetWorld(), *FString::Printf( TEXT("MODE SHOWBRUSHMARKERPOLYS=%d"), !GEditor->bShowBrushMarkerPolys ? 1 : 0 ) );
|
|
GEditor->SaveConfig();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsDrawBrushMarkerPolysEnabled()
|
|
{
|
|
return GEditor->bShowBrushMarkerPolys;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleOnlyLoadVisibleInPIE()
|
|
{
|
|
ULevelEditorPlaySettings* PlaySettings = GetMutableDefault<ULevelEditorPlaySettings>();
|
|
PlaySettings->bOnlyLoadVisibleLevelsInPIE = !PlaySettings->bOnlyLoadVisibleLevelsInPIE;
|
|
PlaySettings->PostEditChange();
|
|
PlaySettings->SaveConfig();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsOnlyLoadVisibleInPIEEnabled()
|
|
{
|
|
return GetDefault<ULevelEditorPlaySettings>()->bOnlyLoadVisibleLevelsInPIE;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleSocketSnapping()
|
|
{
|
|
GEditor->bEnableSocketSnapping = !GEditor->bEnableSocketSnapping;
|
|
GEditor->RedrawLevelEditingViewports();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsSocketSnappingEnabled()
|
|
{
|
|
return GEditor->bEnableSocketSnapping;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleParticleSystemLOD()
|
|
{
|
|
GEngine->bEnableEditorPSysRealtimeLOD = !GEngine->bEnableEditorPSysRealtimeLOD;
|
|
GEditor->RedrawLevelEditingViewports();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsParticleSystemLODEnabled()
|
|
{
|
|
return GEditor->bEnableEditorPSysRealtimeLOD;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleFreezeParticleSimulation()
|
|
{
|
|
IConsoleManager& ConsoleManager = IConsoleManager::Get();
|
|
IConsoleVariable* CVar = ConsoleManager.FindConsoleVariable(TEXT("FX.FreezeParticleSimulation"));
|
|
if (CVar)
|
|
{
|
|
CVar->Set(CVar->GetInt() == 0 ? 1 : 0, ECVF_SetByConsole);
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsParticleSimulationFrozen()
|
|
{
|
|
IConsoleManager& ConsoleManager = IConsoleManager::Get();
|
|
static const auto* CVar = ConsoleManager.FindTConsoleVariableDataInt(TEXT("FX.FreezeParticleSimulation"));
|
|
if (CVar)
|
|
{
|
|
return CVar->GetValueOnGameThread() != 0;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleParticleSystemHelpers()
|
|
{
|
|
GEditor->bDrawParticleHelpers = !GEditor->bDrawParticleHelpers;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsParticleSystemHelpersEnabled()
|
|
{
|
|
return GEditor->bDrawParticleHelpers;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleLODViewLocking()
|
|
{
|
|
GEditor->bEnableLODLocking = !GEditor->bEnableLODLocking;
|
|
GEditor->RedrawLevelEditingViewports();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsLODViewLockingEnabled()
|
|
{
|
|
return GEditor->bEnableLODLocking;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleLevelStreamingVolumePrevis()
|
|
{
|
|
ULevelEditorViewportSettings* ViewportSettings = GetMutableDefault<ULevelEditorViewportSettings>();
|
|
|
|
ViewportSettings->bLevelStreamingVolumePrevis = !ViewportSettings->bLevelStreamingVolumePrevis;
|
|
ViewportSettings->PostEditChange();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsLevelStreamingVolumePrevisEnabled()
|
|
{
|
|
return GetDefault<ULevelEditorViewportSettings>()->bLevelStreamingVolumePrevis;
|
|
}
|
|
|
|
FText FLevelEditorActionCallbacks::GetAudioVolumeToolTip()
|
|
{
|
|
if ( !GEditor->IsRealTimeAudioMuted() )
|
|
{
|
|
const float Volume = GEditor->GetRealTimeAudioVolume() * 100.0f;
|
|
return FText::AsNumber( FMath::RoundToInt(Volume) );
|
|
}
|
|
return NSLOCTEXT("UnrealEd", "Muted", "Muted" );
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetAudioVolume()
|
|
{
|
|
return GEditor->GetRealTimeAudioVolume();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnAudioVolumeChanged(float Volume)
|
|
{
|
|
GEditor->SetRealTimeAudioVolume(Volume);
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::GetAudioMuted()
|
|
{
|
|
return GEditor->IsRealTimeAudioMuted();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnAudioMutedChanged(bool bMuted)
|
|
{
|
|
GEditor->MuteRealTimeAudio(bMuted);
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SnapObjectToView_Clicked()
|
|
{
|
|
const FScopedTransaction Transaction(NSLOCTEXT("UnrealEd", "SnapObjectToView", "Snap Object to View"));
|
|
for (FSelectionIterator It(GEditor->GetSelectedActorIterator()); It; ++It)
|
|
{
|
|
AActor* Actor = Cast<AActor>(*It);
|
|
Actor->Modify();
|
|
FVector Location = GCurrentLevelEditingViewportClient->GetViewLocation();
|
|
FRotator Rotation = GCurrentLevelEditingViewportClient->GetViewRotation();
|
|
|
|
Actor->SetActorLocation(Location);
|
|
Actor->SetActorRotation(Rotation);
|
|
}
|
|
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnEnableActorSnap()
|
|
{
|
|
FSnappingUtils::EnableActorSnap( !FSnappingUtils::IsSnapToActorEnabled() );
|
|
|
|
// If the setting is enabled and there's no distance, revert to default
|
|
if ( FSnappingUtils::IsSnapToActorEnabled() && FSnappingUtils::GetActorSnapDistance() == 0.0f )
|
|
{
|
|
FSnappingUtils::SetActorSnapDistance( 1.0f );
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsActorSnapEnabled()
|
|
{
|
|
return FSnappingUtils::IsSnapToActorEnabled();
|
|
}
|
|
|
|
|
|
void FLevelEditorActionCallbacks::OnEnableVertexSnap()
|
|
{
|
|
ULevelEditorViewportSettings* ViewportSettings = GetMutableDefault<ULevelEditorViewportSettings>();
|
|
ViewportSettings->bSnapVertices = !ViewportSettings->bSnapVertices;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::OnIsVertexSnapEnabled()
|
|
{
|
|
return GetDefault<ULevelEditorViewportSettings>()->bSnapVertices;
|
|
}
|
|
|
|
FText FLevelEditorActionCallbacks::GetActorSnapTooltip()
|
|
{
|
|
// If the setting is enabled, return the distance, otherwise say disabled
|
|
if ( FSnappingUtils::IsSnapToActorEnabled() )
|
|
{
|
|
static const FNumberFormattingOptions FormatOptions = FNumberFormattingOptions()
|
|
.SetMinimumFractionalDigits(2)
|
|
.SetMaximumFractionalDigits(2);
|
|
return FText::AsNumber( FSnappingUtils::GetActorSnapDistance(), &FormatOptions );
|
|
}
|
|
return NSLOCTEXT("UnrealEd", "Disabled", "Disabled" );
|
|
}
|
|
|
|
float FLevelEditorActionCallbacks::GetActorSnapSetting()
|
|
{
|
|
// If the setting is enabled, return the distance, otherwise say 0
|
|
if (FSnappingUtils::IsSnapToActorEnabled() )
|
|
{
|
|
return FSnappingUtils::GetActorSnapDistance(true) ;
|
|
}
|
|
return 0.0f;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetActorSnapSetting(float Distance)
|
|
{
|
|
FSnappingUtils::SetActorSnapDistance( Distance );
|
|
|
|
// If the distance is 0, disable the setting until it's > 0
|
|
FSnappingUtils::EnableActorSnap( ( Distance > 0.0f ? true : false ) );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnToggleHideViewportUI()
|
|
{
|
|
GLevelEditorModeTools().SetHideViewportUI( !GLevelEditorModeTools().IsViewportUIHidden() );
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsViewportUIHidden()
|
|
{
|
|
return GLevelEditorModeTools().IsViewportUIHidden();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsEditorModeActive( FEditorModeID EditorMode )
|
|
{
|
|
return GLevelEditorModeTools().IsModeActive( EditorMode );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnAddVolume( UClass* VolumeClass )
|
|
{
|
|
GUnrealEd->Exec( GetWorld(), *FString::Printf( TEXT("BRUSH ADDVOLUME CLASS=%s"), *VolumeClass->GetName() ) );
|
|
|
|
// A new volume actor was added, update the volumes visibility.
|
|
// This volume should be hidden if the user doesn't have this type of volume visible.
|
|
GUnrealEd->UpdateVolumeActorVisibility( VolumeClass );
|
|
|
|
GEditor->RedrawAllViewports();
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::OnAddMatinee()
|
|
{
|
|
// Warn the user prior to creating our actor
|
|
if ( GEditor->ShouldOpenMatinee( NULL ) )
|
|
{
|
|
// Spawn a matinee actor at the origin, and either move infront of the camera or focus camera on it (depending on the viewport) and open for edit
|
|
UActorFactory* ActorFactory = GEditor->FindActorFactoryForActorClass( AMatineeActor::StaticClass() );
|
|
check( ActorFactory );
|
|
AMatineeActor* MatineeActor = CastChecked<AMatineeActor>( FLevelEditorActionCallbacks::AddActor( ActorFactory, FAssetData(), &FTransform::Identity ) );
|
|
if( GCurrentLevelEditingViewportClient->IsPerspective() )
|
|
{
|
|
GEditor->MoveActorInFrontOfCamera( *MatineeActor, GCurrentLevelEditingViewportClient->GetViewLocation(), GCurrentLevelEditingViewportClient->GetViewRotation().Vector() );
|
|
}
|
|
else
|
|
{
|
|
GEditor->MoveViewportCamerasToActor( *MatineeActor, false );
|
|
}
|
|
GEditor->OpenMatinee( MatineeActor, false );
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SelectActorsInLayers()
|
|
{
|
|
// Iterate over selected actors and make a list of all layers the selected actors belong to.
|
|
TArray< FName > SelectedLayers;
|
|
for ( FSelectionIterator It( GEditor->GetSelectedActorIterator() ) ; It ; ++It )
|
|
{
|
|
AActor* Actor = Cast<AActor>( *It );
|
|
|
|
// Add them to the list of selected layers.
|
|
for( int32 LayerIndex = 0 ; LayerIndex < Actor->Layers.Num() ; ++LayerIndex )
|
|
{
|
|
SelectedLayers.AddUnique( Actor->Layers[ LayerIndex ] );
|
|
}
|
|
}
|
|
|
|
bool bSelect = true;
|
|
bool bNotify = true;
|
|
GEditor->Layers->SelectActorsInLayers( SelectedLayers, bSelect, bNotify );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetWidgetMode( FWidget::EWidgetMode WidgetMode )
|
|
{
|
|
if( !GLevelEditorModeTools().IsTracking() )
|
|
{
|
|
GLevelEditorModeTools().SetWidgetMode( WidgetMode );
|
|
GEditor->RedrawAllViewports();
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsWidgetModeActive( FWidget::EWidgetMode WidgetMode )
|
|
{
|
|
return GLevelEditorModeTools().GetWidgetMode() == WidgetMode;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanSetWidgetMode( FWidget::EWidgetMode WidgetMode )
|
|
{
|
|
return GLevelEditorModeTools().GetShowWidget() == true;
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsTranslateRotateModeVisible()
|
|
{
|
|
return GetDefault<ULevelEditorViewportSettings>()->bAllowTranslateRotateZWidget;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SetCoordinateSystem( ECoordSystem CoordinateSystem )
|
|
{
|
|
GLevelEditorModeTools().SetCoordSystem( CoordinateSystem );
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::IsCoordinateSystemActive( ECoordSystem CoordinateSystem )
|
|
{
|
|
return GLevelEditorModeTools().GetCoordSystem() == CoordinateSystem;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::MoveActorToGrid_Clicked( bool InAlign, bool bInPerActor )
|
|
{
|
|
const FScopedTransaction Transaction( NSLOCTEXT("UnrealEd", "MoveActorToGrid", "Snap Origin to Grid") );
|
|
MoveActorTo_Clicked( InAlign, NULL, bInPerActor );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::MoveActorToActor_Clicked( bool InAlign )
|
|
{
|
|
AActor* Actor = GEditor->GetSelectedActors()->GetBottom<AActor>();
|
|
if( Actor )
|
|
{
|
|
const FScopedTransaction Transaction( NSLOCTEXT("UnrealEd", "MoveActorToActor", "Snap Origin to Actor") );
|
|
MoveActorTo_Clicked( InAlign, Actor );
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::MoveActorTo_Clicked( const bool InAlign, const AActor* InDestination/* = NULL*/, bool bInPerActor/* = false*/ )
|
|
{
|
|
// Fires ULevel::LevelDirtiedEvent when falling out of scope.
|
|
FScopedLevelDirtied LevelDirtyCallback;
|
|
|
|
// Update the pivot location.
|
|
FVector Delta = FVector::ZeroVector;
|
|
FVector NewLocation = FVector::ZeroVector;
|
|
FRotator NewRotation = FRotator::ZeroRotator;
|
|
|
|
if(!bInPerActor)
|
|
{
|
|
if ( InDestination )
|
|
{
|
|
NewLocation = InDestination->GetActorLocation();
|
|
NewRotation = InDestination->GetActorRotation();
|
|
GEditor->SetPivot( NewLocation, false, true );
|
|
}
|
|
else
|
|
{
|
|
const FVector OldPivot = GEditor->GetPivotLocation();
|
|
const FVector NewPivot = OldPivot.GridSnap(GEditor->GetGridSize());
|
|
Delta = NewPivot - OldPivot;
|
|
GEditor->SetPivot( NewPivot, false, true );
|
|
}
|
|
}
|
|
|
|
for ( FSelectionIterator It( GEditor->GetSelectedActorIterator() ) ; It ; ++It )
|
|
{
|
|
AActor* Actor = Cast<AActor>( *It );
|
|
checkSlow( Actor->IsA(AActor::StaticClass()) );
|
|
if ( Actor == InDestination ) // Early out
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Actor->Modify();
|
|
|
|
if(!InDestination)
|
|
{
|
|
if ( bInPerActor )
|
|
{
|
|
const FVector OldPivot = Actor->GetActorLocation();
|
|
const FVector NewPivot = OldPivot.GridSnap(GEditor->GetGridSize());
|
|
Delta = NewPivot - OldPivot;
|
|
GEditor->SetPivot( NewPivot, false, true );
|
|
}
|
|
|
|
NewLocation = Actor->GetActorLocation() + Delta;
|
|
}
|
|
|
|
Actor->TeleportTo( NewLocation, ( !InAlign ? Actor->GetActorRotation() : NewRotation ), false, true );
|
|
Actor->InvalidateLightingCache();
|
|
Actor->UpdateComponentTransforms();
|
|
|
|
Actor->MarkPackageDirty();
|
|
LevelDirtyCallback.Request();
|
|
}
|
|
|
|
GEditor->RedrawLevelEditingViewports();
|
|
GEditor->RebuildAlteredBSP(); // Update the Bsp of any levels containing a modified brush
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SnapTo2DLayer_Clicked()
|
|
{
|
|
// Fires ULevel::LevelDirtiedEvent when falling out of scope.
|
|
FScopedLevelDirtied LevelDirtyCallback;
|
|
|
|
const ULevelEditorViewportSettings* ViewportSettings = GetDefault<ULevelEditorViewportSettings>();
|
|
const ULevelEditor2DSettings* Settings2D = GetDefault<ULevelEditor2DSettings>();
|
|
if (Settings2D->SnapLayers.IsValidIndex(ViewportSettings->ActiveSnapLayerIndex))
|
|
{
|
|
const FScopedTransaction Transaction(NSLOCTEXT("UnrealEd", "SnapSelection2D", "Snap Selection to 2D Layer"));
|
|
|
|
float SnapDepth = Settings2D->SnapLayers[ViewportSettings->ActiveSnapLayerIndex].Depth;
|
|
USelection* SelectedActors = GEditor->GetSelectedActors();
|
|
for (FSelectionIterator Iter(*SelectedActors); Iter; ++Iter)
|
|
{
|
|
AActor* Actor = CastChecked<AActor>(*Iter);
|
|
|
|
// Only snap actors that are not attached to something else
|
|
if (Actor->GetAttachParentActor() == nullptr)
|
|
{
|
|
FTransform Transform = Actor->GetTransform();
|
|
FVector CurrentLocation = Transform.GetLocation();
|
|
|
|
switch (Settings2D->SnapAxis)
|
|
{
|
|
case ELevelEditor2DAxis::X: CurrentLocation.X = SnapDepth; break;
|
|
case ELevelEditor2DAxis::Y: CurrentLocation.Y = SnapDepth; break;
|
|
case ELevelEditor2DAxis::Z: CurrentLocation.Z = SnapDepth; break;
|
|
}
|
|
|
|
Transform.SetLocation(CurrentLocation);
|
|
Actor->Modify();
|
|
Actor->SetActorTransform(Transform);
|
|
|
|
Actor->InvalidateLightingCache();
|
|
Actor->UpdateComponentTransforms();
|
|
|
|
Actor->MarkPackageDirty();
|
|
LevelDirtyCallback.Request();
|
|
}
|
|
}
|
|
|
|
GEditor->RedrawLevelEditingViewports(true);
|
|
GEditor->RebuildAlteredBSP();
|
|
}
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanSnapTo2DLayer()
|
|
{
|
|
const ULevelEditor2DSettings* Settings = GetDefault<ULevelEditor2DSettings>();
|
|
return Settings->SnapLayers.IsValidIndex(GetDefault<ULevelEditorViewportSettings>()->ActiveSnapLayerIndex) && (GEditor->GetSelectedActorCount() > 0);
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::MoveSelectionToDifferent2DLayer_Clicked(bool bGoingUp, bool bForceToTopOrBottom)
|
|
{
|
|
// Change the active layer first
|
|
const ULevelEditor2DSettings* Settings2D = GetDefault<ULevelEditor2DSettings>();
|
|
ULevelEditorViewportSettings* SettingsVP = GetMutableDefault<ULevelEditorViewportSettings>();
|
|
|
|
const int32 NumLayers = Settings2D->SnapLayers.Num();
|
|
|
|
if (NumLayers > 0)
|
|
{
|
|
if (bGoingUp && (SettingsVP->ActiveSnapLayerIndex > 0))
|
|
{
|
|
SettingsVP->ActiveSnapLayerIndex = bForceToTopOrBottom ? 0 : (SettingsVP->ActiveSnapLayerIndex - 1);
|
|
SettingsVP->PostEditChange();
|
|
}
|
|
else if (!bGoingUp && ((SettingsVP->ActiveSnapLayerIndex + 1) < NumLayers))
|
|
{
|
|
SettingsVP->ActiveSnapLayerIndex = bForceToTopOrBottom ? (NumLayers - 1) : (SettingsVP->ActiveSnapLayerIndex + 1);
|
|
SettingsVP->PostEditChange();
|
|
}
|
|
}
|
|
|
|
// Snap the selection to the new active layer
|
|
SnapTo2DLayer_Clicked();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::CanMoveSelectionToDifferent2DLayer(bool bGoingUp)
|
|
{
|
|
const ULevelEditor2DSettings* Settings2D = GetDefault<ULevelEditor2DSettings>();
|
|
const ULevelEditorViewportSettings* SettingsVP = GetMutableDefault<ULevelEditorViewportSettings>();
|
|
|
|
const int32 SelectedIndex = SettingsVP->ActiveSnapLayerIndex;
|
|
const int32 NumLayers = Settings2D->SnapLayers.Num();
|
|
|
|
const bool bHasLayerInDirection = bGoingUp ? (SelectedIndex > 0) : (SelectedIndex + 1 < NumLayers);
|
|
const bool bHasActorSelected = GEditor->GetSelectedActorCount() > 0;
|
|
|
|
// Allow it even if there is no layer in the corresponding direction, to let it double as a snap operation shortcut even when at the end stops
|
|
return bHasLayerInDirection || bHasActorSelected;
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::Select2DLayerDeltaAway_Clicked(int32 Delta)
|
|
{
|
|
const ULevelEditor2DSettings* Settings2D = GetDefault<ULevelEditor2DSettings>();
|
|
ULevelEditorViewportSettings* SettingsVP = GetMutableDefault<ULevelEditorViewportSettings>();
|
|
|
|
const int32 SelectedIndex = SettingsVP->ActiveSnapLayerIndex;
|
|
const int32 NumLayers = Settings2D->SnapLayers.Num();
|
|
|
|
if (NumLayers > 0)
|
|
{
|
|
const int32 NewIndex = ((NumLayers + SelectedIndex + Delta) % NumLayers);
|
|
|
|
SettingsVP->ActiveSnapLayerIndex = NewIndex;
|
|
SettingsVP->PostEditChange();
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SnapToFloor_Clicked( bool InAlign, bool InUseLineTrace, bool InUseBounds, bool InUsePivot )
|
|
{
|
|
const FScopedTransaction Transaction( NSLOCTEXT("UnrealEd", "SnapActorsToFloor", "Snap Actors To Floor") );
|
|
SnapTo_Clicked( InAlign, InUseLineTrace, InUseBounds, InUsePivot );
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SnapActorToActor_Clicked( bool InAlign, bool InUseLineTrace, bool InUseBounds, bool InUsePivot )
|
|
{
|
|
AActor* Actor = GEditor->GetSelectedActors()->GetBottom<AActor>();
|
|
if( Actor )
|
|
{
|
|
const FScopedTransaction Transaction( NSLOCTEXT("UnrealEd", "SnapActorsToActor", "Snap Actors To Actor") );
|
|
SnapTo_Clicked( InAlign, InUseLineTrace, InUseBounds, InUsePivot, Actor );
|
|
}
|
|
}
|
|
|
|
void FLevelEditorActionCallbacks::SnapTo_Clicked( const bool InAlign, const bool InUseLineTrace, const bool InUseBounds, const bool InUsePivot, AActor* InDestination )
|
|
{
|
|
// Fires ULevel::LevelDirtiedEvent when falling out of scope.
|
|
FScopedLevelDirtied LevelDirtyCallback;
|
|
|
|
bool bSnappedComponents = false;
|
|
if( GEditor->GetSelectedComponentCount() > 0 )
|
|
{
|
|
for(FSelectedEditableComponentIterator It(GEditor->GetSelectedEditableComponentIterator()); It; ++It)
|
|
{
|
|
USceneComponent* SceneComponent = Cast<USceneComponent>(*It);
|
|
if(SceneComponent)
|
|
{
|
|
SceneComponent->Modify();
|
|
AActor* ActorOwner = SceneComponent->GetOwner();
|
|
bSnappedComponents = true;
|
|
if(ActorOwner)
|
|
{
|
|
ActorOwner->Modify();
|
|
GEditor->SnapObjectTo(FActorOrComponent(SceneComponent), InAlign, InUseLineTrace, InUseBounds, InUsePivot, FActorOrComponent(InDestination));
|
|
ActorOwner->InvalidateLightingCache();
|
|
ActorOwner->UpdateComponentTransforms();
|
|
|
|
LevelDirtyCallback.Request();
|
|
}
|
|
}
|
|
}
|
|
|
|
USceneComponent* LastComp = GEditor->GetSelectedComponents()->GetBottom<USceneComponent>();
|
|
|
|
GEditor->SetPivot(LastComp->GetComponentLocation(), false, true);
|
|
}
|
|
|
|
if( !bSnappedComponents )
|
|
{
|
|
for(FSelectionIterator It(GEditor->GetSelectedActorIterator()); It; ++It)
|
|
{
|
|
AActor* Actor = Cast<AActor>(*It);
|
|
if(Actor)
|
|
{
|
|
Actor->Modify();
|
|
GEditor->SnapObjectTo(FActorOrComponent(Actor), InAlign, InUseLineTrace, InUseBounds, InUsePivot, FActorOrComponent(InDestination));
|
|
Actor->InvalidateLightingCache();
|
|
Actor->UpdateComponentTransforms();
|
|
|
|
LevelDirtyCallback.Request();
|
|
}
|
|
}
|
|
|
|
|
|
AActor* Actor = GEditor->GetSelectedActors()->GetBottom<AActor>();
|
|
if(Actor)
|
|
{
|
|
GEditor->SetPivot(Actor->GetActorLocation(), false, true);
|
|
|
|
if(GEditor->bGroupingActive)
|
|
{
|
|
// set group pivot for the root-most group
|
|
AGroupActor* ActorGroupRoot = AGroupActor::GetRootForActor(Actor, true, true);
|
|
if(ActorGroupRoot)
|
|
{
|
|
ActorGroupRoot->CenterGroupLocation();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
GEditor->RedrawLevelEditingViewports();
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::ActorSelected_CanExecute()
|
|
{
|
|
// Had to have something selected
|
|
return ( ( GEditor->GetSelectedActorCount() > 0 ) ? true : false );
|
|
}
|
|
|
|
bool FLevelEditorActionCallbacks::ActorsSelected_CanExecute()
|
|
{
|
|
// Has to have more than one selected
|
|
return ( ( GEditor->GetSelectedActorCount() > 1 ) ? true : false );
|
|
}
|
|
|
|
class UWorld* FLevelEditorActionCallbacks::GetWorld()
|
|
{
|
|
return GEditor->GetEditorWorldContext().World();
|
|
}
|
|
|
|
/** UI_COMMAND takes long for the compile to optimize */
|
|
PRAGMA_DISABLE_OPTIMIZATION
|
|
void FLevelEditorCommands::RegisterCommands()
|
|
{
|
|
UI_COMMAND( BrowseDocumentation, "Documentation...", "Opens the main documentation page, and allows you to search across all UE4 support sites.", EUserInterfaceActionType::Button, FInputChord( EKeys::F1 ) );
|
|
UI_COMMAND( BrowseAPIReference, "API Reference...", "Opens the API reference documentation", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( BrowseCVars, "Console Variables", "Creates an HTML file to browse the console variables and commands (console command 'help')", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( BrowseViewportControls, "Viewport Controls...", "Opens the viewport controls cheat sheet", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( NewLevel, "New Level...", "Create a new level, or choose a level template to start from.", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Control, EKeys::N ) );
|
|
UI_COMMAND( OpenLevel, "Open Level...", "Loads an existing level", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Control, EKeys::O ) );
|
|
UI_COMMAND( Save, "Save", "Saves the current level to disk", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SaveAs, "Save As...", "Save the current level as...", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Shift|EModifierKey::Control, EKeys::S ) );
|
|
UI_COMMAND( SaveAllLevels, "Save All Levels", "Saves all unsaved levels to disk", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ToggleFavorite, "Toggle Favorite", "Sets whether the currently loaded level will appear in the list of favorite levels", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
for( int32 CurRecentIndex = 0; CurRecentIndex < FLevelEditorCommands::MaxRecentFiles; ++CurRecentIndex )
|
|
{
|
|
// NOTE: The actual label and tool-tip will be overridden at runtime when the command is bound to a menu item, however
|
|
// we still need to set one here so that the key bindings UI can function properly
|
|
TSharedRef< FUICommandInfo > OpenRecentFile =
|
|
FUICommandInfoDecl(
|
|
this->AsShared(),
|
|
FName( *FString::Printf( TEXT( "OpenRecentFile%i" ), CurRecentIndex ) ),
|
|
FText::Format( NSLOCTEXT( "LevelEditorCommands", "OpenRecentFile", "Open Recent File {0}" ), FText::AsNumber( CurRecentIndex ) ),
|
|
NSLOCTEXT( "LevelEditorCommands", "OpenRecentFileToolTip", "Opens a recently opened file" ) )
|
|
.UserInterfaceType( EUserInterfaceActionType::Button )
|
|
.DefaultChord( FInputChord() );
|
|
OpenRecentFileCommands.Add( OpenRecentFile );
|
|
}
|
|
|
|
UI_COMMAND( ImportScene, "Import Into Level...", "Imports a scene from a FBX or T3D format into the current level", EUserInterfaceActionType::Button, FInputChord());
|
|
UI_COMMAND( ExportAll, "Export All...", "Exports the entire level to a file on disk (multiple formats are supported.)", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ExportSelected, "Export Selected...", "Exports currently-selected objects to a file on disk (multiple formats are supported.)", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( Build, "Build All Levels", "Builds all levels (precomputes lighting data and visibility data, generates navigation networks and updates brush models.)", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( BuildAndSubmitToSourceControl, "Build and Submit...", "Displays a window that allows you to build all levels and submit them to source control", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( BuildLightingOnly, "Build Lighting", "Only precomputes lighting (all levels.)", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Control|EModifierKey::Shift, EKeys::Semicolon) );
|
|
UI_COMMAND( BuildReflectionCapturesOnly, "Update Reflection Captures", "Only updates Reflection Captures (all levels.)", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( BuildLightingOnly_VisibilityOnly, "Precompute Static Visibility", "Only precomputes static visibility data (all levels.)", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( LightingBuildOptions_UseErrorColoring, "Use Error Coloring", "When enabled, errors during lighting precomputation will be baked as colors into light map data", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( LightingBuildOptions_ShowLightingStats, "Show Lighting Stats", "When enabled, a window containing metrics about lighting performance and memory will be displayed after a successful build.", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( BuildGeometryOnly, "Build Geometry", "Only builds geometry (all levels.)", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( BuildGeometryOnly_OnlyCurrentLevel, "Build Geometry (Current Level)", "Builds geometry, only for the current level", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( BuildPathsOnly, "Build Paths", "Only builds paths (all levels.)", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( BuildLODsOnly, "Build LODs", "Only builds LODs (all levels.)", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( BuildTextureStreamingOnly, "Build Texture Streaming", "Build texture streaming data", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( LightingQuality_Production, "Production", "Sets precomputed lighting quality to highest possible quality (slowest computation time.)", EUserInterfaceActionType::RadioButton, FInputChord() );
|
|
UI_COMMAND( LightingQuality_High, "High", "Sets precomputed lighting quality to high quality", EUserInterfaceActionType::RadioButton, FInputChord() );
|
|
UI_COMMAND( LightingQuality_Medium, "Medium", "Sets precomputed lighting quality to medium quality", EUserInterfaceActionType::RadioButton, FInputChord() );
|
|
UI_COMMAND( LightingQuality_Preview, "Preview", "Sets precomputed lighting quality to preview quality (fastest computation time.)", EUserInterfaceActionType::RadioButton, FInputChord() );
|
|
UI_COMMAND( LightingDensity_RenderGrayscale, "Render Grayscale", "Renders the lightmap density.", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( LightingResolution_CurrentLevel, "Current Level", "Adjust only primitives in the current level.", EUserInterfaceActionType::RadioButton, FInputChord() );
|
|
UI_COMMAND( LightingResolution_SelectedLevels, "Selected Levels", "Adjust only primitives in the selected levels.", EUserInterfaceActionType::RadioButton, FInputChord() );
|
|
UI_COMMAND( LightingResolution_AllLoadedLevels, "All Loaded Levels", "Adjust primitives in all loaded levels.", EUserInterfaceActionType::RadioButton, FInputChord() );
|
|
UI_COMMAND( LightingResolution_SelectedObjectsOnly, "Selected Objects Only", "Adjust only selected objects in the levels.", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( LightingStaticMeshInfo, "Lighting StaticMesh Info...", "Shows the lighting information for the StaticMeshes.", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SceneStats, "Open Scene Stats", "Opens the Scene Stats viewer", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( TextureStats, "Open Texture Stats", "Opens the Texture Stats viewer", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MapCheck, "Open Map Check", "Checks map for errors", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( RecompileGameCode, "Recompile Game Code", "Recompiles and reloads C++ code for game systems on the fly", EUserInterfaceActionType::Button, FInputChord( EKeys::P, EModifierKey::Alt | EModifierKey::Control | EModifierKey::Shift ) );
|
|
|
|
UI_COMMAND( EditAsset, "Edit Asset", "Edits the asset associated with the selected actor", EUserInterfaceActionType::Button, FInputChord( EKeys::E, EModifierKey::Control ) );
|
|
UI_COMMAND( EditAssetNoConfirmMultiple, "Edit Asset", "Edits the asset associated with the selected actor", EUserInterfaceActionType::Button, FInputChord( EKeys::E, EModifierKey::Control | EModifierKey::Shift ) );
|
|
|
|
UI_COMMAND( GoHere, "Go Here", "Moves the camera to the current mouse position", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( SnapCameraToObject, "Snap View to Object", "Snaps the view to the selected object", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SnapObjectToCamera, "Snap Object to View", "Snaps the selected object to the view", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( GoToCodeForActor, "Go to C++ Code for Actor", "Opens a code editing IDE and navigates to the source file associated with the seleced actor", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( GoToDocsForActor, "Go to Documentation for Actor", "Opens documentation for the Actor in the default web browser", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( PasteHere, "Paste Here", "Pastes the actor at the click location", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( SnapOriginToGrid, "Snap Origin to Grid", "Snaps the actor to the nearest grid location at its origin", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Control, EKeys::End ) );
|
|
UI_COMMAND( SnapOriginToGridPerActor, "Snap Origin to Grid Per Actor", "Snaps each selected actor separately to the nearest grid location at its origin", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AlignOriginToGrid, "Align Origin to Grid", "Aligns the actor to the nearest grid location at its origin", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( SnapTo2DLayer, "Snap to 2D Layer", "Snaps the actor to the current 2D snap layer", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Control, EKeys::SpaceBar ) );
|
|
UI_COMMAND( MoveSelectionUpIn2DLayers, "Bring selection forward a snap layer", "Bring selection forward a snap layer", EUserInterfaceActionType::Button, FInputChord(EKeys::PageUp, EModifierKey::Control) );
|
|
UI_COMMAND( MoveSelectionDownIn2DLayers, "Send selection backward a snap layer", "Send selection backward a snap layer", EUserInterfaceActionType::Button, FInputChord(EKeys::PageDown, EModifierKey::Control) );
|
|
UI_COMMAND( MoveSelectionToTop2DLayer, "Bring selection to the front snap layer", "Bring selection to the front snap layer", EUserInterfaceActionType::Button, FInputChord(EKeys::PageUp, EModifierKey::Shift | EModifierKey::Control) );
|
|
UI_COMMAND( MoveSelectionToBottom2DLayer, "Send selection to the back snap layer", "Send selection to the back snap layer", EUserInterfaceActionType::Button, FInputChord(EKeys::PageDown, EModifierKey::Shift | EModifierKey::Control) );
|
|
UI_COMMAND( Select2DLayerAbove, "Select next 2D layer", "Changes the active layer to the next 2D layer", EUserInterfaceActionType::Button, FInputChord(EKeys::PageUp, EModifierKey::Alt) );
|
|
UI_COMMAND( Select2DLayerBelow, "Select previous 2D layer", "Changes the active layer to the previous 2D layer", EUserInterfaceActionType::Button, FInputChord(EKeys::PageDown, EModifierKey::Alt) );
|
|
|
|
|
|
UI_COMMAND( SnapToFloor, "Snap to Floor", "Snaps the actor or component to the floor below it", EUserInterfaceActionType::Button, FInputChord( EKeys::End ) );
|
|
UI_COMMAND( AlignToFloor, "Align to Floor", "Aligns the actor or component with the floor", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SnapPivotToFloor, "Snap Pivot to Floor", "Snaps the actor to the floor at its pivot point", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Alt, EKeys::End ) );
|
|
UI_COMMAND( AlignPivotToFloor, "Align Pivot to Floor", "Aligns the actor with the floor at its pivot point", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SnapBottomCenterBoundsToFloor, "Snap Bottom Center Bounds to Floor", "Snaps the actor to the floor at its bottom center bounds", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Shift, EKeys::End ) );
|
|
UI_COMMAND( AlignBottomCenterBoundsToFloor, "Align Bottom Center Bounds to Floor", "Aligns the actor with the floor at its bottom center bounds", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SnapOriginToActor, "Snap Origin to Actor", "SNaps the actor to another actor at its origin", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AlignOriginToActor, "Align Origin to Actor", "Aligns the actor to another actor at its origin", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SnapToActor, "Snap to Actor", "Snaps the actor to another actor", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AlignToActor, "Align to Actor", "Aligns the actor with another actor", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SnapPivotToActor, "Snap Pivot to Actor", "Snaps the actor to another actor at its pivot point", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AlignPivotToActor, "Align Pivot to Actor", "Aligns the actor with another actor at its pivot point", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SnapBottomCenterBoundsToActor, "Snap Bottom Center Bounds to Actor", "Snaps the actor to another actor at its bottom center bounds", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AlignBottomCenterBoundsToActor, "Align Bottom Center Bounds to Actor", "Aligns the actor with another actor at its bottom center bounds", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( DeltaTransformToActors, "Delta Transform", "Apply Delta Transform to selected actors", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MirrorActorX, "Mirror X", "Mirrors the actor along the X axis", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MirrorActorY, "Mirror Y", "Mirrors the actor along the Y axis", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MirrorActorZ, "Mirror Z", "Mirrors the actor along the Z axis", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( LockActorMovement, "Lock Actor Movement", "Locks the actor so it cannot be moved", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( DetachFromParent, "Detach", "Detach the actor from its parent", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AttachSelectedActors, "Attach Selected Actors", "Attach the selected actors to the last selected actor", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Alt, EKeys::B) );
|
|
UI_COMMAND( AttachActorIteractive, "Attach Actor Interactive", "Start an interactive actor picker to let you choose a parent for the currently selected actor", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Alt, EKeys::A) );
|
|
UI_COMMAND( CreateNewOutlinerFolder, "Create Folder", "Place the selected actors in a new folder", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( HoldToEnableVertexSnapping, "Hold to Enable Vertex Snapping", "When the key binding is pressed and held vertex snapping will be enabled", EUserInterfaceActionType::ToggleButton, FInputChord(EKeys::V) );
|
|
|
|
//@ todo Slate better tooltips for pivot options
|
|
UI_COMMAND( SavePivotToPrePivot, "Set as Pivot Offset", "Sets the current pivot location as the pivot offset for this actor", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ResetPrePivot, "Reset Pivot Offset", "Resets the pivot offset for this actor", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ResetPivot, "Reset Pivot", "Resets the pivot", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MovePivotHere, "Set Pivot Offset Here", "Sets the pivot offset to the clicked location", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MovePivotHereSnapped, "Set Pivot Offset Here (Snapped)", "Sets the pivot offset to the nearest grid point to the clicked location", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MovePivotToCenter, "Center on Selection", "Centers the pivot to the middle of the selection", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( ConvertToAdditive, "Additive", "Converts the selected brushes to additive brushes", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ConvertToSubtractive, "Subtractive", "Converts the selected brushes to subtractive brushes", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( OrderFirst, "To First", "Changes the drawing order of the selected brushes so they are the first to draw", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( OrderLast, "To Last", "Changes the drawing order of the selected brushes so they are the last to draw", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( MakeSolid, "Solid", "Makes the selected brushes solid", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MakeSemiSolid, "Semi-Solid", "Makes the selected brushes semi-solid", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( MakeNonSolid, "Non-Solid", "Makes the selected brushes non-solid", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( MergePolys, "Merge", "Merges multiple polygons on a brush face into as few as possible", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SeparatePolys, "Separate", "Reverses the effect of a previous merge", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
// RegroupActors uses GroupActors for it's label and tooltip when simply grouping a selection of actors using overrides. This is to provide display of the chord which is the same for both.
|
|
UI_COMMAND( GroupActors, "Group", "Groups the selected actors", EUserInterfaceActionType::Button, FInputChord( /*EKeys::G, EModifierKey::Control*/ ) );
|
|
UI_COMMAND( RegroupActors, "Regroup", "Regroups the selected actors into a new group, removing any current groups in the selection", EUserInterfaceActionType::Button, FInputChord( EKeys::G, EModifierKey::Control ) );
|
|
UI_COMMAND( UngroupActors, "Ungroup", "Ungroups the selected actors", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Shift, EKeys::G ) );
|
|
UI_COMMAND( AddActorsToGroup, "Add to Group", "Adds the selected actors to the selected group", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( RemoveActorsFromGroup, "Remove from Group", "Removes the selected actors from the selected groups", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( LockGroup, "Lock", "Locks the selected groups", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( UnlockGroup, "Unlock", "Unlocks the selected groups", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
#if PLATFORM_MAC
|
|
UI_COMMAND( ShowAll, "Show All Actors", "Shows all actors", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Command, EKeys::H ) );
|
|
#else
|
|
UI_COMMAND( ShowAll, "Show All Actors", "Shows all actors", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Control, EKeys::H ) );
|
|
#endif
|
|
UI_COMMAND( ShowSelectedOnly, "Show Only Selected", "Shows only the selected actors", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ShowSelected, "Show Selected", "Shows the selected actors", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Shift, EKeys::H ) );
|
|
UI_COMMAND( HideSelected, "Hide Selected", "Hides the selected actors", EUserInterfaceActionType::Button, FInputChord( EKeys::H ) );
|
|
UI_COMMAND( ShowAllStartup, "Show All At Startup", "Shows all actors at startup", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ShowSelectedStartup, "Show Selected At Startup", "Shows selected actors at startup", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( HideSelectedStartup, "Hide Selected At Startup", "Hide selected actors at startup", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( CycleNavigationDataDrawn, "Cycle Navigation Data Drawn", "Cycles through navigation data (navmeshes for example) to draw one at a time", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Alt, EKeys::N ) );
|
|
|
|
UI_COMMAND( SelectNone, "Unselect All", "Unselects all actors", EUserInterfaceActionType::Button, FInputChord( EKeys::Escape ) ) ;
|
|
UI_COMMAND( InvertSelection, "Invert Selection", "Inverts the current selection", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( SelectAllActorsOfSameClass, "Select All Actors of Same Class", "Selects all the actors that have the same class", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift|EModifierKey::Control, EKeys::A) );
|
|
UI_COMMAND( SelectAllActorsOfSameClassWithArchetype, "Select All Actors with Same Archetype", "Selects all the actors of the same class that have the same archetype", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SelectComponentOwnerActor, "Select Component Owner", "Select the actor that owns the currently selected component(s)", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SelectRelevantLights, "Select Relevant Lights", "Select all lights relevant to the current selection", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SelectStaticMeshesOfSameClass, "Select All Using Selected Static Meshes (Selected Actor Types)", "Selects all actors with the same static mesh and actor class as the selection", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SelectOwningHierarchicalLODCluster, "Select Owning Hierarchical LOD cluster Using Selected Static Mesh (Selected Actor Types)", "Select Owning Hierarchical LOD cluster for the selected actor", EUserInterfaceActionType::Button, FInputChord());
|
|
UI_COMMAND( SelectStaticMeshesAllClasses, "Select All Using Selected Static Meshes (All Actor Types)", "Selects all actors with the same static mesh as the selection", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Shift, EKeys::E ) );
|
|
UI_COMMAND( SelectSkeletalMeshesOfSameClass, "Select All Using Selected Skeletal Meshes (Selected Actor Types)", "Selects all actors with the same skeletal mesh and actor class as the selection", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SelectSkeletalMeshesAllClasses, "Select All Using Selected Skeletal Meshes (All Actor Types)", "Selects all actors with the same skeletal mesh as the selection", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SelectAllWithSameMaterial, "Select All With Same Material", "Selects all actors with the same material as the selection", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SelectMatchingEmitter, "Select All Matching Emitters", "Selects all emitters with the same particle system as the selection", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SelectAllLights, "Select All Lights", "Selects all lights", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SelectStationaryLightsExceedingOverlap, "Select Stationary Lights exceeding overlap", "Selects all stationary lights exceeding the overlap limit", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SelectAllAddditiveBrushes, "Select All Additive Brushes", "Selects all additive brushes", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SelectAllSubtractiveBrushes, "Select All Subtractive Brushes", "Selects all subtractive brushes", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SelectAllActorsControlledByMatinee, "Select Actors Used by This Matinee", "Selects all actors controlled by this Matinee", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( SelectAllSurfaces, "Select All Surfaces", "Selects all bsp surfaces", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::S) );
|
|
|
|
UI_COMMAND( SurfSelectAllMatchingBrush, "Select Matching Brush", "Selects the surfaces belonging to the same brush as the selected surfaces", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::B) );
|
|
UI_COMMAND( SurfSelectAllMatchingTexture, "Select Matching Material", "Selects all surfaces with the same material as the selected surfaces", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::T) );
|
|
UI_COMMAND( SurfSelectAllAdjacents, "Select All Adjacent Surfaces", "Selects all surfaces adjacent to the currently selected surfaces", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::J) );
|
|
UI_COMMAND( SurfSelectAllAdjacentCoplanars, "Select All Coplanar Surfaces", "Selects all surfaces adjacent and coplanar with the selected surfaces", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::C) );
|
|
UI_COMMAND( SurfSelectAllAdjacentWalls, "Select All Adjacent Wall Surfaces", "Selects all adjacent upright surfaces", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::W) );
|
|
UI_COMMAND( SurfSelectAllAdjacentFloors, "Select All Adjacent Floor Surfaces", "Selects all adjacent floor sufaces(ones with normals pointing up)", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::U) );
|
|
UI_COMMAND( SurfSelectAllAdjacentSlants, "Select All Adjacent Slant Surfaces", "Selects all adjacent slant surfaces (surfaces that are not walls, floors, or ceilings according to their normals) to the currently selected surfaces.", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::Y) );
|
|
UI_COMMAND( SurfSelectReverse, "Invert Surface Selection", "Inverts the current surface selection", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::Q) );
|
|
UI_COMMAND( SurfSelectMemorize, "Memorize Surface Selection", "Stores the current surface selection in memory", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::M) );
|
|
UI_COMMAND( SurfSelectRecall, "Recall Surface Selection", "Replace the current selection with the selection saved in memory", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::R) );
|
|
UI_COMMAND( SurfSelectOr, "Surface Selection OR", "Replace the current selection with only the surfaces which are both currently selected and contained within the saved selection in memory", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::O) );
|
|
UI_COMMAND( SurfSelectAnd, "Surface Selection AND", "Add the selection of surfaces saved in memory to the current selection", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::A) );
|
|
UI_COMMAND( SurfSelectXor, "Surace Selection XOR", " Replace the current selection with only the surfaces that are not in both the current selection and the selection saved in memory", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Shift, EKeys::X) );
|
|
UI_COMMAND( SurfUnalign, "Align Surface Default", "Default surface alignment", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SurfAlignPlanarAuto, "Align Surface Planar", "Planar surface alignment", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SurfAlignPlanarWall, "Align Surface Planar Wall", "Planar wall surface alignment", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SurfAlignPlanarFloor, "Align Surface Planar Floor", "Planar floor surface alignment", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SurfAlignBox, "Align Surface Box", "Box surface alignment", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( SurfAlignFit, "Align Surface Fit", "Best fit surface alignment", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ApplyMaterialToSurface, "Apply Material to Surface Selection", "Applies the selected material to the selected surfaces", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( CreateBoundingBoxVolume, "Create Bounding Box Blocking Volume From Mesh", "Create a bounding box blocking volume from the static mesh", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( CreateHeavyConvexVolume, "Heavy Convex Blocking Volume From Mesh", "Creates a heavy convex blocking volume from the static mesh", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( CreateNormalConvexVolume, "Normal Convex Blocking Volume From Mesh", "Creates a normal convex blocking volume from the static mesh", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( CreateLightConvexVolume, "Light Convex Blocking Volume From Mesh", "Creates a light convex blocking volume from the static mesh", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( CreateRoughConvexVolume, "Rought Convex Blocking Volume From Mesh", "Creates a rough convex blocking volume from the static mesh", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( KeepSimulationChanges, "Keep Simulation Changes", "Saves the changes made to this actor in Simulate mode to the actor's default state.", EUserInterfaceActionType::Button, FInputChord( EKeys::K ) );
|
|
|
|
UI_COMMAND( MakeActorLevelCurrent, "Make Selected Actor's Level Current", "Makes the selected actor's level the current level", EUserInterfaceActionType::Button, FInputChord( EKeys::M ) );
|
|
#if PLATFORM_MAC
|
|
UI_COMMAND( MoveSelectedToCurrentLevel, "Move Selection to Current Level", "Moves the selected actors to the current level", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Command, EKeys::M ) );
|
|
#else
|
|
UI_COMMAND( MoveSelectedToCurrentLevel, "Move Selection to Current Level", "Moves the selected actors to the current level", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Control, EKeys::M ) );
|
|
#endif
|
|
UI_COMMAND( FindActorLevelInContentBrowser, "Find Actor Level in Content Browser", "Finds the selected actors' level in the content browser", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( FindLevelsInLevelBrowser, "Find Levels in Level Browser", "Finds the selected actors' levels in the level browser", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AddLevelsToSelection, "Add Levels to Selection", "Adds the selected actors' levels to the current level browser selection", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( RemoveLevelsFromSelection, "Remove Levels from Selection", "Removes the selected actors' levels from the current level browser selection", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( FindActorInLevelScript, "Find in Level Blueprint", "Finds any references to the selected actor in its level's blueprint", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( WorldProperties, "World Settings", "Displays the world settings", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( OpenContentBrowser, "Open Content Browser", "Opens the Content Browser", EUserInterfaceActionType::Button, FInputChord(EModifierKey::Control|EModifierKey::Shift, EKeys::F) );
|
|
UI_COMMAND( OpenMarketplace, "Open Marketplace", "Opens the Marketplace", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( AddMatinee, "Add Matinee [Legacy]", "Creates a new matinee actor to edit", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( EditMatinee, "Edit Matinee", "Selects a Matinee to edit", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( ToggleVR, "Toggle VR", "Toggles VR (Virtual Reality) mode", EUserInterfaceActionType::ToggleButton, FInputChord( EModifierKey::Alt, EKeys::Tilde ) );
|
|
|
|
UI_COMMAND( OpenLevelBlueprint, "Open Level Blueprint", "Edit the Level Blueprint for the current level", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( CheckOutProjectSettingsConfig, "Check Out", "Checks out the project settings config file so the game mode can be set.", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( CreateBlankBlueprintClass, "New Empty Blueprint Class...", "Create a new Blueprint Class", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ConvertSelectionToBlueprintViaHarvest, "Convert Selected Components to Blueprint Class...", "Replace all of the selected actors with a new Blueprint Class based on Actor that contains the components", EUserInterfaceActionType::Button, FInputChord() );
|
|
UI_COMMAND( ConvertSelectionToBlueprintViaSubclass, "Convert Selected Actor to Blueprint Class...", "Replace the selected actor with a new Blueprint subclass based on the class of the selected Actor", EUserInterfaceActionType::Button, FInputChord() );
|
|
|
|
UI_COMMAND( ShowTransformWidget, "Show Transform Widget", "Toggles the visibility of the transform widgets", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( AllowTranslucentSelection, "Allow Translucent Selection", "Allows translucent objects to be selected", EUserInterfaceActionType::ToggleButton, FInputChord(EKeys::T) );
|
|
UI_COMMAND( AllowGroupSelection, "Allow Group Selection", "Allows actor groups to be selected", EUserInterfaceActionType::ToggleButton, FInputChord(EModifierKey::Control|EModifierKey::Shift, EKeys::G) );
|
|
UI_COMMAND( StrictBoxSelect, "Strict Box Selection", "When enabled an object must be entirely encompassed by the selection box when marquee box selecting", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( TransparentBoxSelect, "Box Select Occluded Objects", "When enabled, marquee box select operations will also select objects that are occluded by other objects.", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( DrawBrushMarkerPolys, "Draw Brush Polys", "Draws semi-transparent polygons around a brush when selected", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( OnlyLoadVisibleInPIE, "Only Load Visible Levels in Game Preview", "If enabled, when game preview starts, only visible levels will be loaded", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( ToggleSocketSnapping, "Enable Socket Snapping", "Enables or disables snapping to sockets", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( ToggleParticleSystemLOD, "Enable Particle System LOD Switching", "If enabled particle systems will use distance LOD switching in perspective viewports", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( ToggleFreezeParticleSimulation, "Freeze Particle Simulation", "If enabled particle systems will freeze their simulation state", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( ToggleParticleSystemHelpers, "Toggle Particle System Helpers", "Toggles showing particle system helper widgets in viewports", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( ToggleLODViewLocking, "Enable LOD View Locking", "If enabled viewports of the same type will use the same LOD", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( LevelStreamingVolumePrevis, "Enable Automatic Level Streaming", "If enabled, the viewport will stream in levels automatically when the camera is moved", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( EnableActorSnap, "Enable Actor Snapping", "If enabled, actors will snap to the location of other actors when they are within distance", EUserInterfaceActionType::ToggleButton, FInputChord(EModifierKey::Control|EModifierKey::Shift, EKeys::K) );
|
|
UI_COMMAND( EnableVertexSnap, "Enable Vertex Snapping","If enabled, actors will snap to the location of the nearest vertex on another actor in the direction of movement", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
UI_COMMAND( ToggleHideViewportUI, "Hide Viewport UI", "Toggles hidden viewport UI mode. Hides all overlaid viewport UI widgets", EUserInterfaceActionType::ToggleButton, FInputChord() );
|
|
|
|
//if (FParse::Param( FCommandLine::Get(), TEXT( "editortoolbox" ) ))
|
|
//{
|
|
// UI_COMMAND( BspMode, "Enable Bsp Mode", "Enables BSP mode", EUserInterfaceActionType::ToggleButton, FInputChord( EModifierKey::Shift, EKeys::One ) );
|
|
// UI_COMMAND( MeshPaintMode, "Enable Mesh Paint Mode", "Enables mesh paint mode", EUserInterfaceActionType::ToggleButton, FInputChord( EModifierKey::Shift, EKeys::Two ) );
|
|
// UI_COMMAND( LandscapeMode, "Enable Landscape Mode", "Enables landscape editing", EUserInterfaceActionType::ToggleButton, FInputChord( EModifierKey::Shift, EKeys::Three ) );
|
|
// UI_COMMAND( FoliageMode, "Enable Foliage Mode", "Enables foliage editing", EUserInterfaceActionType::ToggleButton, FInputChord( EModifierKey::Shift, EKeys::Four ) );
|
|
//}
|
|
|
|
UI_COMMAND( ShowSelectedDetails, "Show Actor Details", "Opens a details panel for the selected actors", EUserInterfaceActionType::Button, FInputChord( EKeys::F4 ) );
|
|
|
|
UI_COMMAND( RecompileShaders, "Recompile Changed Shaders", "Recompiles shaders which are out of date", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Shift|EModifierKey::Control, EKeys::Period ) );
|
|
UI_COMMAND( ProfileGPU, "Profile GPU", "Profiles the GPU for the next frame and opens a window with profiled data", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Shift|EModifierKey::Control, EKeys::Comma ) );
|
|
|
|
UI_COMMAND( ResetAllParticleSystems, "Reset All Particle Systems", "Resets all particle system emitters (removes all active particles and restarts them)", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Shift, EKeys::Slash ) );
|
|
UI_COMMAND( ResetSelectedParticleSystem, "Resets Selected Particle Systems" , "Resets selected particle system emitters (removes all active particles and restarts them)", EUserInterfaceActionType::Button, FInputChord( EKeys::Slash ) );
|
|
|
|
UI_COMMAND( SelectActorsInLayers, "Select all actors in selected actor's layers", "Selects all actors belonging to the layers of the currently selected actors", EUserInterfaceActionType::Button, FInputChord( EModifierKey::Control, EKeys::L ) );
|
|
|
|
UI_COMMAND( FocusAllViewportsToSelection, "Focus Selected Actors in All Viewports", "Moves the camera in front of the selected actors in all open viewports", EUserInterfaceActionType::Button, FInputChord( EKeys::F, EModifierKey::Shift ) );
|
|
|
|
UI_COMMAND(MaterialQualityLevel_Low, "Low", "Sets material quality in the scene to low.", EUserInterfaceActionType::RadioButton, FInputChord());
|
|
UI_COMMAND(MaterialQualityLevel_Medium, "Medium", "Sets material quality in the scene to medium.", EUserInterfaceActionType::RadioButton, FInputChord());
|
|
UI_COMMAND(MaterialQualityLevel_High, "High", "Sets material quality in the scene to high.", EUserInterfaceActionType::RadioButton, FInputChord());
|
|
|
|
UI_COMMAND(PreviewPlatformOverride_DefaultES2, "Default Mobile / HTML5 Preview", "Use default mobile settings (no quality overrides).", EUserInterfaceActionType::RadioButton, FInputChord());
|
|
UI_COMMAND(PreviewPlatformOverride_AndroidES2, "Android Preview", "Mobile preview using Android's quality settings.", EUserInterfaceActionType::RadioButton, FInputChord());
|
|
UI_COMMAND(PreviewPlatformOverride_IOSES2, "iOS ES2 Preview", "Mobile preview using iOS's OpenGL ES2 quality settings.", EUserInterfaceActionType::RadioButton, FInputChord());
|
|
|
|
UI_COMMAND( ConnectToSourceControl, "Connect to Source Control...", "Opens a dialog to connect to source control.", EUserInterfaceActionType::Button, FInputChord());
|
|
UI_COMMAND( ChangeSourceControlSettings, "Change Source Control Settings...", "Opens a dialog to change source control settings.", EUserInterfaceActionType::Button, FInputChord());
|
|
UI_COMMAND( CheckOutModifiedFiles, "Check Out Modified Files...", "Opens a dialog to check out any assets which have been modified.", EUserInterfaceActionType::Button, FInputChord());
|
|
UI_COMMAND( SubmitToSourceControl, "Submit to Source Control...", "Opens a dialog with check in options for content and levels.", EUserInterfaceActionType::Button, FInputChord());
|
|
|
|
static const FText FeatureLevelLabels[ERHIFeatureLevel::Num] =
|
|
{
|
|
NSLOCTEXT("LevelEditorCommands", "FeatureLevelPreviewType_ES2", "Mobile / HTML5"),
|
|
NSLOCTEXT("LevelEditorCommands", "FeatureLevelPreviewType_ES31", "High-End Mobile / Metal"),
|
|
NSLOCTEXT("LevelEditorCommands", "FeatureLevelPreviewType_SM4", "Shader Model 4"),
|
|
NSLOCTEXT("LevelEditorCommands", "FeatureLevelPreviewType_SM5", "Shader Model 5"),
|
|
};
|
|
|
|
static const FText FeatureLevelToolTips[ERHIFeatureLevel::Num] =
|
|
{
|
|
NSLOCTEXT("LevelEditorCommands", "FeatureLevelPreviewTooltip_ES2", "OpenGLES 2"),
|
|
NSLOCTEXT("LevelEditorCommands", "FeatureLevelPreviewTooltip_ES3", "OpenGLES 3.1, Metal"),
|
|
NSLOCTEXT("LevelEditorCommands", "FeatureLevelPreviewTooltip_SM4", "DirectX 10, OpenGL 3.3+"),
|
|
NSLOCTEXT("LevelEditorCommands", "FeatureLevelPreviewTooltip_SM5", "DirectX 11, OpenGL 4.3+, PS4, XB1"),
|
|
};
|
|
|
|
for (int32 i = 0; i < ERHIFeatureLevel::Num; ++i)
|
|
{
|
|
FName Name;
|
|
GetFeatureLevelName((ERHIFeatureLevel::Type)i, Name);
|
|
|
|
FeatureLevelPreview[i] =
|
|
FUICommandInfoDecl(
|
|
this->AsShared(),
|
|
Name,
|
|
FeatureLevelLabels[i],
|
|
FeatureLevelToolTips[i])
|
|
.UserInterfaceType(EUserInterfaceActionType::RadioButton)
|
|
.DefaultChord(FInputChord());
|
|
}
|
|
}
|
|
|
|
PRAGMA_ENABLE_OPTIMIZATION
|
|
|
|
#undef LOCTEXT_NAMESPACE
|