OpenNaja / cobra-tools

A suite of GUI tools for extracting and modifying OVL and OVS archives, as well as editing the associated in-house file formats. Also includes a model plugin for Blender. For downloads, guides, and FAQs visit:
https://opennaja.github.io/cobra-tools/
GNU General Public License v3.0
98 stars 28 forks source link

Implementation of multiple args and templates for a field. #328

Closed Candoran2 closed 1 year ago

Candoran2 commented 1 year ago

In python objects and classes are both objects. However, this is not the case in all languages. I would therefore like to restrict template to be limited to types (including templates itself). However, in certain cases template is used as a way to pass a second object. In order to allow for this, I have changed arg (and template, though it wasn't strictly necessary) to allow for the passing of multiple objects.

This is accomplished through attributes starting at arg1 up to arg<n>, on the field. A type that uses multiple args must have args="<n>" denoted on the type, where <n> is the number of args that it uses. In the generated code, these are passed as a tuple in the same place as the arg parameter. It is also still stored as arg, but it is also accessible through the property arg_<i>. This is equivalent to arg[i - 1]. Template is treated the same way.

Example: type:

<struct name="DataStreamData" args="2" module="NiMesh" since="V20_5_0_0">
    <field name="Data" type="byte" binary="true" length="#ARG1#">The data stream as binary (fallback if interpretation with template is not implemented).</field>
</struct>

used in field:

<field name="Data" type="DataStreamData" arg1="Num Bytes" arg2="Component Formats" />

The choice to (re)use the existing arg parameter on the types is to keep the function signatures and field definitions consistent across all types, rather than having to somehow check how many args and templates are passed. The choice to allow accessing the elements of arg through properties is to make the code generation easier - otherwise it would require either implementation of square brackets in the Expression class, or modification of the name_attribute function to make it less universally applicable. As a side-effect, it also makes it very clear upon reading the generated class whether they use multiple args or not.

As it is, I have not yet changed types other than the one in nif.xml to make use of these multiple args. I thought it useful to first check that there were no unforeseen changes beforehand.

Other changes

  1. Fixed RaggedArray.validate_instance and added append and extend methods for it (the latter two are not yet tested).
  2. Removed math.prod use. The README promises compatibility with python 3.7. Since 3.7 does not contain math.prod, I created the same function on the Array class.
HENDRIX-ZT2 commented 1 year ago

Could we not store arg and make the expressions use arg[0] if they get #ARG#?

Candoran2 commented 1 year ago

Could we not store arg and make the expressions use arg[0] if they get #ARG#?

You mean always store arg as a tuple?

HENDRIX-ZT2 commented 1 year ago

You mean always store arg as a tuple?

Yeah

Candoran2 commented 1 year ago

It's possible, I didn't think of that option. Three reasons why not to do it would be:

Of course that's at the detriment of consistency in how we treat arg (single number vs consistently a tuple), so as usual there's a trade-off.