2019-12-26 15:32:37 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
# include "LODUtilities.h"
2022-04-26 12:53:38 -04:00
# if WITH_EDITOR
Copying //UE4/Dev-Build to //UE4/Dev-Main (Source: //UE4/Dev-Build @ 3209340)
#lockdown Nick.Penwarden
#rb none
==========================
MAJOR FEATURES + CHANGES
==========================
Change 3209340 on 2016/11/23 by Ben.Marsh
Convert UE4 codebase to an "include what you use" model - where every header just includes the dependencies it needs, rather than every source file including large monolithic headers like Engine.h and UnrealEd.h.
Measured full rebuild times around 2x faster using XGE on Windows, and improvements of 25% or more for incremental builds and full rebuilds on most other platforms.
* Every header now includes everything it needs to compile.
* There's a CoreMinimal.h header that gets you a set of ubiquitous types from Core (eg. FString, FName, TArray, FVector, etc...). Most headers now include this first.
* There's a CoreTypes.h header that sets up primitive UE4 types and build macros (int32, PLATFORM_WIN64, etc...). All headers in Core include this first, as does CoreMinimal.h.
* Every .cpp file includes its matching .h file first.
* This helps validate that each header is including everything it needs to compile.
* No engine code includes a monolithic header such as Engine.h or UnrealEd.h any more.
* You will get a warning if you try to include one of these from the engine. They still exist for compatibility with game projects and do not produce warnings when included there.
* There have only been minor changes to our internal games down to accommodate these changes. The intent is for this to be as seamless as possible.
* No engine code explicitly includes a precompiled header any more.
* We still use PCHs, but they're force-included on the compiler command line by UnrealBuildTool instead. This lets us tune what they contain without breaking any existing include dependencies.
* PCHs are generated by a tool to get a statistical amount of coverage for the source files using it, and I've seeded the new shared PCHs to contain any header included by > 15% of source files.
Tool used to generate this transform is at Engine\Source\Programs\IncludeTool.
[CL 3209342 by Ben Marsh in Main branch]
2016-11-23 15:48:37 -05:00
# include "Misc/MessageDialog.h"
# include "Misc/FeedbackContext.h"
# include "Modules/ModuleManager.h"
# include "UObject/UObjectIterator.h"
# include "Components/SkinnedMeshComponent.h"
# include "Components/SkeletalMeshComponent.h"
Copying //UE4/Dev-Editor to //UE4/Dev-Main (Source: //UE4/Dev-Editor @ 3497164)
#lockdown Nick.Penwarden
#rb none
=====================================
MAJOR FEATURES + CHANGES
=====================================
Change 3433074 by Matt.Kuhlenschmidt
Fix crash when clicking on certian tutorial blueprints.
#jira UE-44593
Change 3433075 by Matt.Kuhlenschmidt
Remove hittest grid log spam. The underlying problem causing this has been fixed
Change 3433077 by Matt.Kuhlenschmidt
Fix lighting becoming unbuilt when mesh painting
#jira UE-44837
Change 3433081 by Matt.Kuhlenschmidt
PR #3553: Crashfix for static array properties (Contributed by Pierdek)
Change 3433104 by Alexis.Matte
Make sure re-import skeletal mesh follow the import morph option
#jira UE-42846
Change 3434825 by Matt.Kuhlenschmidt
Fix crash when GC happens while the vr editor radial menu is open.
Change 3434831 by Matt.Kuhlenschmidt
Added missing file
Change 3434868 by Shaun.Kime
If you have a reroute node between a Material Function texture input and its usage, the parent material will fail to resolve the reroute node.
#jira ue-44670
Change 3434998 by Alexis.Matte
Meshes editors material/section panel are now fully transactional
- Staticmesh editor: section material slot, section cast shadow, section collision, material slot instance, material slot name
- Skeletal mesh editor: material slot instance, material slot name
Also fix some transaction description
#jira UE-44462
Change 3435195 by Jamie.Dale
Fixed incorrect handling of some LTR scripts that require shaping
These scripts need to go through HarfBuzz, and this also fixes a case where HarfBuzz wasn't applying font scale correctly.
#jira UE-44767
Change 3435199 by Jamie.Dale
Fixed some crashes/artifacts with bidirectional text
It was possible for a line to compute an incorrect range, which could cause crashes or other highlighting issues. The highlighting logic has also been updated as the old code didn't handle all bidirectional cases correctly.
Change 3435200 by Jamie.Dale
Fixed a grapheme cluster metrics issue in the font editor viewport
The viewport also now respects the default shaping method CVar.
Change 3435771 by Alexis.Matte
Fix degenerated bounds calculation for skeletalmesh when the skeleton is remove from a re-import
(PhysicAsset API change, adding 1 function)
#jira UE-44609
Change 3436856 by Jamie.Dale
Added some missing Unicode block ranges
Change 3436914 by Jamie.Dale
Adding some missing combining character ranges to the text shaper
Change 3436923 by Alexis.Matte
PR #3463: Get bounds for all triangles, not just the first one. WedgeIndex was . (Contributed by DaveC79)
#jira UE-43764
Change 3436948 by Jamie.Dale
Updated the Portal to use the predefined Unicode block ranges
Change 3436961 by Max.Chen
Sequencer: Show camera shake/anim track menus even if there aren't any assets.
Change 3437244 by Max.Chen
Sequencer: Clear locked cameras when releasing Sequencer.
#jira UE-44967
Change 3437515 by Arciel.Rekman
UBT: improvements for LocalExecutor.
- Larger number of parallel jobs on 16GB+ machines.
- Use WaitForExit() instead of polling.
- Tested on Linux and Mac.
Change 3437629 by Matt.Kuhlenschmidt
Improve asset import data display in static and skeletal meshes
Change 3438047 by Arciel.Rekman
Fix overlapping ranges being passed to memcpy().
Change 3438822 by Yannick.Lange
ViewportInteraction: Move gizmo handle files to make them private.
Change 3438906 by Matt.Kuhlenschmidt
PR #3556: Git Plugin: fix new option "init Git LFS" that make assets read-only (master/UE4.17) (Contributed by SRombauts)
Change 3438907 by Matt.Kuhlenschmidt
PR #3565: add -quality option to buildlighing commandlet (Contributed by kayama-shift)
Change 3438908 by Matt.Kuhlenschmidt
PR #3558: UE-44862: Always update SColorPicker color on OK button (Contributed by projectgheist)
Change 3439393 by Matt.Kuhlenschmidt
Force highest LOD for highres screenshots
Change 3439819 by Matt.Kuhlenschmidt
Turned FAssetData into a struct for some upcoming script exposure of FAssetData
Change 3439949 by Arciel.Rekman
Fixed selection logic for the UE4_LINUX_USE_LIBCXX environment variable.
- Allows disabling libc++ by setting the variable to 0.
- Pull request #3576 contributed by jared-improbable.
Change 3441078 by Jamie.Dale
The culture/language/locale console commands are now available in all build configs
Change 3441109 by Jamie.Dale
Text containing surrogate pairs now runs through HarfBuzz when shaping in Auto mode
This is needed as the kerning-only shaping code assumes that everything is within the BMP
Change 3441275 by Matt.Kuhlenschmidt
Disable spinning on location and scale. These dont work because we have no notion of infinite spinning
Change 3442748 by Yannick.Lange
ViewportInteraction: Remove unused console variables.
Change 3442775 by James.Golding
Add support for editing MaterialFunctions to MaterialEditingLibrary
Pull Material recompile/update code into UMaterialEditingLibrary::RecompileMaterial
Pull MaterialFunction update code into UMaterialEditingLibrary::UpdateMaterialFunction util
Move RebuildMaterialInstanceEditors to UMaterialEditingLibrary
Added test content for Material/MaterialFunction editing
Add needed BlueprintReadWrite to expressions (constants, function input/output)
Expose UMaterialExpressionMaterialFunctionCall::SetMaterialFunction to BP, rename old func (which takes old function) to SetMaterialFunctionEx, also expose GetInputNameWithType
Change 3442779 by James.Golding
Fix header order
Change 3442817 by Yannick.Lange
ViewportInteraction: Add can execute checks for level editor commands.
Change 3443038 by Michael.Dupuis
#jira UE-43377: When you select a foliage actor we will move all instance contained in it to the new level as we can't move a foliage actor
Only permit moving foliage instance if there is some selected
Change 3443855 by Michael.Dupuis
#jira UE-44885: Unregister from PerModuleDataObjects when the object is destroyed
Change 3446096 by Max.Chen
Sequencer: Add OnFinished() event when a level sequence completes playback
#jira UE-45173
Change 3446097 by Max.Chen
Sequencer: Evaluate one last time before the sequence is torn down and reset
#jira UE-45174
Change 3446242 by Jamie.Dale
Fixed caret not appearing in empty text layouts
Caret selections have no range, and therefore have no width
Change 3446361 by Matt.Kuhlenschmidt
Fix WITH_EDITOR only functions causing generated code compile errors when the all functions on the class are WITH_EDITOR
Change 3446457 by Alexis.Matte
Polish the speed tree import dialog
#jira UE-44963
Change 3446946 by Michael.Trepka
Modified FWindowsWindow::GetRestoredDimensions to return correct window position for normal windows for which GetWindowPlacement returns position in workspace coordinates
#jira UE-37934
Change 3447543 by Arciel.Rekman
Reduce VMAs on Linux.
- Trades off increased address space (VIRT in terms of ps/htop) for smaller number of distinct mappings (VMAs, virtual memory areas).
This decreases possibility to run into vm.max_map_count limit on Linux.
- Tested on Linux and Mac.
Change 3448468 by Arciel.Rekman
Fix race condition during creation of GMalloc.
- On Mac GMalloc can be created on two different thread that are racing with each other - app's main thread and a system thread.
Change 3449012 by Max.Chen
Sequencer: Add time to transform, color and vector key structs so that key times are editable from the key editors.
#jira UE-45089
Change 3449018 by Max.Chen
Sequencer: Add OnCameraCut event that fires when there is a camera cut.
#jira UE-45137
Change 3449195 by Max.Chen
Sequencer: Add setting for limit scrubbing to playback range.
#jira UE-43502
Change 3449198 by Max.Chen
Sequencer: Reorder hierarchical bias so that group priority takes precedence.
Change 3449217 by Max.Chen
Sequencer: Add setting to activate realtime viewports when in sequencer.
Change 3449219 by Max.Chen
Sequencer: Focus on search boxes when opened.
Change 3449238 by Max.Chen
Sequencer: Assign actor should replace the actor itself after it has updated all the components. Also, replace components be fullname rather than by class.
Change 3449239 by Max.Chen
Sequencer: Fix offsets when moving multiple sections. Dragging should be clamped to the bounds that any of the selected sections hits against the unselected sections.
Change 3449241 by Max.Chen
Sequencer: Restore section selection after full tree rebuild.
Change 3449279 by Max.Chen
Sequencer: Set movie scene capture frames only when not using custom frames. This allows the user entered frame numbers to persist in config, rather than overwriting them when doing a "Render Shot"
Change 3449280 by Max.Chen
Sequencer: Spawn in the persistent level. Otherwise, they get spawned into whatever sublevel is current.
#jira UE-44552
Change 3449294 by Max.Chen
Sequencer: Null check for sequencer ed mode crash.
Change 3449297 by Max.Chen
Sequencer: Fix delay in sliding values. Mark changed when sliding values. Mark refresh immediately when committing values since OnValueChanged will be called and needs to have the correct value that was refreshed immediately.
#jira UE-42866
Change 3449542 by Max.Chen
Sequencer: Fix scrubber hit testing so that the time scrubber is really favored over the playback ranges.
#jira UE-44569
Change 3451507 by Matt.Kuhlenschmidt
Fix extra slate uv coords not functioning on ES2
Change 3451510 by Matt.Kuhlenschmidt
PR #3595: Fixed wrong colour for level status (Contributed by ronve)
Change 3451529 by Alexis.Matte
fbx scene importer: Make sure we set INVALID_UNIQUE_ID to node that has no attribute.
#jira UE-34410
Change 3451611 by Yannick.Lange
ViewportInteraction: Dragging gizmo without second pass for snapped calculations.
Change 3452134 by Jamie.Dale
Fixed constant font cache flushing if a widget had no font set
Change 3452239 by Jamie.Dale
Fixed constant font measure flushing if a widget had no font set
Change 3452243 by Jamie.Dale
Removed deprecated code for creating fonts from bulk data
Change 3452277 by Jamie.Dale
The concept of "stale" composite fonts is now editor-only
Change 3452358 by Alexis.Matte
Fbx scene importer: Do not remove existing attribute reference from the blueprint if the reimport of the associate mesh attribute is not tick.
#jira UE-45232
Change 3452678 by Max.Chen
Sequencer: Fix crash on export if there's no shot data.
Change 3453057 by Matt.Kuhlenschmidt
Exposed asset exporting to script
Change 3453782 by Andrew.Rodham
Sequencer: Fixed deterministic cooking issues with movie scene data
- Movie scene signatures are now initialized in PostInitProperties
- A warning is now presented when attempting to cook old data that was never serialized with a signature.
- Removed redundant legacy data upgrade logic that could dirty level sequences on load.
#jira UE-44912
Change 3453788 by Yannick.Lange
ViewportInteraction: Custom scene proxy for gizmo handles.
Change 3453938 by Max.Chen
Sequencer: Hotkeys (shift , and shift .) to step to next/previous shot
#jira UE-45119
Change 3454058 by Michael.Dupuis
Fixed StaticAnalysis
Change 3454077 by Max.Chen
Sequencer: Fix not saving the pre-animated track value when creating a track/key.
On pre object change, broadcast property change so that a track or key can be created. That track/key needs to be evaluated immediately so that the pre-animated state can be saved properly. This is done now with RefreshAllImmediately and is only called when a track has been created. Also, added a return value for OnKeyProperty, so that it's known what changed in particular (ie. track created, track modified, etc)
Also, fixed transform keying so that if a transform track already exists for the object or the scene component, the existing track is used.
#jira UE-45130
Change 3454108 by Nick.Darnell
UMG - Fixing the WIC to properly record cursor delta so that scrollbars work.
Change 3454109 by Jamie.Dale
Cache the text layout source info in non-shipping builds so you can inspect it in the debugger
Change 3454202 by Matt.Kuhlenschmidt
Fix bogus error message about the number of usable texture coordinates on ES2 when compiling a UI domain material
Change 3454390 by Yannick.Lange
Fix creating a plugin in a C++ project opens a second instance of Visual Studio. Use SourceCodeAccessor to open solution when necessary.
#jira UE-45035
Change 3454564 by Matt.Kuhlenschmidt
#rnx Fix deprecation warnings
Change 3455471 by Yannick.Lange
ViewportInteraction: Fix entering and exiting VR Mode disables gizmo in desktop editor viewport.
#jira UE-44965
Change 3456183 by Max.Chen
Sequencer: Auto key, auto track refactor.
Auto key - create a key when the property changes and there's an existing track.
Auto track - create a track when the property changes. This is only exposed in the level sequence editor.
All - create a key and a track when the property changes. This is only exposed in VR Editor.
None - do nothing.
#jira UE-43469
Change 3456349 by Andrew.Rodham
Sequencer: Only perform legacy signature checks on instances, and only where signatures match the CDO
Change 3456678 by Alexis.Matte
Allow to add null level instance override material via the advance material array. But still limit the override material number to the mesh material number.
#jira UE-45306
Change 3456945 by Max.Chen
UMG: Add restore state to 2d transform section.
#jira UE-45372
Change 3457196 by Arciel.Rekman
Linux: serialize allocations from the memory pool.
Change 3458434 by Max.Chen
Sequencer: Remove obsolete set tick prerequites functions.
Change 3458671 by James.Golding
Added MIC editing support to MaterialEditingLibrary
Fix static analysis warning
Change 3458888 by Matt.Kuhlenschmidt
PR #3615: More detailed log messages for debugging warnings/errors (Contributed by projectgheist)
Change 3458893 by Matt.Kuhlenschmidt
PR #3583: UE-44960: Delta value wasn't being used (Contributed by projectgheist)
Change 3458895 by Matt.Kuhlenschmidt
Fix typo
Change 3458902 by Matt.Kuhlenschmidt
PR #3607: Improved InputKeySelector functionality (Contributed by projectgheist)
Change 3458917 by Matt.Kuhlenschmidt
Fix crash with invalid object properties in the class picker
#jira UE-39000
Change 3458939 by Matt.Kuhlenschmidt
Fix compile error
Change 3458984 by andrew.porter
QAGame: Initial check in of sequencer smoke test map
Change 3459510 by Matt.Kuhlenschmidt
Fixed ensure when deleting a map that contains build data which also happens to be the currently loaded map.
#jira UE-45052
Change 3460985 by Max.Chen
Sequencer: Snap play time to keys now allows scrubbing between keys and snaps to key times within a certain screenspace tolerance.
#jira UE-45090
Change 3461698 by Arciel.Rekman
Avoid using ARRAY_COUNT in Vulkan.
- Sometimes those arrays can have no extensions whatsoever, and it is illegal to declare a 0 element C array.
Change 3462053 by Max.Chen
Sequencer: Show sequencer spawnables in the world outliner and add the icon overlay for spawnables.
#jira UE-43470
Change 3462139 by Max.Chen
Property Editor: Add objects to FPropertyAndParent
Change 3462202 by Arciel.Rekman
Fix FSocket::Recv() blocking with Peek when there's no data.
Change 3462253 by Nick.Darnell
Slate - New Clipping System
Clipping is now a stateful choice made during composition of the slate hierarchy. Previously every widget got to respect or modify the clipping rect on an as needed basis. The problem was that clipping was only allowed in the layout space of the widget, and it wasn't possible to properly clip elements with render transforms. The new system permits all kinds of transforms on any widget, and they will all be clipped correctly. It tries to use Scissor Rects as they are much cheaper, but will switch over to stenciling if need be to represent a complicated masking structure with several rotated clipping rects all needed to be combined together.
Here are the new clipping states a widget can have, almost all widgets are set to No. Only change it from No if your widget actually needs to clip, generally speaking most widgets don't need to clip.
/**
* This widget does not clip children, it and all children inherit the clipping area of the last widget that clipped.
*/
Inherit,
/**
* This widget clips content the bounds of this widget. It intersects those bounds with any previous clipping area.
*/
ClipToBounds,
/**
* This widget clips to its bounds. It does NOT intersect with any existing clipping geometry, it pushes a new clipping
* state. Effectively allowing it to render outside the bounds of hierarchy that does clip.
*
* NOTE: This will NOT allow you ignore the clipping zone that is set to [Yes - Always].
*/
ClipToBoundsWithoutIntersecting UMETA(DisplayName = "Yes - Without Intersecting (Advanced)"),
/**
* This widget clips to its bounds. It intersects those bounds with any previous clipping area.
*
* NOTE: This clipping area can NOT be ignored, it will always clip children. Useful for hard barriers
* in the UI where you never want animations or other effects to break this region.
*/
ClipToBoundsAlways UMETA(DisplayName = "Yes - Always (Advanced)"),
/**
* This widget clips to its bounds when it's Desired Size is larger than the allocated geometry
* the widget is given. If that occurs, it behaves like [Yes].
*
* NOTE: This mode was primarily added for Text, which is often placed into containers that eventually
* are resized to not be able to support the length of the text. So rather than needing to tag every
* container that could contain text with [Yes], which would result in almost no batching, this mode
* was added to dynamically adjust the clipping if needed. The reason not every panel is set to OnDemand,
* is because not every panel returns a Desired Size that matches what it plans to render at.
*/
OnDemand UMETA(DisplayName = "On Demand (Advanced)")
- Large API Change -
All FSlateDrawElement::Make_____ calls have been deprecated that involved passing in a clipping rect. You no longer should are passed a Clipping rect via OnPaint. You are still passed a rect, but this rect represents a Culling Rect, which is valuable if you need to just out right not paint things the user can't possibly see.
If you were previously trying to determine if you should cull widgets, by doing something like this,
if ( FSlateRect::DoRectanglesIntersect(MyClippingRect, CurWidget.Geometry.GetRenderBoundingRect()) )
That's no longer a good option since there are ways for widgets to ignore the culling bounds. You should convert anything like above to the one below,
if (!SWidget::IsWidgetCulled(MyCullingRect, CurWidget))
To assist in debugging efforts, there are several new debugging console flags in Slate,
Slate.ShowClipping 1 - Controls whether we should render a clipping zone outline. Yellow = Axis Scissor Rect Clipping (cheap). Red = Stencil Clipping (expensive).
Slate.DebugCulling 1 - Disables pushing clipping or stencil rects to the GPU, but continues to intersect culling rects, so that you can tell if a widget is properly culling children it can't possibly draw.
Slate.ShowTextDebugging 1 - Show debugging painting for text rendering.
I've added a new Experimental Feathering Option, it adds AA geometry around the outside of Box and Image brushes.
Slate.Feathering 1
If you're using RenderDoc or something similar, you can now enable render events for slate, so that you can better grok how we're batching and changing states for each UI render pass.
Slate.EnableDrawEvents 1
#jira UE-4659
#rn
Change 3462714 by Nick.Darnell
Fixing a few more compiler issues with the clipping changes.
Change 3462726 by Max.Chen
Switch OnEditStructChildContentsChanged to use FObjectWriter instead of FMemoryWriter which supports serializeing UObjects. This fixes a crash when adding actor array elements to a user defined event struct.
#jira UE-45431
Change 3462801 by Nick.Darnell
Adding a UMG dependency to EngineTestBuild.
Change 3462914 by Max.Chen
Sequencer: Fix regression where spawnables aren't getting saved. Caused by 3407138
#jira UE-30007
#jira UE-39003
Change 3462946 by Nick.Darnell
Automation - Tweaking the UI automation tests converting them over to use the new UI Screenshot automation test.
Automation - Adding a blur widget test.
Change 3462987 by Matt.Kuhlenschmidt
Back out changelist 3458893
Change 3464774 by Matt.Kuhlenschmidt
PR #3629: Bugfix: Missing small icon in Project Launcher profile editor (Contributed by aarmbruster)
Change 3464785 by Nick.Darnell
Fixing some clipping stuff in the editor.
Change 3464830 by andrew.porter
QAGame: Second pass on sequencer smoke test map
Change 3464902 by Nick.Darnell
Loading - Adding some additional checks to the the loading code to ensure we're on the main thread. Additionally adding a fix from UDN that prevents deadlocks in the rare case a user hits Alt+Tab in a fullscreen game while in a hard loading screen.
Change 3464988 by Max.Chen
Sequencer: Add attenuation settings for attached audio components.
#jira UE-33080
Change 3465024 by Nick.Darnell
MoviePlayer - Impoving the playback mode displaynames.
Change 3465074 by Arciel.Rekman
Fix shadowing issues of GraphicsPSOInit.
Change 3465097 by Matt.Kuhlenschmidt
Some refactoring of the details panel
Exposed new methods of adding a struct on scope to a details panel and have it work properly with customizations. The scruct on scope has a "fake" ustructproperty that allows the details panel to show the whole struct not just an individual property.
Refactored the API for adding rows to details panels to make it more consistent\
AddChildCustomBuilder->AddCustomBuilder
AddChildGroup->AddGroup
AddChildContent->AddCustomRow
AddChildPropert->AddProperty
AddChildStructure->AddExternalStructureProperty
AddStructure->AddAllExternalStructureProperties
AddExternalProperty->AddExternalObjectProperty or AddExternalStructureProperty
Change 3465186 by Max.Chen
Sequencer: Save the BindingID in the pre animated token producer so that it can be destroyed properly. This fixes a bug where the default state of a spawnable isn't saved.
#jira UE-43780
Change 3465315 by Matt.Kuhlenschmidt
Fix Fortnite and Orion details panel customization warnings
Change 3465424 by Nick.Darnell
Automation - Moving the step for setting the link to the automation reports to be set before we start the engine.
Change 3465488 by Nick.Darnell
Automation - Forcing textures to load before taking screenshot, so that the scene gets another opportunity to render before we render with Slate. This should fix the Blur UI Test.
Change 3466277 by Arciel.Rekman
Linux: fix window drift when dragging (UE-40380).
- Change by Cengiz Terzibas.
Change 3466370 by Nick.Darnell
UMG - Fixing the colors for the resize handle in the designer.
Change 3466372 by Nick.Darnell
UMG - Fixing the ruler ticks sometimes not being drawn.
Change 3466374 by Nick.Darnell
UMG - Fixing the designer showing multiple options for sequencer.
Change 3466377 by Nick.Darnell
UMG - Cleaning up some clipping bits.
Change 3467025 by Andrew.Rodham
Re-saving assets that contain legacy (<4.15) movie scene data to remove deterministic cook warning.
If conflicts arise during merging of these assets, please ignore the changes made in dev-editor, and accept game-side changes.
(CIS step 62283298, jobId 7773146)
(CIS step 62283297, jobId 7773146)
Change 3467099 by Max.Chen
Fix GetObjectPropertyClass ensure logic. This was returning UObject::StaticClass when valid.
Change 3467172 by Max.Chen
Sequencer: Evaluation optimizations. Also, fixes subsequences not getting expired, leaving dangling spawnables.
#jira UE-43690
Change 3467192 by Matt.Kuhlenschmidt
Fix transactions getting stuck in the color grading controls. This prevents PIE from working properly and causes shutdown crashes
#jira UE-45527
Change 3467251 by Yannick.Lange
ViewportInteraction: Fix scale and rotation snap while dragging with two lasers.
#jira UE-43489
Change 3467331 by Matt.Kuhlenschmidt
Fix D3D shader compiler hard coding shader path and not giving proper warnings when it cannot find the shaders
Change 3467335 by Matt.Kuhlenschmidt
Remove DarkStyle attribute from SNumericEntryBox and allow a spin box style to be passed to it.
Change 3467558 by Max.Chen
Scene Outliner: Generic support to add default columns to a scene outliner.
Change 3467565 by Jamie.Dale
Removing old screenshot data for test
Change 3467589 by Nick.Darnell
Editor - Random cleanup.
Change 3467596 by Nick.Darnell
Progress Bar - Exposing Border Padding to UMG.
Change 3467600 by Nick.Darnell
Slate - Adjusting the rendering of the splitter, previously it could be off by a pixel or two, which becomes more apparent now with the clipping changes.
Change 3467601 by Max.Chen
Property Editor: Fix static analysis warning
Change 3467662 by Nick.Darnell
Automation - Fixing a bug with the screenshot comparison tool not replacing (removing) the old screenshot data.
Change 3467674 by Max.Chen
Property Editor: Fix static analysis warning
Change 3467737 by Max.Chen
Sequencer: Added OnMovieSceneBindingsChanged delegate
Change 3468053 by tim.gautier
QAGame: Updating Editor Smoke Map
- Updated landscapes into Stations for testing
- Added Foliage Sublevel
Change 3468194 by Arciel.Rekman
Linux: fix problems communicating with various STL-using libs.
- Stop hiding global new/delete signatures.
- Disable CEF3 since this change uncovers the problem with libcef.so not built to use bundled libpng.
Change 3468678 by Max.Chen
Sequencer: Set "Sequencer Actor" tag before setting the actor label so that the outliner refreshes after the actor has the tag.
Change 3469314 by tim.gautier
QAGame: Added Painted Foliage / Spline section to EditorSmoke map
Change 3469377 by Nick.Darnell
Slate - Fixing some warnings in a couple of sample games due to the clipping changes.
#rnx
Change 3469767 by Max.Chen
Sequencer: Outliner column and sequencer binding data
#jira UE-43470
Change 3469974 by Arciel.Rekman
Fix code projects not working in Linux installed build.
Change 3470082 by Nick.Darnell
Slate - The GetRenderer() call on SlateApplication no longer returns a SharedPtr, rather than convert it to a thread safe ptr, going to just make accessing it a raw ptr return, so it can be safely referenced on the game thread while being used on the slate loading thread.
Change 3470174 by Nick.Darnell
Slate - Get the last widget in a widget path utility.
Change 3470176 by Nick.Darnell
UMG - User Widgets now have an easy way to know if they're part of or have been removed from the focused widget path, which is handy for doing effects.
Change 3470261 by Nick.Darnell
Slate - The GetRenderer() call on SlateApplication no longer returns a SharedPtr, rather than convert it to a thread safe ptr, going to just make accessing it a raw ptr return, so it can be safely referenced on the game thread while being used on the slate loading thread.
Change 3470286 by Max.Chen
Sequencer: Scene Component's HiddenInGame now goes through the VisibilityTrack and the visibility template.
Change 3470366 by Nick.Darnell
Slate - We now version focus per user, that way during focus events, we can safely abort focus events and state transitions if someone interrrupts the active focus event with something new.
Change 3470649 by Matt.Kuhlenschmidt
Fix deprecation warnings
Change 3470695 by Matt.Kuhlenschmidt
Fixed typo
#jira UE-45580
Change 3470721 by Matt.Kuhlenschmidt
Fix static analysis
Change 3471254 by Michael.Dupuis
#jira UE-42952: Keep occlusion result per view
Change 3471287 by Nick.Darnell
UMG - Render Focus Rule now defaults to never.
Change 3471291 by Nick.Darnell
Slate - Fixing FSlateRenderer* change fallout.
Change 3471299 by Nick.Darnell
Slate - Fixing FSlateRenderer* change.
Change 3471323 by Nick.Darnell
Automation - Fixing automation and Static Analysis warning.
Change 3471413 by andrew.porter
QAGame: Added test content for anim blending and material parameteres to sequencer smoke level
Change 3471649 by Max.Chen
Sequencer: Modify the track when adding animation
#jira UE-45618
Change 3471659 by Matt.Kuhlenschmidt
Added a way to check if a movie is playing from the engine.
Prevented viewport redraws for canvas loading screens if a slate based loading movie is playing
Change 3471734 by Matt.Kuhlenschmidt
Added basic material hookup to USD. Similar to FBX it will find materials based on rules specified by the user in the import settings
Change 3472176 by Nick.Darnell
UMG - Improving the display of the +Track menu in sequencer for UMG. Renamed it from +Add, which is repetitve to +Track. Additionally, the dropdown now shows the currently selected widgets, as well as a submenu containing all the 'important' widgets, so we no longer populate that list with a ton of irrelevant widgets that are just Buton_1 - N, which is pointless in showing people, they'll never guess which is the right button.
Change 3472740 by Max.Chen
Sequencer: Add GetThisFrameMetaData accessor
Change 3472748 by Max.Chen
Sequencer: Added OnBeginScrubbing and OnEndScrubbing event delegates
Change 3472753 by Max.Chen
Sequencer: Add EMovieSceneDataChangeType parameter to OnMovieSceneDataChanged delegate
Change 3472870 by Nick.Darnell
Clipping - Fixing the deprecated tip for scissor rect boxes to be correct. Removing it's usage from UT.
Change 3473340 by Max.Chen
Scene Outliner: Add ability to register additional filters
Change 3473348 by Max.Chen
Details View: Make ForceRefresh virtual. Added accessors to delegates (ie. GetIsPropertyReadOnlyDelegate)
Change 3473441 by Max.Chen
Sequencer: Autokey Refactor Part 2.
Autokey is now a single toggleable state.
Allow Edits Mode has 3 states:
Allow All Edits - Allow any edits to occur, some of which may produce tracks/keys or modify default properties.
Allow Sequencer Edits Only - All edits will produce either a track or a key.
Allow Level Edits Only - Properties in the details panel will be disabled if they have a track.
#jira UE-45229
Change 3473670 by Nick.Darnell
Modules - The module manager no longer returns sharedptrs to IModuleInterfaces, this was the source of rare hard to track down crashes due to a shared ptr reference leak when GetModule was called on non-main threads. We now store a TUniquePtr internally, and only lease out raw pointers.
#rn
Change 3473711 by Nick.Darnell
Disabling the ensure in the module manager.
Change 3473747 by Max.Chen
Sequencer: Fix tooltip
Change 3474091 by Jamie.Dale
Added a warning when cooking a UFontFace that is outered to a UFont asset
These cause issues with iterative COTF, and should be split off into their own assets (as the UI has been asking people to do for several versions)
Change 3475052 by Yannick.Lange
VR Editor: Fix Crash when quitting the editor with VR Mode enabled. VR Editor was being enabled when saving the map on closing the editor.
#jira UE-45415
Change 3475054 by Yannick.Lange
Fix crash when adding a camera to the world in VR Mode the second time. The slate application did not reset when stop dragging in VR Mode, so the second time when starting to drag a camera out of the UI it would already by in a dragging state.
#jira UE-45574
Change 3475263 by Nick.Darnell
Fixing some additional cases of IModuleInteface SharedPtr usage.
Change 3475268 by Max.Chen
Sequencer: Set jumped state when looping playback. This fixes an issue where audio doesn't stop and restart when looped.
#jira UE-45654
Change 3475269 by Max.Chen
Scene Outliner: Additional filters should only apply to actor browsing mode
Change 3475407 by Nick.Darnell
Fixing some clipping / module shared ptr changes in the launcher code.
Change 3475542 by Max.Chen
Sequencer: Update thumbnail and section highlighting to use new clipping behavior.
#jira UE-45692
#jira UE-45689
Change 3475743 by Michael.Dupuis
#jira UE-45183: When updating phyx region take into account simple collision mip
Change 3475949 by Arciel.Rekman
Remove PhysX deoptimization (no longer needed).
- OR-24947 has been closed three months ago.
Change 3476022 by Michael.Dupuis
#jira UE-45560: Make sure we're not going out of range
Change 3476063 by Michael.Dupuis
#jira UE-45562: Do not try to unregister from static mesh if no static mesh is specified for the component
Change 3476168 by Michael.Trepka
Added handling of directory symlinks to FApplePlatformFile::IterateDirectory
#jira UE-43704
Change 3476172 by Nick.Darnell
Fixing a Imoduleinterface change.
Change 3476183 by Jamie.Dale
Exposing GoTo/ScrollTo to single-line editable text for API parity with multi-line editable text
Change 3476385 by Arciel.Rekman
Linux: handle symlinks when iterating directories.
Change 3476522 by Michael.Trepka
Solved a problem with Mac FMallocTBB::Malloc() returning nullptr for 0 bytes allocations, which is inconsistent with other platforms. On Mac we always scalable_aligned_malloc, which behaves differently than scalable_malloc, so for 0 bytes requests we allocate sizeof(size_t), which is exactly what scalable_malloc does internally in such case.
Change 3476806 by Nick.Darnell
UMG - Focus the designer after dropping a widget onto the surface.
Change 3476809 by Nick.Darnell
Curve Editor - Enable Clipping on the curve editor.
Change 3477475 by Nick.Darnell
Fixing a module interface shared ptr usage in UT.
Change 3477553 by Yannick.Lange
VR Editor: Removed AssetEditorPanelID and replaced it with TabManagerPanelID. A panel for AssetEditorPanelID was never created making it impossible to open an asset editor.
Change 3477734 by Yannick.Lange
VR Editor: Fix Warning: SetRelativeScale3D : Invalid Scale entered (X=inf Y=inf Z=inf). Resetting to 1.f. warning when adding CineCameraActor to World from Modes Panel. Make sure to not divide by zero when there is no boundary scale.
#jira UE-44933
Change 3477761 by Jamie.Dale
Some improvements to avoid loading the native .locres files twice when we don't need to
Change 3477780 by Nick.Darnell
PR #3250: Return correct VirtualUserIndex (Contributed by projectgheist)
Change 3477786 by Nick.Darnell
PR #3650: Changed TestNull to accept const pointers. (Contributed by e-agaubatz)
Change 3477795 by Nick.Darnell
PR #2844: UE-36936: Don't stretch container for Plugin Image (Contributed by projectgheist)
Change 3478092 by Nick.Darnell
PR #2341: Optional Middle Mouse Button panning in Graph Editor (Contributed by flipswitchingmonkey)
Engine Edit - Made some small changes to the enum type, and some naming.
Change 3478450 by Nick.Darnell
Fixing some uninitialized variable errors.
Change 3479827 by Andrew.Rodham
Sequencer: Addressed serialization issues with some struct types
Change 3479874 by Jamie.Dale
Fixed "NativeGameLanguage" not being used correctly during localization initialization
Change 3480012 by Andrew.Rodham
Sequencer: Fixed loading tagged properties as native for track identifiers
#jira UE-45823
Change 3480337 by Alexis.Matte
Fix morph target crash missing some valid index check
Change 3480804 by Alexis.Matte
Fix crash with ColorGradingMode custom detail
#jira UE-45638
Change 3480892 by Andrew.Rodham
Sequencer: Ensure that movie scene sequences know about the editor object version
#jira UE-45842
Change 3481073 by Nick.Darnell
Fix the shader compiler error from main in Slate.
Change 3481303 by Nick.Darnell
UMG - Fixing a bug with the drag handle not working correctly in HDPI mode.
Change 3481308 by Nick.Darnell
Slate - Tweaking the IsWidgetCulled logic to consider both the layout and rendering bounds. If we do this, we get a much more desireable outcome for people that want to animate widgets and such and plan to have temporary animations to move the widget offscreen, but want the layout bounds to anchor that widget in the visible frame so that it animates even when normally it would be culled b/c the render transform and therefore the renderbounds moved it completely outside the culling rect.
Change 3481629 by Max.Chen
Sequencer: Add Level Sequence Actor as an output for CreateLevelSequencePlayer()
#jira UE-45785
Change 3481899 by Yannick.Lange
VR Editor: Added debug modetoggle command with an event that is broadcasted whenever this happens. Currently this is used to show all the floating UIs of the UI system to debug without HMD using VREd.ForceVRMode.
Change 3481984 by Michael.Dupuis
#jira UE-45845: always validate if we have a static mesh before trying to access it as user can decide to not assign one and use the tools
Change 3482047 by Nick.Darnell
Slate - Adding some comments to IsWidgetCulled.
Change 3482110 by Nick.Darnell
Slate - IsWidgetCulled is no longer static and is now called IsChildWidgetCulled.
Change 3482136 by Jamie.Dale
The CamelCase break iterator now treats digits around character tokens as part of the identifier
Change 3482138 by Michael.Dupuis
#jira UE-45854: Properly unregister during undo operation
Change 3482150 by Michael.Dupuis
#jira UE-45845 : Add missing nullcheck for GetStaticMesh
Change 3482153 by Nick.Darnell
Slate - IsWidgetCulled is no longer static and is now called IsChildWidgetCulled.
Change 3482180 by Nick.Darnell
UMG - Widget Components do not need to define a widget class to be rendererd, they can have native slate widgets only. This was a regression from main.
Change 3482273 by Nick.Darnell
UMG - Tweaking some more things about the widget component box outline.
Change 3482308 by Alexis.Matte
Fixing morph target smooth group support. Do not call FillSkeletalMeshImportData more then once on FbxNode since this fonction is doing some conversion and change the FbxNode, applying those conversion twice do not return the same faces smooth group.
#jira UE-45696
Change 3482327 by Nick.Darnell
UMG - More tweaks to the WidgetComponent so both shows the box outline, but works in game and VR editor.
Change 3482705 by Andrew.Rodham
Resaving assets that contain legacy data to suppress CIS warnings.
- If conflicts arise in these assets, please take game-side changes and ignore these.
Change 3484245 by Max.Chen
Sequencer: Evaluate on end scrub. This fixes a bug where audio doesn't evaluate in a stopped position at the end of scrubbing, causing it to not stop all sounds. This fixes a bug introduced from 3365018 where evaluate on end scrub was removed.
#jira UE-45905
Change 3484263 by Max.Chen
Sequencer: Fix crash on forcing refresh of details panel on release.
#jira UE-45911
Change 3484431 by Andrew.Rodham
Resaving assets that contain legacy data to suppress CIS warnings.
- If conflicts arise in these assets, please take game-side changes and ignore these.
Change 3484474 by Alexis.Matte
Fix the morph target animation curve name matching.
#jira UE-20294
Change 3484475 by Alexis.Matte
When removing a LOD, make sure we remove all morph target data associate to the LOD.
Change 3484489 by Nick.Darnell
PR #3668: UE-45908: Cache debug line locations when performing a LineTraceMulti (Contributed by projectgheist)
#jira UE-45908
Change 3484692 by Nick.Darnell
Slate - Reverting a change from a game stream. All Arranged Children don't need to allocated 42 to begin with. Do need to initialize WidgetPaths better.
Change 3484703 by Nick.Darnell
Player Input - Making the input event loop for players obey EKeys::NUM_TOUCH_KEYS, rather than being set to Touch10, as the maximum touch input amount, to make supporting greater than 10 touches easier. Also making the seeding of keys use EKeys::NUM_TOUCH_KEYS.
#jira UE-43213
Change 3484918 by Jamie.Dale
Fixed font measuring regression with RTL text
RTL applies the character count to the next glyph, so it shouldn't process the end of the loop (this was how the older code used to work).
Change 3485718 by Nick.Darnell
Editor - Removing Super Search & User Feedback button.
Change 3485719 by Nick.Darnell
Portal - Removing SuperSearch.
Change 3485751 by Matt.Kuhlenschmidt
Fix crash accessing platformer game menu if the menu is open during a console based load
#jira UE-45950
Change 3486047 by Arciel.Rekman
Linux: add OpenEXR implementation (UE-40270).
#jira UE-40270
Change 3486467 by Max.Chen
Sequencer: Reset max tick rate when destroyed.
#jira UE-45956
Change 3486477 by Max.Chen
Sequencer: Refresh outliner when column is removed.
#jira UE-45891
Change 3486667 by Andrew.Rodham
Added missing include
Change 3486724 by Andrew.Rodham
Sequencer: Fixed curves with no default value, and no keys being evaluated and applied to properties
- Also fixed an edge case where a zero (but non-animated) channel could be applied to a final transform
Change 3486730 by Alexis.Matte
In the Auto-Reimport options, hide the mout point only for the default /Game/ folder
#UE-45684
Change 3486749 by Alexis.Matte
Make sure the parent window of the monitor directory browse folder is set properly
#jira UE-45682
Change 3486805 by Matt.Kuhlenschmidt
Additional safety against invalid objects being accessed by slate
Change 3486848 by Alexis.Matte
Make sure Monitor folder feature support root mount point map folder
During auto import, give priority to asset import factory over the scene import factory
#jira UE-45691
Change 3486879 by Andrew.Rodham
Removing obsolete QA assets
Change 3486950 by Nick.Darnell
PR #2281: Scrollbar missing features and SScrollbar fixes (Contributed by SNikon)
Review - made some adjustments from the original.
Change 3486954 by Nick.Darnell
Slate - Moving the STableViewBase over to the FOverscroll class, rather than it's own clone.
Change 3486967 by Nick.Darnell
Slate - Fixing some HDPI calculations for fitting new windows on screen, it was using the unscaled size of the widgets for fitting, when it needed to scale them up.
Change 3486970 by Andrew.Rodham
Sequencer: Delay mouse capture until drag for sequencer time slider
- Fixes context menus not opening as a result of mouse capture being taken on mouse down
#jira UE-45937
Change 3486984 by Andrew.Rodham
Sequencer: Improved blending type iconography
Change 3486996 by Nick.Darnell
UMG - Adding a way for games to opt-out of the slow widget path, to completely prevent them from being cooked.
UMG - The movie data is no longer cloned for each new instance that inhabits. It now keeps a reference to the now publically accessible movie scene data on the class instead.
Change 3487070 by Andrew.Rodham
Sequencer: Added graphics for key areas that represent empty space
Change 3487195 by Andrew.Rodham
Sequencer: Changed evaluation groups to always flush implicitly
- Due to the latent nature of blended token types, it's no longer safe to rely solely on execution token order between tracks
- This fixes an issue where events set in the PostEvaluation stage were executed before blended token actuation
Change 3487322 by Nick.Darnell
PR #2457: Add .gitdeps.xml-files for plugins support (Contributed by bozaro)
Change 3487363 by Nick.Darnell
PR #2481: Fix for packing of a project with users plugins (Contributed by yatagarasu25)
Change 3487439 by Nick.Darnell
PR #2642: Changed private to protected in SVirtualJoystick.h (Contributed by Skylonxe)
Change 3487500 by Arciel.Rekman
Removed LinuxNativeDialogs.
- No longer used; has been superceded by SlateDialogs since UE 4.8 (2 years ago).
Change 3487630 by Lauren.Ridge
Don't create Landscape Info Maps for Editor Preview Worlds or thumbnail worlds
#jira UE-44885
Change 3487864 by Matt.Kuhlenschmidt
Exposed the asset registry to blueprints and script. Works in editor scripts and runtime scripts
AssetRegistry is now a UInterface object.
Blueprint users can access various asset registry methods using the asset registry interface (via GetAssetRegistry) and various static helpers in the AssetRegistryHelpers object
C++ users should still continue to use IAssetRegistry.
Change 3487879 by Matt.Kuhlenschmidt
Renamed asset tools uobject helper to UAssetToolsHelpers
Change 3487926 by Lauren.Ridge
Fixing reset to default not showing up for custom widgets
#jira UE-44164
Change 3488184 by Matt.Kuhlenschmidt
PR #3656: Make References/Referencers List copyable (Contributed by user37337)
#jira UE-45763
Change 3488240 by Matt.Kuhlenschmidt
Fix compiler issue
Change 3488350 by Lauren.Ridge
Landscape info map transactional state is based on its world's transactional state
#jira UE-44885
#jira UE-46019
Change 3488412 by Matt.Kuhlenschmidt
Fix reset to default showing up in two different places for some customizations
Change 3488413 by Matt.Kuhlenschmidt
Fix slate font customization
Change 3488414 by Matt.Kuhlenschmidt
Fix slate font customization
Change 3488415 by Matt.Kuhlenschmidt
Missed file
Change 3488565 by Arciel.Rekman
Add pretty printers for gdb (UETOOL-1171).
- Committing shelf by Cengiz.Terzibas, with some modifications.
#jira UETOOL-1171
Change 3489094 by Nick.Darnell
Slate - The Slate RHI Renderer now caches the TextureLODGroups so that it can properly lookup the filtering of different texture groups that are set to Default, instead of a particular filter override on a texture.
Engine/Rendering - Simplifying some of the setup logic in TextureLODSettings so that code is shared for setting them up properly after loading from a config file.
Change 3489095 by Nick.Darnell
PR #2699: GameViewportClient - Added a method to allow setting the viewport cur. (Contributed by rfenner)
Review - Fixed spacing.
Change 3489108 by Matt.Kuhlenschmidt
Fix deprecation warning
Change 3489120 by Nick.Darnell
PR #3478: Fix possible UComboBoxString crash (Contributed by nakosung)
Change 3489147 by Andrew.Rodham
Sequencer: Adding return value to function to appease static analysis
- This function is never compiled, and if it is, it won't compile, but static analysis doesn't know that
Change 3489264 by Nick.Darnell
Testing - Finishing the thought behind an enum comment.
Change 3489265 by Nick.Darnell
PR #2750: UE-35164: Button padding (Contributed by projectgheist)
Change 3489267 by Nick.Darnell
PR #3645: UE-45464: Handle SSlider mouse interaction more accurately (Contributed by projectgheist)
Change 3489632 by Arciel.Rekman
Correctness changes to MallocPoisonProxy.
- Missing forwarding functions added. Incorrect comment removed.
- Change by Steve.Robb, doing here so it is in 4.17.
Change 3489689 by Arciel.Rekman
More MallocPoisonProxy changes I missed in previous CL.
Change 3489751 by Matt.Kuhlenschmidt
Moved editor performance settings out of per-project settings so they can be shared across projects
Change 3489837 by Lauren.Ridge
Keyboard shortcut for entering/leaving VR Mode is now Alt+V
Change 3491082 by Arciel.Rekman
Linux: better fix for the crash due to name collision (UE-46040).
- Put classes in Sequencer module into Sequencer namespace instead of SceneOutliner namespace.
- Undid change in the SceneOutliner module.
#jira UE-46040
Change 3491096 by Arciel.Rekman
Fix UAT compilation on the newest mono.
Change 3491240 by Max.Chen
Sequencer: Disable key button when allow level edits only is on.
#jira UE-46060
Change 3491406 by Yannick.Lange
Fix editor crashes when opening a project that includes a plugin with more than two custom Volume classes. This issue was caused because registering show volume commands is based on finding volume classes. Finding these classes at multiple times resulted in a mismatch of the returned array of volume classes because modules/plugins were still being loaded.
#jira UE-45806
Change 3491559 by Alexis.Matte
Make sure we use the good preview mesh when doing a preview
#jira UE-45963
Change 3491563 by Alexis.Matte
Fix crash with staticmesh editor LodLevel selection
Change 3491564 by Nick.Darnell
UMG - Fixing an offset with the grab handles in HDPI mode.
Change 3491595 by Nick.Darnell
Editor - Fixing a clipping artifact in the pin type dropdown in the blueprint editor.
Change 3491604 by Nick.Darnell
Back out changelist 3489265
Change 3491615 by Arciel.Rekman
Added malloc replay proxy (Linux only for now).
- Allows to dump malloc callstream (without regard to threads) and replay later to study the behavior of different mallocs and/or repro problems.
Change 3491684 by Arciel.Rekman
Added FMalloc functions I missed.
- Also moved function bodies into the .cpp file, this does not make a difference in performance in this case.
Change 3491692 by Matt.Kuhlenschmidt
Some minor fixes to the static mesh editor
- Fix UV combo button looking non-standard on the toolbar
- Fix a few combo buttons in the details panel looking too big.
Change 3491702 by Arciel.Rekman
Do not compile replay proxy-specific code when not used.
Change 3491717 by Michael.Dupuis
#jira UE-35083:
The component is now the owner of the PerInstanceRenderData instead of the proxy
Add an Update path to only update specified instances range
Always call BuildTreeIfOutdated so we have a standard code path to make sure static mesh are fully loaded before trying to build the tree
Moved the Instance Buffer aysnc to the base class, as it's not related to UHierarchicalInstancedStaticMeshComponent
Expose a new property to decide if we require dynamic instance buffer
Change 3491758 by Matt.Kuhlenschmidt
Fix crash on static mesh editor shutdown
Change 3491873 by Cody.Albert
Fixed clipping issue in Sequencer curve editor
#rnx
Change 3491956 by Matt.Kuhlenschmidt
Fix crash opening the Previewing sub-menu in the level editor settings menu
#jira UE-46095
Change 3492046 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492076 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492165 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492222 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492274 by Michael.Dupuis
#jira UE-46105: Fixed Clang warning
Change 3492338 by andrew.porter
QAGame: Testing ensure when submitting
Change 3492371 by Nick.Darnell
UMG - Reverting the animation sharing, cossed GLEO regressions in cooking. Will look for a better solution.
Change 3492462 by Matt.Kuhlenschmidt
Fix ensure checking in files through perforce
Change 3492491 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492505 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492517 by Jamie.Dale
The package localization ID is no longer used at all at runtime, and is now truly editor-only
This should have always been the case, but it was leaked into manifest/archives/PO files in 4.14, and while 4.15 removed it from PO files it was still present in the manifest/archives. This change removes it entirely (unless gathering editor-only data, and even then the PO file will still collapse the entries together for translation), and the deprecated 4.14 export behavior will now produce an error if you attempt to use it.
After taking this change you'll need to run a gather, import, and compile of your LocRes files to update your game localization to use the new localization IDs.
Change 3492630 by Nick.Darnell
UMG - Removing some extra cleanup code that's probably overkill and is causing a crash for uses of "Within" in class meta.
#jira UE-46124
Change 3492692 by Matt.Kuhlenschmidt
Fix drop shadows inheriting the outline color of the font. The outline should still appear but not have a different outline color from fill color
Change 3492714 by Matt.Kuhlenschmidt
Added outline with drop shadow to font automation test
Change 3492737 by Matt.Kuhlenschmidt
Fix linux
Change 3492992 by tim.gautier
Resaving Ocean Widget Blueprints / Sequences to resolve Legacy Sequence Data warnings
#jira UE-46132
Change 3493089 by Jamie.Dale
Ensure that the composite font of a font asset is flushed when the font object is GC'd
Change 3493322 by Jamie.Dale
Fixing null crash
#jira UE-45758
Change 3494467 by Andrew.Rodham
Fix Xbox warning
Change 3494852 by tim.gautier
QAGame: Changed streaming method of QA-EditorSmoke-Landscape to Always Loaded
Change 3494853 by Nick.Darnell
Another attempt at fixing the automation blueprint SA warning.
Change 3494896 by Arciel.Rekman
Fix possible null pointer access during Vulkan init.
- May fix static analysis warnings in UE-46142, although warnings seem to be referring to something else.
#jira UE-46142
Change 3494987 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3495010 by Matt.Kuhlenschmidt
Adding additional logging to track down html5 issue
Change 3495212 by Michael.Dupuis
#jira UE-46143: Properly init the InstanceRenderData during the cooking phase (required by fortnite)
Change 3495536 by Jamie.Dale
Updating UGameEngine to call its Super::PreExit after performing its own teardown
This prevents UEngine cleaning up resources that UGameEngine still needs.
#jira UE-46159
Change 3495551 by Arciel.Rekman
Another attempt to fix analyzer problem (UE-46142).
Change 3495794 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3495905 by Matt.Kuhlenschmidt
Fix USD crash when importing a meshwith no material
[CL 3499771 by Matt Kuhlenschmidt in Main branch]
2017-06-19 20:27:30 -04:00
# include "Animation/MorphTarget.h"
2021-03-09 09:40:13 -04:00
# include "UObject/GarbageCollection.h"
2017-10-13 11:32:28 -04:00
# include "Rendering/SkeletalMeshModel.h"
2018-02-22 11:25:06 -05:00
# include "Rendering/SkeletalMeshLODModel.h"
# include "GenericQuadTree.h"
# include "Engine/SkeletalMesh.h"
2022-04-26 12:53:38 -04:00
# include "Engine/SkeletalMeshSocket.h"
2018-11-16 11:15:08 -05:00
# include "EditorFramework/AssetImportData.h"
2014-03-14 14:13:41 -04:00
# include "MeshUtilities.h"
2020-04-22 10:41:35 -04:00
# include "MeshUtilitiesCommon.h"
2019-10-02 17:27:26 -04:00
# include "ClothingAsset.h"
2019-09-10 11:35:20 -04:00
# include "OverlappingCorners.h"
# include "Framework/Commands/UIAction.h"
2020-02-12 12:41:49 -05:00
# include "HAL/ThreadSafeBool.h"
2022-03-15 18:29:37 -04:00
# include "ImageCore.h"
# include "ImageCoreUtils.h"
2014-03-14 14:13:41 -04:00
2019-05-09 06:20:31 -04:00
# include "ObjectTools.h"
2014-06-18 07:25:31 -04:00
# include "ComponentReregisterContext.h"
2017-06-21 10:25:35 -04:00
# include "IMeshReductionManagerModule.h"
2019-05-09 06:20:31 -04:00
# include "Animation/SkinWeightProfile.h"
2019-10-14 09:26:02 -04:00
# include "Async/ParallelFor.h"
2021-03-18 15:20:03 -04:00
# include "Interfaces/ITargetPlatform.h"
# include "Interfaces/ITargetPlatformManagerModule.h"
# include "Misc/CoreMisc.h"
2014-06-18 07:25:31 -04:00
2022-04-26 12:53:38 -04:00
# include "Framework/Notifications/NotificationManager.h"
# include "Widgets/Notifications/SNotificationList.h"
2019-09-10 11:35:20 -04:00
IMPLEMENT_MODULE ( FDefaultModuleImpl , SkeletalMeshUtilitiesCommon )
2019-04-15 10:23:09 -04:00
2019-07-12 00:17:17 -04:00
# define LOCTEXT_NAMESPACE "LODUtilities"
2019-04-15 10:23:09 -04:00
2018-05-23 21:04:31 -04:00
DEFINE_LOG_CATEGORY_STATIC ( LogLODUtilities , Log , All ) ;
2019-09-10 11:35:20 -04:00
/**
* Process and update the vertex Influences using the predefined wedges
*
* @ param WedgeCount - The number of wedges in the corresponding mesh .
* @ param Influences - BoneWeights and Ids for the corresponding vertices .
*/
2020-10-29 13:38:15 -04:00
void FLODUtilities : : ProcessImportMeshInfluences ( const int32 WedgeCount , TArray < SkeletalMeshImportData : : FRawBoneInfluence > & Influences , const FString & MeshName )
2019-09-10 11:35:20 -04:00
{
// Sort influences by vertex index.
struct FCompareVertexIndex
{
bool operator ( ) ( const SkeletalMeshImportData : : FRawBoneInfluence & A , const SkeletalMeshImportData : : FRawBoneInfluence & B ) const
{
if ( A . VertexIndex > B . VertexIndex ) return false ;
else if ( A . VertexIndex < B . VertexIndex ) return true ;
else if ( A . Weight < B . Weight ) return false ;
else if ( A . Weight > B . Weight ) return true ;
else if ( A . BoneIndex > B . BoneIndex ) return false ;
else if ( A . BoneIndex < B . BoneIndex ) return true ;
else return false ;
}
} ;
Influences . Sort ( FCompareVertexIndex ( ) ) ;
TArray < SkeletalMeshImportData : : FRawBoneInfluence > NewInfluences ;
int32 LastNewInfluenceIndex = 0 ;
int32 LastVertexIndex = INDEX_NONE ;
int32 InfluenceCount = 0 ;
float TotalWeight = 0.f ;
const float MINWEIGHT = 0.01f ;
int MaxVertexInfluence = 0 ;
float MaxIgnoredWeight = 0.0f ;
//We have to normalize the data before filtering influences
//Because influence filtering is base on the normalize value.
//Some DCC like Daz studio don't have normalized weight
for ( int32 i = 0 ; i < Influences . Num ( ) ; i + + )
{
// if less than min weight, or it's more than 8, then we clear it to use weight
InfluenceCount + + ;
TotalWeight + = Influences [ i ] . Weight ;
// we have all influence for the same vertex, normalize it now
if ( i + 1 > = Influences . Num ( ) | | Influences [ i ] . VertexIndex ! = Influences [ i + 1 ] . VertexIndex )
{
// Normalize the last set of influences.
if ( InfluenceCount & & ( TotalWeight ! = 1.0f ) )
{
float OneOverTotalWeight = 1.f / TotalWeight ;
for ( int r = 0 ; r < InfluenceCount ; r + + )
{
Influences [ i - r ] . Weight * = OneOverTotalWeight ;
}
}
if ( MaxVertexInfluence < InfluenceCount )
{
MaxVertexInfluence = InfluenceCount ;
}
// clear to count next one
InfluenceCount = 0 ;
TotalWeight = 0.f ;
}
if ( InfluenceCount > MAX_TOTAL_INFLUENCES & & Influences [ i ] . Weight > MaxIgnoredWeight )
{
MaxIgnoredWeight = Influences [ i ] . Weight ;
}
}
// warn about too many influences
if ( MaxVertexInfluence > MAX_TOTAL_INFLUENCES )
{
2020-10-29 13:38:15 -04:00
UE_LOG ( LogLODUtilities , Display , TEXT ( " Skeletal mesh (%s) influence count of %d exceeds max count of %d. Influence truncation will occur. Maximum Ignored Weight %f " ) , * MeshName , MaxVertexInfluence , MAX_TOTAL_INFLUENCES , MaxIgnoredWeight ) ;
2019-09-10 11:35:20 -04:00
}
for ( int32 i = 0 ; i < Influences . Num ( ) ; i + + )
{
// we found next verts, normalize it now
if ( LastVertexIndex ! = Influences [ i ] . VertexIndex )
{
// Normalize the last set of influences.
if ( InfluenceCount & & ( TotalWeight ! = 1.0f ) )
{
float OneOverTotalWeight = 1.f / TotalWeight ;
for ( int r = 0 ; r < InfluenceCount ; r + + )
{
NewInfluences [ LastNewInfluenceIndex - r ] . Weight * = OneOverTotalWeight ;
}
}
// now we insert missing verts
if ( LastVertexIndex ! = INDEX_NONE )
{
int32 CurrentVertexIndex = Influences [ i ] . VertexIndex ;
for ( int32 j = LastVertexIndex + 1 ; j < CurrentVertexIndex ; j + + )
{
// Add a 0-bone weight if none other present (known to happen with certain MAX skeletal setups).
LastNewInfluenceIndex = NewInfluences . AddUninitialized ( ) ;
NewInfluences [ LastNewInfluenceIndex ] . VertexIndex = j ;
NewInfluences [ LastNewInfluenceIndex ] . BoneIndex = 0 ;
NewInfluences [ LastNewInfluenceIndex ] . Weight = 1.f ;
}
}
// clear to count next one
InfluenceCount = 0 ;
TotalWeight = 0.f ;
LastVertexIndex = Influences [ i ] . VertexIndex ;
}
// if less than min weight, or it's more than 8, then we clear it to use weight
if ( Influences [ i ] . Weight > MINWEIGHT & & InfluenceCount < MAX_TOTAL_INFLUENCES )
{
LastNewInfluenceIndex = NewInfluences . Add ( Influences [ i ] ) ;
InfluenceCount + + ;
TotalWeight + = Influences [ i ] . Weight ;
}
}
Influences = NewInfluences ;
// Ensure that each vertex has at least one influence as e.g. CreateSkinningStream relies on it.
// The below code relies on influences being sorted by vertex index.
if ( Influences . Num ( ) = = 0 )
{
// warn about no influences
2020-10-29 13:38:15 -04:00
UE_LOG ( LogLODUtilities , Warning , TEXT ( " Warning skeletal mesh (%s) has no vertex influences " ) , * MeshName ) ;
2019-09-10 11:35:20 -04:00
// add one for each wedge entry
Influences . AddUninitialized ( WedgeCount ) ;
for ( int32 WedgeIdx = 0 ; WedgeIdx < WedgeCount ; WedgeIdx + + )
{
Influences [ WedgeIdx ] . VertexIndex = WedgeIdx ;
Influences [ WedgeIdx ] . BoneIndex = 0 ;
Influences [ WedgeIdx ] . Weight = 1.0f ;
}
for ( int32 i = 0 ; i < Influences . Num ( ) ; i + + )
{
int32 CurrentVertexIndex = Influences [ i ] . VertexIndex ;
if ( LastVertexIndex ! = CurrentVertexIndex )
{
for ( int32 j = LastVertexIndex + 1 ; j < CurrentVertexIndex ; j + + )
{
// Add a 0-bone weight if none other present (known to happen with certain MAX skeletal setups).
Influences . InsertUninitialized ( i , 1 ) ;
Influences [ i ] . VertexIndex = j ;
Influences [ i ] . BoneIndex = 0 ;
Influences [ i ] . Weight = 1.f ;
}
LastVertexIndex = CurrentVertexIndex ;
}
}
}
}
2021-03-18 15:20:03 -04:00
bool FLODUtilities : : RegenerateLOD ( USkeletalMesh * SkeletalMesh , const ITargetPlatform * TargetPlatform , int32 NewLODCount /*= 0*/ , bool bRegenerateEvenIfImported /*= false*/ , bool bGenerateBaseLOD /*= false*/ )
2018-02-22 11:25:06 -05:00
{
if ( SkeletalMesh )
{
2019-10-01 20:41:42 -04:00
FScopedSkeletalMeshPostEditChange ScopedPostEditChange ( SkeletalMesh ) ;
2019-04-15 10:23:09 -04:00
// Unbind any existing clothing assets before we regenerate all LODs
TArray < ClothingAssetUtils : : FClothingAssetMeshBinding > ClothingBindings ;
2019-10-01 20:41:42 -04:00
FLODUtilities : : UnbindClothingAndBackup ( SkeletalMesh , ClothingBindings ) ;
2019-04-15 10:23:09 -04:00
2018-02-22 11:25:06 -05:00
int32 LODCount = SkeletalMesh - > GetLODNum ( ) ;
if ( NewLODCount > 0 )
{
LODCount = NewLODCount ;
}
SkeletalMesh - > Modify ( ) ;
FSkeletalMeshUpdateContext UpdateContext ;
UpdateContext . SkeletalMesh = SkeletalMesh ;
2020-03-05 09:15:06 -05:00
//If we force a regenerate, we want to invalidate the DCC so the render data get rebuilded
SkeletalMesh - > InvalidateDeriveDataCacheGUID ( ) ;
2018-02-22 11:25:06 -05:00
// remove LODs
int32 CurrentNumLODs = SkeletalMesh - > GetLODNum ( ) ;
if ( LODCount < CurrentNumLODs )
{
for ( int32 LODIdx = CurrentNumLODs - 1 ; LODIdx > = LODCount ; LODIdx - - )
{
FLODUtilities : : RemoveLOD ( UpdateContext , LODIdx ) ;
}
}
// we need to add more
else if ( LODCount > CurrentNumLODs )
{
2019-10-14 09:26:02 -04:00
// Only create new skeletal mesh LOD level entries, we cannot multi thread since the LOD will be create here
//TArray are not thread safe.
2018-02-22 11:25:06 -05:00
for ( int32 LODIdx = CurrentNumLODs ; LODIdx < LODCount ; LODIdx + + )
{
// if no previous setting found, it will use default setting.
2021-03-18 15:20:03 -04:00
FLODUtilities : : SimplifySkeletalMeshLOD ( UpdateContext , LODIdx , TargetPlatform , false ) ;
2018-02-22 11:25:06 -05:00
}
}
else
{
2018-11-16 11:15:08 -05:00
for ( int32 LODIdx = 0 ; LODIdx < LODCount ; LODIdx + + )
2018-02-22 11:25:06 -05:00
{
FSkeletalMeshLODInfo & CurrentLODInfo = * ( SkeletalMesh - > GetLODInfo ( LODIdx ) ) ;
2018-11-16 11:15:08 -05:00
if ( ( bRegenerateEvenIfImported & & LODIdx > 0 ) | | ( bGenerateBaseLOD & & LODIdx = = 0 ) | | CurrentLODInfo . bHasBeenSimplified )
2018-02-22 11:25:06 -05:00
{
2021-03-18 15:20:03 -04:00
FLODUtilities : : SimplifySkeletalMeshLOD ( UpdateContext , LODIdx , TargetPlatform , false ) ;
2018-02-22 11:25:06 -05:00
}
}
}
2019-04-15 10:23:09 -04:00
//Restore all clothing we can
2019-10-01 20:41:42 -04:00
FLODUtilities : : RestoreClothingFromBackup ( SkeletalMesh , ClothingBindings ) ;
2018-02-22 11:25:06 -05:00
return true ;
}
return false ;
}
2020-09-24 00:43:27 -04:00
namespace RemoveLODHelper
{
void GetDependentLODs ( USkeletalMesh * SkeletalMesh , const int32 RefLODIndex , TArray < int32 > & DependentLODs )
{
if ( ! SkeletalMesh | | RefLODIndex > = SkeletalMesh - > GetLODNum ( ) - 1 )
{
return ;
}
int32 LODCount = SkeletalMesh - > GetLODNum ( ) ;
FSkeletalMeshModel * SkelMeshModel = SkeletalMesh - > GetImportedModel ( ) ;
for ( int32 LODIndex = RefLODIndex + 1 ; LODIndex < LODCount ; + + LODIndex )
{
if ( ! SkeletalMesh - > IsReductionActive ( LODIndex ) )
{
continue ;
}
const FSkeletalMeshLODInfo * LODInfo = SkeletalMesh - > GetLODInfo ( LODIndex ) ;
if ( ! LODInfo )
{
continue ;
}
if ( LODInfo - > ReductionSettings . BaseLOD = = RefLODIndex )
{
DependentLODs . Add ( LODIndex ) ;
}
}
}
void AdjustReductionSettings ( USkeletalMesh * SkeletalMesh , const int32 DestinationLODIndex , const int32 SourceLODIndex )
{
FSkeletalMeshLODInfo * DestinationLODInfo = SkeletalMesh - > GetLODInfo ( DestinationLODIndex ) ;
const FSkeletalMeshLODInfo * SourceLODInfo = SkeletalMesh - > GetLODInfo ( SourceLODIndex ) ;
if ( ! DestinationLODInfo | | ! SourceLODInfo )
{
return ;
}
//Adjust percent so we end up with the same amount.
DestinationLODInfo - > ReductionSettings . NumOfTrianglesPercentage / = SourceLODInfo - > ReductionSettings . NumOfTrianglesPercentage ;
DestinationLODInfo - > ReductionSettings . NumOfVertPercentage / = SourceLODInfo - > ReductionSettings . NumOfVertPercentage ;
}
} //End namspace RemoveLODHelper
2014-03-14 14:13:41 -04:00
void FLODUtilities : : RemoveLOD ( FSkeletalMeshUpdateContext & UpdateContext , int32 DesiredLOD )
{
USkeletalMesh * SkeletalMesh = UpdateContext . SkeletalMesh ;
2017-10-13 11:32:28 -04:00
FSkeletalMeshModel * SkelMeshModel = SkeletalMesh - > GetImportedModel ( ) ;
2014-03-14 14:13:41 -04:00
2020-09-24 00:43:27 -04:00
if ( SkelMeshModel - > LODModels . Num ( ) < = 1 )
2014-03-14 14:13:41 -04:00
{
2020-09-24 00:43:27 -04:00
if ( ! FApp : : IsUnattended ( ) )
{
FMessageDialog : : Open ( EAppMsgType : : Ok , NSLOCTEXT ( " UnrealEd " , " NoLODToRemove " , " No LODs to remove! " ) ) ;
}
UE_LOG ( LogLODUtilities , Warning , TEXT ( " Cannot remove LOD {0}, there must be at least one LOD after the removal. " ) , DesiredLOD ) ;
2014-03-14 14:13:41 -04:00
return ;
}
2018-02-22 11:25:06 -05:00
check ( SkeletalMesh - > GetLODNum ( ) = = SkelMeshModel - > LODModels . Num ( ) ) ;
2014-03-14 14:13:41 -04:00
2020-09-24 00:43:27 -04:00
// If its a valid LOD, remove it.
if ( DesiredLOD < SkelMeshModel - > LODModels . Num ( ) )
2014-03-14 14:13:41 -04:00
{
2019-10-01 20:41:42 -04:00
FScopedSkeletalMeshPostEditChange ScopedPostEditChange ( SkeletalMesh ) ;
2014-03-14 14:13:41 -04:00
2020-09-24 00:43:27 -04:00
//Get the dependent generated LODs
TArray < int32 > DependentLODs ;
RemoveLODHelper : : GetDependentLODs ( SkeletalMesh , DesiredLOD , DependentLODs ) ;
2014-03-14 14:13:41 -04:00
2020-09-24 00:43:27 -04:00
//Adjust LODInfo properties to be in sync with the LOD removal. We reverse iterate because we want to restore some LOD info property from the previous LOD
for ( int32 NextLODIndex = SkeletalMesh - > GetLODNum ( ) - 1 ; NextLODIndex > DesiredLOD ; NextLODIndex - - )
2014-03-14 14:13:41 -04:00
{
2020-09-24 00:43:27 -04:00
const FSkeletalMeshLODInfo * PreviousLODInfo = SkeletalMesh - > GetLODInfo ( NextLODIndex - 1 ) ;
FSkeletalMeshLODInfo * NextLODInfo = SkeletalMesh - > GetLODInfo ( NextLODIndex ) ;
if ( ! NextLODInfo )
2014-03-14 14:13:41 -04:00
{
2020-09-24 00:43:27 -04:00
continue ;
}
//Adjust the reduction baseLOD
if ( SkeletalMesh - > IsReductionActive ( NextLODIndex ) & & NextLODInfo - > ReductionSettings . BaseLOD > DesiredLOD )
{
NextLODInfo - > ReductionSettings . BaseLOD - - ;
}
//Propagate someproperties we need to take from the previous LOD
if ( PreviousLODInfo )
{
//Screen size
NextLODInfo - > ScreenSize = PreviousLODInfo - > ScreenSize ;
}
}
//Adjust the imported data so it point on the correct LOD index
if ( DependentLODs . Num ( ) > 0 & & ! SkeletalMesh - > IsLODImportedDataEmpty ( DesiredLOD ) )
{
int32 FirstDepLODIndex = DependentLODs [ 0 ] ;
FSkeletalMeshLODInfo * FirstDepLODInfo = SkeletalMesh - > GetLODInfo ( FirstDepLODIndex ) ;
if ( FirstDepLODInfo )
{
FSkeletalMeshImportData ToRemovedLODImportData ;
SkeletalMesh - > LoadLODImportedData ( DesiredLOD , ToRemovedLODImportData ) ;
//Override imported data with the original source imported data (we are depending on the LOD we want to removed)
SkeletalMesh - > SaveLODImportedData ( FirstDepLODIndex , ToRemovedLODImportData ) ;
//Manage the override original reduction source mesh data
2021-09-21 16:06:32 -04:00
if ( SkelMeshModel - > InlineReductionCacheDatas . IsValidIndex ( FirstDepLODIndex ) )
2020-09-24 00:43:27 -04:00
{
if ( SkeletalMesh - > IsLODImportedDataBuildAvailable ( DesiredLOD ) )
{
2021-09-21 16:06:32 -04:00
//The inline reduction cache data will be recache by the build
SkelMeshModel - > InlineReductionCacheDatas [ FirstDepLODIndex ] . SetCacheGeometryInfo ( MAX_uint32 , MAX_uint32 ) ;
2020-09-24 00:43:27 -04:00
}
2021-09-21 16:06:32 -04:00
else if ( SkelMeshModel - > InlineReductionCacheDatas . IsValidIndex ( DesiredLOD ) )
2020-09-24 00:43:27 -04:00
{
//If there is no build copy the one from the DesiredLOD
2021-09-21 16:06:32 -04:00
uint32 CacheVertexCount = 0 ;
uint32 CacheTriangleCount = 0 ;
SkelMeshModel - > InlineReductionCacheDatas [ DesiredLOD ] . GetCacheGeometryInfo ( CacheVertexCount , CacheTriangleCount ) ;
SkelMeshModel - > InlineReductionCacheDatas [ FirstDepLODIndex ] . SetCacheGeometryInfo ( CacheVertexCount , CacheTriangleCount ) ;
2020-09-24 00:43:27 -04:00
}
}
//Adjust Reduction settings
FirstDepLODInfo - > ReductionSettings . BaseLOD = FirstDepLODIndex - 1 ;
RemoveLODHelper : : AdjustReductionSettings ( SkeletalMesh , FirstDepLODIndex , DesiredLOD ) ;
//Do the adjustment for the other dependent LODs
for ( int32 DependentLODsIndex = 1 ; DependentLODsIndex < DependentLODs . Num ( ) ; + + DependentLODsIndex )
{
int32 DepLODIndex = DependentLODs [ DependentLODsIndex ] ;
FSkeletalMeshLODInfo * DepLODInfo = SkeletalMesh - > GetLODInfo ( DepLODIndex ) ;
if ( ! DepLODInfo )
{
continue ;
}
//Adjust Reduction settings
DepLODInfo - > ReductionSettings . BaseLOD = FirstDepLODIndex - 1 ;
RemoveLODHelper : : AdjustReductionSettings ( SkeletalMesh , DepLODIndex , FirstDepLODIndex ) ;
}
2014-03-14 14:13:41 -04:00
}
}
Copying //UE4/Dev-Editor to //UE4/Dev-Main (Source: //UE4/Dev-Editor @ 3497164)
#lockdown Nick.Penwarden
#rb none
=====================================
MAJOR FEATURES + CHANGES
=====================================
Change 3433074 by Matt.Kuhlenschmidt
Fix crash when clicking on certian tutorial blueprints.
#jira UE-44593
Change 3433075 by Matt.Kuhlenschmidt
Remove hittest grid log spam. The underlying problem causing this has been fixed
Change 3433077 by Matt.Kuhlenschmidt
Fix lighting becoming unbuilt when mesh painting
#jira UE-44837
Change 3433081 by Matt.Kuhlenschmidt
PR #3553: Crashfix for static array properties (Contributed by Pierdek)
Change 3433104 by Alexis.Matte
Make sure re-import skeletal mesh follow the import morph option
#jira UE-42846
Change 3434825 by Matt.Kuhlenschmidt
Fix crash when GC happens while the vr editor radial menu is open.
Change 3434831 by Matt.Kuhlenschmidt
Added missing file
Change 3434868 by Shaun.Kime
If you have a reroute node between a Material Function texture input and its usage, the parent material will fail to resolve the reroute node.
#jira ue-44670
Change 3434998 by Alexis.Matte
Meshes editors material/section panel are now fully transactional
- Staticmesh editor: section material slot, section cast shadow, section collision, material slot instance, material slot name
- Skeletal mesh editor: material slot instance, material slot name
Also fix some transaction description
#jira UE-44462
Change 3435195 by Jamie.Dale
Fixed incorrect handling of some LTR scripts that require shaping
These scripts need to go through HarfBuzz, and this also fixes a case where HarfBuzz wasn't applying font scale correctly.
#jira UE-44767
Change 3435199 by Jamie.Dale
Fixed some crashes/artifacts with bidirectional text
It was possible for a line to compute an incorrect range, which could cause crashes or other highlighting issues. The highlighting logic has also been updated as the old code didn't handle all bidirectional cases correctly.
Change 3435200 by Jamie.Dale
Fixed a grapheme cluster metrics issue in the font editor viewport
The viewport also now respects the default shaping method CVar.
Change 3435771 by Alexis.Matte
Fix degenerated bounds calculation for skeletalmesh when the skeleton is remove from a re-import
(PhysicAsset API change, adding 1 function)
#jira UE-44609
Change 3436856 by Jamie.Dale
Added some missing Unicode block ranges
Change 3436914 by Jamie.Dale
Adding some missing combining character ranges to the text shaper
Change 3436923 by Alexis.Matte
PR #3463: Get bounds for all triangles, not just the first one. WedgeIndex was . (Contributed by DaveC79)
#jira UE-43764
Change 3436948 by Jamie.Dale
Updated the Portal to use the predefined Unicode block ranges
Change 3436961 by Max.Chen
Sequencer: Show camera shake/anim track menus even if there aren't any assets.
Change 3437244 by Max.Chen
Sequencer: Clear locked cameras when releasing Sequencer.
#jira UE-44967
Change 3437515 by Arciel.Rekman
UBT: improvements for LocalExecutor.
- Larger number of parallel jobs on 16GB+ machines.
- Use WaitForExit() instead of polling.
- Tested on Linux and Mac.
Change 3437629 by Matt.Kuhlenschmidt
Improve asset import data display in static and skeletal meshes
Change 3438047 by Arciel.Rekman
Fix overlapping ranges being passed to memcpy().
Change 3438822 by Yannick.Lange
ViewportInteraction: Move gizmo handle files to make them private.
Change 3438906 by Matt.Kuhlenschmidt
PR #3556: Git Plugin: fix new option "init Git LFS" that make assets read-only (master/UE4.17) (Contributed by SRombauts)
Change 3438907 by Matt.Kuhlenschmidt
PR #3565: add -quality option to buildlighing commandlet (Contributed by kayama-shift)
Change 3438908 by Matt.Kuhlenschmidt
PR #3558: UE-44862: Always update SColorPicker color on OK button (Contributed by projectgheist)
Change 3439393 by Matt.Kuhlenschmidt
Force highest LOD for highres screenshots
Change 3439819 by Matt.Kuhlenschmidt
Turned FAssetData into a struct for some upcoming script exposure of FAssetData
Change 3439949 by Arciel.Rekman
Fixed selection logic for the UE4_LINUX_USE_LIBCXX environment variable.
- Allows disabling libc++ by setting the variable to 0.
- Pull request #3576 contributed by jared-improbable.
Change 3441078 by Jamie.Dale
The culture/language/locale console commands are now available in all build configs
Change 3441109 by Jamie.Dale
Text containing surrogate pairs now runs through HarfBuzz when shaping in Auto mode
This is needed as the kerning-only shaping code assumes that everything is within the BMP
Change 3441275 by Matt.Kuhlenschmidt
Disable spinning on location and scale. These dont work because we have no notion of infinite spinning
Change 3442748 by Yannick.Lange
ViewportInteraction: Remove unused console variables.
Change 3442775 by James.Golding
Add support for editing MaterialFunctions to MaterialEditingLibrary
Pull Material recompile/update code into UMaterialEditingLibrary::RecompileMaterial
Pull MaterialFunction update code into UMaterialEditingLibrary::UpdateMaterialFunction util
Move RebuildMaterialInstanceEditors to UMaterialEditingLibrary
Added test content for Material/MaterialFunction editing
Add needed BlueprintReadWrite to expressions (constants, function input/output)
Expose UMaterialExpressionMaterialFunctionCall::SetMaterialFunction to BP, rename old func (which takes old function) to SetMaterialFunctionEx, also expose GetInputNameWithType
Change 3442779 by James.Golding
Fix header order
Change 3442817 by Yannick.Lange
ViewportInteraction: Add can execute checks for level editor commands.
Change 3443038 by Michael.Dupuis
#jira UE-43377: When you select a foliage actor we will move all instance contained in it to the new level as we can't move a foliage actor
Only permit moving foliage instance if there is some selected
Change 3443855 by Michael.Dupuis
#jira UE-44885: Unregister from PerModuleDataObjects when the object is destroyed
Change 3446096 by Max.Chen
Sequencer: Add OnFinished() event when a level sequence completes playback
#jira UE-45173
Change 3446097 by Max.Chen
Sequencer: Evaluate one last time before the sequence is torn down and reset
#jira UE-45174
Change 3446242 by Jamie.Dale
Fixed caret not appearing in empty text layouts
Caret selections have no range, and therefore have no width
Change 3446361 by Matt.Kuhlenschmidt
Fix WITH_EDITOR only functions causing generated code compile errors when the all functions on the class are WITH_EDITOR
Change 3446457 by Alexis.Matte
Polish the speed tree import dialog
#jira UE-44963
Change 3446946 by Michael.Trepka
Modified FWindowsWindow::GetRestoredDimensions to return correct window position for normal windows for which GetWindowPlacement returns position in workspace coordinates
#jira UE-37934
Change 3447543 by Arciel.Rekman
Reduce VMAs on Linux.
- Trades off increased address space (VIRT in terms of ps/htop) for smaller number of distinct mappings (VMAs, virtual memory areas).
This decreases possibility to run into vm.max_map_count limit on Linux.
- Tested on Linux and Mac.
Change 3448468 by Arciel.Rekman
Fix race condition during creation of GMalloc.
- On Mac GMalloc can be created on two different thread that are racing with each other - app's main thread and a system thread.
Change 3449012 by Max.Chen
Sequencer: Add time to transform, color and vector key structs so that key times are editable from the key editors.
#jira UE-45089
Change 3449018 by Max.Chen
Sequencer: Add OnCameraCut event that fires when there is a camera cut.
#jira UE-45137
Change 3449195 by Max.Chen
Sequencer: Add setting for limit scrubbing to playback range.
#jira UE-43502
Change 3449198 by Max.Chen
Sequencer: Reorder hierarchical bias so that group priority takes precedence.
Change 3449217 by Max.Chen
Sequencer: Add setting to activate realtime viewports when in sequencer.
Change 3449219 by Max.Chen
Sequencer: Focus on search boxes when opened.
Change 3449238 by Max.Chen
Sequencer: Assign actor should replace the actor itself after it has updated all the components. Also, replace components be fullname rather than by class.
Change 3449239 by Max.Chen
Sequencer: Fix offsets when moving multiple sections. Dragging should be clamped to the bounds that any of the selected sections hits against the unselected sections.
Change 3449241 by Max.Chen
Sequencer: Restore section selection after full tree rebuild.
Change 3449279 by Max.Chen
Sequencer: Set movie scene capture frames only when not using custom frames. This allows the user entered frame numbers to persist in config, rather than overwriting them when doing a "Render Shot"
Change 3449280 by Max.Chen
Sequencer: Spawn in the persistent level. Otherwise, they get spawned into whatever sublevel is current.
#jira UE-44552
Change 3449294 by Max.Chen
Sequencer: Null check for sequencer ed mode crash.
Change 3449297 by Max.Chen
Sequencer: Fix delay in sliding values. Mark changed when sliding values. Mark refresh immediately when committing values since OnValueChanged will be called and needs to have the correct value that was refreshed immediately.
#jira UE-42866
Change 3449542 by Max.Chen
Sequencer: Fix scrubber hit testing so that the time scrubber is really favored over the playback ranges.
#jira UE-44569
Change 3451507 by Matt.Kuhlenschmidt
Fix extra slate uv coords not functioning on ES2
Change 3451510 by Matt.Kuhlenschmidt
PR #3595: Fixed wrong colour for level status (Contributed by ronve)
Change 3451529 by Alexis.Matte
fbx scene importer: Make sure we set INVALID_UNIQUE_ID to node that has no attribute.
#jira UE-34410
Change 3451611 by Yannick.Lange
ViewportInteraction: Dragging gizmo without second pass for snapped calculations.
Change 3452134 by Jamie.Dale
Fixed constant font cache flushing if a widget had no font set
Change 3452239 by Jamie.Dale
Fixed constant font measure flushing if a widget had no font set
Change 3452243 by Jamie.Dale
Removed deprecated code for creating fonts from bulk data
Change 3452277 by Jamie.Dale
The concept of "stale" composite fonts is now editor-only
Change 3452358 by Alexis.Matte
Fbx scene importer: Do not remove existing attribute reference from the blueprint if the reimport of the associate mesh attribute is not tick.
#jira UE-45232
Change 3452678 by Max.Chen
Sequencer: Fix crash on export if there's no shot data.
Change 3453057 by Matt.Kuhlenschmidt
Exposed asset exporting to script
Change 3453782 by Andrew.Rodham
Sequencer: Fixed deterministic cooking issues with movie scene data
- Movie scene signatures are now initialized in PostInitProperties
- A warning is now presented when attempting to cook old data that was never serialized with a signature.
- Removed redundant legacy data upgrade logic that could dirty level sequences on load.
#jira UE-44912
Change 3453788 by Yannick.Lange
ViewportInteraction: Custom scene proxy for gizmo handles.
Change 3453938 by Max.Chen
Sequencer: Hotkeys (shift , and shift .) to step to next/previous shot
#jira UE-45119
Change 3454058 by Michael.Dupuis
Fixed StaticAnalysis
Change 3454077 by Max.Chen
Sequencer: Fix not saving the pre-animated track value when creating a track/key.
On pre object change, broadcast property change so that a track or key can be created. That track/key needs to be evaluated immediately so that the pre-animated state can be saved properly. This is done now with RefreshAllImmediately and is only called when a track has been created. Also, added a return value for OnKeyProperty, so that it's known what changed in particular (ie. track created, track modified, etc)
Also, fixed transform keying so that if a transform track already exists for the object or the scene component, the existing track is used.
#jira UE-45130
Change 3454108 by Nick.Darnell
UMG - Fixing the WIC to properly record cursor delta so that scrollbars work.
Change 3454109 by Jamie.Dale
Cache the text layout source info in non-shipping builds so you can inspect it in the debugger
Change 3454202 by Matt.Kuhlenschmidt
Fix bogus error message about the number of usable texture coordinates on ES2 when compiling a UI domain material
Change 3454390 by Yannick.Lange
Fix creating a plugin in a C++ project opens a second instance of Visual Studio. Use SourceCodeAccessor to open solution when necessary.
#jira UE-45035
Change 3454564 by Matt.Kuhlenschmidt
#rnx Fix deprecation warnings
Change 3455471 by Yannick.Lange
ViewportInteraction: Fix entering and exiting VR Mode disables gizmo in desktop editor viewport.
#jira UE-44965
Change 3456183 by Max.Chen
Sequencer: Auto key, auto track refactor.
Auto key - create a key when the property changes and there's an existing track.
Auto track - create a track when the property changes. This is only exposed in the level sequence editor.
All - create a key and a track when the property changes. This is only exposed in VR Editor.
None - do nothing.
#jira UE-43469
Change 3456349 by Andrew.Rodham
Sequencer: Only perform legacy signature checks on instances, and only where signatures match the CDO
Change 3456678 by Alexis.Matte
Allow to add null level instance override material via the advance material array. But still limit the override material number to the mesh material number.
#jira UE-45306
Change 3456945 by Max.Chen
UMG: Add restore state to 2d transform section.
#jira UE-45372
Change 3457196 by Arciel.Rekman
Linux: serialize allocations from the memory pool.
Change 3458434 by Max.Chen
Sequencer: Remove obsolete set tick prerequites functions.
Change 3458671 by James.Golding
Added MIC editing support to MaterialEditingLibrary
Fix static analysis warning
Change 3458888 by Matt.Kuhlenschmidt
PR #3615: More detailed log messages for debugging warnings/errors (Contributed by projectgheist)
Change 3458893 by Matt.Kuhlenschmidt
PR #3583: UE-44960: Delta value wasn't being used (Contributed by projectgheist)
Change 3458895 by Matt.Kuhlenschmidt
Fix typo
Change 3458902 by Matt.Kuhlenschmidt
PR #3607: Improved InputKeySelector functionality (Contributed by projectgheist)
Change 3458917 by Matt.Kuhlenschmidt
Fix crash with invalid object properties in the class picker
#jira UE-39000
Change 3458939 by Matt.Kuhlenschmidt
Fix compile error
Change 3458984 by andrew.porter
QAGame: Initial check in of sequencer smoke test map
Change 3459510 by Matt.Kuhlenschmidt
Fixed ensure when deleting a map that contains build data which also happens to be the currently loaded map.
#jira UE-45052
Change 3460985 by Max.Chen
Sequencer: Snap play time to keys now allows scrubbing between keys and snaps to key times within a certain screenspace tolerance.
#jira UE-45090
Change 3461698 by Arciel.Rekman
Avoid using ARRAY_COUNT in Vulkan.
- Sometimes those arrays can have no extensions whatsoever, and it is illegal to declare a 0 element C array.
Change 3462053 by Max.Chen
Sequencer: Show sequencer spawnables in the world outliner and add the icon overlay for spawnables.
#jira UE-43470
Change 3462139 by Max.Chen
Property Editor: Add objects to FPropertyAndParent
Change 3462202 by Arciel.Rekman
Fix FSocket::Recv() blocking with Peek when there's no data.
Change 3462253 by Nick.Darnell
Slate - New Clipping System
Clipping is now a stateful choice made during composition of the slate hierarchy. Previously every widget got to respect or modify the clipping rect on an as needed basis. The problem was that clipping was only allowed in the layout space of the widget, and it wasn't possible to properly clip elements with render transforms. The new system permits all kinds of transforms on any widget, and they will all be clipped correctly. It tries to use Scissor Rects as they are much cheaper, but will switch over to stenciling if need be to represent a complicated masking structure with several rotated clipping rects all needed to be combined together.
Here are the new clipping states a widget can have, almost all widgets are set to No. Only change it from No if your widget actually needs to clip, generally speaking most widgets don't need to clip.
/**
* This widget does not clip children, it and all children inherit the clipping area of the last widget that clipped.
*/
Inherit,
/**
* This widget clips content the bounds of this widget. It intersects those bounds with any previous clipping area.
*/
ClipToBounds,
/**
* This widget clips to its bounds. It does NOT intersect with any existing clipping geometry, it pushes a new clipping
* state. Effectively allowing it to render outside the bounds of hierarchy that does clip.
*
* NOTE: This will NOT allow you ignore the clipping zone that is set to [Yes - Always].
*/
ClipToBoundsWithoutIntersecting UMETA(DisplayName = "Yes - Without Intersecting (Advanced)"),
/**
* This widget clips to its bounds. It intersects those bounds with any previous clipping area.
*
* NOTE: This clipping area can NOT be ignored, it will always clip children. Useful for hard barriers
* in the UI where you never want animations or other effects to break this region.
*/
ClipToBoundsAlways UMETA(DisplayName = "Yes - Always (Advanced)"),
/**
* This widget clips to its bounds when it's Desired Size is larger than the allocated geometry
* the widget is given. If that occurs, it behaves like [Yes].
*
* NOTE: This mode was primarily added for Text, which is often placed into containers that eventually
* are resized to not be able to support the length of the text. So rather than needing to tag every
* container that could contain text with [Yes], which would result in almost no batching, this mode
* was added to dynamically adjust the clipping if needed. The reason not every panel is set to OnDemand,
* is because not every panel returns a Desired Size that matches what it plans to render at.
*/
OnDemand UMETA(DisplayName = "On Demand (Advanced)")
- Large API Change -
All FSlateDrawElement::Make_____ calls have been deprecated that involved passing in a clipping rect. You no longer should are passed a Clipping rect via OnPaint. You are still passed a rect, but this rect represents a Culling Rect, which is valuable if you need to just out right not paint things the user can't possibly see.
If you were previously trying to determine if you should cull widgets, by doing something like this,
if ( FSlateRect::DoRectanglesIntersect(MyClippingRect, CurWidget.Geometry.GetRenderBoundingRect()) )
That's no longer a good option since there are ways for widgets to ignore the culling bounds. You should convert anything like above to the one below,
if (!SWidget::IsWidgetCulled(MyCullingRect, CurWidget))
To assist in debugging efforts, there are several new debugging console flags in Slate,
Slate.ShowClipping 1 - Controls whether we should render a clipping zone outline. Yellow = Axis Scissor Rect Clipping (cheap). Red = Stencil Clipping (expensive).
Slate.DebugCulling 1 - Disables pushing clipping or stencil rects to the GPU, but continues to intersect culling rects, so that you can tell if a widget is properly culling children it can't possibly draw.
Slate.ShowTextDebugging 1 - Show debugging painting for text rendering.
I've added a new Experimental Feathering Option, it adds AA geometry around the outside of Box and Image brushes.
Slate.Feathering 1
If you're using RenderDoc or something similar, you can now enable render events for slate, so that you can better grok how we're batching and changing states for each UI render pass.
Slate.EnableDrawEvents 1
#jira UE-4659
#rn
Change 3462714 by Nick.Darnell
Fixing a few more compiler issues with the clipping changes.
Change 3462726 by Max.Chen
Switch OnEditStructChildContentsChanged to use FObjectWriter instead of FMemoryWriter which supports serializeing UObjects. This fixes a crash when adding actor array elements to a user defined event struct.
#jira UE-45431
Change 3462801 by Nick.Darnell
Adding a UMG dependency to EngineTestBuild.
Change 3462914 by Max.Chen
Sequencer: Fix regression where spawnables aren't getting saved. Caused by 3407138
#jira UE-30007
#jira UE-39003
Change 3462946 by Nick.Darnell
Automation - Tweaking the UI automation tests converting them over to use the new UI Screenshot automation test.
Automation - Adding a blur widget test.
Change 3462987 by Matt.Kuhlenschmidt
Back out changelist 3458893
Change 3464774 by Matt.Kuhlenschmidt
PR #3629: Bugfix: Missing small icon in Project Launcher profile editor (Contributed by aarmbruster)
Change 3464785 by Nick.Darnell
Fixing some clipping stuff in the editor.
Change 3464830 by andrew.porter
QAGame: Second pass on sequencer smoke test map
Change 3464902 by Nick.Darnell
Loading - Adding some additional checks to the the loading code to ensure we're on the main thread. Additionally adding a fix from UDN that prevents deadlocks in the rare case a user hits Alt+Tab in a fullscreen game while in a hard loading screen.
Change 3464988 by Max.Chen
Sequencer: Add attenuation settings for attached audio components.
#jira UE-33080
Change 3465024 by Nick.Darnell
MoviePlayer - Impoving the playback mode displaynames.
Change 3465074 by Arciel.Rekman
Fix shadowing issues of GraphicsPSOInit.
Change 3465097 by Matt.Kuhlenschmidt
Some refactoring of the details panel
Exposed new methods of adding a struct on scope to a details panel and have it work properly with customizations. The scruct on scope has a "fake" ustructproperty that allows the details panel to show the whole struct not just an individual property.
Refactored the API for adding rows to details panels to make it more consistent\
AddChildCustomBuilder->AddCustomBuilder
AddChildGroup->AddGroup
AddChildContent->AddCustomRow
AddChildPropert->AddProperty
AddChildStructure->AddExternalStructureProperty
AddStructure->AddAllExternalStructureProperties
AddExternalProperty->AddExternalObjectProperty or AddExternalStructureProperty
Change 3465186 by Max.Chen
Sequencer: Save the BindingID in the pre animated token producer so that it can be destroyed properly. This fixes a bug where the default state of a spawnable isn't saved.
#jira UE-43780
Change 3465315 by Matt.Kuhlenschmidt
Fix Fortnite and Orion details panel customization warnings
Change 3465424 by Nick.Darnell
Automation - Moving the step for setting the link to the automation reports to be set before we start the engine.
Change 3465488 by Nick.Darnell
Automation - Forcing textures to load before taking screenshot, so that the scene gets another opportunity to render before we render with Slate. This should fix the Blur UI Test.
Change 3466277 by Arciel.Rekman
Linux: fix window drift when dragging (UE-40380).
- Change by Cengiz Terzibas.
Change 3466370 by Nick.Darnell
UMG - Fixing the colors for the resize handle in the designer.
Change 3466372 by Nick.Darnell
UMG - Fixing the ruler ticks sometimes not being drawn.
Change 3466374 by Nick.Darnell
UMG - Fixing the designer showing multiple options for sequencer.
Change 3466377 by Nick.Darnell
UMG - Cleaning up some clipping bits.
Change 3467025 by Andrew.Rodham
Re-saving assets that contain legacy (<4.15) movie scene data to remove deterministic cook warning.
If conflicts arise during merging of these assets, please ignore the changes made in dev-editor, and accept game-side changes.
(CIS step 62283298, jobId 7773146)
(CIS step 62283297, jobId 7773146)
Change 3467099 by Max.Chen
Fix GetObjectPropertyClass ensure logic. This was returning UObject::StaticClass when valid.
Change 3467172 by Max.Chen
Sequencer: Evaluation optimizations. Also, fixes subsequences not getting expired, leaving dangling spawnables.
#jira UE-43690
Change 3467192 by Matt.Kuhlenschmidt
Fix transactions getting stuck in the color grading controls. This prevents PIE from working properly and causes shutdown crashes
#jira UE-45527
Change 3467251 by Yannick.Lange
ViewportInteraction: Fix scale and rotation snap while dragging with two lasers.
#jira UE-43489
Change 3467331 by Matt.Kuhlenschmidt
Fix D3D shader compiler hard coding shader path and not giving proper warnings when it cannot find the shaders
Change 3467335 by Matt.Kuhlenschmidt
Remove DarkStyle attribute from SNumericEntryBox and allow a spin box style to be passed to it.
Change 3467558 by Max.Chen
Scene Outliner: Generic support to add default columns to a scene outliner.
Change 3467565 by Jamie.Dale
Removing old screenshot data for test
Change 3467589 by Nick.Darnell
Editor - Random cleanup.
Change 3467596 by Nick.Darnell
Progress Bar - Exposing Border Padding to UMG.
Change 3467600 by Nick.Darnell
Slate - Adjusting the rendering of the splitter, previously it could be off by a pixel or two, which becomes more apparent now with the clipping changes.
Change 3467601 by Max.Chen
Property Editor: Fix static analysis warning
Change 3467662 by Nick.Darnell
Automation - Fixing a bug with the screenshot comparison tool not replacing (removing) the old screenshot data.
Change 3467674 by Max.Chen
Property Editor: Fix static analysis warning
Change 3467737 by Max.Chen
Sequencer: Added OnMovieSceneBindingsChanged delegate
Change 3468053 by tim.gautier
QAGame: Updating Editor Smoke Map
- Updated landscapes into Stations for testing
- Added Foliage Sublevel
Change 3468194 by Arciel.Rekman
Linux: fix problems communicating with various STL-using libs.
- Stop hiding global new/delete signatures.
- Disable CEF3 since this change uncovers the problem with libcef.so not built to use bundled libpng.
Change 3468678 by Max.Chen
Sequencer: Set "Sequencer Actor" tag before setting the actor label so that the outliner refreshes after the actor has the tag.
Change 3469314 by tim.gautier
QAGame: Added Painted Foliage / Spline section to EditorSmoke map
Change 3469377 by Nick.Darnell
Slate - Fixing some warnings in a couple of sample games due to the clipping changes.
#rnx
Change 3469767 by Max.Chen
Sequencer: Outliner column and sequencer binding data
#jira UE-43470
Change 3469974 by Arciel.Rekman
Fix code projects not working in Linux installed build.
Change 3470082 by Nick.Darnell
Slate - The GetRenderer() call on SlateApplication no longer returns a SharedPtr, rather than convert it to a thread safe ptr, going to just make accessing it a raw ptr return, so it can be safely referenced on the game thread while being used on the slate loading thread.
Change 3470174 by Nick.Darnell
Slate - Get the last widget in a widget path utility.
Change 3470176 by Nick.Darnell
UMG - User Widgets now have an easy way to know if they're part of or have been removed from the focused widget path, which is handy for doing effects.
Change 3470261 by Nick.Darnell
Slate - The GetRenderer() call on SlateApplication no longer returns a SharedPtr, rather than convert it to a thread safe ptr, going to just make accessing it a raw ptr return, so it can be safely referenced on the game thread while being used on the slate loading thread.
Change 3470286 by Max.Chen
Sequencer: Scene Component's HiddenInGame now goes through the VisibilityTrack and the visibility template.
Change 3470366 by Nick.Darnell
Slate - We now version focus per user, that way during focus events, we can safely abort focus events and state transitions if someone interrrupts the active focus event with something new.
Change 3470649 by Matt.Kuhlenschmidt
Fix deprecation warnings
Change 3470695 by Matt.Kuhlenschmidt
Fixed typo
#jira UE-45580
Change 3470721 by Matt.Kuhlenschmidt
Fix static analysis
Change 3471254 by Michael.Dupuis
#jira UE-42952: Keep occlusion result per view
Change 3471287 by Nick.Darnell
UMG - Render Focus Rule now defaults to never.
Change 3471291 by Nick.Darnell
Slate - Fixing FSlateRenderer* change fallout.
Change 3471299 by Nick.Darnell
Slate - Fixing FSlateRenderer* change.
Change 3471323 by Nick.Darnell
Automation - Fixing automation and Static Analysis warning.
Change 3471413 by andrew.porter
QAGame: Added test content for anim blending and material parameteres to sequencer smoke level
Change 3471649 by Max.Chen
Sequencer: Modify the track when adding animation
#jira UE-45618
Change 3471659 by Matt.Kuhlenschmidt
Added a way to check if a movie is playing from the engine.
Prevented viewport redraws for canvas loading screens if a slate based loading movie is playing
Change 3471734 by Matt.Kuhlenschmidt
Added basic material hookup to USD. Similar to FBX it will find materials based on rules specified by the user in the import settings
Change 3472176 by Nick.Darnell
UMG - Improving the display of the +Track menu in sequencer for UMG. Renamed it from +Add, which is repetitve to +Track. Additionally, the dropdown now shows the currently selected widgets, as well as a submenu containing all the 'important' widgets, so we no longer populate that list with a ton of irrelevant widgets that are just Buton_1 - N, which is pointless in showing people, they'll never guess which is the right button.
Change 3472740 by Max.Chen
Sequencer: Add GetThisFrameMetaData accessor
Change 3472748 by Max.Chen
Sequencer: Added OnBeginScrubbing and OnEndScrubbing event delegates
Change 3472753 by Max.Chen
Sequencer: Add EMovieSceneDataChangeType parameter to OnMovieSceneDataChanged delegate
Change 3472870 by Nick.Darnell
Clipping - Fixing the deprecated tip for scissor rect boxes to be correct. Removing it's usage from UT.
Change 3473340 by Max.Chen
Scene Outliner: Add ability to register additional filters
Change 3473348 by Max.Chen
Details View: Make ForceRefresh virtual. Added accessors to delegates (ie. GetIsPropertyReadOnlyDelegate)
Change 3473441 by Max.Chen
Sequencer: Autokey Refactor Part 2.
Autokey is now a single toggleable state.
Allow Edits Mode has 3 states:
Allow All Edits - Allow any edits to occur, some of which may produce tracks/keys or modify default properties.
Allow Sequencer Edits Only - All edits will produce either a track or a key.
Allow Level Edits Only - Properties in the details panel will be disabled if they have a track.
#jira UE-45229
Change 3473670 by Nick.Darnell
Modules - The module manager no longer returns sharedptrs to IModuleInterfaces, this was the source of rare hard to track down crashes due to a shared ptr reference leak when GetModule was called on non-main threads. We now store a TUniquePtr internally, and only lease out raw pointers.
#rn
Change 3473711 by Nick.Darnell
Disabling the ensure in the module manager.
Change 3473747 by Max.Chen
Sequencer: Fix tooltip
Change 3474091 by Jamie.Dale
Added a warning when cooking a UFontFace that is outered to a UFont asset
These cause issues with iterative COTF, and should be split off into their own assets (as the UI has been asking people to do for several versions)
Change 3475052 by Yannick.Lange
VR Editor: Fix Crash when quitting the editor with VR Mode enabled. VR Editor was being enabled when saving the map on closing the editor.
#jira UE-45415
Change 3475054 by Yannick.Lange
Fix crash when adding a camera to the world in VR Mode the second time. The slate application did not reset when stop dragging in VR Mode, so the second time when starting to drag a camera out of the UI it would already by in a dragging state.
#jira UE-45574
Change 3475263 by Nick.Darnell
Fixing some additional cases of IModuleInteface SharedPtr usage.
Change 3475268 by Max.Chen
Sequencer: Set jumped state when looping playback. This fixes an issue where audio doesn't stop and restart when looped.
#jira UE-45654
Change 3475269 by Max.Chen
Scene Outliner: Additional filters should only apply to actor browsing mode
Change 3475407 by Nick.Darnell
Fixing some clipping / module shared ptr changes in the launcher code.
Change 3475542 by Max.Chen
Sequencer: Update thumbnail and section highlighting to use new clipping behavior.
#jira UE-45692
#jira UE-45689
Change 3475743 by Michael.Dupuis
#jira UE-45183: When updating phyx region take into account simple collision mip
Change 3475949 by Arciel.Rekman
Remove PhysX deoptimization (no longer needed).
- OR-24947 has been closed three months ago.
Change 3476022 by Michael.Dupuis
#jira UE-45560: Make sure we're not going out of range
Change 3476063 by Michael.Dupuis
#jira UE-45562: Do not try to unregister from static mesh if no static mesh is specified for the component
Change 3476168 by Michael.Trepka
Added handling of directory symlinks to FApplePlatformFile::IterateDirectory
#jira UE-43704
Change 3476172 by Nick.Darnell
Fixing a Imoduleinterface change.
Change 3476183 by Jamie.Dale
Exposing GoTo/ScrollTo to single-line editable text for API parity with multi-line editable text
Change 3476385 by Arciel.Rekman
Linux: handle symlinks when iterating directories.
Change 3476522 by Michael.Trepka
Solved a problem with Mac FMallocTBB::Malloc() returning nullptr for 0 bytes allocations, which is inconsistent with other platforms. On Mac we always scalable_aligned_malloc, which behaves differently than scalable_malloc, so for 0 bytes requests we allocate sizeof(size_t), which is exactly what scalable_malloc does internally in such case.
Change 3476806 by Nick.Darnell
UMG - Focus the designer after dropping a widget onto the surface.
Change 3476809 by Nick.Darnell
Curve Editor - Enable Clipping on the curve editor.
Change 3477475 by Nick.Darnell
Fixing a module interface shared ptr usage in UT.
Change 3477553 by Yannick.Lange
VR Editor: Removed AssetEditorPanelID and replaced it with TabManagerPanelID. A panel for AssetEditorPanelID was never created making it impossible to open an asset editor.
Change 3477734 by Yannick.Lange
VR Editor: Fix Warning: SetRelativeScale3D : Invalid Scale entered (X=inf Y=inf Z=inf). Resetting to 1.f. warning when adding CineCameraActor to World from Modes Panel. Make sure to not divide by zero when there is no boundary scale.
#jira UE-44933
Change 3477761 by Jamie.Dale
Some improvements to avoid loading the native .locres files twice when we don't need to
Change 3477780 by Nick.Darnell
PR #3250: Return correct VirtualUserIndex (Contributed by projectgheist)
Change 3477786 by Nick.Darnell
PR #3650: Changed TestNull to accept const pointers. (Contributed by e-agaubatz)
Change 3477795 by Nick.Darnell
PR #2844: UE-36936: Don't stretch container for Plugin Image (Contributed by projectgheist)
Change 3478092 by Nick.Darnell
PR #2341: Optional Middle Mouse Button panning in Graph Editor (Contributed by flipswitchingmonkey)
Engine Edit - Made some small changes to the enum type, and some naming.
Change 3478450 by Nick.Darnell
Fixing some uninitialized variable errors.
Change 3479827 by Andrew.Rodham
Sequencer: Addressed serialization issues with some struct types
Change 3479874 by Jamie.Dale
Fixed "NativeGameLanguage" not being used correctly during localization initialization
Change 3480012 by Andrew.Rodham
Sequencer: Fixed loading tagged properties as native for track identifiers
#jira UE-45823
Change 3480337 by Alexis.Matte
Fix morph target crash missing some valid index check
Change 3480804 by Alexis.Matte
Fix crash with ColorGradingMode custom detail
#jira UE-45638
Change 3480892 by Andrew.Rodham
Sequencer: Ensure that movie scene sequences know about the editor object version
#jira UE-45842
Change 3481073 by Nick.Darnell
Fix the shader compiler error from main in Slate.
Change 3481303 by Nick.Darnell
UMG - Fixing a bug with the drag handle not working correctly in HDPI mode.
Change 3481308 by Nick.Darnell
Slate - Tweaking the IsWidgetCulled logic to consider both the layout and rendering bounds. If we do this, we get a much more desireable outcome for people that want to animate widgets and such and plan to have temporary animations to move the widget offscreen, but want the layout bounds to anchor that widget in the visible frame so that it animates even when normally it would be culled b/c the render transform and therefore the renderbounds moved it completely outside the culling rect.
Change 3481629 by Max.Chen
Sequencer: Add Level Sequence Actor as an output for CreateLevelSequencePlayer()
#jira UE-45785
Change 3481899 by Yannick.Lange
VR Editor: Added debug modetoggle command with an event that is broadcasted whenever this happens. Currently this is used to show all the floating UIs of the UI system to debug without HMD using VREd.ForceVRMode.
Change 3481984 by Michael.Dupuis
#jira UE-45845: always validate if we have a static mesh before trying to access it as user can decide to not assign one and use the tools
Change 3482047 by Nick.Darnell
Slate - Adding some comments to IsWidgetCulled.
Change 3482110 by Nick.Darnell
Slate - IsWidgetCulled is no longer static and is now called IsChildWidgetCulled.
Change 3482136 by Jamie.Dale
The CamelCase break iterator now treats digits around character tokens as part of the identifier
Change 3482138 by Michael.Dupuis
#jira UE-45854: Properly unregister during undo operation
Change 3482150 by Michael.Dupuis
#jira UE-45845 : Add missing nullcheck for GetStaticMesh
Change 3482153 by Nick.Darnell
Slate - IsWidgetCulled is no longer static and is now called IsChildWidgetCulled.
Change 3482180 by Nick.Darnell
UMG - Widget Components do not need to define a widget class to be rendererd, they can have native slate widgets only. This was a regression from main.
Change 3482273 by Nick.Darnell
UMG - Tweaking some more things about the widget component box outline.
Change 3482308 by Alexis.Matte
Fixing morph target smooth group support. Do not call FillSkeletalMeshImportData more then once on FbxNode since this fonction is doing some conversion and change the FbxNode, applying those conversion twice do not return the same faces smooth group.
#jira UE-45696
Change 3482327 by Nick.Darnell
UMG - More tweaks to the WidgetComponent so both shows the box outline, but works in game and VR editor.
Change 3482705 by Andrew.Rodham
Resaving assets that contain legacy data to suppress CIS warnings.
- If conflicts arise in these assets, please take game-side changes and ignore these.
Change 3484245 by Max.Chen
Sequencer: Evaluate on end scrub. This fixes a bug where audio doesn't evaluate in a stopped position at the end of scrubbing, causing it to not stop all sounds. This fixes a bug introduced from 3365018 where evaluate on end scrub was removed.
#jira UE-45905
Change 3484263 by Max.Chen
Sequencer: Fix crash on forcing refresh of details panel on release.
#jira UE-45911
Change 3484431 by Andrew.Rodham
Resaving assets that contain legacy data to suppress CIS warnings.
- If conflicts arise in these assets, please take game-side changes and ignore these.
Change 3484474 by Alexis.Matte
Fix the morph target animation curve name matching.
#jira UE-20294
Change 3484475 by Alexis.Matte
When removing a LOD, make sure we remove all morph target data associate to the LOD.
Change 3484489 by Nick.Darnell
PR #3668: UE-45908: Cache debug line locations when performing a LineTraceMulti (Contributed by projectgheist)
#jira UE-45908
Change 3484692 by Nick.Darnell
Slate - Reverting a change from a game stream. All Arranged Children don't need to allocated 42 to begin with. Do need to initialize WidgetPaths better.
Change 3484703 by Nick.Darnell
Player Input - Making the input event loop for players obey EKeys::NUM_TOUCH_KEYS, rather than being set to Touch10, as the maximum touch input amount, to make supporting greater than 10 touches easier. Also making the seeding of keys use EKeys::NUM_TOUCH_KEYS.
#jira UE-43213
Change 3484918 by Jamie.Dale
Fixed font measuring regression with RTL text
RTL applies the character count to the next glyph, so it shouldn't process the end of the loop (this was how the older code used to work).
Change 3485718 by Nick.Darnell
Editor - Removing Super Search & User Feedback button.
Change 3485719 by Nick.Darnell
Portal - Removing SuperSearch.
Change 3485751 by Matt.Kuhlenschmidt
Fix crash accessing platformer game menu if the menu is open during a console based load
#jira UE-45950
Change 3486047 by Arciel.Rekman
Linux: add OpenEXR implementation (UE-40270).
#jira UE-40270
Change 3486467 by Max.Chen
Sequencer: Reset max tick rate when destroyed.
#jira UE-45956
Change 3486477 by Max.Chen
Sequencer: Refresh outliner when column is removed.
#jira UE-45891
Change 3486667 by Andrew.Rodham
Added missing include
Change 3486724 by Andrew.Rodham
Sequencer: Fixed curves with no default value, and no keys being evaluated and applied to properties
- Also fixed an edge case where a zero (but non-animated) channel could be applied to a final transform
Change 3486730 by Alexis.Matte
In the Auto-Reimport options, hide the mout point only for the default /Game/ folder
#UE-45684
Change 3486749 by Alexis.Matte
Make sure the parent window of the monitor directory browse folder is set properly
#jira UE-45682
Change 3486805 by Matt.Kuhlenschmidt
Additional safety against invalid objects being accessed by slate
Change 3486848 by Alexis.Matte
Make sure Monitor folder feature support root mount point map folder
During auto import, give priority to asset import factory over the scene import factory
#jira UE-45691
Change 3486879 by Andrew.Rodham
Removing obsolete QA assets
Change 3486950 by Nick.Darnell
PR #2281: Scrollbar missing features and SScrollbar fixes (Contributed by SNikon)
Review - made some adjustments from the original.
Change 3486954 by Nick.Darnell
Slate - Moving the STableViewBase over to the FOverscroll class, rather than it's own clone.
Change 3486967 by Nick.Darnell
Slate - Fixing some HDPI calculations for fitting new windows on screen, it was using the unscaled size of the widgets for fitting, when it needed to scale them up.
Change 3486970 by Andrew.Rodham
Sequencer: Delay mouse capture until drag for sequencer time slider
- Fixes context menus not opening as a result of mouse capture being taken on mouse down
#jira UE-45937
Change 3486984 by Andrew.Rodham
Sequencer: Improved blending type iconography
Change 3486996 by Nick.Darnell
UMG - Adding a way for games to opt-out of the slow widget path, to completely prevent them from being cooked.
UMG - The movie data is no longer cloned for each new instance that inhabits. It now keeps a reference to the now publically accessible movie scene data on the class instead.
Change 3487070 by Andrew.Rodham
Sequencer: Added graphics for key areas that represent empty space
Change 3487195 by Andrew.Rodham
Sequencer: Changed evaluation groups to always flush implicitly
- Due to the latent nature of blended token types, it's no longer safe to rely solely on execution token order between tracks
- This fixes an issue where events set in the PostEvaluation stage were executed before blended token actuation
Change 3487322 by Nick.Darnell
PR #2457: Add .gitdeps.xml-files for plugins support (Contributed by bozaro)
Change 3487363 by Nick.Darnell
PR #2481: Fix for packing of a project with users plugins (Contributed by yatagarasu25)
Change 3487439 by Nick.Darnell
PR #2642: Changed private to protected in SVirtualJoystick.h (Contributed by Skylonxe)
Change 3487500 by Arciel.Rekman
Removed LinuxNativeDialogs.
- No longer used; has been superceded by SlateDialogs since UE 4.8 (2 years ago).
Change 3487630 by Lauren.Ridge
Don't create Landscape Info Maps for Editor Preview Worlds or thumbnail worlds
#jira UE-44885
Change 3487864 by Matt.Kuhlenschmidt
Exposed the asset registry to blueprints and script. Works in editor scripts and runtime scripts
AssetRegistry is now a UInterface object.
Blueprint users can access various asset registry methods using the asset registry interface (via GetAssetRegistry) and various static helpers in the AssetRegistryHelpers object
C++ users should still continue to use IAssetRegistry.
Change 3487879 by Matt.Kuhlenschmidt
Renamed asset tools uobject helper to UAssetToolsHelpers
Change 3487926 by Lauren.Ridge
Fixing reset to default not showing up for custom widgets
#jira UE-44164
Change 3488184 by Matt.Kuhlenschmidt
PR #3656: Make References/Referencers List copyable (Contributed by user37337)
#jira UE-45763
Change 3488240 by Matt.Kuhlenschmidt
Fix compiler issue
Change 3488350 by Lauren.Ridge
Landscape info map transactional state is based on its world's transactional state
#jira UE-44885
#jira UE-46019
Change 3488412 by Matt.Kuhlenschmidt
Fix reset to default showing up in two different places for some customizations
Change 3488413 by Matt.Kuhlenschmidt
Fix slate font customization
Change 3488414 by Matt.Kuhlenschmidt
Fix slate font customization
Change 3488415 by Matt.Kuhlenschmidt
Missed file
Change 3488565 by Arciel.Rekman
Add pretty printers for gdb (UETOOL-1171).
- Committing shelf by Cengiz.Terzibas, with some modifications.
#jira UETOOL-1171
Change 3489094 by Nick.Darnell
Slate - The Slate RHI Renderer now caches the TextureLODGroups so that it can properly lookup the filtering of different texture groups that are set to Default, instead of a particular filter override on a texture.
Engine/Rendering - Simplifying some of the setup logic in TextureLODSettings so that code is shared for setting them up properly after loading from a config file.
Change 3489095 by Nick.Darnell
PR #2699: GameViewportClient - Added a method to allow setting the viewport cur. (Contributed by rfenner)
Review - Fixed spacing.
Change 3489108 by Matt.Kuhlenschmidt
Fix deprecation warning
Change 3489120 by Nick.Darnell
PR #3478: Fix possible UComboBoxString crash (Contributed by nakosung)
Change 3489147 by Andrew.Rodham
Sequencer: Adding return value to function to appease static analysis
- This function is never compiled, and if it is, it won't compile, but static analysis doesn't know that
Change 3489264 by Nick.Darnell
Testing - Finishing the thought behind an enum comment.
Change 3489265 by Nick.Darnell
PR #2750: UE-35164: Button padding (Contributed by projectgheist)
Change 3489267 by Nick.Darnell
PR #3645: UE-45464: Handle SSlider mouse interaction more accurately (Contributed by projectgheist)
Change 3489632 by Arciel.Rekman
Correctness changes to MallocPoisonProxy.
- Missing forwarding functions added. Incorrect comment removed.
- Change by Steve.Robb, doing here so it is in 4.17.
Change 3489689 by Arciel.Rekman
More MallocPoisonProxy changes I missed in previous CL.
Change 3489751 by Matt.Kuhlenschmidt
Moved editor performance settings out of per-project settings so they can be shared across projects
Change 3489837 by Lauren.Ridge
Keyboard shortcut for entering/leaving VR Mode is now Alt+V
Change 3491082 by Arciel.Rekman
Linux: better fix for the crash due to name collision (UE-46040).
- Put classes in Sequencer module into Sequencer namespace instead of SceneOutliner namespace.
- Undid change in the SceneOutliner module.
#jira UE-46040
Change 3491096 by Arciel.Rekman
Fix UAT compilation on the newest mono.
Change 3491240 by Max.Chen
Sequencer: Disable key button when allow level edits only is on.
#jira UE-46060
Change 3491406 by Yannick.Lange
Fix editor crashes when opening a project that includes a plugin with more than two custom Volume classes. This issue was caused because registering show volume commands is based on finding volume classes. Finding these classes at multiple times resulted in a mismatch of the returned array of volume classes because modules/plugins were still being loaded.
#jira UE-45806
Change 3491559 by Alexis.Matte
Make sure we use the good preview mesh when doing a preview
#jira UE-45963
Change 3491563 by Alexis.Matte
Fix crash with staticmesh editor LodLevel selection
Change 3491564 by Nick.Darnell
UMG - Fixing an offset with the grab handles in HDPI mode.
Change 3491595 by Nick.Darnell
Editor - Fixing a clipping artifact in the pin type dropdown in the blueprint editor.
Change 3491604 by Nick.Darnell
Back out changelist 3489265
Change 3491615 by Arciel.Rekman
Added malloc replay proxy (Linux only for now).
- Allows to dump malloc callstream (without regard to threads) and replay later to study the behavior of different mallocs and/or repro problems.
Change 3491684 by Arciel.Rekman
Added FMalloc functions I missed.
- Also moved function bodies into the .cpp file, this does not make a difference in performance in this case.
Change 3491692 by Matt.Kuhlenschmidt
Some minor fixes to the static mesh editor
- Fix UV combo button looking non-standard on the toolbar
- Fix a few combo buttons in the details panel looking too big.
Change 3491702 by Arciel.Rekman
Do not compile replay proxy-specific code when not used.
Change 3491717 by Michael.Dupuis
#jira UE-35083:
The component is now the owner of the PerInstanceRenderData instead of the proxy
Add an Update path to only update specified instances range
Always call BuildTreeIfOutdated so we have a standard code path to make sure static mesh are fully loaded before trying to build the tree
Moved the Instance Buffer aysnc to the base class, as it's not related to UHierarchicalInstancedStaticMeshComponent
Expose a new property to decide if we require dynamic instance buffer
Change 3491758 by Matt.Kuhlenschmidt
Fix crash on static mesh editor shutdown
Change 3491873 by Cody.Albert
Fixed clipping issue in Sequencer curve editor
#rnx
Change 3491956 by Matt.Kuhlenschmidt
Fix crash opening the Previewing sub-menu in the level editor settings menu
#jira UE-46095
Change 3492046 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492076 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492165 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492222 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492274 by Michael.Dupuis
#jira UE-46105: Fixed Clang warning
Change 3492338 by andrew.porter
QAGame: Testing ensure when submitting
Change 3492371 by Nick.Darnell
UMG - Reverting the animation sharing, cossed GLEO regressions in cooking. Will look for a better solution.
Change 3492462 by Matt.Kuhlenschmidt
Fix ensure checking in files through perforce
Change 3492491 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492505 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492517 by Jamie.Dale
The package localization ID is no longer used at all at runtime, and is now truly editor-only
This should have always been the case, but it was leaked into manifest/archives/PO files in 4.14, and while 4.15 removed it from PO files it was still present in the manifest/archives. This change removes it entirely (unless gathering editor-only data, and even then the PO file will still collapse the entries together for translation), and the deprecated 4.14 export behavior will now produce an error if you attempt to use it.
After taking this change you'll need to run a gather, import, and compile of your LocRes files to update your game localization to use the new localization IDs.
Change 3492630 by Nick.Darnell
UMG - Removing some extra cleanup code that's probably overkill and is causing a crash for uses of "Within" in class meta.
#jira UE-46124
Change 3492692 by Matt.Kuhlenschmidt
Fix drop shadows inheriting the outline color of the font. The outline should still appear but not have a different outline color from fill color
Change 3492714 by Matt.Kuhlenschmidt
Added outline with drop shadow to font automation test
Change 3492737 by Matt.Kuhlenschmidt
Fix linux
Change 3492992 by tim.gautier
Resaving Ocean Widget Blueprints / Sequences to resolve Legacy Sequence Data warnings
#jira UE-46132
Change 3493089 by Jamie.Dale
Ensure that the composite font of a font asset is flushed when the font object is GC'd
Change 3493322 by Jamie.Dale
Fixing null crash
#jira UE-45758
Change 3494467 by Andrew.Rodham
Fix Xbox warning
Change 3494852 by tim.gautier
QAGame: Changed streaming method of QA-EditorSmoke-Landscape to Always Loaded
Change 3494853 by Nick.Darnell
Another attempt at fixing the automation blueprint SA warning.
Change 3494896 by Arciel.Rekman
Fix possible null pointer access during Vulkan init.
- May fix static analysis warnings in UE-46142, although warnings seem to be referring to something else.
#jira UE-46142
Change 3494987 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3495010 by Matt.Kuhlenschmidt
Adding additional logging to track down html5 issue
Change 3495212 by Michael.Dupuis
#jira UE-46143: Properly init the InstanceRenderData during the cooking phase (required by fortnite)
Change 3495536 by Jamie.Dale
Updating UGameEngine to call its Super::PreExit after performing its own teardown
This prevents UEngine cleaning up resources that UGameEngine still needs.
#jira UE-46159
Change 3495551 by Arciel.Rekman
Another attempt to fix analyzer problem (UE-46142).
Change 3495794 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3495905 by Matt.Kuhlenschmidt
Fix USD crash when importing a meshwith no material
[CL 3499771 by Matt Kuhlenschmidt in Main branch]
2017-06-19 20:27:30 -04:00
//remove all Morph target data for this LOD
2020-11-25 11:17:08 -04:00
for ( UMorphTarget * MorphTarget : SkeletalMesh - > GetMorphTargets ( ) )
Copying //UE4/Dev-Editor to //UE4/Dev-Main (Source: //UE4/Dev-Editor @ 3497164)
#lockdown Nick.Penwarden
#rb none
=====================================
MAJOR FEATURES + CHANGES
=====================================
Change 3433074 by Matt.Kuhlenschmidt
Fix crash when clicking on certian tutorial blueprints.
#jira UE-44593
Change 3433075 by Matt.Kuhlenschmidt
Remove hittest grid log spam. The underlying problem causing this has been fixed
Change 3433077 by Matt.Kuhlenschmidt
Fix lighting becoming unbuilt when mesh painting
#jira UE-44837
Change 3433081 by Matt.Kuhlenschmidt
PR #3553: Crashfix for static array properties (Contributed by Pierdek)
Change 3433104 by Alexis.Matte
Make sure re-import skeletal mesh follow the import morph option
#jira UE-42846
Change 3434825 by Matt.Kuhlenschmidt
Fix crash when GC happens while the vr editor radial menu is open.
Change 3434831 by Matt.Kuhlenschmidt
Added missing file
Change 3434868 by Shaun.Kime
If you have a reroute node between a Material Function texture input and its usage, the parent material will fail to resolve the reroute node.
#jira ue-44670
Change 3434998 by Alexis.Matte
Meshes editors material/section panel are now fully transactional
- Staticmesh editor: section material slot, section cast shadow, section collision, material slot instance, material slot name
- Skeletal mesh editor: material slot instance, material slot name
Also fix some transaction description
#jira UE-44462
Change 3435195 by Jamie.Dale
Fixed incorrect handling of some LTR scripts that require shaping
These scripts need to go through HarfBuzz, and this also fixes a case where HarfBuzz wasn't applying font scale correctly.
#jira UE-44767
Change 3435199 by Jamie.Dale
Fixed some crashes/artifacts with bidirectional text
It was possible for a line to compute an incorrect range, which could cause crashes or other highlighting issues. The highlighting logic has also been updated as the old code didn't handle all bidirectional cases correctly.
Change 3435200 by Jamie.Dale
Fixed a grapheme cluster metrics issue in the font editor viewport
The viewport also now respects the default shaping method CVar.
Change 3435771 by Alexis.Matte
Fix degenerated bounds calculation for skeletalmesh when the skeleton is remove from a re-import
(PhysicAsset API change, adding 1 function)
#jira UE-44609
Change 3436856 by Jamie.Dale
Added some missing Unicode block ranges
Change 3436914 by Jamie.Dale
Adding some missing combining character ranges to the text shaper
Change 3436923 by Alexis.Matte
PR #3463: Get bounds for all triangles, not just the first one. WedgeIndex was . (Contributed by DaveC79)
#jira UE-43764
Change 3436948 by Jamie.Dale
Updated the Portal to use the predefined Unicode block ranges
Change 3436961 by Max.Chen
Sequencer: Show camera shake/anim track menus even if there aren't any assets.
Change 3437244 by Max.Chen
Sequencer: Clear locked cameras when releasing Sequencer.
#jira UE-44967
Change 3437515 by Arciel.Rekman
UBT: improvements for LocalExecutor.
- Larger number of parallel jobs on 16GB+ machines.
- Use WaitForExit() instead of polling.
- Tested on Linux and Mac.
Change 3437629 by Matt.Kuhlenschmidt
Improve asset import data display in static and skeletal meshes
Change 3438047 by Arciel.Rekman
Fix overlapping ranges being passed to memcpy().
Change 3438822 by Yannick.Lange
ViewportInteraction: Move gizmo handle files to make them private.
Change 3438906 by Matt.Kuhlenschmidt
PR #3556: Git Plugin: fix new option "init Git LFS" that make assets read-only (master/UE4.17) (Contributed by SRombauts)
Change 3438907 by Matt.Kuhlenschmidt
PR #3565: add -quality option to buildlighing commandlet (Contributed by kayama-shift)
Change 3438908 by Matt.Kuhlenschmidt
PR #3558: UE-44862: Always update SColorPicker color on OK button (Contributed by projectgheist)
Change 3439393 by Matt.Kuhlenschmidt
Force highest LOD for highres screenshots
Change 3439819 by Matt.Kuhlenschmidt
Turned FAssetData into a struct for some upcoming script exposure of FAssetData
Change 3439949 by Arciel.Rekman
Fixed selection logic for the UE4_LINUX_USE_LIBCXX environment variable.
- Allows disabling libc++ by setting the variable to 0.
- Pull request #3576 contributed by jared-improbable.
Change 3441078 by Jamie.Dale
The culture/language/locale console commands are now available in all build configs
Change 3441109 by Jamie.Dale
Text containing surrogate pairs now runs through HarfBuzz when shaping in Auto mode
This is needed as the kerning-only shaping code assumes that everything is within the BMP
Change 3441275 by Matt.Kuhlenschmidt
Disable spinning on location and scale. These dont work because we have no notion of infinite spinning
Change 3442748 by Yannick.Lange
ViewportInteraction: Remove unused console variables.
Change 3442775 by James.Golding
Add support for editing MaterialFunctions to MaterialEditingLibrary
Pull Material recompile/update code into UMaterialEditingLibrary::RecompileMaterial
Pull MaterialFunction update code into UMaterialEditingLibrary::UpdateMaterialFunction util
Move RebuildMaterialInstanceEditors to UMaterialEditingLibrary
Added test content for Material/MaterialFunction editing
Add needed BlueprintReadWrite to expressions (constants, function input/output)
Expose UMaterialExpressionMaterialFunctionCall::SetMaterialFunction to BP, rename old func (which takes old function) to SetMaterialFunctionEx, also expose GetInputNameWithType
Change 3442779 by James.Golding
Fix header order
Change 3442817 by Yannick.Lange
ViewportInteraction: Add can execute checks for level editor commands.
Change 3443038 by Michael.Dupuis
#jira UE-43377: When you select a foliage actor we will move all instance contained in it to the new level as we can't move a foliage actor
Only permit moving foliage instance if there is some selected
Change 3443855 by Michael.Dupuis
#jira UE-44885: Unregister from PerModuleDataObjects when the object is destroyed
Change 3446096 by Max.Chen
Sequencer: Add OnFinished() event when a level sequence completes playback
#jira UE-45173
Change 3446097 by Max.Chen
Sequencer: Evaluate one last time before the sequence is torn down and reset
#jira UE-45174
Change 3446242 by Jamie.Dale
Fixed caret not appearing in empty text layouts
Caret selections have no range, and therefore have no width
Change 3446361 by Matt.Kuhlenschmidt
Fix WITH_EDITOR only functions causing generated code compile errors when the all functions on the class are WITH_EDITOR
Change 3446457 by Alexis.Matte
Polish the speed tree import dialog
#jira UE-44963
Change 3446946 by Michael.Trepka
Modified FWindowsWindow::GetRestoredDimensions to return correct window position for normal windows for which GetWindowPlacement returns position in workspace coordinates
#jira UE-37934
Change 3447543 by Arciel.Rekman
Reduce VMAs on Linux.
- Trades off increased address space (VIRT in terms of ps/htop) for smaller number of distinct mappings (VMAs, virtual memory areas).
This decreases possibility to run into vm.max_map_count limit on Linux.
- Tested on Linux and Mac.
Change 3448468 by Arciel.Rekman
Fix race condition during creation of GMalloc.
- On Mac GMalloc can be created on two different thread that are racing with each other - app's main thread and a system thread.
Change 3449012 by Max.Chen
Sequencer: Add time to transform, color and vector key structs so that key times are editable from the key editors.
#jira UE-45089
Change 3449018 by Max.Chen
Sequencer: Add OnCameraCut event that fires when there is a camera cut.
#jira UE-45137
Change 3449195 by Max.Chen
Sequencer: Add setting for limit scrubbing to playback range.
#jira UE-43502
Change 3449198 by Max.Chen
Sequencer: Reorder hierarchical bias so that group priority takes precedence.
Change 3449217 by Max.Chen
Sequencer: Add setting to activate realtime viewports when in sequencer.
Change 3449219 by Max.Chen
Sequencer: Focus on search boxes when opened.
Change 3449238 by Max.Chen
Sequencer: Assign actor should replace the actor itself after it has updated all the components. Also, replace components be fullname rather than by class.
Change 3449239 by Max.Chen
Sequencer: Fix offsets when moving multiple sections. Dragging should be clamped to the bounds that any of the selected sections hits against the unselected sections.
Change 3449241 by Max.Chen
Sequencer: Restore section selection after full tree rebuild.
Change 3449279 by Max.Chen
Sequencer: Set movie scene capture frames only when not using custom frames. This allows the user entered frame numbers to persist in config, rather than overwriting them when doing a "Render Shot"
Change 3449280 by Max.Chen
Sequencer: Spawn in the persistent level. Otherwise, they get spawned into whatever sublevel is current.
#jira UE-44552
Change 3449294 by Max.Chen
Sequencer: Null check for sequencer ed mode crash.
Change 3449297 by Max.Chen
Sequencer: Fix delay in sliding values. Mark changed when sliding values. Mark refresh immediately when committing values since OnValueChanged will be called and needs to have the correct value that was refreshed immediately.
#jira UE-42866
Change 3449542 by Max.Chen
Sequencer: Fix scrubber hit testing so that the time scrubber is really favored over the playback ranges.
#jira UE-44569
Change 3451507 by Matt.Kuhlenschmidt
Fix extra slate uv coords not functioning on ES2
Change 3451510 by Matt.Kuhlenschmidt
PR #3595: Fixed wrong colour for level status (Contributed by ronve)
Change 3451529 by Alexis.Matte
fbx scene importer: Make sure we set INVALID_UNIQUE_ID to node that has no attribute.
#jira UE-34410
Change 3451611 by Yannick.Lange
ViewportInteraction: Dragging gizmo without second pass for snapped calculations.
Change 3452134 by Jamie.Dale
Fixed constant font cache flushing if a widget had no font set
Change 3452239 by Jamie.Dale
Fixed constant font measure flushing if a widget had no font set
Change 3452243 by Jamie.Dale
Removed deprecated code for creating fonts from bulk data
Change 3452277 by Jamie.Dale
The concept of "stale" composite fonts is now editor-only
Change 3452358 by Alexis.Matte
Fbx scene importer: Do not remove existing attribute reference from the blueprint if the reimport of the associate mesh attribute is not tick.
#jira UE-45232
Change 3452678 by Max.Chen
Sequencer: Fix crash on export if there's no shot data.
Change 3453057 by Matt.Kuhlenschmidt
Exposed asset exporting to script
Change 3453782 by Andrew.Rodham
Sequencer: Fixed deterministic cooking issues with movie scene data
- Movie scene signatures are now initialized in PostInitProperties
- A warning is now presented when attempting to cook old data that was never serialized with a signature.
- Removed redundant legacy data upgrade logic that could dirty level sequences on load.
#jira UE-44912
Change 3453788 by Yannick.Lange
ViewportInteraction: Custom scene proxy for gizmo handles.
Change 3453938 by Max.Chen
Sequencer: Hotkeys (shift , and shift .) to step to next/previous shot
#jira UE-45119
Change 3454058 by Michael.Dupuis
Fixed StaticAnalysis
Change 3454077 by Max.Chen
Sequencer: Fix not saving the pre-animated track value when creating a track/key.
On pre object change, broadcast property change so that a track or key can be created. That track/key needs to be evaluated immediately so that the pre-animated state can be saved properly. This is done now with RefreshAllImmediately and is only called when a track has been created. Also, added a return value for OnKeyProperty, so that it's known what changed in particular (ie. track created, track modified, etc)
Also, fixed transform keying so that if a transform track already exists for the object or the scene component, the existing track is used.
#jira UE-45130
Change 3454108 by Nick.Darnell
UMG - Fixing the WIC to properly record cursor delta so that scrollbars work.
Change 3454109 by Jamie.Dale
Cache the text layout source info in non-shipping builds so you can inspect it in the debugger
Change 3454202 by Matt.Kuhlenschmidt
Fix bogus error message about the number of usable texture coordinates on ES2 when compiling a UI domain material
Change 3454390 by Yannick.Lange
Fix creating a plugin in a C++ project opens a second instance of Visual Studio. Use SourceCodeAccessor to open solution when necessary.
#jira UE-45035
Change 3454564 by Matt.Kuhlenschmidt
#rnx Fix deprecation warnings
Change 3455471 by Yannick.Lange
ViewportInteraction: Fix entering and exiting VR Mode disables gizmo in desktop editor viewport.
#jira UE-44965
Change 3456183 by Max.Chen
Sequencer: Auto key, auto track refactor.
Auto key - create a key when the property changes and there's an existing track.
Auto track - create a track when the property changes. This is only exposed in the level sequence editor.
All - create a key and a track when the property changes. This is only exposed in VR Editor.
None - do nothing.
#jira UE-43469
Change 3456349 by Andrew.Rodham
Sequencer: Only perform legacy signature checks on instances, and only where signatures match the CDO
Change 3456678 by Alexis.Matte
Allow to add null level instance override material via the advance material array. But still limit the override material number to the mesh material number.
#jira UE-45306
Change 3456945 by Max.Chen
UMG: Add restore state to 2d transform section.
#jira UE-45372
Change 3457196 by Arciel.Rekman
Linux: serialize allocations from the memory pool.
Change 3458434 by Max.Chen
Sequencer: Remove obsolete set tick prerequites functions.
Change 3458671 by James.Golding
Added MIC editing support to MaterialEditingLibrary
Fix static analysis warning
Change 3458888 by Matt.Kuhlenschmidt
PR #3615: More detailed log messages for debugging warnings/errors (Contributed by projectgheist)
Change 3458893 by Matt.Kuhlenschmidt
PR #3583: UE-44960: Delta value wasn't being used (Contributed by projectgheist)
Change 3458895 by Matt.Kuhlenschmidt
Fix typo
Change 3458902 by Matt.Kuhlenschmidt
PR #3607: Improved InputKeySelector functionality (Contributed by projectgheist)
Change 3458917 by Matt.Kuhlenschmidt
Fix crash with invalid object properties in the class picker
#jira UE-39000
Change 3458939 by Matt.Kuhlenschmidt
Fix compile error
Change 3458984 by andrew.porter
QAGame: Initial check in of sequencer smoke test map
Change 3459510 by Matt.Kuhlenschmidt
Fixed ensure when deleting a map that contains build data which also happens to be the currently loaded map.
#jira UE-45052
Change 3460985 by Max.Chen
Sequencer: Snap play time to keys now allows scrubbing between keys and snaps to key times within a certain screenspace tolerance.
#jira UE-45090
Change 3461698 by Arciel.Rekman
Avoid using ARRAY_COUNT in Vulkan.
- Sometimes those arrays can have no extensions whatsoever, and it is illegal to declare a 0 element C array.
Change 3462053 by Max.Chen
Sequencer: Show sequencer spawnables in the world outliner and add the icon overlay for spawnables.
#jira UE-43470
Change 3462139 by Max.Chen
Property Editor: Add objects to FPropertyAndParent
Change 3462202 by Arciel.Rekman
Fix FSocket::Recv() blocking with Peek when there's no data.
Change 3462253 by Nick.Darnell
Slate - New Clipping System
Clipping is now a stateful choice made during composition of the slate hierarchy. Previously every widget got to respect or modify the clipping rect on an as needed basis. The problem was that clipping was only allowed in the layout space of the widget, and it wasn't possible to properly clip elements with render transforms. The new system permits all kinds of transforms on any widget, and they will all be clipped correctly. It tries to use Scissor Rects as they are much cheaper, but will switch over to stenciling if need be to represent a complicated masking structure with several rotated clipping rects all needed to be combined together.
Here are the new clipping states a widget can have, almost all widgets are set to No. Only change it from No if your widget actually needs to clip, generally speaking most widgets don't need to clip.
/**
* This widget does not clip children, it and all children inherit the clipping area of the last widget that clipped.
*/
Inherit,
/**
* This widget clips content the bounds of this widget. It intersects those bounds with any previous clipping area.
*/
ClipToBounds,
/**
* This widget clips to its bounds. It does NOT intersect with any existing clipping geometry, it pushes a new clipping
* state. Effectively allowing it to render outside the bounds of hierarchy that does clip.
*
* NOTE: This will NOT allow you ignore the clipping zone that is set to [Yes - Always].
*/
ClipToBoundsWithoutIntersecting UMETA(DisplayName = "Yes - Without Intersecting (Advanced)"),
/**
* This widget clips to its bounds. It intersects those bounds with any previous clipping area.
*
* NOTE: This clipping area can NOT be ignored, it will always clip children. Useful for hard barriers
* in the UI where you never want animations or other effects to break this region.
*/
ClipToBoundsAlways UMETA(DisplayName = "Yes - Always (Advanced)"),
/**
* This widget clips to its bounds when it's Desired Size is larger than the allocated geometry
* the widget is given. If that occurs, it behaves like [Yes].
*
* NOTE: This mode was primarily added for Text, which is often placed into containers that eventually
* are resized to not be able to support the length of the text. So rather than needing to tag every
* container that could contain text with [Yes], which would result in almost no batching, this mode
* was added to dynamically adjust the clipping if needed. The reason not every panel is set to OnDemand,
* is because not every panel returns a Desired Size that matches what it plans to render at.
*/
OnDemand UMETA(DisplayName = "On Demand (Advanced)")
- Large API Change -
All FSlateDrawElement::Make_____ calls have been deprecated that involved passing in a clipping rect. You no longer should are passed a Clipping rect via OnPaint. You are still passed a rect, but this rect represents a Culling Rect, which is valuable if you need to just out right not paint things the user can't possibly see.
If you were previously trying to determine if you should cull widgets, by doing something like this,
if ( FSlateRect::DoRectanglesIntersect(MyClippingRect, CurWidget.Geometry.GetRenderBoundingRect()) )
That's no longer a good option since there are ways for widgets to ignore the culling bounds. You should convert anything like above to the one below,
if (!SWidget::IsWidgetCulled(MyCullingRect, CurWidget))
To assist in debugging efforts, there are several new debugging console flags in Slate,
Slate.ShowClipping 1 - Controls whether we should render a clipping zone outline. Yellow = Axis Scissor Rect Clipping (cheap). Red = Stencil Clipping (expensive).
Slate.DebugCulling 1 - Disables pushing clipping or stencil rects to the GPU, but continues to intersect culling rects, so that you can tell if a widget is properly culling children it can't possibly draw.
Slate.ShowTextDebugging 1 - Show debugging painting for text rendering.
I've added a new Experimental Feathering Option, it adds AA geometry around the outside of Box and Image brushes.
Slate.Feathering 1
If you're using RenderDoc or something similar, you can now enable render events for slate, so that you can better grok how we're batching and changing states for each UI render pass.
Slate.EnableDrawEvents 1
#jira UE-4659
#rn
Change 3462714 by Nick.Darnell
Fixing a few more compiler issues with the clipping changes.
Change 3462726 by Max.Chen
Switch OnEditStructChildContentsChanged to use FObjectWriter instead of FMemoryWriter which supports serializeing UObjects. This fixes a crash when adding actor array elements to a user defined event struct.
#jira UE-45431
Change 3462801 by Nick.Darnell
Adding a UMG dependency to EngineTestBuild.
Change 3462914 by Max.Chen
Sequencer: Fix regression where spawnables aren't getting saved. Caused by 3407138
#jira UE-30007
#jira UE-39003
Change 3462946 by Nick.Darnell
Automation - Tweaking the UI automation tests converting them over to use the new UI Screenshot automation test.
Automation - Adding a blur widget test.
Change 3462987 by Matt.Kuhlenschmidt
Back out changelist 3458893
Change 3464774 by Matt.Kuhlenschmidt
PR #3629: Bugfix: Missing small icon in Project Launcher profile editor (Contributed by aarmbruster)
Change 3464785 by Nick.Darnell
Fixing some clipping stuff in the editor.
Change 3464830 by andrew.porter
QAGame: Second pass on sequencer smoke test map
Change 3464902 by Nick.Darnell
Loading - Adding some additional checks to the the loading code to ensure we're on the main thread. Additionally adding a fix from UDN that prevents deadlocks in the rare case a user hits Alt+Tab in a fullscreen game while in a hard loading screen.
Change 3464988 by Max.Chen
Sequencer: Add attenuation settings for attached audio components.
#jira UE-33080
Change 3465024 by Nick.Darnell
MoviePlayer - Impoving the playback mode displaynames.
Change 3465074 by Arciel.Rekman
Fix shadowing issues of GraphicsPSOInit.
Change 3465097 by Matt.Kuhlenschmidt
Some refactoring of the details panel
Exposed new methods of adding a struct on scope to a details panel and have it work properly with customizations. The scruct on scope has a "fake" ustructproperty that allows the details panel to show the whole struct not just an individual property.
Refactored the API for adding rows to details panels to make it more consistent\
AddChildCustomBuilder->AddCustomBuilder
AddChildGroup->AddGroup
AddChildContent->AddCustomRow
AddChildPropert->AddProperty
AddChildStructure->AddExternalStructureProperty
AddStructure->AddAllExternalStructureProperties
AddExternalProperty->AddExternalObjectProperty or AddExternalStructureProperty
Change 3465186 by Max.Chen
Sequencer: Save the BindingID in the pre animated token producer so that it can be destroyed properly. This fixes a bug where the default state of a spawnable isn't saved.
#jira UE-43780
Change 3465315 by Matt.Kuhlenschmidt
Fix Fortnite and Orion details panel customization warnings
Change 3465424 by Nick.Darnell
Automation - Moving the step for setting the link to the automation reports to be set before we start the engine.
Change 3465488 by Nick.Darnell
Automation - Forcing textures to load before taking screenshot, so that the scene gets another opportunity to render before we render with Slate. This should fix the Blur UI Test.
Change 3466277 by Arciel.Rekman
Linux: fix window drift when dragging (UE-40380).
- Change by Cengiz Terzibas.
Change 3466370 by Nick.Darnell
UMG - Fixing the colors for the resize handle in the designer.
Change 3466372 by Nick.Darnell
UMG - Fixing the ruler ticks sometimes not being drawn.
Change 3466374 by Nick.Darnell
UMG - Fixing the designer showing multiple options for sequencer.
Change 3466377 by Nick.Darnell
UMG - Cleaning up some clipping bits.
Change 3467025 by Andrew.Rodham
Re-saving assets that contain legacy (<4.15) movie scene data to remove deterministic cook warning.
If conflicts arise during merging of these assets, please ignore the changes made in dev-editor, and accept game-side changes.
(CIS step 62283298, jobId 7773146)
(CIS step 62283297, jobId 7773146)
Change 3467099 by Max.Chen
Fix GetObjectPropertyClass ensure logic. This was returning UObject::StaticClass when valid.
Change 3467172 by Max.Chen
Sequencer: Evaluation optimizations. Also, fixes subsequences not getting expired, leaving dangling spawnables.
#jira UE-43690
Change 3467192 by Matt.Kuhlenschmidt
Fix transactions getting stuck in the color grading controls. This prevents PIE from working properly and causes shutdown crashes
#jira UE-45527
Change 3467251 by Yannick.Lange
ViewportInteraction: Fix scale and rotation snap while dragging with two lasers.
#jira UE-43489
Change 3467331 by Matt.Kuhlenschmidt
Fix D3D shader compiler hard coding shader path and not giving proper warnings when it cannot find the shaders
Change 3467335 by Matt.Kuhlenschmidt
Remove DarkStyle attribute from SNumericEntryBox and allow a spin box style to be passed to it.
Change 3467558 by Max.Chen
Scene Outliner: Generic support to add default columns to a scene outliner.
Change 3467565 by Jamie.Dale
Removing old screenshot data for test
Change 3467589 by Nick.Darnell
Editor - Random cleanup.
Change 3467596 by Nick.Darnell
Progress Bar - Exposing Border Padding to UMG.
Change 3467600 by Nick.Darnell
Slate - Adjusting the rendering of the splitter, previously it could be off by a pixel or two, which becomes more apparent now with the clipping changes.
Change 3467601 by Max.Chen
Property Editor: Fix static analysis warning
Change 3467662 by Nick.Darnell
Automation - Fixing a bug with the screenshot comparison tool not replacing (removing) the old screenshot data.
Change 3467674 by Max.Chen
Property Editor: Fix static analysis warning
Change 3467737 by Max.Chen
Sequencer: Added OnMovieSceneBindingsChanged delegate
Change 3468053 by tim.gautier
QAGame: Updating Editor Smoke Map
- Updated landscapes into Stations for testing
- Added Foliage Sublevel
Change 3468194 by Arciel.Rekman
Linux: fix problems communicating with various STL-using libs.
- Stop hiding global new/delete signatures.
- Disable CEF3 since this change uncovers the problem with libcef.so not built to use bundled libpng.
Change 3468678 by Max.Chen
Sequencer: Set "Sequencer Actor" tag before setting the actor label so that the outliner refreshes after the actor has the tag.
Change 3469314 by tim.gautier
QAGame: Added Painted Foliage / Spline section to EditorSmoke map
Change 3469377 by Nick.Darnell
Slate - Fixing some warnings in a couple of sample games due to the clipping changes.
#rnx
Change 3469767 by Max.Chen
Sequencer: Outliner column and sequencer binding data
#jira UE-43470
Change 3469974 by Arciel.Rekman
Fix code projects not working in Linux installed build.
Change 3470082 by Nick.Darnell
Slate - The GetRenderer() call on SlateApplication no longer returns a SharedPtr, rather than convert it to a thread safe ptr, going to just make accessing it a raw ptr return, so it can be safely referenced on the game thread while being used on the slate loading thread.
Change 3470174 by Nick.Darnell
Slate - Get the last widget in a widget path utility.
Change 3470176 by Nick.Darnell
UMG - User Widgets now have an easy way to know if they're part of or have been removed from the focused widget path, which is handy for doing effects.
Change 3470261 by Nick.Darnell
Slate - The GetRenderer() call on SlateApplication no longer returns a SharedPtr, rather than convert it to a thread safe ptr, going to just make accessing it a raw ptr return, so it can be safely referenced on the game thread while being used on the slate loading thread.
Change 3470286 by Max.Chen
Sequencer: Scene Component's HiddenInGame now goes through the VisibilityTrack and the visibility template.
Change 3470366 by Nick.Darnell
Slate - We now version focus per user, that way during focus events, we can safely abort focus events and state transitions if someone interrrupts the active focus event with something new.
Change 3470649 by Matt.Kuhlenschmidt
Fix deprecation warnings
Change 3470695 by Matt.Kuhlenschmidt
Fixed typo
#jira UE-45580
Change 3470721 by Matt.Kuhlenschmidt
Fix static analysis
Change 3471254 by Michael.Dupuis
#jira UE-42952: Keep occlusion result per view
Change 3471287 by Nick.Darnell
UMG - Render Focus Rule now defaults to never.
Change 3471291 by Nick.Darnell
Slate - Fixing FSlateRenderer* change fallout.
Change 3471299 by Nick.Darnell
Slate - Fixing FSlateRenderer* change.
Change 3471323 by Nick.Darnell
Automation - Fixing automation and Static Analysis warning.
Change 3471413 by andrew.porter
QAGame: Added test content for anim blending and material parameteres to sequencer smoke level
Change 3471649 by Max.Chen
Sequencer: Modify the track when adding animation
#jira UE-45618
Change 3471659 by Matt.Kuhlenschmidt
Added a way to check if a movie is playing from the engine.
Prevented viewport redraws for canvas loading screens if a slate based loading movie is playing
Change 3471734 by Matt.Kuhlenschmidt
Added basic material hookup to USD. Similar to FBX it will find materials based on rules specified by the user in the import settings
Change 3472176 by Nick.Darnell
UMG - Improving the display of the +Track menu in sequencer for UMG. Renamed it from +Add, which is repetitve to +Track. Additionally, the dropdown now shows the currently selected widgets, as well as a submenu containing all the 'important' widgets, so we no longer populate that list with a ton of irrelevant widgets that are just Buton_1 - N, which is pointless in showing people, they'll never guess which is the right button.
Change 3472740 by Max.Chen
Sequencer: Add GetThisFrameMetaData accessor
Change 3472748 by Max.Chen
Sequencer: Added OnBeginScrubbing and OnEndScrubbing event delegates
Change 3472753 by Max.Chen
Sequencer: Add EMovieSceneDataChangeType parameter to OnMovieSceneDataChanged delegate
Change 3472870 by Nick.Darnell
Clipping - Fixing the deprecated tip for scissor rect boxes to be correct. Removing it's usage from UT.
Change 3473340 by Max.Chen
Scene Outliner: Add ability to register additional filters
Change 3473348 by Max.Chen
Details View: Make ForceRefresh virtual. Added accessors to delegates (ie. GetIsPropertyReadOnlyDelegate)
Change 3473441 by Max.Chen
Sequencer: Autokey Refactor Part 2.
Autokey is now a single toggleable state.
Allow Edits Mode has 3 states:
Allow All Edits - Allow any edits to occur, some of which may produce tracks/keys or modify default properties.
Allow Sequencer Edits Only - All edits will produce either a track or a key.
Allow Level Edits Only - Properties in the details panel will be disabled if they have a track.
#jira UE-45229
Change 3473670 by Nick.Darnell
Modules - The module manager no longer returns sharedptrs to IModuleInterfaces, this was the source of rare hard to track down crashes due to a shared ptr reference leak when GetModule was called on non-main threads. We now store a TUniquePtr internally, and only lease out raw pointers.
#rn
Change 3473711 by Nick.Darnell
Disabling the ensure in the module manager.
Change 3473747 by Max.Chen
Sequencer: Fix tooltip
Change 3474091 by Jamie.Dale
Added a warning when cooking a UFontFace that is outered to a UFont asset
These cause issues with iterative COTF, and should be split off into their own assets (as the UI has been asking people to do for several versions)
Change 3475052 by Yannick.Lange
VR Editor: Fix Crash when quitting the editor with VR Mode enabled. VR Editor was being enabled when saving the map on closing the editor.
#jira UE-45415
Change 3475054 by Yannick.Lange
Fix crash when adding a camera to the world in VR Mode the second time. The slate application did not reset when stop dragging in VR Mode, so the second time when starting to drag a camera out of the UI it would already by in a dragging state.
#jira UE-45574
Change 3475263 by Nick.Darnell
Fixing some additional cases of IModuleInteface SharedPtr usage.
Change 3475268 by Max.Chen
Sequencer: Set jumped state when looping playback. This fixes an issue where audio doesn't stop and restart when looped.
#jira UE-45654
Change 3475269 by Max.Chen
Scene Outliner: Additional filters should only apply to actor browsing mode
Change 3475407 by Nick.Darnell
Fixing some clipping / module shared ptr changes in the launcher code.
Change 3475542 by Max.Chen
Sequencer: Update thumbnail and section highlighting to use new clipping behavior.
#jira UE-45692
#jira UE-45689
Change 3475743 by Michael.Dupuis
#jira UE-45183: When updating phyx region take into account simple collision mip
Change 3475949 by Arciel.Rekman
Remove PhysX deoptimization (no longer needed).
- OR-24947 has been closed three months ago.
Change 3476022 by Michael.Dupuis
#jira UE-45560: Make sure we're not going out of range
Change 3476063 by Michael.Dupuis
#jira UE-45562: Do not try to unregister from static mesh if no static mesh is specified for the component
Change 3476168 by Michael.Trepka
Added handling of directory symlinks to FApplePlatformFile::IterateDirectory
#jira UE-43704
Change 3476172 by Nick.Darnell
Fixing a Imoduleinterface change.
Change 3476183 by Jamie.Dale
Exposing GoTo/ScrollTo to single-line editable text for API parity with multi-line editable text
Change 3476385 by Arciel.Rekman
Linux: handle symlinks when iterating directories.
Change 3476522 by Michael.Trepka
Solved a problem with Mac FMallocTBB::Malloc() returning nullptr for 0 bytes allocations, which is inconsistent with other platforms. On Mac we always scalable_aligned_malloc, which behaves differently than scalable_malloc, so for 0 bytes requests we allocate sizeof(size_t), which is exactly what scalable_malloc does internally in such case.
Change 3476806 by Nick.Darnell
UMG - Focus the designer after dropping a widget onto the surface.
Change 3476809 by Nick.Darnell
Curve Editor - Enable Clipping on the curve editor.
Change 3477475 by Nick.Darnell
Fixing a module interface shared ptr usage in UT.
Change 3477553 by Yannick.Lange
VR Editor: Removed AssetEditorPanelID and replaced it with TabManagerPanelID. A panel for AssetEditorPanelID was never created making it impossible to open an asset editor.
Change 3477734 by Yannick.Lange
VR Editor: Fix Warning: SetRelativeScale3D : Invalid Scale entered (X=inf Y=inf Z=inf). Resetting to 1.f. warning when adding CineCameraActor to World from Modes Panel. Make sure to not divide by zero when there is no boundary scale.
#jira UE-44933
Change 3477761 by Jamie.Dale
Some improvements to avoid loading the native .locres files twice when we don't need to
Change 3477780 by Nick.Darnell
PR #3250: Return correct VirtualUserIndex (Contributed by projectgheist)
Change 3477786 by Nick.Darnell
PR #3650: Changed TestNull to accept const pointers. (Contributed by e-agaubatz)
Change 3477795 by Nick.Darnell
PR #2844: UE-36936: Don't stretch container for Plugin Image (Contributed by projectgheist)
Change 3478092 by Nick.Darnell
PR #2341: Optional Middle Mouse Button panning in Graph Editor (Contributed by flipswitchingmonkey)
Engine Edit - Made some small changes to the enum type, and some naming.
Change 3478450 by Nick.Darnell
Fixing some uninitialized variable errors.
Change 3479827 by Andrew.Rodham
Sequencer: Addressed serialization issues with some struct types
Change 3479874 by Jamie.Dale
Fixed "NativeGameLanguage" not being used correctly during localization initialization
Change 3480012 by Andrew.Rodham
Sequencer: Fixed loading tagged properties as native for track identifiers
#jira UE-45823
Change 3480337 by Alexis.Matte
Fix morph target crash missing some valid index check
Change 3480804 by Alexis.Matte
Fix crash with ColorGradingMode custom detail
#jira UE-45638
Change 3480892 by Andrew.Rodham
Sequencer: Ensure that movie scene sequences know about the editor object version
#jira UE-45842
Change 3481073 by Nick.Darnell
Fix the shader compiler error from main in Slate.
Change 3481303 by Nick.Darnell
UMG - Fixing a bug with the drag handle not working correctly in HDPI mode.
Change 3481308 by Nick.Darnell
Slate - Tweaking the IsWidgetCulled logic to consider both the layout and rendering bounds. If we do this, we get a much more desireable outcome for people that want to animate widgets and such and plan to have temporary animations to move the widget offscreen, but want the layout bounds to anchor that widget in the visible frame so that it animates even when normally it would be culled b/c the render transform and therefore the renderbounds moved it completely outside the culling rect.
Change 3481629 by Max.Chen
Sequencer: Add Level Sequence Actor as an output for CreateLevelSequencePlayer()
#jira UE-45785
Change 3481899 by Yannick.Lange
VR Editor: Added debug modetoggle command with an event that is broadcasted whenever this happens. Currently this is used to show all the floating UIs of the UI system to debug without HMD using VREd.ForceVRMode.
Change 3481984 by Michael.Dupuis
#jira UE-45845: always validate if we have a static mesh before trying to access it as user can decide to not assign one and use the tools
Change 3482047 by Nick.Darnell
Slate - Adding some comments to IsWidgetCulled.
Change 3482110 by Nick.Darnell
Slate - IsWidgetCulled is no longer static and is now called IsChildWidgetCulled.
Change 3482136 by Jamie.Dale
The CamelCase break iterator now treats digits around character tokens as part of the identifier
Change 3482138 by Michael.Dupuis
#jira UE-45854: Properly unregister during undo operation
Change 3482150 by Michael.Dupuis
#jira UE-45845 : Add missing nullcheck for GetStaticMesh
Change 3482153 by Nick.Darnell
Slate - IsWidgetCulled is no longer static and is now called IsChildWidgetCulled.
Change 3482180 by Nick.Darnell
UMG - Widget Components do not need to define a widget class to be rendererd, they can have native slate widgets only. This was a regression from main.
Change 3482273 by Nick.Darnell
UMG - Tweaking some more things about the widget component box outline.
Change 3482308 by Alexis.Matte
Fixing morph target smooth group support. Do not call FillSkeletalMeshImportData more then once on FbxNode since this fonction is doing some conversion and change the FbxNode, applying those conversion twice do not return the same faces smooth group.
#jira UE-45696
Change 3482327 by Nick.Darnell
UMG - More tweaks to the WidgetComponent so both shows the box outline, but works in game and VR editor.
Change 3482705 by Andrew.Rodham
Resaving assets that contain legacy data to suppress CIS warnings.
- If conflicts arise in these assets, please take game-side changes and ignore these.
Change 3484245 by Max.Chen
Sequencer: Evaluate on end scrub. This fixes a bug where audio doesn't evaluate in a stopped position at the end of scrubbing, causing it to not stop all sounds. This fixes a bug introduced from 3365018 where evaluate on end scrub was removed.
#jira UE-45905
Change 3484263 by Max.Chen
Sequencer: Fix crash on forcing refresh of details panel on release.
#jira UE-45911
Change 3484431 by Andrew.Rodham
Resaving assets that contain legacy data to suppress CIS warnings.
- If conflicts arise in these assets, please take game-side changes and ignore these.
Change 3484474 by Alexis.Matte
Fix the morph target animation curve name matching.
#jira UE-20294
Change 3484475 by Alexis.Matte
When removing a LOD, make sure we remove all morph target data associate to the LOD.
Change 3484489 by Nick.Darnell
PR #3668: UE-45908: Cache debug line locations when performing a LineTraceMulti (Contributed by projectgheist)
#jira UE-45908
Change 3484692 by Nick.Darnell
Slate - Reverting a change from a game stream. All Arranged Children don't need to allocated 42 to begin with. Do need to initialize WidgetPaths better.
Change 3484703 by Nick.Darnell
Player Input - Making the input event loop for players obey EKeys::NUM_TOUCH_KEYS, rather than being set to Touch10, as the maximum touch input amount, to make supporting greater than 10 touches easier. Also making the seeding of keys use EKeys::NUM_TOUCH_KEYS.
#jira UE-43213
Change 3484918 by Jamie.Dale
Fixed font measuring regression with RTL text
RTL applies the character count to the next glyph, so it shouldn't process the end of the loop (this was how the older code used to work).
Change 3485718 by Nick.Darnell
Editor - Removing Super Search & User Feedback button.
Change 3485719 by Nick.Darnell
Portal - Removing SuperSearch.
Change 3485751 by Matt.Kuhlenschmidt
Fix crash accessing platformer game menu if the menu is open during a console based load
#jira UE-45950
Change 3486047 by Arciel.Rekman
Linux: add OpenEXR implementation (UE-40270).
#jira UE-40270
Change 3486467 by Max.Chen
Sequencer: Reset max tick rate when destroyed.
#jira UE-45956
Change 3486477 by Max.Chen
Sequencer: Refresh outliner when column is removed.
#jira UE-45891
Change 3486667 by Andrew.Rodham
Added missing include
Change 3486724 by Andrew.Rodham
Sequencer: Fixed curves with no default value, and no keys being evaluated and applied to properties
- Also fixed an edge case where a zero (but non-animated) channel could be applied to a final transform
Change 3486730 by Alexis.Matte
In the Auto-Reimport options, hide the mout point only for the default /Game/ folder
#UE-45684
Change 3486749 by Alexis.Matte
Make sure the parent window of the monitor directory browse folder is set properly
#jira UE-45682
Change 3486805 by Matt.Kuhlenschmidt
Additional safety against invalid objects being accessed by slate
Change 3486848 by Alexis.Matte
Make sure Monitor folder feature support root mount point map folder
During auto import, give priority to asset import factory over the scene import factory
#jira UE-45691
Change 3486879 by Andrew.Rodham
Removing obsolete QA assets
Change 3486950 by Nick.Darnell
PR #2281: Scrollbar missing features and SScrollbar fixes (Contributed by SNikon)
Review - made some adjustments from the original.
Change 3486954 by Nick.Darnell
Slate - Moving the STableViewBase over to the FOverscroll class, rather than it's own clone.
Change 3486967 by Nick.Darnell
Slate - Fixing some HDPI calculations for fitting new windows on screen, it was using the unscaled size of the widgets for fitting, when it needed to scale them up.
Change 3486970 by Andrew.Rodham
Sequencer: Delay mouse capture until drag for sequencer time slider
- Fixes context menus not opening as a result of mouse capture being taken on mouse down
#jira UE-45937
Change 3486984 by Andrew.Rodham
Sequencer: Improved blending type iconography
Change 3486996 by Nick.Darnell
UMG - Adding a way for games to opt-out of the slow widget path, to completely prevent them from being cooked.
UMG - The movie data is no longer cloned for each new instance that inhabits. It now keeps a reference to the now publically accessible movie scene data on the class instead.
Change 3487070 by Andrew.Rodham
Sequencer: Added graphics for key areas that represent empty space
Change 3487195 by Andrew.Rodham
Sequencer: Changed evaluation groups to always flush implicitly
- Due to the latent nature of blended token types, it's no longer safe to rely solely on execution token order between tracks
- This fixes an issue where events set in the PostEvaluation stage were executed before blended token actuation
Change 3487322 by Nick.Darnell
PR #2457: Add .gitdeps.xml-files for plugins support (Contributed by bozaro)
Change 3487363 by Nick.Darnell
PR #2481: Fix for packing of a project with users plugins (Contributed by yatagarasu25)
Change 3487439 by Nick.Darnell
PR #2642: Changed private to protected in SVirtualJoystick.h (Contributed by Skylonxe)
Change 3487500 by Arciel.Rekman
Removed LinuxNativeDialogs.
- No longer used; has been superceded by SlateDialogs since UE 4.8 (2 years ago).
Change 3487630 by Lauren.Ridge
Don't create Landscape Info Maps for Editor Preview Worlds or thumbnail worlds
#jira UE-44885
Change 3487864 by Matt.Kuhlenschmidt
Exposed the asset registry to blueprints and script. Works in editor scripts and runtime scripts
AssetRegistry is now a UInterface object.
Blueprint users can access various asset registry methods using the asset registry interface (via GetAssetRegistry) and various static helpers in the AssetRegistryHelpers object
C++ users should still continue to use IAssetRegistry.
Change 3487879 by Matt.Kuhlenschmidt
Renamed asset tools uobject helper to UAssetToolsHelpers
Change 3487926 by Lauren.Ridge
Fixing reset to default not showing up for custom widgets
#jira UE-44164
Change 3488184 by Matt.Kuhlenschmidt
PR #3656: Make References/Referencers List copyable (Contributed by user37337)
#jira UE-45763
Change 3488240 by Matt.Kuhlenschmidt
Fix compiler issue
Change 3488350 by Lauren.Ridge
Landscape info map transactional state is based on its world's transactional state
#jira UE-44885
#jira UE-46019
Change 3488412 by Matt.Kuhlenschmidt
Fix reset to default showing up in two different places for some customizations
Change 3488413 by Matt.Kuhlenschmidt
Fix slate font customization
Change 3488414 by Matt.Kuhlenschmidt
Fix slate font customization
Change 3488415 by Matt.Kuhlenschmidt
Missed file
Change 3488565 by Arciel.Rekman
Add pretty printers for gdb (UETOOL-1171).
- Committing shelf by Cengiz.Terzibas, with some modifications.
#jira UETOOL-1171
Change 3489094 by Nick.Darnell
Slate - The Slate RHI Renderer now caches the TextureLODGroups so that it can properly lookup the filtering of different texture groups that are set to Default, instead of a particular filter override on a texture.
Engine/Rendering - Simplifying some of the setup logic in TextureLODSettings so that code is shared for setting them up properly after loading from a config file.
Change 3489095 by Nick.Darnell
PR #2699: GameViewportClient - Added a method to allow setting the viewport cur. (Contributed by rfenner)
Review - Fixed spacing.
Change 3489108 by Matt.Kuhlenschmidt
Fix deprecation warning
Change 3489120 by Nick.Darnell
PR #3478: Fix possible UComboBoxString crash (Contributed by nakosung)
Change 3489147 by Andrew.Rodham
Sequencer: Adding return value to function to appease static analysis
- This function is never compiled, and if it is, it won't compile, but static analysis doesn't know that
Change 3489264 by Nick.Darnell
Testing - Finishing the thought behind an enum comment.
Change 3489265 by Nick.Darnell
PR #2750: UE-35164: Button padding (Contributed by projectgheist)
Change 3489267 by Nick.Darnell
PR #3645: UE-45464: Handle SSlider mouse interaction more accurately (Contributed by projectgheist)
Change 3489632 by Arciel.Rekman
Correctness changes to MallocPoisonProxy.
- Missing forwarding functions added. Incorrect comment removed.
- Change by Steve.Robb, doing here so it is in 4.17.
Change 3489689 by Arciel.Rekman
More MallocPoisonProxy changes I missed in previous CL.
Change 3489751 by Matt.Kuhlenschmidt
Moved editor performance settings out of per-project settings so they can be shared across projects
Change 3489837 by Lauren.Ridge
Keyboard shortcut for entering/leaving VR Mode is now Alt+V
Change 3491082 by Arciel.Rekman
Linux: better fix for the crash due to name collision (UE-46040).
- Put classes in Sequencer module into Sequencer namespace instead of SceneOutliner namespace.
- Undid change in the SceneOutliner module.
#jira UE-46040
Change 3491096 by Arciel.Rekman
Fix UAT compilation on the newest mono.
Change 3491240 by Max.Chen
Sequencer: Disable key button when allow level edits only is on.
#jira UE-46060
Change 3491406 by Yannick.Lange
Fix editor crashes when opening a project that includes a plugin with more than two custom Volume classes. This issue was caused because registering show volume commands is based on finding volume classes. Finding these classes at multiple times resulted in a mismatch of the returned array of volume classes because modules/plugins were still being loaded.
#jira UE-45806
Change 3491559 by Alexis.Matte
Make sure we use the good preview mesh when doing a preview
#jira UE-45963
Change 3491563 by Alexis.Matte
Fix crash with staticmesh editor LodLevel selection
Change 3491564 by Nick.Darnell
UMG - Fixing an offset with the grab handles in HDPI mode.
Change 3491595 by Nick.Darnell
Editor - Fixing a clipping artifact in the pin type dropdown in the blueprint editor.
Change 3491604 by Nick.Darnell
Back out changelist 3489265
Change 3491615 by Arciel.Rekman
Added malloc replay proxy (Linux only for now).
- Allows to dump malloc callstream (without regard to threads) and replay later to study the behavior of different mallocs and/or repro problems.
Change 3491684 by Arciel.Rekman
Added FMalloc functions I missed.
- Also moved function bodies into the .cpp file, this does not make a difference in performance in this case.
Change 3491692 by Matt.Kuhlenschmidt
Some minor fixes to the static mesh editor
- Fix UV combo button looking non-standard on the toolbar
- Fix a few combo buttons in the details panel looking too big.
Change 3491702 by Arciel.Rekman
Do not compile replay proxy-specific code when not used.
Change 3491717 by Michael.Dupuis
#jira UE-35083:
The component is now the owner of the PerInstanceRenderData instead of the proxy
Add an Update path to only update specified instances range
Always call BuildTreeIfOutdated so we have a standard code path to make sure static mesh are fully loaded before trying to build the tree
Moved the Instance Buffer aysnc to the base class, as it's not related to UHierarchicalInstancedStaticMeshComponent
Expose a new property to decide if we require dynamic instance buffer
Change 3491758 by Matt.Kuhlenschmidt
Fix crash on static mesh editor shutdown
Change 3491873 by Cody.Albert
Fixed clipping issue in Sequencer curve editor
#rnx
Change 3491956 by Matt.Kuhlenschmidt
Fix crash opening the Previewing sub-menu in the level editor settings menu
#jira UE-46095
Change 3492046 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492076 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492165 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492222 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492274 by Michael.Dupuis
#jira UE-46105: Fixed Clang warning
Change 3492338 by andrew.porter
QAGame: Testing ensure when submitting
Change 3492371 by Nick.Darnell
UMG - Reverting the animation sharing, cossed GLEO regressions in cooking. Will look for a better solution.
Change 3492462 by Matt.Kuhlenschmidt
Fix ensure checking in files through perforce
Change 3492491 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492505 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492517 by Jamie.Dale
The package localization ID is no longer used at all at runtime, and is now truly editor-only
This should have always been the case, but it was leaked into manifest/archives/PO files in 4.14, and while 4.15 removed it from PO files it was still present in the manifest/archives. This change removes it entirely (unless gathering editor-only data, and even then the PO file will still collapse the entries together for translation), and the deprecated 4.14 export behavior will now produce an error if you attempt to use it.
After taking this change you'll need to run a gather, import, and compile of your LocRes files to update your game localization to use the new localization IDs.
Change 3492630 by Nick.Darnell
UMG - Removing some extra cleanup code that's probably overkill and is causing a crash for uses of "Within" in class meta.
#jira UE-46124
Change 3492692 by Matt.Kuhlenschmidt
Fix drop shadows inheriting the outline color of the font. The outline should still appear but not have a different outline color from fill color
Change 3492714 by Matt.Kuhlenschmidt
Added outline with drop shadow to font automation test
Change 3492737 by Matt.Kuhlenschmidt
Fix linux
Change 3492992 by tim.gautier
Resaving Ocean Widget Blueprints / Sequences to resolve Legacy Sequence Data warnings
#jira UE-46132
Change 3493089 by Jamie.Dale
Ensure that the composite font of a font asset is flushed when the font object is GC'd
Change 3493322 by Jamie.Dale
Fixing null crash
#jira UE-45758
Change 3494467 by Andrew.Rodham
Fix Xbox warning
Change 3494852 by tim.gautier
QAGame: Changed streaming method of QA-EditorSmoke-Landscape to Always Loaded
Change 3494853 by Nick.Darnell
Another attempt at fixing the automation blueprint SA warning.
Change 3494896 by Arciel.Rekman
Fix possible null pointer access during Vulkan init.
- May fix static analysis warnings in UE-46142, although warnings seem to be referring to something else.
#jira UE-46142
Change 3494987 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3495010 by Matt.Kuhlenschmidt
Adding additional logging to track down html5 issue
Change 3495212 by Michael.Dupuis
#jira UE-46143: Properly init the InstanceRenderData during the cooking phase (required by fortnite)
Change 3495536 by Jamie.Dale
Updating UGameEngine to call its Super::PreExit after performing its own teardown
This prevents UEngine cleaning up resources that UGameEngine still needs.
#jira UE-46159
Change 3495551 by Arciel.Rekman
Another attempt to fix analyzer problem (UE-46142).
Change 3495794 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3495905 by Matt.Kuhlenschmidt
Fix USD crash when importing a meshwith no material
[CL 3499771 by Matt Kuhlenschmidt in Main branch]
2017-06-19 20:27:30 -04:00
{
if ( MorphTarget - > HasDataForLOD ( DesiredLOD ) )
{
2021-09-07 10:20:14 -04:00
MorphTarget - > GetMorphLODModels ( ) . RemoveAt ( DesiredLOD ) ;
Copying //UE4/Dev-Editor to //UE4/Dev-Main (Source: //UE4/Dev-Editor @ 3497164)
#lockdown Nick.Penwarden
#rb none
=====================================
MAJOR FEATURES + CHANGES
=====================================
Change 3433074 by Matt.Kuhlenschmidt
Fix crash when clicking on certian tutorial blueprints.
#jira UE-44593
Change 3433075 by Matt.Kuhlenschmidt
Remove hittest grid log spam. The underlying problem causing this has been fixed
Change 3433077 by Matt.Kuhlenschmidt
Fix lighting becoming unbuilt when mesh painting
#jira UE-44837
Change 3433081 by Matt.Kuhlenschmidt
PR #3553: Crashfix for static array properties (Contributed by Pierdek)
Change 3433104 by Alexis.Matte
Make sure re-import skeletal mesh follow the import morph option
#jira UE-42846
Change 3434825 by Matt.Kuhlenschmidt
Fix crash when GC happens while the vr editor radial menu is open.
Change 3434831 by Matt.Kuhlenschmidt
Added missing file
Change 3434868 by Shaun.Kime
If you have a reroute node between a Material Function texture input and its usage, the parent material will fail to resolve the reroute node.
#jira ue-44670
Change 3434998 by Alexis.Matte
Meshes editors material/section panel are now fully transactional
- Staticmesh editor: section material slot, section cast shadow, section collision, material slot instance, material slot name
- Skeletal mesh editor: material slot instance, material slot name
Also fix some transaction description
#jira UE-44462
Change 3435195 by Jamie.Dale
Fixed incorrect handling of some LTR scripts that require shaping
These scripts need to go through HarfBuzz, and this also fixes a case where HarfBuzz wasn't applying font scale correctly.
#jira UE-44767
Change 3435199 by Jamie.Dale
Fixed some crashes/artifacts with bidirectional text
It was possible for a line to compute an incorrect range, which could cause crashes or other highlighting issues. The highlighting logic has also been updated as the old code didn't handle all bidirectional cases correctly.
Change 3435200 by Jamie.Dale
Fixed a grapheme cluster metrics issue in the font editor viewport
The viewport also now respects the default shaping method CVar.
Change 3435771 by Alexis.Matte
Fix degenerated bounds calculation for skeletalmesh when the skeleton is remove from a re-import
(PhysicAsset API change, adding 1 function)
#jira UE-44609
Change 3436856 by Jamie.Dale
Added some missing Unicode block ranges
Change 3436914 by Jamie.Dale
Adding some missing combining character ranges to the text shaper
Change 3436923 by Alexis.Matte
PR #3463: Get bounds for all triangles, not just the first one. WedgeIndex was . (Contributed by DaveC79)
#jira UE-43764
Change 3436948 by Jamie.Dale
Updated the Portal to use the predefined Unicode block ranges
Change 3436961 by Max.Chen
Sequencer: Show camera shake/anim track menus even if there aren't any assets.
Change 3437244 by Max.Chen
Sequencer: Clear locked cameras when releasing Sequencer.
#jira UE-44967
Change 3437515 by Arciel.Rekman
UBT: improvements for LocalExecutor.
- Larger number of parallel jobs on 16GB+ machines.
- Use WaitForExit() instead of polling.
- Tested on Linux and Mac.
Change 3437629 by Matt.Kuhlenschmidt
Improve asset import data display in static and skeletal meshes
Change 3438047 by Arciel.Rekman
Fix overlapping ranges being passed to memcpy().
Change 3438822 by Yannick.Lange
ViewportInteraction: Move gizmo handle files to make them private.
Change 3438906 by Matt.Kuhlenschmidt
PR #3556: Git Plugin: fix new option "init Git LFS" that make assets read-only (master/UE4.17) (Contributed by SRombauts)
Change 3438907 by Matt.Kuhlenschmidt
PR #3565: add -quality option to buildlighing commandlet (Contributed by kayama-shift)
Change 3438908 by Matt.Kuhlenschmidt
PR #3558: UE-44862: Always update SColorPicker color on OK button (Contributed by projectgheist)
Change 3439393 by Matt.Kuhlenschmidt
Force highest LOD for highres screenshots
Change 3439819 by Matt.Kuhlenschmidt
Turned FAssetData into a struct for some upcoming script exposure of FAssetData
Change 3439949 by Arciel.Rekman
Fixed selection logic for the UE4_LINUX_USE_LIBCXX environment variable.
- Allows disabling libc++ by setting the variable to 0.
- Pull request #3576 contributed by jared-improbable.
Change 3441078 by Jamie.Dale
The culture/language/locale console commands are now available in all build configs
Change 3441109 by Jamie.Dale
Text containing surrogate pairs now runs through HarfBuzz when shaping in Auto mode
This is needed as the kerning-only shaping code assumes that everything is within the BMP
Change 3441275 by Matt.Kuhlenschmidt
Disable spinning on location and scale. These dont work because we have no notion of infinite spinning
Change 3442748 by Yannick.Lange
ViewportInteraction: Remove unused console variables.
Change 3442775 by James.Golding
Add support for editing MaterialFunctions to MaterialEditingLibrary
Pull Material recompile/update code into UMaterialEditingLibrary::RecompileMaterial
Pull MaterialFunction update code into UMaterialEditingLibrary::UpdateMaterialFunction util
Move RebuildMaterialInstanceEditors to UMaterialEditingLibrary
Added test content for Material/MaterialFunction editing
Add needed BlueprintReadWrite to expressions (constants, function input/output)
Expose UMaterialExpressionMaterialFunctionCall::SetMaterialFunction to BP, rename old func (which takes old function) to SetMaterialFunctionEx, also expose GetInputNameWithType
Change 3442779 by James.Golding
Fix header order
Change 3442817 by Yannick.Lange
ViewportInteraction: Add can execute checks for level editor commands.
Change 3443038 by Michael.Dupuis
#jira UE-43377: When you select a foliage actor we will move all instance contained in it to the new level as we can't move a foliage actor
Only permit moving foliage instance if there is some selected
Change 3443855 by Michael.Dupuis
#jira UE-44885: Unregister from PerModuleDataObjects when the object is destroyed
Change 3446096 by Max.Chen
Sequencer: Add OnFinished() event when a level sequence completes playback
#jira UE-45173
Change 3446097 by Max.Chen
Sequencer: Evaluate one last time before the sequence is torn down and reset
#jira UE-45174
Change 3446242 by Jamie.Dale
Fixed caret not appearing in empty text layouts
Caret selections have no range, and therefore have no width
Change 3446361 by Matt.Kuhlenschmidt
Fix WITH_EDITOR only functions causing generated code compile errors when the all functions on the class are WITH_EDITOR
Change 3446457 by Alexis.Matte
Polish the speed tree import dialog
#jira UE-44963
Change 3446946 by Michael.Trepka
Modified FWindowsWindow::GetRestoredDimensions to return correct window position for normal windows for which GetWindowPlacement returns position in workspace coordinates
#jira UE-37934
Change 3447543 by Arciel.Rekman
Reduce VMAs on Linux.
- Trades off increased address space (VIRT in terms of ps/htop) for smaller number of distinct mappings (VMAs, virtual memory areas).
This decreases possibility to run into vm.max_map_count limit on Linux.
- Tested on Linux and Mac.
Change 3448468 by Arciel.Rekman
Fix race condition during creation of GMalloc.
- On Mac GMalloc can be created on two different thread that are racing with each other - app's main thread and a system thread.
Change 3449012 by Max.Chen
Sequencer: Add time to transform, color and vector key structs so that key times are editable from the key editors.
#jira UE-45089
Change 3449018 by Max.Chen
Sequencer: Add OnCameraCut event that fires when there is a camera cut.
#jira UE-45137
Change 3449195 by Max.Chen
Sequencer: Add setting for limit scrubbing to playback range.
#jira UE-43502
Change 3449198 by Max.Chen
Sequencer: Reorder hierarchical bias so that group priority takes precedence.
Change 3449217 by Max.Chen
Sequencer: Add setting to activate realtime viewports when in sequencer.
Change 3449219 by Max.Chen
Sequencer: Focus on search boxes when opened.
Change 3449238 by Max.Chen
Sequencer: Assign actor should replace the actor itself after it has updated all the components. Also, replace components be fullname rather than by class.
Change 3449239 by Max.Chen
Sequencer: Fix offsets when moving multiple sections. Dragging should be clamped to the bounds that any of the selected sections hits against the unselected sections.
Change 3449241 by Max.Chen
Sequencer: Restore section selection after full tree rebuild.
Change 3449279 by Max.Chen
Sequencer: Set movie scene capture frames only when not using custom frames. This allows the user entered frame numbers to persist in config, rather than overwriting them when doing a "Render Shot"
Change 3449280 by Max.Chen
Sequencer: Spawn in the persistent level. Otherwise, they get spawned into whatever sublevel is current.
#jira UE-44552
Change 3449294 by Max.Chen
Sequencer: Null check for sequencer ed mode crash.
Change 3449297 by Max.Chen
Sequencer: Fix delay in sliding values. Mark changed when sliding values. Mark refresh immediately when committing values since OnValueChanged will be called and needs to have the correct value that was refreshed immediately.
#jira UE-42866
Change 3449542 by Max.Chen
Sequencer: Fix scrubber hit testing so that the time scrubber is really favored over the playback ranges.
#jira UE-44569
Change 3451507 by Matt.Kuhlenschmidt
Fix extra slate uv coords not functioning on ES2
Change 3451510 by Matt.Kuhlenschmidt
PR #3595: Fixed wrong colour for level status (Contributed by ronve)
Change 3451529 by Alexis.Matte
fbx scene importer: Make sure we set INVALID_UNIQUE_ID to node that has no attribute.
#jira UE-34410
Change 3451611 by Yannick.Lange
ViewportInteraction: Dragging gizmo without second pass for snapped calculations.
Change 3452134 by Jamie.Dale
Fixed constant font cache flushing if a widget had no font set
Change 3452239 by Jamie.Dale
Fixed constant font measure flushing if a widget had no font set
Change 3452243 by Jamie.Dale
Removed deprecated code for creating fonts from bulk data
Change 3452277 by Jamie.Dale
The concept of "stale" composite fonts is now editor-only
Change 3452358 by Alexis.Matte
Fbx scene importer: Do not remove existing attribute reference from the blueprint if the reimport of the associate mesh attribute is not tick.
#jira UE-45232
Change 3452678 by Max.Chen
Sequencer: Fix crash on export if there's no shot data.
Change 3453057 by Matt.Kuhlenschmidt
Exposed asset exporting to script
Change 3453782 by Andrew.Rodham
Sequencer: Fixed deterministic cooking issues with movie scene data
- Movie scene signatures are now initialized in PostInitProperties
- A warning is now presented when attempting to cook old data that was never serialized with a signature.
- Removed redundant legacy data upgrade logic that could dirty level sequences on load.
#jira UE-44912
Change 3453788 by Yannick.Lange
ViewportInteraction: Custom scene proxy for gizmo handles.
Change 3453938 by Max.Chen
Sequencer: Hotkeys (shift , and shift .) to step to next/previous shot
#jira UE-45119
Change 3454058 by Michael.Dupuis
Fixed StaticAnalysis
Change 3454077 by Max.Chen
Sequencer: Fix not saving the pre-animated track value when creating a track/key.
On pre object change, broadcast property change so that a track or key can be created. That track/key needs to be evaluated immediately so that the pre-animated state can be saved properly. This is done now with RefreshAllImmediately and is only called when a track has been created. Also, added a return value for OnKeyProperty, so that it's known what changed in particular (ie. track created, track modified, etc)
Also, fixed transform keying so that if a transform track already exists for the object or the scene component, the existing track is used.
#jira UE-45130
Change 3454108 by Nick.Darnell
UMG - Fixing the WIC to properly record cursor delta so that scrollbars work.
Change 3454109 by Jamie.Dale
Cache the text layout source info in non-shipping builds so you can inspect it in the debugger
Change 3454202 by Matt.Kuhlenschmidt
Fix bogus error message about the number of usable texture coordinates on ES2 when compiling a UI domain material
Change 3454390 by Yannick.Lange
Fix creating a plugin in a C++ project opens a second instance of Visual Studio. Use SourceCodeAccessor to open solution when necessary.
#jira UE-45035
Change 3454564 by Matt.Kuhlenschmidt
#rnx Fix deprecation warnings
Change 3455471 by Yannick.Lange
ViewportInteraction: Fix entering and exiting VR Mode disables gizmo in desktop editor viewport.
#jira UE-44965
Change 3456183 by Max.Chen
Sequencer: Auto key, auto track refactor.
Auto key - create a key when the property changes and there's an existing track.
Auto track - create a track when the property changes. This is only exposed in the level sequence editor.
All - create a key and a track when the property changes. This is only exposed in VR Editor.
None - do nothing.
#jira UE-43469
Change 3456349 by Andrew.Rodham
Sequencer: Only perform legacy signature checks on instances, and only where signatures match the CDO
Change 3456678 by Alexis.Matte
Allow to add null level instance override material via the advance material array. But still limit the override material number to the mesh material number.
#jira UE-45306
Change 3456945 by Max.Chen
UMG: Add restore state to 2d transform section.
#jira UE-45372
Change 3457196 by Arciel.Rekman
Linux: serialize allocations from the memory pool.
Change 3458434 by Max.Chen
Sequencer: Remove obsolete set tick prerequites functions.
Change 3458671 by James.Golding
Added MIC editing support to MaterialEditingLibrary
Fix static analysis warning
Change 3458888 by Matt.Kuhlenschmidt
PR #3615: More detailed log messages for debugging warnings/errors (Contributed by projectgheist)
Change 3458893 by Matt.Kuhlenschmidt
PR #3583: UE-44960: Delta value wasn't being used (Contributed by projectgheist)
Change 3458895 by Matt.Kuhlenschmidt
Fix typo
Change 3458902 by Matt.Kuhlenschmidt
PR #3607: Improved InputKeySelector functionality (Contributed by projectgheist)
Change 3458917 by Matt.Kuhlenschmidt
Fix crash with invalid object properties in the class picker
#jira UE-39000
Change 3458939 by Matt.Kuhlenschmidt
Fix compile error
Change 3458984 by andrew.porter
QAGame: Initial check in of sequencer smoke test map
Change 3459510 by Matt.Kuhlenschmidt
Fixed ensure when deleting a map that contains build data which also happens to be the currently loaded map.
#jira UE-45052
Change 3460985 by Max.Chen
Sequencer: Snap play time to keys now allows scrubbing between keys and snaps to key times within a certain screenspace tolerance.
#jira UE-45090
Change 3461698 by Arciel.Rekman
Avoid using ARRAY_COUNT in Vulkan.
- Sometimes those arrays can have no extensions whatsoever, and it is illegal to declare a 0 element C array.
Change 3462053 by Max.Chen
Sequencer: Show sequencer spawnables in the world outliner and add the icon overlay for spawnables.
#jira UE-43470
Change 3462139 by Max.Chen
Property Editor: Add objects to FPropertyAndParent
Change 3462202 by Arciel.Rekman
Fix FSocket::Recv() blocking with Peek when there's no data.
Change 3462253 by Nick.Darnell
Slate - New Clipping System
Clipping is now a stateful choice made during composition of the slate hierarchy. Previously every widget got to respect or modify the clipping rect on an as needed basis. The problem was that clipping was only allowed in the layout space of the widget, and it wasn't possible to properly clip elements with render transforms. The new system permits all kinds of transforms on any widget, and they will all be clipped correctly. It tries to use Scissor Rects as they are much cheaper, but will switch over to stenciling if need be to represent a complicated masking structure with several rotated clipping rects all needed to be combined together.
Here are the new clipping states a widget can have, almost all widgets are set to No. Only change it from No if your widget actually needs to clip, generally speaking most widgets don't need to clip.
/**
* This widget does not clip children, it and all children inherit the clipping area of the last widget that clipped.
*/
Inherit,
/**
* This widget clips content the bounds of this widget. It intersects those bounds with any previous clipping area.
*/
ClipToBounds,
/**
* This widget clips to its bounds. It does NOT intersect with any existing clipping geometry, it pushes a new clipping
* state. Effectively allowing it to render outside the bounds of hierarchy that does clip.
*
* NOTE: This will NOT allow you ignore the clipping zone that is set to [Yes - Always].
*/
ClipToBoundsWithoutIntersecting UMETA(DisplayName = "Yes - Without Intersecting (Advanced)"),
/**
* This widget clips to its bounds. It intersects those bounds with any previous clipping area.
*
* NOTE: This clipping area can NOT be ignored, it will always clip children. Useful for hard barriers
* in the UI where you never want animations or other effects to break this region.
*/
ClipToBoundsAlways UMETA(DisplayName = "Yes - Always (Advanced)"),
/**
* This widget clips to its bounds when it's Desired Size is larger than the allocated geometry
* the widget is given. If that occurs, it behaves like [Yes].
*
* NOTE: This mode was primarily added for Text, which is often placed into containers that eventually
* are resized to not be able to support the length of the text. So rather than needing to tag every
* container that could contain text with [Yes], which would result in almost no batching, this mode
* was added to dynamically adjust the clipping if needed. The reason not every panel is set to OnDemand,
* is because not every panel returns a Desired Size that matches what it plans to render at.
*/
OnDemand UMETA(DisplayName = "On Demand (Advanced)")
- Large API Change -
All FSlateDrawElement::Make_____ calls have been deprecated that involved passing in a clipping rect. You no longer should are passed a Clipping rect via OnPaint. You are still passed a rect, but this rect represents a Culling Rect, which is valuable if you need to just out right not paint things the user can't possibly see.
If you were previously trying to determine if you should cull widgets, by doing something like this,
if ( FSlateRect::DoRectanglesIntersect(MyClippingRect, CurWidget.Geometry.GetRenderBoundingRect()) )
That's no longer a good option since there are ways for widgets to ignore the culling bounds. You should convert anything like above to the one below,
if (!SWidget::IsWidgetCulled(MyCullingRect, CurWidget))
To assist in debugging efforts, there are several new debugging console flags in Slate,
Slate.ShowClipping 1 - Controls whether we should render a clipping zone outline. Yellow = Axis Scissor Rect Clipping (cheap). Red = Stencil Clipping (expensive).
Slate.DebugCulling 1 - Disables pushing clipping or stencil rects to the GPU, but continues to intersect culling rects, so that you can tell if a widget is properly culling children it can't possibly draw.
Slate.ShowTextDebugging 1 - Show debugging painting for text rendering.
I've added a new Experimental Feathering Option, it adds AA geometry around the outside of Box and Image brushes.
Slate.Feathering 1
If you're using RenderDoc or something similar, you can now enable render events for slate, so that you can better grok how we're batching and changing states for each UI render pass.
Slate.EnableDrawEvents 1
#jira UE-4659
#rn
Change 3462714 by Nick.Darnell
Fixing a few more compiler issues with the clipping changes.
Change 3462726 by Max.Chen
Switch OnEditStructChildContentsChanged to use FObjectWriter instead of FMemoryWriter which supports serializeing UObjects. This fixes a crash when adding actor array elements to a user defined event struct.
#jira UE-45431
Change 3462801 by Nick.Darnell
Adding a UMG dependency to EngineTestBuild.
Change 3462914 by Max.Chen
Sequencer: Fix regression where spawnables aren't getting saved. Caused by 3407138
#jira UE-30007
#jira UE-39003
Change 3462946 by Nick.Darnell
Automation - Tweaking the UI automation tests converting them over to use the new UI Screenshot automation test.
Automation - Adding a blur widget test.
Change 3462987 by Matt.Kuhlenschmidt
Back out changelist 3458893
Change 3464774 by Matt.Kuhlenschmidt
PR #3629: Bugfix: Missing small icon in Project Launcher profile editor (Contributed by aarmbruster)
Change 3464785 by Nick.Darnell
Fixing some clipping stuff in the editor.
Change 3464830 by andrew.porter
QAGame: Second pass on sequencer smoke test map
Change 3464902 by Nick.Darnell
Loading - Adding some additional checks to the the loading code to ensure we're on the main thread. Additionally adding a fix from UDN that prevents deadlocks in the rare case a user hits Alt+Tab in a fullscreen game while in a hard loading screen.
Change 3464988 by Max.Chen
Sequencer: Add attenuation settings for attached audio components.
#jira UE-33080
Change 3465024 by Nick.Darnell
MoviePlayer - Impoving the playback mode displaynames.
Change 3465074 by Arciel.Rekman
Fix shadowing issues of GraphicsPSOInit.
Change 3465097 by Matt.Kuhlenschmidt
Some refactoring of the details panel
Exposed new methods of adding a struct on scope to a details panel and have it work properly with customizations. The scruct on scope has a "fake" ustructproperty that allows the details panel to show the whole struct not just an individual property.
Refactored the API for adding rows to details panels to make it more consistent\
AddChildCustomBuilder->AddCustomBuilder
AddChildGroup->AddGroup
AddChildContent->AddCustomRow
AddChildPropert->AddProperty
AddChildStructure->AddExternalStructureProperty
AddStructure->AddAllExternalStructureProperties
AddExternalProperty->AddExternalObjectProperty or AddExternalStructureProperty
Change 3465186 by Max.Chen
Sequencer: Save the BindingID in the pre animated token producer so that it can be destroyed properly. This fixes a bug where the default state of a spawnable isn't saved.
#jira UE-43780
Change 3465315 by Matt.Kuhlenschmidt
Fix Fortnite and Orion details panel customization warnings
Change 3465424 by Nick.Darnell
Automation - Moving the step for setting the link to the automation reports to be set before we start the engine.
Change 3465488 by Nick.Darnell
Automation - Forcing textures to load before taking screenshot, so that the scene gets another opportunity to render before we render with Slate. This should fix the Blur UI Test.
Change 3466277 by Arciel.Rekman
Linux: fix window drift when dragging (UE-40380).
- Change by Cengiz Terzibas.
Change 3466370 by Nick.Darnell
UMG - Fixing the colors for the resize handle in the designer.
Change 3466372 by Nick.Darnell
UMG - Fixing the ruler ticks sometimes not being drawn.
Change 3466374 by Nick.Darnell
UMG - Fixing the designer showing multiple options for sequencer.
Change 3466377 by Nick.Darnell
UMG - Cleaning up some clipping bits.
Change 3467025 by Andrew.Rodham
Re-saving assets that contain legacy (<4.15) movie scene data to remove deterministic cook warning.
If conflicts arise during merging of these assets, please ignore the changes made in dev-editor, and accept game-side changes.
(CIS step 62283298, jobId 7773146)
(CIS step 62283297, jobId 7773146)
Change 3467099 by Max.Chen
Fix GetObjectPropertyClass ensure logic. This was returning UObject::StaticClass when valid.
Change 3467172 by Max.Chen
Sequencer: Evaluation optimizations. Also, fixes subsequences not getting expired, leaving dangling spawnables.
#jira UE-43690
Change 3467192 by Matt.Kuhlenschmidt
Fix transactions getting stuck in the color grading controls. This prevents PIE from working properly and causes shutdown crashes
#jira UE-45527
Change 3467251 by Yannick.Lange
ViewportInteraction: Fix scale and rotation snap while dragging with two lasers.
#jira UE-43489
Change 3467331 by Matt.Kuhlenschmidt
Fix D3D shader compiler hard coding shader path and not giving proper warnings when it cannot find the shaders
Change 3467335 by Matt.Kuhlenschmidt
Remove DarkStyle attribute from SNumericEntryBox and allow a spin box style to be passed to it.
Change 3467558 by Max.Chen
Scene Outliner: Generic support to add default columns to a scene outliner.
Change 3467565 by Jamie.Dale
Removing old screenshot data for test
Change 3467589 by Nick.Darnell
Editor - Random cleanup.
Change 3467596 by Nick.Darnell
Progress Bar - Exposing Border Padding to UMG.
Change 3467600 by Nick.Darnell
Slate - Adjusting the rendering of the splitter, previously it could be off by a pixel or two, which becomes more apparent now with the clipping changes.
Change 3467601 by Max.Chen
Property Editor: Fix static analysis warning
Change 3467662 by Nick.Darnell
Automation - Fixing a bug with the screenshot comparison tool not replacing (removing) the old screenshot data.
Change 3467674 by Max.Chen
Property Editor: Fix static analysis warning
Change 3467737 by Max.Chen
Sequencer: Added OnMovieSceneBindingsChanged delegate
Change 3468053 by tim.gautier
QAGame: Updating Editor Smoke Map
- Updated landscapes into Stations for testing
- Added Foliage Sublevel
Change 3468194 by Arciel.Rekman
Linux: fix problems communicating with various STL-using libs.
- Stop hiding global new/delete signatures.
- Disable CEF3 since this change uncovers the problem with libcef.so not built to use bundled libpng.
Change 3468678 by Max.Chen
Sequencer: Set "Sequencer Actor" tag before setting the actor label so that the outliner refreshes after the actor has the tag.
Change 3469314 by tim.gautier
QAGame: Added Painted Foliage / Spline section to EditorSmoke map
Change 3469377 by Nick.Darnell
Slate - Fixing some warnings in a couple of sample games due to the clipping changes.
#rnx
Change 3469767 by Max.Chen
Sequencer: Outliner column and sequencer binding data
#jira UE-43470
Change 3469974 by Arciel.Rekman
Fix code projects not working in Linux installed build.
Change 3470082 by Nick.Darnell
Slate - The GetRenderer() call on SlateApplication no longer returns a SharedPtr, rather than convert it to a thread safe ptr, going to just make accessing it a raw ptr return, so it can be safely referenced on the game thread while being used on the slate loading thread.
Change 3470174 by Nick.Darnell
Slate - Get the last widget in a widget path utility.
Change 3470176 by Nick.Darnell
UMG - User Widgets now have an easy way to know if they're part of or have been removed from the focused widget path, which is handy for doing effects.
Change 3470261 by Nick.Darnell
Slate - The GetRenderer() call on SlateApplication no longer returns a SharedPtr, rather than convert it to a thread safe ptr, going to just make accessing it a raw ptr return, so it can be safely referenced on the game thread while being used on the slate loading thread.
Change 3470286 by Max.Chen
Sequencer: Scene Component's HiddenInGame now goes through the VisibilityTrack and the visibility template.
Change 3470366 by Nick.Darnell
Slate - We now version focus per user, that way during focus events, we can safely abort focus events and state transitions if someone interrrupts the active focus event with something new.
Change 3470649 by Matt.Kuhlenschmidt
Fix deprecation warnings
Change 3470695 by Matt.Kuhlenschmidt
Fixed typo
#jira UE-45580
Change 3470721 by Matt.Kuhlenschmidt
Fix static analysis
Change 3471254 by Michael.Dupuis
#jira UE-42952: Keep occlusion result per view
Change 3471287 by Nick.Darnell
UMG - Render Focus Rule now defaults to never.
Change 3471291 by Nick.Darnell
Slate - Fixing FSlateRenderer* change fallout.
Change 3471299 by Nick.Darnell
Slate - Fixing FSlateRenderer* change.
Change 3471323 by Nick.Darnell
Automation - Fixing automation and Static Analysis warning.
Change 3471413 by andrew.porter
QAGame: Added test content for anim blending and material parameteres to sequencer smoke level
Change 3471649 by Max.Chen
Sequencer: Modify the track when adding animation
#jira UE-45618
Change 3471659 by Matt.Kuhlenschmidt
Added a way to check if a movie is playing from the engine.
Prevented viewport redraws for canvas loading screens if a slate based loading movie is playing
Change 3471734 by Matt.Kuhlenschmidt
Added basic material hookup to USD. Similar to FBX it will find materials based on rules specified by the user in the import settings
Change 3472176 by Nick.Darnell
UMG - Improving the display of the +Track menu in sequencer for UMG. Renamed it from +Add, which is repetitve to +Track. Additionally, the dropdown now shows the currently selected widgets, as well as a submenu containing all the 'important' widgets, so we no longer populate that list with a ton of irrelevant widgets that are just Buton_1 - N, which is pointless in showing people, they'll never guess which is the right button.
Change 3472740 by Max.Chen
Sequencer: Add GetThisFrameMetaData accessor
Change 3472748 by Max.Chen
Sequencer: Added OnBeginScrubbing and OnEndScrubbing event delegates
Change 3472753 by Max.Chen
Sequencer: Add EMovieSceneDataChangeType parameter to OnMovieSceneDataChanged delegate
Change 3472870 by Nick.Darnell
Clipping - Fixing the deprecated tip for scissor rect boxes to be correct. Removing it's usage from UT.
Change 3473340 by Max.Chen
Scene Outliner: Add ability to register additional filters
Change 3473348 by Max.Chen
Details View: Make ForceRefresh virtual. Added accessors to delegates (ie. GetIsPropertyReadOnlyDelegate)
Change 3473441 by Max.Chen
Sequencer: Autokey Refactor Part 2.
Autokey is now a single toggleable state.
Allow Edits Mode has 3 states:
Allow All Edits - Allow any edits to occur, some of which may produce tracks/keys or modify default properties.
Allow Sequencer Edits Only - All edits will produce either a track or a key.
Allow Level Edits Only - Properties in the details panel will be disabled if they have a track.
#jira UE-45229
Change 3473670 by Nick.Darnell
Modules - The module manager no longer returns sharedptrs to IModuleInterfaces, this was the source of rare hard to track down crashes due to a shared ptr reference leak when GetModule was called on non-main threads. We now store a TUniquePtr internally, and only lease out raw pointers.
#rn
Change 3473711 by Nick.Darnell
Disabling the ensure in the module manager.
Change 3473747 by Max.Chen
Sequencer: Fix tooltip
Change 3474091 by Jamie.Dale
Added a warning when cooking a UFontFace that is outered to a UFont asset
These cause issues with iterative COTF, and should be split off into their own assets (as the UI has been asking people to do for several versions)
Change 3475052 by Yannick.Lange
VR Editor: Fix Crash when quitting the editor with VR Mode enabled. VR Editor was being enabled when saving the map on closing the editor.
#jira UE-45415
Change 3475054 by Yannick.Lange
Fix crash when adding a camera to the world in VR Mode the second time. The slate application did not reset when stop dragging in VR Mode, so the second time when starting to drag a camera out of the UI it would already by in a dragging state.
#jira UE-45574
Change 3475263 by Nick.Darnell
Fixing some additional cases of IModuleInteface SharedPtr usage.
Change 3475268 by Max.Chen
Sequencer: Set jumped state when looping playback. This fixes an issue where audio doesn't stop and restart when looped.
#jira UE-45654
Change 3475269 by Max.Chen
Scene Outliner: Additional filters should only apply to actor browsing mode
Change 3475407 by Nick.Darnell
Fixing some clipping / module shared ptr changes in the launcher code.
Change 3475542 by Max.Chen
Sequencer: Update thumbnail and section highlighting to use new clipping behavior.
#jira UE-45692
#jira UE-45689
Change 3475743 by Michael.Dupuis
#jira UE-45183: When updating phyx region take into account simple collision mip
Change 3475949 by Arciel.Rekman
Remove PhysX deoptimization (no longer needed).
- OR-24947 has been closed three months ago.
Change 3476022 by Michael.Dupuis
#jira UE-45560: Make sure we're not going out of range
Change 3476063 by Michael.Dupuis
#jira UE-45562: Do not try to unregister from static mesh if no static mesh is specified for the component
Change 3476168 by Michael.Trepka
Added handling of directory symlinks to FApplePlatformFile::IterateDirectory
#jira UE-43704
Change 3476172 by Nick.Darnell
Fixing a Imoduleinterface change.
Change 3476183 by Jamie.Dale
Exposing GoTo/ScrollTo to single-line editable text for API parity with multi-line editable text
Change 3476385 by Arciel.Rekman
Linux: handle symlinks when iterating directories.
Change 3476522 by Michael.Trepka
Solved a problem with Mac FMallocTBB::Malloc() returning nullptr for 0 bytes allocations, which is inconsistent with other platforms. On Mac we always scalable_aligned_malloc, which behaves differently than scalable_malloc, so for 0 bytes requests we allocate sizeof(size_t), which is exactly what scalable_malloc does internally in such case.
Change 3476806 by Nick.Darnell
UMG - Focus the designer after dropping a widget onto the surface.
Change 3476809 by Nick.Darnell
Curve Editor - Enable Clipping on the curve editor.
Change 3477475 by Nick.Darnell
Fixing a module interface shared ptr usage in UT.
Change 3477553 by Yannick.Lange
VR Editor: Removed AssetEditorPanelID and replaced it with TabManagerPanelID. A panel for AssetEditorPanelID was never created making it impossible to open an asset editor.
Change 3477734 by Yannick.Lange
VR Editor: Fix Warning: SetRelativeScale3D : Invalid Scale entered (X=inf Y=inf Z=inf). Resetting to 1.f. warning when adding CineCameraActor to World from Modes Panel. Make sure to not divide by zero when there is no boundary scale.
#jira UE-44933
Change 3477761 by Jamie.Dale
Some improvements to avoid loading the native .locres files twice when we don't need to
Change 3477780 by Nick.Darnell
PR #3250: Return correct VirtualUserIndex (Contributed by projectgheist)
Change 3477786 by Nick.Darnell
PR #3650: Changed TestNull to accept const pointers. (Contributed by e-agaubatz)
Change 3477795 by Nick.Darnell
PR #2844: UE-36936: Don't stretch container for Plugin Image (Contributed by projectgheist)
Change 3478092 by Nick.Darnell
PR #2341: Optional Middle Mouse Button panning in Graph Editor (Contributed by flipswitchingmonkey)
Engine Edit - Made some small changes to the enum type, and some naming.
Change 3478450 by Nick.Darnell
Fixing some uninitialized variable errors.
Change 3479827 by Andrew.Rodham
Sequencer: Addressed serialization issues with some struct types
Change 3479874 by Jamie.Dale
Fixed "NativeGameLanguage" not being used correctly during localization initialization
Change 3480012 by Andrew.Rodham
Sequencer: Fixed loading tagged properties as native for track identifiers
#jira UE-45823
Change 3480337 by Alexis.Matte
Fix morph target crash missing some valid index check
Change 3480804 by Alexis.Matte
Fix crash with ColorGradingMode custom detail
#jira UE-45638
Change 3480892 by Andrew.Rodham
Sequencer: Ensure that movie scene sequences know about the editor object version
#jira UE-45842
Change 3481073 by Nick.Darnell
Fix the shader compiler error from main in Slate.
Change 3481303 by Nick.Darnell
UMG - Fixing a bug with the drag handle not working correctly in HDPI mode.
Change 3481308 by Nick.Darnell
Slate - Tweaking the IsWidgetCulled logic to consider both the layout and rendering bounds. If we do this, we get a much more desireable outcome for people that want to animate widgets and such and plan to have temporary animations to move the widget offscreen, but want the layout bounds to anchor that widget in the visible frame so that it animates even when normally it would be culled b/c the render transform and therefore the renderbounds moved it completely outside the culling rect.
Change 3481629 by Max.Chen
Sequencer: Add Level Sequence Actor as an output for CreateLevelSequencePlayer()
#jira UE-45785
Change 3481899 by Yannick.Lange
VR Editor: Added debug modetoggle command with an event that is broadcasted whenever this happens. Currently this is used to show all the floating UIs of the UI system to debug without HMD using VREd.ForceVRMode.
Change 3481984 by Michael.Dupuis
#jira UE-45845: always validate if we have a static mesh before trying to access it as user can decide to not assign one and use the tools
Change 3482047 by Nick.Darnell
Slate - Adding some comments to IsWidgetCulled.
Change 3482110 by Nick.Darnell
Slate - IsWidgetCulled is no longer static and is now called IsChildWidgetCulled.
Change 3482136 by Jamie.Dale
The CamelCase break iterator now treats digits around character tokens as part of the identifier
Change 3482138 by Michael.Dupuis
#jira UE-45854: Properly unregister during undo operation
Change 3482150 by Michael.Dupuis
#jira UE-45845 : Add missing nullcheck for GetStaticMesh
Change 3482153 by Nick.Darnell
Slate - IsWidgetCulled is no longer static and is now called IsChildWidgetCulled.
Change 3482180 by Nick.Darnell
UMG - Widget Components do not need to define a widget class to be rendererd, they can have native slate widgets only. This was a regression from main.
Change 3482273 by Nick.Darnell
UMG - Tweaking some more things about the widget component box outline.
Change 3482308 by Alexis.Matte
Fixing morph target smooth group support. Do not call FillSkeletalMeshImportData more then once on FbxNode since this fonction is doing some conversion and change the FbxNode, applying those conversion twice do not return the same faces smooth group.
#jira UE-45696
Change 3482327 by Nick.Darnell
UMG - More tweaks to the WidgetComponent so both shows the box outline, but works in game and VR editor.
Change 3482705 by Andrew.Rodham
Resaving assets that contain legacy data to suppress CIS warnings.
- If conflicts arise in these assets, please take game-side changes and ignore these.
Change 3484245 by Max.Chen
Sequencer: Evaluate on end scrub. This fixes a bug where audio doesn't evaluate in a stopped position at the end of scrubbing, causing it to not stop all sounds. This fixes a bug introduced from 3365018 where evaluate on end scrub was removed.
#jira UE-45905
Change 3484263 by Max.Chen
Sequencer: Fix crash on forcing refresh of details panel on release.
#jira UE-45911
Change 3484431 by Andrew.Rodham
Resaving assets that contain legacy data to suppress CIS warnings.
- If conflicts arise in these assets, please take game-side changes and ignore these.
Change 3484474 by Alexis.Matte
Fix the morph target animation curve name matching.
#jira UE-20294
Change 3484475 by Alexis.Matte
When removing a LOD, make sure we remove all morph target data associate to the LOD.
Change 3484489 by Nick.Darnell
PR #3668: UE-45908: Cache debug line locations when performing a LineTraceMulti (Contributed by projectgheist)
#jira UE-45908
Change 3484692 by Nick.Darnell
Slate - Reverting a change from a game stream. All Arranged Children don't need to allocated 42 to begin with. Do need to initialize WidgetPaths better.
Change 3484703 by Nick.Darnell
Player Input - Making the input event loop for players obey EKeys::NUM_TOUCH_KEYS, rather than being set to Touch10, as the maximum touch input amount, to make supporting greater than 10 touches easier. Also making the seeding of keys use EKeys::NUM_TOUCH_KEYS.
#jira UE-43213
Change 3484918 by Jamie.Dale
Fixed font measuring regression with RTL text
RTL applies the character count to the next glyph, so it shouldn't process the end of the loop (this was how the older code used to work).
Change 3485718 by Nick.Darnell
Editor - Removing Super Search & User Feedback button.
Change 3485719 by Nick.Darnell
Portal - Removing SuperSearch.
Change 3485751 by Matt.Kuhlenschmidt
Fix crash accessing platformer game menu if the menu is open during a console based load
#jira UE-45950
Change 3486047 by Arciel.Rekman
Linux: add OpenEXR implementation (UE-40270).
#jira UE-40270
Change 3486467 by Max.Chen
Sequencer: Reset max tick rate when destroyed.
#jira UE-45956
Change 3486477 by Max.Chen
Sequencer: Refresh outliner when column is removed.
#jira UE-45891
Change 3486667 by Andrew.Rodham
Added missing include
Change 3486724 by Andrew.Rodham
Sequencer: Fixed curves with no default value, and no keys being evaluated and applied to properties
- Also fixed an edge case where a zero (but non-animated) channel could be applied to a final transform
Change 3486730 by Alexis.Matte
In the Auto-Reimport options, hide the mout point only for the default /Game/ folder
#UE-45684
Change 3486749 by Alexis.Matte
Make sure the parent window of the monitor directory browse folder is set properly
#jira UE-45682
Change 3486805 by Matt.Kuhlenschmidt
Additional safety against invalid objects being accessed by slate
Change 3486848 by Alexis.Matte
Make sure Monitor folder feature support root mount point map folder
During auto import, give priority to asset import factory over the scene import factory
#jira UE-45691
Change 3486879 by Andrew.Rodham
Removing obsolete QA assets
Change 3486950 by Nick.Darnell
PR #2281: Scrollbar missing features and SScrollbar fixes (Contributed by SNikon)
Review - made some adjustments from the original.
Change 3486954 by Nick.Darnell
Slate - Moving the STableViewBase over to the FOverscroll class, rather than it's own clone.
Change 3486967 by Nick.Darnell
Slate - Fixing some HDPI calculations for fitting new windows on screen, it was using the unscaled size of the widgets for fitting, when it needed to scale them up.
Change 3486970 by Andrew.Rodham
Sequencer: Delay mouse capture until drag for sequencer time slider
- Fixes context menus not opening as a result of mouse capture being taken on mouse down
#jira UE-45937
Change 3486984 by Andrew.Rodham
Sequencer: Improved blending type iconography
Change 3486996 by Nick.Darnell
UMG - Adding a way for games to opt-out of the slow widget path, to completely prevent them from being cooked.
UMG - The movie data is no longer cloned for each new instance that inhabits. It now keeps a reference to the now publically accessible movie scene data on the class instead.
Change 3487070 by Andrew.Rodham
Sequencer: Added graphics for key areas that represent empty space
Change 3487195 by Andrew.Rodham
Sequencer: Changed evaluation groups to always flush implicitly
- Due to the latent nature of blended token types, it's no longer safe to rely solely on execution token order between tracks
- This fixes an issue where events set in the PostEvaluation stage were executed before blended token actuation
Change 3487322 by Nick.Darnell
PR #2457: Add .gitdeps.xml-files for plugins support (Contributed by bozaro)
Change 3487363 by Nick.Darnell
PR #2481: Fix for packing of a project with users plugins (Contributed by yatagarasu25)
Change 3487439 by Nick.Darnell
PR #2642: Changed private to protected in SVirtualJoystick.h (Contributed by Skylonxe)
Change 3487500 by Arciel.Rekman
Removed LinuxNativeDialogs.
- No longer used; has been superceded by SlateDialogs since UE 4.8 (2 years ago).
Change 3487630 by Lauren.Ridge
Don't create Landscape Info Maps for Editor Preview Worlds or thumbnail worlds
#jira UE-44885
Change 3487864 by Matt.Kuhlenschmidt
Exposed the asset registry to blueprints and script. Works in editor scripts and runtime scripts
AssetRegistry is now a UInterface object.
Blueprint users can access various asset registry methods using the asset registry interface (via GetAssetRegistry) and various static helpers in the AssetRegistryHelpers object
C++ users should still continue to use IAssetRegistry.
Change 3487879 by Matt.Kuhlenschmidt
Renamed asset tools uobject helper to UAssetToolsHelpers
Change 3487926 by Lauren.Ridge
Fixing reset to default not showing up for custom widgets
#jira UE-44164
Change 3488184 by Matt.Kuhlenschmidt
PR #3656: Make References/Referencers List copyable (Contributed by user37337)
#jira UE-45763
Change 3488240 by Matt.Kuhlenschmidt
Fix compiler issue
Change 3488350 by Lauren.Ridge
Landscape info map transactional state is based on its world's transactional state
#jira UE-44885
#jira UE-46019
Change 3488412 by Matt.Kuhlenschmidt
Fix reset to default showing up in two different places for some customizations
Change 3488413 by Matt.Kuhlenschmidt
Fix slate font customization
Change 3488414 by Matt.Kuhlenschmidt
Fix slate font customization
Change 3488415 by Matt.Kuhlenschmidt
Missed file
Change 3488565 by Arciel.Rekman
Add pretty printers for gdb (UETOOL-1171).
- Committing shelf by Cengiz.Terzibas, with some modifications.
#jira UETOOL-1171
Change 3489094 by Nick.Darnell
Slate - The Slate RHI Renderer now caches the TextureLODGroups so that it can properly lookup the filtering of different texture groups that are set to Default, instead of a particular filter override on a texture.
Engine/Rendering - Simplifying some of the setup logic in TextureLODSettings so that code is shared for setting them up properly after loading from a config file.
Change 3489095 by Nick.Darnell
PR #2699: GameViewportClient - Added a method to allow setting the viewport cur. (Contributed by rfenner)
Review - Fixed spacing.
Change 3489108 by Matt.Kuhlenschmidt
Fix deprecation warning
Change 3489120 by Nick.Darnell
PR #3478: Fix possible UComboBoxString crash (Contributed by nakosung)
Change 3489147 by Andrew.Rodham
Sequencer: Adding return value to function to appease static analysis
- This function is never compiled, and if it is, it won't compile, but static analysis doesn't know that
Change 3489264 by Nick.Darnell
Testing - Finishing the thought behind an enum comment.
Change 3489265 by Nick.Darnell
PR #2750: UE-35164: Button padding (Contributed by projectgheist)
Change 3489267 by Nick.Darnell
PR #3645: UE-45464: Handle SSlider mouse interaction more accurately (Contributed by projectgheist)
Change 3489632 by Arciel.Rekman
Correctness changes to MallocPoisonProxy.
- Missing forwarding functions added. Incorrect comment removed.
- Change by Steve.Robb, doing here so it is in 4.17.
Change 3489689 by Arciel.Rekman
More MallocPoisonProxy changes I missed in previous CL.
Change 3489751 by Matt.Kuhlenschmidt
Moved editor performance settings out of per-project settings so they can be shared across projects
Change 3489837 by Lauren.Ridge
Keyboard shortcut for entering/leaving VR Mode is now Alt+V
Change 3491082 by Arciel.Rekman
Linux: better fix for the crash due to name collision (UE-46040).
- Put classes in Sequencer module into Sequencer namespace instead of SceneOutliner namespace.
- Undid change in the SceneOutliner module.
#jira UE-46040
Change 3491096 by Arciel.Rekman
Fix UAT compilation on the newest mono.
Change 3491240 by Max.Chen
Sequencer: Disable key button when allow level edits only is on.
#jira UE-46060
Change 3491406 by Yannick.Lange
Fix editor crashes when opening a project that includes a plugin with more than two custom Volume classes. This issue was caused because registering show volume commands is based on finding volume classes. Finding these classes at multiple times resulted in a mismatch of the returned array of volume classes because modules/plugins were still being loaded.
#jira UE-45806
Change 3491559 by Alexis.Matte
Make sure we use the good preview mesh when doing a preview
#jira UE-45963
Change 3491563 by Alexis.Matte
Fix crash with staticmesh editor LodLevel selection
Change 3491564 by Nick.Darnell
UMG - Fixing an offset with the grab handles in HDPI mode.
Change 3491595 by Nick.Darnell
Editor - Fixing a clipping artifact in the pin type dropdown in the blueprint editor.
Change 3491604 by Nick.Darnell
Back out changelist 3489265
Change 3491615 by Arciel.Rekman
Added malloc replay proxy (Linux only for now).
- Allows to dump malloc callstream (without regard to threads) and replay later to study the behavior of different mallocs and/or repro problems.
Change 3491684 by Arciel.Rekman
Added FMalloc functions I missed.
- Also moved function bodies into the .cpp file, this does not make a difference in performance in this case.
Change 3491692 by Matt.Kuhlenschmidt
Some minor fixes to the static mesh editor
- Fix UV combo button looking non-standard on the toolbar
- Fix a few combo buttons in the details panel looking too big.
Change 3491702 by Arciel.Rekman
Do not compile replay proxy-specific code when not used.
Change 3491717 by Michael.Dupuis
#jira UE-35083:
The component is now the owner of the PerInstanceRenderData instead of the proxy
Add an Update path to only update specified instances range
Always call BuildTreeIfOutdated so we have a standard code path to make sure static mesh are fully loaded before trying to build the tree
Moved the Instance Buffer aysnc to the base class, as it's not related to UHierarchicalInstancedStaticMeshComponent
Expose a new property to decide if we require dynamic instance buffer
Change 3491758 by Matt.Kuhlenschmidt
Fix crash on static mesh editor shutdown
Change 3491873 by Cody.Albert
Fixed clipping issue in Sequencer curve editor
#rnx
Change 3491956 by Matt.Kuhlenschmidt
Fix crash opening the Previewing sub-menu in the level editor settings menu
#jira UE-46095
Change 3492046 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492076 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492165 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492222 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492274 by Michael.Dupuis
#jira UE-46105: Fixed Clang warning
Change 3492338 by andrew.porter
QAGame: Testing ensure when submitting
Change 3492371 by Nick.Darnell
UMG - Reverting the animation sharing, cossed GLEO regressions in cooking. Will look for a better solution.
Change 3492462 by Matt.Kuhlenschmidt
Fix ensure checking in files through perforce
Change 3492491 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492505 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3492517 by Jamie.Dale
The package localization ID is no longer used at all at runtime, and is now truly editor-only
This should have always been the case, but it was leaked into manifest/archives/PO files in 4.14, and while 4.15 removed it from PO files it was still present in the manifest/archives. This change removes it entirely (unless gathering editor-only data, and even then the PO file will still collapse the entries together for translation), and the deprecated 4.14 export behavior will now produce an error if you attempt to use it.
After taking this change you'll need to run a gather, import, and compile of your LocRes files to update your game localization to use the new localization IDs.
Change 3492630 by Nick.Darnell
UMG - Removing some extra cleanup code that's probably overkill and is causing a crash for uses of "Within" in class meta.
#jira UE-46124
Change 3492692 by Matt.Kuhlenschmidt
Fix drop shadows inheriting the outline color of the font. The outline should still appear but not have a different outline color from fill color
Change 3492714 by Matt.Kuhlenschmidt
Added outline with drop shadow to font automation test
Change 3492737 by Matt.Kuhlenschmidt
Fix linux
Change 3492992 by tim.gautier
Resaving Ocean Widget Blueprints / Sequences to resolve Legacy Sequence Data warnings
#jira UE-46132
Change 3493089 by Jamie.Dale
Ensure that the composite font of a font asset is flushed when the font object is GC'd
Change 3493322 by Jamie.Dale
Fixing null crash
#jira UE-45758
Change 3494467 by Andrew.Rodham
Fix Xbox warning
Change 3494852 by tim.gautier
QAGame: Changed streaming method of QA-EditorSmoke-Landscape to Always Loaded
Change 3494853 by Nick.Darnell
Another attempt at fixing the automation blueprint SA warning.
Change 3494896 by Arciel.Rekman
Fix possible null pointer access during Vulkan init.
- May fix static analysis warnings in UE-46142, although warnings seem to be referring to something else.
#jira UE-46142
Change 3494987 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3495010 by Matt.Kuhlenschmidt
Adding additional logging to track down html5 issue
Change 3495212 by Michael.Dupuis
#jira UE-46143: Properly init the InstanceRenderData during the cooking phase (required by fortnite)
Change 3495536 by Jamie.Dale
Updating UGameEngine to call its Super::PreExit after performing its own teardown
This prevents UEngine cleaning up resources that UGameEngine still needs.
#jira UE-46159
Change 3495551 by Arciel.Rekman
Another attempt to fix analyzer problem (UE-46142).
Change 3495794 by Jamie.Dale
Fixing some font cooking warnings by splitting out font faces from their font assets
#jira UE-45843
Change 3495905 by Matt.Kuhlenschmidt
Fix USD crash when importing a meshwith no material
[CL 3499771 by Matt Kuhlenschmidt in Main branch]
2017-06-19 20:27:30 -04:00
}
}
2017-10-13 11:32:28 -04:00
2020-09-24 00:43:27 -04:00
SkelMeshModel - > LODModels . RemoveAt ( DesiredLOD ) ;
SkeletalMesh - > RemoveLODInfo ( DesiredLOD ) ;
RefreshLODChange ( SkeletalMesh ) ;
// Adjust the force LOD to point on the same one, if we are forcing a LOD greater then the one we delete, we want to continue pointing on it
// If we delete the LOD we are loking at, we fall back on auto LOD
for ( auto Iter = UpdateContext . AssociatedComponents . CreateIterator ( ) ; Iter ; + + Iter )
{
USkinnedMeshComponent * SkinnedComponent = Cast < USkinnedMeshComponent > ( * Iter ) ;
if ( SkinnedComponent )
{
int32 CurrentForceLOD = SkinnedComponent - > GetForcedLOD ( ) ;
CurrentForceLOD = CurrentForceLOD = = 0 ? 0 : CurrentForceLOD - 1 ;
if ( CurrentForceLOD = = DesiredLOD )
{
SkinnedComponent - > SetForcedLOD ( 0 ) ;
}
else if ( CurrentForceLOD > DesiredLOD )
{
//Set back the force LOD, CurrentForceLOD was reduce by one so we simply set it.
SkinnedComponent - > SetForcedLOD ( CurrentForceLOD ) ;
}
}
}
2014-03-14 14:13:41 -04:00
//Notify calling system of change
UpdateContext . OnLODChanged . ExecuteIfBound ( ) ;
// Mark things for saving.
SkeletalMesh - > MarkPackageDirty ( ) ;
}
}
2020-09-24 00:43:27 -04:00
void FLODUtilities : : RemoveLODs ( FSkeletalMeshUpdateContext & UpdateContext , const TArray < int32 > & DesiredLODs )
{
USkeletalMesh * SkeletalMesh = UpdateContext . SkeletalMesh ;
FSkeletalMeshModel * SkelMeshModel = SkeletalMesh - > GetImportedModel ( ) ;
auto NoLODToRemoveDialog = [ ] ( )
{
if ( ! FApp : : IsUnattended ( ) )
{
FMessageDialog : : Open ( EAppMsgType : : Ok , NSLOCTEXT ( " UnrealEd " , " NoLODToRemove " , " No LODs to remove! " ) ) ;
}
UE_LOG ( LogLODUtilities , Warning , TEXT ( " No LOD to remove or there must be at least one LOD after we remove this one. " ) ) ;
} ;
if ( SkelMeshModel - > LODModels . Num ( ) < = 1 | | DesiredLODs . Num ( ) < 1 )
{
NoLODToRemoveDialog ( ) ;
return ;
}
check ( SkeletalMesh - > GetLODNum ( ) = = SkelMeshModel - > LODModels . Num ( ) ) ;
TArray < int32 > SortedDesiredLODs ;
for ( int32 DesiredLODIndex = 0 ; DesiredLODIndex < DesiredLODs . Num ( ) ; + + DesiredLODIndex )
{
int32 DesiredLOD = DesiredLODs [ DesiredLODIndex ] ;
if ( SkelMeshModel - > LODModels . Num ( ) > 1 & & SkelMeshModel - > LODModels . IsValidIndex ( DesiredLOD ) )
{
SortedDesiredLODs . Add ( DesiredLOD ) ;
}
else
{
UE_LOG ( LogLODUtilities , Warning , TEXT ( " Cannot remove LOD {0} " ) , DesiredLOD ) ;
}
}
if ( SortedDesiredLODs . Num ( ) < 1 )
{
NoLODToRemoveDialog ( ) ;
return ;
}
{
FScopedSkeletalMeshPostEditChange ScopedPostEditChange ( SkeletalMesh ) ;
//Sort the LODs and reverse iterate the sorted array to remove the LODs from the end to avoid having to remap LODs index in the sortedDesiredLODs array
SortedDesiredLODs . Sort ( ) ;
for ( int32 SortedDesiredLODIndex = SortedDesiredLODs . Num ( ) - 1 ; SortedDesiredLODIndex > = 0 ; SortedDesiredLODIndex - - )
{
int32 LODToRemove = SortedDesiredLODs [ SortedDesiredLODIndex ] ;
check ( SkelMeshModel - > LODModels . IsValidIndex ( LODToRemove ) )
FLODUtilities : : RemoveLOD ( UpdateContext , LODToRemove ) ;
}
}
}
2022-04-26 12:53:38 -04:00
bool FLODUtilities : : SetCustomLOD ( USkeletalMesh * DestinationSkeletalMesh , USkeletalMesh * SourceSkeletalMesh , const int32 LodIndex , const FString & SourceDataFilename )
{
if ( ! DestinationSkeletalMesh | | ! SourceSkeletalMesh )
{
return false ;
}
FScopedSkeletalMeshPostEditChange ScopePostEditChange ( DestinationSkeletalMesh ) ;
//If the imported LOD already exist, we will need to reimport all the skin weight profiles
bool bMustReimportAlternateSkinWeightProfile = false ;
// Get a list of all the clothing assets affecting this LOD so we can re-apply later
TArray < ClothingAssetUtils : : FClothingAssetMeshBinding > ClothingBindings ;
TArray < UClothingAssetBase * > ClothingAssetsInUse ;
TArray < int32 > ClothingAssetSectionIndices ;
TArray < int32 > ClothingAssetInternalLodIndices ;
FSkeletalMeshModel * SourceImportedResource = SourceSkeletalMesh - > GetImportedModel ( ) ;
FSkeletalMeshModel * DestImportedResource = DestinationSkeletalMesh - > GetImportedModel ( ) ;
if ( SourceImportedResource & & SourceImportedResource - > LODModels . IsValidIndex ( LodIndex ) )
{
bMustReimportAlternateSkinWeightProfile = true ;
FLODUtilities : : UnbindClothingAndBackup ( DestinationSkeletalMesh , ClothingBindings , LodIndex ) ;
}
//Lambda to call to re-apply the clothing
auto ReapplyClothing = [ & DestinationSkeletalMesh , & ClothingBindings , & SourceImportedResource , & LodIndex ] ( )
{
if ( SourceImportedResource & & SourceImportedResource - > LODModels . IsValidIndex ( LodIndex ) )
{
// Re-apply our clothing assets
FLODUtilities : : RestoreClothingFromBackup ( DestinationSkeletalMesh , ClothingBindings , LodIndex ) ;
}
} ;
// Now we copy the base FSkeletalMeshLODModel from the imported skeletal mesh as the new LOD in the selected mesh.
if ( SourceImportedResource - > LODModels . Num ( ) = = 0 )
{
return false ;
}
// Names of root bones must match.
// If the names of root bones don't match, the LOD Mesh does not share skeleton with base Mesh.
if ( SourceSkeletalMesh - > GetRefSkeleton ( ) . GetBoneName ( 0 ) ! = DestinationSkeletalMesh - > GetRefSkeleton ( ) . GetBoneName ( 0 ) )
{
UE_LOG ( LogLODUtilities , Error , TEXT ( " SkeletalMesh [%s] FLODUtilities::SetCustomLOD: Root bone in LOD is '%s' instead of '%s'. \n Import failed.. " )
, * DestinationSkeletalMesh - > GetName ( )
, * SourceSkeletalMesh - > GetRefSkeleton ( ) . GetBoneName ( 0 ) . ToString ( )
, * DestinationSkeletalMesh - > GetRefSkeleton ( ) . GetBoneName ( 0 ) . ToString ( ) ) ;
return false ;
}
// We do some checking here that for every bone in the mesh we just imported, it's in our base ref skeleton, and the parent is the same.
for ( int32 i = 0 ; i < SourceSkeletalMesh - > GetRefSkeleton ( ) . GetRawBoneNum ( ) ; i + + )
{
int32 LODBoneIndex = i ;
FName LODBoneName = SourceSkeletalMesh - > GetRefSkeleton ( ) . GetBoneName ( LODBoneIndex ) ;
int32 BaseBoneIndex = DestinationSkeletalMesh - > GetRefSkeleton ( ) . FindBoneIndex ( LODBoneName ) ;
if ( BaseBoneIndex = = INDEX_NONE )
{
UE_LOG ( LogLODUtilities , Error , TEXT ( " FLODUtilities::SetCustomLOD: Bone '%s' not found in destination SkeletalMesh '%s'. \n Import failed. " )
, * LODBoneName . ToString ( )
, * DestinationSkeletalMesh - > GetName ( ) ) ;
return false ;
}
if ( i > 0 )
{
int32 LODParentIndex = SourceSkeletalMesh - > GetRefSkeleton ( ) . GetParentIndex ( LODBoneIndex ) ;
FName LODParentName = SourceSkeletalMesh - > GetRefSkeleton ( ) . GetBoneName ( LODParentIndex ) ;
int32 BaseParentIndex = DestinationSkeletalMesh - > GetRefSkeleton ( ) . GetParentIndex ( BaseBoneIndex ) ;
FName BaseParentName = DestinationSkeletalMesh - > GetRefSkeleton ( ) . GetBoneName ( BaseParentIndex ) ;
if ( LODParentName ! = BaseParentName )
{
UE_LOG ( LogLODUtilities , Error , TEXT ( " SkeletalMesh [%s] FLODUtilities::SetCustomLOD: Bone '%s' in LOD has parent '%s' instead of '%s' " )
, * DestinationSkeletalMesh - > GetName ( )
, * LODBoneName . ToString ( )
, * LODParentName . ToString ( )
, * BaseParentName . ToString ( ) ) ;
return false ;
}
}
}
FScopedSkeletalMeshPostEditChange ScopedPostEditChange ( DestinationSkeletalMesh ) ;
FSkeletalMeshLODModel & NewLODModel = SourceImportedResource - > LODModels [ 0 ] ;
// If this LOD is not the base LOD, we check all bones we have sockets on are present in it.
if ( LodIndex > 0 )
{
const TArray < USkeletalMeshSocket * > & Sockets = DestinationSkeletalMesh - > GetMeshOnlySocketList ( ) ;
for ( int32 i = 0 ; i < Sockets . Num ( ) ; i + + )
{
// Find bone index the socket is attached to.
USkeletalMeshSocket * Socket = Sockets [ i ] ;
int32 SocketBoneIndex = SourceSkeletalMesh - > GetRefSkeleton ( ) . FindBoneIndex ( Socket - > BoneName ) ;
// If this LOD does not contain the socket bone, abort import.
if ( SocketBoneIndex = = INDEX_NONE )
{
UE_LOG ( LogLODUtilities , Error , TEXT ( " FLODUtilities::SetCustomLOD: This LOD is missing bone '%s' used by socket '%s'. \n Aborting import. " )
, * Socket - > BoneName . ToString ( )
, * Socket - > SocketName . ToString ( ) ) ;
return false ;
}
}
}
{
//The imported LOD is always in LOD 0 of the SourceSkeletalMesh
const int32 SourceLODIndex = 0 ;
if ( ! SourceSkeletalMesh - > IsLODImportedDataEmpty ( SourceLODIndex ) )
{
// Fix up the imported data bone indexes
FSkeletalMeshImportData LODImportData ;
SourceSkeletalMesh - > LoadLODImportedData ( SourceLODIndex , LODImportData ) ;
const int32 LODImportDataBoneNumber = LODImportData . RefBonesBinary . Num ( ) ;
//We want to create a remap array so we can fix all influence easily
TArray < int32 > ImportDataBoneRemap ;
ImportDataBoneRemap . AddZeroed ( LODImportDataBoneNumber ) ;
//We generate a new RefBonesBinary array to replace the existing one
TArray < SkeletalMeshImportData : : FBone > RemapedRefBonesBinary ;
RemapedRefBonesBinary . AddZeroed ( DestinationSkeletalMesh - > GetRefSkeleton ( ) . GetNum ( ) ) ;
for ( int32 ImportBoneIndex = 0 ; ImportBoneIndex < LODImportDataBoneNumber ; + + ImportBoneIndex )
{
SkeletalMeshImportData : : FBone & ImportedBone = LODImportData . RefBonesBinary [ ImportBoneIndex ] ;
int32 LODBoneIndex = ImportBoneIndex ;
FName LODBoneName = FName ( * ImportedBone . Name ) ;
int32 BaseBoneIndex = DestinationSkeletalMesh - > GetRefSkeleton ( ) . FindBoneIndex ( LODBoneName ) ;
ImportDataBoneRemap [ ImportBoneIndex ] = BaseBoneIndex ;
if ( BaseBoneIndex ! = INDEX_NONE )
{
RemapedRefBonesBinary [ BaseBoneIndex ] = ImportedBone ;
if ( RemapedRefBonesBinary [ BaseBoneIndex ] . ParentIndex ! = INDEX_NONE )
{
RemapedRefBonesBinary [ BaseBoneIndex ] . ParentIndex = ImportDataBoneRemap [ RemapedRefBonesBinary [ BaseBoneIndex ] . ParentIndex ] ;
}
}
}
//Copy the new RefBonesBinary over the existing one
LODImportData . RefBonesBinary = RemapedRefBonesBinary ;
//Fix the influences
bool bNeedShrinking = false ;
const int32 InfluenceNumber = LODImportData . Influences . Num ( ) ;
for ( int32 InfluenceIndex = InfluenceNumber - 1 ; InfluenceIndex > = 0 ; - - InfluenceIndex )
{
SkeletalMeshImportData : : FRawBoneInfluence & Influence = LODImportData . Influences [ InfluenceIndex ] ;
Influence . BoneIndex = ImportDataBoneRemap [ Influence . BoneIndex ] ;
if ( Influence . BoneIndex = = INDEX_NONE )
{
const int32 DeleteCount = 1 ;
const bool AllowShrink = false ;
LODImportData . Influences . RemoveAt ( InfluenceIndex , DeleteCount , AllowShrink ) ;
bNeedShrinking = true ;
}
}
//Shrink the array if we have deleted at least one entry
if ( bNeedShrinking )
{
LODImportData . Influences . Shrink ( ) ;
}
//Save the fix up remap bone index
SourceSkeletalMesh - > SaveLODImportedData ( SourceLODIndex , LODImportData ) ;
}
// Fix up the ActiveBoneIndices array.
for ( int32 ActiveIndex = 0 ; ActiveIndex < NewLODModel . ActiveBoneIndices . Num ( ) ; ActiveIndex + + )
{
int32 LODBoneIndex = NewLODModel . ActiveBoneIndices [ ActiveIndex ] ;
FName LODBoneName = SourceSkeletalMesh - > GetRefSkeleton ( ) . GetBoneName ( LODBoneIndex ) ;
int32 BaseBoneIndex = DestinationSkeletalMesh - > GetRefSkeleton ( ) . FindBoneIndex ( LODBoneName ) ;
NewLODModel . ActiveBoneIndices [ ActiveIndex ] = BaseBoneIndex ;
}
// Fix up the chunk BoneMaps.
for ( int32 SectionIndex = 0 ; SectionIndex < NewLODModel . Sections . Num ( ) ; SectionIndex + + )
{
FSkelMeshSection & Section = NewLODModel . Sections [ SectionIndex ] ;
for ( int32 BoneMapIndex = 0 ; BoneMapIndex < Section . BoneMap . Num ( ) ; BoneMapIndex + + )
{
int32 LODBoneIndex = Section . BoneMap [ BoneMapIndex ] ;
FName LODBoneName = SourceSkeletalMesh - > GetRefSkeleton ( ) . GetBoneName ( LODBoneIndex ) ;
int32 BaseBoneIndex = DestinationSkeletalMesh - > GetRefSkeleton ( ) . FindBoneIndex ( LODBoneName ) ;
Section . BoneMap [ BoneMapIndex ] = BaseBoneIndex ;
}
}
// Create the RequiredBones array in the LODModel from the ref skeleton.
for ( int32 RequiredBoneIndex = 0 ; RequiredBoneIndex < NewLODModel . RequiredBones . Num ( ) ; RequiredBoneIndex + + )
{
FName LODBoneName = SourceSkeletalMesh - > GetRefSkeleton ( ) . GetBoneName ( NewLODModel . RequiredBones [ RequiredBoneIndex ] ) ;
int32 BaseBoneIndex = DestinationSkeletalMesh - > GetRefSkeleton ( ) . FindBoneIndex ( LODBoneName ) ;
if ( BaseBoneIndex ! = INDEX_NONE )
{
NewLODModel . RequiredBones [ RequiredBoneIndex ] = BaseBoneIndex ;
}
else
{
NewLODModel . RequiredBones . RemoveAt ( RequiredBoneIndex - - ) ;
}
}
// Also sort the RequiredBones array to be strictly increasing.
NewLODModel . RequiredBones . Sort ( ) ;
DestinationSkeletalMesh - > GetRefSkeleton ( ) . EnsureParentsExistAndSort ( NewLODModel . ActiveBoneIndices ) ;
}
// To be extra-nice, we apply the difference between the root transform of the meshes to the verts.
FMatrix44f LODToBaseTransform = FMatrix44f ( SourceSkeletalMesh - > GetRefPoseMatrix ( 0 ) . InverseFast ( ) * DestinationSkeletalMesh - > GetRefPoseMatrix ( 0 ) ) ;
for ( int32 SectionIndex = 0 ; SectionIndex < NewLODModel . Sections . Num ( ) ; SectionIndex + + )
{
FSkelMeshSection & Section = NewLODModel . Sections [ SectionIndex ] ;
// Fix up soft verts.
for ( int32 i = 0 ; i < Section . SoftVertices . Num ( ) ; i + + )
{
Section . SoftVertices [ i ] . Position = LODToBaseTransform . TransformPosition ( Section . SoftVertices [ i ] . Position ) ;
Section . SoftVertices [ i ] . TangentX = LODToBaseTransform . TransformVector ( Section . SoftVertices [ i ] . TangentX ) ;
Section . SoftVertices [ i ] . TangentY = LODToBaseTransform . TransformVector ( Section . SoftVertices [ i ] . TangentY ) ;
Section . SoftVertices [ i ] . TangentZ = LODToBaseTransform . TransformVector ( Section . SoftVertices [ i ] . TangentZ ) ;
}
}
//Restore the LOD section data in case this LOD was reimport and some material match
if ( DestImportedResource - > LODModels . IsValidIndex ( LodIndex ) & & SourceImportedResource - > LODModels . IsValidIndex ( 0 ) )
{
const TArray < FSkelMeshSection > & ExistingSections = DestImportedResource - > LODModels [ LodIndex ] . Sections ;
const FSkeletalMeshLODInfo & ExistingInfo = * ( DestinationSkeletalMesh - > GetLODInfo ( LodIndex ) ) ;
TArray < FSkelMeshSection > & ImportedSections = SourceImportedResource - > LODModels [ 0 ] . Sections ;
const FSkeletalMeshLODInfo & ImportedInfo = * ( SourceSkeletalMesh - > GetLODInfo ( 0 ) ) ;
auto GetImportMaterialSlotName = [ ] ( const USkeletalMesh * SkelMesh , const FSkelMeshSection & Section , int32 SectionIndex , const FSkeletalMeshLODInfo & Info , int32 & OutMaterialIndex ) - > FName
{
const TArray < FSkeletalMaterial > & MeshMaterials = SkelMesh - > GetMaterials ( ) ;
check ( MeshMaterials . Num ( ) > 0 ) ;
OutMaterialIndex = Section . MaterialIndex ;
if ( Info . LODMaterialMap . IsValidIndex ( SectionIndex ) & & Info . LODMaterialMap [ SectionIndex ] ! = INDEX_NONE )
{
OutMaterialIndex = Info . LODMaterialMap [ SectionIndex ] ;
}
FName ImportedMaterialSlotName = NAME_None ;
if ( MeshMaterials . IsValidIndex ( OutMaterialIndex ) )
{
ImportedMaterialSlotName = MeshMaterials [ OutMaterialIndex ] . ImportedMaterialSlotName ;
}
else
{
ImportedMaterialSlotName = MeshMaterials [ 0 ] . ImportedMaterialSlotName ;
OutMaterialIndex = 0 ;
}
return ImportedMaterialSlotName ;
} ;
for ( int32 ExistingSectionIndex = 0 ; ExistingSectionIndex < ExistingSections . Num ( ) ; + + ExistingSectionIndex )
{
const FSkelMeshSection & ExistingSection = ExistingSections [ ExistingSectionIndex ] ;
int32 ExistingMaterialIndex = 0 ;
FName ExistingImportedMaterialSlotName = GetImportMaterialSlotName ( DestinationSkeletalMesh , ExistingSection , ExistingSectionIndex , ExistingInfo , ExistingMaterialIndex ) ;
for ( int32 ImportedSectionIndex = 0 ; ImportedSectionIndex < ImportedSections . Num ( ) ; + + ImportedSectionIndex )
{
FSkelMeshSection & ImportedSection = ImportedSections [ ImportedSectionIndex ] ;
int32 ImportedMaterialIndex = 0 ;
FName ImportedImportedMaterialSlotName = GetImportMaterialSlotName ( SourceSkeletalMesh , ImportedSection , ImportedSectionIndex , ImportedInfo , ImportedMaterialIndex ) ;
if ( ExistingImportedMaterialSlotName ! = NAME_None )
{
if ( ImportedImportedMaterialSlotName = = ExistingImportedMaterialSlotName )
{
//Set the value and exit
ImportedSection . bCastShadow = ExistingSection . bCastShadow ;
ImportedSection . bVisibleInRayTracing = ExistingSection . bVisibleInRayTracing ;
ImportedSection . bRecomputeTangent = ExistingSection . bRecomputeTangent ;
ImportedSection . RecomputeTangentsVertexMaskChannel = ExistingSection . RecomputeTangentsVertexMaskChannel ;
break ;
}
}
else if ( SourceSkeletalMesh - > GetMaterials ( ) [ ImportedMaterialIndex ] = = DestinationSkeletalMesh - > GetMaterials ( ) [ ExistingMaterialIndex ] ) //Use material slot compare to match in case the name is none
{
//Set the value and exit
ImportedSection . bCastShadow = ExistingSection . bCastShadow ;
ImportedSection . bVisibleInRayTracing = ExistingSection . bVisibleInRayTracing ;
ImportedSection . bRecomputeTangent = ExistingSection . bRecomputeTangent ;
ImportedSection . RecomputeTangentsVertexMaskChannel = ExistingSection . RecomputeTangentsVertexMaskChannel ;
break ;
}
}
}
}
// If we want to add this as a new LOD to this mesh - add to LODModels/LODInfo array.
if ( LodIndex = = DestImportedResource - > LODModels . Num ( ) )
{
DestImportedResource - > LODModels . Add ( new FSkeletalMeshLODModel ( ) ) ;
// Add element to LODInfo array.
DestinationSkeletalMesh - > AddLODInfo ( ) ;
check ( DestinationSkeletalMesh - > GetLODNum ( ) = = DestImportedResource - > LODModels . Num ( ) ) ;
}
// Set up LODMaterialMap to number of materials in new mesh.
FSkeletalMeshLODInfo & LODInfo = * ( DestinationSkeletalMesh - > GetLODInfo ( LodIndex ) ) ;
//Copy the build settings
if ( SourceSkeletalMesh - > GetLODInfo ( 0 ) )
{
const FSkeletalMeshLODInfo & ImportedLODInfo = * ( SourceSkeletalMesh - > GetLODInfo ( 0 ) ) ;
LODInfo . BuildSettings = ImportedLODInfo . BuildSettings ;
}
TArray < FSkeletalMaterial > & BaseMaterials = DestinationSkeletalMesh - > GetMaterials ( ) ;
LODInfo . LODMaterialMap . Empty ( ) ;
// Now set up the material mapping array.
for ( int32 SectionIndex = 0 ; SectionIndex < NewLODModel . Sections . Num ( ) ; SectionIndex + + )
{
int32 MatIdx = NewLODModel . Sections [ SectionIndex ] . MaterialIndex ;
// Try and find the auto-assigned material in the array.
int32 LODMatIndex = INDEX_NONE ;
//First try to match by name
for ( int32 BaseMaterialIndex = 0 ; BaseMaterialIndex < BaseMaterials . Num ( ) ; + + BaseMaterialIndex )
{
const FSkeletalMaterial & SkeletalMaterial = BaseMaterials [ BaseMaterialIndex ] ;
if ( SkeletalMaterial . ImportedMaterialSlotName ! = NAME_None & & SkeletalMaterial . ImportedMaterialSlotName = = SourceSkeletalMesh - > GetMaterials ( ) [ MatIdx ] . ImportedMaterialSlotName )
{
LODMatIndex = BaseMaterialIndex ;
break ;
}
}
// If we dont have a match, add a new entry to the material list.
if ( LODMatIndex = = INDEX_NONE )
{
LODMatIndex = BaseMaterials . Add ( SourceSkeletalMesh - > GetMaterials ( ) [ MatIdx ] ) ;
}
LODInfo . LODMaterialMap . Add ( LODMatIndex ) ;
}
// Release all resources before replacing the model
DestinationSkeletalMesh - > PreEditChange ( NULL ) ;
// Assign new FSkeletalMeshLODModel to desired slot in selected skeletal mesh.
FSkeletalMeshLODModel : : CopyStructure ( & ( DestImportedResource - > LODModels [ LodIndex ] ) , & NewLODModel ) ;
//Copy the import data into the base skeletalmesh for the imported LOD
USkeletalMesh : : CopyImportedData ( 0 , SourceSkeletalMesh , LodIndex , DestinationSkeletalMesh ) ;
// If this LOD had been generated previously by automatic mesh reduction, clear that flag.
LODInfo . bHasBeenSimplified = false ;
if ( DestinationSkeletalMesh - > GetLODSettings ( ) = = nullptr | | ! DestinationSkeletalMesh - > GetLODSettings ( ) - > HasValidSettings ( ) | | DestinationSkeletalMesh - > GetLODSettings ( ) - > GetNumberOfSettings ( ) < = LodIndex )
{
//Make sure any custom LOD have correct settings (no reduce)
LODInfo . ReductionSettings . NumOfTrianglesPercentage = 1.0f ;
LODInfo . ReductionSettings . NumOfVertPercentage = 1.0f ;
LODInfo . ReductionSettings . MaxDeviationPercentage = 0.0f ;
}
// Set LOD source filename
DestinationSkeletalMesh - > GetLODInfo ( LodIndex ) - > SourceImportFilename = UAssetImportData : : SanitizeImportFilename ( SourceDataFilename , nullptr ) ;
DestinationSkeletalMesh - > GetLODInfo ( LodIndex ) - > bImportWithBaseMesh = false ;
ReapplyClothing ( ) ;
//Must be the last step because it cleanup the fbx importer to import the alternate skinning FBX
if ( bMustReimportAlternateSkinWeightProfile )
{
//TODO port skin weights utilities outside of UnrealEd module
//FSkinWeightsUtilities::ReimportAlternateSkinWeight(DestinationSkeletalMesh, LodIndex);
}
// Notification of success
FNotificationInfo NotificationInfo ( FText : : GetEmpty ( ) ) ;
NotificationInfo . Text = FText : : Format ( NSLOCTEXT ( " UnrealEd " , " LODImportSuccessful " , " Mesh for LOD {0} imported successfully! " ) , FText : : AsNumber ( LodIndex ) ) ;
NotificationInfo . ExpireDuration = 5.0f ;
FSlateNotificationManager : : Get ( ) . AddNotification ( NotificationInfo ) ;
return true ;
}
2018-02-22 11:25:06 -05:00
/** Given three direction vectors, indicates if A and B are on the same 'side' of Vec. */
bool VectorsOnSameSide ( const FVector2D & Vec , const FVector2D & A , const FVector2D & B )
{
2022-04-20 19:05:47 -04:00
return ! ( ( ( B . Y - A . Y ) * ( Vec . X - A . X ) ) + ( ( A . X - B . X ) * ( Vec . Y - A . Y ) ) < 0.0f ) ;
2018-02-22 11:25:06 -05:00
}
float PointToSegmentDistanceSquare ( const FVector2D & A , const FVector2D & B , const FVector2D & P )
{
return FVector2D : : DistSquared ( P , FMath : : ClosestPointOnSegment2D ( P , A , B ) ) ;
}
/** Return true if P is within triangle created by A, B and C. */
bool PointInTriangle ( const FVector2D & A , const FVector2D & B , const FVector2D & C , const FVector2D & P )
{
//If the point is on a triangle point we consider the point inside the triangle
if ( P . Equals ( A ) | | P . Equals ( B ) | | P . Equals ( C ) )
{
return true ;
}
// If its on the same side as the remaining vert for all edges, then its inside.
if ( VectorsOnSameSide ( A , B , P ) & &
VectorsOnSameSide ( B , C , P ) & &
VectorsOnSameSide ( C , A , P ) )
{
return true ;
}
//Make sure point on the edge are count inside the triangle
if ( PointToSegmentDistanceSquare ( A , B , P ) < = KINDA_SMALL_NUMBER )
{
return true ;
}
if ( PointToSegmentDistanceSquare ( B , C , P ) < = KINDA_SMALL_NUMBER )
{
return true ;
}
if ( PointToSegmentDistanceSquare ( C , A , P ) < = KINDA_SMALL_NUMBER )
{
return true ;
}
return false ;
}
2019-05-09 06:20:31 -04:00
/** Given three direction vectors, indicates if A and B are on the same 'side' of Vec. */
2021-05-05 15:07:25 -04:00
bool VectorsOnSameSide ( const FVector3f & Vec , const FVector3f & A , const FVector3f & B , const float SameSideDotProductEpsilon )
2019-05-09 06:20:31 -04:00
{
2022-02-02 07:59:31 -05:00
const FVector CrossA = FVector ( Vec ^ A ) ;
const FVector CrossB = FVector ( Vec ^ B ) ;
2019-05-09 06:20:31 -04:00
float DotWithEpsilon = SameSideDotProductEpsilon + ( CrossA | CrossB ) ;
2022-04-20 19:05:47 -04:00
return ! ( DotWithEpsilon < 0.0f ) ;
2019-05-09 06:20:31 -04:00
}
/** Util to see if P lies within triangle created by A, B and C. */
2021-05-05 15:07:25 -04:00
bool PointInTriangle ( const FVector3f & A , const FVector3f & B , const FVector3f & C , const FVector3f & P )
2019-05-09 06:20:31 -04:00
{
// Cross product indicates which 'side' of the vector the point is on
// If its on the same side as the remaining vert for all edges, then its inside.
if ( VectorsOnSameSide ( B - A , P - A , C - A , KINDA_SMALL_NUMBER ) & &
VectorsOnSameSide ( C - B , P - B , A - B , KINDA_SMALL_NUMBER ) & &
VectorsOnSameSide ( A - C , P - C , B - C , KINDA_SMALL_NUMBER ) )
{
return true ;
}
return false ;
}
2021-05-05 15:07:25 -04:00
FVector3f GetBaryCentric ( const FVector3f & Point , const FVector3f & A , const FVector3f & B , const FVector3f & C )
2018-02-22 11:25:06 -05:00
{
// Compute the normal of the triangle
2021-05-05 15:07:25 -04:00
const FVector3f TriNorm = ( B - A ) ^ ( C - A ) ;
2018-02-22 11:25:06 -05:00
//check collinearity of A,B,C
if ( TriNorm . SizeSquared ( ) < = SMALL_NUMBER )
{
2021-05-05 15:07:25 -04:00
float DistA = FVector3f : : DistSquared ( Point , A ) ;
float DistB = FVector3f : : DistSquared ( Point , B ) ;
float DistC = FVector3f : : DistSquared ( Point , C ) ;
2019-05-09 06:20:31 -04:00
if ( DistA < = DistB & & DistA < = DistC )
{
2021-05-05 15:07:25 -04:00
return FVector3f ( 1.0f , 0.0f , 0.0f ) ;
2019-05-09 06:20:31 -04:00
}
if ( DistB < = DistC )
{
2021-05-05 15:07:25 -04:00
return FVector3f ( 0.0f , 1.0f , 0.0f ) ;
2019-05-09 06:20:31 -04:00
}
2021-05-05 15:07:25 -04:00
return FVector3f ( 0.0f , 0.0f , 1.0f ) ;
2018-02-22 11:25:06 -05:00
}
2022-02-02 07:59:31 -05:00
return ( FVector3f ) FMath : : ComputeBaryCentric2D ( ( FVector ) Point , ( FVector ) A , ( FVector ) B , ( FVector ) C ) ;
2018-02-22 11:25:06 -05:00
}
struct FTriangleElement
{
FBox2D UVsBound ;
2021-04-08 14:32:07 -04:00
FBoxCenterAndExtent PositionBound ;
2018-02-22 11:25:06 -05:00
TArray < FSoftSkinVertex > Vertices ;
TArray < uint32 > Indexes ;
uint32 TriangleIndex ;
} ;
bool FindTriangleUVMatch ( const FVector2D & TargetUV , const TArray < FTriangleElement > & Triangles , const TArray < uint32 > & QuadTreeTriangleResults , TArray < uint32 > & MatchTriangleIndexes )
{
for ( uint32 TriangleIndex : QuadTreeTriangleResults )
{
const FTriangleElement & TriangleElement = Triangles [ TriangleIndex ] ;
2022-02-02 01:45:23 -05:00
if ( PointInTriangle ( FVector2D ( TriangleElement . Vertices [ 0 ] . UVs [ 0 ] ) , FVector2D ( TriangleElement . Vertices [ 1 ] . UVs [ 0 ] ) , FVector2D ( TriangleElement . Vertices [ 2 ] . UVs [ 0 ] ) , TargetUV ) )
2018-02-22 11:25:06 -05:00
{
MatchTriangleIndexes . Add ( TriangleIndex ) ;
}
TriangleIndex + + ;
}
return MatchTriangleIndexes . Num ( ) = = 0 ? false : true ;
}
2019-05-09 06:20:31 -04:00
bool FindTrianglePositionMatch ( const FVector & Position , const TArray < FTriangleElement > & Triangles , const TArray < FTriangleElement > & OcTreeTriangleResults , TArray < uint32 > & MatchTriangleIndexes )
{
for ( const FTriangleElement & Triangle : OcTreeTriangleResults )
{
uint32 TriangleIndex = Triangle . TriangleIndex ;
const FTriangleElement & TriangleElement = Triangles [ TriangleIndex ] ;
2022-02-02 07:59:31 -05:00
if ( PointInTriangle ( ( FVector3f ) TriangleElement . Vertices [ 0 ] . Position , ( FVector3f ) TriangleElement . Vertices [ 1 ] . Position , ( FVector3f ) TriangleElement . Vertices [ 2 ] . Position , ( FVector3f ) Position ) )
2019-05-09 06:20:31 -04:00
{
MatchTriangleIndexes . Add ( TriangleIndex ) ;
}
TriangleIndex + + ;
}
return MatchTriangleIndexes . Num ( ) = = 0 ? false : true ;
}
2018-02-22 11:25:06 -05:00
struct FTargetMatch
{
float BarycentricWeight [ 3 ] ; //The weight we use to interpolate the TARGET data
uint32 Indices [ 3 ] ; //BASE Index of the triangle vertice
2020-09-01 14:07:48 -04:00
//Default constructor
FTargetMatch ( )
{
BarycentricWeight [ 0 ] = BarycentricWeight [ 1 ] = BarycentricWeight [ 2 ] = 0.0f ;
Indices [ 0 ] = Indices [ 1 ] = Indices [ 2 ] = INDEX_NONE ;
}
2018-02-22 11:25:06 -05:00
} ;
void ProjectTargetOnBase ( const TArray < FSoftSkinVertex > & BaseVertices , const TArray < TArray < uint32 > > & PerSectionBaseTriangleIndices ,
2018-11-16 11:15:08 -05:00
TArray < FTargetMatch > & TargetMatchData , const TArray < FSkelMeshSection > & TargetSections , const TArray < int32 > & TargetSectionMatchBaseIndex , const TCHAR * DebugContext )
2018-02-22 11:25:06 -05:00
{
2018-05-23 21:04:31 -04:00
bool bNoMatchMsgDone = false ;
2020-08-11 01:36:57 -04:00
bool bNoUVsMsgDisplayed = false ;
2018-02-22 11:25:06 -05:00
TArray < FTriangleElement > Triangles ;
//Project section target vertices on match base section using the UVs coordinates
for ( int32 SectionIndex = 0 ; SectionIndex < TargetSections . Num ( ) ; + + SectionIndex )
{
//Use the remap base index in case some sections disappear during the reduce phase
int32 BaseSectionIndex = TargetSectionMatchBaseIndex [ SectionIndex ] ;
2019-10-01 20:41:42 -04:00
if ( BaseSectionIndex = = INDEX_NONE | | ! PerSectionBaseTriangleIndices . IsValidIndex ( BaseSectionIndex ) | | PerSectionBaseTriangleIndices [ BaseSectionIndex ] . Num ( ) < 1 )
2018-02-22 11:25:06 -05:00
{
continue ;
}
//Target vertices for the Section
const TArray < FSoftSkinVertex > & TargetVertices = TargetSections [ SectionIndex ] . SoftVertices ;
//Base Triangle indices for the matched base section
const TArray < uint32 > & BaseTriangleIndices = PerSectionBaseTriangleIndices [ BaseSectionIndex ] ;
2018-11-16 11:15:08 -05:00
FBox2D BaseMeshUVBound ( EForceInit : : ForceInit ) ;
FBox BaseMeshPositionBound ( EForceInit : : ForceInit ) ;
2018-02-22 11:25:06 -05:00
//Fill the triangle element to speed up the triangle research
Triangles . Reset ( BaseTriangleIndices . Num ( ) / 3 ) ;
for ( uint32 TriangleIndex = 0 ; TriangleIndex < ( uint32 ) BaseTriangleIndices . Num ( ) ; TriangleIndex + = 3 )
{
FTriangleElement TriangleElement ;
TriangleElement . UVsBound . Init ( ) ;
for ( int32 Corner = 0 ; Corner < 3 ; + + Corner )
{
uint32 CornerIndice = BaseTriangleIndices [ TriangleIndex + Corner ] ;
check ( BaseVertices . IsValidIndex ( CornerIndice ) ) ;
const FSoftSkinVertex & BaseVertex = BaseVertices [ CornerIndice ] ;
TriangleElement . Indexes . Add ( CornerIndice ) ;
TriangleElement . Vertices . Add ( BaseVertex ) ;
2022-02-02 01:45:23 -05:00
TriangleElement . UVsBound + = FVector2D ( BaseVertex . UVs [ 0 ] ) ;
2022-02-02 07:59:31 -05:00
BaseMeshPositionBound + = ( FVector ) BaseVertex . Position ;
2018-02-22 11:25:06 -05:00
}
2018-11-16 11:15:08 -05:00
BaseMeshUVBound + = TriangleElement . UVsBound ;
2018-02-22 11:25:06 -05:00
TriangleElement . TriangleIndex = Triangles . Num ( ) ;
Triangles . Add ( TriangleElement ) ;
}
2020-08-11 01:36:57 -04:00
if ( BaseMeshUVBound . GetExtent ( ) . IsNearlyZero ( ) )
{
if ( ! bNoUVsMsgDisplayed )
{
UE_LOG ( LogLODUtilities , Warning , TEXT ( " SkeletalMesh [%s] Remap morph target: Cannot remap morph target because source UVs are missings. " ) , DebugContext ? DebugContext : TEXT ( " Unknown Source " ) ) ;
bNoUVsMsgDisplayed = true ;
}
continue ;
}
2018-02-22 11:25:06 -05:00
//Setup the Quad tree
float UVsQuadTreeMinSize = 0.001f ;
2018-11-16 11:15:08 -05:00
TQuadTree < uint32 , 100 > QuadTree ( BaseMeshUVBound , UVsQuadTreeMinSize ) ;
2018-02-22 11:25:06 -05:00
for ( FTriangleElement & TriangleElement : Triangles )
{
2018-11-16 11:15:08 -05:00
QuadTree . Insert ( TriangleElement . TriangleIndex , TriangleElement . UVsBound , DebugContext ) ;
2018-02-22 11:25:06 -05:00
}
2018-11-16 11:15:08 -05:00
//Retrieve all triangle that are close to our point, let get 5% of UV extend
float DistanceThreshold = BaseMeshUVBound . GetExtent ( ) . Size ( ) * 0.05f ;
2018-02-22 11:25:06 -05:00
//Find a match triangle for every target vertices
TArray < uint32 > QuadTreeTriangleResults ;
QuadTreeTriangleResults . Reserve ( Triangles . Num ( ) / 10 ) ; //Reserve 10% to speed up the query
for ( uint32 TargetVertexIndex = 0 ; TargetVertexIndex < ( uint32 ) TargetVertices . Num ( ) ; + + TargetVertexIndex )
{
2022-02-02 01:45:23 -05:00
FVector2D TargetUV = FVector2D ( TargetVertices [ TargetVertexIndex ] . UVs [ 0 ] ) ;
2018-02-22 11:25:06 -05:00
//Reset the last data without flushing the memmery allocation
QuadTreeTriangleResults . Reset ( ) ;
2018-05-23 21:04:31 -04:00
const uint32 FullTargetIndex = TargetSections [ SectionIndex ] . BaseVertexIndex + TargetVertexIndex ;
//Make sure the array is allocate properly
if ( ! TargetMatchData . IsValidIndex ( FullTargetIndex ) )
{
continue ;
}
//Set default data for the target match, in case we cannot found a match
FTargetMatch & TargetMatch = TargetMatchData [ FullTargetIndex ] ;
for ( int32 Corner = 0 ; Corner < 3 ; + + Corner )
{
TargetMatch . Indices [ Corner ] = INDEX_NONE ;
TargetMatch . BarycentricWeight [ Corner ] = 0.3333f ; //The weight will be use to found the proper delta
}
2018-02-22 11:25:06 -05:00
FVector2D Extent ( DistanceThreshold , DistanceThreshold ) ;
FBox2D CurBox ( TargetUV - Extent , TargetUV + Extent ) ;
2018-11-16 11:15:08 -05:00
while ( QuadTreeTriangleResults . Num ( ) < = 0 )
{
QuadTree . GetElements ( CurBox , QuadTreeTriangleResults ) ;
Extent * = 2 ;
CurBox = FBox2D ( TargetUV - Extent , TargetUV + Extent ) ;
}
auto GetDistancePointToBaseTriangle = [ & Triangles , & TargetVertices , & TargetVertexIndex ] ( const uint32 BaseTriangleIndex ) - > float
{
FTriangleElement & CandidateTriangle = Triangles [ BaseTriangleIndex ] ;
2022-02-02 07:59:31 -05:00
return FVector : : DistSquared ( FMath : : ClosestPointOnTriangleToPoint ( ( FVector ) TargetVertices [ TargetVertexIndex ] . Position , ( FVector ) CandidateTriangle . Vertices [ 0 ] . Position , ( FVector ) CandidateTriangle . Vertices [ 1 ] . Position , ( FVector ) CandidateTriangle . Vertices [ 2 ] . Position ) , ( FVector ) TargetVertices [ TargetVertexIndex ] . Position ) ;
2018-11-16 11:15:08 -05:00
} ;
auto FailSafeUnmatchVertex = [ & GetDistancePointToBaseTriangle , & QuadTreeTriangleResults ] ( uint32 & OutIndexMatch ) - > bool
{
bool bFoundMatch = false ;
float ClosestTriangleDistSquared = MAX_flt ;
for ( uint32 MatchTriangleIndex : QuadTreeTriangleResults )
{
float TriangleDistSquared = GetDistancePointToBaseTriangle ( MatchTriangleIndex ) ;
if ( TriangleDistSquared < ClosestTriangleDistSquared )
{
ClosestTriangleDistSquared = TriangleDistSquared ;
OutIndexMatch = MatchTriangleIndex ;
bFoundMatch = true ;
}
}
return bFoundMatch ;
} ;
2018-02-22 11:25:06 -05:00
//Find all Triangles that contain the Target UV
if ( QuadTreeTriangleResults . Num ( ) > 0 )
{
TArray < uint32 > MatchTriangleIndexes ;
uint32 FoundIndexMatch = INDEX_NONE ;
if ( ! FindTriangleUVMatch ( TargetUV , Triangles , QuadTreeTriangleResults , MatchTriangleIndexes ) )
{
2018-11-16 11:15:08 -05:00
if ( ! FailSafeUnmatchVertex ( FoundIndexMatch ) )
2018-02-22 11:25:06 -05:00
{
2018-11-16 11:15:08 -05:00
//We should always have a match
if ( ! bNoMatchMsgDone )
{
UE_LOG ( LogLODUtilities , Warning , TEXT ( " Reduce LOD, remap morph target: Cannot find a triangle from the base LOD that contain a vertex UV in the target LOD. Remap morph target quality will be lower. " ) ) ;
bNoMatchMsgDone = true ;
}
continue ;
2018-02-22 11:25:06 -05:00
}
}
2018-11-16 11:15:08 -05:00
float ClosestTriangleDistSquared = MAX_flt ;
2018-02-22 11:25:06 -05:00
if ( MatchTriangleIndexes . Num ( ) = = 1 )
{
//One match, this mean no mirror UVs simply take the single match
FoundIndexMatch = MatchTriangleIndexes [ 0 ] ;
2018-11-16 11:15:08 -05:00
ClosestTriangleDistSquared = GetDistancePointToBaseTriangle ( FoundIndexMatch ) ;
2018-02-22 11:25:06 -05:00
}
else
{
//Geometry can use mirror so the UVs are not unique. Use the closest match triangle to the point to find the best match
for ( uint32 MatchTriangleIndex : MatchTriangleIndexes )
{
2018-11-16 11:15:08 -05:00
float TriangleDistSquared = GetDistancePointToBaseTriangle ( MatchTriangleIndex ) ;
2018-02-22 11:25:06 -05:00
if ( TriangleDistSquared < ClosestTriangleDistSquared )
{
ClosestTriangleDistSquared = TriangleDistSquared ;
FoundIndexMatch = MatchTriangleIndex ;
}
}
}
2018-11-16 11:15:08 -05:00
//FAIL SAFE, make sure we have a match that make sense
//Use the mesh section geometry bound extent (10% of it) to validate we are close enough.
if ( ClosestTriangleDistSquared > BaseMeshPositionBound . GetExtent ( ) . SizeSquared ( ) * 0.1f )
{
//Executing fail safe, if the UVs are too much off because of the reduction, use the closest distance to polygons to find the match
//This path is not optimize and should not happen often.
FailSafeUnmatchVertex ( FoundIndexMatch ) ;
}
2018-02-22 11:25:06 -05:00
//We should always have a valid match at this point
check ( FoundIndexMatch ! = INDEX_NONE ) ;
FTriangleElement & BestTriangle = Triangles [ FoundIndexMatch ] ;
//Found the surface area of the 3 barycentric triangles from the UVs
2021-05-05 15:07:25 -04:00
FVector3f BarycentricWeight ;
2022-02-02 01:45:23 -05:00
BarycentricWeight = GetBaryCentric ( FVector3f ( FVector2f ( TargetUV ) , 0.0f ) , FVector3f ( BestTriangle . Vertices [ 0 ] . UVs [ 0 ] , 0.0f ) , FVector3f ( BestTriangle . Vertices [ 1 ] . UVs [ 0 ] , 0.0f ) , FVector3f ( BestTriangle . Vertices [ 2 ] . UVs [ 0 ] , 0.0f ) ) ; // LWC_TODO: Precision loss
2018-02-22 11:25:06 -05:00
//Fill the target match
for ( int32 Corner = 0 ; Corner < 3 ; + + Corner )
{
TargetMatch . Indices [ Corner ] = BestTriangle . Indexes [ Corner ] ;
TargetMatch . BarycentricWeight [ Corner ] = BarycentricWeight [ Corner ] ; //The weight will be use to found the proper delta
}
}
else
{
2018-05-23 21:04:31 -04:00
if ( ! bNoMatchMsgDone )
2018-02-22 11:25:06 -05:00
{
2018-05-23 21:04:31 -04:00
UE_LOG ( LogLODUtilities , Warning , TEXT ( " Reduce LOD, remap morph target: Cannot find a triangle from the base LOD that contain a vertex UV in the target LOD. Remap morph target quality will be lower. " ) ) ;
bNoMatchMsgDone = true ;
2018-02-22 11:25:06 -05:00
}
continue ;
}
}
}
}
2021-09-21 16:06:32 -04:00
void CreateLODMorphTarget ( USkeletalMesh * SkeletalMesh , const FInlineReductionDataParameter & InlineReductionDataParameter , int32 SourceLOD , int32 DestinationLOD , const TMap < UMorphTarget * , TMap < uint32 , uint32 > > & PerMorphTargetBaseIndexToMorphTargetDelta , const TMap < uint32 , TArray < uint32 > > & BaseMorphIndexToTargetIndexList , const TArray < FSoftSkinVertex > & TargetVertices , const TArray < FTargetMatch > & TargetMatchData )
2018-02-22 11:25:06 -05:00
{
2019-01-21 17:47:02 -05:00
FSkeletalMeshModel * SkeletalMeshModel = SkeletalMesh - > GetImportedModel ( ) ;
const FSkeletalMeshLODModel & TargetLODModel = SkeletalMeshModel - > LODModels [ DestinationLOD ] ;
bool bInitializeMorphData = false ;
2020-11-25 11:17:08 -04:00
for ( UMorphTarget * MorphTarget : SkeletalMesh - > GetMorphTargets ( ) )
2018-02-22 11:25:06 -05:00
{
2018-11-16 11:15:08 -05:00
if ( ! MorphTarget - > HasDataForLOD ( SourceLOD ) )
2018-02-22 11:25:06 -05:00
{
continue ;
}
2021-09-21 16:06:32 -04:00
bool bUseBaseMorphDelta = SourceLOD = = DestinationLOD & & InlineReductionDataParameter . bIsDataValid & & InlineReductionDataParameter . InlineOriginalSrcMorphTargetData . Contains ( MorphTarget - > GetFullName ( ) ) ;
2018-11-16 11:15:08 -05:00
2021-09-21 16:06:32 -04:00
const TArray < FMorphTargetDelta > * BaseMorphDeltas = bUseBaseMorphDelta ? InlineReductionDataParameter . InlineOriginalSrcMorphTargetData . Find ( MorphTarget - > GetFullName ( ) ) : nullptr ;
2018-11-16 11:15:08 -05:00
if ( BaseMorphDeltas = = nullptr | | BaseMorphDeltas - > Num ( ) < = 0 )
{
bUseBaseMorphDelta = false ;
}
2018-02-22 11:25:06 -05:00
const TMap < uint32 , uint32 > & BaseIndexToMorphTargetDelta = PerMorphTargetBaseIndexToMorphTargetDelta [ MorphTarget ] ;
TArray < FMorphTargetDelta > NewMorphTargetDeltas ;
TSet < uint32 > CreatedTargetIndex ;
2021-05-05 15:07:25 -04:00
TMap < FVector3f , TArray < uint32 > > MorphTargetPerPosition ;
2021-09-07 10:20:14 -04:00
const FMorphTargetLODModel & BaseMorphModel = MorphTarget - > GetMorphLODModels ( ) [ SourceLOD ] ;
2018-02-22 11:25:06 -05:00
//Iterate each original morph target source index to fill the NewMorphTargetDeltas array with the TargetMatchData.
2018-11-16 11:15:08 -05:00
const TArray < FMorphTargetDelta > & Vertices = bUseBaseMorphDelta ? * BaseMorphDeltas : BaseMorphModel . Vertices ;
for ( uint32 MorphDeltaIndex = 0 ; MorphDeltaIndex < ( uint32 ) ( Vertices . Num ( ) ) ; + + MorphDeltaIndex )
2018-02-22 11:25:06 -05:00
{
2018-11-16 11:15:08 -05:00
const FMorphTargetDelta & MorphDelta = Vertices [ MorphDeltaIndex ] ;
2018-02-22 11:25:06 -05:00
const TArray < uint32 > * TargetIndexesPtr = BaseMorphIndexToTargetIndexList . Find ( MorphDelta . SourceIdx ) ;
if ( TargetIndexesPtr = = nullptr )
{
continue ;
}
const TArray < uint32 > & TargetIndexes = * TargetIndexesPtr ;
for ( int32 MorphTargetIndex = 0 ; MorphTargetIndex < TargetIndexes . Num ( ) ; + + MorphTargetIndex )
{
uint32 TargetIndex = TargetIndexes [ MorphTargetIndex ] ;
if ( CreatedTargetIndex . Contains ( TargetIndex ) )
{
continue ;
}
CreatedTargetIndex . Add ( TargetIndex ) ;
2021-05-05 15:07:25 -04:00
const FVector3f & SearchPosition = TargetVertices [ TargetIndex ] . Position ;
2018-02-22 11:25:06 -05:00
FMorphTargetDelta MatchMorphDelta ;
MatchMorphDelta . SourceIdx = TargetIndex ;
const FTargetMatch & TargetMatch = TargetMatchData [ TargetIndex ] ;
//Find the Position/tangent delta for the MatchMorphDelta using the barycentric weight
2022-02-02 07:59:31 -05:00
MatchMorphDelta . PositionDelta = FVector3f : : ZeroVector ;
MatchMorphDelta . TangentZDelta = FVector3f : : ZeroVector ;
2018-02-22 11:25:06 -05:00
for ( int32 Corner = 0 ; Corner < 3 ; + + Corner )
{
const uint32 * BaseMorphTargetIndexPtr = BaseIndexToMorphTargetDelta . Find ( TargetMatch . Indices [ Corner ] ) ;
2018-11-16 11:15:08 -05:00
if ( BaseMorphTargetIndexPtr ! = nullptr & & Vertices . IsValidIndex ( * BaseMorphTargetIndexPtr ) )
2018-02-22 11:25:06 -05:00
{
2018-11-16 11:15:08 -05:00
const FMorphTargetDelta & BaseMorphTargetDelta = Vertices [ * BaseMorphTargetIndexPtr ] ;
2021-05-05 15:07:25 -04:00
FVector3f BasePositionDelta = ! BaseMorphTargetDelta . PositionDelta . ContainsNaN ( ) ? BaseMorphTargetDelta . PositionDelta : FVector3f ( 0.0f ) ;
FVector3f BaseTangentZDelta = ! BaseMorphTargetDelta . TangentZDelta . ContainsNaN ( ) ? BaseMorphTargetDelta . TangentZDelta : FVector3f ( 0.0f ) ;
2018-02-22 11:25:06 -05:00
MatchMorphDelta . PositionDelta + = BasePositionDelta * TargetMatch . BarycentricWeight [ Corner ] ;
MatchMorphDelta . TangentZDelta + = BaseTangentZDelta * TargetMatch . BarycentricWeight [ Corner ] ;
}
ensure ( ! MatchMorphDelta . PositionDelta . ContainsNaN ( ) ) ;
ensure ( ! MatchMorphDelta . TangentZDelta . ContainsNaN ( ) ) ;
}
//Make sure all morph delta that are at the same position use the same delta to avoid hole in the geometry
TArray < uint32 > * MorphTargetsIndexUsingPosition = nullptr ;
MorphTargetsIndexUsingPosition = MorphTargetPerPosition . Find ( SearchPosition ) ;
if ( MorphTargetsIndexUsingPosition ! = nullptr )
{
//Get the maximum position/tangent delta for the existing matched morph delta
2021-05-05 15:07:25 -04:00
FVector3f PositionDelta = MatchMorphDelta . PositionDelta ;
FVector3f TangentZDelta = MatchMorphDelta . TangentZDelta ;
2018-02-22 11:25:06 -05:00
for ( uint32 ExistingMorphTargetIndex : * MorphTargetsIndexUsingPosition )
{
const FMorphTargetDelta & ExistingMorphDelta = NewMorphTargetDeltas [ ExistingMorphTargetIndex ] ;
PositionDelta = PositionDelta . SizeSquared ( ) > ExistingMorphDelta . PositionDelta . SizeSquared ( ) ? PositionDelta : ExistingMorphDelta . PositionDelta ;
TangentZDelta = TangentZDelta . SizeSquared ( ) > ExistingMorphDelta . TangentZDelta . SizeSquared ( ) ? TangentZDelta : ExistingMorphDelta . TangentZDelta ;
}
//Update all MorphTarget that share the same position.
for ( uint32 ExistingMorphTargetIndex : * MorphTargetsIndexUsingPosition )
{
FMorphTargetDelta & ExistingMorphDelta = NewMorphTargetDeltas [ ExistingMorphTargetIndex ] ;
ExistingMorphDelta . PositionDelta = PositionDelta ;
ExistingMorphDelta . TangentZDelta = TangentZDelta ;
}
MatchMorphDelta . PositionDelta = PositionDelta ;
MatchMorphDelta . TangentZDelta = TangentZDelta ;
MorphTargetsIndexUsingPosition - > Add ( NewMorphTargetDeltas . Num ( ) ) ;
}
else
{
MorphTargetPerPosition . Add ( TargetVertices [ TargetIndex ] . Position ) . Add ( NewMorphTargetDeltas . Num ( ) ) ;
}
NewMorphTargetDeltas . Add ( MatchMorphDelta ) ;
}
}
//Register the new morph target on the target LOD
2018-11-16 11:15:08 -05:00
MorphTarget - > PopulateDeltas ( NewMorphTargetDeltas , DestinationLOD , TargetLODModel . Sections , false , true ) ;
2019-01-21 17:47:02 -05:00
if ( MorphTarget - > HasValidData ( ) )
{
bInitializeMorphData | = SkeletalMesh - > RegisterMorphTarget ( MorphTarget , false ) ;
}
}
if ( bInitializeMorphData )
{
SkeletalMesh - > InitMorphTargetsAndRebuildRenderData ( ) ;
2018-02-22 11:25:06 -05:00
}
}
void FLODUtilities : : ClearGeneratedMorphTarget ( USkeletalMesh * SkeletalMesh , int32 TargetLOD )
{
check ( SkeletalMesh ) ;
FSkeletalMeshModel * SkeletalMeshResource = SkeletalMesh - > GetImportedModel ( ) ;
if ( ! SkeletalMeshResource | |
! SkeletalMeshResource - > LODModels . IsValidIndex ( TargetLOD ) )
{
//Abort clearing
return ;
}
const FSkeletalMeshLODModel & TargetLODModel = SkeletalMeshResource - > LODModels [ TargetLOD ] ;
//Make sure we have some morph for this LOD
2020-11-25 11:17:08 -04:00
for ( UMorphTarget * MorphTarget : SkeletalMesh - > GetMorphTargets ( ) )
2018-02-22 11:25:06 -05:00
{
if ( ! MorphTarget - > HasDataForLOD ( TargetLOD ) )
{
continue ;
}
2019-01-21 17:47:02 -05:00
//if (MorphTarget->MorphLODModels[TargetLOD].bGeneratedByEngine)
2018-02-22 11:25:06 -05:00
{
2021-09-07 10:20:14 -04:00
MorphTarget - > GetMorphLODModels ( ) [ TargetLOD ] . Reset ( ) ;
2018-02-22 11:25:06 -05:00
// if this is the last one, we can remove empty ones
2021-09-07 10:20:14 -04:00
if ( TargetLOD = = MorphTarget - > GetMorphLODModels ( ) . Num ( ) - 1 )
2018-02-22 11:25:06 -05:00
{
MorphTarget - > RemoveEmptyMorphTargets ( ) ;
}
}
}
}
2021-09-21 16:06:32 -04:00
void FLODUtilities : : ApplyMorphTargetsToLOD ( USkeletalMesh * SkeletalMesh , int32 SourceLOD , int32 DestinationLOD , const FInlineReductionDataParameter & InlineReductionDataParameter )
2018-02-22 11:25:06 -05:00
{
check ( SkeletalMesh ) ;
FSkeletalMeshModel * SkeletalMeshResource = SkeletalMesh - > GetImportedModel ( ) ;
if ( ! SkeletalMeshResource | |
2018-11-16 11:15:08 -05:00
! SkeletalMeshResource - > LODModels . IsValidIndex ( SourceLOD ) | |
! SkeletalMeshResource - > LODModels . IsValidIndex ( DestinationLOD ) | |
SourceLOD > DestinationLOD )
{
//Cannot reduce if the source model is missing or we reduce from a higher index LOD
return ;
}
FSkeletalMeshLODModel & SourceLODModel = SkeletalMeshResource - > LODModels [ SourceLOD ] ;
2021-09-21 16:06:32 -04:00
bool bReduceBaseLOD = DestinationLOD = = SourceLOD & & InlineReductionDataParameter . bIsDataValid ;
2018-11-16 11:15:08 -05:00
if ( ! bReduceBaseLOD & & SourceLOD = = DestinationLOD )
2018-02-22 11:25:06 -05:00
{
//Abort remapping of morph target since the data is missing
return ;
}
2020-02-19 15:48:37 -05:00
//Make sure we have some morph for this LOD
bool bContainsMorphTargets = false ;
2020-11-25 11:17:08 -04:00
for ( UMorphTarget * MorphTarget : SkeletalMesh - > GetMorphTargets ( ) )
2020-02-19 15:48:37 -05:00
{
if ( MorphTarget - > HasDataForLOD ( SourceLOD ) )
{
bContainsMorphTargets = true ;
}
}
if ( ! bContainsMorphTargets )
{
//No morph target to remap
return ;
}
2021-09-21 16:06:32 -04:00
const FSkeletalMeshLODModel & BaseLODModel = bReduceBaseLOD ? InlineReductionDataParameter . InlineOriginalSrcModel : SkeletalMeshResource - > LODModels [ SourceLOD ] ;
2019-11-14 18:43:05 -05:00
const FSkeletalMeshLODInfo * BaseLODInfo = SkeletalMesh - > GetLODInfo ( SourceLOD ) ;
2018-11-16 11:15:08 -05:00
const FSkeletalMeshLODModel & TargetLODModel = SkeletalMeshResource - > LODModels [ DestinationLOD ] ;
2019-11-14 18:43:05 -05:00
const FSkeletalMeshLODInfo * TargetLODInfo = SkeletalMesh - > GetLODInfo ( DestinationLOD ) ;
TArray < int32 > BaseLODMaterialMap = BaseLODInfo ? BaseLODInfo - > LODMaterialMap : TArray < int32 > ( ) ;
TArray < int32 > TargetLODMaterialMap = TargetLODInfo ? TargetLODInfo - > LODMaterialMap : TArray < int32 > ( ) ;
auto InternalGetSectionMaterialIndex = [ ] ( const FSkeletalMeshLODModel & LODModel , int32 SectionIndex ) - > int32
{
if ( ! LODModel . Sections . IsValidIndex ( SectionIndex ) )
{
return 0 ;
}
return LODModel . Sections [ SectionIndex ] . MaterialIndex ;
} ;
auto GetBaseSectionMaterialIndex = [ & BaseLODModel , & InternalGetSectionMaterialIndex ] ( int32 SectionIndex ) - > int32
{
return InternalGetSectionMaterialIndex ( BaseLODModel , SectionIndex ) ;
} ;
auto GetTargetSectionMaterialIndex = [ & TargetLODModel , & InternalGetSectionMaterialIndex ] ( int32 SectionIndex ) - > int32
{
return InternalGetSectionMaterialIndex ( TargetLODModel , SectionIndex ) ;
} ;
2018-02-22 11:25:06 -05:00
//We have to match target sections index with the correct base section index. Reduced LODs can contain a different number of sections than the base LOD
TArray < int32 > TargetSectionMatchBaseIndex ;
//Initialize the array to INDEX_NONE
TargetSectionMatchBaseIndex . AddUninitialized ( TargetLODModel . Sections . Num ( ) ) ;
for ( int32 TargetSectionIndex = 0 ; TargetSectionIndex < TargetLODModel . Sections . Num ( ) ; + + TargetSectionIndex )
{
TargetSectionMatchBaseIndex [ TargetSectionIndex ] = INDEX_NONE ;
}
2019-11-14 18:43:05 -05:00
TBitArray < > BaseSectionMatch ;
BaseSectionMatch . Init ( false , BaseLODModel . Sections . Num ( ) ) ;
2018-02-22 11:25:06 -05:00
//Find corresponding section indices from Source LOD for Target LOD
2019-11-14 18:43:05 -05:00
for ( int32 TargetSectionIndex = 0 ; TargetSectionIndex < TargetLODModel . Sections . Num ( ) ; + + TargetSectionIndex )
2018-02-22 11:25:06 -05:00
{
2019-11-14 18:43:05 -05:00
int32 TargetSectionMaterialIndex = GetTargetSectionMaterialIndex ( TargetSectionIndex ) ;
for ( int32 BaseSectionIndex = 0 ; BaseSectionIndex < BaseLODModel . Sections . Num ( ) ; + + BaseSectionIndex )
2018-02-22 11:25:06 -05:00
{
2019-11-14 18:43:05 -05:00
if ( BaseSectionMatch [ BaseSectionIndex ] )
2018-02-22 11:25:06 -05:00
{
2019-11-14 18:43:05 -05:00
continue ;
}
int32 BaseSectionMaterialIndex = GetBaseSectionMaterialIndex ( BaseSectionIndex ) ;
if ( TargetSectionMaterialIndex = = BaseSectionMaterialIndex )
{
TargetSectionMatchBaseIndex [ TargetSectionIndex ] = BaseSectionIndex ;
BaseSectionMatch [ BaseSectionIndex ] = true ;
2018-02-22 11:25:06 -05:00
break ;
}
}
}
//We should have match all the target sections
2021-09-21 16:06:32 -04:00
if ( TargetSectionMatchBaseIndex . Contains ( INDEX_NONE ) )
{
//This case is not fatal but need attention.
//Because of the chunking its possible a generated LOD end up with more sections.
UE_ASSET_LOG ( LogLODUtilities , Display , SkeletalMesh , TEXT ( " FLODUtilities::ApplyMorphTargetsToLOD: The target contain more section then the source. Extra sections will not be affected by morph targets remap " ) ) ;
}
2018-02-22 11:25:06 -05:00
TArray < FSoftSkinVertex > BaseVertices ;
TArray < FSoftSkinVertex > TargetVertices ;
2019-10-07 17:36:43 -04:00
BaseLODModel . GetVertices ( BaseVertices ) ;
TargetLODModel . GetVertices ( TargetVertices ) ;
2018-02-22 11:25:06 -05:00
//Create the base triangle indices per section
TArray < TArray < uint32 > > BaseTriangleIndices ;
2019-09-10 11:35:20 -04:00
int32 SectionCount = BaseLODModel . Sections . Num ( ) ;
2018-02-22 11:25:06 -05:00
BaseTriangleIndices . AddDefaulted ( SectionCount ) ;
for ( int32 SectionIndex = 0 ; SectionIndex < SectionCount ; + + SectionIndex )
{
const FSkelMeshSection & Section = BaseLODModel . Sections [ SectionIndex ] ;
uint32 TriangleCount = Section . NumTriangles ;
for ( uint32 TriangleIndex = 0 ; TriangleIndex < TriangleCount ; + + TriangleIndex )
{
for ( uint32 PointIndex = 0 ; PointIndex < 3 ; PointIndex + + )
{
2019-10-07 17:36:43 -04:00
uint32 IndexBufferValue = BaseLODModel . IndexBuffer [ Section . BaseIndex + ( ( TriangleIndex * 3 ) + PointIndex ) ] ;
BaseTriangleIndices [ SectionIndex ] . Add ( IndexBufferValue ) ;
2018-02-22 11:25:06 -05:00
}
}
}
//Every target vertices match a Base LOD triangle, we also want the barycentric weight of the triangle match. All this done using the UVs
TArray < FTargetMatch > TargetMatchData ;
2020-09-01 14:07:48 -04:00
TargetMatchData . AddDefaulted ( TargetVertices . Num ( ) ) ;
2018-02-22 11:25:06 -05:00
//Match all target vertices to a Base triangle Using UVs.
2018-11-16 11:15:08 -05:00
ProjectTargetOnBase ( BaseVertices , BaseTriangleIndices , TargetMatchData , TargetLODModel . Sections , TargetSectionMatchBaseIndex , * SkeletalMesh - > GetName ( ) ) ;
2018-02-22 11:25:06 -05:00
//Helper to retrieve the FMorphTargetDelta from the BaseIndex
TMap < UMorphTarget * , TMap < uint32 , uint32 > > PerMorphTargetBaseIndexToMorphTargetDelta ;
//Create a map from BaseIndex to a list of match target index for all base morph target point
TMap < uint32 , TArray < uint32 > > BaseMorphIndexToTargetIndexList ;
2020-11-25 11:17:08 -04:00
for ( UMorphTarget * MorphTarget : SkeletalMesh - > GetMorphTargets ( ) )
2018-02-22 11:25:06 -05:00
{
2018-11-16 11:15:08 -05:00
if ( ! MorphTarget - > HasDataForLOD ( SourceLOD ) )
2018-02-22 11:25:06 -05:00
{
continue ;
}
2018-11-16 11:15:08 -05:00
2021-09-21 16:06:32 -04:00
bool bUseTempMorphDelta = SourceLOD = = DestinationLOD & & bReduceBaseLOD & & InlineReductionDataParameter . InlineOriginalSrcMorphTargetData . Contains ( MorphTarget - > GetFullName ( ) ) ;
const TArray < FMorphTargetDelta > * TempMorphDeltas = bUseTempMorphDelta ? InlineReductionDataParameter . InlineOriginalSrcMorphTargetData . Find ( MorphTarget - > GetFullName ( ) ) : nullptr ;
2018-11-16 11:15:08 -05:00
if ( TempMorphDeltas = = nullptr | | TempMorphDeltas - > Num ( ) < = 0 )
2018-02-22 11:25:06 -05:00
{
2018-11-16 11:15:08 -05:00
bUseTempMorphDelta = false ;
}
TMap < uint32 , uint32 > & BaseIndexToMorphTargetDelta = PerMorphTargetBaseIndexToMorphTargetDelta . FindOrAdd ( MorphTarget ) ;
2021-09-07 10:20:14 -04:00
const FMorphTargetLODModel & BaseMorphModel = MorphTarget - > GetMorphLODModels ( ) [ SourceLOD ] ;
2018-11-16 11:15:08 -05:00
const TArray < FMorphTargetDelta > & Vertices = bUseTempMorphDelta ? * TempMorphDeltas : BaseMorphModel . Vertices ;
for ( uint32 MorphDeltaIndex = 0 ; MorphDeltaIndex < ( uint32 ) ( Vertices . Num ( ) ) ; + + MorphDeltaIndex )
{
const FMorphTargetDelta & MorphDelta = Vertices [ MorphDeltaIndex ] ;
2018-02-22 11:25:06 -05:00
BaseIndexToMorphTargetDelta . Add ( MorphDelta . SourceIdx , MorphDeltaIndex ) ;
//Iterate the targetmatch data so we can store which target indexes is impacted by this morph delta.
for ( int32 TargetIndex = 0 ; TargetIndex < TargetMatchData . Num ( ) ; + + TargetIndex )
{
const FTargetMatch & TargetMatch = TargetMatchData [ TargetIndex ] ;
2018-05-23 21:04:31 -04:00
if ( TargetMatch . Indices [ 0 ] = = INDEX_NONE )
{
//In case this vertex did not found a triangle match
continue ;
}
2018-02-22 11:25:06 -05:00
if ( TargetMatch . Indices [ 0 ] = = MorphDelta . SourceIdx | | TargetMatch . Indices [ 1 ] = = MorphDelta . SourceIdx | | TargetMatch . Indices [ 2 ] = = MorphDelta . SourceIdx )
{
TArray < uint32 > & TargetIndexes = BaseMorphIndexToTargetIndexList . FindOrAdd ( MorphDelta . SourceIdx ) ;
TargetIndexes . AddUnique ( TargetIndex ) ;
}
}
}
}
//Create the target morph target
2021-09-21 16:06:32 -04:00
CreateLODMorphTarget ( SkeletalMesh , InlineReductionDataParameter , SourceLOD , DestinationLOD , PerMorphTargetBaseIndexToMorphTargetDelta , BaseMorphIndexToTargetIndexList , TargetVertices , TargetMatchData ) ;
2018-02-22 11:25:06 -05:00
}
2021-03-18 15:20:03 -04:00
void FLODUtilities : : SimplifySkeletalMeshLOD ( USkeletalMesh * SkeletalMesh , int32 DesiredLOD , const ITargetPlatform * TargetPlatform , bool bRestoreClothing /*= false*/ , FThreadSafeBool * OutNeedsPackageDirtied /*= nullptr*/ )
2015-02-13 15:44:00 -05:00
{
2021-02-18 11:19:19 -04:00
TRACE_CPUPROFILER_EVENT_SCOPE ( FLODUtilities : : SimplifySkeletalMeshLOD ) ;
2017-06-21 10:25:35 -04:00
IMeshReductionModule & ReductionModule = FModuleManager : : Get ( ) . LoadModuleChecked < IMeshReductionModule > ( " MeshReductionInterface " ) ;
IMeshReduction * MeshReduction = ReductionModule . GetSkeletalMeshReductionInterface ( ) ;
2021-04-08 14:32:07 -04:00
if ( ! MeshReduction )
{
UE_ASSET_LOG ( LogLODUtilities , Warning , SkeletalMesh , TEXT ( " Cannot reduce skeletalmesh LOD because there is no active reduction plugin. " ) ) ;
return ;
}
2015-02-13 15:44:00 -05:00
2021-04-08 14:32:07 -04:00
check ( MeshReduction - > IsSupported ( ) ) ;
2018-11-16 11:15:08 -05:00
2019-10-01 20:41:42 -04:00
2018-11-16 11:15:08 -05:00
if ( DesiredLOD = = 0
& & SkeletalMesh - > GetLODInfo ( DesiredLOD ) ! = nullptr
& & SkeletalMesh - > GetLODInfo ( DesiredLOD ) - > bHasBeenSimplified
2021-09-21 16:06:32 -04:00
& & ! SkeletalMesh - > GetImportedModel ( ) - > InlineReductionCacheDatas . IsValidIndex ( 0 ) )
2018-11-16 11:15:08 -05:00
{
//The base LOD was reduce and there is no valid data, we cannot regenerate this lod it must be re-import before
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " SkeletalMeshName " ) , FText : : FromString ( SkeletalMesh - > GetName ( ) ) ) ;
Args . Add ( TEXT ( " LODIndex " ) , FText : : AsNumber ( DesiredLOD ) ) ;
FText Message = FText : : Format ( NSLOCTEXT ( " UnrealEd " , " MeshSimp_GenerateLODCannotGenerateMissingData " , " Cannot generate LOD {LODIndex} for skeletal mesh '{SkeletalMeshName}'. This LOD must be re-import to create the necessary data " ) , Args ) ;
2021-02-18 11:19:19 -04:00
if ( FApp : : IsUnattended ( ) | | ! IsInGameThread ( ) )
2018-11-16 11:15:08 -05:00
{
UE_LOG ( LogLODUtilities , Warning , TEXT ( " %s " ) , * ( Message . ToString ( ) ) ) ;
}
else
{
FMessageDialog : : Open ( EAppMsgType : : Ok , Message ) ;
}
return ;
}
2019-10-14 09:26:02 -04:00
if ( IsInGameThread ( ) )
2015-02-13 15:44:00 -05:00
{
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " DesiredLOD " ) , DesiredLOD ) ;
Args . Add ( TEXT ( " SkeletalMeshName " ) , FText : : FromString ( SkeletalMesh - > GetName ( ) ) ) ;
const FText StatusUpdate = FText : : Format ( NSLOCTEXT ( " UnrealEd " , " MeshSimp_GeneratingLOD_F " , " Generating LOD{DesiredLOD} for {SkeletalMeshName}... " ) , Args ) ;
GWarn - > BeginSlowTask ( StatusUpdate , true ) ;
}
2019-10-01 20:41:42 -04:00
FScopedSkeletalMeshPostEditChange ScopedPostEditChange ( SkeletalMesh ) ;
2019-04-15 10:23:09 -04:00
// Unbind DesiredLOD existing clothing assets before we simplify this LOD
TArray < ClothingAssetUtils : : FClothingAssetMeshBinding > ClothingBindings ;
2019-10-01 20:41:42 -04:00
if ( bRestoreClothing & & SkeletalMesh - > GetImportedModel ( ) & & SkeletalMesh - > GetImportedModel ( ) - > LODModels . IsValidIndex ( DesiredLOD ) )
2019-04-15 10:23:09 -04:00
{
2019-10-01 20:41:42 -04:00
FLODUtilities : : UnbindClothingAndBackup ( SkeletalMesh , ClothingBindings , DesiredLOD ) ;
2019-04-15 10:23:09 -04:00
}
2021-09-21 16:06:32 -04:00
FInlineReductionDataParameter InlineReductionDataParameter ;
2018-11-16 11:15:08 -05:00
if ( SkeletalMesh - > GetLODInfo ( DesiredLOD ) ! = nullptr )
{
FSkeletalMeshModel * SkeletalMeshResource = SkeletalMesh - > GetImportedModel ( ) ;
FSkeletalMeshOptimizationSettings & Settings = SkeletalMesh - > GetLODInfo ( DesiredLOD ) - > ReductionSettings ;
2019-09-10 11:35:20 -04:00
//We must save the original reduction data, special case when we reduce inline we save even if its already simplified
if ( SkeletalMeshResource - > LODModels . IsValidIndex ( DesiredLOD ) & & ( ! SkeletalMesh - > GetLODInfo ( DesiredLOD ) - > bHasBeenSimplified | | DesiredLOD = = Settings . BaseLOD ) )
2018-11-16 11:15:08 -05:00
{
2020-06-23 18:40:00 -04:00
2018-11-16 11:15:08 -05:00
FSkeletalMeshLODModel & SrcModel = SkeletalMeshResource - > LODModels [ DesiredLOD ] ;
2021-09-21 16:06:32 -04:00
if ( ! SkeletalMeshResource - > InlineReductionCacheDatas . IsValidIndex ( DesiredLOD ) )
2018-11-16 11:15:08 -05:00
{
2021-09-21 16:06:32 -04:00
//We should not do that in a worker thread, the serialization of the SkeletalMeshResource is suppose to allocate the correct number of inline data caches
//If the user add LOD in person editor, the simplification will be call in the game thread, see FLODUtilities::RegenerateLOD
if ( ! ensure ( IsInGameThread ( ) ) )
{
UE_ASSET_LOG ( LogLODUtilities , Error , SkeletalMesh , TEXT ( " FLODUtilities::SimplifySkeletalMeshLOD: InlineReductionCacheDatas was not added in the game thread. " ) ) ;
}
SkeletalMeshResource - > InlineReductionCacheDatas . AddDefaulted ( ( DesiredLOD + 1 ) - SkeletalMeshResource - > InlineReductionCacheDatas . Num ( ) ) ;
2018-11-16 11:15:08 -05:00
}
2021-09-21 16:06:32 -04:00
check ( SkeletalMeshResource - > InlineReductionCacheDatas . IsValidIndex ( DesiredLOD ) ) ;
SkeletalMeshResource - > InlineReductionCacheDatas [ DesiredLOD ] . SetCacheGeometryInfo ( SrcModel ) ;
InlineReductionDataParameter . InlineOriginalSrcMorphTargetData . Empty ( SkeletalMesh - > GetMorphTargets ( ) . Num ( ) ) ;
for ( UMorphTarget * MorphTarget : SkeletalMesh - > GetMorphTargets ( ) )
2018-11-16 11:15:08 -05:00
{
2021-09-21 16:06:32 -04:00
if ( ! MorphTarget - > HasDataForLOD ( DesiredLOD ) )
2018-11-16 11:15:08 -05:00
{
2021-09-21 16:06:32 -04:00
continue ;
2018-11-16 11:15:08 -05:00
}
2021-09-21 16:06:32 -04:00
TArray < FMorphTargetDelta > & MorphDeltasArray = InlineReductionDataParameter . InlineOriginalSrcMorphTargetData . FindOrAdd ( MorphTarget - > GetFullName ( ) ) ;
const FMorphTargetLODModel & BaseMorphModel = MorphTarget - > GetMorphLODModels ( ) [ DesiredLOD ] ;
//Iterate each original morph target source index to fill the NewMorphTargetDeltas array with the TargetMatchData.
int32 NumDeltas = 0 ;
const FMorphTargetDelta * BaseDeltaArray = MorphTarget - > GetMorphTargetDelta ( DesiredLOD , NumDeltas ) ;
for ( int32 DeltaIndex = 0 ; DeltaIndex < NumDeltas ; DeltaIndex + + )
2019-10-01 20:41:42 -04:00
{
2021-09-21 16:06:32 -04:00
MorphDeltasArray . Add ( BaseDeltaArray [ DeltaIndex ] ) ;
2019-10-01 20:41:42 -04:00
}
2021-09-21 16:06:32 -04:00
}
2018-11-16 11:15:08 -05:00
2021-09-21 16:06:32 -04:00
// Copy the original SkeletalMesh LODModel
// Unbind clothing before saving the original data, we must not restore clothing to do inline reduction
{
TArray < ClothingAssetUtils : : FClothingAssetMeshBinding > TemporaryRemoveClothingBindings ;
FLODUtilities : : UnbindClothingAndBackup ( SkeletalMesh , TemporaryRemoveClothingBindings , DesiredLOD ) ;
FSkeletalMeshLODModel : : CopyStructure ( & InlineReductionDataParameter . InlineOriginalSrcModel , & SrcModel ) ;
if ( TemporaryRemoveClothingBindings . Num ( ) > 0 )
2018-11-16 11:15:08 -05:00
{
2021-09-21 16:06:32 -04:00
FLODUtilities : : RestoreClothingFromBackup ( SkeletalMesh , TemporaryRemoveClothingBindings , DesiredLOD ) ;
2018-11-16 11:15:08 -05:00
}
}
2021-09-21 16:06:32 -04:00
InlineReductionDataParameter . bIsDataValid = true ;
if ( DesiredLOD = = 0 )
{
SkeletalMesh - > GetLODInfo ( DesiredLOD ) - > SourceImportFilename = SkeletalMesh - > GetAssetImportData ( ) - > GetFirstFilename ( ) ;
}
2018-11-16 11:15:08 -05:00
}
}
2021-03-18 15:20:03 -04:00
if ( MeshReduction - > ReduceSkeletalMesh ( SkeletalMesh , DesiredLOD , TargetPlatform ) )
2015-02-13 15:44:00 -05:00
{
2018-11-16 11:15:08 -05:00
check ( SkeletalMesh - > GetLODNum ( ) > = 1 ) ;
2019-01-09 16:21:13 -05:00
2021-09-21 16:06:32 -04:00
//Manage morph target after the reduction. either apply to the reduce LOD or clear them all
2018-02-22 11:25:06 -05:00
{
2019-01-09 16:21:13 -05:00
FSkeletalMeshOptimizationSettings & ReductionSettings = SkeletalMesh - > GetLODInfo ( DesiredLOD ) - > ReductionSettings ;
//Apply morph to the new LOD. Force it if we reduce the base LOD, base LOD must apply the morph target
if ( ReductionSettings . bRemapMorphTargets )
2018-02-22 11:25:06 -05:00
{
2021-09-21 16:06:32 -04:00
ApplyMorphTargetsToLOD ( SkeletalMesh , ReductionSettings . BaseLOD , DesiredLOD , InlineReductionDataParameter ) ;
2018-02-22 11:25:06 -05:00
}
else
{
2019-01-09 16:21:13 -05:00
ClearGeneratedMorphTarget ( SkeletalMesh , DesiredLOD ) ;
2018-02-22 11:25:06 -05:00
}
2021-09-21 16:06:32 -04:00
}
2019-01-09 16:21:13 -05:00
2020-02-12 12:41:49 -05:00
if ( IsInGameThread ( ) )
{
SkeletalMesh - > MarkPackageDirty ( ) ;
}
else if ( OutNeedsPackageDirtied )
{
( * OutNeedsPackageDirtied ) = true ;
}
2015-02-13 15:44:00 -05:00
}
else
{
// Simplification failed! Warn the user.
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " SkeletalMeshName " ) , FText : : FromString ( SkeletalMesh - > GetName ( ) ) ) ;
const FText Message = FText : : Format ( NSLOCTEXT ( " UnrealEd " , " MeshSimp_GenerateLODFailed_F " , " An error occurred while simplifying the geometry for mesh '{SkeletalMeshName}'. Consider adjusting simplification parameters and re-simplifying the mesh. " ) , Args ) ;
2021-02-18 11:19:19 -04:00
if ( FApp : : IsUnattended ( ) | | ! IsInGameThread ( ) )
{
UE_LOG ( LogLODUtilities , Warning , TEXT ( " %s " ) , * ( Message . ToString ( ) ) ) ;
}
else
{
FMessageDialog : : Open ( EAppMsgType : : Ok , Message ) ;
}
2015-02-13 15:44:00 -05:00
}
2019-04-15 10:23:09 -04:00
//Put back the clothing for the DesiredLOD
2019-10-01 20:41:42 -04:00
if ( bRestoreClothing & & ClothingBindings . Num ( ) > 0 & & SkeletalMesh - > GetImportedModel ( ) - > LODModels . IsValidIndex ( DesiredLOD ) )
2019-04-15 10:23:09 -04:00
{
2019-10-01 20:41:42 -04:00
FLODUtilities : : RestoreClothingFromBackup ( SkeletalMesh , ClothingBindings , DesiredLOD ) ;
2019-04-15 10:23:09 -04:00
}
2019-10-14 09:26:02 -04:00
if ( IsInGameThread ( ) )
{
GWarn - > EndSlowTask ( ) ;
}
2015-02-13 15:44:00 -05:00
}
2021-03-18 15:20:03 -04:00
void FLODUtilities : : SimplifySkeletalMeshLOD ( FSkeletalMeshUpdateContext & UpdateContext , int32 DesiredLOD , const ITargetPlatform * TargetPlatform , bool bRestoreClothing /*= false*/ , FThreadSafeBool * OutNeedsPackageDirtied /*= nullptr*/ )
2015-10-28 08:58:16 -04:00
{
USkeletalMesh * SkeletalMesh = UpdateContext . SkeletalMesh ;
2017-06-21 10:25:35 -04:00
IMeshReductionModule & ReductionModule = FModuleManager : : Get ( ) . LoadModuleChecked < IMeshReductionModule > ( " MeshReductionInterface " ) ;
IMeshReduction * MeshReduction = ReductionModule . GetSkeletalMeshReductionInterface ( ) ;
2015-10-28 08:58:16 -04:00
if ( MeshReduction & & MeshReduction - > IsSupported ( ) & & SkeletalMesh )
{
2021-03-18 15:20:03 -04:00
SimplifySkeletalMeshLOD ( SkeletalMesh , DesiredLOD , TargetPlatform , bRestoreClothing , OutNeedsPackageDirtied ) ;
2018-02-22 11:25:06 -05:00
2018-05-23 21:04:31 -04:00
if ( UpdateContext . OnLODChanged . IsBound ( ) )
{
//Notify calling system of change
UpdateContext . OnLODChanged . ExecuteIfBound ( ) ;
}
2015-10-28 08:58:16 -04:00
}
}
2018-11-16 11:15:08 -05:00
2021-09-21 16:06:32 -04:00
bool FLODUtilities : : RestoreSkeletalMeshLODImportedData_DEPRECATED ( USkeletalMesh * SkeletalMesh , int32 LodIndex )
2018-11-16 11:15:08 -05:00
{
2021-09-21 16:06:32 -04:00
const bool bThisFunctionIsDeprecated = true ;
ensure ( ! bThisFunctionIsDeprecated ) ;
UE_ASSET_LOG ( LogLODUtilities , Error , SkeletalMesh , TEXT ( " FLODUtilities::RestoreSkeletalMeshLODImportedData_DEPRECATED: This function is deprecated. " ) ) ;
return false ;
2018-11-16 11:15:08 -05:00
}
2014-10-01 14:45:23 -04:00
void FLODUtilities : : RefreshLODChange ( const USkeletalMesh * SkeletalMesh )
2014-03-14 14:13:41 -04:00
{
2021-01-21 16:22:06 -04:00
for ( FThreadSafeObjectIterator Iter ( USkeletalMeshComponent : : StaticClass ( ) ) ; Iter ; + + Iter )
2014-03-14 14:13:41 -04:00
{
USkeletalMeshComponent * SkeletalMeshComponent = Cast < USkeletalMeshComponent > ( * Iter ) ;
2022-06-16 09:14:04 -04:00
if ( SkeletalMeshComponent - > GetSkeletalMesh ( ) = = SkeletalMesh )
2014-03-14 14:13:41 -04:00
{
// it needs to recreate IF it already has been created
if ( SkeletalMeshComponent - > IsRegistered ( ) )
{
SkeletalMeshComponent - > UpdateLODStatus ( ) ;
SkeletalMeshComponent - > MarkRenderStateDirty ( ) ;
}
}
}
}
2019-05-09 06:20:31 -04:00
2020-06-23 18:40:00 -04:00
bool ValidateAlternateSkeleton ( const FSkeletalMeshImportData & ImportDataSrc , const FSkeletalMeshImportData & ImportDataDest , const FString & SkeletalMeshDestName , const int32 LODIndexDest )
2019-05-09 06:20:31 -04:00
{
bool bIsunattended = GIsRunningUnattendedScript | | FApp : : IsUnattended ( ) ;
int32 BoneNumberDest = ImportDataDest . RefBonesBinary . Num ( ) ;
int32 BoneNumberSrc = ImportDataSrc . RefBonesBinary . Num ( ) ;
//We also want to report any missing bone, because skinning quality will be impacted if bones are missing
TArray < FString > DestBonesNotUsedBySrc ;
TArray < FString > SrcBonesNotUsedByDest ;
for ( int32 BoneIndexSrc = 0 ; BoneIndexSrc < BoneNumberSrc ; + + BoneIndexSrc )
{
FString BoneNameSrc = ImportDataSrc . RefBonesBinary [ BoneIndexSrc ] . Name ;
2020-06-23 18:40:00 -04:00
bool bFoundMatch = false ;
2019-05-09 06:20:31 -04:00
for ( int32 BoneIndexDest = 0 ; BoneIndexDest < BoneNumberDest ; + + BoneIndexDest )
{
if ( ImportDataDest . RefBonesBinary [ BoneIndexDest ] . Name . Equals ( BoneNameSrc ) )
{
2020-06-23 18:40:00 -04:00
bFoundMatch = true ;
2019-05-09 06:20:31 -04:00
break ;
}
}
2020-06-23 18:40:00 -04:00
if ( ! bFoundMatch )
2019-05-09 06:20:31 -04:00
{
SrcBonesNotUsedByDest . Add ( BoneNameSrc ) ;
}
}
for ( int32 BoneIndexDest = 0 ; BoneIndexDest < BoneNumberDest ; + + BoneIndexDest )
{
FString BoneNameDest = ImportDataDest . RefBonesBinary [ BoneIndexDest ] . Name ;
bool bFound = false ;
for ( int32 BoneIndexSrc = 0 ; BoneIndexSrc < BoneNumberSrc ; + + BoneIndexSrc )
{
FString BoneNameSrc = ImportDataSrc . RefBonesBinary [ BoneIndexSrc ] . Name ;
if ( BoneNameDest . Equals ( BoneNameSrc ) )
{
bFound = true ;
break ;
}
}
if ( ! bFound )
{
DestBonesNotUsedBySrc . Add ( BoneNameDest ) ;
}
}
if ( SrcBonesNotUsedByDest . Num ( ) > 0 )
{
//Let the user know
if ( ! bIsunattended )
{
FString BoneList ;
for ( FString & BoneName : SrcBonesNotUsedByDest )
{
BoneList + = BoneName ;
BoneList + = TEXT ( " \n " ) ;
}
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " SkeletalMeshName " ) , FText : : FromString ( SkeletalMeshDestName ) ) ;
Args . Add ( TEXT ( " LODIndex " ) , FText : : AsNumber ( LODIndexDest ) ) ;
Args . Add ( TEXT ( " BoneList " ) , FText : : FromString ( BoneList ) ) ;
FText Message = FText : : Format ( NSLOCTEXT ( " UnrealEd " , " AlternateSkinningImport_SourceBoneNotUseByDestination " , " Not all the alternate mesh bones are used by the LOD {LODIndex} when importing alternate weights for skeletal mesh '{SkeletalMeshName}'. \n Bones List: \n {BoneList} " ) , Args ) ;
2020-06-23 18:40:00 -04:00
if ( FMessageDialog : : Open ( EAppMsgType : : OkCancel , Message ) = = EAppReturnType : : Cancel )
{
return false ;
}
}
else
{
UE_LOG ( LogLODUtilities , Error , TEXT ( " Alternate skinning import: Not all the alternate mesh bones are used by the mesh. " ) ) ;
return false ;
2019-05-09 06:20:31 -04:00
}
}
2020-06-23 18:40:00 -04:00
else if ( DestBonesNotUsedBySrc . Num ( ) > 0 ) //Do a else here since the DestBonesNotUsedBySrc is less prone to give a bad alternate influence result.
2019-05-09 06:20:31 -04:00
{
//Let the user know
if ( ! bIsunattended )
{
FString BoneList ;
for ( FString & BoneName : DestBonesNotUsedBySrc )
{
BoneList + = BoneName ;
BoneList + = TEXT ( " \n " ) ;
}
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " SkeletalMeshName " ) , FText : : FromString ( SkeletalMeshDestName ) ) ;
Args . Add ( TEXT ( " LODIndex " ) , FText : : AsNumber ( LODIndexDest ) ) ;
Args . Add ( TEXT ( " BoneList " ) , FText : : FromString ( BoneList ) ) ;
FText Message = FText : : Format ( NSLOCTEXT ( " UnrealEd " , " AlternateSkinningImport_DestinationBoneNotUseBySource " , " Not all the LOD {LODIndex} bones are used by the alternate mesh when importing alternate weights for skeletal mesh '{SkeletalMeshName}'. \n Bones List: \n {BoneList} " ) , Args ) ;
2020-06-23 18:40:00 -04:00
if ( FMessageDialog : : Open ( EAppMsgType : : OkCancel , Message ) = = EAppReturnType : : Cancel )
{
return false ;
}
}
else
{
UE_LOG ( LogLODUtilities , Display , TEXT ( " Alternate skinning import: Not all the mesh bones are used by the alternate mesh. " ) ) ;
return false ;
}
}
return true ;
}
/*
* The remap use the name to find the corresponding bone index between the source and destination skeleton
*/
void FillRemapBoneIndexSrcToDest ( const FSkeletalMeshImportData & ImportDataSrc , const FSkeletalMeshImportData & ImportDataDest , TMap < int32 , int32 > & RemapBoneIndexSrcToDest )
{
RemapBoneIndexSrcToDest . Empty ( ImportDataSrc . RefBonesBinary . Num ( ) ) ;
int32 BoneNumberDest = ImportDataDest . RefBonesBinary . Num ( ) ;
int32 BoneNumberSrc = ImportDataSrc . RefBonesBinary . Num ( ) ;
for ( int32 BoneIndexSrc = 0 ; BoneIndexSrc < BoneNumberSrc ; + + BoneIndexSrc )
{
FString BoneNameSrc = ImportDataSrc . RefBonesBinary [ BoneIndexSrc ] . Name ;
for ( int32 BoneIndexDest = 0 ; BoneIndexDest < BoneNumberDest ; + + BoneIndexDest )
{
if ( ImportDataDest . RefBonesBinary [ BoneIndexDest ] . Name . Equals ( BoneNameSrc ) )
{
RemapBoneIndexSrcToDest . Add ( BoneIndexSrc , BoneIndexDest ) ;
break ;
}
}
if ( ! RemapBoneIndexSrcToDest . Contains ( BoneIndexSrc ) )
{
RemapBoneIndexSrcToDest . Add ( BoneIndexSrc , INDEX_NONE ) ;
2019-05-09 06:20:31 -04:00
}
}
}
namespace VertexMatchNameSpace
{
struct FVertexMatchResult
{
TArray < uint32 > VertexIndexes ;
TArray < float > Ratios ;
} ;
}
struct FTriangleOctreeSemantics
{
// When a leaf gets more than this number of elements, it will split itself into a node with multiple child leaves
2020-04-22 10:41:35 -04:00
enum { MaxElementsPerLeaf = 10 } ;
2019-05-09 06:20:31 -04:00
// This is used for incremental updates. When removing a polygon, larger values will cause leaves to be removed and collapsed into a parent node.
2020-04-22 10:41:35 -04:00
enum { MinInclusiveElementsPerNode = 5 } ;
2019-05-09 06:20:31 -04:00
// How deep the tree can go.
enum { MaxNodeDepth = 20 } ;
typedef TInlineAllocator < MaxElementsPerLeaf > ElementAllocator ;
FORCEINLINE static FBoxCenterAndExtent GetBoundingBox ( const FTriangleElement & Element )
{
return Element . PositionBound ;
}
FORCEINLINE static bool AreElementsEqual ( const FTriangleElement & A , const FTriangleElement & B )
{
return ( A . TriangleIndex = = B . TriangleIndex ) ;
}
2020-04-21 23:23:12 -04:00
FORCEINLINE static void SetElementId ( const FTriangleElement & Element , FOctreeElementId2 OctreeElementID )
2019-05-09 06:20:31 -04:00
{
}
} ;
2020-04-21 20:01:52 -04:00
typedef TOctree2 < FTriangleElement , FTriangleOctreeSemantics > TTriangleElementOctree ;
2019-05-09 06:20:31 -04:00
void MatchVertexIndexUsingPosition (
const FSkeletalMeshImportData & ImportDataDest
, const FSkeletalMeshImportData & ImportDataSrc
, TSortedMap < uint32 , VertexMatchNameSpace : : FVertexMatchResult > & VertexIndexSrcToVertexIndexDestMatches
2020-06-23 18:40:00 -04:00
, const TArray < uint32 > & VertexIndexToMatchWithPositions
2019-05-09 06:20:31 -04:00
, bool & bNoMatchMsgDone )
{
2020-06-23 18:40:00 -04:00
if ( VertexIndexToMatchWithPositions . Num ( ) < = 0 )
2019-05-09 06:20:31 -04:00
{
return ;
}
int32 FaceNumberDest = ImportDataDest . Faces . Num ( ) ;
//Setup the Position Octree with the destination faces so we can match the source vertex index
TArray < FTriangleElement > TrianglesDest ;
FBox BaseMeshPositionBound ( EForceInit : : ForceInit ) ;
for ( int32 FaceIndexDest = 0 ; FaceIndexDest < FaceNumberDest ; + + FaceIndexDest )
{
const SkeletalMeshImportData : : FTriangle & Triangle = ImportDataDest . Faces [ FaceIndexDest ] ;
FTriangleElement TriangleElement ;
TriangleElement . UVsBound . Init ( ) ;
2021-04-08 14:32:07 -04:00
FBox TrianglePositionBound ;
TrianglePositionBound . Init ( ) ;
2019-05-09 06:20:31 -04:00
for ( int32 Corner = 0 ; Corner < 3 ; + + Corner )
{
const uint32 WedgeIndexDest = Triangle . WedgeIndex [ Corner ] ;
const uint32 VertexIndexDest = ImportDataDest . Wedges [ WedgeIndexDest ] . VertexIndex ;
TriangleElement . Indexes . Add ( WedgeIndexDest ) ;
FSoftSkinVertex SoftSkinVertex ;
SoftSkinVertex . Position = ImportDataDest . Points [ VertexIndexDest ] ;
SoftSkinVertex . UVs [ 0 ] = ImportDataDest . Wedges [ WedgeIndexDest ] . UVs [ 0 ] ;
TriangleElement . Vertices . Add ( SoftSkinVertex ) ;
2022-02-02 01:45:23 -05:00
TriangleElement . UVsBound + = FVector2D ( SoftSkinVertex . UVs [ 0 ] ) ;
2022-02-02 07:59:31 -05:00
TrianglePositionBound + = ( FVector ) SoftSkinVertex . Position ;
BaseMeshPositionBound + = ( FVector ) SoftSkinVertex . Position ;
2019-05-09 06:20:31 -04:00
}
2021-04-08 14:32:07 -04:00
BaseMeshPositionBound + = TrianglePositionBound ;
TriangleElement . PositionBound = FBoxCenterAndExtent ( TrianglePositionBound ) ;
2019-05-09 06:20:31 -04:00
TriangleElement . TriangleIndex = FaceIndexDest ;
TrianglesDest . Add ( TriangleElement ) ;
}
TTriangleElementOctree OcTree ( BaseMeshPositionBound . GetCenter ( ) , BaseMeshPositionBound . GetExtent ( ) . Size ( ) ) ;
for ( FTriangleElement & TriangleElement : TrianglesDest )
{
OcTree . AddElement ( TriangleElement ) ;
}
//Retrieve all triangles that are close to our point, start at 0.25% of OcTree extend
float DistanceThreshold = BaseMeshPositionBound . GetExtent ( ) . Size ( ) * 0.0025f ;
//Find a match triangle for every target vertices
TArray < FTriangleElement > OcTreeTriangleResults ;
OcTreeTriangleResults . Reserve ( TrianglesDest . Num ( ) / 50 ) ; //Reserve 2% to speed up the query
//This lambda store a source vertex index -> source wedge index destination triangle.
//It use a barycentric function to determine the impact on the 3 corner of the triangle.
2021-05-05 15:07:25 -04:00
auto AddMatchTriangle = [ & ImportDataDest , & TrianglesDest , & VertexIndexSrcToVertexIndexDestMatches ] ( const FTriangleElement & BestTriangle , const FVector3f & Position , const uint32 VertexIndexSrc )
2019-05-09 06:20:31 -04:00
{
//Found the surface area of the 3 barycentric triangles from the UVs
2021-05-05 15:07:25 -04:00
FVector3f BarycentricWeight ;
2019-05-09 06:20:31 -04:00
BarycentricWeight = GetBaryCentric ( Position , BestTriangle . Vertices [ 0 ] . Position , BestTriangle . Vertices [ 1 ] . Position , BestTriangle . Vertices [ 2 ] . Position ) ;
//Fill the match
VertexMatchNameSpace : : FVertexMatchResult & VertexMatchDest = VertexIndexSrcToVertexIndexDestMatches . FindOrAdd ( VertexIndexSrc ) ;
for ( int32 CornerIndex = 0 ; CornerIndex < 3 ; + + CornerIndex )
{
int32 VertexIndexDest = ImportDataDest . Wedges [ BestTriangle . Indexes [ CornerIndex ] ] . VertexIndex ;
float Ratio = BarycentricWeight [ CornerIndex ] ;
int32 FindIndex = INDEX_NONE ;
if ( ! VertexMatchDest . VertexIndexes . Find ( VertexIndexDest , FindIndex ) )
{
VertexMatchDest . VertexIndexes . Add ( VertexIndexDest ) ;
VertexMatchDest . Ratios . Add ( Ratio ) ;
}
else
{
check ( VertexMatchDest . Ratios . IsValidIndex ( FindIndex ) ) ;
VertexMatchDest . Ratios [ FindIndex ] = FMath : : Max ( VertexMatchDest . Ratios [ FindIndex ] , Ratio ) ;
}
}
} ;
2020-06-23 18:40:00 -04:00
for ( int32 VertexIndexSrc : VertexIndexToMatchWithPositions )
2019-05-09 06:20:31 -04:00
{
2021-05-05 15:07:25 -04:00
FVector3f PositionSrc = ImportDataSrc . Points [ VertexIndexSrc ] ;
2019-05-09 06:20:31 -04:00
OcTreeTriangleResults . Reset ( ) ;
//Use the OcTree to find closest triangle
FVector Extent ( DistanceThreshold , DistanceThreshold , DistanceThreshold ) ;
2022-02-02 07:59:31 -05:00
FBoxCenterAndExtent CurBox ( ( FVector ) PositionSrc , Extent ) ;
2020-04-22 10:41:35 -04:00
2019-05-09 06:20:31 -04:00
while ( OcTreeTriangleResults . Num ( ) < = 0 )
{
2020-04-15 01:18:48 -04:00
OcTree . FindElementsWithBoundsTest ( CurBox , [ & OcTreeTriangleResults ] ( const FTriangleElement & Element )
2019-05-09 06:20:31 -04:00
{
// Add all of the elements in the current node to the list of points to consider for closest point calculations
2020-04-14 16:59:52 -04:00
OcTreeTriangleResults . Add ( Element ) ;
} ) ;
2019-05-09 06:20:31 -04:00
//Increase the extend so we try to found in a larger area
Extent * = 2 ;
2020-04-22 10:41:35 -04:00
if ( Extent . SizeSquared ( ) > = BaseMeshPositionBound . GetSize ( ) . SizeSquared ( ) )
{
//Extend must not be bigger then the whole mesh, its acceptable to have error at this point
break ;
}
2022-02-02 07:59:31 -05:00
CurBox = FBox ( ( FVector ) PositionSrc - Extent , ( FVector ) PositionSrc + Extent ) ;
2019-05-09 06:20:31 -04:00
}
//Get the 3D distance between a point and a destination triangle
auto GetDistanceSrcPointToDestTriangle = [ & TrianglesDest , & PositionSrc ] ( const uint32 DestTriangleIndex ) - > float
{
FTriangleElement & CandidateTriangle = TrianglesDest [ DestTriangleIndex ] ;
2022-02-02 07:59:31 -05:00
return FVector : : DistSquared ( FMath : : ClosestPointOnTriangleToPoint ( ( FVector ) PositionSrc , ( FVector ) CandidateTriangle . Vertices [ 0 ] . Position , ( FVector ) CandidateTriangle . Vertices [ 1 ] . Position , ( FVector ) CandidateTriangle . Vertices [ 2 ] . Position ) , ( FVector ) PositionSrc ) ;
2019-05-09 06:20:31 -04:00
} ;
//Brute force finding of closest triangle using 3D position
auto FailSafeUnmatchVertex = [ & GetDistanceSrcPointToDestTriangle , & OcTreeTriangleResults ] ( uint32 & OutIndexMatch ) - > bool
{
bool bFoundMatch = false ;
float ClosestTriangleDistSquared = MAX_flt ;
for ( const FTriangleElement & MatchTriangle : OcTreeTriangleResults )
{
int32 MatchTriangleIndex = MatchTriangle . TriangleIndex ;
float TriangleDistSquared = GetDistanceSrcPointToDestTriangle ( MatchTriangleIndex ) ;
if ( TriangleDistSquared < ClosestTriangleDistSquared )
{
ClosestTriangleDistSquared = TriangleDistSquared ;
OutIndexMatch = MatchTriangleIndex ;
bFoundMatch = true ;
}
}
return bFoundMatch ;
} ;
//Find all Triangles that contain the Target UV
if ( OcTreeTriangleResults . Num ( ) > 0 )
{
TArray < uint32 > MatchTriangleIndexes ;
uint32 FoundIndexMatch = INDEX_NONE ;
2022-02-02 07:59:31 -05:00
if ( ! FindTrianglePositionMatch ( ( FVector ) PositionSrc , TrianglesDest , OcTreeTriangleResults , MatchTriangleIndexes ) )
2019-05-09 06:20:31 -04:00
{
2020-06-23 18:40:00 -04:00
//There is no Position match possible, use brute force fail safe
2019-05-09 06:20:31 -04:00
if ( ! FailSafeUnmatchVertex ( FoundIndexMatch ) )
{
//We should always have a match
if ( ! bNoMatchMsgDone )
{
UE_LOG ( LogLODUtilities , Warning , TEXT ( " Alternate skinning import: Cannot find a triangle from the destination LOD that contain a vertex UV in the imported alternate skinning LOD mesh. Alternate skinning quality will be lower. " ) ) ;
bNoMatchMsgDone = true ;
}
continue ;
}
}
float ClosestTriangleDistSquared = MAX_flt ;
if ( MatchTriangleIndexes . Num ( ) = = 1 )
{
//One match, this mean no mirror UVs simply take the single match
FoundIndexMatch = MatchTriangleIndexes [ 0 ] ;
ClosestTriangleDistSquared = GetDistanceSrcPointToDestTriangle ( FoundIndexMatch ) ;
}
else
{
//Geometry can use mirror so the UVs are not unique. Use the closest match triangle to the point to find the best match
for ( uint32 MatchTriangleIndex : MatchTriangleIndexes )
{
float TriangleDistSquared = GetDistanceSrcPointToDestTriangle ( MatchTriangleIndex ) ;
if ( TriangleDistSquared < ClosestTriangleDistSquared )
{
ClosestTriangleDistSquared = TriangleDistSquared ;
FoundIndexMatch = MatchTriangleIndex ;
}
}
}
//FAIL SAFE, make sure we have a match that make sense
//Use the mesh geometry bound extent (1% of it) to validate we are close enough.
if ( ClosestTriangleDistSquared > BaseMeshPositionBound . GetExtent ( ) . SizeSquared ( ) * 0.01f )
{
//Executing fail safe, if the UVs are too much off because of the reduction, use the closest distance to polygons to find the match
//This path is not optimize and should not happen often.
FailSafeUnmatchVertex ( FoundIndexMatch ) ;
}
//We should always have a valid match at this point
check ( TrianglesDest . IsValidIndex ( FoundIndexMatch ) ) ;
AddMatchTriangle ( TrianglesDest [ FoundIndexMatch ] , PositionSrc , VertexIndexSrc ) ;
}
else
{
if ( ! bNoMatchMsgDone )
{
UE_LOG ( LogLODUtilities , Warning , TEXT ( " Alternate skinning import: Cannot find a triangle from the destination LOD that contain a vertex UV in the imported alternate skinning LOD mesh. Alternate skinning quality will be lower. " ) ) ;
bNoMatchMsgDone = true ;
}
}
}
}
2019-09-10 11:35:20 -04:00
bool FLODUtilities : : UpdateAlternateSkinWeights ( USkeletalMesh * SkeletalMeshDest , const FName & ProfileNameDest , int32 LODIndexDest , FOverlappingThresholds OverlappingThresholds , bool ShouldImportNormals , bool ShouldImportTangents , bool bUseMikkTSpace , bool bComputeWeightedNormals )
2019-05-09 06:20:31 -04:00
{
//Grab all the destination structure
check ( SkeletalMeshDest ) ;
check ( SkeletalMeshDest - > GetImportedModel ( ) ) ;
check ( SkeletalMeshDest - > GetImportedModel ( ) - > LODModels . IsValidIndex ( LODIndexDest ) ) ;
FSkeletalMeshLODModel & LODModelDest = SkeletalMeshDest - > GetImportedModel ( ) - > LODModels [ LODIndexDest ] ;
2019-12-19 18:07:47 -05:00
if ( SkeletalMeshDest - > IsLODImportedDataEmpty ( LODIndexDest ) )
2019-05-09 06:20:31 -04:00
{
2019-12-19 18:07:47 -05:00
UE_LOG ( LogLODUtilities , Error , TEXT ( " Failed to import Skin Weight Profile as the target skeletal mesh (%s) requires reimporting first. " ) , * SkeletalMeshDest - > GetName ( ) ) ;
2019-05-09 06:20:31 -04:00
//Very old asset will not have this data, we cannot add alternate until the asset is reimported
return false ;
}
FSkeletalMeshImportData ImportDataDest ;
2019-12-19 18:07:47 -05:00
SkeletalMeshDest - > LoadLODImportedData ( LODIndexDest , ImportDataDest ) ;
2020-11-25 11:17:08 -04:00
return UpdateAlternateSkinWeights ( LODModelDest , ImportDataDest , SkeletalMeshDest , SkeletalMeshDest - > GetRefSkeleton ( ) , ProfileNameDest , LODIndexDest , OverlappingThresholds , ShouldImportNormals , ShouldImportTangents , bUseMikkTSpace , bComputeWeightedNormals ) ;
2019-12-19 18:07:47 -05:00
}
2021-02-18 11:19:19 -04:00
bool FLODUtilities : : UpdateAlternateSkinWeights ( FSkeletalMeshLODModel & LODModelDest , FSkeletalMeshImportData & ImportDataDest , USkeletalMesh * SkeletalMeshDest , const FReferenceSkeleton & RefSkeleton , const FName & ProfileNameDest , int32 LODIndexDest , FOverlappingThresholds OverlappingThresholds , bool ShouldImportNormals , bool ShouldImportTangents , bool bUseMikkTSpace , bool bComputeWeightedNormals )
2019-12-19 18:07:47 -05:00
{
//Ensure log message only once
bool bNoMatchMsgDone = false ;
2019-05-09 06:20:31 -04:00
int32 PointNumberDest = ImportDataDest . Points . Num ( ) ;
int32 VertexNumberDest = ImportDataDest . Points . Num ( ) ;
2019-09-10 11:35:20 -04:00
int32 ProfileIndex = 0 ;
if ( ! ImportDataDest . AlternateInfluenceProfileNames . Find ( ProfileNameDest . ToString ( ) , ProfileIndex ) )
{
2020-06-23 18:40:00 -04:00
FFormatNamedArguments Args ;
2020-08-11 01:36:57 -04:00
Args . Add ( TEXT ( " SkeletalMeshName " ) , FText : : FromString ( SkeletalMeshDest - > GetName ( ) ) ) ;
2020-06-23 18:40:00 -04:00
FText Message = FText : : Format ( NSLOCTEXT ( " FLODUtilities_UpdateAlternateSkinWeights " , " AlternateDataNotAvailable " , " Asset {SkeletalMeshName} failed to import skin weight profile the alternate skinning imported source data is not available. " ) , Args ) ;
UE_LOG ( LogLODUtilities , Warning , TEXT ( " %s " ) , * ( Message . ToString ( ) ) ) ;
2019-09-10 11:35:20 -04:00
return false ;
}
2020-06-23 18:40:00 -04:00
2019-09-10 11:35:20 -04:00
check ( ImportDataDest . AlternateInfluences . IsValidIndex ( ProfileIndex ) ) ;
//The data must be there and must be verified before getting here
const FSkeletalMeshImportData & ImportDataSrc = ImportDataDest . AlternateInfluences [ ProfileIndex ] ;
2019-05-09 06:20:31 -04:00
int32 PointNumberSrc = ImportDataSrc . Points . Num ( ) ;
int32 VertexNumberSrc = ImportDataSrc . Points . Num ( ) ;
int32 InfluenceNumberSrc = ImportDataSrc . Influences . Num ( ) ;
2020-06-23 18:40:00 -04:00
if ( PointNumberDest ! = PointNumberSrc )
2019-05-09 06:20:31 -04:00
{
2020-06-23 18:40:00 -04:00
FFormatNamedArguments Args ;
2020-08-11 01:36:57 -04:00
Args . Add ( TEXT ( " SkeletalMeshName " ) , FText : : FromString ( SkeletalMeshDest - > GetName ( ) ) ) ;
2020-06-23 18:40:00 -04:00
Args . Add ( TEXT ( " PointNumberSrc " ) , PointNumberSrc ) ;
Args . Add ( TEXT ( " PointNumberDest " ) , PointNumberDest ) ;
FText Message = FText : : Format ( NSLOCTEXT ( " FLODUtilities_UpdateAlternateSkinWeights " , " DifferentPointNumber " , " Asset {SkeletalMeshName} failed to import skin weight profile the alternate skinning model has a different number of vertex. Alternate vertex count: {PointNumberSrc}, LOD vertex count: {PointNumberDest} " ) , Args ) ;
UE_LOG ( LogLODUtilities , Warning , TEXT ( " %s " ) , * ( Message . ToString ( ) ) ) ;
2019-05-09 06:20:31 -04:00
return false ;
}
2020-06-23 18:40:00 -04:00
2020-04-22 10:41:35 -04:00
// Create a list of vertex Z/index pairs
TArray < FIndexAndZ > VertIndexAndZ ;
VertIndexAndZ . Reserve ( VertexNumberDest ) ;
for ( int32 VertexIndex = 0 ; VertexIndex < VertexNumberDest ; + + VertexIndex )
{
2022-02-02 07:59:31 -05:00
new ( VertIndexAndZ ) FIndexAndZ ( VertexIndex , ( FVector ) ImportDataDest . Points [ VertexIndex ] ) ;
2020-04-22 10:41:35 -04:00
}
// Sort the vertices by z value
VertIndexAndZ . Sort ( FCompareIndexAndZ ( ) ) ;
2021-05-05 15:07:25 -04:00
auto FindSimilarPosition = [ & VertIndexAndZ , & ImportDataDest ] ( const FVector3f & Position , TArray < int32 > & PositionMatches , const float ComparisonThreshold )
2020-04-22 10:41:35 -04:00
{
PositionMatches . Reset ( ) ;
2022-02-02 07:59:31 -05:00
FIndexAndZ PositionZ = FIndexAndZ ( 0 , ( FVector ) Position ) ;
2020-04-22 10:41:35 -04:00
// Search for duplicates, quickly!
for ( int32 i = 0 ; i < VertIndexAndZ . Num ( ) ; i + + )
{
if ( PositionZ . Z - ComparisonThreshold > VertIndexAndZ [ i ] . Z )
{
continue ;
}
else if ( PositionZ . Z + ComparisonThreshold < VertIndexAndZ [ i ] . Z )
{
break ;
}
2021-05-05 15:07:25 -04:00
const FVector3f & PositionA = ImportDataDest . Points [ VertIndexAndZ [ i ] . Index ] ;
2020-04-22 10:41:35 -04:00
if ( PointsEqual ( PositionA , Position , ComparisonThreshold ) )
{
PositionMatches . Add ( VertIndexAndZ [ i ] . Index ) ;
}
}
} ;
2019-05-09 06:20:31 -04:00
//Create a map linking all similar Position of destination vertex index
2021-05-05 15:07:25 -04:00
TMap < FVector3f , TArray < uint32 > > PositionToVertexIndexDest ;
2019-05-09 06:20:31 -04:00
PositionToVertexIndexDest . Reserve ( VertexNumberSrc ) ;
for ( int32 VertexIndex = 0 ; VertexIndex < VertexNumberDest ; + + VertexIndex )
{
2021-05-05 15:07:25 -04:00
const FVector3f & Position = ImportDataDest . Points [ VertexIndex ] ;
2019-05-09 06:20:31 -04:00
TArray < uint32 > & VertexIndexArray = PositionToVertexIndexDest . FindOrAdd ( Position ) ;
VertexIndexArray . Add ( VertexIndex ) ;
}
//Create a map to remap source bone index to destination bone index
TMap < int32 , int32 > RemapBoneIndexSrcToDest ;
2020-06-23 18:40:00 -04:00
FillRemapBoneIndexSrcToDest ( ImportDataSrc , ImportDataDest , RemapBoneIndexSrcToDest ) ;
2019-05-09 06:20:31 -04:00
//Map to get the vertex index source to a destination vertex match
TSortedMap < uint32 , VertexMatchNameSpace : : FVertexMatchResult > VertexIndexSrcToVertexIndexDestMatches ;
VertexIndexSrcToVertexIndexDestMatches . Reserve ( VertexNumberSrc ) ;
2020-06-23 18:40:00 -04:00
TArray < uint32 > VertexIndexToMatchWithPositions ;
2021-10-01 11:15:15 -04:00
auto FindWedgeIndexesUsingVertexIndex = [ ] ( const FSkeletalMeshImportData & ImportData , const int32 VertexIndex , TArray < int32 > & OutWedgeIndexes )
{
for ( int32 WedgeIndex = 0 ; WedgeIndex < ImportData . Wedges . Num ( ) ; + + WedgeIndex )
{
const SkeletalMeshImportData : : FVertex & Wedge = ImportData . Wedges [ WedgeIndex ] ;
if ( Wedge . VertexIndex = = VertexIndex )
{
OutWedgeIndexes . Add ( WedgeIndex ) ;
}
}
} ;
2019-05-09 06:20:31 -04:00
// Match all source vertex with destination vertex
for ( int32 VertexIndexSrc = 0 ; VertexIndexSrc < PointNumberSrc ; + + VertexIndexSrc )
{
2021-05-05 15:07:25 -04:00
const FVector3f & PositionSrc = ImportDataSrc . Points [ VertexIndexSrc ] ;
2019-05-09 06:20:31 -04:00
2020-04-22 10:41:35 -04:00
TArray < int32 > SimilarDestinationVertex ;
FindSimilarPosition ( PositionSrc , SimilarDestinationVertex , KINDA_SMALL_NUMBER ) ;
if ( SimilarDestinationVertex . Num ( ) = = 0 )
2019-05-09 06:20:31 -04:00
{
//Match with UV projection
2020-06-23 18:40:00 -04:00
VertexIndexToMatchWithPositions . Add ( VertexIndexSrc ) ;
2019-05-09 06:20:31 -04:00
}
else
{
//We have a direct match
VertexMatchNameSpace : : FVertexMatchResult & VertexMatchDest = VertexIndexSrcToVertexIndexDestMatches . Add ( VertexIndexSrc ) ;
2021-10-01 11:15:15 -04:00
TArray < int32 > SrcWedgeIndexes ;
FindWedgeIndexesUsingVertexIndex ( ImportDataSrc , VertexIndexSrc , SrcWedgeIndexes ) ;
2022-03-30 14:39:21 -04:00
if ( SrcWedgeIndexes . Num ( ) > 0 & & SimilarDestinationVertex . Num ( ) > 1 )
2019-05-09 06:20:31 -04:00
{
2022-03-30 14:39:21 -04:00
//Check if we have a point that is perfectly matching (position, UV, material and vertex color). Because normals and tangent are on the triangles we do not test those.
for ( int32 MatchDestinationIndex = 0 ; MatchDestinationIndex < SimilarDestinationVertex . Num ( ) ; + + MatchDestinationIndex )
2021-10-01 11:15:15 -04:00
{
2022-03-30 14:39:21 -04:00
int32 VertexIndexDest = SimilarDestinationVertex [ MatchDestinationIndex ] ;
TArray < int32 > DestWedgeIndexes ;
FindWedgeIndexesUsingVertexIndex ( ImportDataDest , VertexIndexDest , DestWedgeIndexes ) ;
for ( int32 IndexDest = 0 ; IndexDest < DestWedgeIndexes . Num ( ) ; + + IndexDest )
2021-10-01 11:15:15 -04:00
{
2022-03-30 14:39:21 -04:00
int32 DestWedgeIndex = DestWedgeIndexes [ IndexDest ] ;
const SkeletalMeshImportData : : FVertex & WedgeDest = ImportDataDest . Wedges [ DestWedgeIndex ] ;
for ( int32 IndexSrc = 0 ; IndexSrc < SrcWedgeIndexes . Num ( ) ; + + IndexSrc )
{
int32 SrcWedgeIndex = SrcWedgeIndexes [ IndexSrc ] ;
const SkeletalMeshImportData : : FVertex & WedgeSrc = ImportDataSrc . Wedges [ SrcWedgeIndex ] ;
//Wedge == operator test: material, vertex color and UVs
if ( WedgeDest = = WedgeSrc )
{
VertexMatchDest . VertexIndexes . Add ( SimilarDestinationVertex [ MatchDestinationIndex ] ) ;
VertexMatchDest . Ratios . Add ( 1.0f ) ;
break ;
}
}
if ( VertexMatchDest . VertexIndexes . Num ( ) > 0 )
2021-10-01 11:15:15 -04:00
{
break ;
}
}
}
}
//If there is no direct match, simply put everything
if ( VertexMatchDest . VertexIndexes . Num ( ) = = 0 )
{
for ( int32 MatchDestinationIndex = 0 ; MatchDestinationIndex < SimilarDestinationVertex . Num ( ) ; + + MatchDestinationIndex )
{
VertexMatchDest . VertexIndexes . Add ( SimilarDestinationVertex [ MatchDestinationIndex ] ) ;
VertexMatchDest . Ratios . Add ( 1.0f ) ;
}
2019-05-09 06:20:31 -04:00
}
}
}
//Find a match for all unmatched source vertex, unmatched vertex happen when the geometry is different between source and destination mesh
2020-06-23 18:40:00 -04:00
bool bAllSourceVertexAreMatch = VertexIndexToMatchWithPositions . Num ( ) < = 0 & & VertexIndexSrcToVertexIndexDestMatches . Num ( ) = = PointNumberSrc ;
2019-05-09 06:20:31 -04:00
if ( ! bAllSourceVertexAreMatch )
{
2020-06-23 18:40:00 -04:00
MatchVertexIndexUsingPosition ( ImportDataDest , ImportDataSrc , VertexIndexSrcToVertexIndexDestMatches , VertexIndexToMatchWithPositions , bNoMatchMsgDone ) ;
2019-05-09 06:20:31 -04:00
//Make sure each vertex index source has a match, warn the user in case there is no match
for ( int32 VertexIndexSource = 0 ; VertexIndexSource < VertexNumberSrc ; + + VertexIndexSource )
{
if ( ! VertexIndexSrcToVertexIndexDestMatches . Contains ( VertexIndexSource ) )
{
//Skip this vertex, its possible the skinning quality can be affected here
if ( ! bNoMatchMsgDone )
{
UE_LOG ( LogLODUtilities , Warning , TEXT ( " Alternate skinning import: Cannot find a destination vertex index match for source vertex index. Alternate skinning quality will be lower. " ) ) ;
bNoMatchMsgDone = true ;
}
continue ;
}
}
2020-04-22 10:41:35 -04:00
bAllSourceVertexAreMatch = VertexIndexSrcToVertexIndexDestMatches . Num ( ) = = PointNumberSrc ;
2019-05-09 06:20:31 -04:00
}
//Find the Destination to source match, to make sure all extra destination vertex get weighted properly in the alternate influences
TSortedMap < uint32 , VertexMatchNameSpace : : FVertexMatchResult > VertexIndexDestToVertexIndexSrcMatches ;
if ( ! bAllSourceVertexAreMatch | | PointNumberDest ! = PointNumberSrc )
{
VertexIndexDestToVertexIndexSrcMatches . Reserve ( VertexNumberDest ) ;
TArray < uint32 > VertexIndexToMatch ;
VertexIndexToMatch . Reserve ( PointNumberDest ) ;
for ( int32 VertexIndexDest = 0 ; VertexIndexDest < PointNumberDest ; + + VertexIndexDest )
{
VertexIndexToMatch . Add ( VertexIndexDest ) ;
}
MatchVertexIndexUsingPosition ( ImportDataSrc , ImportDataDest , VertexIndexDestToVertexIndexSrcMatches , VertexIndexToMatch , bNoMatchMsgDone ) ;
}
//We now iterate the source influence and create the alternate influence by using the matches between source and destination vertex
TArray < SkeletalMeshImportData : : FRawBoneInfluence > AlternateInfluences ;
AlternateInfluences . Empty ( ImportDataSrc . Influences . Num ( ) ) ;
TMap < uint32 , TArray < int32 > > SourceVertexIndexToAlternateInfluenceIndexMap ;
SourceVertexIndexToAlternateInfluenceIndexMap . Reserve ( InfluenceNumberSrc ) ;
for ( int32 InfluenceIndexSrc = 0 ; InfluenceIndexSrc < InfluenceNumberSrc ; + + InfluenceIndexSrc )
{
2019-09-10 11:35:20 -04:00
const SkeletalMeshImportData : : FRawBoneInfluence & InfluenceSrc = ImportDataSrc . Influences [ InfluenceIndexSrc ] ;
2020-04-22 10:41:35 -04:00
int32 VertexIndexSource = InfluenceSrc . VertexIndex ;
int32 BoneIndexSource = InfluenceSrc . BoneIndex ;
2019-05-09 06:20:31 -04:00
float Weight = InfluenceSrc . Weight ;
//We need to remap the source bone index to have the matching target bone index
2020-04-22 10:41:35 -04:00
int32 BoneIndexDest = RemapBoneIndexSrcToDest [ BoneIndexSource ] ;
2019-05-09 06:20:31 -04:00
if ( BoneIndexDest ! = INDEX_NONE )
{
//Find the match destination vertex index
VertexMatchNameSpace : : FVertexMatchResult * SourceVertexMatch = VertexIndexSrcToVertexIndexDestMatches . Find ( VertexIndexSource ) ;
if ( SourceVertexMatch = = nullptr | | SourceVertexMatch - > VertexIndexes . Num ( ) < = 0 )
{
//No match skip this influence
continue ;
}
TArray < int32 > & AlternateInfluencesMap = SourceVertexIndexToAlternateInfluenceIndexMap . FindOrAdd ( VertexIndexSource ) ;
//No need to merge all vertexindex per bone, ProcessImportMeshInfluences will do this for us later
//So just add all of the entry we have.
for ( int32 ImpactedIndex = 0 ; ImpactedIndex < SourceVertexMatch - > VertexIndexes . Num ( ) ; + + ImpactedIndex )
{
uint32 VertexIndexDest = SourceVertexMatch - > VertexIndexes [ ImpactedIndex ] ;
float Ratio = SourceVertexMatch - > Ratios [ ImpactedIndex ] ;
if ( FMath : : IsNearlyZero ( Ratio , KINDA_SMALL_NUMBER ) )
{
continue ;
}
SkeletalMeshImportData : : FRawBoneInfluence AlternateInfluence ;
AlternateInfluence . BoneIndex = BoneIndexDest ;
AlternateInfluence . VertexIndex = VertexIndexDest ;
2020-09-24 00:43:27 -04:00
AlternateInfluence . Weight = InfluenceSrc . Weight * Ratio ;
2019-05-09 06:20:31 -04:00
int32 AlternateInfluencesIndex = AlternateInfluences . Add ( AlternateInfluence ) ;
AlternateInfluencesMap . Add ( AlternateInfluencesIndex ) ;
}
}
}
//In case the source geometry was not matching the destination we have to add influence for each extra destination vertex index
if ( VertexIndexDestToVertexIndexSrcMatches . Num ( ) > 0 )
{
TArray < bool > DestinationVertexIndexMatched ;
DestinationVertexIndexMatched . AddZeroed ( PointNumberDest ) ;
int32 InfluenceNumberDest = ImportDataDest . Influences . Num ( ) ;
int32 AlternateInfluenceNumber = AlternateInfluences . Num ( ) ;
//We want to avoid making duplicate so we use a map where the key is the boneindex mix with the destination vertex index
TMap < uint64 , int32 > InfluenceKeyToInfluenceIndex ;
InfluenceKeyToInfluenceIndex . Reserve ( AlternateInfluenceNumber ) ;
for ( int32 AlternateInfluenceIndex = 0 ; AlternateInfluenceIndex < AlternateInfluenceNumber ; + + AlternateInfluenceIndex )
{
SkeletalMeshImportData : : FRawBoneInfluence & Influence = AlternateInfluences [ AlternateInfluenceIndex ] ;
DestinationVertexIndexMatched [ Influence . VertexIndex ] = true ;
uint64 Key = ( ( uint64 ) ( Influence . BoneIndex ) < < 32 & 0xFFFFFFFF00000000 ) | ( ( uint64 ) ( Influence . VertexIndex ) & 0x00000000FFFFFFFF ) ;
InfluenceKeyToInfluenceIndex . Add ( Key , AlternateInfluenceIndex ) ;
}
for ( int32 VertexIndexDestination = 0 ; VertexIndexDestination < VertexNumberDest ; + + VertexIndexDestination )
{
//Skip if the vertex is already matched
if ( DestinationVertexIndexMatched [ VertexIndexDestination ] )
{
continue ;
}
VertexMatchNameSpace : : FVertexMatchResult * DestinationVertexMatch = VertexIndexDestToVertexIndexSrcMatches . Find ( VertexIndexDestination ) ;
if ( DestinationVertexMatch = = nullptr | | DestinationVertexMatch - > VertexIndexes . Num ( ) < = 0 )
{
//No match skip this influence
continue ;
}
for ( int32 ImpactedIndex = 0 ; ImpactedIndex < DestinationVertexMatch - > VertexIndexes . Num ( ) ; + + ImpactedIndex )
{
uint32 VertexIndexSrc = DestinationVertexMatch - > VertexIndexes [ ImpactedIndex ] ;
float Ratio = DestinationVertexMatch - > Ratios [ ImpactedIndex ] ;
if ( ! FMath : : IsNearlyZero ( Ratio , KINDA_SMALL_NUMBER ) )
{
//Find src influence for this source vertex index
TArray < int32 > * AlternateInfluencesMap = SourceVertexIndexToAlternateInfluenceIndexMap . Find ( VertexIndexSrc ) ;
if ( AlternateInfluencesMap = = nullptr )
{
continue ;
}
for ( int32 AlternateInfluencesMapIndex = 0 ; AlternateInfluencesMapIndex < ( * AlternateInfluencesMap ) . Num ( ) ; + + AlternateInfluencesMapIndex )
{
int32 AlternateInfluenceIndex = ( * AlternateInfluencesMap ) [ AlternateInfluencesMapIndex ] ;
if ( ! AlternateInfluences . IsValidIndex ( AlternateInfluenceIndex ) )
{
continue ;
}
DestinationVertexIndexMatched [ VertexIndexDestination ] = true ;
SkeletalMeshImportData : : FRawBoneInfluence AlternateInfluence = AlternateInfluences [ AlternateInfluenceIndex ] ;
uint64 Key = ( ( uint64 ) ( AlternateInfluence . BoneIndex ) < < 32 & 0xFFFFFFFF00000000 ) | ( ( uint64 ) ( VertexIndexDestination ) & 0x00000000FFFFFFFF ) ;
if ( ! InfluenceKeyToInfluenceIndex . Contains ( Key ) )
{
AlternateInfluence . VertexIndex = VertexIndexDestination ;
InfluenceKeyToInfluenceIndex . Add ( Key , AlternateInfluences . Add ( AlternateInfluence ) ) ;
}
else
{
int32 & InfluenceIndex = InfluenceKeyToInfluenceIndex . FindOrAdd ( Key ) ;
SkeletalMeshImportData : : FRawBoneInfluence & ExistAlternateInfluence = AlternateInfluences [ InfluenceIndex ] ;
if ( ExistAlternateInfluence . Weight < AlternateInfluence . Weight )
{
ExistAlternateInfluence . Weight = AlternateInfluence . Weight ;
}
}
}
}
}
}
}
//Sort and normalize weights for alternate influences
2020-10-29 13:38:15 -04:00
ProcessImportMeshInfluences ( ImportDataDest . Wedges . Num ( ) , AlternateInfluences , SkeletalMeshDest - > GetPathName ( ) ) ;
2019-05-09 06:20:31 -04:00
//Store the remapped influence into the profile, the function SkeletalMeshTools::ChunkSkinnedVertices will use all profiles including this one to chunk the sections
FImportedSkinWeightProfileData & ImportedProfileData = LODModelDest . SkinWeightProfiles . Add ( ProfileNameDest ) ;
ImportedProfileData . SourceModelInfluences . Empty ( AlternateInfluences . Num ( ) ) ;
for ( int32 InfluenceIndex = 0 ; InfluenceIndex < AlternateInfluences . Num ( ) ; + + InfluenceIndex )
{
const SkeletalMeshImportData : : FRawBoneInfluence & RawInfluence = AlternateInfluences [ InfluenceIndex ] ;
SkeletalMeshImportData : : FVertInfluence LODAlternateInfluence ;
LODAlternateInfluence . BoneIndex = RawInfluence . BoneIndex ;
LODAlternateInfluence . VertIndex = RawInfluence . VertexIndex ;
LODAlternateInfluence . Weight = RawInfluence . Weight ;
ImportedProfileData . SourceModelInfluences . Add ( LODAlternateInfluence ) ;
}
//
//////////////////////////////////////////////////////////////////////////
2020-04-22 10:41:35 -04:00
bool bBuildSuccess = true ;
2019-05-09 06:20:31 -04:00
//Prepare the build data to rebuild the asset with the alternate influences
//The chunking can be different when we have alternate influences
//Grab the build data from ImportDataDest
2021-05-05 15:07:25 -04:00
TArray < FVector3f > LODPointsDest ;
2019-05-09 06:20:31 -04:00
TArray < SkeletalMeshImportData : : FMeshWedge > LODWedgesDest ;
TArray < SkeletalMeshImportData : : FMeshFace > LODFacesDest ;
TArray < SkeletalMeshImportData : : FVertInfluence > LODInfluencesDest ;
TArray < int32 > LODPointToRawMapDest ;
ImportDataDest . CopyLODImportData ( LODPointsDest , LODWedgesDest , LODFacesDest , LODInfluencesDest , LODPointToRawMapDest ) ;
//Set the options with the current asset build options
IMeshUtilities : : MeshBuildOptions BuildOptions ;
2019-09-10 11:35:20 -04:00
BuildOptions . OverlappingThresholds = OverlappingThresholds ;
BuildOptions . bComputeNormals = ! ShouldImportNormals | | ! ImportDataDest . bHasNormals ;
BuildOptions . bComputeTangents = ! ShouldImportTangents | | ! ImportDataDest . bHasTangents ;
BuildOptions . bUseMikkTSpace = ( bUseMikkTSpace ) & & ( ! ShouldImportNormals | | ! ShouldImportTangents ) ;
BuildOptions . bComputeWeightedNormals = bComputeWeightedNormals ;
2019-05-09 06:20:31 -04:00
BuildOptions . bRemoveDegenerateTriangles = false ;
2021-03-18 15:20:03 -04:00
BuildOptions . TargetPlatform = GetTargetPlatformManagerRef ( ) . GetRunningTargetPlatform ( ) ;
2019-05-09 06:20:31 -04:00
//Build the skeletal mesh asset
IMeshUtilities & MeshUtilities = FModuleManager : : Get ( ) . LoadModuleChecked < IMeshUtilities > ( " MeshUtilities " ) ;
TArray < FText > WarningMessages ;
TArray < FName > WarningNames ;
2020-08-11 01:36:57 -04:00
//BaseLOD need to make sure the source data fit with the skeletalmesh materials array before using meshutilities.BuildSkeletalMesh
2020-11-25 11:17:08 -04:00
AdjustImportDataFaceMaterialIndex ( SkeletalMeshDest - > GetMaterials ( ) , ImportDataDest . Materials , LODFacesDest , LODIndexDest ) ;
2020-08-11 01:36:57 -04:00
2019-05-09 06:20:31 -04:00
//Build the destination mesh with the Alternate influences, so the chunking is done properly.
2020-09-24 00:43:27 -04:00
bBuildSuccess = MeshUtilities . BuildSkeletalMesh ( LODModelDest , SkeletalMeshDest - > GetName ( ) , RefSkeleton , LODInfluencesDest , LODWedgesDest , LODFacesDest , LODPointsDest , LODPointToRawMapDest , BuildOptions , & WarningMessages , & WarningNames ) ;
2019-10-01 20:41:42 -04:00
//Re-Apply the user section changes, the UserSectionsData is map to original section and should match the builded LODModel
LODModelDest . SyncronizeUserSectionsDataArray ( ) ;
2019-05-09 06:20:31 -04:00
RegenerateAllImportSkinWeightProfileData ( LODModelDest ) ;
return bBuildSuccess ;
}
2019-09-10 11:35:20 -04:00
bool FLODUtilities : : UpdateAlternateSkinWeights ( USkeletalMesh * SkeletalMeshDest , const FName & ProfileNameDest , USkeletalMesh * SkeletalMeshSrc , int32 LODIndexDest , int32 LODIndexSrc , FOverlappingThresholds OverlappingThresholds , bool ShouldImportNormals , bool ShouldImportTangents , bool bUseMikkTSpace , bool bComputeWeightedNormals )
{
//Grab all the destination structure
check ( SkeletalMeshDest ) ;
check ( SkeletalMeshDest - > GetImportedModel ( ) ) ;
check ( SkeletalMeshDest - > GetImportedModel ( ) - > LODModels . IsValidIndex ( LODIndexDest ) ) ;
FSkeletalMeshLODModel & LODModelDest = SkeletalMeshDest - > GetImportedModel ( ) - > LODModels [ LODIndexDest ] ;
2019-12-19 18:07:47 -05:00
if ( SkeletalMeshDest - > IsLODImportedDataEmpty ( LODIndexDest ) )
2019-09-10 11:35:20 -04:00
{
UE_LOG ( LogLODUtilities , Error , TEXT ( " Failed to import Skin Weight Profile as the target skeletal mesh (%s) requires reimporting first. " ) , SkeletalMeshDest ? * SkeletalMeshDest - > GetName ( ) : TEXT ( " NULL " ) ) ;
//Very old asset will not have this data, we cannot add alternate until the asset is reimported
return false ;
}
FSkeletalMeshImportData ImportDataDest ;
2019-12-19 18:07:47 -05:00
SkeletalMeshDest - > LoadLODImportedData ( LODIndexDest , ImportDataDest ) ;
2019-09-10 11:35:20 -04:00
int32 PointNumberDest = ImportDataDest . Points . Num ( ) ;
int32 VertexNumberDest = ImportDataDest . Points . Num ( ) ;
//Grab all the source structure
check ( SkeletalMeshSrc ) ;
2019-12-19 18:07:47 -05:00
2019-09-10 11:35:20 -04:00
//The source model is a fresh import and the data need to be there
2019-12-19 18:07:47 -05:00
check ( ! SkeletalMeshSrc - > IsLODImportedDataEmpty ( LODIndexSrc ) ) ;
2019-09-10 11:35:20 -04:00
FSkeletalMeshImportData ImportDataSrc ;
2019-12-19 18:07:47 -05:00
SkeletalMeshSrc - > LoadLODImportedData ( LODIndexSrc , ImportDataSrc ) ;
2019-09-10 11:35:20 -04:00
//Remove all unnecessary array data from the structure (this will save a lot of memory)
ImportDataSrc . KeepAlternateSkinningBuildDataOnly ( ) ;
2020-06-23 18:40:00 -04:00
FString SkeletalMeshDestName = SkeletalMeshDest - > GetName ( ) ;
if ( ImportDataSrc . Points . Num ( ) ! = PointNumberDest )
{
UE_LOG ( LogLODUtilities , Error , TEXT ( " Asset %s failed to import Skin Weight Profile as the incomming alternate influence model vertex number is different. LOD model vertex count: %d Alternate model vertex count: %d " ) , * SkeletalMeshDestName , PointNumberDest , ImportDataSrc . Points . Num ( ) ) ;
return false ;
}
if ( ! ValidateAlternateSkeleton ( ImportDataSrc , ImportDataDest , SkeletalMeshDestName , LODIndexDest ) )
{
//Log are print in the validate function
return false ;
}
2019-09-10 11:35:20 -04:00
//Replace the data into the destination bulk data and save it
int32 ProfileIndex = 0 ;
if ( ImportDataDest . AlternateInfluenceProfileNames . Find ( ProfileNameDest . ToString ( ) , ProfileIndex ) )
{
ImportDataDest . AlternateInfluenceProfileNames . RemoveAt ( ProfileIndex ) ;
ImportDataDest . AlternateInfluences . RemoveAt ( ProfileIndex ) ;
}
ImportDataDest . AlternateInfluenceProfileNames . Add ( ProfileNameDest . ToString ( ) ) ;
ImportDataDest . AlternateInfluences . Add ( ImportDataSrc ) ;
2019-12-19 18:07:47 -05:00
2019-09-10 11:35:20 -04:00
//Resave the bulk data with the new or refreshed data
2019-12-19 18:07:47 -05:00
SkeletalMeshDest - > SaveLODImportedData ( LODIndexDest , ImportDataDest ) ;
2019-09-10 11:35:20 -04:00
2020-04-22 10:41:35 -04:00
if ( ! SkeletalMeshDest - > IsLODImportedDataBuildAvailable ( LODIndexDest ) )
{
//Build the alternate buffer with all the data into the bulk, in case the build data is not existing (old asset)
return UpdateAlternateSkinWeights ( SkeletalMeshDest , ProfileNameDest , LODIndexDest , OverlappingThresholds , ShouldImportNormals , ShouldImportTangents , bUseMikkTSpace , bComputeWeightedNormals ) ;
}
return true ;
2019-09-10 11:35:20 -04:00
}
2022-03-30 14:39:21 -04:00
void FLODUtilities : : GenerateImportedSkinWeightProfileData ( FSkeletalMeshLODModel & LODModelDest , FImportedSkinWeightProfileData & ImportedProfileData )
2019-05-09 06:20:31 -04:00
{
//Add the override buffer with the alternate influence data
TArray < FSoftSkinVertex > DestinationSoftVertices ;
LODModelDest . GetVertices ( DestinationSoftVertices ) ;
//Get the SkinWeights buffer allocated before filling it
TArray < FRawSkinWeight > & SkinWeights = ImportedProfileData . SkinWeights ;
SkinWeights . Empty ( DestinationSoftVertices . Num ( ) ) ;
2020-06-23 18:40:00 -04:00
//Get the maximum allow bone influence, so we can cut lowest weight properly and get the same result has the sk build
const int32 MaxInfluenceCount = FGPUBaseSkinVertexFactory : : UseUnlimitedBoneInfluences ( MAX_TOTAL_INFLUENCES ) ? MAX_TOTAL_INFLUENCES : EXTRA_BONE_INFLUENCES ;
2022-03-30 14:39:21 -04:00
int32 MaxNumInfluences = 0 ;
2020-06-23 18:40:00 -04:00
2019-05-09 06:20:31 -04:00
for ( int32 VertexInstanceIndex = 0 ; VertexInstanceIndex < DestinationSoftVertices . Num ( ) ; + + VertexInstanceIndex )
{
int32 SectionIndex = INDEX_NONE ;
int32 OutVertexIndexGarb = INDEX_NONE ;
LODModelDest . GetSectionFromVertexIndex ( VertexInstanceIndex , SectionIndex , OutVertexIndexGarb ) ;
if ( ! LODModelDest . Sections . IsValidIndex ( SectionIndex ) )
{
continue ;
}
2022-03-30 14:39:21 -04:00
FSkelMeshSection & Section = LODModelDest . Sections [ SectionIndex ] ;
const TArray < FBoneIndexType > SectionBoneMap = Section . BoneMap ;
2019-05-09 06:20:31 -04:00
const FSoftSkinVertex & Vertex = DestinationSoftVertices [ VertexInstanceIndex ] ;
const int32 VertexIndex = LODModelDest . MeshToImportVertexMap [ VertexInstanceIndex ] ;
check ( VertexIndex > = 0 & & VertexIndex < = LODModelDest . MaxImportVertex ) ;
FRawSkinWeight & SkinWeight = SkinWeights . AddDefaulted_GetRef ( ) ;
//Zero out all value
for ( int32 InfluenceIndex = 0 ; InfluenceIndex < MAX_TOTAL_INFLUENCES ; + + InfluenceIndex )
{
SkinWeight . InfluenceBones [ InfluenceIndex ] = 0 ;
SkinWeight . InfluenceWeights [ InfluenceIndex ] = 0 ;
}
2020-06-23 18:40:00 -04:00
2019-05-09 06:20:31 -04:00
TMap < FBoneIndexType , float > WeightForBone ;
for ( const SkeletalMeshImportData : : FVertInfluence & VertInfluence : ImportedProfileData . SourceModelInfluences )
{
if ( VertexIndex = = VertInfluence . VertIndex )
{
//Use the section bone map to remap the bone index
int32 BoneMapIndex = INDEX_NONE ;
SectionBoneMap . Find ( VertInfluence . BoneIndex , BoneMapIndex ) ;
if ( BoneMapIndex = = INDEX_NONE )
{
//Map to root of the section
BoneMapIndex = 0 ;
}
WeightForBone . Add ( BoneMapIndex , VertInfluence . Weight ) ;
}
}
2020-06-23 18:40:00 -04:00
2019-05-09 06:20:31 -04:00
//Add the prepared alternate influences for this skin vertex
uint32 TotalInfluenceWeight = 0 ;
int32 InfluenceBoneIndex = 0 ;
for ( auto Kvp : WeightForBone )
{
2020-01-22 17:58:55 -05:00
SkinWeight . InfluenceBones [ InfluenceBoneIndex ] = Kvp . Key ;
2019-05-09 06:20:31 -04:00
SkinWeight . InfluenceWeights [ InfluenceBoneIndex ] = FMath : : Clamp ( ( uint8 ) ( Kvp . Value * ( ( float ) 0xFF ) ) , ( uint8 ) 0x00 , ( uint8 ) 0xFF ) ;
TotalInfluenceWeight + = SkinWeight . InfluenceWeights [ InfluenceBoneIndex ] ;
InfluenceBoneIndex + + ;
2020-06-23 18:40:00 -04:00
if ( InfluenceBoneIndex > = MaxInfluenceCount )
{
break ;
}
2019-05-09 06:20:31 -04:00
}
2022-03-30 14:39:21 -04:00
//Adjust section influence count if the alternate influence bone count is greater
if ( InfluenceBoneIndex > MaxNumInfluences )
{
MaxNumInfluences = InfluenceBoneIndex ;
if ( MaxNumInfluences > Section . GetMaxBoneInfluences ( ) )
{
Section . MaxBoneInfluences = MaxNumInfluences ;
}
}
2019-05-09 06:20:31 -04:00
//Use the same code has the build where we modify the index 0 to have a sum of 255 for all influence per skin vertex
SkinWeight . InfluenceWeights [ 0 ] + = 255 - TotalInfluenceWeight ;
}
}
void FLODUtilities : : RegenerateAllImportSkinWeightProfileData ( FSkeletalMeshLODModel & LODModelDest )
{
for ( TPair < FName , FImportedSkinWeightProfileData > & ProfilePair : LODModelDest . SkinWeightProfiles )
{
GenerateImportedSkinWeightProfileData ( LODModelDest , ProfilePair . Value ) ;
}
}
2021-03-18 15:20:03 -04:00
void FLODUtilities : : RegenerateDependentLODs ( USkeletalMesh * SkeletalMesh , int32 LODIndex , const ITargetPlatform * TargetPlatform )
2019-05-09 06:20:31 -04:00
{
int32 LODNumber = SkeletalMesh - > GetLODNum ( ) ;
2019-10-14 09:26:02 -04:00
TMap < int32 , TArray < int32 > > Dependencies ;
TBitArray < > DependentLOD ;
DependentLOD . Init ( false , LODNumber ) ;
DependentLOD [ LODIndex ] = true ;
2019-05-09 06:20:31 -04:00
for ( int32 DependentLODIndex = LODIndex + 1 ; DependentLODIndex < LODNumber ; + + DependentLODIndex )
{
const FSkeletalMeshLODInfo * LODInfo = SkeletalMesh - > GetLODInfo ( DependentLODIndex ) ;
2019-10-14 09:26:02 -04:00
//Only add active reduction LOD that are not inline reducted (inline mean they do not depend on LODIndex)
if ( LODInfo & & ( SkeletalMesh - > IsReductionActive ( DependentLODIndex ) | | LODInfo - > bHasBeenSimplified ) & & DependentLODIndex > LODInfo - > ReductionSettings . BaseLOD & & DependentLOD [ LODInfo - > ReductionSettings . BaseLOD ] )
2019-05-09 06:20:31 -04:00
{
2019-10-14 09:26:02 -04:00
TArray < int32 > & LODDependencies = Dependencies . FindOrAdd ( LODInfo - > ReductionSettings . BaseLOD ) ;
LODDependencies . Add ( DependentLODIndex ) ;
DependentLOD [ DependentLODIndex ] = true ;
2019-05-09 06:20:31 -04:00
}
}
2019-10-14 09:26:02 -04:00
if ( Dependencies . Contains ( LODIndex ) )
2019-05-09 06:20:31 -04:00
{
2019-10-14 09:26:02 -04:00
//Load the necessary module before going multithreaded
IMeshReductionModule & ReductionModule = FModuleManager : : Get ( ) . LoadModuleChecked < IMeshReductionModule > ( " MeshReductionInterface " ) ;
//This will load all necessary module before kicking the multi threaded reduction
IMeshReduction * MeshReduction = ReductionModule . GetSkeletalMeshReductionInterface ( ) ;
2021-04-08 14:32:07 -04:00
if ( ! MeshReduction )
{
UE_ASSET_LOG ( LogLODUtilities , Warning , SkeletalMesh , TEXT ( " Cannot reduce skeletalmesh LOD because there is no active reduction plugin. " ) ) ;
return ;
}
check ( MeshReduction - > IsSupported ( ) ) ;
2019-10-14 09:26:02 -04:00
2019-10-01 20:41:42 -04:00
FScopedSkeletalMeshPostEditChange ScopedPostEditChange ( SkeletalMesh ) ;
2021-02-18 11:19:19 -04:00
if ( IsInGameThread ( ) )
2019-05-09 06:20:31 -04:00
{
2019-10-14 09:26:02 -04:00
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " DesiredLOD " ) , LODIndex ) ;
Args . Add ( TEXT ( " SkeletalMeshName " ) , FText : : FromString ( SkeletalMesh - > GetName ( ) ) ) ;
const FText StatusUpdate = FText : : Format ( NSLOCTEXT ( " UnrealEd " , " MeshSimp_GeneratingDependentLODs_F " , " Generating All Dependent LODs from LOD {DesiredLOD} for {SkeletalMeshName}... " ) , Args ) ;
GWarn - > BeginSlowTask ( StatusUpdate , true ) ;
}
2021-02-18 11:19:19 -04:00
2019-10-14 09:26:02 -04:00
for ( const auto & Kvp : Dependencies )
{
2019-12-19 18:07:47 -05:00
int32 MaxDependentLODIndex = 0 ;
2019-10-14 09:26:02 -04:00
//Use a TQueue which is thread safe, this Queue will be fill by some delegate call from other threads
TQueue < FSkeletalMeshLODModel * > LODModelReplaceByReduction ;
const TArray < int32 > & DependentLODs = Kvp . Value ;
//Clothing do not play well with multithread, backup it here. Also bind the LODModel delete delegates
TMap < int32 , TArray < ClothingAssetUtils : : FClothingAssetMeshBinding > > PerLODClothingBindings ;
for ( int32 DependentLODIndex : DependentLODs )
2019-05-09 06:20:31 -04:00
{
2019-12-19 18:07:47 -05:00
MaxDependentLODIndex = FMath : : Max ( MaxDependentLODIndex , DependentLODIndex ) ;
2019-10-14 09:26:02 -04:00
TArray < ClothingAssetUtils : : FClothingAssetMeshBinding > & ClothingBindings = PerLODClothingBindings . FindOrAdd ( DependentLODIndex ) ;
FLODUtilities : : UnbindClothingAndBackup ( SkeletalMesh , ClothingBindings , DependentLODIndex ) ;
const FSkeletalMeshLODInfo * LODInfo = SkeletalMesh - > GetLODInfo ( DependentLODIndex ) ;
check ( LODInfo ) ;
2021-02-18 11:19:19 -04:00
2019-10-14 09:26:02 -04:00
LODInfo - > ReductionSettings . OnDeleteLODModelDelegate . BindLambda ( [ & LODModelReplaceByReduction ] ( FSkeletalMeshLODModel * ReplacedLODModel )
2019-10-01 20:41:42 -04:00
{
2019-10-14 09:26:02 -04:00
LODModelReplaceByReduction . Enqueue ( ReplacedLODModel ) ;
} ) ;
}
2019-12-19 18:07:47 -05:00
SkeletalMesh - > ReserveLODImportData ( MaxDependentLODIndex ) ;
2020-06-23 18:40:00 -04:00
//Reduce all dependent LODs
2020-02-12 12:41:49 -05:00
FThreadSafeBool bNeedsPackageDirtied ( false ) ;
2020-06-23 18:40:00 -04:00
2021-09-21 16:06:32 -04:00
//Adjust the InlineReductionCacheDatas before simplifying dependent LODs
if ( SkeletalMesh - > GetImportedModel ( ) - > InlineReductionCacheDatas . Num ( ) < LODNumber )
{
SkeletalMesh - > GetImportedModel ( ) - > InlineReductionCacheDatas . AddDefaulted ( LODNumber - SkeletalMesh - > GetImportedModel ( ) - > InlineReductionCacheDatas . Num ( ) ) ;
}
else if ( SkeletalMesh - > GetImportedModel ( ) - > InlineReductionCacheDatas . Num ( ) > LODNumber )
{
//If we have too much entry simply shrink the array to valid LODModel size
SkeletalMesh - > GetImportedModel ( ) - > InlineReductionCacheDatas . SetNum ( LODNumber ) ;
}
// Reduce LODs in parallel (reduction is multithread safe)
2021-02-18 11:19:19 -04:00
const bool bHasAccessToLockedProperties = ! FSkeletalMeshAsyncBuildScope : : ShouldWaitOnLockedProperties ( SkeletalMesh ) ;
2021-09-21 16:06:32 -04:00
ParallelFor ( DependentLODs . Num ( ) , [ & DependentLODs , & SkeletalMesh , & bNeedsPackageDirtied , bHasAccessToLockedProperties , & TargetPlatform ] ( int32 IterationIndex )
2019-10-14 09:26:02 -04:00
{
2021-02-18 11:19:19 -04:00
TUniquePtr < FSkeletalMeshAsyncBuildScope > AsyncBuildScope ( bHasAccessToLockedProperties ? MakeUnique < FSkeletalMeshAsyncBuildScope > ( SkeletalMesh ) : nullptr ) ;
2019-10-14 09:26:02 -04:00
check ( DependentLODs . IsValidIndex ( IterationIndex ) ) ;
int32 DependentLODIndex = DependentLODs [ IterationIndex ] ;
2021-09-21 16:06:32 -04:00
check ( SkeletalMesh - > GetLODInfo ( DependentLODIndex ) ) ; //We cannot add a LOD when reducing with multi thread, so check we already have one
FLODUtilities : : SimplifySkeletalMeshLOD ( SkeletalMesh , DependentLODIndex , TargetPlatform , false , & bNeedsPackageDirtied ) ;
2021-12-16 19:57:37 -05:00
} , IsInGameThread ( ) ? EParallelForFlags : : None : EParallelForFlags : : ForceSingleThread ) ;
2019-10-14 09:26:02 -04:00
2021-02-18 11:19:19 -04:00
if ( bNeedsPackageDirtied & & IsInGameThread ( ) )
2020-02-12 12:41:49 -05:00
{
SkeletalMesh - > MarkPackageDirty ( ) ;
}
2019-10-14 09:26:02 -04:00
//Restore the clothings and unbind the delegates
for ( int32 DependentLODIndex : DependentLODs )
{
TArray < ClothingAssetUtils : : FClothingAssetMeshBinding > & ClothingBindings = PerLODClothingBindings . FindChecked ( DependentLODIndex ) ;
FLODUtilities : : RestoreClothingFromBackup ( SkeletalMesh , ClothingBindings ) ;
FSkeletalMeshLODInfo * LODInfo = SkeletalMesh - > GetLODInfo ( DependentLODIndex ) ;
check ( LODInfo ) ;
LODInfo - > ReductionSettings . OnDeleteLODModelDelegate . Unbind ( ) ;
}
while ( ! LODModelReplaceByReduction . IsEmpty ( ) )
{
FSkeletalMeshLODModel * ReplacedLODModel = nullptr ;
LODModelReplaceByReduction . Dequeue ( ReplacedLODModel ) ;
if ( ReplacedLODModel )
{
delete ReplacedLODModel ;
2019-10-01 20:41:42 -04:00
}
2019-05-09 06:20:31 -04:00
}
2019-10-14 09:26:02 -04:00
check ( LODModelReplaceByReduction . IsEmpty ( ) ) ;
}
2019-10-01 20:41:42 -04:00
2021-02-18 11:19:19 -04:00
if ( IsInGameThread ( ) )
{
GWarn - > EndSlowTask ( ) ;
}
2019-05-09 06:20:31 -04:00
}
}
2019-09-10 11:35:20 -04:00
//////////////////////////////////////////////////////////////////////////
// Morph targets build code
//
struct FMeshDataBundle
2019-05-09 06:20:31 -04:00
{
2021-05-05 15:07:25 -04:00
TArray < FVector3f > Vertices ;
2019-09-10 11:35:20 -04:00
TArray < uint32 > Indices ;
2021-11-18 14:37:34 -05:00
TArray < FVector2f > UVs ;
2019-09-10 11:35:20 -04:00
TArray < uint32 > SmoothingGroups ;
TArray < SkeletalMeshImportData : : FTriangle > Faces ;
} ;
2019-05-09 06:20:31 -04:00
2019-09-10 11:35:20 -04:00
static void ConvertImportDataToMeshData ( const FSkeletalMeshImportData & ImportData , FMeshDataBundle & MeshDataBundle )
{
for ( const SkeletalMeshImportData : : FTriangle & Face : ImportData . Faces )
2019-05-09 06:20:31 -04:00
{
2019-09-10 11:35:20 -04:00
SkeletalMeshImportData : : FTriangle FaceTriangle ;
FaceTriangle = Face ;
for ( int32 i = 0 ; i < 3 ; + + i )
{
const SkeletalMeshImportData : : FVertex & Wedge = ImportData . Wedges [ Face . WedgeIndex [ i ] ] ;
int32 FaceWedgeIndex = MeshDataBundle . Indices . Add ( Wedge . VertexIndex ) ;
MeshDataBundle . UVs . Add ( Wedge . UVs [ 0 ] ) ;
FaceTriangle . WedgeIndex [ i ] = FaceWedgeIndex ;
}
MeshDataBundle . Faces . Add ( FaceTriangle ) ;
MeshDataBundle . SmoothingGroups . Add ( Face . SmoothingGroups ) ;
2019-05-09 06:20:31 -04:00
}
2019-09-10 11:35:20 -04:00
MeshDataBundle . Vertices = ImportData . Points ;
}
/**
* A class encapsulating morph target processing that occurs during import on a separate thread
*/
class FAsyncImportMorphTargetWork : public FNonAbandonableTask
{
public :
2021-05-05 15:07:25 -04:00
FAsyncImportMorphTargetWork ( FSkeletalMeshLODModel * InLODModel , const FReferenceSkeleton & InRefSkeleton , const FSkeletalMeshImportData & InBaseImportData , TArray < FVector3f > & & InMorphLODPoints ,
2022-01-10 08:51:57 -05:00
TArray < FMorphTargetDelta > & InMorphDeltas , TArray < uint32 > & InBaseIndexData , const TArray < uint32 > & InBaseWedgePointIndices ,
2019-09-10 11:35:20 -04:00
TMap < uint32 , uint32 > & InWedgePointToVertexIndexMap , const FOverlappingCorners & InOverlappingCorners ,
2021-05-05 15:07:25 -04:00
const TSet < uint32 > InModifiedPoints , const TMultiMap < int32 , int32 > & InWedgeToFaces , const FMeshDataBundle & InMeshDataBundle , const TArray < FVector3f > & InTangentZ ,
2019-12-19 18:07:47 -05:00
bool InShouldImportNormals , bool InShouldImportTangents , bool InbUseMikkTSpace , const FOverlappingThresholds InThresholds )
2019-09-10 11:35:20 -04:00
: LODModel ( InLODModel )
, RefSkeleton ( InRefSkeleton )
, BaseImportData ( InBaseImportData )
2020-01-29 18:50:10 -05:00
, CompressMorphLODPoints ( InMorphLODPoints )
2019-09-10 11:35:20 -04:00
, MorphTargetDeltas ( InMorphDeltas )
, BaseIndexData ( InBaseIndexData )
, BaseWedgePointIndices ( InBaseWedgePointIndices )
, WedgePointToVertexIndexMap ( InWedgePointToVertexIndexMap )
, OverlappingCorners ( InOverlappingCorners )
, ModifiedPoints ( InModifiedPoints )
, WedgeToFaces ( InWedgeToFaces )
, MeshDataBundle ( InMeshDataBundle )
, BaseTangentZ ( InTangentZ )
, TangentZ ( InTangentZ )
, ShouldImportNormals ( InShouldImportNormals )
, ShouldImportTangents ( InShouldImportTangents )
, bUseMikkTSpace ( InbUseMikkTSpace )
2019-12-19 18:07:47 -05:00
, Thresholds ( InThresholds )
2019-05-09 06:20:31 -04:00
{
2019-09-10 11:35:20 -04:00
MeshUtilities = & FModuleManager : : Get ( ) . LoadModuleChecked < IMeshUtilities > ( " MeshUtilities " ) ;
}
2020-01-29 18:50:10 -05:00
//Decompress the shape points data
void DecompressData ( )
{
2021-05-05 15:07:25 -04:00
const TArray < FVector3f > & BaseMeshPoints = BaseImportData . Points ;
2020-01-29 18:50:10 -05:00
MorphLODPoints = BaseMeshPoints ;
int32 ModifiedPointIndex = 0 ;
for ( uint32 PointIndex : ModifiedPoints )
{
MorphLODPoints [ PointIndex ] = CompressMorphLODPoints [ ModifiedPointIndex ] ;
ModifiedPointIndex + + ;
}
check ( MorphLODPoints . Num ( ) = = MeshDataBundle . Vertices . Num ( ) ) ;
}
2019-09-10 11:35:20 -04:00
void PrepareTangents ( )
{
TArray < bool > WasProcessed ;
WasProcessed . Empty ( MeshDataBundle . Indices . Num ( ) ) ;
WasProcessed . AddZeroed ( MeshDataBundle . Indices . Num ( ) ) ;
TArray < int32 > WedgeFaces ;
2021-08-02 08:48:58 -04:00
TArray < int32 > OtherWedgeFaces ;
2019-09-10 11:35:20 -04:00
TArray < int32 > OverlappingWedgesDummy ;
TArray < int32 > OtherOverlappingWedgesDummy ;
// For each ModifiedPoints, reset the tangents for the affected wedges
for ( int32 WedgeIdx = 0 ; WedgeIdx < MeshDataBundle . Indices . Num ( ) ; + + WedgeIdx )
2019-05-09 06:20:31 -04:00
{
2019-09-10 11:35:20 -04:00
int32 PointIdx = MeshDataBundle . Indices [ WedgeIdx ] ;
if ( ModifiedPoints . Find ( PointIdx ) ! = nullptr )
{
2022-02-02 07:59:31 -05:00
TangentZ [ WedgeIdx ] = FVector3f : : ZeroVector ;
2019-09-10 11:35:20 -04:00
const TArray < int32 > & OverlappingWedges = FindIncludingNoOverlapping ( OverlappingCorners , WedgeIdx , OverlappingWedgesDummy ) ;
for ( const int32 OverlappingWedgeIndex : OverlappingWedges )
{
if ( WasProcessed [ OverlappingWedgeIndex ] )
{
continue ;
}
WasProcessed [ OverlappingWedgeIndex ] = true ;
WedgeFaces . Reset ( ) ;
WedgeToFaces . MultiFind ( OverlappingWedgeIndex , WedgeFaces ) ;
for ( const int32 FaceIndex : WedgeFaces )
{
for ( int32 CornerIndex = 0 ; CornerIndex < 3 ; + + CornerIndex )
{
int32 WedgeIndex = MeshDataBundle . Faces [ FaceIndex ] . WedgeIndex [ CornerIndex ] ;
2022-02-02 07:59:31 -05:00
TangentZ [ WedgeIndex ] = FVector3f : : ZeroVector ;
2019-09-10 11:35:20 -04:00
const TArray < int32 > & OtherOverlappingWedges = FindIncludingNoOverlapping ( OverlappingCorners , WedgeIndex , OtherOverlappingWedgesDummy ) ;
for ( const int32 OtherDupVert : OtherOverlappingWedges )
{
2021-08-02 08:48:58 -04:00
OtherWedgeFaces . Reset ( ) ;
2019-09-10 11:35:20 -04:00
WedgeToFaces . MultiFind ( OtherDupVert , OtherWedgeFaces ) ;
for ( const int32 OtherFaceIndex : OtherWedgeFaces )
{
for ( int32 OtherCornerIndex = 0 ; OtherCornerIndex < 3 ; + + OtherCornerIndex )
{
int32 OtherWedgeIndex = MeshDataBundle . Faces [ OtherFaceIndex ] . WedgeIndex [ OtherCornerIndex ] ;
2022-02-02 07:59:31 -05:00
TangentZ [ OtherWedgeIndex ] = FVector3f : : ZeroVector ;
2019-09-10 11:35:20 -04:00
}
}
}
}
}
}
}
}
}
void ComputeTangents ( )
{
bool bComputeNormals = ! ShouldImportNormals | | ! BaseImportData . bHasNormals ;
bool bComputeTangents = ! ShouldImportTangents | | ! BaseImportData . bHasTangents ;
bool bUseMikkTSpaceFinal = bUseMikkTSpace & & ( ! ShouldImportNormals | | ! ShouldImportTangents ) ;
check ( MorphLODPoints . Num ( ) = = MeshDataBundle . Vertices . Num ( ) ) ;
ETangentOptions : : Type TangentOptions = ETangentOptions : : BlendOverlappingNormals ;
// MikkTSpace should be use only when the user want to recompute the normals or tangents otherwise should always fallback on builtin
if ( bUseMikkTSpaceFinal & & ( bComputeNormals | | bComputeTangents ) )
{
TangentOptions = ( ETangentOptions : : Type ) ( TangentOptions | ETangentOptions : : UseMikkTSpace ) ;
}
MeshUtilities - > CalculateNormals ( MorphLODPoints , MeshDataBundle . Indices , MeshDataBundle . UVs , MeshDataBundle . SmoothingGroups , TangentOptions , TangentZ ) ;
}
void ComputeMorphDeltas ( )
{
TArray < bool > WasProcessed ;
WasProcessed . Empty ( LODModel - > NumVertices ) ;
WasProcessed . AddZeroed ( LODModel - > NumVertices ) ;
for ( int32 Idx = 0 ; Idx < BaseIndexData . Num ( ) ; + + Idx )
{
uint32 BaseVertIdx = BaseIndexData [ Idx ] ;
// check for duplicate processing
if ( ! WasProcessed [ BaseVertIdx ] )
{
// mark this base vertex as already processed
WasProcessed [ BaseVertIdx ] = true ;
// clothing can add extra verts, and we won't have source point, so we ignore those
if ( BaseWedgePointIndices . IsValidIndex ( BaseVertIdx ) )
{
// get the base mesh's original wedge point index
uint32 BasePointIdx = BaseWedgePointIndices [ BaseVertIdx ] ;
if ( MeshDataBundle . Vertices . IsValidIndex ( BasePointIdx ) & & MorphLODPoints . IsValidIndex ( BasePointIdx ) )
{
2022-02-02 07:59:31 -05:00
FVector BasePosition = ( FVector ) MeshDataBundle . Vertices [ BasePointIdx ] ;
FVector TargetPosition = ( FVector ) MorphLODPoints [ BasePointIdx ] ;
2019-09-10 11:35:20 -04:00
FVector PositionDelta = TargetPosition - BasePosition ;
uint32 * VertexIdx = WedgePointToVertexIndexMap . Find ( BasePointIdx ) ;
FVector NormalDeltaZ = FVector : : ZeroVector ;
if ( VertexIdx ! = nullptr )
{
2022-02-02 07:59:31 -05:00
FVector BaseNormal = ( FVector ) BaseTangentZ [ * VertexIdx ] ;
FVector TargetNormal = ( FVector ) TangentZ [ * VertexIdx ] ;
2019-09-10 11:35:20 -04:00
NormalDeltaZ = TargetNormal - BaseNormal ;
}
// check if position actually changed much
2019-12-19 18:07:47 -05:00
if ( PositionDelta . SizeSquared ( ) > FMath : : Square ( Thresholds . MorphThresholdPosition ) | |
2019-09-10 11:35:20 -04:00
// since we can't get imported morphtarget normal from FBX
// we can't compare normal unless it's calculated
// this is special flag to ignore normal diff
( ( ShouldImportNormals = = false ) & & NormalDeltaZ . SizeSquared ( ) > 0.01f ) )
{
// create a new entry
FMorphTargetDelta NewVertex ;
// position delta
2022-02-02 07:59:31 -05:00
NewVertex . PositionDelta = ( FVector3f ) PositionDelta ;
2019-09-10 11:35:20 -04:00
// normal delta
2022-02-02 07:59:31 -05:00
NewVertex . TangentZDelta = ( FVector3f ) NormalDeltaZ ;
2019-09-10 11:35:20 -04:00
// index of base mesh vert this entry is to modify
NewVertex . SourceIdx = BaseVertIdx ;
// add it to the list of changed verts
MorphTargetDeltas . Add ( NewVertex ) ;
}
}
}
}
}
}
void DoWork ( )
{
2020-01-29 18:50:10 -05:00
DecompressData ( ) ;
2019-09-10 11:35:20 -04:00
PrepareTangents ( ) ;
ComputeTangents ( ) ;
ComputeMorphDeltas ( ) ;
}
FORCEINLINE TStatId GetStatId ( ) const
{
RETURN_QUICK_DECLARE_CYCLE_STAT ( FAsyncImportMorphTargetWork , STATGROUP_ThreadPoolAsyncTasks ) ;
}
private :
const TArray < int32 > & FindIncludingNoOverlapping ( const FOverlappingCorners & Corners , int32 Key , TArray < int32 > & NoOverlapping )
{
const TArray < int32 > & Found = Corners . FindIfOverlapping ( Key ) ;
if ( Found . Num ( ) > 0 )
{
return Found ;
2019-05-09 06:20:31 -04:00
}
else
{
2019-09-10 11:35:20 -04:00
NoOverlapping . Reset ( 1 ) ;
NoOverlapping . Add ( Key ) ;
return NoOverlapping ;
2019-05-09 06:20:31 -04:00
}
}
2019-09-10 11:35:20 -04:00
FSkeletalMeshLODModel * LODModel ;
// @todo not thread safe
const FReferenceSkeleton & RefSkeleton ;
const FSkeletalMeshImportData & BaseImportData ;
2021-05-05 15:07:25 -04:00
const TArray < FVector3f > CompressMorphLODPoints ;
TArray < FVector3f > MorphLODPoints ;
2019-09-10 11:35:20 -04:00
IMeshUtilities * MeshUtilities ;
TArray < FMorphTargetDelta > & MorphTargetDeltas ;
TArray < uint32 > & BaseIndexData ;
2022-01-10 08:51:57 -05:00
const TArray < uint32 > & BaseWedgePointIndices ;
2019-09-10 11:35:20 -04:00
TMap < uint32 , uint32 > & WedgePointToVertexIndexMap ;
const FOverlappingCorners & OverlappingCorners ;
const TSet < uint32 > ModifiedPoints ;
const TMultiMap < int32 , int32 > & WedgeToFaces ;
const FMeshDataBundle & MeshDataBundle ;
2021-05-05 15:07:25 -04:00
const TArray < FVector3f > & BaseTangentZ ;
TArray < FVector3f > TangentZ ;
2019-09-10 11:35:20 -04:00
bool ShouldImportNormals ;
bool ShouldImportTangents ;
bool bUseMikkTSpace ;
2019-12-19 18:07:47 -05:00
const FOverlappingThresholds Thresholds ;
2019-09-10 11:35:20 -04:00
} ;
2019-12-19 18:07:47 -05:00
void FLODUtilities : : BuildMorphTargets ( USkeletalMesh * BaseSkelMesh , FSkeletalMeshImportData & BaseImportData , int32 LODIndex , bool ShouldImportNormals , bool ShouldImportTangents , bool bUseMikkTSpace , const FOverlappingThresholds & Thresholds )
2019-09-10 11:35:20 -04:00
{
bool bComputeNormals = ! ShouldImportNormals | | ! BaseImportData . bHasNormals ;
bool bComputeTangents = ! ShouldImportTangents | | ! BaseImportData . bHasTangents ;
bool bUseMikkTSpaceFinal = bUseMikkTSpace & & ( ! ShouldImportNormals | | ! ShouldImportTangents ) ;
// Prepare base data
FSkeletalMeshLODModel & BaseLODModel = BaseSkelMesh - > GetImportedModel ( ) - > LODModels [ LODIndex ] ;
FMeshDataBundle MeshDataBundle ;
ConvertImportDataToMeshData ( BaseImportData , MeshDataBundle ) ;
IMeshUtilities & MeshUtilities = FModuleManager : : Get ( ) . LoadModuleChecked < IMeshUtilities > ( " MeshUtilities " ) ;
ETangentOptions : : Type TangentOptions = ETangentOptions : : BlendOverlappingNormals ;
// MikkTSpace should be use only when the user want to recompute the normals or tangents otherwise should always fallback on builtin
if ( bUseMikkTSpaceFinal & & ( bComputeNormals | | bComputeTangents ) )
{
TangentOptions = ( ETangentOptions : : Type ) ( TangentOptions | ETangentOptions : : UseMikkTSpace ) ;
}
FOverlappingCorners OverlappingVertices ;
MeshUtilities . CalculateOverlappingCorners ( MeshDataBundle . Vertices , MeshDataBundle . Indices , false , OverlappingVertices ) ;
2021-05-05 15:07:25 -04:00
TArray < FVector3f > TangentZ ;
2019-09-10 11:35:20 -04:00
MeshUtilities . CalculateNormals ( MeshDataBundle . Vertices , MeshDataBundle . Indices , MeshDataBundle . UVs , MeshDataBundle . SmoothingGroups , TangentOptions , TangentZ ) ;
TArray < uint32 > BaseIndexData = BaseLODModel . IndexBuffer ;
TMap < uint32 , uint32 > WedgePointToVertexIndexMap ;
// Build a mapping of wedge point indices to vertex indices for fast lookup later.
for ( int32 Idx = 0 ; Idx < MeshDataBundle . Indices . Num ( ) ; + + Idx )
{
WedgePointToVertexIndexMap . Add ( MeshDataBundle . Indices [ Idx ] , Idx ) ;
}
// Create a map from wedge indices to faces
TMultiMap < int32 , int32 > WedgeToFaces ;
for ( int32 FaceIndex = 0 ; FaceIndex < MeshDataBundle . Faces . Num ( ) ; FaceIndex + + )
{
const SkeletalMeshImportData : : FTriangle & Face = MeshDataBundle . Faces [ FaceIndex ] ;
for ( int32 CornerIndex = 0 ; CornerIndex < 3 ; + + CornerIndex )
{
WedgeToFaces . AddUnique ( Face . WedgeIndex [ CornerIndex ] , FaceIndex ) ;
}
}
// Temp arrays to keep track of data being used by threads
TArray < TArray < FMorphTargetDelta > * > Results ;
TArray < UMorphTarget * > MorphTargets ;
// Array of pending tasks that are not complete
TIndirectArray < FAsyncTask < FAsyncImportMorphTargetWork > > PendingWork ;
int32 NumCompleted = 0 ;
int32 NumTasks = 0 ;
int32 MaxShapeInProcess = FPlatformMisc : : NumberOfCoresIncludingHyperthreads ( ) ;
int32 ShapeIndex = 0 ;
int32 TotalShapeCount = BaseImportData . MorphTargetNames . Num ( ) ;
2021-02-18 11:19:19 -04:00
TMap < FName , UMorphTarget * > ExistingMorphTargets ;
for ( UMorphTarget * MorphTarget : BaseSkelMesh - > GetMorphTargets ( ) )
{
ExistingMorphTargets . Add ( MorphTarget - > GetFName ( ) , MorphTarget ) ;
}
2019-09-10 11:35:20 -04:00
// iterate through shapename, and create morphtarget
for ( int32 MorphTargetIndex = 0 ; MorphTargetIndex < BaseImportData . MorphTargetNames . Num ( ) ; + + MorphTargetIndex )
{
int32 CurrentNumTasks = PendingWork . Num ( ) ;
while ( CurrentNumTasks > = MaxShapeInProcess )
{
//Wait until the first slot is available
PendingWork [ 0 ] . EnsureCompletion ( ) ;
for ( int32 TaskIndex = PendingWork . Num ( ) - 1 ; TaskIndex > = 0 ; - - TaskIndex )
{
if ( PendingWork [ TaskIndex ] . IsDone ( ) )
{
PendingWork . RemoveAt ( TaskIndex ) ;
+ + NumCompleted ;
2021-02-18 11:19:19 -04:00
if ( IsInGameThread ( ) )
{
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " NumCompleted " ) , NumCompleted ) ;
Args . Add ( TEXT ( " NumTasks " ) , TotalShapeCount ) ;
GWarn - > StatusUpdate ( NumCompleted , TotalShapeCount , FText : : Format ( LOCTEXT ( " ImportingMorphTargetStatus " , " Importing Morph Target: {NumCompleted} of {NumTasks} " ) , Args ) ) ;
}
2019-09-10 11:35:20 -04:00
}
}
CurrentNumTasks = PendingWork . Num ( ) ;
}
check ( BaseImportData . MorphTargetNames . IsValidIndex ( MorphTargetIndex ) ) ;
check ( BaseImportData . MorphTargetModifiedPoints . IsValidIndex ( MorphTargetIndex ) ) ;
check ( BaseImportData . MorphTargets . IsValidIndex ( MorphTargetIndex ) ) ;
FString & ShapeName = BaseImportData . MorphTargetNames [ MorphTargetIndex ] ;
FSkeletalMeshImportData & ShapeImportData = BaseImportData . MorphTargets [ MorphTargetIndex ] ;
TSet < uint32 > & ModifiedPoints = BaseImportData . MorphTargetModifiedPoints [ MorphTargetIndex ] ;
2021-03-15 15:52:42 -04:00
bool bNeedToClearAsyncFlag = false ;
2021-02-18 11:19:19 -04:00
UMorphTarget * MorphTarget = nullptr ;
2019-09-10 11:35:20 -04:00
{
2021-02-18 11:19:19 -04:00
FName ObjectName = * ShapeName ;
MorphTarget = ExistingMorphTargets . FindRef ( ObjectName ) ;
// we only create new one for LOD0, otherwise don't create new one
if ( ! MorphTarget )
2019-09-10 11:35:20 -04:00
{
2021-02-18 11:19:19 -04:00
if ( LODIndex = = 0 )
{
2021-03-15 15:52:42 -04:00
if ( ! IsInGameThread ( ) )
{
//TODO remove this code when overriding a UObject will be allow outside of the game thread
//We currently need to avoid overriding an existing asset outside of the game thread
UObject * ExistingMorphTarget = StaticFindObject ( UMorphTarget : : StaticClass ( ) , BaseSkelMesh , * ShapeName ) ;
if ( ExistingMorphTarget )
{
//make sure the object is not standalone or transactional
ExistingMorphTarget - > ClearFlags ( RF_Standalone | RF_Transactional ) ;
//Move this object in the transient package
ExistingMorphTarget - > Rename ( nullptr , GetTransientPackage ( ) , REN_ForceNoResetLoaders | REN_DoNotDirty | REN_DontCreateRedirectors | REN_NonTransactional ) ;
ExistingMorphTarget = nullptr ;
}
bNeedToClearAsyncFlag = true ;
}
2021-03-09 09:40:13 -04:00
FGCScopeGuard GCScopeGuard ;
2021-02-18 11:19:19 -04:00
MorphTarget = NewObject < UMorphTarget > ( BaseSkelMesh , ObjectName ) ;
}
else
{
/*AddTokenizedErrorMessage(FTokenizedMessage::Create(EMessageSeverity::Error, FText::Format(FText::FromString("Could not find the {0} morphtarget for LOD {1}. \
Make sure the name for morphtarget matches with LOD 0 " ), FText::FromString(ShapeName), FText::FromString(FString::FromInt(LODIndex)))),
FFbxErrors : : SkeletalMesh_LOD_MissingMorphTarget ) ; */
}
2019-09-10 11:35:20 -04:00
}
}
if ( MorphTarget )
{
MorphTargets . Add ( MorphTarget ) ;
int32 NewMorphDeltasIdx = Results . Add ( new TArray < FMorphTargetDelta > ( ) ) ;
TArray < FMorphTargetDelta > * Deltas = Results [ NewMorphDeltasIdx ] ;
2020-11-25 11:17:08 -04:00
FAsyncTask < FAsyncImportMorphTargetWork > * NewWork = new FAsyncTask < FAsyncImportMorphTargetWork > ( & BaseLODModel , BaseSkelMesh - > GetRefSkeleton ( ) , BaseImportData ,
2022-01-10 08:51:57 -05:00
MoveTemp ( ShapeImportData . Points ) , * Deltas , BaseIndexData , BaseLODModel . GetRawPointIndices ( ) , WedgePointToVertexIndexMap , OverlappingVertices , MoveTemp ( ModifiedPoints ) , WedgeToFaces , MeshDataBundle , TangentZ ,
2019-12-19 18:07:47 -05:00
ShouldImportNormals , ShouldImportTangents , bUseMikkTSpace , Thresholds ) ;
2019-09-10 11:35:20 -04:00
PendingWork . Add ( NewWork ) ;
NewWork - > StartBackgroundTask ( GLargeThreadPool ) ;
CurrentNumTasks + + ;
NumTasks + + ;
2021-03-15 15:52:42 -04:00
if ( bNeedToClearAsyncFlag )
{
const EInternalObjectFlags AsyncFlags = EInternalObjectFlags : : Async | EInternalObjectFlags : : AsyncLoading ;
MorphTarget - > ClearInternalFlags ( AsyncFlags ) ;
}
2019-09-10 11:35:20 -04:00
}
+ + ShapeIndex ;
}
// Wait for all importing tasks to complete
for ( int32 TaskIndex = 0 ; TaskIndex < PendingWork . Num ( ) ; + + TaskIndex )
{
PendingWork [ TaskIndex ] . EnsureCompletion ( ) ;
+ + NumCompleted ;
2021-02-18 11:19:19 -04:00
if ( IsInGameThread ( ) )
{
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " NumCompleted " ) , NumCompleted ) ;
Args . Add ( TEXT ( " NumTasks " ) , TotalShapeCount ) ;
GWarn - > StatusUpdate ( NumCompleted , NumTasks , FText : : Format ( LOCTEXT ( " ImportingMorphTargetStatus " , " Importing Morph Target: {NumCompleted} of {NumTasks} " ) , Args ) ) ;
}
2019-09-10 11:35:20 -04:00
}
bool bNeedToInvalidateRegisteredMorph = false ;
// Create morph streams for each morph target we are importing.
// This has to happen on a single thread since the skeletal meshes' bulk data is locked and cant be accessed by multiple threads simultaneously
for ( int32 Index = 0 ; Index < MorphTargets . Num ( ) ; Index + + )
{
2021-02-18 11:19:19 -04:00
if ( IsInGameThread ( ) )
{
FFormatNamedArguments Args ;
Args . Add ( TEXT ( " NumCompleted " ) , Index + 1 ) ;
Args . Add ( TEXT ( " NumTasks " ) , MorphTargets . Num ( ) ) ;
GWarn - > StatusUpdate ( Index + 1 , MorphTargets . Num ( ) , FText : : Format ( LOCTEXT ( " BuildingMorphTargetRenderDataStatus " , " Building Morph Target Render Data: {NumCompleted} of {NumTasks} " ) , Args ) ) ;
}
2019-09-10 11:35:20 -04:00
UMorphTarget * MorphTarget = MorphTargets [ Index ] ;
2019-12-19 18:07:47 -05:00
MorphTarget - > PopulateDeltas ( * Results [ Index ] , LODIndex , BaseLODModel . Sections , ShouldImportNormals = = false , false , Thresholds . MorphThresholdPosition ) ;
2019-09-10 11:35:20 -04:00
// register does mark package as dirty
if ( MorphTarget - > HasValidData ( ) )
{
bNeedToInvalidateRegisteredMorph | = BaseSkelMesh - > RegisterMorphTarget ( MorphTarget , false ) ;
}
delete Results [ Index ] ;
Results [ Index ] = nullptr ;
2021-02-18 11:19:19 -04:00
// We might have created new MorphTarget in an async thread, so we need to remove the async flag so they can get
// garbage collected in the future now that their references are properly setup and reachable by the GC.
MorphTarget - > ClearInternalFlags ( EInternalObjectFlags : : Async ) ;
2019-09-10 11:35:20 -04:00
}
if ( bNeedToInvalidateRegisteredMorph )
{
BaseSkelMesh - > InitMorphTargetsAndRebuildRenderData ( ) ;
}
2019-07-12 00:17:17 -04:00
}
2019-10-01 20:41:42 -04:00
void FLODUtilities : : UnbindClothingAndBackup ( USkeletalMesh * SkeletalMesh , TArray < ClothingAssetUtils : : FClothingAssetMeshBinding > & ClothingBindings )
{
for ( int32 LODIndex = 0 ; LODIndex < SkeletalMesh - > GetImportedModel ( ) - > LODModels . Num ( ) ; + + LODIndex )
{
TArray < ClothingAssetUtils : : FClothingAssetMeshBinding > LODBindings ;
UnbindClothingAndBackup ( SkeletalMesh , LODBindings , LODIndex ) ;
ClothingBindings . Append ( LODBindings ) ;
}
}
void FLODUtilities : : UnbindClothingAndBackup ( USkeletalMesh * SkeletalMesh , TArray < ClothingAssetUtils : : FClothingAssetMeshBinding > & ClothingBindings , const int32 LODIndex )
{
if ( ! SkeletalMesh - > GetImportedModel ( ) - > LODModels . IsValidIndex ( LODIndex ) )
{
return ;
}
FSkeletalMeshLODModel & LODModel = SkeletalMesh - > GetImportedModel ( ) - > LODModels [ LODIndex ] ;
//Store the clothBinding
2021-12-10 17:48:54 -05:00
ClothingAssetUtils : : GetAllLodMeshClothingAssetBindings ( SkeletalMesh , ClothingBindings , LODIndex ) ;
2019-10-01 20:41:42 -04:00
//Unbind the Cloth for this LOD before we reduce it, we will put back the cloth after the reduction, if it still match the sections
for ( ClothingAssetUtils : : FClothingAssetMeshBinding & Binding : ClothingBindings )
{
if ( Binding . LODIndex = = LODIndex )
{
//Use the UserSectionsData original section index, this will ensure we remap correctly the cloth if the reduction has change the number of sections
int32 OriginalDataSectionIndex = LODModel . Sections [ Binding . SectionIndex ] . OriginalDataSectionIndex ;
2020-01-21 18:07:45 -05:00
if ( Binding . Asset )
{
Binding . Asset - > UnbindFromSkeletalMesh ( SkeletalMesh , Binding . LODIndex ) ;
Binding . SectionIndex = OriginalDataSectionIndex ;
}
2019-10-01 20:41:42 -04:00
FSkelMeshSourceSectionUserData & SectionUserData = LODModel . UserSectionsData . FindChecked ( OriginalDataSectionIndex ) ;
SectionUserData . ClothingData . AssetGuid = FGuid ( ) ;
SectionUserData . ClothingData . AssetLodIndex = INDEX_NONE ;
SectionUserData . CorrespondClothAssetIndex = INDEX_NONE ;
}
}
}
void FLODUtilities : : RestoreClothingFromBackup ( USkeletalMesh * SkeletalMesh , TArray < ClothingAssetUtils : : FClothingAssetMeshBinding > & ClothingBindings )
{
for ( int32 LODIndex = 0 ; LODIndex < SkeletalMesh - > GetImportedModel ( ) - > LODModels . Num ( ) ; + + LODIndex )
{
RestoreClothingFromBackup ( SkeletalMesh , ClothingBindings , LODIndex ) ;
}
}
void FLODUtilities : : RestoreClothingFromBackup ( USkeletalMesh * SkeletalMesh , TArray < ClothingAssetUtils : : FClothingAssetMeshBinding > & ClothingBindings , const int32 LODIndex )
{
if ( ! SkeletalMesh - > GetImportedModel ( ) - > LODModels . IsValidIndex ( LODIndex ) )
{
return ;
}
FSkeletalMeshLODModel & LODModel = SkeletalMesh - > GetImportedModel ( ) - > LODModels [ LODIndex ] ;
for ( ClothingAssetUtils : : FClothingAssetMeshBinding & Binding : ClothingBindings )
{
for ( int32 SectionIndex = 0 ; SectionIndex < LODModel . Sections . Num ( ) ; + + SectionIndex )
{
if ( LODModel . Sections [ SectionIndex ] . OriginalDataSectionIndex ! = Binding . SectionIndex )
{
continue ;
}
2020-01-21 18:07:45 -05:00
if ( Binding . LODIndex = = LODIndex & & Binding . Asset )
2019-10-01 20:41:42 -04:00
{
if ( Binding . Asset - > BindToSkeletalMesh ( SkeletalMesh , Binding . LODIndex , SectionIndex , Binding . AssetInternalLodIndex ) )
{
//If successfull set back the section user data
FSkelMeshSourceSectionUserData & SectionUserData = LODModel . UserSectionsData . FindChecked ( Binding . SectionIndex ) ;
SectionUserData . CorrespondClothAssetIndex = LODModel . Sections [ SectionIndex ] . CorrespondClothAssetIndex ;
SectionUserData . ClothingData = LODModel . Sections [ SectionIndex ] . ClothingData ;
}
}
break ;
}
}
}
2020-08-11 01:36:57 -04:00
void FLODUtilities : : AdjustImportDataFaceMaterialIndex ( const TArray < FSkeletalMaterial > & Materials , TArray < SkeletalMeshImportData : : FMaterial > & RawMeshMaterials , TArray < SkeletalMeshImportData : : FMeshFace > & LODFaces , int32 LODIndex )
{
if ( ( Materials . Num ( ) < = 1 & & RawMeshMaterials . Num ( ) < = 1 ) | | LODIndex ! = 0 )
{
//Nothing to fix if we have 1 or less material or we are not adjusting the base LOD
return ;
}
//Fix the material for the faces
TArray < int32 > MaterialRemap ;
MaterialRemap . Reserve ( RawMeshMaterials . Num ( ) ) ;
//Optimization to avoid doing the remap if no material have to change
bool bNeedRemapping = false ;
for ( int32 MaterialIndex = 0 ; MaterialIndex < RawMeshMaterials . Num ( ) ; + + MaterialIndex )
{
MaterialRemap . Add ( MaterialIndex ) ;
FName MaterialImportName = * ( RawMeshMaterials [ MaterialIndex ] . MaterialImportName ) ;
for ( int32 MeshMaterialIndex = 0 ; MeshMaterialIndex < Materials . Num ( ) ; + + MeshMaterialIndex )
{
FName MeshMaterialName = Materials [ MeshMaterialIndex ] . ImportedMaterialSlotName ;
if ( MaterialImportName = = MeshMaterialName )
{
bNeedRemapping | = ( MaterialRemap [ MaterialIndex ] ! = MeshMaterialIndex ) ;
MaterialRemap [ MaterialIndex ] = MeshMaterialIndex ;
break ;
}
}
}
if ( bNeedRemapping )
{
//Make sure the data is good before doing the change, We cannot do the remap if we
//have a bad synchronization between the face data and the Materials data.
for ( int32 FaceIndex = 0 ; FaceIndex < LODFaces . Num ( ) ; + + FaceIndex )
{
if ( ! MaterialRemap . IsValidIndex ( LODFaces [ FaceIndex ] . MeshMaterialIndex ) )
{
return ;
}
}
//Update all the faces
for ( int32 FaceIndex = 0 ; FaceIndex < LODFaces . Num ( ) ; + + FaceIndex )
{
LODFaces [ FaceIndex ] . MeshMaterialIndex = MaterialRemap [ LODFaces [ FaceIndex ] . MeshMaterialIndex ] ;
}
}
}
2020-09-24 00:43:27 -04:00
namespace TriangleStripHelper
{
struct FTriangle2D
{
FVector2D Vertices [ 3 ] ;
} ;
2019-10-01 20:41:42 -04:00
2020-09-24 00:43:27 -04:00
bool IntersectTriangleAndAABB ( const FTriangle2D & Triangle , const FBox2D & Box )
{
FBox2D TriangleBox ( Triangle . Vertices [ 0 ] , Triangle . Vertices [ 0 ] ) ;
TriangleBox + = Triangle . Vertices [ 1 ] ;
TriangleBox + = Triangle . Vertices [ 2 ] ;
auto IntersectBoxes = [ & TriangleBox , & Box ] ( ) - > bool
{
if ( ( FMath : : RoundToInt ( TriangleBox . Min . X ) > = FMath : : RoundToInt ( Box . Max . X ) ) | | ( FMath : : RoundToInt ( Box . Min . X ) > = FMath : : RoundToInt ( TriangleBox . Max . X ) ) )
{
return false ;
}
if ( ( FMath : : RoundToInt ( TriangleBox . Min . Y ) > = FMath : : RoundToInt ( Box . Max . Y ) ) | | ( FMath : : RoundToInt ( Box . Min . Y ) > = FMath : : RoundToInt ( TriangleBox . Max . Y ) ) )
{
return false ;
}
return true ;
} ;
//If the triangle box do not intersect, return false
if ( ! IntersectBoxes ( ) )
{
return false ;
}
auto IsInsideBox = [ & Box ] ( const FVector2D & TestPoint ) - > bool
{
return ( ( FMath : : RoundToInt ( TestPoint . X ) > = FMath : : RoundToInt ( Box . Min . X ) ) & &
( FMath : : RoundToInt ( TestPoint . X ) < = FMath : : RoundToInt ( Box . Max . X ) ) & &
( FMath : : RoundToInt ( TestPoint . Y ) > = FMath : : RoundToInt ( Box . Min . Y ) ) & &
( FMath : : RoundToInt ( TestPoint . Y ) < = FMath : : RoundToInt ( Box . Max . Y ) ) ) ;
} ;
if ( IsInsideBox ( Triangle . Vertices [ 0 ] ) | |
IsInsideBox ( Triangle . Vertices [ 1 ] ) | |
IsInsideBox ( Triangle . Vertices [ 2 ] ) )
{
return true ;
}
auto SegmentIntersection2D = [ ] ( const FVector2D & SegmentStartA , const FVector2D & SegmentEndA , const FVector2D & SegmentStartB , const FVector2D & SegmentEndB )
{
const FVector2D VectorA = SegmentEndA - SegmentStartA ;
const FVector2D VectorB = SegmentEndB - SegmentStartB ;
const float S = ( - VectorA . Y * ( SegmentStartA . X - SegmentStartB . X ) + VectorA . X * ( SegmentStartA . Y - SegmentStartB . Y ) ) / ( - VectorB . X * VectorA . Y + VectorA . X * VectorB . Y ) ;
const float T = ( VectorB . X * ( SegmentStartA . Y - SegmentStartB . Y ) - VectorB . Y * ( SegmentStartA . X - SegmentStartB . X ) ) / ( - VectorB . X * VectorA . Y + VectorA . X * VectorB . Y ) ;
return ( S > = 0 & & S < = 1 & & T > = 0 & & T < = 1 ) ;
} ;
auto IsInsideTriangle = [ & Triangle , & SegmentIntersection2D , & Box , & TriangleBox ] ( const FVector2D & TestPoint ) - > bool
{
float Extent = ( 2.0f * Box . GetSize ( ) . Size ( ) ) + ( 2.0f * TriangleBox . GetSize ( ) . Size ( ) ) ;
FVector2D TestPointExtend ( Extent , Extent ) ;
int32 IntersectionCount = SegmentIntersection2D ( Triangle . Vertices [ 0 ] , Triangle . Vertices [ 1 ] , TestPoint , TestPoint + TestPointExtend ) ? 1 : 0 ;
IntersectionCount + = SegmentIntersection2D ( Triangle . Vertices [ 1 ] , Triangle . Vertices [ 2 ] , TestPoint , TestPoint + TestPointExtend ) ? 1 : 0 ;
IntersectionCount + = SegmentIntersection2D ( Triangle . Vertices [ 2 ] , Triangle . Vertices [ 0 ] , TestPoint , TestPoint + TestPointExtend ) ? 1 : 0 ;
return ( IntersectionCount = = 1 ) ;
} ;
if ( IsInsideTriangle ( Box . Min ) | |
IsInsideTriangle ( Box . Max ) | |
IsInsideTriangle ( FVector2D ( Box . Min . X , Box . Max . Y ) ) | |
IsInsideTriangle ( FVector2D ( Box . Max . X , Box . Min . Y ) ) )
{
return true ;
}
auto IsTriangleEdgeIntersectBoxEdges = [ & SegmentIntersection2D , & Box ] ( const FVector2D & EdgeStart , const FVector2D & EdgeEnd ) - > bool
{
//Triangle Edges 0-1 intersection with box
if ( SegmentIntersection2D ( EdgeStart , EdgeEnd , Box . Min , FVector2D ( Box . Min . X , Box . Max . Y ) ) | |
SegmentIntersection2D ( EdgeStart , EdgeEnd , Box . Max , FVector2D ( Box . Min . X , Box . Max . Y ) ) | |
SegmentIntersection2D ( EdgeStart , EdgeEnd , Box . Max , FVector2D ( Box . Max . X , Box . Min . Y ) ) | |
SegmentIntersection2D ( EdgeStart , EdgeEnd , Box . Min , FVector2D ( Box . Max . X , Box . Min . Y ) ) )
{
return true ;
}
return false ;
} ;
if ( IsTriangleEdgeIntersectBoxEdges ( Triangle . Vertices [ 0 ] , Triangle . Vertices [ 1 ] ) | |
IsTriangleEdgeIntersectBoxEdges ( Triangle . Vertices [ 1 ] , Triangle . Vertices [ 2 ] ) | |
IsTriangleEdgeIntersectBoxEdges ( Triangle . Vertices [ 2 ] , Triangle . Vertices [ 0 ] ) )
{
return true ;
}
return false ;
}
} //End namespace TriangleStripHelper
bool FLODUtilities : : StripLODGeometry ( USkeletalMesh * SkeletalMesh , const int32 LODIndex , UTexture2D * TextureMask , const float Threshold )
{
if ( LODIndex < 0 | | LODIndex > = SkeletalMesh - > GetLODNum ( ) | | ! SkeletalMesh - > GetImportedModel ( ) | | ! SkeletalMesh - > GetImportedModel ( ) - > LODModels . IsValidIndex ( LODIndex ) | | ! TextureMask )
{
UE_LOG ( LogLODUtilities , Warning , TEXT ( " Cannot strip triangle for skeletalmesh %s LOD %d. " ) , * SkeletalMesh - > GetPathName ( ) , LODIndex ) ;
return false ;
}
//Grab the reference data
FSkeletalMeshLODModel & LODModel = SkeletalMesh - > GetImportedModel ( ) - > LODModels [ LODIndex ] ;
const FSkeletalMeshLODInfo & LODInfo = * ( SkeletalMesh - > GetLODInfo ( LODIndex ) ) ;
const bool bIsReductionActive = SkeletalMesh - > IsReductionActive ( LODIndex ) ;
if ( bIsReductionActive & & LODInfo . ReductionSettings . BaseLOD < LODIndex )
{
//No need to strip if the LOD is reduce using another LOD as the source data
UE_LOG ( LogLODUtilities , Warning , TEXT ( " Cannot strip triangle for skeletalmesh %s LOD %d. Because this LOD is generated, strip the source instead. " ) , * SkeletalMesh - > GetPathName ( ) , LODIndex ) ;
return false ;
}
//Check the texture mask source data, it must be valid
FTextureSource & InitialSource = TextureMask - > Source ;
const int32 ResX = InitialSource . GetSizeX ( ) ;
const int32 ResY = InitialSource . GetSizeY ( ) ;
const int32 FormatDataSize = InitialSource . GetBytesPerPixel ( ) ;
if ( FormatDataSize < = 0 )
{
UE_LOG ( LogLODUtilities , Warning , TEXT ( " Cannot strip triangle for skeletalmesh %s LOD %d. Because the texture format size is 0. " ) , * SkeletalMesh - > GetPathName ( ) , LODIndex ) ;
return false ;
}
ETextureSourceFormat SourceFormat = InitialSource . GetFormat ( ) ;
if ( SourceFormat < = TSF_Invalid | | SourceFormat > = TSF_MAX )
{
UE_LOG ( LogLODUtilities , Warning , TEXT ( " Cannot strip triangle for skeletalmesh %s LOD %d. Because the texture format is invalid. " ) , * SkeletalMesh - > GetPathName ( ) , LODIndex ) ;
return false ;
}
TArray64 < uint8 > Ref2DData ;
if ( ! InitialSource . GetMipData ( Ref2DData , 0 , nullptr ) )
{
UE_LOG ( LogLODUtilities , Warning , TEXT ( " Cannot strip triangle for skeletalmesh %s LOD %d. Because the texture data cannot be extracted. " ) , * SkeletalMesh - > GetPathName ( ) , LODIndex ) ;
return false ;
}
//Post edit change scope
{
FScopedSkeletalMeshPostEditChange ScopePostEditChange ( SkeletalMesh ) ;
//This is like a re-import, we must force to use a new DDC
SkeletalMesh - > InvalidateDeriveDataCacheGUID ( ) ;
const bool bContainImportedData = SkeletalMesh - > IsLODImportedDataEmpty ( LODIndex ) ;
const bool bBuildAvailable = SkeletalMesh - > IsLODImportedDataBuildAvailable ( LODIndex ) ;
FSkeletalMeshImportData ImportedData ;
//Get the imported data if available
if ( bBuildAvailable )
{
SkeletalMesh - > LoadLODImportedData ( LODIndex , ImportedData ) ;
}
SkeletalMesh - > Modify ( ) ;
2022-03-15 18:29:37 -04:00
ERawImageFormat : : Type RawFormat = FImageCoreUtils : : ConvertToRawImageFormat ( SourceFormat ) ;
bool bSRGB = TextureMask - > SRGB ;
2020-09-24 00:43:27 -04:00
2022-03-15 18:29:37 -04:00
auto ShouldStripTriangle = [ & ] ( const FVector2D & UvA , const FVector2D & UvB , const FVector2D & UvC ) - > bool
2020-09-24 00:43:27 -04:00
{
FVector2D PixelUvA = FVector2D ( FMath : : FloorToInt ( UvA . X * ( float ) ResX ) % ( ResX + 1 ) , FMath : : FloorToInt ( UvA . Y * ( float ) ResY ) % ( ResY + 1 ) ) ;
FVector2D PixelUvB = FVector2D ( FMath : : FloorToInt ( UvB . X * ( float ) ResX ) % ( ResX + 1 ) , FMath : : FloorToInt ( UvB . Y * ( float ) ResY ) % ( ResY + 1 ) ) ;
FVector2D PixelUvC = FVector2D ( FMath : : FloorToInt ( UvC . X * ( float ) ResX ) % ( ResX + 1 ) , FMath : : FloorToInt ( UvC . Y * ( float ) ResY ) % ( ResY + 1 ) ) ;
int32 MinU = FMath : : Clamp ( FMath : : Min3 < int32 > ( PixelUvA . X , PixelUvB . X , PixelUvC . X ) , 0 , ResX ) ;
int32 MinV = FMath : : Clamp ( FMath : : Min3 < int32 > ( PixelUvA . Y , PixelUvB . Y , PixelUvC . Y ) , 0 , ResY ) ;
int32 MaxU = FMath : : Clamp ( FMath : : Max3 < int32 > ( PixelUvA . X , PixelUvB . X , PixelUvC . X ) , 0 , ResX ) ;
int32 MaxV = FMath : : Clamp ( FMath : : Max3 < int32 > ( PixelUvA . Y , PixelUvB . Y , PixelUvC . Y ) , 0 , ResY ) ;
//Do not read the alpha value when testing the texture value
2022-03-15 18:29:37 -04:00
auto IsPixelZero = [ & ] ( int32 PosX , int32 PosY ) - > bool
2020-09-24 00:43:27 -04:00
{
const int32 RefPos = PosX + ( PosY * InitialSource . GetSizeX ( ) ) ;
2022-03-15 18:29:37 -04:00
const void * PixelPtr = Ref2DData . GetData ( ) + RefPos * FormatDataSize ;
2020-09-24 00:43:27 -04:00
2022-03-15 18:29:37 -04:00
FLinearColor Color = ERawImageFormat : : GetOnePixelLinear ( PixelPtr , RawFormat , bSRGB ) ;
bool bPixelIsZero =
FMath : : IsNearlyZero ( Color . R , Threshold ) & &
FMath : : IsNearlyZero ( Color . G , Threshold ) & &
FMath : : IsNearlyZero ( Color . B , Threshold ) ;
2020-09-24 00:43:27 -04:00
return bPixelIsZero ;
} ;
//Triangle smaller or equal to one pixel just need to test the pixel color value
if ( MinU = = MaxU | | MinV = = MaxV )
{
return IsPixelZero ( MinU , MinV ) ;
}
for ( int32 PosY = MinV ; PosY < MaxV ; + + PosY )
{
for ( int32 PosX = MinU ; PosX < MaxU ; + + PosX )
{
bool bStripPixel = IsPixelZero ( PosX , PosY ) ;
//if any none zeroed pixel intersect the triangle, prevent stripping of this triangle
if ( ! bStripPixel )
{
FVector2D StartPixel ( ( float ) PosX , ( float ) PosY ) ;
FVector2D EndPixel ( ( float ) ( PosX + 1 ) , ( float ) ( PosY + 1 ) ) ;
FBox2D Box2D ( StartPixel , EndPixel ) ;
//Test if the triangle UV touch this pixel
TriangleStripHelper : : FTriangle2D Triangle ;
Triangle . Vertices [ 0 ] = PixelUvA ;
Triangle . Vertices [ 1 ] = PixelUvB ;
Triangle . Vertices [ 2 ] = PixelUvC ;
if ( TriangleStripHelper : : IntersectTriangleAndAABB ( Triangle , Box2D ) )
{
return false ;
}
}
}
}
return true ;
} ;
2022-01-10 08:51:57 -05:00
const TArray < uint32 > & SoftVertexIndexToImportDataPointIndex = LODModel . GetRawPointIndices ( ) ;
2020-09-24 00:43:27 -04:00
TMap < uint64 , TArray < int32 > > OptimizedFaceFinder ;
auto GetMatchFaceIndex = [ & OptimizedFaceFinder , & ImportedData ] ( const int32 FaceVertexA , const int32 FaceVertexB , int32 FaceVertexC ) - > int32
{
uint64 Key = ( uint64 ) FaceVertexA | ( ( uint64 ) FaceVertexB > > 32 ) | ( ( ( uint64 ) FaceVertexC & 0xFFFF ) > > 48 ) ;
TArray < int32 > & FaceIndices = OptimizedFaceFinder . FindChecked ( Key ) ;
for ( int32 PossibleFaceIndex = 0 ; PossibleFaceIndex < FaceIndices . Num ( ) ; + + PossibleFaceIndex )
{
int32 FaceIndex = FaceIndices [ PossibleFaceIndex ] ;
const SkeletalMeshImportData : : FTriangle & Face = ImportedData . Faces [ FaceIndex ] ;
if ( FaceVertexA = = ImportedData . Wedges [ Face . WedgeIndex [ 0 ] ] . VertexIndex )
{
if ( FaceVertexB = = ImportedData . Wedges [ Face . WedgeIndex [ 1 ] ] . VertexIndex )
{
if ( FaceVertexC = = ImportedData . Wedges [ Face . WedgeIndex [ 2 ] ] . VertexIndex )
{
return FaceIndex ;
}
}
}
}
return INDEX_NONE ;
} ;
for ( int32 FaceIndex = 0 ; FaceIndex < ImportedData . Faces . Num ( ) ; + + FaceIndex )
{
const SkeletalMeshImportData : : FTriangle & Face = ImportedData . Faces [ FaceIndex ] ;
int32 FaceVertexA = ImportedData . Wedges [ Face . WedgeIndex [ 0 ] ] . VertexIndex ;
int32 FaceVertexB = ImportedData . Wedges [ Face . WedgeIndex [ 1 ] ] . VertexIndex ;
int32 FaceVertexC = ImportedData . Wedges [ Face . WedgeIndex [ 2 ] ] . VertexIndex ;
uint64 Key = ( uint64 ) FaceVertexA | ( ( uint64 ) FaceVertexB > > 32 ) | ( ( ( uint64 ) FaceVertexC & 0xFFFF ) > > 48 ) ;
TArray < int32 > & FaceIndices = OptimizedFaceFinder . FindOrAdd ( Key ) ;
FaceIndices . Add ( FaceIndex ) ;
}
int32 RemovedFaceCount = 0 ;
TBitArray < > FaceToRemove ;
FaceToRemove . Init ( false , ImportedData . Faces . Num ( ) ) ;
int32 NumTriangleIndex = LODModel . IndexBuffer . Num ( ) ;
for ( int32 TriangleIndex = NumTriangleIndex - 1 ; TriangleIndex > = 0 ; TriangleIndex - = 3 )
{
int32 VertexIndexA = LODModel . IndexBuffer [ TriangleIndex - 2 ] ;
int32 VertexIndexB = LODModel . IndexBuffer [ TriangleIndex - 1 ] ;
int32 VertexIndexC = LODModel . IndexBuffer [ TriangleIndex ] ;
int32 SectionIndex ;
int32 SectionVertexIndexA ;
int32 SectionVertexIndexB ;
int32 SectionVertexIndexC ;
LODModel . GetSectionFromVertexIndex ( VertexIndexA , SectionIndex , SectionVertexIndexA ) ;
LODModel . GetSectionFromVertexIndex ( VertexIndexB , SectionIndex , SectionVertexIndexB ) ;
LODModel . GetSectionFromVertexIndex ( VertexIndexC , SectionIndex , SectionVertexIndexC ) ;
FSkelMeshSection & Section = LODModel . Sections [ SectionIndex ] ;
//Get the UV triangle, add the small number that will act like threshold when converting the UV into pixel coordinate.
2022-02-02 01:45:23 -05:00
FVector2D UvA = FVector2D ( Section . SoftVertices [ SectionVertexIndexA ] . UVs [ 0 ] ) + KINDA_SMALL_NUMBER ;
FVector2D UvB = FVector2D ( Section . SoftVertices [ SectionVertexIndexB ] . UVs [ 0 ] ) + KINDA_SMALL_NUMBER ;
FVector2D UvC = FVector2D ( Section . SoftVertices [ SectionVertexIndexC ] . UVs [ 0 ] ) + KINDA_SMALL_NUMBER ;
2020-09-24 00:43:27 -04:00
if ( ShouldStripTriangle ( UvA , UvB , UvC ) )
{
//Find the face in the imported data
if ( bBuildAvailable )
{
//Findback the face in the import data
int32 ImportedPointIndexA = SoftVertexIndexToImportDataPointIndex [ VertexIndexA ] ;
int32 ImportedPointIndexB = SoftVertexIndexToImportDataPointIndex [ VertexIndexB ] ;
int32 ImportedPointIndexC = SoftVertexIndexToImportDataPointIndex [ VertexIndexC ] ;
int32 FaceIndex = GetMatchFaceIndex ( ImportedPointIndexA , ImportedPointIndexB , ImportedPointIndexC ) ;
if ( FaceIndex ! = INDEX_NONE )
{
if ( ! FaceToRemove [ FaceIndex ] )
{
FaceToRemove [ FaceIndex ] = true ;
RemovedFaceCount + + ;
}
}
}
else
{
//Remove the source model vertex if there is no build data
LODModel . IndexBuffer . RemoveAt ( TriangleIndex - 2 , 3 , false ) ;
}
}
}
if ( bBuildAvailable & & RemovedFaceCount > 0 )
{
//Recreate a new imported data with only the remaining faces
FSkeletalMeshImportData StrippedImportedData ;
StrippedImportedData = ImportedData ;
StrippedImportedData . Faces . Reset ( ) ;
StrippedImportedData . Wedges . Reset ( ) ;
StrippedImportedData . Points . Reset ( ) ;
StrippedImportedData . PointToRawMap . Reset ( ) ;
StrippedImportedData . Influences . Reset ( ) ;
TArray < int32 > RemapVertexIndex ;
RemapVertexIndex . AddZeroed ( ImportedData . Points . Num ( ) ) ;
for ( int32 VertexIndex = 0 ; VertexIndex < ImportedData . Points . Num ( ) ; + + VertexIndex )
{
RemapVertexIndex [ VertexIndex ] = INDEX_NONE ;
}
StrippedImportedData . Faces . AddDefaulted ( ImportedData . Faces . Num ( ) - RemovedFaceCount ) ;
StrippedImportedData . Wedges . AddDefaulted ( StrippedImportedData . Faces . Num ( ) * 3 ) ;
int32 NewFaceIndex = 0 ;
int32 NewWedgeIndex = 0 ;
for ( int32 FaceIndex = 0 ; FaceIndex < ImportedData . Faces . Num ( ) ; + + FaceIndex )
{
//Skip removed faces
if ( FaceToRemove [ FaceIndex ] )
{
continue ;
}
SkeletalMeshImportData : : FTriangle & NewFace = StrippedImportedData . Faces [ NewFaceIndex + + ] ;
NewFace = ImportedData . Faces [ FaceIndex ] ;
for ( int32 FaceWedgeIndex = 0 ; FaceWedgeIndex < 3 ; + + FaceWedgeIndex )
{
SkeletalMeshImportData : : FVertex & NewWedge = StrippedImportedData . Wedges [ NewWedgeIndex ] ;
NewWedge = ImportedData . Wedges [ NewFace . WedgeIndex [ FaceWedgeIndex ] ] ;
NewFace . WedgeIndex [ FaceWedgeIndex ] = NewWedgeIndex ;
int32 VertexIndex = NewWedge . VertexIndex ;
if ( RemapVertexIndex [ VertexIndex ] = = INDEX_NONE )
{
StrippedImportedData . PointToRawMap . Add ( ImportedData . PointToRawMap [ VertexIndex ] ) ;
NewWedge . VertexIndex = StrippedImportedData . Points . Add ( ImportedData . Points [ VertexIndex ] ) ;
RemapVertexIndex [ VertexIndex ] = NewWedge . VertexIndex ;
}
else
{
NewWedge . VertexIndex = RemapVertexIndex [ VertexIndex ] ;
}
NewWedgeIndex + + ;
}
}
//Fix the influences with the RemapVertexIndex
for ( int32 InfluenceIndex = 0 ; InfluenceIndex < ImportedData . Influences . Num ( ) ; + + InfluenceIndex )
{
int32 VertexIndex = ImportedData . Influences [ InfluenceIndex ] . VertexIndex ;
int32 RemappedVertexIndex = RemapVertexIndex [ VertexIndex ] ;
if ( RemappedVertexIndex ! = INDEX_NONE )
{
SkeletalMeshImportData : : FRawBoneInfluence & Influence = StrippedImportedData . Influences . Add_GetRef ( ImportedData . Influences [ InfluenceIndex ] ) ;
Influence . VertexIndex = RemapVertexIndex [ VertexIndex ] ;
}
}
SkeletalMesh - > SaveLODImportedData ( LODIndex , StrippedImportedData ) ;
}
}
return true ;
}
2019-10-01 20:41:42 -04:00
2022-04-26 12:53:38 -04:00
# undef LOCTEXT_NAMESPACE // "LODUtilities"
# endif //WITH_EDITOR