Exemplo n.º 1
0
        protected override Control MakeUI(object value)
        {
            if (value == null)
            {
                return(new Label {
                    Text = "null", Align = Label.AlignMode.Right
                });
            }

            // NOTE: value is NOT always the actual object.
            // Only thing we can really rely on is that ToString works out correctly.
            // This is because of reference tokens, but due to simplicity the object ref is still passed.

            var toString = value.ToString();

            if (value.GetType().FullName == toString)
            {
                toString = TypeAbbreviation.Abbreviate(toString);
            }

            var button = new Button
            {
                Text                = $"Reference: {toString}",
                ClipText            = true,
                SizeFlagsHorizontal = Control.SizeFlags.FillExpand
            };

            button.OnPressed += _ =>
            {
                OnPressed?.Invoke();
            };
            return(button);
        }
        protected internal static IEnumerable <IGrouping <Type, Control> > LocalPropertyList(object obj, IViewVariablesManagerInternal vvm,
                                                                                             IRobustSerializer robustSerializer)
        {
            var styleOther = false;
            var type       = obj.GetType();

            var members = new List <(MemberInfo, VVAccess, object?value, Action <object?, bool> onValueChanged, Type)>();

            foreach (var fieldInfo in type.GetAllFields())
            {
                if (!ViewVariablesUtility.TryGetViewVariablesAccess(fieldInfo, out var access))
                {
                    continue;
                }

                members.Add((fieldInfo, (VVAccess)access, fieldInfo.GetValue(obj), (v, _) => fieldInfo.SetValue(obj, v),
                             fieldInfo.FieldType));
            }

            foreach (var propertyInfo in type.GetAllProperties())
            {
                if (!ViewVariablesUtility.TryGetViewVariablesAccess(propertyInfo, out var access))
                {
                    continue;
                }

                if (!propertyInfo.IsBasePropertyDefinition())
                {
                    continue;
                }

                members.Add((propertyInfo, (VVAccess)access, propertyInfo.GetValue(obj),
                             (v, _) => propertyInfo.GetSetMethod(true) !.Invoke(obj, new[] { v }), propertyInfo.PropertyType));
            }

            var groupedSorted = members
                                .OrderBy(p => p.Item1.Name)
                                .GroupBy(p => p.Item1.DeclaringType !, tuple =>
            {
                var(memberInfo, access, value, onValueChanged, memberType) = tuple;
                var data = new ViewVariablesBlobMembers.MemberData
                {
                    Editable   = access == VVAccess.ReadWrite,
                    Name       = memberInfo.Name,
                    Type       = memberType.AssemblyQualifiedName,
                    TypePretty = TypeAbbreviation.Abbreviate(memberType),
                    Value      = value
                };

                var propertyEdit = new ViewVariablesPropertyControl(vvm, robustSerializer);
                propertyEdit.SetStyle(styleOther = !styleOther);
                var editor             = propertyEdit.SetProperty(data);
                editor.OnValueChanged += onValueChanged;
                return(propertyEdit);
            })
                                .OrderByDescending(p => p.Key, TypeHelpers.TypeInheritanceComparer);

            return(groupedSorted);
        }
        protected internal static IEnumerable <Control> LocalPropertyList(object obj, IViewVariablesManagerInternal vvm,
                                                                          IResourceCache resCache)
        {
            var styleOther = false;
            var type       = obj.GetType();

            var members = new List <(MemberInfo, VVAccess, object?value, Action <object> onValueChanged, Type)>();

            foreach (var fieldInfo in type.GetAllFields())
            {
                var attr = fieldInfo.GetCustomAttribute <ViewVariablesAttribute>();
                if (attr == null)
                {
                    continue;
                }

                members.Add((fieldInfo, attr.Access, fieldInfo.GetValue(obj), v => fieldInfo.SetValue(obj, v),
                             fieldInfo.FieldType));
            }

            foreach (var propertyInfo in type.GetAllProperties())
            {
                var attr = propertyInfo.GetCustomAttribute <ViewVariablesAttribute>();
                if (attr == null)
                {
                    continue;
                }

                if (!propertyInfo.IsBasePropertyDefinition())
                {
                    continue;
                }

                members.Add((propertyInfo, attr.Access, propertyInfo.GetValue(obj),
                             v => propertyInfo.GetSetMethod(true) !.Invoke(obj, new[] { v }), propertyInfo.PropertyType));
            }

            members.Sort((a, b) => string.Compare(a.Item1.Name, b.Item1.Name, StringComparison.Ordinal));

            foreach (var(memberInfo, access, value, onValueChanged, memberType) in members)
            {
                var data = new ViewVariablesBlobMembers.MemberData
                {
                    Editable   = access == VVAccess.ReadWrite,
                    Name       = memberInfo.Name,
                    Type       = memberType.AssemblyQualifiedName,
                    TypePretty = TypeAbbreviation.Abbreviate(memberType),
                    Value      = value
                };

                var propertyEdit = new ViewVariablesPropertyControl(vvm, resCache);
                propertyEdit.SetStyle(styleOther = !styleOther);
                var editor = propertyEdit.SetProperty(data);
                editor.OnValueChanged += onValueChanged;

                yield return(propertyEdit);
            }
        }
        public override ViewVariablesBlob?DataRequest(ViewVariablesRequest viewVariablesRequest)
        {
            var entMan = IoCManager.Resolve <IEntityManager>();

            if (viewVariablesRequest is ViewVariablesRequestMembers)
            {
                var blob = new ViewVariablesBlobMembers();

                // TODO VV: Fill blob with info about this entity.

                return(blob);
            }

            if (viewVariablesRequest is ViewVariablesRequestEntityComponents)
            {
                var list = new List <ViewVariablesBlobEntityComponents.Entry>();
                // See engine#636 for why the Distinct() call.
                foreach (var component in entMan.GetComponents(_entity))
                {
                    var type = component.GetType();
                    list.Add(new ViewVariablesBlobEntityComponents.Entry
                    {
                        Stringified = TypeAbbreviation.Abbreviate(type), FullName = type.FullName, ComponentName = component.Name
                    });
                }

                return(new ViewVariablesBlobEntityComponents
                {
                    ComponentTypes = list
                });
            }

            if (viewVariablesRequest is ViewVariablesRequestAllValidComponents)
            {
                var list = new List <string>();

                var componentFactory = IoCManager.Resolve <IComponentFactory>();

                foreach (var type in componentFactory.AllRegisteredTypes)
                {
                    if (entMan.HasComponent(_entity, type))
                    {
                        continue;
                    }

                    list.Add(componentFactory.GetRegistration(type).Name);
                }

                return(new ViewVariablesBlobAllValidComponents()
                {
                    ComponentTypes = list
                });
            }

            return(base.DataRequest(viewVariablesRequest));
        }
        public override async void Refresh()
        {
            _memberList.DisposeAllChildren();

            if (Instance.Object != null)
            {
                var first = true;
                foreach (var group in ViewVariablesInstance.LocalPropertyList(Instance.Object,
                                                                              Instance.ViewVariablesManager, _robustSerializer))
                {
                    CreateMemberGroupHeader(
                        ref first,
                        TypeAbbreviation.Abbreviate(group.Key),
                        _memberList);

                    foreach (var control in group)
                    {
                        _memberList.AddChild(control);
                    }
                }
            }
            else
            {
                DebugTools.AssertNotNull(Instance.Session);

                var blob = await Instance.ViewVariablesManager.RequestData <ViewVariablesBlobMembers>(
                    Instance.Session !, new ViewVariablesRequestMembers());

                var otherStyle = false;
                var first      = true;
                foreach (var(groupName, groupMembers) in blob.MemberGroups)
                {
                    CreateMemberGroupHeader(ref first, groupName, _memberList);

                    foreach (var propertyData in groupMembers)
                    {
                        var propertyEdit = new ViewVariablesPropertyControl(_vvm, _robustSerializer);
                        propertyEdit.SetStyle(otherStyle = !otherStyle);
                        var editor = propertyEdit.SetProperty(propertyData);

                        var selectorChain = new object[] { new ViewVariablesMemberSelector(propertyData.PropertyIndex) };
                        editor.WireNetworkSelector(Instance.Session !.SessionId, selectorChain);
                        editor.OnValueChanged += o =>
                        {
                            Instance.ViewVariablesManager.ModifyRemote(Instance.Session !,
                                                                       selectorChain, o);
                        };

                        _memberList.AddChild(propertyEdit);
                    }
                }
            }
        }
Exemplo n.º 6
0
        protected override void Update(FrameEventArgs args)
        {
            base.Update(args);

            if ((_gameTiming.RealTime - _lastUpdate).Seconds < 1 || !VisibleInTree)
            {
                return;
            }

            _lastUpdate = _gameTiming.RealTime;

            var bandwidth = _netManager.MessageBandwidthUsage
                            .OrderByDescending(p => p.Value)
                            .Select(p => $"{TypeAbbreviation.Abbreviate(p.Key)}: {p.Value / OneKibibyte} KiB");

            _contents.Text = string.Join('\n', bandwidth);

            MinimumSizeChanged();
        }
        public override ViewVariablesBlob DataRequest(ViewVariablesRequest viewVariablesRequest)
        {
            if (viewVariablesRequest is ViewVariablesRequestEntityComponents)
            {
                var list = new List <ViewVariablesBlobEntityComponents.Entry>();
                // See engine#636 for why the Distinct() call.
                foreach (var component in _entity.GetAllComponents())
                {
                    var type = component.GetType();
                    list.Add(new ViewVariablesBlobEntityComponents.Entry
                    {
                        Stringified = TypeAbbreviation.Abbreviate(type.ToString()), FullName = type.FullName
                    });
                }

                return(new ViewVariablesBlobEntityComponents
                {
                    ComponentTypes = list
                });
            }

            return(base.DataRequest(viewVariablesRequest));
        }
        private void PopulateClientComponents()
        {
            _clientComponents.DisposeAllChildren();

            _clientComponents.AddChild(_clientComponentsSearchBar = new LineEdit
            {
                PlaceHolder      = Loc.GetString("view-variable-instance-entity-client-components-search-bar-placeholder"),
                HorizontalExpand = true,
            });

            _clientComponents.AddChild(_clientComponentsAddButton = new Button()
            {
                Text             = Loc.GetString("view-variable-instance-entity-server-components-add-component-button-placeholder"),
                HorizontalExpand = true,
            });

            _clientComponentsAddButton.OnPressed     += OnClientComponentsAddButtonPressed;
            _clientComponentsSearchBar.OnTextChanged += OnClientComponentsSearchBarChanged;

            var componentList = _entityManager.GetComponents(_entity).OrderBy(c => c.GetType().ToString());

            foreach (var component in componentList)
            {
                var button = new Button {
                    Text = TypeAbbreviation.Abbreviate(component.GetType()), TextAlign = Label.AlignMode.Left
                };
                var removeButton = new TextureButton()
                {
                    StyleClasses        = { DefaultWindow.StyleClassWindowCloseButton },
                    HorizontalAlignment = HAlignment.Right
                };
                button.OnPressed       += _ => ViewVariablesManager.OpenVV(component);
                removeButton.OnPressed += _ => RemoveClientComponent(component);
                button.AddChild(removeButton);
                _clientComponents.AddChild(button);
            }
        }
Exemplo n.º 9
0
        private void PopulateClientComponents()
        {
            _clientComponents.DisposeAllChildren();

            _clientComponents.AddChild(_clientComponentsSearchBar = new LineEdit
            {
                PlaceHolder         = Loc.GetString("Search"),
                SizeFlagsHorizontal = SizeFlags.FillExpand
            });

            _clientComponents.AddChild(_clientComponentsAddButton = new Button()
            {
                Text = Loc.GetString("Add Component"),
                SizeFlagsHorizontal = SizeFlags.FillExpand
            });

            _clientComponentsAddButton.OnPressed     += OnClientComponentsAddButtonPressed;
            _clientComponentsSearchBar.OnTextChanged += OnClientComponentsSearchBarChanged;

            var componentList = _entity.GetAllComponents().OrderBy(c => c.GetType().ToString());

            foreach (var component in componentList)
            {
                var button = new Button {
                    Text = TypeAbbreviation.Abbreviate(component.GetType()), TextAlign = Label.AlignMode.Left
                };
                var removeButton = new TextureButton()
                {
                    StyleClasses        = { SS14Window.StyleClassWindowCloseButton },
                    SizeFlagsHorizontal = SizeFlags.ShrinkEnd
                };
                button.OnPressed       += _ => ViewVariablesManager.OpenVV(component);
                removeButton.OnPressed += _ => RemoveClientComponent(component);
                button.AddChild(removeButton);
                _clientComponents.AddChild(button);
            }
        }
Exemplo n.º 10
0
        public ViewVariablesBlob?DataRequest(ViewVariablesRequest messageRequestMeta)
        {
            if (messageRequestMeta is ViewVariablesRequestMetadata)
            {
                return(new ViewVariablesBlobMetadata
                {
                    ObjectType = ObjectType.AssemblyQualifiedName,
                    ObjectTypePretty = TypeAbbreviation.Abbreviate(ObjectType),
                    Stringified = Object.ToString(),
                    Traits = new List <object>(Host.TraitIdsFor(ObjectType))
                });
            }

            foreach (var trait in _traits)
            {
                var blob = trait.DataRequest(messageRequestMeta);
                if (blob != null)
                {
                    return(blob);
                }
            }

            return(null);
        }
Exemplo n.º 11
0
        /// <summary>
        ///     Swaps values like references over to reference tokens to prevent issues.
        /// </summary>
        protected object MakeValueNetSafe(object value)
        {
            if (value == null)
            {
                return(null);
            }

            var valType = value.GetType();

            if (!valType.IsValueType)
            {
                // TODO: More flexibility in which types can be sent here.
                if (valType != typeof(string))
                {
                    var stringified = value.ToString();
                    if (stringified == value.GetType().FullName)
                    {
                        stringified = TypeAbbreviation.Abbreviate(stringified);
                    }
                    return(new ViewVariablesBlobMembers.ReferenceToken
                    {
                        Stringified = stringified
                    });
                }
            }
            else if (!Session.RobustSerializer.CanSerialize(valType))
            {
                // Can't send this value type over the wire.
                return(new ViewVariablesBlobMembers.ServerValueTypeToken
                {
                    Stringified = value.ToString()
                });
            }

            return(value);
        }
        public override void Initialize(DefaultWindow window, object obj)
        {
            _entity = (EntityUid)obj;

            var scrollContainer = new ScrollContainer();

            //scrollContainer.SetAnchorPreset(Control.LayoutPreset.Wide, true);
            window.Contents.AddChild(scrollContainer);
            var vBoxContainer = new BoxContainer
            {
                Orientation = LayoutOrientation.Vertical
            };

            scrollContainer.AddChild(vBoxContainer);

            // Handle top bar displaying type and ToString().
            {
                Control top;
                var     stringified = PrettyPrint.PrintUserFacingWithType(obj, out var typeStringified);
                if (typeStringified != "")
                {
                    //var smallFont = new VectorFont(_resourceCache.GetResource<FontResource>("/Fonts/CALIBRI.TTF"), 10);
                    // Custom ToString() implementation.
                    var headBox = new BoxContainer
                    {
                        Orientation        = LayoutOrientation.Vertical,
                        SeparationOverride = 0
                    };
                    headBox.AddChild(new Label {
                        Text = stringified, ClipText = true
                    });
                    headBox.AddChild(new Label
                    {
                        Text = typeStringified,
                        //    FontOverride = smallFont,
                        FontColorOverride = Color.DarkGray,
                        ClipText          = true
                    });
                    top = headBox;
                }
                else
                {
                    top = new Label {
                        Text = stringified
                    };
                }

                if (_entityManager.TryGetComponent(_entity, out ISpriteComponent? sprite))
                {
                    var hBox = new BoxContainer
                    {
                        Orientation = LayoutOrientation.Horizontal
                    };
                    top.HorizontalExpand = true;
                    hBox.AddChild(top);
                    hBox.AddChild(new SpriteView {
                        Sprite = sprite, OverrideDirection = Direction.South
                    });
                    vBoxContainer.AddChild(hBox);
                }
                else
                {
                    vBoxContainer.AddChild(top);
                }
            }

            _tabs = new TabContainer();
            _tabs.OnTabChanged += _tabsOnTabChanged;
            vBoxContainer.AddChild(_tabs);

            var clientVBox = new BoxContainer
            {
                Orientation        = LayoutOrientation.Vertical,
                SeparationOverride = 0
            };

            _tabs.AddChild(clientVBox);
            _tabs.SetTabTitle(TabClientVars, Loc.GetString("view-variable-instance-entity-client-variables-tab-title"));

            var first = true;

            foreach (var group in LocalPropertyList(obj, ViewVariablesManager, _robustSerializer))
            {
                ViewVariablesTraitMembers.CreateMemberGroupHeader(
                    ref first,
                    TypeAbbreviation.Abbreviate(group.Key),
                    clientVBox);

                foreach (var control in group)
                {
                    clientVBox.AddChild(control);
                }
            }

            _clientComponents = new BoxContainer
            {
                Orientation        = LayoutOrientation.Vertical,
                SeparationOverride = 0
            };
            _tabs.AddChild(_clientComponents);
            _tabs.SetTabTitle(TabClientComponents, Loc.GetString("view-variable-instance-entity-client-components-tab-title"));

            PopulateClientComponents();

            if (!_entity.IsClientSide())
            {
                _serverVariables = new BoxContainer
                {
                    Orientation        = LayoutOrientation.Vertical,
                    SeparationOverride = 0
                };
                _tabs.AddChild(_serverVariables);
                _tabs.SetTabTitle(TabServerVars, Loc.GetString("view-variable-instance-entity-server-variables-tab-title"));

                _serverComponents = new BoxContainer
                {
                    Orientation        = LayoutOrientation.Vertical,
                    SeparationOverride = 0
                };
                _tabs.AddChild(_serverComponents);
                _tabs.SetTabTitle(TabServerComponents, Loc.GetString("view-variable-instance-entity-server-components-tab-title"));

                PopulateServerComponents(false);
            }
        }
        public override void Initialize(SS14Window window, object obj)
        {
            _entity = (IEntity)obj;

            var type = obj.GetType();

            var scrollContainer = new ScrollContainer();

            //scrollContainer.SetAnchorPreset(Control.LayoutPreset.Wide, true);
            window.Contents.AddChild(scrollContainer);
            var vBoxContainer = new VBoxContainer
            {
                SizeFlagsHorizontal = Control.SizeFlags.FillExpand,
                SizeFlagsVertical   = Control.SizeFlags.FillExpand,
            };

            scrollContainer.AddChild(vBoxContainer);

            // Handle top bar displaying type and ToString().
            {
                Control top;
                var     stringified = PrettyPrint.PrintUserFacingWithType(obj, out var typeStringified);
                if (typeStringified != "")
                {
                    //var smallFont = new VectorFont(_resourceCache.GetResource<FontResource>("/Fonts/CALIBRI.TTF"), 10);
                    // Custom ToString() implementation.
                    var headBox = new VBoxContainer {
                        SeparationOverride = 0
                    };
                    headBox.AddChild(new Label {
                        Text = stringified, ClipText = true
                    });
                    headBox.AddChild(new Label
                    {
                        Text = typeStringified,
                        //    FontOverride = smallFont,
                        FontColorOverride = Color.DarkGray,
                        ClipText          = true
                    });
                    top = headBox;
                }
                else
                {
                    top = new Label {
                        Text = stringified
                    };
                }

                if (_entity.TryGetComponent(out ISpriteComponent? sprite))
                {
                    var hBox = new HBoxContainer();
                    top.SizeFlagsHorizontal = Control.SizeFlags.FillExpand;
                    hBox.AddChild(top);
                    hBox.AddChild(new SpriteView {
                        Sprite = sprite
                    });
                    vBoxContainer.AddChild(hBox);
                }
                else
                {
                    vBoxContainer.AddChild(top);
                }
            }

            _tabs = new TabContainer();
            _tabs.OnTabChanged += _tabsOnTabChanged;
            vBoxContainer.AddChild(_tabs);

            var clientVBox = new VBoxContainer {
                SeparationOverride = 0
            };

            _tabs.AddChild(clientVBox);
            _tabs.SetTabTitle(TabClientVars, "Client Variables");

            foreach (var control in LocalPropertyList(obj, ViewVariablesManager, _resourceCache))
            {
                clientVBox.AddChild(control);
            }

            var clientComponents = new VBoxContainer {
                SeparationOverride = 0
            };

            _tabs.AddChild(clientComponents);
            _tabs.SetTabTitle(TabClientComponents, "Client Components");

            // See engine#636 for why the Distinct() call.
            var componentList = _entity.GetAllComponents().OrderBy(c => c.GetType().ToString());

            foreach (var component in componentList)
            {
                var button = new Button {
                    Text = TypeAbbreviation.Abbreviate(component.GetType()), TextAlign = Label.AlignMode.Left
                };
                button.OnPressed += args => { ViewVariablesManager.OpenVV(component); };
                clientComponents.AddChild(button);
            }

            if (!_entity.Uid.IsClientSide())
            {
                _serverVariables = new VBoxContainer {
                    SeparationOverride = 0
                };
                _tabs.AddChild(_serverVariables);
                _tabs.SetTabTitle(TabServerVars, "Server Variables");

                _serverComponents = new VBoxContainer {
                    SeparationOverride = 0
                };
                _tabs.AddChild(_serverComponents);
                _tabs.SetTabTitle(TabServerComponents, "Server Components");
            }
        }
        public override ViewVariablesBlob?DataRequest(ViewVariablesRequest messageRequestMeta)
        {
            if (!(messageRequestMeta is ViewVariablesRequestMembers))
            {
                return(null);
            }

            var dataList = new List <ViewVariablesBlobMembers.MemberData>();
            var blob     = new ViewVariablesBlobMembers
            {
                Members = dataList
            };

            foreach (var property in Session.ObjectType.GetAllProperties())
            {
                var attr = property.GetCustomAttribute <ViewVariablesAttribute>();
                if (attr == null)
                {
                    continue;
                }

                if (!property.IsBasePropertyDefinition())
                {
                    continue;
                }

                dataList.Add(new ViewVariablesBlobMembers.MemberData
                {
                    Editable      = attr.Access == VVAccess.ReadWrite,
                    Name          = property.Name,
                    Type          = property.PropertyType.AssemblyQualifiedName,
                    TypePretty    = TypeAbbreviation.Abbreviate(property.PropertyType),
                    Value         = property.GetValue(Session.Object),
                    PropertyIndex = _members.Count
                });
                _members.Add(property);
            }

            foreach (var field in Session.ObjectType.GetAllFields())
            {
                var attr = field.GetCustomAttribute <ViewVariablesAttribute>();
                if (attr == null)
                {
                    continue;
                }

                dataList.Add(new ViewVariablesBlobMembers.MemberData
                {
                    Editable      = attr.Access == VVAccess.ReadWrite,
                    Name          = field.Name,
                    Type          = field.FieldType.AssemblyQualifiedName,
                    TypePretty    = TypeAbbreviation.Abbreviate(field.FieldType),
                    Value         = field.GetValue(Session.Object),
                    PropertyIndex = _members.Count
                });
                _members.Add(field);
            }

            dataList.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.Ordinal));

            foreach (var data in dataList)
            {
                data.Value = MakeValueNetSafe(data.Value);
            }

            return(blob);
        }
Exemplo n.º 15
0
        public override ViewVariablesBlob?DataRequest(ViewVariablesRequest messageRequestMeta)
        {
            if (!(messageRequestMeta is ViewVariablesRequestMembers))
            {
                return(null);
            }

            var members = new List <(MemberData mData, MemberInfo mInfo)>();

            foreach (var property in Session.ObjectType.GetAllProperties())
            {
                var attr = property.GetCustomAttribute <ViewVariablesAttribute>();
                if (attr == null)
                {
                    continue;
                }

                if (!property.IsBasePropertyDefinition())
                {
                    continue;
                }

                members.Add((new MemberData
                {
                    Editable = attr.Access == VVAccess.ReadWrite,
                    Name = property.Name,
                    Type = property.PropertyType.AssemblyQualifiedName,
                    TypePretty = TypeAbbreviation.Abbreviate(property.PropertyType),
                    Value = property.GetValue(Session.Object),
                    PropertyIndex = _members.Count
                }, property));
                _members.Add(property);
            }

            foreach (var field in Session.ObjectType.GetAllFields())
            {
                var attr = field.GetCustomAttribute <ViewVariablesAttribute>();
                if (attr == null)
                {
                    continue;
                }

                members.Add((new MemberData
                {
                    Editable = attr.Access == VVAccess.ReadWrite,
                    Name = field.Name,
                    Type = field.FieldType.AssemblyQualifiedName,
                    TypePretty = TypeAbbreviation.Abbreviate(field.FieldType),
                    Value = field.GetValue(Session.Object),
                    PropertyIndex = _members.Count
                }, field));

                _members.Add(field);
            }

            foreach (var(mData, _) in members)
            {
                mData.Value = MakeValueNetSafe(mData.Value);
            }

            var dataList = members
                           .OrderBy(p => p.mData.Name)
                           .GroupBy(p => p.mInfo.DeclaringType !)
                           .OrderByDescending(g => g.Key, TypeHelpers.TypeInheritanceComparer)
                           .Select(g =>
                                   (
                                       TypeAbbreviation.Abbreviate(g.Key),
                                       g.Select(d => d.mData).ToList()
                                   ))
                           .ToList();

            return(new ViewVariablesBlobMembers
            {
                MemberGroups = dataList
            });
        }