UE3或者UE4的FString类型无法在内存中直接看到值,为了debug方便,需要第三方文件的协助,可以将以下两个文件UE3.natvis和UE4.natvis拷贝到$USERPROFILE/Documents/Visual Studio 2012/Visualizers 目录下,在debug的时候可以实时看到FString的值了:
<?xml version="1.0" encoding="utf-8"?> <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> <!-- Epic Games, Inc. UE3 Visualizers --> <!-- Copy this into c:\Users\<Your user folder>\My Documents\Visual Studio 2012\Visualizers --> <!-- FString visualizer --> <Type Name="UE3::FString"> <DisplayString Condition="ArrayNum == 0">Empty</DisplayString> <DisplayString Condition="ArrayNum < 0">Invalid</DisplayString> <DisplayString Condition="ArrayMax < ArrayNum">Invalid</DisplayString> <DisplayString Condition="ArrayMax >= ArrayNum">{AllocatorInstance.Data,su}</DisplayString> <StringView Condition="ArrayMax >= ArrayNum">AllocatorInstance.Data,su</StringView> </Type> <!-- FName visualizer --> <Type Name="UE3::FName"> <DisplayString Condition="Index >= Names.ArrayNum">Invalid</DisplayString> <DisplayString Condition="Index < 0">Invalid</DisplayString> <DisplayString Condition="0 == (((((FNameEntry**) Names.AllocatorInstance.Data)[Index])->Index) & 1) && Number > 0">{(((FNameEntry**) Names.AllocatorInstance.Data)[Index])->AnsiName,s}_{Number - 1}</DisplayString> <DisplayString Condition="1 == (((((FNameEntry**) Names.AllocatorInstance.Data)[Index])->Index) & 1) && Number > 0">{(((FNameEntry**) Names.AllocatorInstance.Data)[Index])->UniName,su}_{Number - 1}</DisplayString> <DisplayString Condition="0 == (((((FNameEntry**) Names.AllocatorInstance.Data)[Index])->Index) & 1)">{(((FNameEntry**) Names.AllocatorInstance.Data)[Index])->AnsiName,s}</DisplayString> <DisplayString Condition="1 == (((((FNameEntry**) Names.AllocatorInstance.Data)[Index])->Index) & 1)">{(((FNameEntry**) Names.AllocatorInstance.Data)[Index])->UniName,su}</DisplayString> </Type> <!-- TArray visualizer --> <Type Name="UE3::TArray<*,*>|UE3::TArrayNoInit<*,*>"> <DisplayString Condition="ArrayNum == 0">Empty</DisplayString> <DisplayString Condition="ArrayNum < 0">Invalid</DisplayString> <DisplayString Condition="ArrayMax < ArrayNum">Invalid</DisplayString> <DisplayString Condition="ArrayMax >= ArrayNum">Num={ArrayNum}</DisplayString> <Expand> <ArrayItems Condition="ArrayNum <= ArrayMax"> <Size>ArrayNum</Size> <ValuePointer>($T1*) AllocatorInstance.Data</ValuePointer> </ArrayItems> </Expand> </Type> <!-- TIndirectArray visualizer --> <Type Name="UE3::TIndirectArray<*,*>"> <DisplayString Condition="ArrayNum == 0">Empty</DisplayString> <DisplayString Condition="ArrayNum < 0">Invalid</DisplayString> <DisplayString Condition="ArrayMax < ArrayNum">Invalid</DisplayString> <DisplayString Condition="ArrayMax >= ArrayNum">Num={ArrayNum}</DisplayString> <Expand> <IndexListItems Condition="ArrayNum <= ArrayMax"> <Size>ArrayNum</Size> <ValueNode>*(($T1**)AllocatorInstance.Data)[$i]</ValueNode> </IndexListItems> </Expand> </Type> <!-- TSparseArray visualizer --> <Type Name="UE3::TSparseArray<*,*>|UE3::TSparseArrayNoInit<*,*>"> <DisplayString Condition="Data.ArrayNum == 0">Empty</DisplayString> <DisplayString Condition="Data.ArrayNum < 0">Invalid</DisplayString> <DisplayString Condition="Data.ArrayMax < Data.ArrayNum">Invalid</DisplayString> <DisplayString Condition="Data.ArrayMax >= Data.ArrayNum">Num={Data.ArrayNum}</DisplayString> <Expand> <ArrayItems Condition="Data.ArrayNum <= Data.ArrayMax"> <Size>Data.ArrayNum</Size> <ValuePointer>($T1*) Data.AllocatorInstance.Data</ValuePointer> </ArrayItems> </Expand> </Type> <!-- TMapBase::FPair visualizer --> <Type Name="UE3::TMapBase<*,*,*,*,*>::FPair"> <DisplayString>({Key}, {Value})</DisplayString> </Type> <!-- TMapBase visualizer --> <Type Name="UE3::TMapBase<*,*,*,*,*>"> <DisplayString Condition="Pairs.Elements.Data.ArrayNum <= 0">Empty</DisplayString> <DisplayString Condition="Pairs.Elements.Data.ArrayNum <= Pairs.Elements.Data.ArrayMax">Num={Pairs.Elements.Data.ArrayNum - Pairs.Elements.NumFreeIndices}</DisplayString> <Expand> <IndexListItems Condition="Pairs.Elements.Data.ArrayNum > 0 && Pairs.Elements.Data.ArrayNum <= Pairs.Elements.Data.ArrayMax"> <Size>Pairs.Elements.Data.ArrayNum</Size> <ValueNode>((TSet<TMapBase<$T1,$T2,$T3,$T4>::FPair,TMapBase<$T1,$T2,$T3,$T4>::KeyFuncs,$T4>::FElement *) Pairs.Elements.Data.AllocatorInstance.Data + $i)->Value</ValueNode> </IndexListItems> </Expand> </Type> <!-- GFx GAtomicValueBase visualizer --> <Type Name="GAtomicValueBase"> <DisplayString>{Value}</DisplayString> </Type> <!-- UObject visualizer --> <Type Name="UE3::UObject"> <DisplayString Condition="Outer">(Name={Name}, Outer={Outer})</DisplayString> <DisplayString Condition="!Outer">(Name={Name})</DisplayString> </Type> </AutoVisualizer>
<?xml version="1.0" encoding="utf-8"?> <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> <!-- Epic Games, Inc. UE4 Visualizers --> <!-- Copy this into c:\Users\<Your user folder>\My Documents\Visual Studio 2012\Visualizers --> <!-- FString visualizer --> <Type Name="FString"> <DisplayString Condition="Data.ArrayNum == 0">Empty</DisplayString> <DisplayString Condition="Data.ArrayNum < 0">Invalid</DisplayString> <DisplayString Condition="Data.ArrayMax < Data.ArrayNum">Invalid</DisplayString> <DisplayString Condition="Data.ArrayMax >= Data.ArrayNum">{Data.AllocatorInstance.Data,su}</DisplayString> <StringView Condition="Data.ArrayMax >= Data.ArrayNum">Data.AllocatorInstance.Data,su</StringView> </Type> <!-- FName visualizer --> <Type Name="FName"> <DisplayString Condition="ComparisonIndex >= 2097152">Invalid</DisplayString> <DisplayString Condition="ComparisonIndex < 0">Invalid</DisplayString> <DisplayString Condition="ComparisonIndex < 2097152 && Number > 0">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[ComparisonIndex / 16384][ComparisonIndex % 16384]))->AnsiName,s}_{Number-1}</DisplayString> <DisplayString Condition="ComparisonIndex < 2097152">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[ComparisonIndex / 16384][ComparisonIndex % 16384]))->AnsiName,s}</DisplayString> <StringView Condition="ComparisonIndex < 2097152">((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[ComparisonIndex / 16384][ComparisonIndex % 16384]))->AnsiName</StringView> </Type> <Type Name="FName"> <DisplayString Condition="DisplayIndex >= 2097152">Invalid</DisplayString> <DisplayString Condition="DisplayIndex < 0">Invalid</DisplayString> <DisplayString Condition="DisplayIndex < 2097152 && Number > 0">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[DisplayIndex / 16384][DisplayIndex % 16384]))->AnsiName,s}_{Number-1}</DisplayString> <DisplayString Condition="DisplayIndex < 2097152">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[DisplayIndex / 16384][DisplayIndex % 16384]))->AnsiName,s}</DisplayString> <StringView Condition="DisplayIndex < 2097152">((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[DisplayIndex / 16384][DisplayIndex % 16384]))->AnsiName</StringView> </Type> <Type Name="FMinimalName"> <DisplayString Condition="Index >= 2097152">Invalid</DisplayString> <DisplayString Condition="Index < 0">Invalid</DisplayString> <DisplayString Condition="Index < 2097152 && Number > 0">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[Index / 16384][Index % 16384]))->AnsiName}_{Number-1}</DisplayString> <DisplayString Condition="Index < 2097152">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[Index / 16384][Index % 16384]))->AnsiName}</DisplayString> <StringView Condition="Index < 2097152">((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[Index / 16384][Index % 16384]))->AnsiName</StringView> </Type> <!-- FStatMessage visualizer @see Stats2.h --> <Type Name="FStatMessage"> <!--ST_None=1--> <DisplayString Condition="((NameAndInfo.NameAndInfo.Number >> 9)&0x7) == 1" >{{NoneType NameAndInfo={NameAndInfo.NameAndInfo}}}</DisplayString> <!--ST_int64=2--> <DisplayString Condition="((NameAndInfo.NameAndInfo.Number >> 9)&0x7) == 2" >{{Int64={DebugStatData.Cycles},C={DebugStatData.CCAndDuration[0]},D={DebugStatData.CCAndDuration[1]} NameAndInfo={NameAndInfo.NameAndInfo}}}</DisplayString> <!--ST_double=3--> <DisplayString Condition="((NameAndInfo.NameAndInfo.Number >> 9)&0x7) == 3" >{{Float={DebugStatData.Float} NameAndInfo={NameAndInfo.NameAndInfo}}}</DisplayString> <!--ST_FName=4--> <!--ST_Ptr=5--> <DisplayString Condition="((NameAndInfo.NameAndInfo.Number >> 9)&0x7) == 5" >{{Ptr={DebugStatData.Ptr} NameAndInfo={NameAndInfo.NameAndInfo}}}</DisplayString> </Type> <Type Name="FVector_NetQuantize"> <DisplayString>{{X={X} Y={Y} Z={Z}}</DisplayString> </Type> <Type Name="FVector_NetQuantize10"> <DisplayString>{{X={X} Y={Y} Z={Z}}</DisplayString> </Type> <Type Name="FVector_NetQuantize100"> <DisplayString>{{X={X} Y={Y} Z={Z}}</DisplayString> </Type> <Type Name="FVector_NetQuantizeNormal"> <DisplayString>{{X={X} Y={Y} Z={Z}}</DisplayString> </Type> <!-- TEnumAsByte visualizer --> <Type Name="TEnumAsByte<*>"> <DisplayString>{($T1)Value}</DisplayString> </Type> <!-- UObjectBase visualizer --> <Type Name="UObjectBase"> <DisplayString Condition="Outer">(Name={Name}, Outer={Outer})</DisplayString> <DisplayString Condition="!Outer">(Name={Name})</DisplayString> </Type> <!-- TArray<*,TFixedAllocator<*> > visualizer --> <Type Name="TArray<*,TFixedAllocator<*>>"> <DisplayString Condition="ArrayNum == 0">Empty</DisplayString> <DisplayString Condition="ArrayNum < 0">Invalid</DisplayString> <DisplayString Condition="ArrayMax < ArrayNum">Invalid</DisplayString> <DisplayString Condition="ArrayMax >= ArrayNum">Num={ArrayNum}</DisplayString> <Expand> <ArrayItems Condition="ArrayNum <= ArrayMax"> <Size>ArrayNum</Size> <ValuePointer>($T1*)AllocatorInstance.InlineData</ValuePointer> </ArrayItems> </Expand> </Type> <!-- TArray<*,TInlineAllocator<*,*> > visualizer --> <Type Name="TArray<*,TInlineAllocator<*,*>>"> <DisplayString Condition="ArrayNum == 0">Empty</DisplayString> <DisplayString Condition="ArrayNum < 0">Invalid</DisplayString> <DisplayString Condition="ArrayMax < ArrayNum">Invalid</DisplayString> <DisplayString Condition="ArrayMax >= ArrayNum">Num={ArrayNum}</DisplayString> <Expand> <ArrayItems Condition="ArrayNum <= ArrayMax"> <Size>ArrayNum</Size> <ValuePointer Condition="AllocatorInstance.SecondaryData.Data == 0">($T1*)AllocatorInstance.InlineData</ValuePointer> <ValuePointer Condition="AllocatorInstance.SecondaryData.Data != 0">($T1*)AllocatorInstance.SecondaryData.Data</ValuePointer> </ArrayItems> </Expand> </Type> <!-- TArray visualizer --> <Type Name="TArray<*,*>"> <DisplayString Condition="ArrayNum == 0">Empty</DisplayString> <DisplayString Condition="ArrayNum < 0">Invalid</DisplayString> <DisplayString Condition="ArrayMax < ArrayNum">Invalid</DisplayString> <DisplayString Condition="ArrayMax >= ArrayNum">Num={ArrayNum}</DisplayString> <Expand> <ArrayItems Condition="ArrayNum <= ArrayMax"> <Size>ArrayNum</Size> <ValuePointer>($T1*)AllocatorInstance.Data</ValuePointer> </ArrayItems> </Expand> </Type> <!-- TIndirectArray visualizer --> <Type Name="TIndirectArray<*,*>"> <DisplayString Condition="Array.ArrayNum == 0">Empty</DisplayString> <DisplayString Condition="Array.ArrayNum < 0">Invalid</DisplayString> <DisplayString Condition="Array.ArrayMax < Array.ArrayNum">Invalid</DisplayString> <DisplayString Condition="Array.ArrayMax >= Array.ArrayNum">Num={Array.ArrayNum}</DisplayString> <Expand> <IndexListItems Condition="Array.ArrayNum <= Array.ArrayMax"> <Size>Array.ArrayNum</Size> <ValueNode>*(($T1**)Array.AllocatorInstance.Data)[$i]</ValueNode> </IndexListItems> </Expand> </Type> <!-- TChunkedArray visualizer --> <Type Name="TChunkedArray<*,*>"> <DisplayString Condition="NumElements == 0">Empty</DisplayString> <DisplayString Condition="NumElements < 0">Invalid</DisplayString> <DisplayString Condition="NumElements > 0">NumElements={NumElements}, NumChunks={Chunks.Array.ArrayNum}, {NumElementsPerChunk}</DisplayString> <Expand> <IndexListItems Condition="NumElements > 0"> <Size>NumElements</Size> <ValueNode> *( *( ($T1**)Chunks.Array.AllocatorInstance.Data + ($i / NumElementsPerChunk) ) + ($i % NumElementsPerChunk) ) </ValueNode> </IndexListItems> </Expand> </Type> <!-- TSparseArray visualizer --> <Type Name="TSparseArray<*,*>"> <DisplayString Condition="(Data.ArrayNum - NumFreeIndices) <= 0">Empty</DisplayString> <DisplayString Condition="Data.ArrayNum <= Data.ArrayMax">Num={Data.ArrayNum - NumFreeIndices}</DisplayString> <Expand> <IndexListItems Condition="Data.ArrayNum > 0 && Data.ArrayNum <= Data.ArrayMax"> <Size>Data.ArrayNum</Size> <ValueNode Condition="(AllocationFlags.SecondaryData.Data != 0) && (reinterpret_cast<uint32*>(AllocationFlags.SecondaryData.Data)[$i/32]>>$i & 1) != 0">($T1*)Data.AllocatorInstance.Data + $i</ValueNode> <ValueNode Condition="(AllocationFlags.SecondaryData.Data == 0) && (reinterpret_cast<uint32*>(AllocationFlags.InlineData )[$i/32]>>$i & 1) != 0">($T1*)Data.AllocatorInstance.Data + $i</ValueNode> <ValueNode Condition="(AllocationFlags.SecondaryData.Data != 0) && (reinterpret_cast<uint32*>(AllocationFlags.SecondaryData.Data)[$i/32]>>$i & 1) == 0">Invalid</ValueNode> <ValueNode Condition="(AllocationFlags.SecondaryData.Data == 0) && (reinterpret_cast<uint32*>(AllocationFlags.InlineData )[$i/32]>>$i & 1) == 0">Invalid</ValueNode> </IndexListItems> </Expand> </Type> <!-- TBitArray visualizer --> <Type Name="TBitArray<*>"> <DisplayString Condition="NumBits == 0">Empty</DisplayString> <DisplayString Condition="NumBits < 0">Invalid</DisplayString> <DisplayString Condition="NumBits > 0">NumBits={NumBits}, MaxBits={MaxBits}</DisplayString> <Expand> <IndexListItems Condition="NumBits > 0"> <Size>NumBits</Size> <ValueNode Condition="(AllocatorInstance.SecondaryData.Data != 0) && (reinterpret_cast<uint32*>(AllocatorInstance.SecondaryData.Data )[$i/32]>>$i & 1) != 0">1</ValueNode> <ValueNode Condition="(AllocatorInstance.SecondaryData.Data == 0) && (reinterpret_cast<uint32*>(AllocatorInstance.InlineData )[$i/32]>>$i & 1) != 0">1</ValueNode> <ValueNode Condition="(AllocatorInstance.SecondaryData.Data != 0) && (reinterpret_cast<uint32*>(AllocatorInstance.SecondaryData.Data )[$i/32]>>$i & 1) == 0">0</ValueNode> <ValueNode Condition="(AllocatorInstance.SecondaryData.Data == 0) && (reinterpret_cast<uint32*>(AllocatorInstance.InlineData )[$i/32]>>$i & 1) == 0">0</ValueNode> </IndexListItems> </Expand> </Type> <!-- TPair visualizer --> <Type Name="TPair<*,*>"> <DisplayString>({Key}, {Value})</DisplayString> </Type> <!-- TSharedPtr visualizer --> <Type Name="TSharedPtr<*,*>"> <DisplayString Condition="Object == 0">Null</DisplayString> <DisplayString Condition="Object != 0">Ptr={(void*)Object}, SharedRefs={SharedReferenceCount.ReferenceController->SharedReferenceCount}, WeakRefs={SharedReferenceCount.ReferenceController->WeakReferenceCount}, Object={*Object}</DisplayString> <Expand> <Item Condition="Object != 0" Name="[SharedReferenceCount]">SharedReferenceCount.ReferenceController->SharedReferenceCount</Item> <Item Condition="Object != 0" Name="[WeakReferenceCount]">SharedReferenceCount.ReferenceController->WeakReferenceCount</Item> <Item Condition="Object != 0" Name="[Ptr]">(void*)Object</Item> <ExpandedItem Condition="Object != 0">*Object</ExpandedItem> </Expand> </Type> <!-- TSharedRef visualizer --> <Type Name="TSharedRef<*,*>"> <DisplayString Condition="Object != 0">Ptr={(void*)Object}, SharedRefs={SharedReferenceCount.ReferenceController->SharedReferenceCount}, WeakRefs={SharedReferenceCount.ReferenceController->WeakReferenceCount}, Object={*Object}</DisplayString> <Expand> <Item Condition="Object != 0" Name="[SharedReferenceCount]">SharedReferenceCount.ReferenceController->SharedReferenceCount</Item> <Item Condition="Object != 0" Name="[WeakReferenceCount]">SharedReferenceCount.ReferenceController->WeakReferenceCount</Item> <Item Condition="Object != 0" Name="[Ptr]">(void*)Object</Item> <ExpandedItem Condition="Object != 0">*Object</ExpandedItem> </Expand> </Type> <!-- TWeakPtr visualizer --> <Type Name="TWeakPtr<*,*>"> <DisplayString Condition="Object == 0">Null</DisplayString> <DisplayString Condition="WeakReferenceCount.ReferenceController->SharedReferenceCount == 0">Object has been destroyed</DisplayString> <DisplayString Condition="Object != 0">Ptr={(void*)Object}, SharedRefs={WeakReferenceCount.ReferenceController->SharedReferenceCount}, WeakRefs={WeakReferenceCount.ReferenceController->WeakReferenceCount}, Object={*Object}</DisplayString> <Expand> <Item Condition="Object != 0" Name="[SharedReferenceCount]">WeakReferenceCount.ReferenceController->SharedReferenceCount</Item> <Item Condition="Object != 0" Name="[WeakReferenceCount]">WeakReferenceCount.ReferenceController->WeakReferenceCount</Item> <Item Condition="Object != 0 && WeakReferenceCount.ReferenceController->SharedReferenceCount > 0" Name="[Ptr]">(void*)Object</Item> <ExpandedItem Condition="Object != 0 && WeakReferenceCount.ReferenceController->SharedReferenceCount > 0">*Object</ExpandedItem> </Expand> </Type> <!-- TMapBase visualizer --> <Type Name="TMapBase<*,*,*,*>"> <DisplayString Condition="Pairs.Elements.Data.ArrayNum - Pairs.Elements.NumFreeIndices <= 0">Empty</DisplayString> <DisplayString Condition="Pairs.Elements.Data.ArrayNum <= Pairs.Elements.Data.ArrayMax" >Num={Pairs.Elements.Data.ArrayNum - Pairs.Elements.NumFreeIndices}</DisplayString> <Expand> <IndexListItems Condition="Pairs.Elements.Data.ArrayNum - Pairs.Elements.NumFreeIndices > 0 && Pairs.Elements.Data.ArrayNum <= Pairs.Elements.Data.ArrayMax"> <Size>Pairs.Elements.Data.ArrayNum</Size> <ValueNode Condition="(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data != 0) && (reinterpret_cast<uint32*>(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data)[$i/32]>>$i & 1) != 0">((TSetElement<TPair<$T1,$T2> > *)Pairs.Elements.Data.AllocatorInstance.Data)[$i].Value</ValueNode> <ValueNode Condition="(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data == 0) && (reinterpret_cast<uint32*>(Pairs.Elements.AllocationFlags.AllocatorInstance.InlineData )[$i/32]>>$i & 1) != 0">((TSetElement<TPair<$T1,$T2> > *)Pairs.Elements.Data.AllocatorInstance.Data)[$i].Value</ValueNode> <ValueNode Condition="(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data != 0) && (reinterpret_cast<uint32*>(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data)[$i/32]>>$i & 1) == 0">Invalid</ValueNode> <ValueNode Condition="(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data == 0) && (reinterpret_cast<uint32*>(Pairs.Elements.AllocationFlags.AllocatorInstance.InlineData )[$i/32]>>$i & 1) == 0">Invalid</ValueNode> </IndexListItems> </Expand> </Type> <!-- TSet visualizer --> <Type Name="TSet<*,*,*>"> <DisplayString Condition="Elements.Data.ArrayNum - Elements.NumFreeIndices <= 0">Empty</DisplayString> <DisplayString Condition="Elements.Data.ArrayNum <= Elements.Data.ArrayMax">Num={Elements.Data.ArrayNum - Elements.NumFreeIndices}</DisplayString> <Expand> <IndexListItems Condition="Elements.Data.ArrayNum - Elements.NumFreeIndices > 0 && Elements.Data.ArrayNum <= Elements.Data.ArrayMax"> <Size>Elements.Data.ArrayNum</Size> <ValueNode Condition="(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data != 0) && (reinterpret_cast<uint32*>(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data)[$i/32]>>$i & 1) != 0">((TSetElement <$T1> *)Elements.Data.AllocatorInstance.Data)[$i].Value</ValueNode> <ValueNode Condition="(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data == 0) && (reinterpret_cast<uint32*>(Elements.AllocationFlags.AllocatorInstance.InlineData )[$i/32]>>$i & 1) != 0">((TSetElement <$T1> *)Elements.Data.AllocatorInstance.Data)[$i].Value</ValueNode> <ValueNode Condition="(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data != 0) && (reinterpret_cast<uint32*>(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data)[$i/32]>>$i & 1) == 0">Invalid</ValueNode> <ValueNode Condition="(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data == 0) && (reinterpret_cast<uint32*>(Elements.AllocationFlags.AllocatorInstance.InlineData)[$i/32]>>$i & 1) == 0">Invalid</ValueNode> </IndexListItems> </Expand> </Type> <!-- FWeakObjectPtr|TWeakObjectPtr<*>|TAutoWeakObjectPtr<*> visualizer --> <Type Name="FWeakObjectPtr|TWeakObjectPtr<*>|TAutoWeakObjectPtr<*>"> <DisplayString Condition="ObjectSerialNumber < 1">NULL</DisplayString> <DisplayString Condition="*((*(*GSerialNumberBlocksForDebugVisualizers + (ObjectIndex / 0x4000))) + (ObjectIndex % 0x4000)) != ObjectSerialNumber">STALE</DisplayString> <DisplayString>{GObjectArrayForDebugVisualizers[ObjectIndex / 0x4000][ObjectIndex % 0x4000]}</DisplayString> <Expand> <ExpandedItem>GObjectArrayForDebugVisualizers[ObjectIndex / 0x4000][ObjectIndex % 0x4000]</ExpandedItem> </Expand> </Type> <!-- FSubobjectPtr|TSubobjectPtr visualizer --> <Type Name="FSubobjectPtr|TSubobjectPtr<*>"> <DisplayString>{Object}</DisplayString> </Type> <!-- TOptional visualizer --> <Type Name="TOptional<*>"> <DisplayString Condition="!bIsSet">Unset</DisplayString> <DisplayString Condition="bIsSet">Set: {{{*($T1*)&Value}}}</DisplayString> <Expand> <ExpandedItem Condition="bIsSet">*($T1*)&Value</ExpandedItem> </Expand> </Type> <!-- TFunction visualizer --> <Type Name="UE4Function_Private::TDebugHelper<*>"> <DisplayString>{*Ptr}</DisplayString> <Expand> <ExpandedItem>*Ptr</ExpandedItem> </Expand> </Type> <Type Name="TFunctionRef<*>"> <DisplayString Condition="Ptr">{DebugPtrStorage}</DisplayString> <DisplayString Condition="!Ptr">Unset</DisplayString> <Expand> <ExpandedItem Condition="Ptr">DebugPtrStorage</ExpandedItem> </Expand> </Type> </AutoVisualizer>
针对于PS4版本的debug,需要将以下两个文件拷贝到:c:\Users\username\Documents\SCE\orbis-debugger :
<?xml version="1.0" encoding="utf-8"?> <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> <!-- UE3 Visualizers --> <!-- Copy this into $USERPROFILE/Documents/SCE/orbis-debugger --> <!-- FString visualizer --> <Type Name="UE3::FString"> <DisplayString Condition="ArrayNum == 0">Empty</DisplayString> <DisplayString Condition="ArrayNum < 0">Invalid</DisplayString> <DisplayString Condition="ArrayMax < ArrayNum">Invalid</DisplayString> <DisplayString Condition="ArrayMax >= ArrayNum">{AllocatorInstance.Data,su}</DisplayString> <StringView Condition="ArrayMax >= ArrayNum">AllocatorInstance.Data,su</StringView> </Type> <!-- FName visualizer --> <Type Name="UE3::FName"> <DisplayString Condition="Index >= Names.ArrayNum">Invalid</DisplayString> <DisplayString Condition="Index < 0">Invalid</DisplayString> <DisplayString Condition="0 == (((((::UE3::FNameEntry**) Names.AllocatorInstance.Data)[Index])->Index) & 1)">{(((::UE3::FNameEntry**) Names.AllocatorInstance.Data)[Index])->AnsiName,s}_{Number - 1}</DisplayString> <DisplayString Condition="1 == (((((::UE3::FNameEntry**) Names.AllocatorInstance.Data)[Index])->Index) & 1)">{(((::UE3::FNameEntry**) Names.AllocatorInstance.Data)[Index])->UniName,su}_{Number - 1}</DisplayString> </Type> <!-- TArray visualizer --> <Type Name="UE3::TArray<*,*>"> <DisplayString Condition="ArrayNum == 0">Empty</DisplayString> <DisplayString Condition="ArrayNum < 0">Invalid</DisplayString> <DisplayString Condition="ArrayMax < ArrayNum">Invalid</DisplayString> <DisplayString Condition="ArrayMax >= ArrayNum">Num={ArrayNum}</DisplayString> <Expand> <ArrayItems> <Size>ArrayNum</Size> <ValuePointer>($T1 *) AllocatorInstance.Data</ValuePointer> </ArrayItems> </Expand> </Type> <!-- AC TArray has 3 template parameters --> <Type Name="UE3::TArray<*,*,*>"> <DisplayString Condition="ArrayNum == 0">Empty</DisplayString> <DisplayString Condition="ArrayNum < 0">Invalid</DisplayString> <DisplayString Condition="ArrayMax < ArrayNum">Invalid</DisplayString> <DisplayString Condition="ArrayMax >= ArrayNum">Num={ArrayNum}</DisplayString> <Expand> <ArrayItems> <Size>ArrayNum</Size> <ValuePointer>($T1 *) AllocatorInstance.Data</ValuePointer> </ArrayItems> </Expand> </Type> <!-- TSparseArray visualizer --> <Type Name="UE3::TSparseArray<*,*>"> <DisplayString Condition="Data.ArrayNum == 0">Empty</DisplayString> <DisplayString Condition="Data.ArrayNum < 0">Invalid</DisplayString> <DisplayString Condition="Data.ArrayMax < Data.ArrayNum">Invalid</DisplayString> <DisplayString Condition="Data.ArrayMax >= Data.ArrayNum">Num={Data.ArrayNum}</DisplayString> <Expand> <ArrayItems Condition="Data.ArrayNum <= Data.ArrayMax"> <Size>Data.ArrayNum</Size> <ValuePointer>(::$T1 *) Data.AllocatorInstance.Data</ValuePointer> </ArrayItems> </Expand> </Type> <!-- TMapBase::FPair visualizer --> <Type Name="UE3::TMapBase<*,*,*,*,*>::FPair"> <DisplayString>({Key}, {Value})</DisplayString> </Type> <!-- TMapBase visualizer --> <Type Name="UE3::TMapBase<*,*,*,*,*>"> <DisplayString Condition="Pairs.Elements.Data.ArrayNum <= 0">Empty</DisplayString> <DisplayString Condition="Pairs.Elements.Data.ArrayNum <= Pairs.Elements.Data.ArrayMax">Num={Pairs.Elements.Data.ArrayNum - Pairs.Elements.NumFreeIndices}</DisplayString> <Expand> <IndexListItems Condition="Pairs.Elements.Data.ArrayNum > 0 && Pairs.Elements.Data.ArrayNum <= Pairs.Elements.Data.ArrayMax"> <Size>Pairs.Elements.Data.ArrayNum</Size> <ValueNode>((TSet<TMapBase<$T1,$T2,$T3,$T4>::FPair,TMapBase<$T1,$T2,$T3,$T4>::KeyFuncs,$T4>::FElement *) Pairs.Elements.Data.AllocatorInstance.Data + $i)->Value</ValueNode> </IndexListItems> </Expand> </Type> <!-- GFx GAtomicValueBase visualizer --> <Type Name="GAtomicValueBase"> <DisplayString>{Value}</DisplayString> </Type> <!-- UObject visualizer --> <Type Name="UE3::UObject"> <DisplayString Condition="0 != Outer">(Name={Name}, Outer={Outer})</DisplayString> <DisplayString Condition="0 == Outer">(Name={Name})</DisplayString> </Type> </AutoVisualizer>
<?xml version="1.0" encoding="utf-8"?> <AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> <!-- Epic Games, Inc. UE4 Visualizers --> <!-- Copy this into Documents\SCE\orbis-debugger --> <!-- FString visualizer --> <Type Name="FString"> <DisplayString Condition="Data.ArrayNum == 0">Empty</DisplayString> <DisplayString Condition="Data.ArrayNum < 0">Invalid</DisplayString> <DisplayString Condition="Data.ArrayMax < Data.ArrayNum">Invalid</DisplayString> <DisplayString Condition="Data.ArrayMax >= Data.ArrayNum">{Data.AllocatorInstance.Data,su}</DisplayString> <StringView Condition="Data.ArrayMax >= Data.ArrayNum">Data.AllocatorInstance.Data,su</StringView> </Type> <!-- FName visualizer --> <Type Name="FName"> <DisplayString Condition="ComparisonIndex >= 2097152">Invalid</DisplayString> <DisplayString Condition="ComparisonIndex < 0">Invalid</DisplayString> <DisplayString Condition="(ComparisonIndex < 2097152) && (Number > 0)">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[ComparisonIndex / 16384][ComparisonIndex % 16384]))->AnsiName,s}_{Number-1}</DisplayString> <DisplayString Condition="ComparisonIndex < 2097152">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[ComparisonIndex / 16384][ComparisonIndex % 16384]))->AnsiName,s}</DisplayString> <StringView Condition="ComparisonIndex < 2097152">((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[ComparisonIndex / 16384][ComparisonIndex % 16384]))->AnsiName</StringView> </Type> <Type Name="FMinimalName"> <DisplayString Condition="Index >= 2097152">Invalid</DisplayString> <DisplayString Condition="Index < 0">Invalid</DisplayString> <DisplayString Condition="(Index < 2097152) && (Number > 0)">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[Index / 16384][Index % 16384]))->AnsiName}_{Number-1}</DisplayString> <DisplayString Condition="Index < 2097152">{((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[Index / 16384][Index % 16384]))->AnsiName}</DisplayString> <StringView Condition="Index < 2097152">((FNameEntry*)(((FNameEntry***)GFNameTableForDebuggerVisualizers_MT)[Index / 16384][Index % 16384]))->AnsiName</StringView> </Type> <!-- FStatMessage visualizer @see Stats2.h --> <Type Name="FStatMessage"> <!--ST_None=1--> <DisplayString Condition="((NameAndInfo.NameAndInfo.Number >> 9)&0x7) == 1" >{{NoneType NameAndInfo={NameAndInfo.NameAndInfo}}}</DisplayString> <!--ST_int64=2--> <DisplayString Condition="((NameAndInfo.NameAndInfo.Number >> 9)&0x7) == 2" >{{Int64={DebugStatData.Cycles},C={DebugStatData.CCAndDuration[0]},D={DebugStatData.CCAndDuration[1]} NameAndInfo={NameAndInfo.NameAndInfo}}}</DisplayString> <!--ST_double=3--> <DisplayString Condition="((NameAndInfo.NameAndInfo.Number >> 9)&0x7) == 3" >{{Float={DebugStatData.Float} NameAndInfo={NameAndInfo.NameAndInfo}}}</DisplayString> <!--ST_FName=4--> <!--ST_Ptr=5--> <DisplayString Condition="((NameAndInfo.NameAndInfo.Number >> 9)&0x7) == 5" >{{Ptr={DebugStatData.Ptr} NameAndInfo={NameAndInfo.NameAndInfo}}}</DisplayString> </Type> <Type Name="FVector_NetQuantize"> <DisplayString>{{X={X} Y={Y} Z={Z}}</DisplayString> </Type> <Type Name="FVector_NetQuantize10"> <DisplayString>{{X={X} Y={Y} Z={Z}}</DisplayString> </Type> <Type Name="FVector_NetQuantize100"> <DisplayString>{{X={X} Y={Y} Z={Z}}</DisplayString> </Type> <Type Name="FVector_NetQuantizeNormal"> <DisplayString>{{X={X} Y={Y} Z={Z}}</DisplayString> </Type> <!-- TEnumAsByte visualizer --> <Type Name="TEnumAsByte<*>"> <DisplayString>{($T1)Value}</DisplayString> </Type> <!-- UObjectBase visualizer --> <Type Name="UObjectBase"> <DisplayString>(Name={Name}, Outer={Outer})</DisplayString> </Type> <!-- TArray<*,TFixedAllocator<*> > visualizer --> <Type Name="TArray<*,TFixedAllocator<*>>"> <DisplayString Condition="ArrayNum == 0">Empty</DisplayString> <DisplayString Condition="ArrayNum < 0">Invalid</DisplayString> <DisplayString Condition="ArrayMax < ArrayNum">Invalid</DisplayString> <DisplayString Condition="ArrayMax >= ArrayNum">Num={ArrayNum}</DisplayString> <Expand> <ArrayItems Condition="ArrayNum <= ArrayMax"> <Size>ArrayNum</Size> <ValuePointer>($T1*)AllocatorInstance.InlineData</ValuePointer> </ArrayItems> </Expand> </Type> <!-- TArray<*,TInlineAllocator<*,*> > visualizer --> <Type Name="TArray<*,TInlineAllocator<*,*>>"> <DisplayString Condition="ArrayNum == 0">Empty</DisplayString> <DisplayString Condition="ArrayNum < 0">Invalid</DisplayString> <DisplayString Condition="ArrayMax < ArrayNum">Invalid</DisplayString> <DisplayString Condition="ArrayMax >= ArrayNum">Num={ArrayNum}</DisplayString> <Expand> <ArrayItems Condition="ArrayNum <= ArrayMax"> <Size>ArrayNum</Size> <ValuePointer Condition="AllocatorInstance.SecondaryData.Data == 0">($T1*)AllocatorInstance.InlineData</ValuePointer> <ValuePointer Condition="AllocatorInstance.SecondaryData.Data != 0">($T1*)AllocatorInstance.SecondaryData.Data</ValuePointer> </ArrayItems> </Expand> </Type> <!-- TArray visualizer --> <Type Name="TArray<*,*>"> <DisplayString Condition="ArrayNum == 0">Empty</DisplayString> <DisplayString Condition="ArrayNum < 0">Invalid</DisplayString> <DisplayString Condition="ArrayMax < ArrayNum">Invalid</DisplayString> <DisplayString Condition="ArrayMax >= ArrayNum">Num={ArrayNum}</DisplayString> <Expand> <ArrayItems Condition="ArrayNum <= ArrayMax"> <Size>ArrayNum</Size> <ValuePointer>(::$T1*)AllocatorInstance.Data</ValuePointer> </ArrayItems> </Expand> </Type> <!-- TIndirectArray visualizer --> <Type Name="TIndirectArray<*,*>"> <DisplayString Condition="Array.ArrayNum == 0">Empty</DisplayString> <DisplayString Condition="Array.ArrayNum < 0">Invalid</DisplayString> <DisplayString Condition="Array.ArrayMax < Array.ArrayNum">Invalid</DisplayString> <DisplayString Condition="Array.ArrayMax >= Array.ArrayNum">Num={Array.ArrayNum}</DisplayString> <Expand> <IndexListItems Condition="Array.ArrayNum <= Array.ArrayMax"> <Size>Array.ArrayNum</Size> <ValueNode>*(($T1**)Array.AllocatorInstance.Data)[$i]</ValueNode> </IndexListItems> </Expand> </Type> <!-- TChunkedArray visualizer --> <Type Name="TChunkedArray<*,*>"> <DisplayString Condition="NumElements == 0">Empty</DisplayString> <DisplayString Condition="NumElements < 0">Invalid</DisplayString> <DisplayString Condition="NumElements > 0">NumElements={NumElements}, NumChunks={Chunks.Array.ArrayNum}, {NumElementsPerChunk}</DisplayString> <Expand> <IndexListItems Condition="NumElements > 0"> <Size>NumElements</Size> <ValueNode> *( *( ($T1**)Chunks.Array.AllocatorInstance.Data + ($i / NumElementsPerChunk) ) + ($i % NumElementsPerChunk) ) </ValueNode> </IndexListItems> </Expand> </Type> <!-- TSparseArray visualizer --> <Type Name="TSparseArray<*,*>"> <DisplayString Condition="(Data.ArrayNum - NumFreeIndices) <= 0">Empty</DisplayString> <DisplayString Condition="Data.ArrayNum <= Data.ArrayMax">Num={Data.ArrayNum - NumFreeIndices}</DisplayString> <Expand> <IndexListItems Condition="Data.ArrayNum > 0 && Data.ArrayNum <= Data.ArrayMax"> <Size>Data.ArrayNum</Size> <ValueNode Condition="(AllocationFlags.SecondaryData.Data != 0) && (reinterpret_cast<uint32*>(AllocationFlags.SecondaryData.Data)[$i/32]>>$i & 1) != 0">($T1*)Data.AllocatorInstance.Data + $i</ValueNode> <ValueNode Condition="(AllocationFlags.SecondaryData.Data == 0) && (reinterpret_cast<uint32*>(AllocationFlags.InlineData )[$i/32]>>$i & 1) != 0">($T1*)Data.AllocatorInstance.Data + $i</ValueNode> <ValueNode Condition="(AllocationFlags.SecondaryData.Data != 0) && (reinterpret_cast<uint32*>(AllocationFlags.SecondaryData.Data)[$i/32]>>$i & 1) == 0">Invalid</ValueNode> <ValueNode Condition="(AllocationFlags.SecondaryData.Data == 0) && (reinterpret_cast<uint32*>(AllocationFlags.InlineData )[$i/32]>>$i & 1) == 0">Invalid</ValueNode> </IndexListItems> </Expand> </Type> <!-- TBitArray visualizer --> <Type Name="TBitArray<*>"> <DisplayString Condition="NumBits == 0">Empty</DisplayString> <DisplayString Condition="NumBits < 0">Invalid</DisplayString> <DisplayString Condition="NumBits > 0">NumBits={NumBits}, MaxBits={MaxBits}</DisplayString> <Expand> <IndexListItems Condition="NumBits > 0"> <Size>NumBits</Size> <ValueNode Condition="(AllocatorInstance.SecondaryData.Data != 0) && (reinterpret_cast<uint32*>(AllocatorInstance.SecondaryData.Data )[$i/32]>>$i & 1) != 0">1</ValueNode> <ValueNode Condition="(AllocatorInstance.SecondaryData.Data == 0) && (reinterpret_cast<uint32*>(AllocatorInstance.InlineData )[$i/32]>>$i & 1) != 0">1</ValueNode> <ValueNode Condition="(AllocatorInstance.SecondaryData.Data != 0) && (reinterpret_cast<uint32*>(AllocatorInstance.SecondaryData.Data )[$i/32]>>$i & 1) == 0">0</ValueNode> <ValueNode Condition="(AllocatorInstance.SecondaryData.Data == 0) && (reinterpret_cast<uint32*>(AllocatorInstance.InlineData )[$i/32]>>$i & 1) == 0">0</ValueNode> </IndexListItems> </Expand> </Type> <!-- TPair visualizer --> <Type Name="TPair<*,*>"> <DisplayString>({Key}, {Value})</DisplayString> </Type> <!-- TSharedPtr visualizer --> <Type Name="TSharedPtr<*,*>"> <DisplayString Condition="Object == 0">Null</DisplayString> <DisplayString Condition="Object != 0">Ptr={(void*)Object}, SharedRefs={SharedReferenceCount.ReferenceController->SharedReferenceCount}, WeakRefs={SharedReferenceCount.ReferenceController->WeakReferenceCount}, Object={*Object}</DisplayString> <Expand> <Item Condition="Object != 0" Name="[SharedReferenceCount]">SharedReferenceCount.ReferenceController->SharedReferenceCount</Item> <Item Condition="Object != 0" Name="[WeakReferenceCount]">SharedReferenceCount.ReferenceController->WeakReferenceCount</Item> <Item Condition="Object != 0" Name="[Ptr]">(void*)Object</Item> <ExpandedItem Condition="Object != 0">*Object</ExpandedItem> </Expand> </Type> <!-- TSharedRef visualizer --> <Type Name="TSharedRef<*,*>"> <DisplayString Condition="Object != 0">Ptr={(void*)Object}, SharedRefs={SharedReferenceCount.ReferenceController->SharedReferenceCount}, WeakRefs={SharedReferenceCount.ReferenceController->WeakReferenceCount}, Object={*Object}</DisplayString> <Expand> <Item Condition="Object != 0" Name="[SharedReferenceCount]">SharedReferenceCount.ReferenceController->SharedReferenceCount</Item> <Item Condition="Object != 0" Name="[WeakReferenceCount]">SharedReferenceCount.ReferenceController->WeakReferenceCount</Item> <Item Condition="Object != 0" Name="[Ptr]">(void*)Object</Item> <ExpandedItem Condition="Object != 0">*Object</ExpandedItem> </Expand> </Type> <!-- TWeakPtr visualizer --> <Type Name="TWeakPtr<*,*>"> <DisplayString Condition="Object == 0">Null</DisplayString> <DisplayString Condition="WeakReferenceCount.ReferenceController->SharedReferenceCount == 0">Object has been destroyed</DisplayString> <DisplayString Condition="Object != 0">Ptr={(void*)Object}, SharedRefs={WeakReferenceCount.ReferenceController->SharedReferenceCount}, WeakRefs={WeakReferenceCount.ReferenceController->WeakReferenceCount}, Object={*Object}</DisplayString> <Expand> <Item Condition="Object != 0" Name="[SharedReferenceCount]">WeakReferenceCount.ReferenceController->SharedReferenceCount</Item> <Item Condition="Object != 0" Name="[WeakReferenceCount]">WeakReferenceCount.ReferenceController->WeakReferenceCount</Item> <Item Condition="Object != 0 && WeakReferenceCount.ReferenceController->SharedReferenceCount > 0" Name="[Ptr]">(void*)Object</Item> <ExpandedItem Condition="Object != 0 && WeakReferenceCount.ReferenceController->SharedReferenceCount > 0">*Object</ExpandedItem> </Expand> </Type> <!-- TMapBase visualizer --> <Type Name="TMapBase<*,*,*,*,*>"> <DisplayString Condition="Pairs.Elements.Data.ArrayNum - Pairs.Elements.NumFreeIndices <= 0">Empty</DisplayString> <DisplayString Condition="Pairs.Elements.Data.ArrayNum <= Pairs.Elements.Data.ArrayMax" >Num={Pairs.Elements.Data.ArrayNum - Pairs.Elements.NumFreeIndices}</DisplayString> <Expand> <IndexListItems Condition="Pairs.Elements.Data.ArrayNum - Pairs.Elements.NumFreeIndices > 0 && Pairs.Elements.Data.ArrayNum <= Pairs.Elements.Data.ArrayMax"> <Size>Pairs.Elements.Data.ArrayNum</Size> <ValueNode Condition="(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data != 0) && (reinterpret_cast<uint32*>(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data)[$i/32]>>$i & 1) != 0">((TSetElement<TPair<$T1,$T2> > *)Pairs.Elements.Data.AllocatorInstance.Data)[$i].Value</ValueNode> <ValueNode Condition="(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data == 0) && (reinterpret_cast<uint32*>(Pairs.Elements.AllocationFlags.AllocatorInstance.InlineData )[$i/32]>>$i & 1) != 0">((TSetElement<TPair<$T1,$T2> > *)Pairs.Elements.Data.AllocatorInstance.Data)[$i].Value</ValueNode> <ValueNode Condition="(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data != 0) && (reinterpret_cast<uint32*>(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data)[$i/32]>>$i & 1) == 0">Invalid</ValueNode> <ValueNode Condition="(Pairs.Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data == 0) && (reinterpret_cast<uint32*>(Pairs.Elements.AllocationFlags.AllocatorInstance.InlineData )[$i/32]>>$i & 1) == 0">Invalid</ValueNode> </IndexListItems> </Expand> </Type> <!-- TSet visualizer --> <Type Name="TSet<*,*,*>"> <DisplayString Condition="Elements.Data.ArrayNum - Elements.NumFreeIndices <= 0">Empty</DisplayString> <DisplayString Condition="Elements.Data.ArrayNum <= Elements.Data.ArrayMax">Num={Elements.Data.ArrayNum - Elements.NumFreeIndices}</DisplayString> <Expand> <IndexListItems Condition="Elements.Data.ArrayNum - Elements.NumFreeIndices > 0 && Elements.Data.ArrayNum <= Elements.Data.ArrayMax"> <Size>Elements.Data.ArrayNum</Size> <ValueNode Condition="(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data != 0) && (reinterpret_cast<uint32*>(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data)[$i/32]>>$i & 1) != 0">((TSetElement <$T1> *)Elements.Data.AllocatorInstance.Data)[$i].Value</ValueNode> <ValueNode Condition="(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data == 0) && (reinterpret_cast<uint32*>(Elements.AllocationFlags.AllocatorInstance.InlineData )[$i/32]>>$i & 1) != 0">((TSetElement <$T1> *)Elements.Data.AllocatorInstance.Data)[$i].Value</ValueNode> <ValueNode Condition="(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data != 0) && (reinterpret_cast<uint32*>(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data)[$i/32]>>$i & 1) == 0">Invalid</ValueNode> <ValueNode Condition="(Elements.AllocationFlags.AllocatorInstance.SecondaryData.Data == 0) && (reinterpret_cast<uint32*>(Elements.AllocationFlags.AllocatorInstance.InlineData)[$i/32]>>$i & 1) == 0">Invalid</ValueNode> </IndexListItems> </Expand> </Type> <!-- FWeakObjectPtr|TWeakObjectPtr<*>|TAutoWeakObjectPtr<*> visualizer --> <Type Name="FWeakObjectPtr"> <DisplayString Condition="ObjectSerialNumber < 1">NULL</DisplayString> <DisplayString Condition="*((*(*GSerialNumberBlocksForDebugVisualizers + (ObjectIndex / 0x4000))) + (ObjectIndex % 0x4000)) != ObjectSerialNumber">STALE</DisplayString> <DisplayString>{GObjectArrayForDebugVisualizers[ObjectIndex / 0x4000][ObjectIndex % 0x4000]}</DisplayString> <Expand> <ExpandedItem>GObjectArrayForDebugVisualizers[ObjectIndex / 0x4000][ObjectIndex % 0x4000]</ExpandedItem> </Expand> </Type> <Type Name="TWeakObjectPtr<*>"> <DisplayString Condition="ObjectSerialNumber < 1">NULL</DisplayString> <DisplayString Condition="*((*(*GSerialNumberBlocksForDebugVisualizers + (ObjectIndex / 0x4000))) + (ObjectIndex % 0x4000)) != ObjectSerialNumber">STALE</DisplayString> <DisplayString>{GObjectArrayForDebugVisualizers[ObjectIndex / 0x4000][ObjectIndex % 0x4000]}</DisplayString> <Expand> <ExpandedItem>GObjectArrayForDebugVisualizers[ObjectIndex / 0x4000][ObjectIndex % 0x4000]</ExpandedItem> </Expand> </Type> <Type Name="TAutoWeakObjectPtr<*>"> <DisplayString Condition="ObjectSerialNumber < 1">NULL</DisplayString> <DisplayString Condition="*((*(*GSerialNumberBlocksForDebugVisualizers + (ObjectIndex / 0x4000))) + (ObjectIndex % 0x4000)) != ObjectSerialNumber">STALE</DisplayString> <DisplayString>{GObjectArrayForDebugVisualizers[ObjectIndex / 0x4000][ObjectIndex % 0x4000]}</DisplayString> <Expand> <ExpandedItem>GObjectArrayForDebugVisualizers[ObjectIndex / 0x4000][ObjectIndex % 0x4000]</ExpandedItem> </Expand> </Type> <!-- FSubobjectPtr|TSubobjectPtr visualizer --> <Type Name="FSubobjectPtr"> <DisplayString>{Object}</DisplayString> </Type> <Type Name="TSubobjectPtr<*>"> <DisplayString>{Object}</DisplayString> </Type> <!-- TOptional visualizer --> <Type Name="TOptional<*>"> <DisplayString Condition="!bIsSet">Unset</DisplayString> <DisplayString Condition="bIsSet">Set: {{{*($T1*)&Value}}}</DisplayString> <Expand> <ExpandedItem Condition="bIsSet">*($T1*)&Value</ExpandedItem> </Expand> </Type> <!-- TFunction visualizer --> <Type Name="UE4Function_Private::TDebugHelper<*>"> <DisplayString>{*Ptr}</DisplayString> <Expand> <ExpandedItem>*Ptr</ExpandedItem> </Expand> </Type> <Type Name="TFunctionRef<*>"> <DisplayString Condition="Ptr">{DebugPtrStorage}</DisplayString> <DisplayString Condition="!Ptr">Unset</DisplayString> <Expand> <ExpandedItem Condition="Ptr">DebugPtrStorage</ExpandedItem> </Expand> </Type> </AutoVisualizer>
下面的sh执行文件可以用于一键执行:
#!/bin/bash cp_args="-v --preserve=timestamps" cp $cp_args UE{3,4}.natvis "$USERPROFILE/Documents/Visual Studio 2012/Visualizers" cp $cp_args UE{3,4}.natvis "$USERPROFILE/Documents/Visual Studio 2013/Visualizers" cp $cp_args PS4UE{3,4}.natvis "$USERPROFILE/Documents/SCE/orbis-debugger"
注意在以上几个文件中更改自己所使用的VS版本号使之与本机VS版本一致;