Welcome
Ladies and Gents:

These forums are now closed and registration disabled.

Please join us at our new forum on Proboards. Our hope is that these new forums are more stable, provide more and better features, and allow continuation of the project forums in a safer, more secure, long term environment.

me3explorer.proboards.com

--The ME3Explorer Team

Property Reader and Property Grid

Coder-centric area for programming advice and questions.

Property Reader and Property Grid

Postby Fog.Gene » 21 Feb 2014, 13:40

Disclaimer: I tried to explain the best I can, but this might get a bit dense anyways. You have been warned.

I'm trying to recreate the code that you use in PCCEditor2.0 to view my XCOM save properties (only the tree and propertygrid stuff). I'd like this code to also work nice with the Serialization in C# code that you posted.

Description: I got pretty much all the serialization code in place for my XCOM data. In the case of object lists and properties, when the savegame is loaded to memory I initialize the serializing classes and sequentially read them. The reference to each object class is then passed onto a custom treenode and added to the TreeView control. When the user clicks on an object in the treeview, the serialized data (class ref) is reflected in the PropertyGrid control. This way the users can edit the class data directly through the property grid and I just have to repack it when they hit "Save File" or whatever (not implemented yet).

This is a screenshot of the UI that gives an idea of what I just said above. Sorry about the size, you may have to scroll right to see all of it (or if you are WV: sorry about the size, you may have to zoom-in the image so it doesn't look too small on your big ass monitor :P)

Spoiler:
Image


In the screenshot above I highlighted a simple BoolProperty to keep things simple. Right now in my serializing object-class, the one currently reflected in prop. grid, I have a (custom) collection of generic properties (yet another class that uses the serializing code). Most properties have a common set of infos (name, string_type, data_size, prop_index) and then their unique data. Something like this:

public class xProperty
{
public string name { get; set; } // property name
//public int unk0; // 0x0
public string type { get; set; } // property type
//public int unk1; // 0x0
public int size; // 0x9 in BoolProperty
public int index { get; set; } // only set in StructProperty
public byte[] data { get; set; } // dynamic prop data
}


The prop data is variable depending on the property. For a BoolProperty like the one above it is very simple, 8 bytes of zeroed data (not shown) and a single 01/00 for true/false respectively. IntProps are an int32, float a floating precision point... and so on and so forth. For StructProps and ArrayProps shit hits the fan and we can have from int[] or string[] to xProperty[][] (yes that's a two-dimensional array).

The Problem: From what I've seen in the PCCEditor2.0 code, to display this variety of property data in prop. grid,as something else than an array of bytes, I might have to code:

- a struct for each of the complex property variants (pretty much all of them except for the ones that hold a single value: BoolProp, IntProp, etc.)
- a CustomProperty class that holds a generic object with the struct corresponding to its property type?
- a CustomPropertyCollection class (with its own ICustomTypeDescriptor), then have this collection in my serializing object class?
- a CustomProperty reader that takes an xProperty as argument, to decode the byte[] data into the appropriate struct object (this is quite confusing in your code, since you pass PCC export data to the custom prop, and I don't know crap about Unreal Engine exports stuff).
- a classy Smith and Wesson revolver* (I knew a guy that named his two sons after this, don't ask...)

So what I'd eventually pass to my serializing object class, would be not a xProperty[], but rather the final CustomPropertyCollection. Does this make any sense? How did you come up with all this stuff?

* Optional

In PCC Editor there is only a handful of structs, but I think I'd need several more since the savegame properties in XCOM are quite distinct from each other (nothing so pleasant as seeing an ArrayProp data hold an array of strings, instead of other properties).

I'm thinking that I should perhaps mimic a bit more PCC Editor structure. I mean, try to recreate an export with all the stuff that is in the savegame, if that is even possible. I have a bunch of NameLists and ObjectLists (each object in each list with its own properties), what am I missing? Somebody suggested the IndexTables tables I have might be packages, but I have decoded a few of them and those are only a header followed by a bunch of [int, bool] structs). Then there is also savegame progress data, not sure how it would tie in with the export stuff.

All in all, I'm not sure this is "just a savegame" anymore. It looks like a damn UPK file, but only with the exports data (or part of it) glued to a bunch savegame progress data.

Thoughts?

[I have to commit the new code to the SVN, so if you're thinking about opening the tool let me know and I'll upload the new stuff. The previous version was just the code without the UI stuff] It's up to date now.


Should I use the S&W yet?
Regere: Let the world know of its sovereign. I shall be the rule by which all things are measured.
Polyhistor: Then I am to be the slave, for all things shall be my master.
Fog.Gene
Emeritus
 
Posts: 259
Joined: 20 Feb 2013, 05:09
Has thanked: 119 time
Have thanks: 65 time

Re: Property Reader and Property Grid

Postby WarrantyVoider » 21 Feb 2014, 13:58

good progress! well, nested property grid is always a good goal, but I never got it working right, instead I wrote interpreter, that trial&errors through the arrays/structs and is guessing, if it contains properties or not. btw, savegames are usually complex :P

greetz WV
always backup your files!
mess with the best or die like the rest!
"I tried everything!" - "mkay, please list that..." ; please dont pm me for help, we have a help section
User avatar
WarrantyVoider
Emeritus
 
Posts: 2270
Joined: 22 Aug 2012, 11:33
Has thanked: 480 time
Have thanks: 626 time

Re: Property Reader and Property Grid

Postby Fog.Gene » 21 Feb 2014, 14:54

I'm looking at the Interpreter2.cs code right now, maybe there's something that can help me there.

For completeness, below is my current PropertyReader code (long). Some of the methods are extensions of your Serializer overrides. I call the reader from the serializing class and pass the container directly. The idea is that, instead, I could perhaps call an intermediary CustomPropertyLoader class that calls this method below, and then iterates through the properties and returns a nested grid.

From what I can see this is no different from what you have in PropGrid.cs, so there's hope. I'll let you know if I make any progress.

Edit: heh, I just realized that I've been moving so much code out of that switch that I can reduce it to only three cases. I'll put it in the to-do list :P

Spoiler:
public static xPropertyCollection PropertyLoader(SerializingContainer container, xPropertyCollection _props)
{
xPropertyCollection props;
if (_props == null)
props = new xPropertyCollection();
else
props = _props;
xProperty p;
int pass = 0;
int absize;
while (true)
{
if (props.Count == pass)
{
p = new xProperty();
}
else
{
p = props[pass];
}
pass += 1; // will cause a mismatch next round if unknown prop.

p.name = container > p.name;
container.Seek(4, SeekOrigin.Current); //0x0
if (p.name != "None\0")
{
p.type = container > p.type;
container.Seek(4, SeekOrigin.Current); //0x0
p.size = container > p.size;
p.index = container > p.index;
}
else
p.type = "None";

switch (p.type)
{
case "ArrayProperty\0":
if (p.data == null)
p.data = new byte[p.size];
p.data = container < p.data;
props.Add(p);
break;

case "BoolProperty\0":
if (p.data == null)
p.data = new byte[1];
p.data = container < p.data;
props.Add(p);
break;

case "ByteProperty\0":
if (p.size != 1)
{
absize = p.size;
absize = 4 + (container + absize); // bytepropname
absize += 4; // 0x0
if (p.data == null)
p.data = new byte[absize];
p.data = container < p.data;
}
props.Add(p);
break;

case "FloatProperty\0":
if (p.data == null)
p.data = new byte[p.size];
p.data = container < p.data;
props.Add(p);
break;

case "IntProperty\0":
if (p.data == null)
p.data = new byte[p.size];
p.data = container < p.data;
props.Add(p);
break;

case "NameProperty\0":
if (p.data == null)
p.data = new byte[p.size];
p.data = container < p.data;
props.Add(p);
break;

case "ObjectProperty\0":
if (p.data == null)
p.data = new byte[p.size];
p.data = container < p.data;
props.Add(p);
break;

case "StrProperty\0":
if (p.data == null)
p.data = new byte[p.size];
p.data = container < p.data;
props.Add(p);
break;

case "StructProperty\0":
absize = p.size;
absize = 4 + (container + absize); // structpropname
absize += 4; // 0x0
if (p.data == null)
p.data = new byte[absize];
p.data = container < p.data;
props.Add(p);
break;

case "None":
props.Add(p);
return props;
}
}
}
Regere: Let the world know of its sovereign. I shall be the rule by which all things are measured.
Polyhistor: Then I am to be the slave, for all things shall be my master.
Fog.Gene
Emeritus
 
Posts: 259
Joined: 20 Feb 2013, 05:09
Has thanked: 119 time
Have thanks: 65 time

Re: Property Reader and Property Grid

Postby Fog.Gene » 22 Feb 2014, 22:17

OK I checked the interpreter and I see that's how you build the tree. It's pretty neat, but that part I had already working on my own (although I might revisit your code later on).

The part that I am going crazy about is how you handle the CustomProperty and PropGrid (CustomProperty collection) code in PropGrid.cs. An example:

- In your code when I browse the treenode that links to the PropGrid, I see a bunch of custom property objects nicely cast to their correct type

Spoiler:
Image


- In my code I have also implemented a CustomProperty class with its own descriptor (and a custom collection too, but not using it yet). Before filling out a whole collection, first I check if a single property is correctly displayed. This is what happens when I reflect it in the PropertyGrid control

Spoiler:
Image


Obviously not right. I don't even get why ReadOnly and Visible are showing up on the grid in the first place, I don't even pass them as attributes when creating the custom property. But I don't know what I'm doing wrong. Any chance you might have time for a quick Skype tut on this at some point? UI stuff is really a pain to code and it is aggravating, because getting this right is the only thing before writing the repacking methods.

Edit: These guys are more or less asking the same stuff I am. How to have a property grid display dynamic types loaded a runtime:
http://stackoverflow.com/questions/313822/how-to-modify-propertygrid-at-runtime-add-remove-property-and-dynamic-types-enu
http://stackoverflow.com/questions/1884851/propertygrid-and-dynamic-types-of-objects
Regere: Let the world know of its sovereign. I shall be the rule by which all things are measured.
Polyhistor: Then I am to be the slave, for all things shall be my master.
Fog.Gene
Emeritus
 
Posts: 259
Joined: 20 Feb 2013, 05:09
Has thanked: 119 time
Have thanks: 65 time

Re: Property Reader and Property Grid

Postby WarrantyVoider » 22 Feb 2014, 22:42

check this and propgrid.cs in unreal folder, also maybe its usage, its a bit complex to explain

http://www.codeproject.com/Articles/4448/Customized-display-of-collection-data-in-a-Propert

greetz WV
always backup your files!
mess with the best or die like the rest!
"I tried everything!" - "mkay, please list that..." ; please dont pm me for help, we have a help section
User avatar
WarrantyVoider
Emeritus
 
Posts: 2270
Joined: 22 Aug 2012, 11:33
Has thanked: 480 time
Have thanks: 626 time

Re: Property Reader and Property Grid

Postby Fog.Gene » 22 Feb 2014, 22:59

Oh yeah I already went through that one. That's how I implement my generic property collections.

I'm not doing a very good job at explaining myself today, it seems. I'm trying to put together a new reader to fill a runtime-decided dynamic collection. Will get back to you when I've done that, maybe it'll make more sense then.
Regere: Let the world know of its sovereign. I shall be the rule by which all things are measured.
Polyhistor: Then I am to be the slave, for all things shall be my master.
Fog.Gene
Emeritus
 
Posts: 259
Joined: 20 Feb 2013, 05:09
Has thanked: 119 time
Have thanks: 65 time


Return to Coders' Help

Who is online

Users browsing this forum: No registered users and 1 guest

suspicion-preferred