private static void ProcessMember(ref ComputeUpdateOperationState state, UpdateMemberInfo animationPath, UpdatableMember updatableMember, List <object> temporaryObjectsList) { int leaveOffset = 0; var leaveOperation = UpdateOperationType.Invalid; var updatableField = updatableMember as UpdatableField; if (updatableField != null) { // Apply field offset state.NewOffset += updatableField.Offset; if (state.ParseElementEnd == animationPath.Name.Length) { // Leaf node, perform the set operation state.UpdateOperations.Add(new UpdateOperation { Type = updatableField.GetSetOperationType(), Member = updatableField, AdjustOffset = state.NewOffset - state.PreviousOffset, DataOffset = animationPath.DataOffset, }); state.PreviousOffset = state.NewOffset; } else if (!updatableField.MemberType.GetTypeInfo().IsValueType) { // Only in case of objects we need to enter into them state.UpdateOperations.Add(new UpdateOperation { Type = UpdateOperationType.EnterObjectField, Member = updatableField, AdjustOffset = state.NewOffset - state.PreviousOffset, }); leaveOperation = UpdateOperationType.Leave; leaveOffset = state.NewOffset; state.PreviousOffset = state.NewOffset = 0; } } else { var updatableProperty = updatableMember as UpdatablePropertyBase; if (updatableProperty != null) { if (state.ParseElementEnd == animationPath.Name.Length) { // Leaf node, perform the set the value state.UpdateOperations.Add(new UpdateOperation { Type = updatableProperty.GetSetOperationType(), Member = updatableProperty, AdjustOffset = state.NewOffset - state.PreviousOffset, DataOffset = animationPath.DataOffset, }); state.PreviousOffset = state.NewOffset; } else { // Otherwise enter into the property bool isStruct = updatableProperty.MemberType.GetTypeInfo().IsValueType; int temporaryObjectIndex = -1; if (isStruct) { // Struct properties need a storage area so that we can later set the updated value back into the property leaveOperation = UpdateOperationType.LeaveAndCopyStructPropertyBase; temporaryObjectIndex = temporaryObjectsList.Count; temporaryObjectsList.Add(Activator.CreateInstance(updatableProperty.MemberType)); } else { leaveOperation = UpdateOperationType.Leave; } state.UpdateOperations.Add(new UpdateOperation { Type = updatableProperty.GetEnterOperationType(), Member = updatableProperty, AdjustOffset = state.NewOffset - state.PreviousOffset, DataOffset = temporaryObjectIndex, SkipCountIfNull = -1, }); leaveOffset = state.NewOffset; state.PreviousOffset = state.NewOffset = 0; } } } // No need to add the last part of the path, as we rarely set and then enter (and if we do we need to reevaluate updated value anyway) if (state.ParseElementEnd < animationPath.Name.Length) { state.StackPath.Add(new AnimationBuilderStackEntry(updatableMember.MemberType, state.ParseElementStart, state.ParseElementEnd, state.UpdateOperations.Count - 1) { Member = updatableMember, LeaveOperation = leaveOperation, LeaveOffset = leaveOffset, ObjectStartOffset = state.NewOffset }); } }
private static void ProcessMember(ref ComputeUpdateOperationState state, UpdateMemberInfo animationPath, UpdatableMember updatableMember, List<object> temporaryObjectsList) { int leaveOffset = 0; var leaveOperation = UpdateOperationType.Invalid; var updatableField = updatableMember as UpdatableField; if (updatableField != null) { // Apply field offset state.NewOffset += updatableField.Offset; if (state.ParseElementEnd == animationPath.Name.Length) { // Leaf node, perform the set operation state.UpdateOperations.Add(new UpdateOperation { Type = updatableField.GetSetOperationType(), Member = updatableField, AdjustOffset = state.NewOffset - state.PreviousOffset, DataOffset = animationPath.DataOffset, }); state.PreviousOffset = state.NewOffset; } else if (!updatableField.MemberType.GetTypeInfo().IsValueType) { // Only in case of objects we need to enter into them state.UpdateOperations.Add(new UpdateOperation { Type = UpdateOperationType.EnterObjectField, Member = updatableField, AdjustOffset = state.NewOffset - state.PreviousOffset, }); leaveOperation = UpdateOperationType.Leave; leaveOffset = state.NewOffset; state.PreviousOffset = state.NewOffset = 0; } } else { var updatableProperty = updatableMember as UpdatablePropertyBase; if (updatableProperty != null) { if (state.ParseElementEnd == animationPath.Name.Length) { // Leaf node, perform the set the value state.UpdateOperations.Add(new UpdateOperation { Type = updatableProperty.GetSetOperationType(), Member = updatableProperty, AdjustOffset = state.NewOffset - state.PreviousOffset, DataOffset = animationPath.DataOffset, }); state.PreviousOffset = state.NewOffset; } else { // Otherwise enter into the property bool isStruct = updatableProperty.MemberType.GetTypeInfo().IsValueType; int temporaryObjectIndex = -1; if (isStruct) { // Struct properties need a storage area so that we can later set the updated value back into the property leaveOperation = UpdateOperationType.LeaveAndCopyStructPropertyBase; temporaryObjectIndex = temporaryObjectsList.Count; temporaryObjectsList.Add(Activator.CreateInstance(updatableProperty.MemberType)); } else { leaveOperation = UpdateOperationType.Leave; } state.UpdateOperations.Add(new UpdateOperation { Type = updatableProperty.GetEnterOperationType(), Member = updatableProperty, AdjustOffset = state.NewOffset - state.PreviousOffset, DataOffset = temporaryObjectIndex, SkipCountIfNull = -1, }); leaveOffset = state.NewOffset; state.PreviousOffset = state.NewOffset = 0; } } } // No need to add the last part of the path, as we rarely set and then enter (and if we do we need to reevaluate updated value anyway) if (state.ParseElementEnd < animationPath.Name.Length) { state.StackPath.Add(new AnimationBuilderStackEntry(updatableMember.MemberType, state.ParseElementStart, state.ParseElementEnd, state.UpdateOperations.Count - 1) { Member = updatableMember, LeaveOperation = leaveOperation, LeaveOffset = leaveOffset, ObjectStartOffset = state.NewOffset }); } }