From 769924a9b318b3ab50b8df69e100db3b59eefb69 Mon Sep 17 00:00:00 2001 From: Gary Oberbrunner Date: Wed, 28 Aug 2024 17:09:40 -0400 Subject: [PATCH] Add all props to sets (NOT FINISHED) & generate props_by_set.hxx Signed-off-by: Gary Oberbrunner --- include/ofx-props.yml | 150 +++++++++++++++++++++++++++++------------- scripts/gen-props.py | 108 +++++++++++++++++++++++++----- 2 files changed, 193 insertions(+), 65 deletions(-) diff --git a/include/ofx-props.yml b/include/ofx-props.yml index 50797b57..34b06b9d 100644 --- a/include/ofx-props.yml +++ b/include/ofx-props.yml @@ -6,6 +6,8 @@ # property. propertySets: + General: + - kOfxPropTime ImageEffectHost: - kOfxPropAPIVersion - kOfxPropType @@ -157,6 +159,8 @@ propertySets: - kOfxPropLongLabel - kOfxImageEffectPropSupportedComponents - kOfxImageEffectPropTemporalClipAccess + - kOfxImageClipPropColourspace + - kOfxImageClipPropPreferredColourspaces - kOfxImageClipPropOptional - kOfxImageClipPropFieldExtraction - kOfxImageClipPropIsMask @@ -193,60 +197,59 @@ propertySets: ParameterSet: - kOfxPropParamSetNeedsSyncing - ParamsCommonDefs: - - &ParamsCommon - - kOfxPropType - - kOfxPropName - - kOfxPropLabel - - kOfxPropShortLabel - - kOfxPropLongLabel - - kOfxParamPropType - - kOfxParamPropSecret - - kOfxParamPropHint - - kOfxParamPropScriptName - - kOfxParamPropParent - - kOfxParamPropEnabled - - kOfxParamPropDataPtr - - kOfxPropIcon - - &PropertiesAllButGroupPage - - kOfxParamPropInteractV1 - - kOfxParamPropInteractSize - - kOfxParamPropInteractSizeAspect - - kOfxParamPropInteractMinimumSize - - kOfxParamPropInteractPreferedSize - - kOfxParamPropHasHostOverlayHandle - - kOfxParamPropUseHostOverlayHandle - - &ParamsValue - - kOfxParamPropDefault - - kOfxParamPropAnimates - - kOfxParamPropIsAnimating - - kOfxParamPropIsAutoKeying - - kOfxParamPropPersistant - - kOfxParamPropEvaluateOnChange - - kOfxParamPropPluginMayWrite - - kOfxParamPropCacheInvalidation - - kOfxParamPropCanUndo - - &ParamsNumeric - - kOfxParamPropMin - - kOfxParamPropMax - - kOfxParamPropDisplayMin - - kOfxParamPropDisplayMax - - &ParamsDouble - - kOfxParamPropIncrement - - kOfxParamPropDigits + ParamsCommon_DEF: + - kOfxPropType + - kOfxPropName + - kOfxPropLabel + - kOfxPropShortLabel + - kOfxPropLongLabel + - kOfxParamPropType + - kOfxParamPropSecret + - kOfxParamPropHint + - kOfxParamPropScriptName + - kOfxParamPropParent + - kOfxParamPropEnabled + - kOfxParamPropDataPtr + - kOfxPropIcon + ParamsAllButGroupPage_DEF: + - kOfxParamPropInteractV1 + - kOfxParamPropInteractSize + - kOfxParamPropInteractSizeAspect + - kOfxParamPropInteractMinimumSize + - kOfxParamPropInteractPreferedSize + - kOfxParamPropHasHostOverlayHandle + - kOfxParamPropUseHostOverlayHandle + ParamsValue_DEF: + - kOfxParamPropDefault + - kOfxParamPropAnimates + - kOfxParamPropIsAnimating + - kOfxParamPropIsAutoKeying + - kOfxParamPropPersistant + - kOfxParamPropEvaluateOnChange + - kOfxParamPropPluginMayWrite + - kOfxParamPropCacheInvalidation + - kOfxParamPropCanUndo + ParamsNumeric_DEF: + - kOfxParamPropMin + - kOfxParamPropMax + - kOfxParamPropDisplayMin + - kOfxParamPropDisplayMax + ParamsDouble_DEF: + - kOfxParamPropIncrement + - kOfxParamPropDigits ParamsGroup: - kOfxParamPropGroupOpen - - <<* ParamsCommon + - ParamsCommon_REF ParamDouble1D: - kOfxParamPropShowTimeMarker - kOfxParamPropDoubleType - - <<* ParamsCommon - - <<* ParamsAllButGroupPage - - <<* ParamsValue - - <<* ParamsNumeric - - <<* ParamsDouble + - ParamsCommon_REF + - ParamsAllButGroupPage_REF + - ParamsValue_REF + - ParamsNumeric_REF + - ParamsDouble_REF ParamsDouble2D3D: - kOfxParamPropDoubleType @@ -299,6 +302,59 @@ propertySets: - kOfxInteractPropSlaveToParam - kOfxInteractPropSuggestedColour + Misc: + - kOfxImageEffectFrameVarying + - kOfxImageEffectPluginPropOverlayInteractV2 + - kOfxImageEffectPropColourManagementAvailableConfigs + - kOfxImageEffectPropColourManagementConfig + - kOfxImageEffectPropColourManagementStyle + - kOfxImageEffectPropCudaEnabled + - kOfxImageEffectPropCudaRenderSupported + - kOfxImageEffectPropCudaStream + - kOfxImageEffectPropCudaStreamSupported + - kOfxImageEffectPropDisplayColourspace + - kOfxImageEffectPropFieldToRender + - kOfxImageEffectPropFrameStep + - kOfxImageEffectPropInAnalysis + - kOfxImageEffectPropInteractiveRenderStatus + - kOfxImageEffectPropMetalCommandQueue + - kOfxImageEffectPropMetalEnabled + - kOfxImageEffectPropMetalRenderSupported + - kOfxImageEffectPropOCIOConfig + - kOfxImageEffectPropOCIODisplay + - kOfxImageEffectPropOCIOView + - kOfxImageEffectPropOpenCLCommandQueue + - kOfxImageEffectPropOpenCLEnabled + - kOfxImageEffectPropOpenCLImage + - kOfxImageEffectPropOpenCLRenderSupported + - kOfxImageEffectPropOpenCLSupported + - kOfxImageEffectPropOpenGLEnabled + - kOfxImageEffectPropOpenGLTextureIndex + - kOfxImageEffectPropOpenGLTextureTarget + - kOfxImageEffectPropPluginHandle + - kOfxImageEffectPropRegionOfDefinition + - kOfxImageEffectPropRegionOfInterest + - kOfxImageEffectPropRenderWindow + - kOfxImageEffectPropSequentialRenderStatus + - kOfxInteractPropDrawContext + - kOfxInteractPropPenPosition + - kOfxInteractPropPenPressure + - kOfxInteractPropPenViewportPosition + - kOfxInteractPropViewportSize + - kOfxOpenGLPropPixelDepth + - kOfxParamHostPropSupportsStrChoice + - kOfxParamHostPropSupportsStrChoiceAnimation + - kOfxParamPropChoiceEnum + - kOfxParamPropCustomValue + - kOfxParamPropInterpolationAmount + - kOfxParamPropInterpolationTime + - kOfxPluginPropParamPageOrder + - kOfxPropChangeReason + - kOfxPropKeyString + - kOfxPropKeySym + + + # Properties by name. # Notes: # type=bool means an int property with value 1 or 0 for true or false. diff --git a/scripts/gen-props.py b/scripts/gen-props.py index 5f6e4bb4..940bc902 100644 --- a/scripts/gen-props.py +++ b/scripts/gen-props.py @@ -5,8 +5,9 @@ import difflib import argparse import yaml -from pathlib import Path import logging +from pathlib import Path +from collections.abc import Iterable # Set up basic configuration for logging logging.basicConfig( @@ -73,6 +74,37 @@ def getPropertiesFromDir(dir): props |= getPropertiesFromFile(file_path) return list(props) +def get_def(name: str, defs): + if name.endswith('_REF'): + defname = name.replace("_REF", "_DEF") + return defs[defname] + else: + return [name] + +def expand_set_props(props_by_set): + """Expand refs in props_by_sets. + YAML can't interpolate a list, so we do it here, using + our own method: + - A prop set may end with _DEF in which case it's just a definition + containing a list of prop names. + - A prop *name* may be _REF which means to interpolate the + corresponding DEF list into this set's props. + Returns a new props_by_set with DEFs removed and all lists interpolated. + """ + # First get all the list defs + defs = {} + sets = {} + for key, value in props_by_set.items(): + if key.endswith('_DEF'): + defs[key] = value # should be a list to be interpolated + else: + sets[key] = value + for key in sets: + sets[key] = [item for element in sets[key] \ + for item in get_def(element, defs)] + return sets + + def find_missing(all_props, props_metadata): """Find and print all mismatches between prop defs and metadata. @@ -101,16 +133,29 @@ def check_props_by_set(props_by_set, props_metadata): errs = 0 for pset in sorted(props_by_set): for prop in sorted(props_by_set[pset]): - # Sometimes prop will be a list of props, instead of a string - if isinstance(prop, str): - prop = (prop,) - for p in prop: - if not props_metadata.get(p): - logging.error(f"No props metadata found for {pset}.{p}") - errs += 1 + if not props_metadata.get(prop): + logging.error(f"No props metadata found for {pset}.{prop}") + errs += 1 + return errs + +def check_props_used_by_set(props_by_set, props_metadata): + """Find and print all mismatches between prop set specs, props, and metadata. + + * Each prop name in props_metadata should be used in at least one set. + Returns 0 if no errors. + """ + errs = 0 + for prop in props_metadata: + found = 0 + for pset in props_by_set: + for set_prop in props_by_set[pset]: + if set_prop == prop: + found += 1 + if not found: + logging.error(f"Prop {prop} not used in any prop set in YML file") return errs -def gen_props_metadata(props_metadata, outfile_path): +def gen_props_metadata(props_metadata, outfile_path: Path): """Generate a header file with metadata for each prop""" with open(outfile_path, 'w') as outfile: outfile.write(""" @@ -175,9 +220,29 @@ def gen_props_metadata(props_metadata, outfile_path): raise(e) outfile.write("};\n") +def gen_props_by_set(props_by_set, outfile_path: Path): + """Generate a header file with definitions of all prop sets, including their props""" + with open(outfile_path, 'w') as outfile: + outfile.write(""" +#include +#include +#include +#include "ofxImageEffect.h" +#include "ofxGPURender.h" +#include "ofxColour.h" +#include "ofxDrawSuite.h" +#include "ofxParametricParam.h" +#include "ofxKeySyms.h" +#include "ofxOld.h" + +""") + outfile.write("const std::map> prop_sets {\n") + for pset in sorted(props_by_set.keys()): + propnames = ",".join(props_by_set[pset]) + outfile.write(f"{{ \"{pset}\", {{ {propnames} }} }},\n") + outfile.write("};\n") + def main(args): - if args.verbose: - print("Verbose mode enabled") script_dir = os.path.dirname(os.path.abspath(__file__)) include_dir = Path(script_dir).parent / 'include' all_props = getPropertiesFromDir(include_dir) @@ -185,33 +250,40 @@ def main(args): with open(include_dir / 'ofx-props.yml', 'r') as props_file: props_data = yaml.safe_load(props_file) - props_by_set = props_data['propertySets'] - props_metadata = props_data['properties'] + props_by_set = props_data['propertySets'] + props_by_set = expand_set_props(props_by_set) + props_metadata = props_data['properties'] if args.verbose: print("\n=== Checking ofx-props.yml: should map 1:1 to props found in source/header files") errs = find_missing(all_props, props_metadata) - if not errs: + if not errs and args.verbose: print(" ✔️ ALL OK") if args.verbose: print("\n=== Checking ofx-props.yml: every prop in a set should have metadata in the YML file") errs = check_props_by_set(props_by_set, props_metadata) - if not errs: + if not errs and args.verbose: + print(" ✔️ ALL OK") + + if args.verbose: + print("\n=== Checking ofx-props.yml: every prop should be used in in at least one set in the YML file") + errs = check_props_used_by_set(props_by_set, props_metadata) + if not errs and args.verbose: print(" ✔️ ALL OK") if args.verbose: print("=== Generating gen_props_metadata.hxx") gen_props_metadata(props_metadata, include_dir / 'gen_props_metadata.hxx') if args.verbose: - print("=== Generating props by set header") - # gen_props_by_set(props_by_set, props_metadata) + print("=== Generating props by set header gen_props_by_set.hxx") + gen_props_by_set(props_by_set, include_dir / 'gen_props_by_set.hxx') if __name__ == "__main__": parser = argparse.ArgumentParser(description="Check OpenFX properties and generate ancillary data structures") # Define arguments here - parser.add_argument('--verbose', action='store_true', help='Enable verbose mode') + parser.add_argument('-v', '--verbose', action='store_true', help='Enable verbose mode') # Parse the arguments args = parser.parse_args()