-
Notifications
You must be signed in to change notification settings - Fork 43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Investigate depreciating <basic name ="Flags"> #3
Comments
@neomonkeus @ttl269 I think I've arrived at this conclusion as well. The values for the Flags end up being hardcoded in NifSkope and then do not get updated when nif.xml is updated. However I think the proposed formatting isn't sufficient. A more complicated example is:
It would be nice if the format would be able to reflect that certain bits are grouped together and are exclusive options within that bit range. If this can't be done strictly in XML for whatever reason, the text inside the current tags could at least be in a more easily parsable format. |
@jonwd7 @neomonkeus Proposal of <bitflags name="AlphaPropertyFlags" storage="ushort">
Transparency flags.
<option value="0" name="Enable Blending">alpha blending enable</option>
<bitgroup value="1 4" name="Source Blend Mode">source blend mode
<option value="0000" name="One">GL_ONE</option>
<option value="0001" name="Zero">GL_ZERO</option>
<option value="0010" name="Src Color">GL_SRC_COLOR</option>
<option value="0011" name="Inv Src Color">GL_ONE_MINUS_SRC_COLOR</option>
<option value="0100" name="Dst Color">GL_DST_COLOR</option>
<option value="0101" name="Inv Dst Color">GL_ONE_MINUS_DST_COLOR</option>
<option value="0110" name="Src Alpha">GL_SRC_ALPHA</option>
<option value="0111" name="Inv Src Alpha">GL_ONE_MINUS_SRC_ALPHA</option>
<option value="1000" name="Dst Alpha">GL_DST_ALPHA</option>
<option value="1001" name="Inv Dst Alpha">GL_ONE_MINUS_DST_ALPHA</option>
<option value="1010" name="Src Alpha Saturate">GL_SRC_ALPHA_SATURATE</option>
</bitgroup>
<bitgroup value="5 8" name="Destination Blend Mode">destination blend mode
<option value="0000" name="One">GL_ONE</option>
<option value="0001" name="Zero">GL_ZERO</option>
<option value="0010" name="Src Color">GL_SRC_COLOR</option>
<option value="0011" name="Inv Src Color">GL_ONE_MINUS_SRC_COLOR</option>
<option value="0100" name="Dst Color">GL_DST_COLOR</option>
<option value="0101" name="Inv Dst Color">GL_ONE_MINUS_DST_COLOR</option>
<option value="0110" name="Src Alpha">GL_SRC_ALPHA</option>
<option value="0111" name="Inv Src Alpha">GL_ONE_MINUS_SRC_ALPHA</option>
<option value="1000" name="Dst Alpha">GL_DST_ALPHA</option>
<option value="1001" name="Inv Dst Alpha">GL_ONE_MINUS_DST_ALPHA</option>
<option value="1010" name="Src Alpha Saturate">GL_SRC_ALPHA_SATURATE</option>
</bitgroup>
<option value="9" name="Enable Testing">alpha test enable</option>
<bitgroup value="10 12" name="Destination Blend Mode">destination blend mode
<option value="000" name="Always">GL_ALWAYS</option>
<option value="001" name="Less">GL_LESS</option>
<option value="010" name="Equal">GL_EQUAL</option>
<option value="011" name="Less or Equal">GL_LEQUAL</option>
<option value="100" name="Greater">GL_GREATER</option>
<option value="101" name="Not Equal">GL_NOTEQUAL</option>
<option value="110" name="Greater or Equal">GL_GEQUAL</option>
<option value="111" name="Never">GL_NEVER</option>
</bitgroup>
<option value="13" name="No Sorter">no sorter</option>
<option value="15" name="Editor Alpha Ref Test">editor alpha ref test - function unknown</option>
</bitflags> Introduced new xml element <bitgroup bitstart="1" bitend="4" name="XXX"> Which maybe better for parsing the values defining the range of bits. It would be great if Nifskope could parse this enhanced <bitflags name="SomeFlags" storage="ushort">
Flags flags flags.
<option value="0" name="Enable XXX">decription of XXX enabled</option>
<option value="2" name="Enable YYY">decription of YYY enabled</option>
<bitgroup value="3 6" name="ZZZ Mode">description of ZZZ mode
<option value="0000" name="Mode 0">description of mode 0</option>
<option value="0001" name="Mode 1">description of mode 1</option>
<option value="0010" name="Unknown">unknown (found in aaa.nif file)</option>
<option value="1000" name="Mode A">description of mode A</option>
<option value="1001" name="Mode B">GL_ONE_MINUS_DST_ALPHA</option>
</bitgroup>
<option value="7" name="Enable God">enable God mode.</option>
<bitgroup value="8 9" name="God Mode">god modes description
<option value="00" name="God One">GOD_1</option>
<option value="01" name="God Two">GOD_2</option>
<option value="10" name="God Three">GOD_3</option>
<option value="11" name="God Zeus">GOD_4</option>
</bitgroup>
<option value="13" name="Enable Debug">show debug information</option>
<option value="14" name="Enable Collision Geometry in Exterior Cells">draw collision geometry</option>
<option value="15" name="Enable Wireframe">enable wireframe mode.</option>
</bitflags> would be good if Nifskope could render:
Having universal element for any Flags would make possible to get rid of very unconfortable ticking/unticking of Also editing of |
@neomonkeus @ttl269 Just some initial thoughts, haven't thought about it too much yet: <bitgroup bitstart="1" bitend="4" name="XXX"> I think that "start" and "width" would be better: <bitgroup start="5" width="4" name="Destination Blend Mode"> You're saying explicitly that the bit width is 4 that way. Instead of the potentially confusing start=5, end=8 ... You don't really to list the end value. In this case it's immediately followed by an option with value=9. So it's a little easier to tell you've added up the bitfield columns correctly since start 5 + width 4 = 9 (the next available value). Secondly, is having the bitgroup values in binary necessary? Could just be: <bitgroup start="5" width="4" name="Destination Blend Mode">destination blend mode
<option value="0" name="One">GL_ONE</option>
<option value="1" name="Zero">GL_ZERO</option>
<option value="2" name="Src Color">GL_SRC_COLOR</option>
<option value="3" name="Inv Src Color">GL_ONE_MINUS_SRC_COLOR</option>
<option value="4" name="Dst Color">GL_DST_COLOR</option>
<option value="5" name="Inv Dst Color">GL_ONE_MINUS_DST_COLOR</option>
<option value="6" name="Src Alpha">GL_SRC_ALPHA</option>
<option value="7" name="Inv Src Alpha">GL_ONE_MINUS_SRC_ALPHA</option>
<option value="8" name="Dst Alpha">GL_DST_ALPHA</option>
<option value="9" name="Inv Dst Alpha">GL_ONE_MINUS_DST_ALPHA</option>
<option value="10" name="Src Alpha Saturate">GL_SRC_ALPHA_SATURATE</option>
</bitgroup> ...keeps the "value" field in line with other usages which are (mostly) decimal. Though this brings up a third issue. Should the "size" of the bitgroup also be defined or should the options just be counted by the parser? For example there are only 11 options for "Destination Blend Mode" even though there are 16 slots available. So, then it could also be: <bitgroup start="5" width="4" size="11" name="Destination Blend Mode"> Though maybe a more specific word can be used other than "size". "Count" may be a better term. |
@jonwd7
|
@ttl269, @jonwd7 - good to see this has been given some serious consideration. The main issue which I think we still that needs to be address is the addressing of bit locations. <bitflags name="SomeFlags" storage="ushort">
Flags flags flags.
<option value="0" name="Enable XXX">decription of XXX enabled</option>
//no value="1"
<option value="2" name="Enable YYY">decription of YYY enabled</option>
<bitgroup start="5" width="4" name="Destination Blend Mode">destination blend mode
<offset offset="0" name="One">GL_ONE</option>
<offset offset="1" name="Zero">GL_ZERO</option>
<offset offset="2" name="Src Color">GL_SRC_COLOR</option>
</bitgroup> One thing I have noticed is that the ConsistencyType has binary option values. I am not sure internally how these are converted but this has confused me previously. <enum name="ConsistencyType" storage="ushort">
Used by NiGeometryData to control the volatility of the mesh. While they appear to be flags they behave as an enum.
<option value="0x0000" name="CT_MUTABLE">Mutable Mesh</option>
<option value="0x4000" name="CT_STATIC">Static Mesh</option>
<option value="0x8000" name="CT_VOLATILE">Volatile Mesh</option>
</enum> The other concern is there any flags which are conditional on the state of other. <bitflags name="SomeFlags" storage="ushort">
Flags flags flags.
<option value="0" name="Enable XXX">decription of XXX enabled</option>
<option value="2" name="Enable Collision">Enables Collision system</option>
<bitgroup start="5" width="4" name="Collision System" cond="Enable Collision == 1">destination blend mode
<offset value="0" name="Basic">Basic</option>
<offset value="1" name="Spherical">Spherical</option>
<offset value="2" name="Full">Full Havok</option>
</bitgroup> |
@jonwd7 @neomonkeus Good idea to use name The I think that conditionals for |
Yeah, they were mainly some ideas I threw out as possible things to consider as part of the overall context as we were not using a totally real example. it would be still good to consider these things. Parser can always be updated with new features, but when updating the domain description, its important to think about these situations which even if they never occur, its good to consider at least the possibility. Not sure about offset for the 0 & 1 but that can be changed too. There are a lot of general name choices I can suggest better name for. Still focusing on the current situation, I would suggest if we were going all out, then I would propose the following: <bitflags name="SomeFlags" storage="ushort">
Flags flags flags.
<bit offset="0" name="Enable XXX">decription of XXX enabled</option>
<bit offset="2" name="Enable Collision">Enables Collision system</option>
<bitgroup start="3" width="4" name="Collision System Type" cond="Enable Collision == 1">destination blend mode
<bit offset="0" name="Basic">Basic</option>
<bit offset="1" name="Spherical">Spherical</option>
<bit offset="2" name="Full">Full Havok</option>
</bitgroup> The reason I did not propose this is it would have much larger impact on all parsers. That said, as I always say, the format description should is care if there is a large changes, just ease of xml usability. Speaking of which @jonwd7, must sit down and talk about removing NifSkope specific data from the format. |
For niftools#3, niftools#76 Replaces all Flags types with real enums (where there were only two options) or a new bitfield type. Bitfield mimics the bitfield syntax of C structs (Compounds), but also acts like Enum/Bitflags with the `storage` attribute in that the entire structure can simply be aliased to a basic type like `ushort`. The `type` on each Bitfield member does **NOT denote size**. Each member only takes up the bits that are defined by `width` and `pos`. The `type` information is for casting for getters and setters. That means for C structs, code generation would not use the type on each member, but the storage type instead.
I detail the removal of 'Flags' in #76, so read up on it there. But I will at least elaborate on the decided upon layout for the new tag: <bitfield name="AlphaFlags" storage="ushort">
Flags for NiAlphaProperty
<member width="1" pos="0" mask="0x0001" name="Alpha Blend" type="bool" />
<member width="4" pos="1" mask="0x001E" name="Source Blend Mode" type="AlphaFunction" default="SRC_ALPHA" />
<member width="4" pos="5" mask="0x01E0" name="Destination Blend Mode" type="AlphaFunction" default="INV_SRC_ALPHA" />
<member width="1" pos="9" mask="0x0200" name="Alpha Test" type="bool" default="1" />
<member width="3" pos="10" mask="0x1C00" name="Test Func" type="TestFunction" default="TEST_GREATER" />
<member width="1" pos="13" mask="0x2000" name="No Sorter" type="bool" />
</bitfield> The attributes:
For C++, this would look like the following struct AlphaFlags
{
// Cutting out AlphaFunction and TestFunction enums...
using ushort = unsigned short;
union {
ushort value;
struct {
ushort alphaBlend : 1;
ushort sourceBlendMode : 4;
ushort destinationBlendMode : 4;
ushort alphaTest : 1;
ushort testFunc : 3;
ushort noSorter : 1;
} bits;
};
// OR just simply
// ushort value;
ushort GetValue() const
{
return value;
}
// If using `bits` struct, mask/pos are actually unneeded
bool GetAlphaBlend() const
{
// OR return (bool)(value & 0x0001);
return (bool)bits.alphaBlend;
}
AlphaFunction GetSourceBlendMode() const
{
// OR return (AlphaFunction)((value & 0x001E) >> 1);
return (AlphaFunction)bits.sourceBlendMode;
}
AlphaFunction GetDestinationBlendMode() const
{
// OR return (AlphaFunction)((value & 0x01E0) >> 5);
return (AlphaFunction)bits.destinationBlendMode;
}
bool GetAlphaTest() const
{
// OR return (bool)((value & 0x0200) >> 9);
return (bool)bits.alphaTest;
}
TestFunction GetTestFunc() const
{
// OR return (TestFunction)((value & 0x1C00) >> 10);
return (TestFunction)bits.testFunc;
}
bool GetNoSorter() const
{
// OR return (bool)((value & 0x2000) >> 13);
return (bool)bits.noSorter;
}
// Not all setters shown for example
void SetAlphaBlend(bool val)
{
// or value = (value & ~0x0001) | (ushort)val;
bits.alphaBlend = (ushort)val;
}
void SetSourceBlendMode(AlphaFunction val)
{
// or value = (value & ~0x001E) | ((ushort)val << 1);
bits.sourceBlendMode = (ushort)val;
}
void SetDestinationBlendMode(AlphaFunction val)
{
// or value = (value & ~0x01E0) | ((ushort)val << 5);
bits.destinationBlendMode = (ushort)val;
}
}; Other languages could get by with just storing the single ushort value and having the Get/Set functions with the mask/pos. |
The basic type Flags just a wraps a number value but offers no value. The number in most cases is still presented to the user as is, and the options, usually documented in the nif.xml is unlikely to read by a user .
There are two structures which we currently use which provide what the "Flags" real functionality should.
This could be reworked as
This example does highlight a potential redesign in implementation. We do not have any way to to allow certain flags to be mutually exclusive, only be able to select subset of flags, ie only one Cycle Type selectable.
Additionally most tools have to add additional logic so that the value is presented in a meaningful manner to the user. eg. NifSkope know to break Col Filter into 3 options,
*LINK property,
*Collision,
*Scaled
A partial solution, but using bitflags a generic implementation would just pull all the information directly. Less code to maintain if its generic.
The only downside is that it more bitflag types will need to be created and depending on the number of available options this will increase the size of the nif.xml. If the options can be conditional then some could be reused, like Col Filter & Skyrim Col Filter, but less readable.
The text was updated successfully, but these errors were encountered: