theRAPTLab / gsgo

GEM-STEP Foundation repo migrated from GitLab June 2023
1 stars 1 forks source link

Add symbol data support for complex gvar types #799

Open benloh opened 8 months ago

benloh commented 8 months ago

See #783 for original issue.

Continuation of GEM-STEP text styling.

As we discussed last week, Joshua is wanting to add text alignment and justification to character text labels. This is currently implemented a series of flags that set alignment (top, middle, bottom; left, center, right) and justification for multiple lines of text (left, center, right). This is working well.

The challenge is the wizard: we need to provide a way for the Graphing feature property to select options for the alignment and justication properties, e.g. featProp character.Graphing.textAlign setToOption 'left', where setToOption will show a selection menu with predefined option types. The idea was to use a GVar Number option setting to define values for each setting, e.g. left as 1, center as 2, and middle as 4, etc. SlotEditor_Block.jsx components would look up symbol bundles as a way to populate selection menus with those options.

The problem with this approach is that symbol bundles (at least as they are currently defined) are static symbols. To better illustrate the issue: We define a textAlign featProp in the Graphing feature, and then also define 3 options for the values:

// feat-graphing.ts
decorate(agent) {
  ...
  let prop = new SM_Number();
  prop.addOption('top', FLAGS.ALIGNMENT.TOP);
  prop.addOption('middle', FLAGS.ALIGNMENT.MIDDLE);
  prop.addOption('bottom', FLAGS.ALIGNMENT.BOTTOM);
  ..
  this.featAddProp(agent, 'textAlign', prop);

Using code, we can then use a line like this within a character script:

featProp character.Graphing.textAlign setToOption 'right'

This works well for the code view. But things vall apart in the wizard view. In SlotEditor_Block.jsx we need to retrieve the list of available options. We can use the symbol bundles to retrieve the list of static methods available to the textAlign featProp, and args, info, and name, e.g.

// SM_Bunde
...
symbols:
> features:
  > Graphing:
    > props:
      > textAlign:
        > methods: {
            ...
            addOption: {
              args: ['label:string', 'value:number'],
              info: "Defines a new option...",
              name: "addOption"
            }
            ...
        }

...but the dynamically generated options defined in feat-graphing.ts (e.g. prop.addOption('top', FLAGS.ALIGNMENT.TOP) are not visible to the symbol bundle.

In trying to figure out what to do, I though I could try to dynamically read the options in the static class-sm-number.Symbolize definition, or even add a options parameter to the symbol bundle, but I believe we can't call methods to retrieve those values.

Sri adds: "it does sound like you need to add additional symbol data across the entire system because options turn every gvar into a complex type"

daveseah commented 7 months ago

I think your instinct to add additional symbol data is the right one. All the existing SymbolData in the system now is there to cover the needs that emerged. This new hack of options onto GVar creates the new need.

Aside: The way options are hacked into the system adds an option list (this could have been added to the base SM_Class I think unless there are special cases for runtime checks)...can add a getOptions() method to that too but this is only good for runtime, not script editing time.

The architecture of the compiler is based on lines of statements so custom code can be run for each keyword. Since I'm guessing that your script looks like this (next time, include an example script so we don't need to hunt for it)

addProp foo number 0
prop foo.addOption 'label' 100

The addProp keyword adds symbol data. The prop keyword does not because it generally doesn't need to. Your new functionality would work better with a separate addPropOption keyword that might look like this:

addPropOption foo 'label' 100

So you can insert this symbol data into the symbol bundles for that prop. Compare addProp and prop keyword modules for an example of the difference. There isn't currently a propOptions symboltype but it could certainly be inserted with some careful thought. Once the propOptions is defined, you should be able to modify SymbolHelper by adding a getPropOptions and getFeaturePropOptions method...maybe. The symbol help code really depends on having detectable patterns in the keyword, and having unique keywords that can do different argument processing helps in that regard.

For FeatureProps, there's a set of mirroring functions that add symbol data to the Feature Symbol Bundles, but the operation is probably similar.

OPINION TIME!

This code hacks across so many key systems (render, simulation agents, script-compiler, script-editor, blueprint-symbols) that it's like "the tail wagging the dog." If it was just ONE of those systems it would be fine as a hack, but because it touches so many thing this is really a system engineering feature for implementing a styling flexibility for a specific case. Generally this is not good engineering practice but I get that ultimately our end goal is to support the core research needs. It might be expensive to fix in the future, but capturing the need in the codebase now is good for compiling the visual feature revamp tech plan.