UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
VVMValueObjectInline.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
4#if WITH_VERSE_VM || defined(__INTELLISENSE__)
5
9#include "VerseVM/VVMCell.h"
12
13// NOTE: (yiliang.siew) Silence these warnings for now in the cases below.
14#if defined(__GNUC__) || defined(__clang__)
15#pragma GCC diagnostic push
16#pragma GCC diagnostic ignored "-Wswitch-enum"
17#endif
18
19namespace Verse
20{
21
22inline VValueObject& VValueObject::NewUninitialized(FAllocationContext Context, VEmergentType& InEmergentType)
23{
24 return *new (AllocateCell(Context, *InEmergentType.CppClassInfo, InEmergentType.Shape->NumIndexedFields)) VValueObject(Context, InEmergentType);
25}
26
27inline std::byte* VValueObject::AllocateCell(FAllocationContext Context, VCppClassInfo& CppClassInfo, uint64 NumIndexedFields)
28{
29 return Context.AllocateFastCell(DataOffset(CppClassInfo) + NumIndexedFields * sizeof(VRestValue));
30}
31
32inline VValueObject::VValueObject(FAllocationContext Context, VEmergentType& InEmergentType)
34{
35 // We only need to allocate space for indexed fields since we are raising constants to the shape
36 // and not storing their data on per-object instances.
38 const uint64 NumIndexedFields = InEmergentType.Shape->NumIndexedFields;
40 {
41 // We map whether this field has been created in the emergent shape
42 new (&Data[Index]) VRestValue(0);
43 }
44}
45
46inline bool VValueObject::CreateFieldCached(FAllocationContext Context, FCreateFieldCacheCase Cache)
47{
48 switch (Cache.Kind)
49 {
50 case FCreateFieldCacheCase::EKind::ValueObjectField:
51 {
52 bool bNewField = EmergentTypeOffset != Cache.NextEmergentTypeOffset;
53 if (bNewField)
54 {
55 SetEmergentType(Context, FHeap::EmergentTypeOffsetToPtr(Cache.NextEmergentTypeOffset));
56 }
57 return bNewField;
58 }
59 default:
60 return false;
61 }
62}
63
64inline bool VValueObject::CreateField(FAllocationContext Context, VUniqueString& Name, FCreateFieldCacheCase* OutCacheCase)
65{
66 // TODO: (yiliang.siew) In the future, when the emergent type cache is not limited to the class, this will also need
67 // to consider the type of the field, not just the name of the field itself, because a field being checked if it's
68 // in the shape versus in the object should not be considered the same field when checking if it's already been
69 // initialized.
72 const VShape* Shape = EmergentType->Shape.Get();
73 V_DIE_UNLESS(Shape);
74 FSetElementId Index = Shape->Fields.FindId({Context, Name});
75 V_DIE_UNLESS(Index.IsValidId());
76 const VShape::VEntry& Field = Shape->Fields.Get(Index).Value;
77 // TODO: (yiliang.siew) We shouldn't be able to hit this today, but in the future when we allow adding fields dynamically
78 // to objects, we should just return `false` if we don't have the field yet.
79 V_DIE_IF_MSG(Field.IsProperty(), "`VValueObject::CreateField` was called for a native property: %s! This should be done through `VNativeConstructorWrapper::CreateField` instead!", *Name.AsString());
80
81 if (Field.Type == EFieldType::Constant) // Field data lives in the shape, so we shouldn't bother running any initialization code here.
82 {
83 V_DIE_IF(Field.Value.Get().IsUninitialized());
84 if (Field.Value.Get().IsCellOfType<VAccessor>())
85 {
86 int32 FieldIndex = Index.AsInteger();
87 // proxy vars are stored as constants but still need to be marked like normal vars
88 if (!EmergentType->IsFieldCreated(FieldIndex))
89 {
90 VEmergentType* NewType = EmergentType->MarkFieldAsCreated(Context, FieldIndex);
91 SetEmergentType(Context, NewType);
92 if (OutCacheCase)
93 {
94 OutCacheCase->Kind = FCreateFieldCacheCase::EKind::ValueObjectField;
95 OutCacheCase->FieldIndex = FieldIndex;
96 OutCacheCase->NextEmergentTypeOffset = FHeap::EmergentTypePtrToOffset(NewType);
97 }
98 return true;
99 }
100 }
101 if (OutCacheCase)
102 {
103 OutCacheCase->Kind = FCreateFieldCacheCase::EKind::ValueObjectConstant;
104 }
105 return false;
106 }
107
108 if (Field.Type == EFieldType::Offset) // Field data lives in the object
109 {
110 int32 FieldIndex = Index.AsInteger();
111 if (EmergentType->IsFieldCreated(FieldIndex))
112 {
113 if (OutCacheCase)
114 {
115 OutCacheCase->Kind = FCreateFieldCacheCase::EKind::ValueObjectField;
116 OutCacheCase->FieldIndex = FieldIndex;
117 OutCacheCase->NextEmergentTypeOffset = FHeap::EmergentTypePtrToOffset(EmergentType);
118 }
119 return false;
120 }
121
122 VEmergentType* NewType = EmergentType->MarkFieldAsCreated(Context, FieldIndex);
123 SetEmergentType(Context, NewType);
124 if (OutCacheCase)
125 {
126 OutCacheCase->Kind = FCreateFieldCacheCase::EKind::ValueObjectField;
127 OutCacheCase->FieldIndex = FieldIndex;
128 OutCacheCase->NextEmergentTypeOffset = FHeap::EmergentTypePtrToOffset(NewType);
129 }
130 return true;
131 }
132
133 V_DIE("%s has an unsupported field type!", *Name.AsString());
134}
135
136} // namespace Verse
137#if defined(__GNUC__) || defined(__clang__)
138#pragma GCC diagnostic pop
139#endif
140#endif // WITH_VERSE_VM
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
FPlatformTypes::uint64 uint64
A 64-bit unsigned integer.
Definition Platform.h:1117
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
Definition SetUtilities.h:95
GeometryCollection::Facades::FMuscleActivationData Data
Definition MuscleActivationConstraints.h:15
Definition FieldSystemNoiseAlgo.cpp:6
Definition Archive.h:36
U16 Index
Definition radfft.cpp:71