├── .gitignore
├── Config
├── DefaultCtrlLevelReferenceViewer.ini
├── DefaultCtrlReferenceVisualizer.ini
└── FilterPlugin.ini
├── Content
├── Sample_Maps
│ ├── CRV_Actor_Tests.umap
│ ├── CRV_Component_Tests.umap
│ ├── CRV_DefaultEnvironment.umap
│ ├── CRV_Nesting_Tests.umap
│ ├── CRV_Test_Map.umap
│ ├── CRV_Test_Map2.umap
│ ├── CRV_Test_Map_Trivial.umap
│ └── SampleAssets
│ │ ├── AC_CRV_TestComponent.uasset
│ │ ├── BP_CRV_SampleFloor.uasset
│ │ ├── BP_CRV_TestActor.uasset
│ │ ├── BP_CRV_TestActorNative.uasset
│ │ ├── BP_CRV_TestActorNative_WithChildActor.uasset
│ │ ├── CRV_Cube_AFC9EB59.uasset
│ │ ├── MI_CRV_FlatColor_27.uasset
│ │ ├── MI_CRV_PrototypeGrid_Brown.uasset
│ │ ├── MM_CRV_FlatColor_01.uasset
│ │ ├── M_CRV_PrototypeGrid.uasset
│ │ └── SM_CRV_SampleFloor.uasset
└── __ExternalActors__
│ └── Sample_Maps
│ ├── CRV_Actor_Tests
│ ├── 0
│ │ ├── 1K
│ │ │ └── HB7322RWV6H54QYB4HCZML.uasset
│ │ ├── AP
│ │ │ └── 7T54NFZASQDZY449X0XBX7.uasset
│ │ ├── EK
│ │ │ └── 4Z9GCU8ZAYESN0RN4P43VY.uasset
│ │ ├── F5
│ │ │ └── IJ4GPCBY4DN6SXLKZZ68QN.uasset
│ │ ├── IP
│ │ │ └── 2NJAQ7UU1N0VY6P5ATDEMW.uasset
│ │ └── M9
│ │ │ └── V2T6VEVXVLR462PTCGTFXC.uasset
│ ├── 1
│ │ ├── 10
│ │ │ └── M2PXPYCROZE3YO4S31JGG2.uasset
│ │ ├── 37
│ │ │ └── L77KZMYDO5ZD610B2WMV7M.uasset
│ │ ├── BQ
│ │ │ └── JOBAB3FMHCAMKDNAM94MXK.uasset
│ │ └── WD
│ │ │ └── 4NYNPX5IU51SKEEYZ751BP.uasset
│ ├── 2
│ │ ├── 5R
│ │ │ └── RX8WANBIUQ7YW6AH271F37.uasset
│ │ ├── C5
│ │ │ └── W7FZGWSC43AVEJ5NEKHRI6.uasset
│ │ ├── G4
│ │ │ └── J1IK0MWCMIVUUEWTG9D36C.uasset
│ │ ├── QT
│ │ │ └── CNZGTV0AGA01PCBFD43OS1.uasset
│ │ └── WM
│ │ │ └── LLNFQ8TKFR4IDFKKGMC7TC.uasset
│ ├── 3
│ │ ├── 7R
│ │ │ └── FF5UHJMXQUGRAW02CST87B.uasset
│ │ └── PW
│ │ │ └── B1RCFH5FN8IZC1YNZMHFFR.uasset
│ ├── 4
│ │ └── 0C
│ │ │ └── WNLNEKE3IQMYI70V4ZQETG.uasset
│ ├── 5
│ │ ├── 29
│ │ │ └── YWNMNOP8HKMV5CJ5OB03F5.uasset
│ │ └── MF
│ │ │ └── BLQVG0K3DKM5ORBLXT8EIK.uasset
│ ├── 6
│ │ └── P7
│ │ │ └── D2ZFA68TZMVQM792Y9G9Z7.uasset
│ ├── 7
│ │ ├── 4L
│ │ │ └── LBJX8X6CHE1RXPTY4K5AW4.uasset
│ │ └── L6
│ │ │ └── RG5RWZTENLY8PS0IV0CXU5.uasset
│ ├── 8
│ │ ├── 12
│ │ │ └── WHNSXWZ5OY0DDTP46RWLFG.uasset
│ │ ├── 8U
│ │ │ └── NZINKCEO85B41MHXAU1KHY.uasset
│ │ ├── EW
│ │ │ └── YQQMSZ3KPA89ATOAATP0NL.uasset
│ │ └── MA
│ │ │ └── JUOT1N7D0YTC58XAXOOGPB.uasset
│ ├── 9
│ │ ├── 16
│ │ │ └── VE328OCJCYP5ITU159L5RB.uasset
│ │ ├── 4F
│ │ │ └── TLCUWP8ZI67T4V7WATEJPS.uasset
│ │ ├── 5N
│ │ │ └── JYZNTUY3ZCO14CPBZ0OYJB.uasset
│ │ ├── OI
│ │ │ └── SUWHJCC0PEC1C9I4X35TVY.uasset
│ │ └── R1
│ │ │ └── ANV7VDB5SNSBQ0NZ6V6VIA.uasset
│ ├── A
│ │ ├── 3S
│ │ │ └── NCNKDAW1MI1WJQSOEB7GVL.uasset
│ │ └── 7J
│ │ │ └── QL2Q70RZ1AD8ECCJ0DQOK0.uasset
│ ├── B
│ │ ├── 7O
│ │ │ └── JVBJFPNP5YRV20VEL68QFD.uasset
│ │ └── KQ
│ │ │ └── CS70CFMJCXGP2HTJ43M7ID.uasset
│ ├── C
│ │ ├── 0Z
│ │ │ └── BSEIYPE7Z7OVPWPCNT4CVR.uasset
│ │ ├── 5W
│ │ │ └── XKL6CWJ88V2MZQ1HTIL74K.uasset
│ │ └── YQ
│ │ │ └── TRP0QNVPI3X5RO9ITMYXKX.uasset
│ ├── D
│ │ ├── 6Y
│ │ │ └── Y7CSU0157X4964YVD50LPM.uasset
│ │ ├── KC
│ │ │ └── PS6MQADHANF9CA5YB7HMSG.uasset
│ │ ├── P2
│ │ │ └── YJPXDZPY0HLQJF114MC0FP.uasset
│ │ ├── SH
│ │ │ └── GXPSUV9MC3C7EUGO0CF2W9.uasset
│ │ ├── VE
│ │ │ └── OC0KL3GX9OJIYAN7K1V6R7.uasset
│ │ └── WY
│ │ │ └── F8A5KKZR3ZOX1778TXOGHP.uasset
│ └── E
│ │ ├── 2X
│ │ └── CX5YCZ2GWG5RT20BY3W2NB.uasset
│ │ ├── AZ
│ │ └── JQ8V89VQ2LPX29RB7SQ415.uasset
│ │ └── CW
│ │ └── 7BEMYVPZ8FD7DX78M81AT9.uasset
│ ├── CRV_Component_Tests
│ ├── 0
│ │ └── 10
│ │ │ └── 8GQUCZOZEBNF8W6V5AVDWP.uasset
│ ├── 1
│ │ ├── GO
│ │ │ └── NTYM67SQHKD5HDM8NOWROU.uasset
│ │ └── IT
│ │ │ └── 6ROL3W3C5I3V4PYR32VIVT.uasset
│ ├── 2
│ │ ├── JQ
│ │ │ └── JHIK4YLTY022M6KKL4P2ES.uasset
│ │ └── NG
│ │ │ └── YK3C52K50GBJCO20BLXD6R.uasset
│ ├── 3
│ │ ├── CX
│ │ │ └── 540X88PL9D2SOC988GT14V.uasset
│ │ ├── FH
│ │ │ └── IVLO0QK593N8U1WOS059DE.uasset
│ │ ├── FU
│ │ │ └── S30EG04809ZFTYRQEQFT86.uasset
│ │ ├── LC
│ │ │ └── P48RYQ0RNIH18OWZARWW8R.uasset
│ │ └── M9
│ │ │ └── J20P132W10EWMN71JLHZAA.uasset
│ ├── 4
│ │ ├── 4W
│ │ │ └── NOWDTQ1GW65BKN9L8U1FSB.uasset
│ │ └── QU
│ │ │ └── CEWHMSSTS899VWORCU54JY.uasset
│ ├── 5
│ │ ├── 3N
│ │ │ └── R92E55LZ77L444PAA1DU46.uasset
│ │ └── KU
│ │ │ └── 5Q0MSYI1QUSBIRH5NH8HOZ.uasset
│ ├── 8
│ │ └── RF
│ │ │ └── RSLZF7D7B2SZJVWH6YAP3H.uasset
│ ├── 9
│ │ └── 39
│ │ │ └── 8LWDNM01R0TZR6M9Z3ELLO.uasset
│ ├── C
│ │ ├── HL
│ │ │ └── F0ZZ7I3EHBGJ9BPID7CK3D.uasset
│ │ └── Y0
│ │ │ └── 7YR3UWQSJLDWINQ5IN867E.uasset
│ ├── D
│ │ ├── 1D
│ │ │ └── 5ENE0Z6D3N3T9EICYG92JA.uasset
│ │ ├── U7
│ │ │ └── LW6FQYMUSQULU477OGB9EC.uasset
│ │ └── X6
│ │ │ └── Z70B3JZYZL3NXPFU97TP8J.uasset
│ └── E
│ │ ├── 7F
│ │ └── NVM740XZ0NWSIQ3Q7AFV3L.uasset
│ │ ├── H0
│ │ └── GLR1CWABNKUMJSHHS5IZUW.uasset
│ │ └── J3
│ │ └── 40G0U5I509TXV6FLYIFVGY.uasset
│ ├── CRV_DefaultEnvironment
│ ├── 1
│ │ └── SQ
│ │ │ └── SS0APMSP1BG68MHEDJBEA8.uasset
│ ├── 2
│ │ └── RH
│ │ │ └── XQ412HIUEAOT1RUGY3P1PI.uasset
│ ├── 3
│ │ └── A3
│ │ │ └── C5E15W1R1NGRK3PFP6DZPP.uasset
│ └── C
│ │ ├── 4O
│ │ └── FVQ17H8S1UBHD5JPSBEUJB.uasset
│ │ └── HO
│ │ └── 3RUQHZ1ZTGI8CGO9HV8WM7.uasset
│ └── CRV_Nesting_Tests
│ ├── 1
│ └── QO
│ │ └── C4A0OV2U50G2BCLNOTN4D7.uasset
│ ├── 3
│ └── WP
│ │ └── I0BPL983SWH7N5M45UCLWT.uasset
│ ├── 4
│ └── 0S
│ │ └── K9BSHYULX4J3PIZMCMCJFN.uasset
│ ├── 5
│ └── GR
│ │ └── L3XI6P8Z3MSWLGIRCTZEKZ.uasset
│ ├── 8
│ ├── D8
│ │ └── 0NV4RJDI6JJJH341KZ9UFO.uasset
│ └── K8
│ │ └── 9FQ5PNUKL2X2U5X483CHSW.uasset
│ ├── 9
│ └── FK
│ │ └── LCA3QO39IEVSZ0UM7UW5X9.uasset
│ ├── B
│ └── NK
│ │ └── 4R1TYR48JUSXDQ2LGCHE75.uasset
│ ├── C
│ ├── 68
│ │ └── D5KDXR6EN0QFLBSLDZ5KEL.uasset
│ └── JJ
│ │ └── PAGXJ46ZRYWOU6043NCOD5.uasset
│ ├── D
│ └── 50
│ │ └── OL1PEWTMVIFPFTR85OE2Y8.uasset
│ └── E
│ ├── 49
│ └── 3H9O8BNIAG64RFVZKI1QSS.uasset
│ └── MJ
│ └── J8D4BFKTLH3OBFR4FRWYKY.uasset
├── CtrlReferenceVisualizer.uplugin
├── LICENSE.md
├── README.md
├── Resources
├── Icon128.png
└── Icon16.png
└── Source
└── CtrlReferenceVisualizer
├── CtrlReferenceVisualizer.Build.cs
├── Private
├── CrvCommands.cpp
├── CrvComponent.cpp
├── CrvDrawUtils.cpp
├── CrvDrawUtils.h
├── CrvHitProxy.cpp
├── CrvRefCache.cpp
├── CrvRefCache.h
├── CrvRefSearch.cpp
├── CrvSampleFloorBase.h
├── CrvSettings.cpp
├── CrvStyle.cpp
├── CrvTestActorBase.cpp
├── CrvTestActorBase.h
├── CrvUtils.cpp
├── CrvUtils.h
├── CtrlReferenceVisualizer.cpp
└── ReferenceVisualizerComponent.cpp
└── Public
├── CrvCommands.h
├── CrvHitProxy.h
├── CrvRefSearch.h
├── CrvSettings.h
├── CrvStyle.h
├── CtrlReferenceVisualizer.h
└── ReferenceVisualizerComponent.h
/.gitignore:
--------------------------------------------------------------------------------
1 | Binaries/
2 | Intermediate/
3 |
--------------------------------------------------------------------------------
/Config/DefaultCtrlLevelReferenceViewer.ini:
--------------------------------------------------------------------------------
1 | [CoreRedirects]
2 | +ClassRedirects=(OldName="/Script/CtrlReferenceVisualizer.LrvComponent",NewName="/Script/CtrlReferenceVisualizer.ReferenceVisualizerComponent")
--------------------------------------------------------------------------------
/Config/DefaultCtrlReferenceVisualizer.ini:
--------------------------------------------------------------------------------
1 | [CoreRedirects]
2 | +EnumRedirects=(OldName="/Script/CtrlReferenceVisualizer.ECrvLineStyle",NewName="/Script/CtrlReferenceVisualizer.ECrvLineType")
--------------------------------------------------------------------------------
/Config/FilterPlugin.ini:
--------------------------------------------------------------------------------
1 | [FilterPlugin]
2 | ; This section lists additional files which will be packaged along with your plugin. Paths should be listed relative to the root plugin directory, and
3 | ; may include "...", "*", and "?" wildcards to match directories, files, and individual characters respectively.
4 | ;
5 | ; Examples:
6 | ; /README.txt
7 | ; /Extras/...
8 | ; /Binaries/ThirdParty/*.dll
9 |
--------------------------------------------------------------------------------
/Content/Sample_Maps/CRV_Actor_Tests.umap:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/Sample_Maps/CRV_Actor_Tests.umap
--------------------------------------------------------------------------------
/Content/Sample_Maps/CRV_Component_Tests.umap:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/Sample_Maps/CRV_Component_Tests.umap
--------------------------------------------------------------------------------
/Content/Sample_Maps/CRV_DefaultEnvironment.umap:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/Sample_Maps/CRV_DefaultEnvironment.umap
--------------------------------------------------------------------------------
/Content/Sample_Maps/CRV_Nesting_Tests.umap:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/Sample_Maps/CRV_Nesting_Tests.umap
--------------------------------------------------------------------------------
/Content/Sample_Maps/CRV_Test_Map.umap:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/Sample_Maps/CRV_Test_Map.umap
--------------------------------------------------------------------------------
/Content/Sample_Maps/CRV_Test_Map2.umap:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/Sample_Maps/CRV_Test_Map2.umap
--------------------------------------------------------------------------------
/Content/Sample_Maps/CRV_Test_Map_Trivial.umap:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/Sample_Maps/CRV_Test_Map_Trivial.umap
--------------------------------------------------------------------------------
/Content/Sample_Maps/SampleAssets/AC_CRV_TestComponent.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/Sample_Maps/SampleAssets/AC_CRV_TestComponent.uasset
--------------------------------------------------------------------------------
/Content/Sample_Maps/SampleAssets/BP_CRV_SampleFloor.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/Sample_Maps/SampleAssets/BP_CRV_SampleFloor.uasset
--------------------------------------------------------------------------------
/Content/Sample_Maps/SampleAssets/BP_CRV_TestActor.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/Sample_Maps/SampleAssets/BP_CRV_TestActor.uasset
--------------------------------------------------------------------------------
/Content/Sample_Maps/SampleAssets/BP_CRV_TestActorNative.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/Sample_Maps/SampleAssets/BP_CRV_TestActorNative.uasset
--------------------------------------------------------------------------------
/Content/Sample_Maps/SampleAssets/BP_CRV_TestActorNative_WithChildActor.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/Sample_Maps/SampleAssets/BP_CRV_TestActorNative_WithChildActor.uasset
--------------------------------------------------------------------------------
/Content/Sample_Maps/SampleAssets/CRV_Cube_AFC9EB59.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/Sample_Maps/SampleAssets/CRV_Cube_AFC9EB59.uasset
--------------------------------------------------------------------------------
/Content/Sample_Maps/SampleAssets/MI_CRV_FlatColor_27.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/Sample_Maps/SampleAssets/MI_CRV_FlatColor_27.uasset
--------------------------------------------------------------------------------
/Content/Sample_Maps/SampleAssets/MI_CRV_PrototypeGrid_Brown.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/Sample_Maps/SampleAssets/MI_CRV_PrototypeGrid_Brown.uasset
--------------------------------------------------------------------------------
/Content/Sample_Maps/SampleAssets/MM_CRV_FlatColor_01.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/Sample_Maps/SampleAssets/MM_CRV_FlatColor_01.uasset
--------------------------------------------------------------------------------
/Content/Sample_Maps/SampleAssets/M_CRV_PrototypeGrid.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/Sample_Maps/SampleAssets/M_CRV_PrototypeGrid.uasset
--------------------------------------------------------------------------------
/Content/Sample_Maps/SampleAssets/SM_CRV_SampleFloor.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/Sample_Maps/SampleAssets/SM_CRV_SampleFloor.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/0/1K/HB7322RWV6H54QYB4HCZML.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/0/1K/HB7322RWV6H54QYB4HCZML.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/0/AP/7T54NFZASQDZY449X0XBX7.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/0/AP/7T54NFZASQDZY449X0XBX7.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/0/EK/4Z9GCU8ZAYESN0RN4P43VY.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/0/EK/4Z9GCU8ZAYESN0RN4P43VY.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/0/F5/IJ4GPCBY4DN6SXLKZZ68QN.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/0/F5/IJ4GPCBY4DN6SXLKZZ68QN.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/0/IP/2NJAQ7UU1N0VY6P5ATDEMW.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/0/IP/2NJAQ7UU1N0VY6P5ATDEMW.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/0/M9/V2T6VEVXVLR462PTCGTFXC.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/0/M9/V2T6VEVXVLR462PTCGTFXC.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/1/10/M2PXPYCROZE3YO4S31JGG2.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/1/10/M2PXPYCROZE3YO4S31JGG2.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/1/37/L77KZMYDO5ZD610B2WMV7M.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/1/37/L77KZMYDO5ZD610B2WMV7M.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/1/BQ/JOBAB3FMHCAMKDNAM94MXK.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/1/BQ/JOBAB3FMHCAMKDNAM94MXK.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/1/WD/4NYNPX5IU51SKEEYZ751BP.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/1/WD/4NYNPX5IU51SKEEYZ751BP.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/2/5R/RX8WANBIUQ7YW6AH271F37.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/2/5R/RX8WANBIUQ7YW6AH271F37.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/2/C5/W7FZGWSC43AVEJ5NEKHRI6.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/2/C5/W7FZGWSC43AVEJ5NEKHRI6.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/2/G4/J1IK0MWCMIVUUEWTG9D36C.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/2/G4/J1IK0MWCMIVUUEWTG9D36C.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/2/QT/CNZGTV0AGA01PCBFD43OS1.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/2/QT/CNZGTV0AGA01PCBFD43OS1.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/2/WM/LLNFQ8TKFR4IDFKKGMC7TC.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/2/WM/LLNFQ8TKFR4IDFKKGMC7TC.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/3/7R/FF5UHJMXQUGRAW02CST87B.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/3/7R/FF5UHJMXQUGRAW02CST87B.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/3/PW/B1RCFH5FN8IZC1YNZMHFFR.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/3/PW/B1RCFH5FN8IZC1YNZMHFFR.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/4/0C/WNLNEKE3IQMYI70V4ZQETG.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/4/0C/WNLNEKE3IQMYI70V4ZQETG.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/5/29/YWNMNOP8HKMV5CJ5OB03F5.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/5/29/YWNMNOP8HKMV5CJ5OB03F5.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/5/MF/BLQVG0K3DKM5ORBLXT8EIK.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/5/MF/BLQVG0K3DKM5ORBLXT8EIK.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/6/P7/D2ZFA68TZMVQM792Y9G9Z7.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/6/P7/D2ZFA68TZMVQM792Y9G9Z7.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/7/4L/LBJX8X6CHE1RXPTY4K5AW4.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/7/4L/LBJX8X6CHE1RXPTY4K5AW4.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/7/L6/RG5RWZTENLY8PS0IV0CXU5.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/7/L6/RG5RWZTENLY8PS0IV0CXU5.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/8/12/WHNSXWZ5OY0DDTP46RWLFG.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/8/12/WHNSXWZ5OY0DDTP46RWLFG.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/8/8U/NZINKCEO85B41MHXAU1KHY.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/8/8U/NZINKCEO85B41MHXAU1KHY.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/8/EW/YQQMSZ3KPA89ATOAATP0NL.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/8/EW/YQQMSZ3KPA89ATOAATP0NL.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/8/MA/JUOT1N7D0YTC58XAXOOGPB.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/8/MA/JUOT1N7D0YTC58XAXOOGPB.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/9/16/VE328OCJCYP5ITU159L5RB.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/9/16/VE328OCJCYP5ITU159L5RB.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/9/4F/TLCUWP8ZI67T4V7WATEJPS.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/9/4F/TLCUWP8ZI67T4V7WATEJPS.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/9/5N/JYZNTUY3ZCO14CPBZ0OYJB.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/9/5N/JYZNTUY3ZCO14CPBZ0OYJB.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/9/OI/SUWHJCC0PEC1C9I4X35TVY.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/9/OI/SUWHJCC0PEC1C9I4X35TVY.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/9/R1/ANV7VDB5SNSBQ0NZ6V6VIA.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/9/R1/ANV7VDB5SNSBQ0NZ6V6VIA.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/A/3S/NCNKDAW1MI1WJQSOEB7GVL.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/A/3S/NCNKDAW1MI1WJQSOEB7GVL.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/A/7J/QL2Q70RZ1AD8ECCJ0DQOK0.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/A/7J/QL2Q70RZ1AD8ECCJ0DQOK0.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/B/7O/JVBJFPNP5YRV20VEL68QFD.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/B/7O/JVBJFPNP5YRV20VEL68QFD.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/B/KQ/CS70CFMJCXGP2HTJ43M7ID.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/B/KQ/CS70CFMJCXGP2HTJ43M7ID.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/C/0Z/BSEIYPE7Z7OVPWPCNT4CVR.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/C/0Z/BSEIYPE7Z7OVPWPCNT4CVR.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/C/5W/XKL6CWJ88V2MZQ1HTIL74K.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/C/5W/XKL6CWJ88V2MZQ1HTIL74K.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/C/YQ/TRP0QNVPI3X5RO9ITMYXKX.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/C/YQ/TRP0QNVPI3X5RO9ITMYXKX.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/D/6Y/Y7CSU0157X4964YVD50LPM.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/D/6Y/Y7CSU0157X4964YVD50LPM.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/D/KC/PS6MQADHANF9CA5YB7HMSG.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/D/KC/PS6MQADHANF9CA5YB7HMSG.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/D/P2/YJPXDZPY0HLQJF114MC0FP.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/D/P2/YJPXDZPY0HLQJF114MC0FP.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/D/SH/GXPSUV9MC3C7EUGO0CF2W9.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/D/SH/GXPSUV9MC3C7EUGO0CF2W9.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/D/VE/OC0KL3GX9OJIYAN7K1V6R7.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/D/VE/OC0KL3GX9OJIYAN7K1V6R7.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/D/WY/F8A5KKZR3ZOX1778TXOGHP.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/D/WY/F8A5KKZR3ZOX1778TXOGHP.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/E/2X/CX5YCZ2GWG5RT20BY3W2NB.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/E/2X/CX5YCZ2GWG5RT20BY3W2NB.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/E/AZ/JQ8V89VQ2LPX29RB7SQ415.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/E/AZ/JQ8V89VQ2LPX29RB7SQ415.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/E/CW/7BEMYVPZ8FD7DX78M81AT9.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Actor_Tests/E/CW/7BEMYVPZ8FD7DX78M81AT9.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/0/10/8GQUCZOZEBNF8W6V5AVDWP.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/0/10/8GQUCZOZEBNF8W6V5AVDWP.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/1/GO/NTYM67SQHKD5HDM8NOWROU.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/1/GO/NTYM67SQHKD5HDM8NOWROU.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/1/IT/6ROL3W3C5I3V4PYR32VIVT.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/1/IT/6ROL3W3C5I3V4PYR32VIVT.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/2/JQ/JHIK4YLTY022M6KKL4P2ES.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/2/JQ/JHIK4YLTY022M6KKL4P2ES.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/2/NG/YK3C52K50GBJCO20BLXD6R.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/2/NG/YK3C52K50GBJCO20BLXD6R.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/3/CX/540X88PL9D2SOC988GT14V.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/3/CX/540X88PL9D2SOC988GT14V.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/3/FH/IVLO0QK593N8U1WOS059DE.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/3/FH/IVLO0QK593N8U1WOS059DE.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/3/FU/S30EG04809ZFTYRQEQFT86.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/3/FU/S30EG04809ZFTYRQEQFT86.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/3/LC/P48RYQ0RNIH18OWZARWW8R.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/3/LC/P48RYQ0RNIH18OWZARWW8R.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/3/M9/J20P132W10EWMN71JLHZAA.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/3/M9/J20P132W10EWMN71JLHZAA.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/4/4W/NOWDTQ1GW65BKN9L8U1FSB.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/4/4W/NOWDTQ1GW65BKN9L8U1FSB.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/4/QU/CEWHMSSTS899VWORCU54JY.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/4/QU/CEWHMSSTS899VWORCU54JY.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/5/3N/R92E55LZ77L444PAA1DU46.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/5/3N/R92E55LZ77L444PAA1DU46.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/5/KU/5Q0MSYI1QUSBIRH5NH8HOZ.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/5/KU/5Q0MSYI1QUSBIRH5NH8HOZ.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/8/RF/RSLZF7D7B2SZJVWH6YAP3H.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/8/RF/RSLZF7D7B2SZJVWH6YAP3H.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/9/39/8LWDNM01R0TZR6M9Z3ELLO.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/9/39/8LWDNM01R0TZR6M9Z3ELLO.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/C/HL/F0ZZ7I3EHBGJ9BPID7CK3D.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/C/HL/F0ZZ7I3EHBGJ9BPID7CK3D.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/C/Y0/7YR3UWQSJLDWINQ5IN867E.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/C/Y0/7YR3UWQSJLDWINQ5IN867E.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/D/1D/5ENE0Z6D3N3T9EICYG92JA.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/D/1D/5ENE0Z6D3N3T9EICYG92JA.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/D/U7/LW6FQYMUSQULU477OGB9EC.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/D/U7/LW6FQYMUSQULU477OGB9EC.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/D/X6/Z70B3JZYZL3NXPFU97TP8J.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/D/X6/Z70B3JZYZL3NXPFU97TP8J.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/E/7F/NVM740XZ0NWSIQ3Q7AFV3L.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/E/7F/NVM740XZ0NWSIQ3Q7AFV3L.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/E/H0/GLR1CWABNKUMJSHHS5IZUW.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/E/H0/GLR1CWABNKUMJSHHS5IZUW.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/E/J3/40G0U5I509TXV6FLYIFVGY.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Component_Tests/E/J3/40G0U5I509TXV6FLYIFVGY.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_DefaultEnvironment/1/SQ/SS0APMSP1BG68MHEDJBEA8.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_DefaultEnvironment/1/SQ/SS0APMSP1BG68MHEDJBEA8.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_DefaultEnvironment/2/RH/XQ412HIUEAOT1RUGY3P1PI.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_DefaultEnvironment/2/RH/XQ412HIUEAOT1RUGY3P1PI.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_DefaultEnvironment/3/A3/C5E15W1R1NGRK3PFP6DZPP.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_DefaultEnvironment/3/A3/C5E15W1R1NGRK3PFP6DZPP.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_DefaultEnvironment/C/4O/FVQ17H8S1UBHD5JPSBEUJB.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_DefaultEnvironment/C/4O/FVQ17H8S1UBHD5JPSBEUJB.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_DefaultEnvironment/C/HO/3RUQHZ1ZTGI8CGO9HV8WM7.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_DefaultEnvironment/C/HO/3RUQHZ1ZTGI8CGO9HV8WM7.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/1/QO/C4A0OV2U50G2BCLNOTN4D7.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/1/QO/C4A0OV2U50G2BCLNOTN4D7.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/3/WP/I0BPL983SWH7N5M45UCLWT.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/3/WP/I0BPL983SWH7N5M45UCLWT.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/4/0S/K9BSHYULX4J3PIZMCMCJFN.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/4/0S/K9BSHYULX4J3PIZMCMCJFN.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/5/GR/L3XI6P8Z3MSWLGIRCTZEKZ.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/5/GR/L3XI6P8Z3MSWLGIRCTZEKZ.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/8/D8/0NV4RJDI6JJJH341KZ9UFO.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/8/D8/0NV4RJDI6JJJH341KZ9UFO.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/8/K8/9FQ5PNUKL2X2U5X483CHSW.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/8/K8/9FQ5PNUKL2X2U5X483CHSW.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/9/FK/LCA3QO39IEVSZ0UM7UW5X9.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/9/FK/LCA3QO39IEVSZ0UM7UW5X9.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/B/NK/4R1TYR48JUSXDQ2LGCHE75.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/B/NK/4R1TYR48JUSXDQ2LGCHE75.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/C/68/D5KDXR6EN0QFLBSLDZ5KEL.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/C/68/D5KDXR6EN0QFLBSLDZ5KEL.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/C/JJ/PAGXJ46ZRYWOU6043NCOD5.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/C/JJ/PAGXJ46ZRYWOU6043NCOD5.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/D/50/OL1PEWTMVIFPFTR85OE2Y8.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/D/50/OL1PEWTMVIFPFTR85OE2Y8.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/E/49/3H9O8BNIAG64RFVZKI1QSS.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/E/49/3H9O8BNIAG64RFVZKI1QSS.uasset
--------------------------------------------------------------------------------
/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/E/MJ/J8D4BFKTLH3OBFR4FRWYKY.uasset:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Content/__ExternalActors__/Sample_Maps/CRV_Nesting_Tests/E/MJ/J8D4BFKTLH3OBFR4FRWYKY.uasset
--------------------------------------------------------------------------------
/CtrlReferenceVisualizer.uplugin:
--------------------------------------------------------------------------------
1 | {
2 | "FileVersion": 3,
3 | "Version": 1,
4 | "VersionName": "1.0",
5 | "FriendlyName": "Ctrl Reference Visualizer",
6 | "Description": "Visualize references to actors & components in a level",
7 | "Category": "Other",
8 | "CreatedBy": "NTY.studio",
9 | "CreatedByURL": "https://nty.studio",
10 | "DocsURL": "https://github.com/ntystudio/CTRLReferenceVisualizer/blob/main/README.md",
11 | "MarketplaceURL": "",
12 | "CanContainContent": true,
13 | "IsBetaVersion": true,
14 | "IsExperimentalVersion": false,
15 | "EnabledByDefault": true,
16 | "Installed": true,
17 | "Modules": [
18 | {
19 | "Name": "CtrlReferenceVisualizer",
20 | "Type": "Editor",
21 | "LoadingPhase": "PostDefault"
22 | }
23 | ]
24 | }
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | =====================
3 |
4 | Copyright © 2024 NTY.studio
5 |
6 | Permission is hereby granted, free of charge, to any person
7 | obtaining a copy of this software and associated documentation
8 | files (the “Software”), to deal in the Software without
9 | restriction, including without limitation the rights to use,
10 | copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the
12 | Software is furnished to do so, subject to the following
13 | conditions:
14 |
15 | The above copyright notice and this permission notice shall be
16 | included in all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 | OTHER DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CTRL Reference Visualizer is part of the [NTY.studio](https://www.nty.studio/) CTRL Framework, a library of utility plugins for Unreal Engine.
6 |
7 | ## Overview
8 | CTRL Reference Visualizer is an editor plugin for Unreal Engine 5 that enables level designers to see outgoing and incoming actor references for actors, components and objects in the world.
9 |
10 |
11 |
12 |
13 |
14 | See the plugin in action below:
15 |
16 |
17 | [](https://youtu.be/87IMYG2a7Qs?si=AoTZWZp94m92QSyj)
18 |
19 |
20 |
21 |
22 | ## Features
23 | - Visualize references between Actors, Components and Objects.
24 | - Filters to disable references to/from specific classes.
25 | - Customizable line colour settings.
26 |
27 |
28 |
29 | ## Prerequisites
30 | - Unreal Engine 5.4+
31 |
32 |
33 |
34 | ## Get Started
35 | Once CTRL Reference Visualizer is installed, you will see a new icon on the action bar above your editor window where you can enable/disable the plugin and access its settings.
36 |
37 |
38 |
39 |
40 |
41 | With the plugin enabled, selecting any actor will show the outgoing references by default.
42 |
43 | If you want to show incoming references too, you'll need to enable this in the plugin settings.
44 |
45 |
46 |
47 |
48 |
49 | You can also customize the reference line styles:
50 |
51 |
52 |
53 |
54 |
55 | ## Feedback
56 |
57 | If you come across an issue while using the plugin or have a suggestion to improve the plugin, feel free to [open an issue](https://github.com/ntystudio/CTRL-reference-visualizer/issues) or leave a post in our [discord server](https://discord.gg/ntystudio) (CTRL Framework section in discord below).
58 |
59 | 
60 |
61 |
62 |
63 | ## Contribution
64 | Contributions from the community are welcome! If you decide to to contribute, we ask that you:
65 | - Fork the repository
66 | - Create a new branch
67 | - Make your changes
68 | - Submit a pull request
69 |
70 |
71 |
72 | ## License
73 | This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details.
74 |
75 | ----
76 |
77 | > [!Tip]
78 | > # NTY Studio Plugins
79 | >
80 | > * [� Unicode Browser](https://github.com/ntystudio/UnicodeBrowser)
81 | > * [CTRL.StateTree](https://github.com/ntystudio/CTRL.StateTree)
82 | > * [CTRL.ReferenceVisualizer](https://github.com/ntystudio/CTRL.ReferenceVisualizer)
83 | > * [CTRL.Core](https://github.com/ntystudio/CTRL.Core)
84 | > * [CTRL.Gas](https://github.com/ntystudio/CTRL.Gas)
85 |
--------------------------------------------------------------------------------
/Resources/Icon128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Resources/Icon128.png
--------------------------------------------------------------------------------
/Resources/Icon16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ntystudio/CTRL.ReferenceVisualizer/d8f511bcf9f9b313b97a51c547d8b6e369e82315/Resources/Icon16.png
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/CtrlReferenceVisualizer.Build.cs:
--------------------------------------------------------------------------------
1 | using UnrealBuildTool;
2 |
3 | public class CtrlReferenceVisualizer : ModuleRules
4 | {
5 | public CtrlReferenceVisualizer(ReadOnlyTargetRules Target) : base(Target)
6 | {
7 | PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
8 | IncludeOrderVersion = EngineIncludeOrderVersion.Latest;
9 | #if UE_5_2_OR_LATER
10 | IWYUSupport = IWYUSupport.Full;
11 | #else
12 | bEnforceIWYU = true;
13 | #endif
14 | CppStandard = CppStandardVersion.Cpp20;
15 |
16 | PublicIncludePaths.AddRange(
17 | new string[]
18 | {
19 | }
20 | );
21 |
22 | PrivateIncludePaths.AddRange(
23 | new string[]
24 | {
25 | }
26 | );
27 |
28 | PublicDependencyModuleNames.AddRange(
29 | new[]
30 | {
31 | "Core",
32 | "CoreUObject",
33 | "Engine",
34 | "DeveloperSettings",
35 | "RenderCore",
36 | "RHI",
37 | "Slate",
38 | "SlateCore",
39 | "UMG",
40 | "Paper2D"
41 | }
42 | );
43 |
44 | // PublicDependencyModuleNames.AddRange(
45 | // new string[] {
46 | // "Core",
47 | // "CoreUObject",
48 | // "Engine",
49 | // "RHI",
50 | // "SlateCore",
51 | // "Slate",
52 | // "NavigationSystem"
53 | // }
54 | // );
55 | //
56 | // PrivateDependencyModuleNames.AddRange(
57 | // new string[] {
58 | // }
59 | // );
60 | //
61 | // if (Target.bBuildEditor == true)
62 | // {
63 | // //@TODO: Needed for the triangulation code used for sprites (but only in editor mode)
64 | // //@TOOD: Try to move the code dependent on the triangulation code to the editor-only module
65 | // PrivateDependencyModuleNames.Add("EditorFramework");
66 | // PrivateDependencyModuleNames.Add("UnrealEd");
67 | // }
68 |
69 | PrivateDependencyModuleNames.AddRange(
70 | new string[]
71 | {
72 | "AssetTools",
73 | "Engine",
74 | "GameplayTags",
75 | "InputCore",
76 | "Json",
77 | "LevelEditor",
78 | "EditorSubsystem",
79 | "EditorFramework",
80 | "Renderer",
81 | "RenderCore",
82 | "TypedElementRuntime",
83 | "TypedElementFramework",
84 | "ToolMenus",
85 | "UnrealEd"
86 | }
87 | );
88 |
89 | DynamicallyLoadedModuleNames.AddRange(
90 | new string[]
91 | {
92 | }
93 | );
94 | }
95 | }
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Private/CrvCommands.cpp:
--------------------------------------------------------------------------------
1 | #include "CrvCommands.h"
2 |
3 | #include "CrvSettings.h"
4 |
5 | #define LOCTEXT_NAMESPACE "ReferenceVisualizer"
6 |
7 | void FCrvCommands::ToggleEnabled_Execute()
8 | {
9 | const auto Settings = GetMutableDefault();
10 | Settings->ToggleEnabled();
11 | }
12 |
13 | bool FCrvCommands::ToggleEnabled_CanExecute()
14 | {
15 | return true;
16 | }
17 |
18 | bool FCrvCommands::ToggleEnabled_IsChecked()
19 | {
20 | const auto Settings = GetDefault();
21 | return Settings->bIsEnabled;
22 | }
23 |
24 | void FCrvCommands::RegisterCommands()
25 | {
26 | UI_COMMAND(
27 | ToggleReferenceVisualizer,
28 | "Reference Visualizer",
29 | "Toggle Reference Visualizer",
30 | EUserInterfaceActionType::ToggleButton,
31 | FInputChord()
32 | );
33 |
34 | if (CommandList.IsValid())
35 | {
36 | return;
37 | }
38 |
39 | CommandList = MakeShareable(new FUICommandList);
40 | CommandList->MapAction(
41 | ToggleReferenceVisualizer,
42 | FExecuteAction::CreateRaw(this, &FCrvCommands::ToggleEnabled_Execute),
43 | FCanExecuteAction::CreateRaw(this, &FCrvCommands::ToggleEnabled_CanExecute),
44 | FIsActionChecked::CreateRaw(this, &FCrvCommands::ToggleEnabled_IsChecked)
45 | );
46 | }
47 |
48 | #undef LOCTEXT_NAMESPACE
49 |
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Private/CrvComponent.cpp:
--------------------------------------------------------------------------------
1 | #include "ReferenceVisualizerComponent.h"
2 |
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Private/CrvDrawUtils.cpp:
--------------------------------------------------------------------------------
1 | // Fill out your copyright notice in the Description page of Project Settings.
2 |
3 | #include "CrvDrawUtils.h"
4 |
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Private/CrvDrawUtils.h:
--------------------------------------------------------------------------------
1 | // Fill out your copyright notice in the Description page of Project Settings.
2 |
3 | #pragma once
4 |
5 | #include "CoreMinimal.h"
6 | #include "Kismet/BlueprintFunctionLibrary.h"
7 | #include "CrvDrawUtils.generated.h"
8 |
9 | /**
10 | *
11 | */
12 | UCLASS()
13 | class CTRLREFERENCEVISUALIZER_API UCrvDrawUtils : public UBlueprintFunctionLibrary
14 | {
15 | GENERATED_BODY()
16 | };
17 |
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Private/CrvHitProxy.cpp:
--------------------------------------------------------------------------------
1 | #include "CrvHitProxy.h"
2 |
3 | IMPLEMENT_HIT_PROXY(HCrvHitProxy, HComponentVisProxy);
4 |
5 | #define LOCTEXT_NAMESPACE "ReferenceVisualizer"
6 |
7 | #undef LOCTEXT_NAMESPACE
8 |
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Private/CrvRefCache.cpp:
--------------------------------------------------------------------------------
1 | #include "CrvRefCache.h"
2 |
3 | #include "CrvRefSearch.h"
4 | #include "CrvSettings.h"
5 | #include "CrvUtils.h"
6 | #include "CtrlReferenceVisualizer.h"
7 | #include "Algo/AnyOf.h"
8 |
9 | #define LOCTEXT_NAMESPACE "ReferenceVisualizer"
10 |
11 | using namespace CtrlRefViz;
12 |
13 | bool UCrvRefCache::HasValues() const
14 | {
15 | return WeakRootObjects.Num() > 0 || Outgoing.Num() > 0 || Incoming.Num() > 0;
16 | }
17 |
18 | void UCrvRefCache::Reset(const FString& Reason)
19 | {
20 | bCached = false;
21 | bHadValidItems = false;
22 | WeakRootObjects.Reset();
23 | Outgoing.Reset();
24 | Incoming.Reset();
25 | UE_CLOG(FCrvModule::IsDebugEnabled(), LogCrv, Log, TEXT("Cache reset... %s"), *Reason);
26 | }
27 |
28 | void UCrvRefCache::Invalidate(const FString& Reason)
29 | {
30 | UE_CLOG(FCrvModule::IsDebugEnabled(), LogCrv, Log, TEXT("Invalidating cache..."));
31 | Reset(Reason);
32 | ScheduleUpdate();
33 | }
34 |
35 | bool UCrvRefCache::Contains(const UObject* Object) const
36 | {
37 | return WeakRootObjects.Contains(Object);
38 | }
39 |
40 | TSet UCrvRefCache::GetReferences(const UObject* Object, const ECrvDirection Direction)
41 | {
42 | static TSet Empty;
43 | if (!Contains(Object)) { return Empty; }
44 | const auto Cached = GetValidCached(Direction);
45 | if (const auto Found = Cached.Find(Object))
46 | {
47 | return *Found;
48 | } else
49 | {
50 | return Empty;
51 | }
52 | }
53 |
54 | FCrvSet UCrvRefCache::GenerateAllRootObjects()
55 | {
56 | FCrvSet All;
57 | for (TObjectIterator It; It; ++It)
58 | {
59 | if (const auto Item = *It)
60 | {
61 | if (Item->HasAnyFlags(RF_ClassDefaultObject))
62 | {
63 | continue;
64 | }
65 | if (const auto Owner = Item->GetOwner())
66 | {
67 | All.Add(Owner);
68 | }
69 | }
70 | }
71 | return MoveTemp(All);
72 | }
73 |
74 | FCrvSet UCrvRefCache::GenerateRootObjects()
75 | {
76 | static FCrvSet Empty;
77 | switch (GetDefault()->Mode)
78 | {
79 | case ECrvMode::OnlySelected:
80 | {
81 | return FCrvRefSearch::GetSelectionSet();
82 | }
83 | case ECrvMode::SelectedOrAll:
84 | {
85 | auto SelectionSet = FCrvRefSearch::GetSelectionSet();
86 | if (SelectionSet.Num() > 0)
87 | {
88 | return MoveTemp(SelectionSet);
89 | }
90 | return GenerateAllRootObjects();
91 | }
92 | case ECrvMode::All:
93 | {
94 | return GenerateAllRootObjects();
95 | }
96 | default:
97 | {
98 | return Empty;
99 | }
100 | }
101 | }
102 |
103 | void UCrvRefCache::UpdateCache()
104 | {
105 | GEditor->GetTimerManager()->ClearTimer(UpdateCacheNextTickHandle);
106 | FillCache(GenerateRootObjects());
107 | }
108 |
109 | void UCrvRefCache::ScheduleUpdate()
110 | {
111 | GEditor->GetTimerManager()->ClearTimer(UpdateCacheNextTickHandle);
112 | auto WeakThis = TWeakObjectPtr(this);
113 | UpdateCacheNextTickHandle = GEditor->GetTimerManager()->SetTimerForNextTick([WeakThis]()
114 | {
115 | if (WeakThis.IsValid())
116 | {
117 | WeakThis->UpdateCache();
118 | }
119 | });
120 | }
121 |
122 | FCrvObjectGraph UCrvRefCache::GetValidCached(const ECrvDirection Direction)
123 | {
124 | static FCrvObjectGraph Empty;
125 | if (!bCached) { return Empty; }
126 |
127 | const auto Cached = Direction == ECrvDirection::Outgoing ? Outgoing : Incoming;
128 | bool bFoundInvalid = false;
129 | auto ValidCached = ResolveWeakGraph(Cached, bFoundInvalid);
130 | if (bFoundInvalid)
131 | {
132 | Invalidate(FString::Printf(TEXT("Invalid %s references"), Direction == ECrvDirection::Outgoing ? TEXT("Outgoing") : TEXT("Incoming")));
133 | }
134 | return MoveTemp(ValidCached);
135 | }
136 |
137 |
138 | bool HasValidItems(const FCrvWeakGraph& CachedItems)
139 | {
140 | for (const auto& [WeakObject, Items] : CachedItems)
141 | {
142 | if (!WeakObject.IsValid())
143 | {
144 | continue;
145 | }
146 |
147 | if (Items.Num() > 0)
148 | {
149 | if (Algo::AnyOf(Items, [](const TWeakObjectPtr& Item) { return Item.IsValid(); }))
150 | {
151 | return true;
152 | }
153 | }
154 | }
155 | return false;
156 | }
157 |
158 | void UCrvRefCache::AutoAddComponents(const FCrvSet& InRootObjects)
159 | {
160 | const auto bAutoAddComponents = GetDefault()->GetAutoAddComponents();
161 | if (!bAutoAddComponents && AutoCreatedComponents.Num() == 0) { return; }
162 | // Remove Components
163 | {
164 | TSet ToRemove;
165 | auto CurrentAutoCreatedComponents = AutoCreatedComponents;
166 | for (auto Item : CurrentAutoCreatedComponents)
167 | {
168 | if (!Item.IsValid())
169 | {
170 | AutoCreatedComponents.Remove(Item);
171 | bCached = false;
172 | continue;
173 | }
174 |
175 | if (!bAutoAddComponents || !InRootObjects.Contains(Item->GetOwner()))
176 | {
177 | AutoCreatedComponents.Remove(Item);
178 | bCached = false;
179 | ToRemove.Add(Item.Get());
180 | }
181 | }
182 |
183 | for (const auto Item : ToRemove)
184 | {
185 | const auto Owner = Item->GetOwner();
186 | Owner->RemoveOwnedComponent(Item);
187 | if (IsValid(Item))
188 | {
189 | Item->DestroyComponent();
190 | }
191 | }
192 | }
193 |
194 | if (!bAutoAddComponents) { return; }
195 | auto AddComponent = [this](AActor* Actor)
196 | {
197 | if (Actor->FindComponentByClass())
198 | {
199 | return; // already has component
200 | }
201 | bCached = false;
202 | auto* DebugComponent = Cast(
203 | Actor->AddComponentByClass(
204 | UReferenceVisualizerComponent::StaticClass(),
205 | false,
206 | FTransform::Identity,
207 | false
208 | )
209 | );
210 |
211 | if (!DebugComponent) { return; }
212 | AutoCreatedComponents.Add(DebugComponent);
213 | Actor->AddOwnedComponent(DebugComponent);
214 | if (!DebugComponent->IsRegistered())
215 | {
216 | DebugComponent->RegisterComponent();
217 | }
218 | };
219 |
220 | for (const auto Item : InRootObjects)
221 | {
222 | ensure(Item != nullptr);
223 | if (const auto Actor = Cast(Item))
224 | {
225 | AddComponent(Actor);
226 | }
227 | else if (auto OuterActor = Item->GetTypedOuter())
228 | {
229 | AddComponent(OuterActor);
230 | }
231 | }
232 | }
233 |
234 | void UCrvRefCache::FillCache(const FCrvSet& InRootObjects)
235 | {
236 | if (bCached && !AreSetsEqual(ResolveWeakSet(WeakRootObjects), InRootObjects))
237 | {
238 | Reset(FString::Printf(TEXT("FillCache: RootObjects Changed")));
239 | }
240 |
241 | const auto Config = GetDefault();
242 | AutoAddComponents(InRootObjects);
243 | WeakRootObjects = ToWeakSet(InRootObjects);
244 | WeakRootObjects.Compact();
245 | const auto RootObjects = InRootObjects;
246 |
247 | if (bCached)
248 | {
249 | UE_CLOG(FCrvModule::IsDebugEnabled(), LogCrv, Log, TEXT("Cache already filled. RootObjects: %d, Outgoing: %d, Incoming: %d"), RootObjects.Num(), Outgoing.Num(), Incoming.Num());
250 | return;
251 | }
252 |
253 | if (Config->bShowOutgoingReferences)
254 | {
255 | FCrvObjectGraph OutRefs;
256 | FCrvRefSearch::FindOutRefs(RootObjects, OutRefs);
257 | Outgoing = ToWeakGraph(OutRefs);
258 | Outgoing.Compact();
259 | }
260 | else
261 | {
262 | Outgoing.Reset();
263 | }
264 |
265 | if (Config->bShowIncomingReferences)
266 | {
267 | FCrvObjectGraph InRefs;
268 | FCrvRefSearch::FindInRefs(RootObjects, InRefs);
269 | Incoming = ToWeakGraph(InRefs);
270 | Incoming.Compact();
271 | }
272 | else
273 | {
274 | Incoming.Reset();
275 | }
276 |
277 | if (!bHadValidItems)
278 | {
279 | bHadValidItems = HasValidItems(Outgoing) || HasValidItems(Incoming);
280 | }
281 |
282 | if (OnCacheUpdated.IsBound())
283 | {
284 | OnCacheUpdated.Broadcast();
285 | }
286 |
287 | bCached = HasValues();
288 | UE_CLOG(FCrvModule::IsDebugEnabled(), LogCrv, Log, TEXT("Cache filled: RootObjects: %d, Outgoing: %d, Incoming: %d"), RootObjects.Num(), Outgoing.Num(), Incoming.Num());
289 | }
290 |
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Private/CrvRefCache.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "CoreMinimal.h"
4 | #include "CrvHitProxy.h"
5 | #include "CrvSettings.h"
6 | #include "CrvUtils.h"
7 | #include "CtrlReferenceVisualizer.h"
8 | #include "CrvRefCache.generated.h"
9 |
10 | class UReferenceVisualizerComponent;
11 | using namespace CtrlRefViz;
12 |
13 | UCLASS(Transient, Hidden)
14 | class UCrvRefCache : public UObject
15 | {
16 | GENERATED_BODY()
17 | public:
18 | static FCrvSet GenerateRootObjects();
19 | static FCrvSet GenerateAllRootObjects();
20 |
21 | bool HasValues() const;
22 | bool Contains(const UObject* Object) const;
23 |
24 | void FillCache(const FCrvSet& InRootObjects);
25 | void Reset(const FString& String);
26 | // reset + schedule update
27 | void Invalidate(const FString& Reason);
28 |
29 | // Get all incoming/outgoing references for a given object
30 | TSet GetReferences(const UObject* Object, ECrvDirection Direction);
31 | FCrvObjectGraph GetValidCached(ECrvDirection Direction);
32 |
33 | void UpdateCache();
34 | void ScheduleUpdate();
35 |
36 | FCrvWeakGraph Outgoing;
37 | FCrvWeakGraph Incoming;
38 | // Objects we want to find references for
39 | UPROPERTY(Transient)
40 | TSet> WeakRootObjects;
41 | void AutoAddComponents(const FCrvSet& InRootObjects);
42 |
43 | bool bCached = false;
44 | bool bHadValidItems = false;
45 |
46 | DECLARE_MULTICAST_DELEGATE(FOnCacheUpdated)
47 | FOnCacheUpdated OnCacheUpdated;
48 | protected:
49 | UPROPERTY(Transient)
50 | TSet> AutoCreatedComponents;
51 | private:
52 | FTimerHandle UpdateCacheNextTickHandle;
53 | };
54 |
55 | struct FCrvHitProxyRef
56 | {
57 | FHitProxyId Id;
58 | TWeakObjectPtr LeafObject;
59 | TWeakObjectPtr RootObject;
60 |
61 | bool IsValid() const
62 | {
63 | return Id != FHitProxyId() && LeafObject.IsValid() && RootObject.IsValid();
64 | }
65 |
66 | FCrvHitProxyRef(HCrvHitProxy* HitProxy)
67 | : Id(HitProxy->Id),
68 | LeafObject(HitProxy->LeafObject),
69 | RootObject(HitProxy->RootObject) {}
70 | };
71 |
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Private/CrvRefSearch.cpp:
--------------------------------------------------------------------------------
1 | #include "CrvRefSearch.h"
2 |
3 | #include "CrvSettings.h"
4 | #include "CrvUtils.h"
5 | #include "CtrlReferenceVisualizer.h"
6 | #include "ReferenceVisualizerComponent.h"
7 | #include "Selection.h"
8 |
9 | #include "Styling/SlateIconFinder.h"
10 |
11 | #include "UObject/ReferenceChainSearch.h"
12 | #include "UObject/ReferencerFinder.h"
13 |
14 | using namespace CtrlRefViz;
15 |
16 | namespace CtrlRefViz::Search
17 | {
18 | bool IsExternal(const FReferenceChainSearch::FReferenceChain* Chain)
19 | {
20 | if (Chain == nullptr)
21 | {
22 | return false;
23 | }
24 |
25 | if (Chain->Num() > 1)
26 | {
27 | // Reference is external if the root (the last node) is not in the first node (target)
28 | return !Chain->GetRootNode()->ObjectInfo->IsIn(Chain->GetNode(0)->ObjectInfo);
29 | }
30 | else
31 | {
32 | return false;
33 | }
34 | }
35 |
36 | template
37 | void TryAddValue(FCrvSet& Found, T PropValue)
38 | {
39 | if (!PropValue.IsValid()) { return; }
40 | Found.Add(PropValue.Get());
41 | }
42 |
43 | TArray FindSoftObjectReferences(const UObject* RootObject)
44 | {
45 | if (!IsValid(RootObject)) { return {}; }
46 | const auto Settings = GetDefault();
47 | FCrvSet Found;
48 | if (Settings->bWalkObjectProperties && RootObject->GetClass())
49 | {
50 | for (TFieldIterator PropIt(RootObject->GetClass(), EFieldIterationFlags::IncludeSuper); PropIt; ++PropIt)
51 | {
52 | if (const auto SoftObjectProperty = CastField(*PropIt))
53 | {
54 | TryAddValue(Found, SoftObjectProperty->GetPropertyValue_InContainer(RootObject));
55 | }
56 | else if (const auto WeakObjectProperty = CastField(*PropIt))
57 | {
58 | TryAddValue(Found, WeakObjectProperty->GetPropertyValue_InContainer(RootObject));
59 | }
60 | else if (const auto LazyObjectProperty = CastField(*PropIt))
61 | {
62 | TryAddValue(Found, LazyObjectProperty->GetPropertyValue_InContainer(RootObject));
63 | }
64 | }
65 | }
66 | return Found.Array();
67 | }
68 |
69 | FCrvSet FindOwnedObjects(FCrvSet Targets)
70 | {
71 | const auto CrvSettings = GetDefault();
72 | TArray Owned;
73 | for (const auto Target : Targets)
74 | {
75 | FReferenceFinder RefFinder(
76 | Owned,
77 | Target,
78 | false,
79 | CrvSettings->bIgnoreArchetype,
80 | CrvSettings->bIsRecursive,
81 | CrvSettings->bIgnoreTransient
82 | );
83 | RefFinder.FindReferences(Target);
84 | }
85 |
86 | return TSet(Owned);
87 | }
88 |
89 | FCrvSet FindOwnedObjects(UObject* Target)
90 | {
91 | const auto CrvSettings = GetDefault();
92 | TArray Owned;
93 | FReferenceFinder RefFinder(
94 | Owned,
95 | Target,
96 | false,
97 | CrvSettings->bIgnoreArchetype,
98 | CrvSettings->bIsRecursive,
99 | CrvSettings->bIgnoreTransient
100 | );
101 |
102 | RefFinder.FindReferences(Target);
103 | return TSet(Owned);
104 | }
105 |
106 | #pragma region GetObjectFlagsString
107 | FString GetObjectFlagsString(const UObject* InObject)
108 | {
109 | if (!InObject)
110 | {
111 | return FString("");
112 | }
113 | TArray Flags;
114 | if (!IsValid(InObject))
115 | {
116 | Flags.Add(TEXT("Invalid"));
117 | }
118 | if (InObject->IsRooted())
119 | {
120 | Flags.Add(TEXT("Root"));
121 | }
122 |
123 | if (InObject->HasAnyFlags(RF_ClassDefaultObject))
124 | {
125 | Flags.Add(TEXT("CDO"));
126 | }
127 |
128 | if (InObject->HasAnyFlags(RF_Transient))
129 | {
130 | Flags.Add(TEXT("Transient"));
131 | }
132 | if (InObject->HasAnyFlags(RF_Public))
133 | {
134 | Flags.Add(TEXT("Public"));
135 | }
136 | if (InObject->HasAnyFlags(RF_Standalone))
137 | {
138 | Flags.Add(TEXT("Standalone"));
139 | }
140 | if (InObject->HasAnyFlags(RF_NeedLoad))
141 | {
142 | Flags.Add(TEXT("NeedLoad"));
143 | }
144 | if (InObject->HasAnyFlags(RF_NeedPostLoad))
145 | {
146 | Flags.Add(TEXT("NeedPostLoad"));
147 | }
148 | if (InObject->HasAnyFlags(RF_NeedPostLoadSubobjects))
149 | {
150 | Flags.Add(TEXT("NeedPostLoadSubobjects"));
151 | }
152 | if (InObject->HasAnyFlags(RF_WasLoaded))
153 | {
154 | Flags.Add(TEXT("WasLoaded"));
155 | }
156 |
157 | CA_SUPPRESS(6011)
158 | if (InObject->IsNative())
159 | {
160 | Flags.Add(TEXT("Native"));
161 | }
162 |
163 | if (InObject->HasAnyInternalFlags(EInternalObjectFlags::Garbage))
164 | {
165 | Flags.Add(TEXT("Garbage"));
166 | }
167 |
168 | if (InObject->HasAnyInternalFlags(EInternalObjectFlags::Async))
169 | {
170 | Flags.Add(TEXT("Async"));
171 | }
172 |
173 | if (InObject->HasAnyInternalFlags(EInternalObjectFlags::AsyncLoading))
174 | {
175 | Flags.Add(TEXT("AsyncLoading"));
176 | }
177 |
178 | return FString::Printf(TEXT("%s"), *FString::Join(Flags, TEXT(", ")));
179 | }
180 | #pragma endregion GetObjectFlagsString
181 | }
182 |
183 | FCrvMenuItem FCrvRefSearch::MakeMenuEntry(const UObject* Parent, const UObject* Object)
184 | {
185 | static FCrvMenuItem Empty;
186 | if (!Object)
187 | {
188 | return Empty;
189 | }
190 | const auto FlagsString = Search::GetObjectFlagsString(Object);
191 | const auto PackageShortName = FPackageName::GetShortName(Object->GetPackage()->GetName());
192 | auto Tooltip = FString::Printf(TEXT("%s\nPath: %s\nPkgName: %s\nFlags: %s"), *GetDebugName(Object), *GetPathNameSafe(Object), *PackageShortName, *FlagsString);
193 | if (const auto OuterActor = Object->GetTypedOuter())
194 | {
195 | if (OuterActor != Object)
196 | {
197 | Tooltip += FString::Printf(TEXT("\nOuterActor: %s"), *OuterActor->GetActorNameOrLabel());
198 | }
199 | }
200 | if (const auto OuterComponent = Object->GetTypedOuter())
201 | {
202 | if (OuterComponent != Object)
203 | {
204 | Tooltip += FString::Printf(TEXT("\nOuterComponent: %s"), *OuterComponent->GetReadableName());
205 | }
206 | }
207 |
208 | if (const auto Actor = Cast(Object))
209 | {
210 | const auto Label = FText::FromString(FString::Printf(TEXT("%s"), *Actor->GetActorNameOrLabel()));
211 | const auto ActorTooltip = FText::FromString(FString::Printf(TEXT("%ls\nGuid: %s"), *Tooltip, *Actor->GetActorInstanceGuid().ToString()));
212 | return {
213 | Actor->GetFName(),
214 | Label,
215 | ActorTooltip,
216 | FSlateIconFinder::FindIconForClass(Actor->GetClass()),
217 | FUIAction(
218 | FExecuteAction::CreateWeakLambda(
219 | Actor,
220 | [Actor]()
221 | {
222 | FCrvModule::Get().SelectReference(const_cast(Actor));
223 | }
224 | )
225 | )
226 | };
227 | }
228 | else if (const auto Component = Cast(Object))
229 | {
230 | const auto Label = FText::FromString(FString::Printf(TEXT("%s"), *Component->GetReadableName()));
231 | return {
232 | Component->GetFName(),
233 | Label,
234 | FText::FromString(Tooltip),
235 | FSlateIconFinder::FindIconForClass(Component->GetClass()),
236 | FUIAction(
237 | FExecuteAction::CreateWeakLambda(
238 | Component,
239 | [Component]()
240 | {
241 | FCrvModule::Get().SelectReference(const_cast(Component));
242 | }
243 | )
244 | )
245 | };
246 | }
247 |
248 | return {
249 | Object->GetFName(),
250 | FText::FromString(Object->GetName()),
251 | FText::FromString(Tooltip),
252 | FSlateIconFinder::FindIconForClass(Object->GetClass()),
253 | FUIAction()
254 | };
255 | }
256 |
257 | bool IsObjectProperty(const FProperty* InProperty)
258 | {
259 | return CastField(InProperty) != nullptr;
260 | }
261 |
262 | #pragma region CanDisplayReference
263 | bool FCrvRefSearch::CanDisplayReference(const UObject* RootObject, const UObject* LeafObject)
264 | {
265 | if (!IsValid(LeafObject))
266 | {
267 | return false;
268 | }
269 | if (!IsValid(RootObject))
270 | {
271 | return false;
272 | }
273 | if (LeafObject == RootObject)
274 | {
275 | return false;
276 | }
277 | if (LeafObject->IsA())
278 | {
279 | return false;
280 | }
281 | if (LeafObject->IsA())
282 | {
283 | return false;
284 | }
285 | if (LeafObject->IsA())
286 | {
287 | return false;
288 | }
289 | if (LeafObject->IsA())
290 | {
291 | return false;
292 | }
293 | if (LeafObject->IsA())
294 | {
295 | return false;
296 | }
297 |
298 | const auto CrvSettings = GetDefault();
299 |
300 | // hide references to self...
301 | if (LeafObject->IsInOuter(RootObject))
302 | {
303 | // unless it's an actor (e.g. child actor)
304 | if (!LeafObject->IsA())
305 | {
306 | return false;
307 | }
308 | }
309 |
310 | if (CrvSettings->bIgnoreTransient && LeafObject->HasAnyFlags(RF_Transient))
311 | {
312 | return false;
313 | }
314 | if (CrvSettings->bIgnoreArchetype && LeafObject->HasAnyFlags(RF_ArchetypeObject))
315 | {
316 | return false;
317 | }
318 | if (CrvSettings->TargetSettings.IgnoreReferencesToClasses.Contains(LeafObject->GetClass()))
319 | {
320 | return false;
321 | }
322 | if (LeafObject->IsA())
323 | {
324 | return true;
325 | }
326 |
327 | if (LeafObject->IsA())
328 | {
329 | return CrvSettings->bShowComponents;
330 | }
331 |
332 | return CrvSettings->bShowObjects;
333 | }
334 | #pragma endregion CanDisplayReference
335 |
336 | FCrvSet FCrvRefSearch::GetSelectionSet()
337 | {
338 | TArray SelectedActors;
339 | TArray SelectedComponents;
340 | GEditor->GetSelectedActors()->GetSelectedObjects(SelectedActors);
341 | GEditor->GetSelectedComponents()->GetSelectedObjects(SelectedComponents);
342 | FCrvSet Selected;
343 | Selected.Append(SelectedActors);
344 | Selected.Append(SelectedComponents);
345 |
346 | FCrvSet SelectedSet;
347 | SelectedSet.Append(Selected);
348 | return MoveTemp(SelectedSet);
349 | }
350 |
351 | static auto GetCanDisplayReference(UObject* RootObject)
352 | {
353 | return [RootObject](const UObject* LeafObject)
354 | {
355 | return FCrvRefSearch::CanDisplayReference(RootObject, LeafObject);
356 | };
357 | }
358 |
359 | FCrvSet Search::FindTargetObjects(UObject* RootObject)
360 | {
361 | static FCrvSet Empty;
362 | if (!IsValid(RootObject)) { return Empty; }
363 | FCrvSet TargetObjects;
364 | TargetObjects.Append(Search::FindOwnedObjects(RootObject));
365 | TargetObjects.Add(RootObject);
366 | return MoveTemp(TargetObjects);
367 | }
368 |
369 | void FCrvRefSearch::FindOutRefs(FCrvSet RootObjects, FCrvObjectGraph& Graph)
370 | {
371 | auto* const CrvSettings = GetDefault();
372 | Graph.Reserve(RootObjects.Num());
373 | Graph.Reset();
374 | for (auto RootObject : RootObjects)
375 | {
376 | FCrvSet RootObjectReferences;
377 | const auto TargetObjects = Search::FindTargetObjects(RootObject);
378 | for (const auto TargetObject : TargetObjects)
379 | {
380 | TArray NewItemsArray;
381 | FReferenceFinder RefFinder(
382 | NewItemsArray,
383 | nullptr,
384 | false,
385 | CrvSettings->bIgnoreArchetype,
386 | CrvSettings->bIsRecursive,
387 | CrvSettings->bIgnoreTransient
388 | );
389 | RefFinder.FindReferences(TargetObject);
390 | RootObjectReferences.Append(NewItemsArray.FilterByPredicate(GetCanDisplayReference(RootObject)));
391 | }
392 | for (const auto TargetObject : TargetObjects)
393 | {
394 | if (CrvSettings->bWalkObjectProperties)
395 | {
396 | RootObjectReferences.Append(Search::FindSoftObjectReferences(TargetObject).FilterByPredicate(GetCanDisplayReference(RootObject)));
397 | }
398 | }
399 | Graph.Add(RootObject, RootObjectReferences);
400 | }
401 | }
402 |
403 | bool ChainContains(const FReferenceChainSearch::FReferenceChain* Chain, const UObject* Object)
404 | {
405 | if (!Chain)
406 | {
407 | return false;
408 | }
409 | if (const auto Root = Chain->GetRootNode()->ObjectInfo->TryResolveObject())
410 | {
411 | if (Root == Object)
412 | {
413 | return true;
414 | }
415 | }
416 |
417 | for (int32 i = 0; i < Chain->Num(); i++)
418 | {
419 | if (Chain->GetNode(i)->ObjectInfo->TryResolveObject() == Object)
420 | {
421 | return true;
422 | }
423 | }
424 | return false;
425 | }
426 |
427 | void FCrvRefSearch::FindInRefs(FCrvSet RootObjects, FCrvObjectGraph& Graph)
428 | {
429 | Graph.Reserve(RootObjects.Num());
430 | for (auto RootObject : RootObjects)
431 | {
432 | auto TargetObjects = Search::FindTargetObjects(RootObject);
433 | auto Referencers = FReferencerFinder::GetAllReferencers(TargetObjects, nullptr, EReferencerFinderFlags::SkipInnerReferences);
434 | auto Filtered = Referencers.FilterByPredicate(GetCanDisplayReference(RootObject));
435 | Graph.Add(RootObject, TSet(Filtered));
436 | }
437 | }
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Private/CrvSampleFloorBase.h:
--------------------------------------------------------------------------------
1 | // Fill out your copyright notice in the Description page of Project Settings.
2 |
3 | #pragma once
4 |
5 | #include "CrvUtils.h"
6 | #include "CtrlReferenceVisualizer.h"
7 | #include "Components/TextRenderComponent.h"
8 | #include "Kismet/BlueprintFunctionLibrary.h"
9 | #include "CrvSampleFloorBase.generated.h"
10 |
11 | UENUM(meta=(Bitflags, UseEnumValuesAsMaskValuesInEditor = "true"))
12 | enum class ECrvHorizontalDirection: uint32
13 | {
14 | None = 0,
15 | North = 1 << 0,
16 | NorthEast = 1 << 1,
17 | East = 1 << 2,
18 | SouthEast = 1 << 3,
19 | South = 1 << 4,
20 | SouthWest = 1 << 5,
21 | West = 1 << 6,
22 | NorthWest = 1 << 7,
23 | Middle = 1 << 8,
24 | All = North | NorthEast | East | SouthEast | South | SouthWest | West | NorthWest | Middle,
25 | };
26 |
27 | ENUM_CLASS_FLAGS(ECrvHorizontalDirection);
28 |
29 | constexpr bool EnumHasAnyFlags(const int32 Flags, ECrvHorizontalDirection Contains) { return (Flags & static_cast(Contains)) != 0; }
30 |
31 | /**
32 | * Base class for sample floor.
33 | * Handles neatly auto-positioning heading text.
34 | * Ok to scale floor to change floor size.
35 | */
36 | UCLASS(Blueprintable, BlueprintType, ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
37 | class ACrvSampleFloorBase : public AActor
38 | {
39 | GENERATED_BODY()
40 |
41 | public:
42 | ACrvSampleFloorBase()
43 | {
44 | SceneRoot = CreateDefaultSubobject(TEXT("SceneRoot"));
45 | RootComponent = SceneRoot;
46 | FloorMesh = CreateDefaultSubobject(TEXT("FloorMesh"));
47 | FloorMesh->SetupAttachment(RootComponent);
48 | SampleHeading = CreateDefaultSubobject(TEXT("SampleHeading"));
49 | SampleHeading->SetupAttachment(RootComponent);
50 | Update();
51 | }
52 |
53 | // position heading if auto position is enabled
54 | UFUNCTION(BlueprintCallable)
55 | void AutoPositionHeading() const
56 | {
57 | if (!bAutoPositionHeading) { return; }
58 | PositionHeading();
59 | }
60 |
61 | UFUNCTION(BlueprintCallable, CallInEditor)
62 | void PositionHeading() const
63 | {
64 | FVector Min, Max;
65 | FloorMesh->GetLocalBounds(Min, Max);
66 | // rotate text to look up
67 | SampleHeading->SetRelativeRotation(FRotator(90, 180, 0));
68 | // bottom left corner
69 | const auto NewLocation = GetCoordinate(ECrvHorizontalDirection::SouthWest);
70 | SampleHeading->SetRelativeLocation(NewLocation);
71 | OnSampleFloorBaseUpdated.Broadcast(Min, Max);
72 | }
73 |
74 | UFUNCTION(BlueprintCallable)
75 | FVector GetCoordinate(const ECrvHorizontalDirection Direction) const
76 | {
77 | FVector Min, Max;
78 | FloorMesh->GetLocalBounds(Min, Max);
79 | switch (Direction)
80 | {
81 | case ECrvHorizontalDirection::North:
82 | return FVector((Max.X - Min.X) / 2, Max.Y - HeadingPadding.Y, Max.Z + HeadingPadding.Z) * FloorMesh->GetComponentScale();
83 | case ECrvHorizontalDirection::East:
84 | return FVector(Max.X - HeadingPadding.X, (Max.Y - Min.Y) / 2, Max.Z + HeadingPadding.Z) * FloorMesh->GetComponentScale();
85 | case ECrvHorizontalDirection::West:
86 | return FVector(Min.X + HeadingPadding.X, (Max.Y - Min.Y) / 2, Max.Z + HeadingPadding.Z) * FloorMesh->GetComponentScale();
87 | case ECrvHorizontalDirection::South:
88 | return FVector((Max.X - Min.X) / 2, Min.Y + HeadingPadding.Y, Max.Z + HeadingPadding.Z) * FloorMesh->GetComponentScale();
89 | case ECrvHorizontalDirection::SouthWest:
90 | return FVector(Min.X + HeadingPadding.X, Min.Y + HeadingPadding.Y, Max.Z + HeadingPadding.Z) * FloorMesh->GetComponentScale();
91 | case ECrvHorizontalDirection::SouthEast:
92 | return FVector(Max.X - HeadingPadding.X, Min.Y + HeadingPadding.Y, Max.Z + HeadingPadding.Z) * FloorMesh->GetComponentScale();
93 | case ECrvHorizontalDirection::NorthEast:
94 | return FVector(Max.X - HeadingPadding.X, Max.Y - HeadingPadding.Y, Max.Z + HeadingPadding.Z) * FloorMesh->GetComponentScale();
95 | case ECrvHorizontalDirection::NorthWest:
96 | return FVector(Min.X + HeadingPadding.X, Max.Y - HeadingPadding.Y, Max.Z + HeadingPadding.Z) * FloorMesh->GetComponentScale();
97 | case ECrvHorizontalDirection::None:
98 | case ECrvHorizontalDirection::Middle:
99 | case ECrvHorizontalDirection::All:
100 | default:
101 | UE_LOG(LogCrv, Warning, TEXT("%s Invalid direction %s"), *CRV_LOG_LINE, *UEnum::GetValueAsString(Direction));
102 | break;
103 | }
104 | return FVector::ZeroVector;
105 | }
106 |
107 | UFUNCTION(BlueprintCallable)
108 | void Update() const
109 | {
110 | SampleHeading->SetWorldSize(HeadingTextSize);
111 | SampleHeading->SetText(HeadingText);
112 | AutoPositionHeading();
113 | }
114 |
115 | protected:
116 | virtual void OnConstruction(const FTransform& Transform) override
117 | {
118 | Super::OnConstruction(Transform);
119 | if (SampleHeading == nullptr)
120 | {
121 | SampleHeading = NewObject(this);
122 | SampleHeading->SetupAttachment(RootComponent);
123 | }
124 | Update();
125 | }
126 |
127 | virtual void PostInitializeComponents() override
128 | {
129 | Super::PostInitializeComponents();
130 | Update();
131 | }
132 |
133 | #if WITH_EDITOR
134 | virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override
135 | {
136 | Super::PostEditChangeProperty(PropertyChangedEvent);
137 | Update();
138 | }
139 | #endif
140 |
141 | public:
142 | // exists so floor can be scaled independently of text
143 | UPROPERTY(BlueprintReadWrite, VisibleAnywhere)
144 | TObjectPtr SceneRoot = nullptr;
145 |
146 | UPROPERTY(BlueprintReadWrite, VisibleAnywhere)
147 | TObjectPtr FloorMesh = nullptr;
148 |
149 | UPROPERTY(BlueprintReadWrite, VisibleAnywhere)
150 | TObjectPtr SampleHeading = nullptr;
151 |
152 | /** e.g. name of sample */
153 | UPROPERTY(BlueprintReadWrite, EditAnywhere, meta=(ExposeOnSpawn="true"))
154 | FText HeadingText = FText::FromString("Sample");
155 |
156 | UPROPERTY(BlueprintReadWrite, EditAnywhere, meta=(ExposeOnSpawn="true"))
157 | float HeadingTextSize = 350.f;
158 |
159 | // disable to manually position heading
160 | UPROPERTY(BlueprintReadWrite, EditAnywhere)
161 | bool bAutoPositionHeading = true;
162 |
163 | UPROPERTY(BlueprintReadWrite, EditAnywhere, meta=(MultiLine="true", ExposeOnSpawn="true", EditCondition="bAutoPositionHeading"))
164 | FVector HeadingPadding = FVector(50.0, 100.0, 1.0);
165 |
166 | DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnSampleFloorBaseUpdated, FVector, Min, FVector, Max);
167 |
168 | UPROPERTY(BlueprintAssignable)
169 | FOnSampleFloorBaseUpdated OnSampleFloorBaseUpdated;
170 | };
171 |
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Private/CrvSettings.cpp:
--------------------------------------------------------------------------------
1 | // Fill out your copyright notice in the Description page of Project Settings.
2 |
3 | #include "CrvSettings.h"
4 |
5 | #include "CrvUtils.h"
6 | #include "CtrlReferenceVisualizer.h"
7 | #include "HAL/PlatformProcess.h"
8 | #include "Misc/FileHelper.h"
9 | #include "Misc/Paths.h"
10 |
11 | #define LOCTEXT_NAMESPACE "ReferenceVisualizer"
12 |
13 | FCrvLineStyle FCrvLineStyle::DefaultOutgoingLineStyle = {
14 | // LineStyle
15 | ECrvLineType::Arrow,
16 | // LineColor
17 | FColor::Green,
18 | // LineColorComponent
19 | FColor::Emerald,
20 | // LineColorObject
21 | FColor::Cyan,
22 | // LineThickness
23 | 2.f,
24 | // ArrowSize
25 | 10.f,
26 | // Depth Priority
27 | SDPG_Foreground
28 | };
29 |
30 | FCrvLineStyle FCrvLineStyle::DefaultIncomingLineStyle = {
31 | // LineStyle
32 | ECrvLineType::Dash,
33 | // LineColor
34 | FColor::Blue,
35 | // LineColorComponent
36 | (FLinearColor(FColor::Emerald) * FLinearColor::Blue).ToFColor(true),
37 | // LineColorObject
38 | (FLinearColor(FColor::Cyan) * FLinearColor::Blue).ToFColor(true),
39 | // LineThickness
40 | 1.f,
41 | // ArrowSize
42 | 5.f,
43 | // Depth Priority
44 | SDPG_Foreground
45 | };
46 |
47 | FCrvStyleSettings::FCrvStyleSettings()
48 | {
49 | }
50 |
51 | FCrvTargetSettings::FCrvTargetSettings()
52 | : IgnoreReferencesToClasses({}),
53 | TargetComponentClasses({TSoftClassPtr(UReferenceVisualizerComponent::StaticClass())})
54 | {
55 |
56 | }
57 |
58 | UCrvSettings::UCrvSettings()
59 | {
60 | CategoryName = "Ctrl";
61 | SectionName = "Reference Visualizer";
62 | Help = LOCTEXT("Help", "Shows references between actors and components in the level.");
63 | }
64 |
65 | FText UCrvSettings::GetSectionText() const
66 | {
67 | return LOCTEXT("CtrlReferenceVisualizerSettingsName", "Reference Visualizer");
68 | }
69 |
70 | FText UCrvSettings::GetSectionDescription() const
71 | {
72 | return LOCTEXT("CtrlReferenceVisualizerSettingsDescription", "Configure Ctrl Reference Visualizer Plugin");
73 | }
74 |
75 | void UCrvSettings::AddComponentClass(const TSoftClassPtr& ComponentClass)
76 | {
77 | TargetSettings.TargetComponentClasses.AddUnique(ComponentClass);
78 | UpdateTargets();
79 | }
80 |
81 | void UCrvSettings::SetEnabled(bool bNewEnabled)
82 | {
83 | if (bIsEnabled == bNewEnabled) { return; }
84 | bIsEnabled = bNewEnabled;
85 | const auto Property = StaticClass()->FindPropertyByName(
86 | GET_MEMBER_NAME_CHECKED(UCrvSettings, bIsEnabled)
87 | );
88 | auto Event = FPropertyChangedEvent(Property);
89 | PostEditChangeProperty(Event);
90 | }
91 |
92 | void UCrvSettings::ToggleEnabled()
93 | {
94 | SetEnabled(!bIsEnabled);
95 | }
96 |
97 | void UCrvSettings::SetShowIncomingReferences(bool bNewShowIncomingReferences)
98 | {
99 | if (bShowIncomingReferences == bNewShowIncomingReferences) { return; }
100 |
101 | bShowIncomingReferences = bNewShowIncomingReferences;
102 | const auto Property = StaticClass()->FindPropertyByName(
103 | GET_MEMBER_NAME_CHECKED(UCrvSettings, bShowIncomingReferences)
104 | );
105 | auto Event = FPropertyChangedEvent(Property);
106 | PostEditChangeProperty(Event);
107 | }
108 |
109 | void UCrvSettings::SetShowOutgoingReferences(bool bNewShowOutgoingReferences)
110 | {
111 | if (bShowOutgoingReferences == bNewShowOutgoingReferences) { return; }
112 | bShowOutgoingReferences = bNewShowOutgoingReferences;
113 | const auto Property = StaticClass()->FindPropertyByName(
114 | GET_MEMBER_NAME_CHECKED(UCrvSettings, bShowOutgoingReferences)
115 | );
116 | auto Event = FPropertyChangedEvent(Property);
117 | PostEditChangeProperty(Event);
118 | }
119 |
120 | void UCrvSettings::Refresh()
121 | {
122 | UpdateTargets();
123 | }
124 |
125 | void UCrvSettings::UpdateTargets()
126 | {
127 | if (bIsUpdating) { return; }
128 | TGuardValue UpdateGuard(bIsUpdating, true);
129 | CleanTargets();
130 | const auto Property = StaticClass()->FindPropertyByName(
131 | GET_MEMBER_NAME_CHECKED(UCrvSettings, TargetSettings)
132 | );
133 | OnModified.Broadcast(this, Property);
134 | }
135 |
136 | void UCrvSettings::CleanTargets()
137 | {
138 | // only allow at most one null entry
139 | auto OnlyOneNull = [](auto IsNullFunc)
140 | {
141 | bool bFoundOneNull = false;
142 | auto Fn = [&bFoundOneNull, &IsNullFunc](const auto& Item)
143 | {
144 | auto bIsOk = !IsNullFunc(Item);
145 | if (!bIsOk && !bFoundOneNull)
146 | {
147 | bFoundOneNull = true;
148 | return false;
149 | }
150 | return !bIsOk;
151 | };
152 | return Fn;
153 | };
154 |
155 | // clean target component classes
156 | TargetSettings.TargetComponentClasses.RemoveAll(
157 | OnlyOneNull([](const TSoftClassPtr& ClassPtr) { return ClassPtr.IsNull(); })
158 | );
159 | }
160 |
161 | bool UCrvSettings::IsEnabled() const
162 | {
163 | return bIsEnabled;
164 | }
165 |
166 | bool UCrvSettings::GetAutoAddComponents() const
167 | {
168 | return IsEnabled() && bAutoAddComponents;
169 | }
170 |
171 | // Function to open plugin documentation
172 | void OpenPluginDocumentation(const FString& PluginName)
173 | {
174 | // Construct the path to the plugin descriptor file
175 | const FString PluginPath = FPaths::ProjectPluginsDir() / PluginName / FString::Printf(TEXT("%s.uplugin"), *PluginName);
176 |
177 | // Read the plugin descriptor file
178 | FString FileContents;
179 | const bool bDidLoadFile = FFileHelper::LoadFileToString(FileContents, *PluginPath);
180 | if (!bDidLoadFile)
181 | {
182 | UE_LOG(LogCrv, Warning, TEXT("Failed to load plugin descriptor for %s"), *PluginName);
183 | return;
184 | }
185 | // Parse the JSON content
186 | TSharedPtr JsonObject;
187 | const TSharedRef> Reader = TJsonReaderFactory<>::Create(FileContents);
188 | const bool bDidDeserialize = FJsonSerializer::Deserialize(Reader, JsonObject);
189 | if (!bDidDeserialize)
190 | {
191 | UE_LOG(LogCrv, Warning, TEXT("Failed to deserialize plugin descriptor for %s"), *PluginName);
192 | return;
193 | }
194 | // Extract the DocsURL
195 | FString DocsURL;
196 | const bool Success = JsonObject->TryGetStringField(TEXT("DocsURL"), DocsURL);
197 | if (!Success)
198 | {
199 | UE_LOG(LogCrv, Warning, TEXT("No DocsURL found in plugin descriptor for %s"), *PluginName);
200 | return;
201 | }
202 | // Open the documentation URL in the default web browser
203 | FPlatformProcess::LaunchURL(*DocsURL, nullptr, nullptr);
204 | }
205 |
206 | void UCrvSettings::Documentation() const
207 | {
208 | OpenPluginDocumentation(TEXT("CtrlReferenceVisualizer"));
209 | }
210 |
211 | void UCrvSettings::PostInitProperties()
212 | {
213 | Super::PostInitProperties();
214 | #if WITH_EDITOR
215 | IConsoleManager::Get().RegisterConsoleVariableSink_Handle(
216 | FConsoleCommandDelegate::CreateUObject(this, &UCrvSettings::CVarSink)
217 | );
218 | #endif
219 | UpdateTargets();
220 | }
221 |
222 | #if WITH_EDITOR
223 |
224 | FCrvLineStyle UCrvSettings::GetLineStyle(const ECrvDirection Direction) const
225 | {
226 | return Direction == ECrvDirection::Incoming ? Style.LineStyleIncoming : Style.LineStyleOutgoing;
227 | }
228 |
229 | void UCrvSettings::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
230 | {
231 | Super::PostEditChangeProperty(PropertyChangedEvent);
232 | if (!PropertyChangedEvent.Property) { return; }
233 |
234 | UpdateTargets();
235 | OnModified.Broadcast(this, PropertyChangedEvent.Property);
236 | }
237 |
238 | void UCrvSettings::CVarSink()
239 | {
240 | if (IsTemplate())
241 | {
242 | ImportConsoleVariableValues();
243 | SetEnabled(CrvConsoleVars::CVarReferenceVisualizerEnabled->GetBool());
244 | UpdateTargets();
245 | }
246 | }
247 | #endif
248 | #undef LOCTEXT_NAMESPACE
249 |
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Private/CrvStyle.cpp:
--------------------------------------------------------------------------------
1 | #include "CrvStyle.h"
2 |
3 | #include "Styling/ISlateStyle.h"
4 | #include "Styling/SlateStyle.h"
5 | #include "Styling/SlateStyleRegistry.h"
6 | #include "Styling/StyleColors.h"
7 |
8 | TSharedPtr FCrvStyle::StyleSet = nullptr;
9 |
10 | TSharedPtr FCrvStyle::Get()
11 | {
12 | ensure(StyleSet.IsValid());
13 | return StyleSet;
14 | }
15 |
16 | FCrvStyle::FCrvStyle()
17 | : FSlateStyleSet(FCrvStyle::GetStyleSetName())
18 | {
19 | }
20 |
21 | void FCrvStyle::Startup()
22 | {
23 | if (StyleSet.IsValid()) { return; } // only init once
24 | StyleSet = MakeShared();
25 | StyleSet->Initialize();
26 | }
27 |
28 | void FCrvStyle::Register()
29 | {
30 | if (!StyleSet.IsValid()) { return; }
31 | FSlateStyleRegistry::RegisterSlateStyle(*StyleSet.Get());
32 | }
33 |
34 | void FCrvStyle::Shutdown()
35 | {
36 | if (StyleSet.IsValid())
37 | {
38 | FSlateStyleRegistry::UnRegisterSlateStyle(*StyleSet.Get());
39 | ensure(StyleSet.IsUnique());
40 | StyleSet.Reset();
41 | }
42 | }
43 |
44 | const FName& FCrvStyle::GetStyleSetName() const
45 | {
46 | static FName CtrlStyleName(TEXT("CrvStyle"));
47 | return CtrlStyleName;
48 | }
49 |
50 | void FCrvStyle::Initialize()
51 | {
52 | const FVector2D Icon128x128(128.0f, 128.0f);
53 | const FVector2D Icon16x16(16.f, 16.f);
54 | const FVector2D Icon32x32(32.f, 32.f);
55 |
56 | SetContentRoot(FPaths::ProjectPluginsDir() / TEXT("CtrlReferenceVisualizer/Resources"));
57 | Set("Ctrl.TabIcon", new FSlateImageBrush(GetContentRootDir() / TEXT("Icon128.png"), Icon128x128));
58 | Set("Ctrl.PlacementModeIcon", new FSlateImageBrush(GetContentRootDir() / TEXT("Icon16.png"), Icon16x16));
59 | // use outliner style to get colors for selection + unfocused selection + hover
60 | auto RowStyle = FAppStyle::Get().GetWidgetStyle("SceneOutliner.TableViewRow");
61 | // add alternating row color
62 | FLinearColor AltColor = FStyleColors::Panel.GetSpecifiedColor().CopyWithNewOpacity(0.2f);
63 | Set(
64 | "Ctrl.TreeView.TableRow",
65 | FTableRowStyle(RowStyle)
66 | .SetEvenRowBackgroundBrush(FSlateColorBrush(FStyleColors::Recessed))
67 | .SetOddRowBackgroundBrush(FSlateColorBrush(FLinearColor(AltColor)))
68 | );
69 | }
70 |
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Private/CrvTestActorBase.cpp:
--------------------------------------------------------------------------------
1 | // Fill out your copyright notice in the Description page of Project Settings.
2 |
3 | #include "CrvTestActorBase.h"
4 | #include "ObjectTools.h"
5 | #include "HAL/PlatformApplicationMisc.h"
6 | #include "Components/TextRenderComponent.h"
7 |
8 | UCrvTestComponentBase::UCrvTestComponentBase()
9 | {
10 | TestObject = CreateDefaultSubobject(TEXT("TestObject"));
11 | }
12 |
13 | ACrvTestActorBase::ACrvTestActorBase()
14 | {
15 | PrimaryActorTick.bCanEverTick = false;
16 |
17 | DefaultSceneRoot = CreateDefaultSubobject(TEXT("DefaultSceneRoot"));
18 | RootComponent = DefaultSceneRoot;
19 | Sphere = CreateDefaultSubobject(TEXT("Sphere"));
20 | Sphere->SetupAttachment(DefaultSceneRoot);
21 | TextRender = CreateDefaultSubobject(TEXT("TextRender"));
22 | TextRender->SetupAttachment(Sphere);
23 | TextRender->SetRelativeLocation(FVector(0, 0, 100));
24 | TextRender->SetRelativeRotation(FRotator(0, 180, 0));
25 | TextRender->HorizontalAlignment = EHorizTextAligment::EHTA_Center;
26 | TestComponent = CreateDefaultSubobject(TEXT("TestComponent"));
27 | TestComponent->SetupAttachment(Sphere);
28 | TestComponent->SetRelativeLocation(FVector(0, 0, 200));
29 | TestObject = CreateDefaultSubobject(TEXT("TestObject"));
30 | }
31 |
32 | void ACrvTestActorBase::OnConstruction(const FTransform& Transform)
33 | {
34 | Super::OnConstruction(Transform);
35 |
36 | TextRender->SetText(FText::FromName(TestName));
37 | }
38 |
39 | void ACrvTestActorBase::CopySettingsToTestComponent()
40 | {
41 | TestComponent->ActorRef = ActorRef;
42 | TestComponent->ActorRef2 = ActorRef2;
43 | TestComponent->SoftActorRef = SoftActorRef;
44 | TestComponent->ComponentRef = ComponentRef;
45 | TestComponent->SoftComponentRef = SoftComponentRef;
46 | TestComponent->OptionalActorRef = OptionalActorRef;
47 | TestComponent->OptionalComponentRef = OptionalComponentRef;
48 | TestComponent->WeakActorRef = WeakActorRef;
49 | TestComponent->WeakComponentRef = WeakComponentRef;
50 | TestComponent->ActorRefArray= ActorRefArray;
51 | TestComponent->ActorRefMap = ActorRefMap;
52 | TestComponent->TestStruct = TestStruct;
53 | TestComponent->TestObject = TestObject;
54 | ActorRef = nullptr;
55 | ActorRef2 = nullptr;
56 | SoftActorRef = nullptr;
57 | ComponentRef = nullptr;
58 | SoftComponentRef = nullptr;
59 | OptionalActorRef = nullptr;
60 | OptionalComponentRef = nullptr;
61 | WeakActorRef = nullptr;
62 | WeakComponentRef = nullptr;
63 | ActorRefArray.Empty();
64 | ActorRefMap.Empty();
65 | }
66 | void ACrvTestActorBase::CopySettingsToTestObject()
67 | {
68 | TestObject->ActorRef = ActorRef;
69 | TestObject->ActorRef2 = ActorRef2;
70 | TestObject->SoftActorRef = SoftActorRef;
71 | TestObject->ComponentRef = ComponentRef;
72 | TestObject->SoftComponentRef = SoftComponentRef;
73 | TestObject->OptionalActorRef = OptionalActorRef;
74 | TestObject->OptionalComponentRef = OptionalComponentRef;
75 | TestObject->WeakActorRef = WeakActorRef;
76 | TestObject->WeakComponentRef = WeakComponentRef;
77 | TestObject->ActorRefArray = ActorRefArray;
78 | TestObject->ActorRefMap = ActorRefMap;
79 | TestObject->TestStruct = TestStruct;
80 | ActorRef = nullptr;
81 | ActorRef2 = nullptr;
82 | SoftActorRef = nullptr;
83 | ComponentRef = nullptr;
84 | SoftComponentRef = nullptr;
85 | OptionalActorRef = nullptr;
86 | OptionalComponentRef = nullptr;
87 | WeakActorRef = nullptr;
88 | WeakComponentRef = nullptr;
89 | ActorRefArray.Empty();
90 | ActorRefMap.Empty();
91 | }
92 | void UCrvCopyReference::CopyReference()
93 | {
94 |
95 | // auto CopyRef = [](UObject* Object)
96 | // {
97 | // if (!Object) { return; }
98 | // FPlatformApplicationMisc::ClipboardCopy(*Object->GetFullName());
99 | // };
100 | // if (What == ECrvCopyWhatReference::ChildActor)
101 | // {
102 | // if (auto OwnerWithChild = GetTypedOuter())
103 | // {
104 | // CopyRef(OwnerWithChild->ChildActor);
105 | // }
106 | // return;
107 | // }
108 | //
109 | // auto Owner = GetTypedOuter();
110 | // if (!Owner) { return; }
111 | // if (What == ECrvCopyWhatReference::ActorRef)
112 | // {
113 | // CopyRef(Owner->ActorRef);
114 | // return;
115 | // }
116 | //
117 | // if (What == ECrvCopyWhatReference::ActorRef2)
118 | // {
119 | // CopyRef(Owner->ActorRef2);
120 | // return;
121 | // }
122 | }
123 |
124 | ACrvTestActorWithChildActorBase::ACrvTestActorWithChildActorBase()
125 | {
126 | ChildActorComponent = CreateDefaultSubobject(TEXT("ChildActorComponent"));
127 | ChildActorComponent->SetupAttachment(RootComponent);
128 | ChildActorComponent->SetRelativeLocation(FVector(200, 0, 0));
129 | ChildActorComponent->SetRelativeScale3D(FVector(0.5, 0.5, 0.5));
130 | ChildActorComponent->SetChildActorClass(ACrvTestActorBase::StaticClass());
131 | }
132 | void ACrvTestActorWithChildActorBase::CopySettingsToChildActor()
133 | {
134 | if (auto Child = Cast(ChildActorComponent->GetChildActor()))
135 | {
136 | Child->ActorRef = ActorRef;
137 | Child->ActorRef2 = ActorRef2;
138 | Child->SoftActorRef = SoftActorRef;
139 | Child->ComponentRef = ComponentRef;
140 | Child->SoftComponentRef = SoftComponentRef;
141 | Child->OptionalActorRef = OptionalActorRef;
142 | Child->OptionalComponentRef = OptionalComponentRef;
143 | Child->WeakActorRef = WeakActorRef;
144 | Child->WeakComponentRef = WeakComponentRef;
145 | Child->ActorRefArray= ActorRefArray;
146 | Child->ActorRefMap = ActorRefMap;
147 | Child->TestStruct = TestStruct;
148 | Child->TestObject = TestObject;
149 | ActorRef = nullptr;
150 | ActorRef2 = nullptr;
151 | SoftActorRef = nullptr;
152 | ComponentRef = nullptr;
153 | SoftComponentRef = nullptr;
154 | OptionalActorRef = nullptr;
155 | OptionalComponentRef = nullptr;
156 | WeakActorRef = nullptr;
157 | WeakComponentRef = nullptr;
158 | ActorRefArray.Empty();
159 | ActorRefMap.Empty();
160 | }
161 | }
162 | void ACrvTestActorWithChildActorBase::OnConstruction(const FTransform& Transform)
163 | {
164 | Super::OnConstruction(Transform);
165 | ChildActor = ChildActorComponent->GetChildActor();
166 | }
167 |
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Private/CrvTestActorBase.h:
--------------------------------------------------------------------------------
1 | // Fill out your copyright notice in the Description page of Project Settings.
2 |
3 | #pragma once
4 |
5 | #include "CoreMinimal.h"
6 | #include "GameFramework/Actor.h"
7 | #include "CrvTestActorBase.generated.h"
8 |
9 | class UCrvTestObject;
10 | class UTextRenderComponent;
11 |
12 | USTRUCT(BlueprintType)
13 | struct FCrvTestStructNested
14 | {
15 | GENERATED_BODY()
16 |
17 | // Direct Reference to an Actor
18 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
19 | TObjectPtr ActorRef;
20 | };
21 | USTRUCT(BlueprintType)
22 | struct FCrvTestStruct
23 | {
24 | GENERATED_BODY()
25 |
26 | // Direct Reference to an Actor
27 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
28 | TObjectPtr ActorRef;
29 |
30 | // Direct Reference to another Actor
31 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
32 | TObjectPtr ActorRef2;
33 |
34 | // Soft Reference to an Actor
35 | UPROPERTY(BlueprintReadWrite, EditAnywhere)
36 | TSoftObjectPtr SoftActorRef;
37 |
38 | // Direct Reference to an Actor Component
39 | UPROPERTY(BlueprintReadWrite, EditAnywhere)
40 | TObjectPtr ComponentRef;
41 |
42 | // Soft Reference to an Actor Component
43 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
44 | TSoftObjectPtr SoftComponentRef;
45 |
46 | // Optional Reference to an Actor
47 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
48 | TOptional OptionalActorRef;
49 |
50 | // Optional Reference to an Actor Component
51 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
52 | TOptional OptionalComponentRef;
53 |
54 | // Weak Reference to an Actor
55 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
56 | TWeakObjectPtr WeakActorRef;
57 |
58 | // Weak Reference to an Actor Component
59 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
60 | TWeakObjectPtr WeakComponentRef;
61 |
62 | // Array of Actors
63 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
64 | TArray ActorRefArray;
65 |
66 | // Map of Actors
67 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
68 | TMap ActorRefMap;
69 |
70 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly, Instanced)
71 | TObjectPtr TestObject;
72 |
73 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
74 | FCrvTestStructNested TestStructNested;
75 | };
76 |
77 | UCLASS(BlueprintType, DefaultToInstanced, EditInlineNew)
78 | class UCrvTestObject: public UObject
79 | {
80 | GENERATED_BODY()
81 |
82 | public:
83 |
84 | // Direct Reference to an Actor
85 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
86 | TObjectPtr ActorRef;
87 |
88 | // Direct Reference to another Actor
89 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
90 | TObjectPtr ActorRef2;
91 |
92 | // Soft Reference to an Actor
93 | UPROPERTY(BlueprintReadWrite, EditAnywhere)
94 | TSoftObjectPtr SoftActorRef;
95 |
96 | // Direct Reference to an Actor Component
97 | UPROPERTY(BlueprintReadWrite, EditAnywhere)
98 | TObjectPtr ComponentRef;
99 |
100 | // Soft Reference to an Actor Component
101 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
102 | TSoftObjectPtr SoftComponentRef;
103 |
104 | // Optional Reference to an Actor
105 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
106 | TOptional OptionalActorRef;
107 |
108 | // Optional Reference to an Actor Component
109 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
110 | TOptional OptionalComponentRef;
111 |
112 | // Weak Reference to an Actor
113 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
114 | TWeakObjectPtr WeakActorRef;
115 |
116 | // Weak Reference to an Actor Component
117 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
118 | TWeakObjectPtr WeakComponentRef;
119 |
120 | // Array of Actors
121 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
122 | TArray ActorRefArray;
123 |
124 | // Map of Actors
125 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
126 | TMap ActorRefMap;
127 |
128 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
129 | FCrvTestStruct TestStruct;
130 |
131 | UFUNCTION(BlueprintCallable, CallInEditor)
132 | void CopyActorToWeakActor()
133 | {
134 |
135 | WeakActorRef = ActorRef;
136 | ActorRef = nullptr;
137 | }
138 | UFUNCTION(BlueprintCallable, CallInEditor)
139 | void ClearWeakActorRef()
140 | {
141 | WeakActorRef = nullptr;
142 | }
143 | UFUNCTION(BlueprintCallable, CallInEditor)
144 | void CopyCompToWeakComp()
145 | {
146 |
147 | WeakComponentRef = ComponentRef;
148 | ComponentRef = nullptr;
149 | }
150 | UFUNCTION(BlueprintCallable, CallInEditor)
151 | void ClearWeakCompRef()
152 | {
153 | WeakComponentRef = nullptr;
154 | }
155 | };
156 |
157 | UCLASS(Blueprintable, BlueprintType)
158 | class CTRLREFERENCEVISUALIZER_API UCrvTestComponentBase : public USceneComponent
159 | {
160 | GENERATED_BODY()
161 |
162 | public:
163 |
164 | UCrvTestComponentBase();
165 | // Direct Reference to an Actor
166 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
167 | TObjectPtr ActorRef;
168 |
169 | // Direct Reference to another Actor
170 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
171 | TObjectPtr ActorRef2;
172 |
173 | // Soft Reference to an Actor
174 | UPROPERTY(BlueprintReadWrite, EditAnywhere)
175 | TSoftObjectPtr SoftActorRef;
176 |
177 | // Direct Reference to an Actor Component
178 | UPROPERTY(BlueprintReadWrite, EditAnywhere)
179 | TObjectPtr ComponentRef;
180 |
181 | // Soft Reference to an Actor Component
182 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
183 | TSoftObjectPtr SoftComponentRef;
184 |
185 | // Optional Reference to an Actor
186 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
187 | TOptional OptionalActorRef;
188 |
189 | // Optional Reference to an Actor Component
190 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
191 | TOptional OptionalComponentRef;
192 |
193 | // Weak Reference to an Actor
194 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
195 | TWeakObjectPtr WeakActorRef;
196 |
197 | // Weak Reference to an Actor Component
198 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
199 | TWeakObjectPtr WeakComponentRef;
200 |
201 | // Array of Actors
202 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
203 | TArray ActorRefArray;
204 |
205 | // Map of Actors
206 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
207 | TMap ActorRefMap;
208 |
209 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
210 | FCrvTestStruct TestStruct;
211 |
212 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly, Instanced)
213 | TObjectPtr TestObject;
214 |
215 | UFUNCTION(BlueprintCallable, CallInEditor)
216 | void CopyActorToWeakActor()
217 | {
218 |
219 | WeakActorRef = ActorRef;
220 | ActorRef = nullptr;
221 | }
222 | UFUNCTION(BlueprintCallable, CallInEditor)
223 | void ClearWeakActorRef()
224 | {
225 | WeakActorRef = nullptr;
226 | }
227 | UFUNCTION(BlueprintCallable, CallInEditor)
228 | void CopyCompToWeakComp()
229 | {
230 |
231 | WeakComponentRef = ComponentRef;
232 | ComponentRef = nullptr;
233 | }
234 | UFUNCTION(BlueprintCallable, CallInEditor)
235 | void ClearWeakCompRef()
236 | {
237 | WeakComponentRef = nullptr;
238 | }
239 |
240 | };
241 |
242 | UCLASS(Blueprintable, BlueprintType)
243 | class CTRLREFERENCEVISUALIZER_API ACrvTestActorBase : public AActor
244 | {
245 | GENERATED_BODY()
246 |
247 | public:
248 | ACrvTestActorBase();
249 | virtual void OnConstruction(const FTransform& Transform) override;
250 |
251 | UPROPERTY(BlueprintReadOnly, EditAnywhere, meta=(GetOptions="GetTestNames"))
252 | FName TestName = TEXT("A");
253 |
254 | UFUNCTION(BlueprintCallable, Category = "CrvTestActorBase")
255 | static TArray GetTestNames() { return TArray{TEXT("A"), TEXT("B"), TEXT("C"), TEXT("D"), TEXT("E"), TEXT("F"), TEXT("G") }; }
256 |
257 | UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
258 | TObjectPtr DefaultSceneRoot;
259 |
260 | UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
261 | TObjectPtr TextRender;
262 |
263 | UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
264 | TObjectPtr Sphere;
265 |
266 | UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
267 | TObjectPtr TestComponent;
268 |
269 | // Test Properties //
270 |
271 | // Direct Reference to an Actor
272 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
273 | TObjectPtr ActorRef;
274 |
275 | // Direct Reference to another Actor
276 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
277 | TObjectPtr ActorRef2;
278 |
279 | // Soft Reference to an Actor
280 | UPROPERTY(BlueprintReadWrite, EditAnywhere)
281 | TSoftObjectPtr SoftActorRef;
282 |
283 | // Direct Reference to an Actor Component
284 | UPROPERTY(BlueprintReadWrite, EditAnywhere)
285 | TObjectPtr ComponentRef;
286 |
287 | // Soft Reference to an Actor Component
288 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
289 | TSoftObjectPtr SoftComponentRef;
290 |
291 | // Optional Reference to an Actor
292 | UPROPERTY(BlueprintReadWrite, EditAnywhere)
293 | TOptional OptionalActorRef;
294 |
295 | // Optional Reference to an Actor Component
296 | UPROPERTY(BlueprintReadWrite, EditAnywhere)
297 | TOptional OptionalComponentRef;
298 |
299 | // Weak Reference to an Actor
300 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
301 | TWeakObjectPtr WeakActorRef;
302 |
303 | // Weak Reference to an Actor Component
304 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
305 | TWeakObjectPtr WeakComponentRef;
306 |
307 | // Array of Actors
308 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
309 | TArray ActorRefArray;
310 |
311 | // Map of Actors
312 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
313 | TMap ActorRefMap;
314 |
315 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
316 | FCrvTestStruct TestStruct;
317 |
318 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
319 | TObjectPtr TestObject;
320 |
321 | UPROPERTY(BlueprintReadWrite, EditInstanceOnly)
322 | TObjectPtr ObjectRef;
323 |
324 | UFUNCTION(BlueprintCallable, CallInEditor)
325 | void CopySettingsToTestComponent();
326 |
327 | void CopySettingsToTestObject();
328 |
329 | UFUNCTION(BlueprintCallable, CallInEditor)
330 | void CopyActorToWeakActor()
331 | {
332 |
333 | WeakActorRef = ActorRef;
334 | ActorRef = nullptr;
335 | }
336 | UFUNCTION(BlueprintCallable, CallInEditor)
337 | void ClearWeakActorRef()
338 | {
339 | WeakActorRef = nullptr;
340 | }
341 | UFUNCTION(BlueprintCallable, CallInEditor)
342 | void CopyCompToWeakComp()
343 | {
344 |
345 | WeakComponentRef = ComponentRef;
346 | ComponentRef = nullptr;
347 | }
348 | UFUNCTION(BlueprintCallable, CallInEditor)
349 | void ClearWeakCompRef()
350 | {
351 | WeakComponentRef = nullptr;
352 | }
353 | };
354 |
355 | UENUM()
356 | enum class ECrvCopyWhatReference : uint8
357 | {
358 | ChildActor,
359 | ChildActorComponent,
360 | TestComponent,
361 | TestObject,
362 | ActorRef,
363 | ActorRef2,
364 | SoftActorRef,
365 | ComponentRef,
366 | SoftComponentRef,
367 | OptionalActorRef,
368 | };
369 | UCLASS(BlueprintType)
370 | class UCrvCopyReference: public UObject
371 | {
372 | GENERATED_BODY()
373 | public:
374 | UPROPERTY(BlueprintReadWrite, EditAnywhere)
375 | ECrvCopyWhatReference What;
376 |
377 | UFUNCTION(BlueprintCallable, CallInEditor)
378 | void CopyReference();
379 |
380 | };
381 |
382 | UCLASS()
383 | class ACrvTestActorWithChildActorBase : public ACrvTestActorBase
384 | {
385 | GENERATED_BODY()
386 | public:
387 | ACrvTestActorWithChildActorBase();
388 |
389 | UPROPERTY(BlueprintReadWrite, VisibleAnywhere)
390 | TObjectPtr ChildActorComponent;
391 |
392 | UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
393 | TObjectPtr ChildActor;
394 |
395 | UFUNCTION(BlueprintCallable, CallInEditor)
396 | void CopySettingsToChildActor();
397 |
398 | virtual void OnConstruction(const FTransform& Transform) override;
399 | };
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Private/CrvUtils.cpp:
--------------------------------------------------------------------------------
1 | #include "CrvUtils.h"
2 |
3 | FString CtrlRefViz::GetDebugName(const UObject* Object)
4 | {
5 | if (!Object)
6 | {
7 | return TEXT("null");
8 | }
9 | FString Name = GetNameSafe(Object);
10 | if (Object->IsA())
11 | {
12 | Name = Cast(Object)->GetActorNameOrLabel();
13 | }
14 | if (Object->IsA())
15 | {
16 | Name = Cast(Object)->GetReadableName();
17 | }
18 | return FString::Printf(TEXT("<%s>%s"), *GetNameSafe(Object->GetClass()), *Name);
19 | }
20 |
21 | AActor* CtrlRefViz::GetOwner(const UObject* Object)
22 | {
23 | return GetOwner(const_cast(Object));
24 | }
25 |
26 | AActor* CtrlRefViz::GetOwner(UObject* Object)
27 | {
28 | if (!Object) { return nullptr; }
29 | if (const auto Actor = Cast(Object))
30 | {
31 | return Actor;
32 | }
33 | if (const auto Component = Cast(Object))
34 | {
35 | return Component->GetOwner();
36 | }
37 | return Object->GetTypedOuter();
38 | }
39 |
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Private/CrvUtils.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "CoreMinimal.h"
3 |
4 | #define CRV_LOG_LINE FString::Printf(TEXT("%s:%d"), *FPaths::GetCleanFilename(ANSI_TO_TCHAR(__FILE__)), __LINE__)
5 |
6 | namespace CtrlRefViz
7 | {
8 | FString GetDebugName(const UObject* Object);
9 | AActor* GetOwner(UObject* Object);
10 | AActor* GetOwner(const UObject* Object);
11 | }
12 |
13 | namespace CrvConsoleVars
14 | {
15 | static int32 IsEnabled = 1;
16 | static FAutoConsoleVariableRef CVarReferenceVisualizerEnabled(
17 | TEXT("ctrl.ReferenceVisualizer"),
18 | IsEnabled,
19 | TEXT("Enable Actor Reference Visualizer Level Editor Display")
20 | );
21 | }
22 |
23 | namespace CtrlRefViz
24 | {
25 | using FCrvSet = TSet;
26 | using FCrvSetProp = TSet>;
27 | using FCrvWeakSet = TSet>;
28 | using FCrvObjectGraph = TMap, FCrvSet>;
29 | using FCrvWeakGraph = TMap, FCrvWeakSet>;
30 |
31 | template
32 | bool AreSetsEqual(const T& Set, const T& RHS)
33 | {
34 | return Set.Num() == RHS.Num() && Set.Difference(RHS).Num() == 0 && RHS.Difference(Set).Num() == 0;
35 | }
36 |
37 | template
38 | TSet> ToWeakSet(const TSet& In)
39 | {
40 | static TSet> EmptySet;
41 | if (In.IsEmpty()) { return EmptySet; }
42 | FCrvWeakSet Out;
43 | Out.Reserve(In.Num());
44 | for (const auto Object : In)
45 | {
46 | if (!IsValid(Object)) { continue; }
47 | Out.Add(Object);
48 | }
49 | return MoveTemp(Out);
50 | }
51 |
52 | template
53 | TSet ResolveWeakSet(const TSet>& Set, bool& bFoundInvalid)
54 | {
55 | static TSet EmptySet;
56 | bFoundInvalid = false;
57 | if (Set.IsEmpty()) { return EmptySet; }
58 | FCrvSet ValidPointers;
59 | // ValidPointers.Reserve(Set.Num());
60 | for (const auto LinkedObject : Set)
61 | {
62 | if (LinkedObject.IsValid())
63 | {
64 | ValidPointers.Add(LinkedObject.Get());
65 | }
66 | else
67 | {
68 | bFoundInvalid = true;
69 | }
70 | }
71 | return MoveTemp(ValidPointers);
72 | }
73 |
74 | template
75 | TSet ResolveWeakSet(const TSet>& Set)
76 | {
77 | bool bFoundInvalid = false;
78 | return ResolveWeakSet(Set, bFoundInvalid);
79 | }
80 |
81 | inline FCrvObjectGraph ResolveWeakGraph(const FCrvWeakGraph& Graph, bool& bFoundInvalid)
82 | {
83 | bFoundInvalid = false;
84 | static FCrvObjectGraph EmptyGraph;
85 | if (Graph.IsEmpty()) { return EmptyGraph; }
86 | FCrvObjectGraph ValidItems;
87 | ValidItems.Reserve(Graph.Num());
88 | for (const auto [Object, WeakSetPtrs] : Graph)
89 | {
90 | if (!Object.IsValid())
91 | {
92 | bFoundInvalid = true;
93 | continue;
94 | }
95 | ValidItems.Add(Object.Get(), ResolveWeakSet(WeakSetPtrs));
96 | }
97 | return MoveTemp(ValidItems);
98 | }
99 |
100 | inline FCrvObjectGraph ResolveWeakGraph(const FCrvWeakGraph& Graph)
101 | {
102 | bool bFoundInvalid = false;
103 | return ResolveWeakGraph(Graph, bFoundInvalid);
104 | }
105 |
106 | inline FCrvWeakGraph ToWeakGraph(const FCrvObjectGraph& Graph)
107 | {
108 | static FCrvWeakGraph EmptyGraph;
109 | if (Graph.IsEmpty()) { return EmptyGraph; }
110 | FCrvWeakGraph Out;
111 | Out.Reserve(Graph.Num());
112 | for (const auto [Object, Set] : Graph)
113 | {
114 | if (!IsValid(Object)) { continue; }
115 | Out.Add(Object, ToWeakSet(Set));
116 | }
117 | return MoveTemp(Out);
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Private/CtrlReferenceVisualizer.cpp:
--------------------------------------------------------------------------------
1 | #include "CtrlReferenceVisualizer.h"
2 |
3 | #include "CrvCommands.h"
4 | #include "CrvRefSearch.h"
5 | #include "CrvSettings.h"
6 | #include "CrvStyle.h"
7 | #include "CrvUtils.h"
8 | #include "ISettingsModule.h"
9 | #include "LevelEditorSubsystem.h"
10 | #include "ObjectEditorUtils.h"
11 |
12 | #include "Styling/SlateIconFinder.h"
13 |
14 | #include "UObject/Object.h"
15 |
16 | #define LOCTEXT_NAMESPACE "ReferenceVisualizer"
17 | using namespace CtrlRefViz;
18 |
19 | DEFINE_LOG_CATEGORY(LogCrv);
20 |
21 | void FCrvModule::MakeReferenceListSubMenu(UToolMenu* SubMenu, const ECrvDirection Direction) const
22 | {
23 | if (!GetDefault()->IsEnabled())
24 | {
25 | const auto ToolEntry = FToolMenuEntry::InitMenuEntry(
26 | FName("CtrlReferenceVisualizer_Disabled"),
27 | LOCTEXT("Disabled", "Disabled"),
28 | LOCTEXT("DisabledTooltip", "Disabled"),
29 | FSlateIcon(),
30 | FUIAction()
31 | );
32 | SubMenu->AddMenuEntry(FName("CtrlReferenceVisualizer_Disabled"), ToolEntry);
33 | return;
34 | }
35 | auto CrvEditorSubsystem = GEditor->GetEditorSubsystem();
36 | auto MenuCache = CrvEditorSubsystem->MenuCache;
37 | MenuCache->FillCache(FCrvRefSearch::GetSelectionSet());
38 |
39 | bool bFoundEntry = false;
40 | FCrvSet Visited;
41 | auto ValidCache = MenuCache->GetValidCached(Direction);
42 | for (auto SelectedObject : FCrvRefSearch::GetSelectionSet())
43 | {
44 | if (!SelectedObject) { return; }
45 | UE_CLOG(IsDebugEnabled(), LogCrv, Log, TEXT("Find %s for SelectedObject: %s"), *SelectedObject->GetFullName(), Direction == ECrvDirection::Outgoing ? TEXT("Outgoing") : TEXT("Incoming"));
46 | auto Refs = MenuCache->GetReferences(SelectedObject, Direction);
47 | if (!Refs.Num()) { continue; }
48 |
49 | auto RefsArray = Refs.Array();
50 | RefsArray.Sort(
51 | [](const UObject& A, const UObject& B) { return A.GetFullName().Compare(B.GetFullName()) < 0; }
52 | );
53 | for (auto Ref : RefsArray)
54 | {
55 | if (Visited.Contains(Ref)) { continue; }
56 |
57 | FToolMenuSection& Section = SubMenu->FindOrAddSection(FName(Ref->GetClass()->GetPathName()));
58 | FToolMenuSection* SectionPtr = &Section;
59 | if (auto BP = UBlueprint::GetBlueprintFromClass(Ref->GetClass()->GetAuthoritativeClass()))
60 | {
61 | auto& Section2 = SubMenu->FindOrAddSection(FName(BP->GetFullName()));
62 | SectionPtr = &Section2;
63 | // get human-readable name from uobject
64 | SectionPtr->Label = FText::FromString(BP->GetFriendlyName());
65 | }
66 | else
67 | {
68 | SectionPtr->Label = FText::FromString(Ref->GetClass()->GetName());
69 | }
70 | auto [Name, Label, ToolTip, Icon, Action] = FCrvRefSearch::MakeMenuEntry(SelectedObject, Ref);
71 | const auto ToolEntry = FToolMenuEntry::InitMenuEntry(Name, Label, ToolTip, Icon, Action);
72 | SectionPtr->AddEntry(ToolEntry);
73 | bFoundEntry = true;
74 | }
75 | Visited.Append(Refs);
76 | }
77 |
78 | if (!bFoundEntry)
79 | {
80 | const auto ToolEntry = FToolMenuEntry::InitMenuEntry(
81 | FName("CtrlReferenceVisualizer_None"),
82 | LOCTEXT("NoReferencesFound", "No references found"),
83 | LOCTEXT("NoReferencesFoundTooltip", "No references found"),
84 | FSlateIcon(),
85 | FUIAction()
86 | );
87 | SubMenu->AddMenuEntry(FName("CtrlReferenceVisualizer_None"), ToolEntry);
88 | }
89 | }
90 |
91 | void FCrvModule::SelectReference(UObject* Object)
92 | {
93 | if (!Object) { return; }
94 | GEditor->GetEditorSubsystem()->OpenEditorForAsset(Object);
95 | const bool bMoveCamera = GetDefault()->bMoveViewportCameraToReference;
96 | if (const auto Actor = Cast(Object))
97 | {
98 | GEditor->SelectNone(false, true);
99 | GEditor->SelectActor(Actor, true, true);
100 | if (bMoveCamera)
101 | {
102 | GEditor->MoveViewportCamerasToActor(*Actor, false);
103 | }
104 | return;
105 | }
106 | if (const auto Component = Cast(Object))
107 | {
108 | GEditor->SelectNone(false, true);
109 | GEditor->SelectComponent(const_cast(Component), true, true);
110 | if (bMoveCamera)
111 | {
112 | if (const auto SceneComponent = Cast(Component))
113 | {
114 | GEditor->MoveViewportCamerasToComponent(SceneComponent, false);
115 | }
116 | else
117 | {
118 | GEditor->MoveViewportCamerasToActor(*Component->GetOwner(), false);
119 | }
120 | }
121 | return;
122 | }
123 |
124 | if (const auto OwningComponent = Object->GetTypedOuter())
125 | {
126 | SelectReference(OwningComponent);
127 | return;
128 | }
129 | if (const auto OwningActor = Object->GetTypedOuter())
130 | {
131 | SelectReference(OwningActor);
132 | return;
133 | }
134 | }
135 |
136 | void FCrvModule::InitActorMenu() const
137 | {
138 | const auto SubMenu = FToolMenuEntry::InitSubMenu(
139 | FName("CtrlReferenceVisualizerOutgoing"),
140 | LOCTEXT("References", "References"),
141 | LOCTEXT("ReferencesTooltip", "List of actor & component references from selected objects"),
142 | FNewToolMenuDelegate::CreateLambda(
143 | [this](UToolMenu* Menu)
144 | {
145 | const auto SubMenuOutgoing = FToolMenuEntry::InitSubMenu(
146 | FName("CtrlReferenceVisualizerOutgoing"),
147 | LOCTEXT("OutgoingReferences", "Outgoing"),
148 | LOCTEXT("OutgoingReferencesTooltip", "List of actor & component references from selected objects"),
149 | FNewToolMenuDelegate::CreateRaw(this, &FCrvModule::MakeReferenceListSubMenu, ECrvDirection::Outgoing),
150 | FToolUIActionChoice(),
151 | EUserInterfaceActionType::None,
152 | false,
153 | FSlateIcon(FAppStyle::GetAppStyleSetName(), "BlendSpaceEditor.ArrowRight")
154 | );
155 | const auto SubMenuIncoming = FToolMenuEntry::InitSubMenu(
156 | FName("CtrlReferenceVisualizerIncoming"),
157 | LOCTEXT("IncomingReferences", "Incoming"),
158 | LOCTEXT("IncomingReferencesTooltip", "List of incoming actor & component references to selected objects"),
159 | FNewToolMenuDelegate::CreateRaw(this, &FCrvModule::MakeReferenceListSubMenu, ECrvDirection::Incoming),
160 | FToolUIActionChoice(),
161 | EUserInterfaceActionType::None,
162 | false,
163 | FSlateIcon(FAppStyle::GetAppStyleSetName(), "BlendSpaceEditor.ArrowLeft")
164 | );
165 | Menu->AddMenuEntry(SubMenuOutgoing.Name, SubMenuOutgoing);
166 | Menu->AddMenuEntry(SubMenuIncoming.Name, SubMenuIncoming);
167 | Menu->AddMenuEntry(FName(), FToolMenuEntry::InitSeparator(NAME_None));
168 |
169 | const auto SubMenuOptions = FToolMenuEntry::InitSubMenu(
170 | FName("CtrlReferenceVisualizerOptions"),
171 | LOCTEXT("Options", "Options"),
172 | LOCTEXT("OptionsTooltip", "More Options"),
173 | FNewToolMenuDelegate::CreateRaw(this, &FCrvModule::MakeActorOptionsSubmenu),
174 | FToolUIActionChoice(),
175 | EUserInterfaceActionType::None,
176 | false,
177 | FSlateIcon()
178 | );
179 | Menu->AddMenuEntry(SubMenuOptions.Name, SubMenuOptions);
180 | }
181 | ),
182 | FToolUIActionChoice(),
183 | EUserInterfaceActionType::None,
184 | false,
185 | FSlateIcon(FAppStyle::GetAppStyleSetName(), "ContentBrowser.ReferenceVisualizer")
186 | );
187 | auto* ActorContextMenu = UToolMenus::Get()->ExtendMenu("LevelEditor.ActorContextMenu");
188 | auto&& Section = ActorContextMenu->FindOrAddSection(FName("Ctrl"));
189 | Section.AddEntry(SubMenu);
190 | }
191 |
192 | void FCrvModule::MakeActorOptionsSubmenu(UToolMenu* Menu) const
193 | {
194 | const auto CanExecuteIfEnabled = FCanExecuteAction::CreateLambda(
195 | [this]()
196 | {
197 | return FCrvModule::IsEnabled();
198 | }
199 | );
200 | Menu->AddMenuEntry(
201 | FName("CtrlReferenceVisualizer"),
202 | FToolMenuEntry::InitMenuEntry(
203 | FName("CtrlReferenceVisualizer"),
204 | LOCTEXT("CtrlReferenceVisualizer", "Enable"),
205 | LOCTEXT("CtrlReferenceVisualizer_Tooltip", "Toggle Reference Visualizer"),
206 | FSlateIcon(),
207 | FUIAction(
208 | FExecuteAction::CreateLambda(
209 | [this]()
210 | {
211 | auto* Settings = GetMutableDefault();
212 | Settings->ToggleEnabled();
213 | Settings->SaveConfig();
214 | // get level editor viewport
215 | auto* LevelEditor = GEditor->GetEditorSubsystem();
216 | LevelEditor->EditorInvalidateViewports();
217 | }
218 | ),
219 | FCanExecuteAction(),
220 | FIsActionChecked::CreateLambda(
221 | [this]()
222 | {
223 | return FCrvModule::IsEnabled();
224 | }
225 | )
226 | ),
227 | EUserInterfaceActionType::ToggleButton
228 | )
229 | );
230 |
231 | Menu->AddMenuEntry(
232 | FName("CtrlReferenceVisualizer"),
233 | FToolMenuEntry::InitMenuEntry(
234 | FName("CtrlShowIncoming"),
235 | LOCTEXT("ShowIncoming", "Visualize Incoming"),
236 | LOCTEXT("ShowIncoming_Tooltip", "Show incoming references as links in the viewport"),
237 | FSlateIcon(),
238 | FUIAction(
239 | FExecuteAction::CreateLambda(
240 | [this]()
241 | {
242 | const auto Config = GetMutableDefault();
243 | Config->SetShowIncomingReferences(!Config->bShowIncomingReferences);
244 | }
245 | ),
246 | CanExecuteIfEnabled,
247 | FIsActionChecked::CreateLambda(
248 | [this]()
249 | {
250 | return GetDefault()->bShowIncomingReferences;
251 | }
252 | )
253 | ),
254 | EUserInterfaceActionType::ToggleButton
255 | )
256 | );
257 |
258 | Menu->AddMenuEntry(
259 | FName("CtrlReferenceVisualizer"),
260 | FToolMenuEntry::InitMenuEntry(
261 | FName("CtrlShowOutgoing"),
262 | LOCTEXT("ShowOutgoing", "Visualize Outgoing"),
263 | LOCTEXT("ShowOutgoing_Tooltip", "Show outgoing references as links in the viewport"),
264 | FSlateIcon(),
265 | FUIAction(
266 | FExecuteAction::CreateLambda(
267 | [this]()
268 | {
269 | const auto Config = GetMutableDefault();
270 | Config->SetShowOutgoingReferences(!Config->bShowOutgoingReferences);
271 | }
272 | ),
273 | CanExecuteIfEnabled,
274 | FIsActionChecked::CreateLambda(
275 | [this]()
276 | {
277 | return GetDefault()->bShowOutgoingReferences;
278 | }
279 | )
280 | ),
281 | EUserInterfaceActionType::ToggleButton
282 | )
283 | );
284 |
285 | Menu->AddMenuEntry(
286 | FName("CtrlReferenceVisualizer"),
287 | FToolMenuEntry::InitMenuEntry(
288 | FName("CtrlRefresh"),
289 | LOCTEXT("Refresh", "Refresh"),
290 | LOCTEXT("Refresh_Tooltip", "Refresh References"),
291 | FSlateIcon(),
292 | FUIAction(
293 | FExecuteAction::CreateLambda(
294 | [this]()
295 | {
296 | const auto Config = GetMutableDefault();
297 | Config->Refresh();
298 | }
299 | ),
300 | CanExecuteIfEnabled
301 | ),
302 | EUserInterfaceActionType::Button
303 | )
304 | );
305 |
306 | Menu->AddMenuEntry(
307 | FName("CtrlReferenceVisualizerSettings"),
308 | GetSettingsMenuEntry()
309 | );
310 | }
311 |
312 | void FCrvModule::InitLevelMenus() const
313 | {
314 | const auto Menu = UToolMenus::Get()->ExtendMenu("LevelEditor.LevelEditorToolBar.PlayToolBar");
315 | auto& Section = Menu->FindOrAddSection("PluginTools");
316 | if (!Section.FindEntry("CtrlMenuButton"))
317 | {
318 | Section.AddEntry(
319 | FToolMenuEntry::InitComboButton(
320 | "CtrlMenuButton",
321 | FToolUIActionChoice(),
322 | FOnGetContent::CreateLambda(
323 | [this]() -> TSharedRef
324 | {
325 | const FToolMenuContext MenuContext;
326 | return UToolMenus::Get()->GenerateWidget("Ctrl.CtrlMenu", MenuContext);
327 | }
328 | ),
329 | LOCTEXT("CtrlMenuEntry", "Ctrl"),
330 | LOCTEXT("CtrlMenuEntry", "Ctrl Tools"),
331 | FSlateIcon(
332 | FCrvStyle::Get()->GetStyleSetName(),
333 | "Ctrl.TabIcon"
334 | )
335 | )
336 | );
337 | }
338 |
339 | const auto InNewToolMenu = UToolMenus::Get()->ExtendMenu("Ctrl.CtrlMenu");
340 |
341 | auto ReferenceVisualizerSubMenu = FToolMenuEntry::InitSubMenu(
342 | "CtrlReferenceVisualizerSubMenu",
343 | LOCTEXT("CtrlReferenceVisualizerSubMenu", "Reference Visualizer"),
344 | LOCTEXT("CtrlReferenceVisualizerSubMenu_Tooltip", "Ctrl Reference Visualizer Actions"),
345 | FNewToolMenuChoice(
346 | FNewToolMenuDelegate::CreateLambda(
347 | [this](UToolMenu* SubMenu)
348 | {
349 | const auto MenuSection = SubMenu->AddSection("CtrlReferenceVisualizerSection", LOCTEXT("CtrlReferenceVisualizerSection", "Reference Visualizer"));
350 | SubMenu->AddMenuEntry(
351 | MenuSection.Name,
352 | FToolMenuEntry::InitMenuEntry(
353 | FName("CtrlReferenceVisualizer"),
354 | LOCTEXT("CtrlReferenceVisualizer", "Enable"),
355 | LOCTEXT("CtrlReferenceVisualizer_Tooltip", "Toggle Reference Visualizer"),
356 | FSlateIcon(),
357 | FUIAction(
358 | FExecuteAction::CreateLambda(
359 | [this]()
360 | {
361 | auto* Settings = GetMutableDefault();
362 | Settings->ToggleEnabled();
363 | Settings->SaveConfig();
364 | // get level editor viewport
365 | auto* LevelEditor = GEditor->GetEditorSubsystem();
366 | LevelEditor->EditorInvalidateViewports();
367 | }
368 | ),
369 | FCanExecuteAction(),
370 | FIsActionChecked::CreateLambda(
371 | [this]()
372 | {
373 | return GetDefault()->bIsEnabled;
374 | }
375 | )
376 | ),
377 | EUserInterfaceActionType::ToggleButton
378 | )
379 | );
380 |
381 | SubMenu->AddMenuEntry(MenuSection.Name, FToolMenuEntry::InitSeparator(NAME_None));
382 | SubMenu->AddMenuEntry(MenuSection.Name, GetSettingsMenuEntry());
383 | }
384 | )
385 | )
386 | );
387 | ReferenceVisualizerSubMenu.Icon = FSlateIconFinder::FindIcon("BTEditor.Graph.BTNode.Task.RunBehavior.Icon");
388 | InNewToolMenu->AddMenuEntry("CtrlEditorSubmenu", ReferenceVisualizerSubMenu);
389 | }
390 |
391 | class SCrvDialog : public SCompoundWidget
392 | {
393 | public:
394 | SLATE_BEGIN_ARGS(SCrvDialog) {}
395 | SLATE_END_ARGS()
396 |
397 | // Constructs this widget with InArgs
398 | void Construct(const FArguments& InArgs);
399 |
400 | // virtual ~SCrvDialog() override;
401 | };
402 |
403 | void SCrvDialog::Construct(const FArguments& InArgs)
404 | {
405 | ChildSlot
406 | [
407 | SNew(SBorder)
408 | .BorderImage(FAppStyle::GetBrush("DetailsView.CategoryTop"))
409 | .Padding(FMargin(0.0f, 3.0f, 1.0f, 0.0f))
410 | [
411 | SNew(SHorizontalBox)
412 | + SHorizontalBox::Slot()
413 | .FillWidth(1.0f)
414 | [
415 | SNew(STextBlock)
416 | .Text(LOCTEXT("CtrlReferenceVisualizer", "Content"))
417 | ]
418 | ]
419 | ];
420 |
421 | }
422 |
423 | void FCrvModule::InitTab()
424 | {
425 | // create and register tab
426 | const FText TitleText = LOCTEXT("CrvWindowTitle", "Ctrl Reference Visualizer");
427 | // Create the window to pick the class
428 | TSharedRef CrvWindow = SNew(SWindow)
429 | .Title(TitleText)
430 | .SizingRule(ESizingRule::UserSized)
431 | .ClientSize(FVector2D(1000.f, 700.f))
432 | .AutoCenter(EAutoCenter::PreferredWorkArea)
433 | .SupportsMinimize(false);
434 |
435 | TSharedRef Dialog = SNew(SCrvDialog);
436 |
437 | CrvWindow->SetContent(Dialog);
438 | TSharedPtr RootWindow = FGlobalTabmanager::Get()->GetRootWindow();
439 | if (RootWindow.IsValid())
440 | {
441 | FSlateApplication::Get().AddWindowAsNativeChild(CrvWindow, RootWindow.ToSharedRef());
442 | }
443 | else
444 | {
445 | FSlateApplication::Get().AddWindow(CrvWindow);
446 | }
447 |
448 |
449 | }
450 |
451 | FToolMenuEntry FCrvModule::GetSettingsMenuEntry() const
452 | {
453 | return FToolMenuEntry::InitMenuEntry(
454 | FName("CtrlReferenceVisualizerSettings"),
455 | LOCTEXT("CtrlReferenceVisualizerSettings", "Settings"),
456 | LOCTEXT("CtrlReferenceVisualizerSettings_Tooltip", "Open Reference Visualizer Settings"),
457 | FSlateIconFinder::FindIcon("LevelViewport.AdvancedSettings"),
458 | FUIAction(
459 | FExecuteAction::CreateLambda(
460 | [this]()
461 | {
462 | FModuleManager::LoadModuleChecked("Settings").ShowViewer("Editor", "Ctrl", "Reference Visualizer");
463 | }
464 | )
465 | )
466 | );
467 | }
468 |
469 |
470 | void FCrvModule::OnPostEngineInit()
471 | {
472 | InitCategories();
473 | FCrvCommands::Register();
474 | InitActorMenu();
475 | InitLevelMenus();
476 |
477 | }
478 |
479 | void FCrvModule::StartupModule()
480 | {
481 | FCrvStyle::Startup();
482 | FCrvStyle::Register();
483 | FCoreDelegates::OnPostEngineInit.AddRaw(this, &FCrvModule::OnPostEngineInit);
484 | }
485 |
486 | bool FCrvModule::IsEnabled()
487 | {
488 | return GetDefault()->IsEnabled();
489 | }
490 |
491 | bool FCrvModule::IsDebugEnabled()
492 | {
493 | return IsEnabled() && GetDefault()->bDebugEnabled;
494 | }
495 |
496 | void FCrvModule::ShutdownModule()
497 | {
498 | if (!UObjectInitialized()) { return; }
499 | SettingsModifiedHandle.Reset();
500 | FCrvCommands::Unregister();
501 | FCrvStyle::Shutdown();
502 | }
503 |
504 | void FCrvModule::AddTargetComponentClass(UClass* Class)
505 | {
506 | auto* Settings = GetMutableDefault();
507 | Settings->AddComponentClass(Class);
508 | }
509 |
510 | void FCrvModule::InitCategories()
511 | {
512 | FPropertyEditorModule& PropertyModule = FModuleManager::GetModuleChecked("PropertyEditor");
513 | auto IsRelevantClass = [](UClass* Class)
514 | {
515 | return Class->GetClassPathName().ToString().StartsWith("/Script/CtrlReferenceVisualizer");
516 | };
517 |
518 | for (auto* const Class : TObjectRange())
519 | {
520 | if (!IsRelevantClass(Class)) { continue; }
521 | const TSharedRef Section = PropertyModule.FindOrCreateSection(
522 | Class->GetFName(),
523 | TEXT("CtrlReferenceVisualizer"),
524 | LOCTEXT("CtrlReferenceVisualizer", "💛 CTRL Reference Visualizer")
525 | );
526 |
527 | // Find all categories for this class
528 | for (TFieldIterator It(Class, EFieldIteratorFlags::IncludeSuper); It; ++It)
529 | {
530 | const auto* const Property = *It;
531 | if (!IsRelevantClass(Property->GetOwnerClass())) { continue; }
532 |
533 | auto Category = FObjectEditorUtils::GetCategoryFName(Property).ToString();
534 |
535 | // prevent crash
536 | if (Category.Contains(TEXT("|")))
537 | {
538 | Category = Category.Left(Category.Find(TEXT("|")));
539 | }
540 | Section->AddCategory(FName(*Category.TrimStartAndEnd()));
541 | }
542 | Section->AddCategory(TEXT("Default"));
543 | Section->AddCategory(Class->GetFName());
544 | }
545 | }
546 | #undef LOCTEXT_NAMESPACE
547 |
548 | IMPLEMENT_MODULE(FCrvModule, CtrlReferenceVisualizer)
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Private/ReferenceVisualizerComponent.cpp:
--------------------------------------------------------------------------------
1 | #include "ReferenceVisualizerComponent.h"
2 |
3 | #include "CrvRefCache.h"
4 | #include "CrvSettings.h"
5 | #include "Selection.h"
6 |
7 | #if ENGINE_MAJOR_VERSION == 5 && ENGINE_MINOR_VERSION >= 2
8 | // Added in UE 5.2
9 | #include "Materials/MaterialRenderProxy.h"
10 | #endif
11 |
12 | void UReferenceVisualizerEditorSubsystem::OnObjectModified(UObject* Object)
13 | {
14 | if (Cache->WeakRootObjects.Contains(Object))
15 | {
16 | Cache->Invalidate(FString::Printf(TEXT("Object modified: %s"), *GetDebugName(Object)));
17 | }
18 | }
19 |
20 | void UReferenceVisualizerEditorSubsystem::OnPropertyChanged(UObject* Object, FPropertyChangedEvent& PropertyChangedEvent)
21 | {
22 | const FString PropertyChangeDescription = PropertyChangedEvent.GetMemberPropertyName().ToString();
23 | if (Cache->WeakRootObjects.Contains(Object))
24 | {
25 | Cache->Invalidate(FString::Printf(TEXT("Property modified: %s %s"), *GetDebugName(Object), *PropertyChangeDescription));
26 | }
27 | }
28 |
29 | void UReferenceVisualizerEditorSubsystem::OnSettingsModified(UObject* Object, FProperty* Property)
30 | {
31 | UpdateCache();
32 | }
33 |
34 | UReferenceVisualizerEditorSubsystem::UReferenceVisualizerEditorSubsystem()
35 | {
36 | Cache = CreateDefaultSubobject(TEXT("Cache"));
37 | MenuCache = CreateDefaultSubobject(TEXT("MenuCache"));
38 | }
39 |
40 | void UReferenceVisualizerEditorSubsystem::Initialize(FSubsystemCollectionBase& Collection)
41 | {
42 | Super::Initialize(Collection);
43 | UCrvSettings* Settings = GetMutableDefault();
44 | Settings->OnModified.RemoveAll(this);
45 | SettingsModifiedHandle.Reset();
46 | SettingsModifiedHandle = Settings->OnModified.AddUObject(this, &UReferenceVisualizerEditorSubsystem::OnSettingsModified);
47 | // Settings->AddComponentClass(UReferenceVisualizerComponent::StaticClass());
48 | // add visualizer to actors when editor selection is changed
49 | USelection::SelectionChangedEvent.AddUObject(this, &UReferenceVisualizerEditorSubsystem::OnSelectionChanged);
50 | FCoreUObjectDelegates::OnObjectModified.AddUObject(this, &UReferenceVisualizerEditorSubsystem::OnObjectModified);
51 | FCoreUObjectDelegates::OnObjectPropertyChanged.AddUObject(this, &UReferenceVisualizerEditorSubsystem::OnPropertyChanged);
52 | }
53 |
54 | void UReferenceVisualizerEditorSubsystem::OnSelectionChanged(UObject* SelectionObject)
55 | {
56 | if (bIsRefreshingSelection)
57 | {
58 | return;
59 | }
60 | TGuardValue ReentrantGuard(bIsRefreshingSelection, true);
61 | UpdateCache();
62 | }
63 |
64 | void UReferenceVisualizerEditorSubsystem::Deinitialize()
65 | {
66 | Super::Deinitialize();
67 | }
68 |
69 | void UReferenceVisualizerEditorSubsystem::UpdateCache()
70 | {
71 | Cache->ScheduleUpdate();
72 | }
73 |
74 | FDebugRenderSceneProxy* UReferenceVisualizerComponent::CreateDebugSceneProxy()
75 | {
76 | FCtrlReferenceVisualizerSceneProxy* DebugProxy = new FCtrlReferenceVisualizerSceneProxy(this);
77 | Lines.Reset();
78 | CreateLines(GetOwner(), ECrvDirection::Outgoing);
79 | CreateLines(GetOwner(), ECrvDirection::Incoming);
80 | DebugProxy->DrawLines(Lines);
81 | Lines.Compact();
82 | return DebugProxy;
83 | }
84 |
85 | void UReferenceVisualizerComponent::CreateLines(
86 | const UObject* RootObject,
87 | const ECrvDirection Direction
88 | )
89 | {
90 | const auto Config = GetDefault();
91 | if (Direction == ECrvDirection::Outgoing && !Config->bShowOutgoingReferences || Direction == ECrvDirection::Incoming && !Config->bShowIncomingReferences)
92 | {
93 | return;
94 | }
95 |
96 | FVector BaseOffset(0, 0, 10);
97 | TObjectPtr RootObjectPtr = const_cast(RootObject);
98 | auto References = CrvEditorSubsystem->Cache->GetReferences(RootObjectPtr, Direction);
99 | if (!CrvEditorSubsystem->Cache->Contains(RootObjectPtr)) { return; }
100 | if (References.Num() == 0) { return; }
101 | // when multiple roots are selected, don't show incoming references that are also outgoing to same node
102 | if (Direction == ECrvDirection::Incoming && CrvEditorSubsystem->Cache->WeakRootObjects.Num() > 1)
103 | {
104 | References = TSet(References.Array().FilterByPredicate([this, RootObjectPtr](UObject* Ref)
105 | {
106 | const auto OutReferences = CrvEditorSubsystem->Cache->GetReferences(Ref, ECrvDirection::Outgoing);
107 | if (!OutReferences.Num()) { return true; }
108 | return !OutReferences.Contains(RootObjectPtr);
109 | }));
110 | if (References.Num() == 0) { return; }
111 | }
112 | const FVector SourceLocation = FCtrlReferenceVisualizerSceneProxy::GetObjectLocation(RootObject);
113 | // draw links to referenced objects
114 | Lines.Reserve(Lines.Num() + References.Num());
115 | UE_CLOG(FCrvModule::IsDebugEnabled(), LogCrv, Log, TEXT("References %s %s"), Direction == ECrvDirection::Outgoing ? TEXT(" Out ") : TEXT(" In "), *CtrlRefViz::GetDebugName(RootObject));
116 | for (const auto DstRef : References)
117 | {
118 | UE_CLOG(FCrvModule::IsDebugEnabled(), LogCrv, Log, TEXT("\t%s"), *CtrlRefViz::GetDebugName(DstRef));
119 | auto DstLocation = FCtrlReferenceVisualizerSceneProxy::GetObjectLocation(DstRef);
120 | auto Offset = Direction == ECrvDirection::Outgoing ? BaseOffset : -BaseOffset;
121 | auto Line = CreateLine(SourceLocation + Offset, DstLocation + Offset, Direction, DstRef->GetClass());
122 | Lines.Add(Line);
123 | }
124 | }
125 |
126 | FCrvLine UReferenceVisualizerComponent::CreateLine(const FVector& SrcOrigin, const FVector& DstOrigin, const ECrvDirection Direction, const UClass* Type)
127 | {
128 | if (Direction == ECrvDirection::Incoming)
129 | {
130 | Swap(SrcOrigin, DstOrigin);
131 | }
132 | const FVector LineDirection = (DstOrigin - SrcOrigin).GetSafeNormal();
133 | const auto Config = GetDefault();
134 | float Distance = FVector::Distance(SrcOrigin, DstOrigin) - (Config->Style.CircleRadius * 2);
135 | Distance = FMath::Max(1.f, Distance); // clamp distance to be at least 1
136 | auto SpacedSrcOrigin = SrcOrigin + LineDirection * Config->Style.CircleRadius;
137 | auto SpacedDstOrigin = SpacedSrcOrigin + LineDirection * Distance;
138 | auto LineStyle = Config->GetLineStyle(Direction);
139 | auto [LineType, LineColor, LineColorComponent, LineColorObject, LineThickness, ArrowSize, DepthPriority] = LineStyle;
140 | auto Color = LineColor;
141 | if (Type->IsChildOf(AActor::StaticClass()))
142 | {
143 | Color = LineColor;
144 | }
145 | else if (Type->IsChildOf(UActorComponent::StaticClass()))
146 | {
147 | Color = LineColorComponent;
148 | }
149 | else
150 | {
151 | Color = LineColorObject;
152 | }
153 | FCrvLine Line;
154 | Line.Start = SpacedSrcOrigin;
155 | Line.End = SpacedDstOrigin;
156 | Line.Style = LineStyle;
157 | Line.Color = Color.ToFColor(true);
158 | return Line;
159 | }
160 |
161 | void FCtrlReferenceVisualizerSceneProxy::GetDynamicMeshElementsForView(
162 | const FSceneView* View,
163 | const int32 ViewIndex,
164 | const FSceneViewFamily& ViewFamily,
165 | const uint32 VisibilityMap,
166 | FMeshElementCollector& Collector,
167 | FMaterialCache& DefaultMaterialCache,
168 | FMaterialCache& SolidMeshMaterialCache
169 | ) const
170 | {
171 | FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);
172 |
173 | // Draw Lines
174 | const int32 LinesNum = Lines.Num();
175 | PDI->AddReserveLines(SDPG_World, LinesNum, false, false);
176 | for (const FDebugLine& Line : Lines)
177 | {
178 | PDI->DrawLine(Line.Start, Line.End, Line.Color, DepthPriorityGroup, Line.Thickness, 0, Line.Thickness > 0);
179 | }
180 |
181 | // Draw Dashed Lines
182 | for (const FDashedLine& Dash : DashedLines)
183 | {
184 | DrawDashedLine(PDI, Dash.Start, Dash.End, Dash.Color, Dash.DashSize, DepthPriorityGroup);
185 | }
186 |
187 | // Draw Arrows
188 | const uint32 ArrowsNum = ArrowLines.Num();
189 | PDI->AddReserveLines(DepthPriorityGroup, 5 * ArrowsNum, false, false);
190 | for (const FArrowLine& ArrowLine : ArrowLines)
191 | {
192 | // draw a pretty arrow
193 | FVector Dir = ArrowLine.End - ArrowLine.Start;
194 | const float DirMag = Dir.Size();
195 | Dir /= DirMag;
196 | FVector YAxis, ZAxis;
197 | Dir.FindBestAxisVectors(YAxis, ZAxis);
198 | FMatrix ArrowTM(Dir, YAxis, ZAxis, ArrowLine.Start);
199 | DrawDirectionalArrow(
200 | PDI,
201 | ArrowTM,
202 | ArrowLine.Color,
203 | DirMag,
204 | 8.f,
205 | DepthPriorityGroup,
206 | 1.f
207 | );
208 | }
209 |
210 | // Draw Stars
211 | for (const FWireStar& Star : Stars)
212 | {
213 | Star.Draw(PDI);
214 | }
215 |
216 | // Draw Cylinders
217 | for (const FWireCylinder& Cylinder : Cylinders)
218 | {
219 | Cylinder.Draw(PDI, (Cylinder.DrawTypeOverride != EDrawType::Invalid) ? Cylinder.DrawTypeOverride : DrawType, DrawAlpha, DefaultMaterialCache, ViewIndex, Collector);
220 | }
221 |
222 | // Draw Boxes
223 | for (const FDebugBox& Box : Boxes)
224 | {
225 | Box.Draw(PDI, (Box.DrawTypeOverride != EDrawType::Invalid) ? Box.DrawTypeOverride : DrawType, DrawAlpha, DefaultMaterialCache, ViewIndex, Collector);
226 | }
227 |
228 | // Draw Cones
229 | TArray Verts;
230 | for (const FCone& Cone : Cones)
231 | {
232 | Cone.Draw(PDI, (Cone.DrawTypeOverride != EDrawType::Invalid) ? Cone.DrawTypeOverride : DrawType, DrawAlpha, DefaultMaterialCache, ViewIndex, Collector, &Verts);
233 | }
234 |
235 | // Draw spheres
236 | for (const FSphere& Sphere : Spheres)
237 | {
238 | if (PointInView(Sphere.Location, View))
239 | {
240 | Sphere.Draw(PDI, (Sphere.DrawTypeOverride != EDrawType::Invalid) ? Sphere.DrawTypeOverride : DrawType, DrawAlpha, DefaultMaterialCache, ViewIndex, Collector);
241 | }
242 | }
243 |
244 | // Draw Capsules
245 | for (const FCapsule& Capsule : Capsules)
246 | {
247 | if (PointInView(Capsule.Base, View))
248 | {
249 | Capsule.Draw(PDI, (Capsule.DrawTypeOverride != EDrawType::Invalid) ? Capsule.DrawTypeOverride : DrawType, DrawAlpha, DefaultMaterialCache, ViewIndex, Collector);
250 | }
251 | }
252 |
253 | // Draw Meshes
254 | for (const FMesh& Mesh : Meshes)
255 | {
256 | FDynamicMeshBuilder MeshBuilder(View->GetFeatureLevel());
257 | MeshBuilder.AddVertices(Mesh.Vertices);
258 | MeshBuilder.AddTriangles(Mesh.Indices);
259 |
260 | // auto&& MeshMaterialCache = Mesh.Color.A == 255 ? SolidMeshMaterialCache : DefaultMaterialCache;
261 | // MeshBuilder.GetMesh(FMatrix::Identity, MeshMaterialCache[Mesh.Color], SDPG_World, false, false, ViewIndex, Collector);
262 | // Parent caches these (only within this function) but let's assume that's not worth it. Will people really
263 | // have lots of meshes with a shared colour in this single context to make it worth it?
264 | const auto MatRenderProxy = new FColoredMaterialRenderProxy(GEngine->WireframeMaterial->GetRenderProxy(), Mesh.Color);
265 | FDynamicMeshBuilderSettings Settings;
266 | Settings.bWireframe = true;
267 | Settings.bUseSelectionOutline = false;
268 | Settings.bUseWireframeSelectionColoring = true;
269 | MeshBuilder.GetMesh(FMatrix::Identity, MatRenderProxy, DepthPriorityGroup, Settings, nullptr, ViewIndex, Collector);
270 | }
271 | }
272 |
273 | void FCtrlReferenceVisualizerSceneProxy::DrawLines(TSet InLines)
274 | {
275 | for (auto Line : InLines)
276 | {
277 | auto [LineType, LineColor, LineColorComponent, LineColorObject, LineThickness, ArrowSize, DepthPriority] = Line.Style;
278 | auto Direction = (Line.End - Line.Start).GetSafeNormal();
279 | auto Distance = FVector::Distance(Line.Start, Line.End);
280 |
281 | if (LineType == ECrvLineType::Dash)
282 | {
283 | DashedLines.Add(FDebugRenderSceneProxy::FDashedLine(Line.Start, Line.End, Line.Color.ToFColor(true), Distance / 20));
284 | auto ArrowStart = Line.Start + Direction * (Distance - ArrowSize * UE_GOLDEN_RATIO * 2);
285 | ArrowLines.Add(FDebugRenderSceneProxy::FArrowLine(ArrowStart, Line.End, Line.Color.ToFColor(true)));
286 | }
287 | else if (LineType == ECrvLineType::Arrow)
288 | {
289 | ArrowLines.Add(FDebugRenderSceneProxy::FArrowLine(Line.Start, Line.End, Line.Color.ToFColor(true)));
290 | }
291 | }
292 | }
293 |
294 | FVector FCtrlReferenceVisualizerSceneProxy::GetComponentLocation(const UActorComponent* Component)
295 | {
296 | if (!IsValid(Component))
297 | {
298 | UE_LOG(LogCrv, Warning, TEXT("Invalid component passed to %s"), *FString(__FUNCTION__));
299 | return FVector::ZeroVector;
300 | }
301 | const auto Owner = Component->GetOwner();
302 | // use component location if it is a scene component
303 | const auto SceneComponent = Cast(Component);
304 | return SceneComponent ? SceneComponent->GetComponentLocation() : GetActorOrigin(Owner);
305 | }
306 |
307 | FVector FCtrlReferenceVisualizerSceneProxy::GetActorOrigin(const AActor* Actor)
308 | {
309 | if (!IsValid(Actor))
310 | {
311 | UE_LOG(LogCrv, Warning, TEXT("Invalid actor passed to %s"), *FString(__FUNCTION__));
312 | return FVector::ZeroVector;
313 | }
314 | const auto Config = GetDefault();
315 | if (Config->bUseActorBounds)
316 | {
317 | const auto BoundingBox = Actor->GetComponentsBoundingBox(Config->bIncludeNonCollidingBounds, Config->bIncludeChildActorsInBounds);
318 | if (BoundingBox.IsValid && !BoundingBox.ContainsNaN())
319 | {
320 | FVector Center;
321 | FVector Extents;
322 | BoundingBox.GetCenterAndExtents(Center, Extents);
323 | if (!Extents.IsNearlyZero())
324 | {
325 | return Center;
326 | }
327 | }
328 | }
329 | return Actor->GetActorLocation();
330 | }
331 |
332 | FCtrlReferenceVisualizerSceneProxy::FCtrlReferenceVisualizerSceneProxy(const UPrimitiveComponent* InComponent): FDebugRenderSceneProxy(InComponent) {}
333 |
334 | SIZE_T FCtrlReferenceVisualizerSceneProxy::GetTypeHash() const
335 | {
336 | static size_t UniquePointer;
337 | return reinterpret_cast(&UniquePointer);
338 | }
339 |
340 | FPrimitiveViewRelevance FCtrlReferenceVisualizerSceneProxy::GetViewRelevance(const FSceneView* View) const
341 | {
342 | FPrimitiveViewRelevance Result;
343 | Result.bDrawRelevance = IsShown(View);
344 | Result.bDynamicRelevance = true;
345 | Result.bShadowRelevance = false;
346 | Result.bStaticRelevance = true;
347 | Result.bEditorPrimitiveRelevance = true;
348 | Result.bEditorVisualizeLevelInstanceRelevance = true;
349 | return Result;
350 | }
351 |
352 | uint32 FCtrlReferenceVisualizerSceneProxy::GetMemoryFootprint() const
353 | {
354 | return sizeof(*this) + GetAllocatedSize();
355 | }
356 |
357 | FVector FCtrlReferenceVisualizerSceneProxy::GetObjectLocation(const UObject* Object)
358 | {
359 | if (const auto Component = Cast(Object))
360 | {
361 | return GetComponentLocation(Component);
362 | }
363 | else if (const auto Actor = Cast(Object))
364 | {
365 | return GetActorOrigin(Actor);
366 | }
367 | else if (const auto OwnerComponent = Object->GetTypedOuter())
368 | {
369 | return GetComponentLocation(OwnerComponent);
370 | }
371 | else if (const auto OwnerActor = Object->GetTypedOuter())
372 | {
373 | return GetActorOrigin(OwnerActor);
374 | }
375 |
376 | return FVector::ZeroVector;
377 | }
378 |
379 | FBoxSphereBounds UReferenceVisualizerComponent::CalcBounds(const FTransform& LocalToWorld) const
380 | {
381 | auto SphereBounds = Super::CalcBounds(LocalToWorld);
382 | if (!GetOwner()) { return SphereBounds; }
383 | if (!CrvEditorSubsystem)
384 | {
385 | return SphereBounds;
386 | }
387 | const auto World = GetWorld();
388 | if (!World) { return SphereBounds; }
389 | if (!CrvEditorSubsystem->Cache->Contains(GetOwner()))
390 | {
391 | return SphereBounds;
392 | }
393 |
394 | FBoxSphereBounds::Builder DebugBoundsBuilder;
395 | DebugBoundsBuilder += SphereBounds;
396 | FVector Origin;
397 | FVector BoxExtent;
398 | GetOwner()->GetActorBounds(false, Origin, BoxExtent);
399 | FBox ActorBounds = FBox::BuildAABB(Origin, BoxExtent);
400 | DebugBoundsBuilder += ActorBounds;
401 | for (auto [Start, End, Color, Style] : Lines)
402 | {
403 | DebugBoundsBuilder += Start;
404 | DebugBoundsBuilder += End;
405 | }
406 | FBoxSphereBounds NewBounds = DebugBoundsBuilder; //.TransformBy(LocalToWorld);
407 | NewBounds = NewBounds.ExpandBy(100);
408 | return NewBounds;
409 | }
410 |
411 | void UReferenceVisualizerComponent::OnRegister()
412 | {
413 | Super::OnRegister();
414 | CrvEditorSubsystem = GEditor->GetEditorSubsystem();
415 | CrvEditorSubsystem->Cache->OnCacheUpdated.AddUObject(this, &UReferenceVisualizerComponent::MarkRenderStateDirty);
416 | CrvEditorSubsystem->Cache->ScheduleUpdate();
417 | }
418 |
419 | void UReferenceVisualizerComponent::OnUnregister()
420 | {
421 | Super::OnUnregister();
422 | if (CrvEditorSubsystem)
423 | {
424 | CrvEditorSubsystem->Cache->ScheduleUpdate();
425 | }
426 | }
427 |
428 | UReferenceVisualizerComponent::UReferenceVisualizerComponent()
429 | {
430 | PrimaryComponentTick.bCanEverTick = false;
431 | bVisibleInReflectionCaptures = false;
432 | bVisibleInRayTracing = false;
433 | bVisibleInRealTimeSkyCaptures = false;
434 | bAutoActivate = true;
435 | AlwaysLoadOnClient = false;
436 | bIsEditorOnly = true;
437 |
438 | SetHiddenInGame(true);
439 |
440 | #if WITH_EDITOR
441 | // Do not show bounding box for better visibility
442 | SetIsVisualizationComponent(true);
443 |
444 | // Disable use of bounds to focus to avoid de-zoom
445 | SetIgnoreBoundsForEditorFocus(true);
446 |
447 | #endif
448 | #if WITH_EDITORONLY_DATA
449 | // Show sprite for this component to visualize it when empty
450 | bVisualizeComponent = true;
451 | #endif
452 | }
453 |
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Public/CrvCommands.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "CoreMinimal.h"
4 | #include "Framework/Commands/Commands.h"
5 |
6 | class FCrvCommands : public TCommands
7 | {
8 | public:
9 | TSharedPtr ToggleReferenceVisualizer;
10 | FCrvCommands()
11 | : TCommands(
12 | TEXT("FCrvCommands"),
13 | NSLOCTEXT("ReferenceVisualizer", "ReferenceVisualizerCommands", "Reference Visualizer Commands"),
14 | NAME_None,
15 | FAppStyle::GetAppStyleSetName()
16 | )
17 | {
18 | }
19 |
20 | virtual ~FCrvCommands() override = default;
21 |
22 | void ToggleEnabled_Execute();
23 | bool ToggleEnabled_CanExecute();
24 | bool ToggleEnabled_IsChecked();
25 | virtual void RegisterCommands() override;
26 |
27 | TSharedPtr CommandList;
28 | };
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Public/CrvHitProxy.h:
--------------------------------------------------------------------------------
1 |
2 | #pragma once
3 |
4 | #include "CoreMinimal.h"
5 | #include "ComponentVisualizer.h"
6 |
7 | struct CTRLREFERENCEVISUALIZER_API HCrvHitProxy : public HComponentVisProxy
8 | {
9 | DECLARE_HIT_PROXY();
10 | const TWeakObjectPtr LeafObject;
11 | const TWeakObjectPtr RootObject;
12 |
13 | DECLARE_DELEGATE(FOnHitProxyHover)
14 | FOnHitProxyHover OnHover;
15 |
16 | bool IsValid() const
17 | {
18 | return LeafObject.IsValid() && RootObject.IsValid();
19 | }
20 |
21 | HCrvHitProxy(const UActorComponent* ParentComponent, const UObject* InRootObject, const UObject* InLeafObject)
22 | : HComponentVisProxy(ParentComponent, HPP_Foreground),
23 | LeafObject(InLeafObject),
24 | RootObject(InRootObject)
25 | {
26 | }
27 |
28 | virtual EMouseCursor::Type GetMouseCursor() override
29 | {
30 | if (OnHover.IsBound())
31 | {
32 | OnHover.Execute();
33 | }
34 | return EMouseCursor::EyeDropper;
35 | }
36 | };
37 |
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Public/CrvRefSearch.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "CoreMinimal.h"
4 | #include "CrvUtils.h"
5 | #include "UObject/ReferenceChainSearch.h"
6 |
7 | using namespace CtrlRefViz;
8 |
9 | struct FCrvMenuItem
10 | {
11 | FName Name;
12 | FText Label;
13 | FText ToolTip;
14 | FSlateIcon Icon;
15 | FUIAction Action;
16 | };
17 |
18 | namespace CtrlRefViz::Search
19 | {
20 | FString LexToString(const FReferenceChainSearch::FReferenceChain* Chain);
21 | bool IsExternal(const FReferenceChainSearch::FReferenceChain* Chain);
22 | FCrvSet FindTargetObjects(UObject* RootObject);
23 | }
24 |
25 | class FCrvRefSearch
26 | {
27 | public:
28 | static FCrvSet GetSelectionSet();
29 |
30 | static void FindOutRefs(FCrvSet RootObjects, FCrvObjectGraph& Graph);
31 | static void FindInRefs(FCrvSet RootObjects, FCrvObjectGraph& Graph);
32 |
33 | static FCrvMenuItem MakeMenuEntry(const UObject* Parent, const UObject* Object);
34 | static bool CanDisplayReference(const UObject* RootObject, const UObject* LeafObject);
35 | };
36 |
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Public/CrvSettings.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "CoreMinimal.h"
4 | #include "Engine/DeveloperSettingsBackedByCVars.h"
5 | #include "Templates/TypeHash.h"
6 | #include "UObject/ReferenceChainSearch.h"
7 |
8 | #include "CrvSettings.generated.h"
9 |
10 | UENUM()
11 | enum class ECrvDirection: uint8
12 | {
13 | Incoming,
14 | Outgoing,
15 | };
16 |
17 | UENUM()
18 | enum class ECrvMode: uint8
19 | {
20 | OnlySelected, // Only show references to/from the selected actor or component
21 | SelectedOrAll, // Show references to/from the selected actor or component, or all references if nothing is selected
22 | All, // Show all references
23 | };
24 |
25 | UENUM()
26 | enum class ECrvLineType: uint8
27 | {
28 | Dash,
29 | Arrow,
30 | };
31 |
32 | USTRUCT()
33 | struct FCrvLineStyle
34 | {
35 | GENERATED_BODY()
36 |
37 | FCrvLineStyle() = default;
38 |
39 | FCrvLineStyle(
40 | const ECrvLineType LineType,
41 | const FLinearColor LineColor,
42 | const FLinearColor LineColorComponent,
43 | const FLinearColor LineColorObject,
44 | const float LineThickness,
45 | const float ArrowSize,
46 | const ESceneDepthPriorityGroup DepthPriority
47 | )
48 | : LineType(LineType),
49 | LineColor(LineColor),
50 | LineColorComponent(LineColorComponent),
51 | LineColorObject(LineColorObject),
52 | LineThickness(LineThickness),
53 | ArrowSize(ArrowSize),
54 | DepthPriority(DepthPriority) {}
55 |
56 | UPROPERTY(Config, EditAnywhere, Category = "Style | General")
57 | ECrvLineType LineType = ECrvLineType::Arrow;
58 |
59 | UPROPERTY(Config, EditAnywhere, Category = "Style | General", DisplayName = "Line Color")
60 | FLinearColor LineColor = FLinearColor::Green;
61 |
62 | UPROPERTY(Config, EditAnywhere, Category = "Style | General", DisplayName = "Line Color (Component)")
63 | FLinearColor LineColorComponent = FColor::Emerald;
64 |
65 | UPROPERTY(Config, EditAnywhere, Category = "Style | General", DisplayName = "Line Color (Object)")
66 | FLinearColor LineColorObject = FColor::Cyan;
67 |
68 | UPROPERTY(Config, EditAnywhere, Category = "Style | General", meta = (ClampMin = "0", UIMin = "0", UIMax = "10", EditCondition = "LineType != ECrvLineStyle::Dash"))
69 | float LineThickness = 2.f;
70 |
71 | UPROPERTY(Config, EditAnywhere, Category = "Style | General", meta = (ClampMin = "0", UIMin = "0", UIMax = "100", EditCondition = "LineType == ECrvLineStyle::Arrow"))
72 | float ArrowSize = 10.f;
73 |
74 | UPROPERTY(Config, EditAnywhere, Category = "Style | General")
75 | TEnumAsByte DepthPriority = ESceneDepthPriorityGroup::SDPG_Foreground;
76 |
77 | friend bool operator==(const FCrvLineStyle& Lhs, const FCrvLineStyle& RHS)
78 | {
79 | return Lhs.LineType == RHS.LineType
80 | && Lhs.LineColor == RHS.LineColor
81 | && Lhs.LineColorComponent == RHS.LineColorComponent
82 | && Lhs.LineColorObject == RHS.LineColorObject
83 | && Lhs.LineThickness == RHS.LineThickness
84 | && Lhs.ArrowSize == RHS.ArrowSize
85 | && Lhs.DepthPriority == RHS.DepthPriority;
86 | }
87 |
88 | friend bool operator!=(const FCrvLineStyle& Lhs, const FCrvLineStyle& RHS)
89 | {
90 | return !(Lhs == RHS);
91 | }
92 |
93 | friend uint32 GetTypeHash(const FCrvLineStyle& Arg)
94 | {
95 | uint32 Hash = HashCombine(GetTypeHash(Arg.LineType), GetTypeHash(Arg.LineColor));
96 | Hash = HashCombine(Hash, GetTypeHash(Arg.LineColorComponent));
97 | Hash = HashCombine(Hash, GetTypeHash(Arg.LineColorObject));
98 | Hash = HashCombine(Hash, GetTypeHash(Arg.LineThickness));
99 | Hash = HashCombine(Hash, GetTypeHash(Arg.ArrowSize));
100 | Hash = HashCombine(Hash, GetTypeHash(Arg.DepthPriority));
101 | return Hash;
102 | }
103 |
104 | static FCrvLineStyle DefaultOutgoingLineStyle;
105 |
106 | static FCrvLineStyle DefaultIncomingLineStyle;
107 | };
108 |
109 |
110 | USTRUCT()
111 | struct FCrvStyleSettings
112 | {
113 | GENERATED_BODY()
114 |
115 | FCrvStyleSettings();
116 |
117 | UPROPERTY(Config, EditAnywhere, Category = "Style | General")
118 | FCrvLineStyle LineStyleOutgoing = FCrvLineStyle::DefaultOutgoingLineStyle;
119 |
120 | UPROPERTY(Config, EditAnywhere, Category = "Style | General")
121 | FCrvLineStyle LineStyleIncoming = FCrvLineStyle::DefaultIncomingLineStyle;
122 |
123 | /* Draw circles around current target & references. */
124 | UPROPERTY(Config, EditAnywhere, Category = "Style | Target Circles")
125 | bool bDrawTargetCircles = false;
126 |
127 | UPROPERTY(
128 | Config,
129 | EditAnywhere,
130 | Category = "Style | Target Circles",
131 | meta = (ClampMin = "0", UIMin = "0", UIMax = "1000", EditCondition = "bDrawTargetCircles")
132 | )
133 | float CircleRadius = 50.f;
134 |
135 | UPROPERTY(
136 | Config,
137 | EditAnywhere,
138 | Category = "Style | Target Circles",
139 | meta = (ClampMin = "3", UIMin = "3", UIMax = "100", EditCondition = "bDrawTargetCircles")
140 | )
141 | float CircleResolution = 32.f;
142 |
143 | UPROPERTY(
144 | Config,
145 | EditAnywhere,
146 | Category = "Style | Target Circles",
147 | meta = (ClampMin = "0", UIMin = "0", UIMax = "10", EditCondition = "bDrawTargetCircles")
148 | )
149 | float CircleLineThickness = 1.f;
150 | /* Circle around the currently selected actor or scene component */
151 | UPROPERTY(Config, EditAnywhere, Category = "Style | Target Circles", meta = (EditCondition = "bDrawTargetCircles"))
152 | FLinearColor CurrentCircleColor = FLinearColor::Gray;
153 |
154 | /* Circle around referenced actors or scene components */
155 | UPROPERTY(Config, EditAnywhere, Category = "Style | Target Circles", meta = (EditCondition = "bDrawTargetCircles"))
156 | FLinearColor LinkedCircleColor = FLinearColor::Transparent;
157 | };
158 |
159 | USTRUCT()
160 | struct FCrvTargetSettings
161 | {
162 | explicit FCrvTargetSettings();
163 |
164 | GENERATED_BODY()
165 |
166 | UPROPERTY(Config, EditAnywhere, Category = "Targets")
167 | TArray> IgnoreReferencesToClasses;
168 |
169 | /* The target actor component classes to enable with the reference viewer debug visualization. */
170 | UPROPERTY(Config, EditAnywhere, AdvancedDisplay, Category = "Targets")
171 | TArray> TargetComponentClasses;
172 | };
173 |
174 | UENUM(meta = (Bitflags, UseEnumValuesAsMaskValuesInEditor = "true"))
175 | enum class EReferenceChainSearchMode_K2: uint32
176 | {
177 | // Returns all reference chains found
178 | Default = 0,
179 | // Returns only reference chains from external objects
180 | ExternalOnly = 1 << 0,
181 | // Returns only the shortest reference chain for each rooted object
182 | Shortest = 1 << 1,
183 | // Returns only the longest reference chain for each rooted object
184 | Longest = 1 << 2,
185 | // Returns only the direct referencers
186 | Direct = 1 << 3,
187 | // Returns complete chains. (Ignoring non GC objects)
188 | FullChain = 1 << 4,
189 | // Returns the shortest path to a garbage object from which the target object is reachable
190 | ShortestToGarbage = 1 << 5,
191 | // Attempts to find a plausible path to the target object with minimal memory usage
192 | // E.g. returns a direct external reference to the target object if one is found
193 | // otherwise returns an external reference to an inner of the target object
194 | Minimal = 1 << 6,
195 | // Skips the disregard-for-GC set that will never be GCd and whose outgoing references are not checked during GC
196 | GCOnly = 1 << 7,
197 |
198 | // Print results
199 | PrintResults = 1 << 16,
200 | // Print ALL results (in some cases there may be thousands of reference chains)
201 | PrintAllResults = 1 << 17,
202 | };
203 |
204 | namespace CtrlRefViz
205 | {
206 | inline FString LexToString(const EReferenceChainSearchMode_K2 Mode)
207 | {
208 | return UEnum::GetValueOrBitfieldAsString(Mode);
209 | }
210 |
211 | inline FString LexToString(EReferenceChainSearchMode Mode)
212 | {
213 | return LexToString(static_cast(Mode));
214 | }
215 | }
216 |
217 | /**
218 | *
219 | */
220 | UCLASS(
221 | Config = EditorPerProjectUserSettings,
222 | PerObjectConfig,
223 | meta = (DisplayName = "Ctrl - Reference Visualizer Settings")
224 | )
225 | class CTRLREFERENCEVISUALIZER_API UCrvSettings : public UDeveloperSettingsBackedByCVars
226 | {
227 | GENERATED_BODY()
228 |
229 | public:
230 | UCrvSettings();
231 |
232 | virtual FName GetContainerName() const override
233 | {
234 | return FName("Editor");
235 | }
236 |
237 | virtual FText GetSectionText() const override;
238 |
239 | virtual FText GetSectionDescription() const override;
240 |
241 | UFUNCTION()
242 | void AddComponentClass(const TSoftClassPtr& ComponentClass);
243 |
244 | void SetEnabled(bool bNewEnabled);
245 |
246 | void ToggleEnabled();
247 |
248 | void SetShowIncomingReferences(bool bNewShowIncomingReferences);
249 |
250 | void SetShowOutgoingReferences(bool bNewShowOutgoingReferences);
251 |
252 | void Refresh();
253 |
254 | void UpdateTargets();
255 |
256 | UFUNCTION()
257 | void CleanTargets();
258 |
259 | bool IsEnabled() const;
260 | bool GetAutoAddComponents() const;
261 |
262 | /* Whether the reference viewer display is enabled */
263 | UPROPERTY(Config, EditAnywhere, Category = "General", meta = (ConsoleVariable = "ctrl.ReferenceVisualizer"))
264 | bool bIsEnabled = true;
265 |
266 | UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "General", meta=(MultiLine=true))
267 | FText Help;
268 |
269 | UPROPERTY(Config, EditAnywhere, Category = "General")
270 | ECrvMode Mode = ECrvMode::SelectedOrAll;
271 |
272 | // automatically add/remove ReferenceVisualizerComponent to actors
273 | UPROPERTY(Config, EditAnywhere, Category = "General")
274 | bool bAutoAddComponents = true;
275 |
276 | // show recursive references to/from the selected actor or component
277 | // UPROPERTY(Config, EditAnywhere, Category = "General", meta = (ClampMin = "1", UIMin = "1", UIMax = "100", EditCondition = "Mode == ECrvMode::OnlySelected || Mode == ECrvMode::SelectedOrAll"))
278 | // int32 Depth = 1;
279 |
280 | UFUNCTION(BlueprintCallable, Exec, CallInEditor)
281 | void Documentation() const;
282 |
283 | UPROPERTY(Config, EditAnywhere, Category = "General", DisplayName = "Visualize Outgoing References")
284 | bool bShowOutgoingReferences = true;
285 |
286 | UPROPERTY(Config, EditAnywhere, Category = "General", DisplayName = "Visualize Incoming References (Potentially Slow)")
287 | bool bShowIncomingReferences = true;
288 |
289 | UPROPERTY(Config, EditAnywhere, Category = "General", DisplayName = "Move Camera to Reference On Select")
290 | bool bMoveViewportCameraToReference = false;
291 |
292 | /* Use the actor bounds to determine center points, otherwise uses actor/scene component location */
293 | UPROPERTY(Config, EditAnywhere, Category = "General", DisplayName = "Use Center of Actor Bounds as Target Point", Experimental)
294 | bool bUseActorBounds = false;
295 |
296 | UPROPERTY(Config, EditAnywhere, Category = "General|Bounds", meta = (EditCondition = "bUseActorBounds"), DisplayName = "Include Non-Colliding Components")
297 | bool bIncludeNonCollidingBounds = false;
298 |
299 | UPROPERTY(Config, EditAnywhere, Category = "General|Bounds", meta = (EditCondition = "bUseActorBounds"), DisplayName = "Include Child Actors")
300 | bool bIncludeChildActorsInBounds = false;
301 |
302 | /* Controls the style of the reference viewer debug drawing */
303 | UPROPERTY(Config, EditAnywhere, Category = "Style", meta = (ShowOnlyInnerProperties))
304 | FCrvStyleSettings Style;
305 |
306 | UPROPERTY(Config, EditAnywhere, Category = "General|Filtering", meta = (ShowOnlyInnerProperties))
307 | FCrvTargetSettings TargetSettings;
308 | /* Include recursive references to child actors and components */
309 | UPROPERTY(Config, EditAnywhere, Category = "General|Filtering")
310 | bool bIsRecursive = true;
311 | // /* Include references from parent actor, rather than just the selected component */
312 | // UPROPERTY(Config, EditAnywhere, Category = "General|Filtering")
313 | // bool bAlwaysIncludeReferencesFromParent = false;
314 |
315 | UPROPERTY(Config, EditAnywhere, Category = "General|Filtering")
316 | bool bShowComponents = true;
317 |
318 | UPROPERTY(Config, EditAnywhere, Category = "General|Filtering")
319 | bool bShowObjects = false;
320 |
321 | // UPROPERTY(Config, EditAnywhere, Category = "General|Filtering", meta = (EditCondition = "bIsRecursive"))
322 | // bool bWalkComponents = true;
323 | //
324 | // UPROPERTY(Config, EditAnywhere, Category = "General|Filtering", meta = (EditCondition = "bIsRecursive"))
325 | // bool bWalkSceneChildComponents = true;
326 | //
327 | // UPROPERTY(Config, EditAnywhere, Category = "General|Filtering", meta = (EditCondition = "bIsRecursive"))
328 | // bool bWalkChildActors = true;
329 |
330 | UPROPERTY(Config, EditAnywhere, Category = "General|Filtering")
331 | bool bWalkObjectProperties = true;
332 |
333 | /* Skip ObjectArchetype references */
334 | UPROPERTY(Config, EditAnywhere, Category = "General|Filtering")
335 | bool bIgnoreArchetype = true;
336 |
337 | /* Skip transient properties */
338 | UPROPERTY(Config, EditAnywhere, Category = "General|Filtering")
339 | bool bIgnoreTransient = true;
340 |
341 | UPROPERTY(Config, EditAnywhere, AdvancedDisplay, Category = "General")
342 | bool bDebugEnabled = false;
343 |
344 | UPROPERTY(EditAnywhere, AdvancedDisplay, Category = "General")
345 | bool bRefreshEnabled = true;
346 |
347 | /* Delegate called when this settings object is modified */
348 | DECLARE_MULTICAST_DELEGATE_TwoParams(UCrvSettingsModified, UObject*, FProperty*);
349 | UCrvSettingsModified OnModified;
350 |
351 | FCrvLineStyle GetLineStyle(ECrvDirection Direction) const;
352 |
353 | #if WITH_EDITOR
354 | virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
355 |
356 | void CVarSink();
357 | #endif
358 | virtual void PostInitProperties() override;
359 |
360 | private:
361 | bool bIsUpdating = false;
362 | };
363 |
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Public/CrvStyle.h:
--------------------------------------------------------------------------------
1 | // Fill out your copyright notice in the Description page of Project Settings.
2 |
3 | #pragma once
4 |
5 | #include "CoreMinimal.h"
6 | #include "Styling/SlateStyle.h"
7 |
8 | class CTRLREFERENCEVISUALIZER_API FCrvStyle : public FSlateStyleSet
9 | {
10 | public:
11 | explicit FCrvStyle();
12 |
13 | static void Startup();
14 | static void Register();
15 | static void Shutdown();
16 |
17 | static TSharedPtr Get();
18 | virtual const FName& GetStyleSetName() const override;
19 | void Initialize();
20 |
21 | private:
22 | static TSharedPtr StyleSet;
23 | };
24 |
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Public/CtrlReferenceVisualizer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "CoreMinimal.h"
4 | #include "CrvRefCache.h"
5 | #include "ReferenceVisualizerComponent.h"
6 | #include "HAL/IConsoleManager.h"
7 | #include "Modules/ModuleManager.h"
8 |
9 | class UToolMenu;
10 | class FCrvDebugVisualizer;
11 | class UReferenceVisualizerComponent;
12 | class UCrvSettings;
13 | class UCrvRefCache;
14 |
15 | DECLARE_LOG_CATEGORY_EXTERN(LogCrv, Log, All);
16 |
17 | class FCrvModule : public IModuleInterface
18 | {
19 | public:
20 | void MakeReferenceListSubMenu(UToolMenu* SubMenu, ECrvDirection Direction) const;
21 | void SelectReference(UObject* Object);
22 | void InitActorMenu() const;
23 | void MakeActorOptionsSubmenu(UToolMenu* Menu) const;
24 | void InitLevelMenus() const;
25 |
26 | void InitTab();
27 |
28 | void OnPostEngineInit();
29 | /** IModuleInterface implementation */
30 | virtual void StartupModule() override;
31 | virtual void ShutdownModule() override;
32 | /** end IModuleInterface implementation */
33 |
34 | virtual void AddTargetComponentClass(class UClass* Class);
35 |
36 | /**
37 | * Singleton-like access to this module's interface. This is just for convenience!
38 | * Beware of calling this during the shutdown phase, though. Your module might have been unloaded already.
39 | *
40 | * @return Returns singleton instance, loading the module on demand if needed
41 | */
42 | static FCrvModule& Get()
43 | {
44 | return FModuleManager::LoadModuleChecked("CtrlReferenceVisualizer");
45 | }
46 |
47 | /**
48 | * Checks to see if this module is loaded and ready. It is only valid to call Get() if IsAvailable() returns true.
49 | *
50 | * @return True if the module is loaded and ready to use
51 | */
52 | static bool IsAvailable()
53 | {
54 | return FModuleManager::Get().IsModuleLoaded("CtrlReferenceVisualizer");
55 | }
56 |
57 | static bool IsEnabled();
58 | static bool IsDebugEnabled();
59 |
60 | protected:
61 | static void InitCategories();
62 | FToolMenuEntry GetSettingsMenuEntry() const;
63 | TArray RegisteredClasses;
64 | FDelegateHandle SettingsModifiedHandle;
65 | };
66 |
67 |
--------------------------------------------------------------------------------
/Source/CtrlReferenceVisualizer/Public/ReferenceVisualizerComponent.h:
--------------------------------------------------------------------------------
1 | // Fill out your copyright notice in the Description page of Project Settings.
2 |
3 | #pragma once
4 |
5 | #include "CoreMinimal.h"
6 | #include "CrvRefCache.h"
7 | #include "CrvSettings.h"
8 | #include "DebugRenderSceneProxy.h"
9 | #include "Components/ActorComponent.h"
10 | #include "Debug/DebugDrawComponent.h"
11 | #include "Templates/TypeHash.h"
12 | #include "ReferenceVisualizerComponent.generated.h"
13 |
14 | class UReferenceVisualizerComponent;
15 | class UCrvRefCache;
16 |
17 | UCLASS()
18 | class UReferenceVisualizerEditorSubsystem : public UEditorSubsystem
19 | {
20 | GENERATED_BODY()
21 |
22 | public:
23 | UReferenceVisualizerEditorSubsystem();
24 |
25 | UPROPERTY(Transient)
26 | TObjectPtr Cache;
27 | UPROPERTY(Transient)
28 | TObjectPtr MenuCache;
29 |
30 | virtual void Initialize(FSubsystemCollectionBase& Collection) override;
31 | virtual void Deinitialize() override;
32 |
33 | void UpdateCache();
34 |
35 | void OnObjectModified(UObject* Object);
36 | void OnPropertyChanged(UObject* Object, FPropertyChangedEvent& PropertyChangedEvent);
37 | void OnSettingsModified(UObject* Object, FProperty* Property);
38 | void OnSelectionChanged(UObject* SelectionObject);
39 |
40 | private:
41 | bool bIsRefreshingSelection = false;
42 | FDelegateHandle SettingsModifiedHandle;
43 | FTimerHandle UpdateCacheNextTickHandle;
44 | };
45 |
46 | USTRUCT()
47 | struct FCrvLine
48 | {
49 | GENERATED_BODY()
50 | UPROPERTY()
51 | FVector Start;
52 | UPROPERTY()
53 | FVector End;
54 | UPROPERTY()
55 | FLinearColor Color;
56 | UPROPERTY()
57 | FCrvLineStyle Style;
58 |
59 | friend bool operator==(const FCrvLine& Lhs, const FCrvLine& RHS)
60 | {
61 | return Lhs.Start == RHS.Start
62 | && Lhs.End == RHS.End
63 | && Lhs.Color == RHS.Color
64 | && Lhs.Style == RHS.Style;
65 | }
66 |
67 | friend bool operator!=(const FCrvLine& Lhs, const FCrvLine& RHS)
68 | {
69 | return !(Lhs == RHS);
70 | }
71 |
72 | friend uint32 GetTypeHash(const FCrvLine& Arg)
73 | {
74 | uint32 Hash = HashCombine(GetTypeHash(Arg.Start), GetTypeHash(Arg.End));
75 | Hash = HashCombine(Hash, GetTypeHash(Arg.Color));
76 | Hash = HashCombine(Hash, GetTypeHash(Arg.Style));
77 | return Hash;
78 | }
79 | };
80 |
81 | /**
82 | * Component used to visualize references in the editor.
83 | * This component is hidden and not blueprintable.
84 | * This component is added/removed automatically on selection, to trigger the visualizer.
85 | */
86 | UCLASS(ClassGroup = Debug, NotBlueprintable, NotBlueprintType, NotEditInlineNew, meta = (BlueprintSpawnableComponent))
87 | class CTRLREFERENCEVISUALIZER_API UReferenceVisualizerComponent : public UDebugDrawComponent
88 | {
89 | GENERATED_BODY()
90 |
91 | public:
92 | virtual FDebugRenderSceneProxy* CreateDebugSceneProxy() override;
93 |
94 | FCrvLine CreateLine(const FVector& SrcOrigin, const FVector& DstOrigin, ECrvDirection Direction, const UClass* Type);
95 |
96 | void CreateLines(const UObject* RootObject, ECrvDirection Direction);
97 |
98 | virtual FBoxSphereBounds CalcBounds(const FTransform& LocalToWorld) const override;
99 | virtual void OnRegister() override;
100 | virtual void OnUnregister() override;
101 |
102 | UPROPERTY(Transient)
103 | TObjectPtr CrvEditorSubsystem;
104 |
105 | UPROPERTY(Transient)
106 | TSet Lines;
107 |
108 | UReferenceVisualizerComponent();
109 | };
110 |
111 | class FCtrlReferenceVisualizerSceneProxy : public FDebugRenderSceneProxy
112 | {
113 | public:
114 | static FVector GetComponentLocation(const UActorComponent* Component);
115 | static FVector GetActorOrigin(const AActor* Actor);
116 |
117 | FCtrlReferenceVisualizerSceneProxy(const UPrimitiveComponent* InComponent);
118 |
119 | virtual SIZE_T GetTypeHash() const override;
120 |
121 | virtual FPrimitiveViewRelevance GetViewRelevance(const FSceneView* View) const override;
122 |
123 | virtual uint32 GetMemoryFootprint() const override;
124 |
125 | virtual void GetDynamicMeshElementsForView(
126 | const FSceneView* View,
127 | int32 ViewIndex,
128 | const FSceneViewFamily& ViewFamily,
129 | uint32 VisibilityMap,
130 | FMeshElementCollector& Collector,
131 | FMaterialCache& DefaultMaterialCache,
132 | FMaterialCache& SolidMeshMaterialCache
133 | ) const override;
134 |
135 | void DrawLines(TSet InLines);
136 |
137 | static FVector GetObjectLocation(const UObject* Object);
138 |
139 | private:
140 | ESceneDepthPriorityGroup DepthPriorityGroup = SDPG_World;
141 |
142 | protected:
143 | inline static bool bMultiple = false;
144 | };
145 |
--------------------------------------------------------------------------------