public static TestUObjectFlags ( string uobj_expr_str, string flags, DkmVisualizedExpression context_expr ) : |
||
uobj_expr_str | string | |
flags | string | |
context_expr | DkmVisualizedExpression | |
return |
public static bool IsNativeUClassOrUInterface(string uclass_expr_str, DkmVisualizedExpression context_expr) { // @TODO: Think we should really check class flags for CLASS_Native, to potentially support interface classes too. // (see comment on flag in UE4 header) return(UE4Utility.TestUObjectFlags(uclass_expr_str, ObjFlags.Native, context_expr)); }
public void EvaluateProperties() { List <DkmEvaluationResult> evals = new List <DkmEvaluationResult>(); // Assume we've been constructed with the fabricated property list expression DkmChildVisualizedExpression proplist_expr = (DkmChildVisualizedExpression)expression_; Debug.Assert(proplist_expr != null); // start could be an expression with the type of any UObject-derived class DkmVisualizedExpression start_expr = proplist_expr.Parent; string base_expression_str = Utility.GetExpressionFullName(start_expr); base_expression_str = Utility.StripExpressionFormatting(base_expression_str); ExpressionManipulator obj_em = null; // @TODO: Deal with non-pointer start expression obj_em = ExpressionManipulator.FromExpression(base_expression_str); // Determine if our base expression is <UObject-type>* or <UObject-type> bool is_pointer = start_expr.GetDataItem <UObjectDataItem>().IsPointer; if (!is_pointer) { obj_em = obj_em.AddressOf(); } var uclass_em = obj_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjClass); if (Config.PropertyDisplayPolicy == Config.PropDisplayPolicyType.BlueprintOnly) { // See if the actual class of the object instance whose properties we want to enumerate // is native or not. bool is_native = UE4Utility.TestUObjectFlags( uclass_em.Expression, ObjFlags.Native, start_expr ); // If the instance class is native, then it can't possibly have any non-native properties, // so bail out now. // @TODO: Even if the class is not native, we should still be able to avoid doing all the work // for enumerating every native property in order to find the non-native ones... if (is_native) { return; } } // Get the UStruct part of the UClass, in order to begin iterating properties var ustruct_em = uclass_em.PtrCast(Typ.UStruct); // Now access PropertyLink member, which is the start of the linked list of properties var prop_em = ustruct_em.PtrMember(Memb.FirstProperty); uint idx = 0; while (true) { Debug.Print("UE4PV: Invoking raw eval on UProperty* expression"); var prop_eval = DefaultEE.DefaultEval(prop_em.Expression, start_expr, true) as DkmSuccessEvaluationResult; Debug.Assert(prop_eval != null); if (prop_eval.Address.Value == 0) { // nullptr, end of property list break; } bool should_skip = false; if (!should_skip && Config.PropertyDisplayPolicy == Config.PropDisplayPolicyType.BlueprintOnly) { // Check to see if this property is native or blueprint // We can test this by getting the UProperty's Outer, and checking its object flags for RF_Native. var prop_outer_em = prop_em.PtrCast(Typ.UObjectBase).PtrMember(Memb.ObjOuter); bool is_native = UE4Utility.TestUObjectFlags(prop_outer_em.Expression, ObjFlags.Native, start_expr); // According to UE4 UStruct API docs, property linked list is ordered from most-derived // to base. If so, we should be able to bail out here knowing that having hit a native property, // all following properties must be native too. if (is_native) { return; } } if (!should_skip) { // @TODO: Here we use the starting expression for the container. // May not work if the root expression was not of pointer type!! var prop_val_eval = GeneratePropertyValueEval( obj_em.Expression, prop_em.Expression, idx, start_expr ); if (prop_val_eval != null && !Config.IsPropertyHidden(prop_val_eval.Name)) { prop_evals_[prop_val_eval.Name] = prop_val_eval; ++idx; } } // Advance to next link prop_em = prop_em.PtrMember(Memb.NextProperty); } }