Core generator distinguishes which fields need to be stored or not (via encoded flag).
diff --git a/dev/core_generator/lib/src/definition.dart b/dev/core_generator/lib/src/definition.dart index 6951988..fdfbea2 100644 --- a/dev/core_generator/lib/src/definition.dart +++ b/dev/core_generator/lib/src/definition.dart
@@ -165,10 +165,17 @@ code.writeln('static const uint16_t ${property.name}PropertyKey = ' '${property.key.intValue};'); } - code.writeln('private:'); + if (properties.any((prop) => !prop.isEncoded)) { + code.writeln('private:'); + } // Write fields. for (final property in properties) { + if (property.isEncoded) { + // Encoded properties don't store data, it's up to the implementation + // to decode and store what it needs. + continue; + } code.writeln('${property.type.cppName} m_${property.capitalizedName}'); var initialize = property.initialValueRuntime ?? @@ -186,19 +193,37 @@ // Write getter/setters. code.writeln('public:'); for (final property in properties) { - code.writeln((property.isVirtual ? 'virtual' : 'inline') + - ' ${property.type.cppGetterName} ${property.name}() const ' + - (property.isGetOverride ? 'override' : '') + - '{ return m_${property.capitalizedName}; }'); + if (property.isEncoded) { + // Encoded properties just have a pure virtual decoder that needs to + // be implemented. Also requires an implemention of copyPropertyName + // as that will no longer automatically be copied by the generated + // code. + code.writeln((property.isSetOverride ? '' : 'virtual ') + + 'void decode${property.capitalizedName}' + + '(${property.type.cppName} value) ' + + (property.isSetOverride ? 'override' : '') + + '= 0;'); + code.writeln((property.isSetOverride ? '' : 'virtual ') + + 'void copy${property.capitalizedName}' + + '(const ${_name}Base& object) ' + + (property.isSetOverride ? 'override' : '') + + '= 0;'); + } else { + code.writeln((property.isVirtual ? 'virtual' : 'inline') + + ' ${property.type.cppGetterName} ${property.name}() const ' + + (property.isGetOverride ? 'override' : '') + + '{ return m_${property.capitalizedName}; }'); - code.writeln('void ${property.name}(${property.type.cppName} value) ' + - (property.isSetOverride ? 'override' : '') + - '{' - 'if(m_${property.capitalizedName} == value)' - '{return;}' - 'm_${property.capitalizedName} = value;' - '${property.name}Changed();' - '}'); + code.writeln( + 'void ${property.name}(${property.type.cppName} value) ' + + (property.isSetOverride ? 'override' : '') + + '{' + 'if(m_${property.capitalizedName} == value)' + '{return;}' + 'm_${property.capitalizedName} = value;' + '${property.name}Changed();' + '}'); + } code.writeln(); } @@ -211,8 +236,12 @@ if (properties.isNotEmpty || _extensionOf == null) { code.writeln('void copy(const ${_name}Base& object) {'); for (final property in properties) { - code.writeln('m_${property.capitalizedName} = ' - 'object.m_${property.capitalizedName};'); + if (property.isEncoded) { + code.writeln('copy${property.capitalizedName}(object);'); + } else { + code.writeln('m_${property.capitalizedName} = ' + 'object.m_${property.capitalizedName};'); + } } if (_extensionOf != null) { code.writeln('${_extensionOf.name}::' @@ -227,8 +256,13 @@ code.writeln('switch (propertyKey){'); for (final property in properties) { code.writeln('case ${property.name}PropertyKey:'); - code.writeln('m_${property.capitalizedName} = ' - '${property.type.runtimeCoreType}::deserialize(reader);'); + if (property.isEncoded) { + code.writeln('decode${property.capitalizedName}' + '(${property.type.runtimeCoreType}::deserialize(reader));'); + } else { + code.writeln('m_${property.capitalizedName} = ' + '${property.type.runtimeCoreType}::deserialize(reader);'); + } code.writeln('return true;'); } code.writeln('}'); @@ -400,18 +434,23 @@ ctxCode.writeln('} return nullptr; }'); var usedFieldTypes = <FieldType, List<Property>>{}; + var getSetFieldTypes = <FieldType, List<Property>>{}; for (final definition in runtimeDefinitions) { for (final property in definition.properties) { usedFieldTypes[property.type] ??= []; usedFieldTypes[property.type].add(property); + if (!property.isEncoded) { + getSetFieldTypes[property.type] ??= []; + getSetFieldTypes[property.type].add(property); + } } } - for (final fieldType in usedFieldTypes.keys) { + for (final fieldType in getSetFieldTypes.keys) { ctxCode .writeln('static void set${fieldType.capitalizedName}(Core* object, ' 'int propertyKey, ${fieldType.cppName} value){'); ctxCode.writeln('switch (propertyKey) {'); - var properties = usedFieldTypes[fieldType]; + var properties = getSetFieldTypes[fieldType]; for (final property in properties) { ctxCode.writeln('case ${property.definition.name}Base' '::${property.name}PropertyKey:'); @@ -421,12 +460,12 @@ } ctxCode.writeln('}}'); } - for (final fieldType in usedFieldTypes.keys) { + for (final fieldType in getSetFieldTypes.keys) { ctxCode.writeln( 'static ${fieldType.cppName} get${fieldType.capitalizedName}(' 'Core* object, int propertyKey){'); ctxCode.writeln('switch (propertyKey) {'); - var properties = usedFieldTypes[fieldType]; + var properties = getSetFieldTypes[fieldType]; for (final property in properties) { ctxCode.writeln('case ${property.definition.name}Base' '::${property.name}PropertyKey:'); @@ -451,25 +490,7 @@ } ctxCode.writeln('default: return -1;}}'); - /*Core makeCoreInstance(int typeKey) { - switch (typeKey) { - case KeyedObjectBase.typeKey: - return KeyedObject(); - case KeyedPropertyBase.typeKey: - return KeyedProperty();*/ - // Put our fields in. - // var usedFieldTypes = <FieldType>{}; - // for (final definition in definitions.values) { - // for (final property in definition.properties) { - // usedFieldTypes.add(property.type); - // } - // } - // // Find fields we use. - // for (final fieldType in usedFieldTypes) { - // ctxCode.writeln('static ${fieldType.runtimeCoreType} ' - // '${fieldType.uncapitalizedName}Type;'); - // } ctxCode.writeln('};}'); var output = generatedHppPath;
diff --git a/dev/core_generator/lib/src/property.dart b/dev/core_generator/lib/src/property.dart index be707a4..76b3be8 100644 --- a/dev/core_generator/lib/src/property.dart +++ b/dev/core_generator/lib/src/property.dart
@@ -1,5 +1,4 @@ import 'package:colorize/colorize.dart'; -import 'package:core_generator/src/comment.dart'; import 'package:core_generator/src/definition.dart'; import 'package:core_generator/src/field_type.dart'; import 'package:core_generator/src/key.dart'; @@ -20,6 +19,7 @@ bool isCoop = true; bool isSetOverride = false; bool isGetOverride = false; + bool isEncoded = false; FieldType typeRuntime; factory Property(Definition type, String name, Map<String, dynamic> data) { @@ -28,7 +28,7 @@ } var fieldType = - FieldType.find(data["typeRuntime"]) ?? FieldType.find(data["type"]); + FieldType.find(data['typeRuntime']) ?? FieldType.find(data['type']); if (fieldType == null) { color('Invalid field type ${data['type']} for $name.', front: Styles.RED); @@ -39,7 +39,11 @@ Property.make( this.definition, this.name, this.type, Map<String, dynamic> data) { - dynamic descriptionValue = data["description"]; + dynamic encodedValue = data['encoded']; + if (encodedValue is bool) { + isEncoded = encodedValue; + } + dynamic descriptionValue = data['description']; if (descriptionValue is String) { description = descriptionValue; } @@ -89,153 +93,11 @@ if (rt is String) { typeRuntime = FieldType.find(rt); } - key = Key.fromJSON(data["key"]) ?? Key.forProperty(this); + key = Key.fromJSON(data['key']) ?? Key.forProperty(this); } FieldType getExportType() => typeRuntime ?? type; - String generateCode(bool forRuntime) { - bool exportAnimates = false; - var exportType = getExportType(); - String propertyKey = '${name}PropertyKey'; - var code = StringBuffer(' /// ${'-' * 74}\n'); - code.write(comment('${capitalize(name)} field with key ${key.intValue}.', - indent: 1)); - if (initialValueRuntime != null || initialValue != null) { - code.writeln( - '${exportType.cppName} _$name = ${initialValueRuntime ?? initialValue};'); - } else { - code.writeln('${exportType.cppName} _$name;'); - } - if (exportAnimates) { - code.writeln('${exportType.cppName} _${name}Animated;'); - code.writeln('KeyState _${name}KeyState = KeyState.none;'); - } - code.writeln('static const int $propertyKey = ${key.intValue};'); - - if (description != null) { - code.write(comment(description, indent: 1)); - } - if (exportAnimates) { - code.write(comment( - 'Get the [_$name] field value.' - 'Note this may not match the core value ' - 'if animation mode is active.', - indent: 1)); - code.writeln( - '${exportType.cppName} get $name => _${name}Animated ?? _$name;'); - code.write( - comment('Get the non-animation [_$name] field value.', indent: 1)); - code.writeln('${exportType.cppName} get ${name}Core => _$name;'); - } else { - code.writeln('${exportType.cppName} get $name => _$name;'); - } - code.write(comment('Change the [_$name] field value.', indent: 1)); - code.write(comment( - '[${name}Changed] will be invoked only if the ' - 'field\'\s value has changed.', - indent: 1)); - code.writeln( - '''set $name${exportAnimates ? 'Core' : ''}(${exportType.cppName} value) { - if(${exportType.equalityCheck('_$name', 'value')}) { return; } - ${exportType.cppName} from = _$name; - _$name = value;'''); - // Property change callbacks to the context don't propagate at runtime. - if (!forRuntime) { - code.writeln('onPropertyChanged($propertyKey, from, value);'); - if (!isCoop) { - code.writeln( - 'context?.editorPropertyChanged(this, $propertyKey, from, value);'); - } - } - // Change callbacks do as we use those to trigger dirty states. - code.writeln(''' - ${name}Changed(from, value); - }'''); - if (exportAnimates) { - code.writeln('''set $name(${exportType.cppName} value) { - if(context != null && context.isAnimating && $name != value) { - _${name}Animate(value, true); - return; - } - ${name}Core = value; - }'''); - - code.writeln( - '''void _${name}Animate(${exportType.cppName} value, bool autoKey) { - if (_${name}Animated == value) { - return; - } - ${exportType.cppName} from = $name; - _${name}Animated = value; - ${exportType.cppName} to = $name; - onAnimatedPropertyChanged($propertyKey, autoKey, from, to); - ${name}Changed(from, to); - }'''); - - code.writeln( - '${exportType.cppName} get ${name}Animated => _${name}Animated;'); - code.writeln('''set ${name}Animated(${exportType.cppName} value) => - _${name}Animate(value, false);'''); - code.writeln('KeyState get ${name}KeyState => _${name}KeyState;'); - code.writeln('''set ${name}KeyState(KeyState value) { - if (_${name}KeyState == value) { - return; - } - _${name}KeyState = value; - // Force update anything listening on this property. - onAnimatedPropertyChanged($propertyKey, false, _${name}Animated, _${name}Animated); - }'''); - } - code.writeln('void ${name}Changed(' - '${exportType.cppName} from, ${exportType.cppName} to);\n'); - - return code.toString(); - } - - Map<String, dynamic> serialize() { - Map<String, dynamic> data = <String, dynamic>{'type': type.name}; - if (typeRuntime != null) { - data['typeRuntime'] = typeRuntime.name; - } - - if (initialValue != null) { - data['initialValue'] = initialValue; - } - if (initialValueRuntime != null) { - data['initialValueRuntime'] = initialValueRuntime; - } - if (isGetOverride) { - data['overrideGet'] = true; - } - if (isSetOverride) { - data['overrideSet'] = true; - } - if (animates) { - data['animates'] = true; - } - if (group != null) { - data['group'] = group; - } - data['key'] = key.serialize(); - if (description != null) { - data['description'] = description; - } - if (isNullable) { - data['nullable'] = true; - } - if (!isRuntime) { - data['runtime'] = false; - } - if (!isCoop) { - data['coop'] = false; - } - if (isVirtual) { - data['virtual'] = true; - } - return data; - } - @override String toString() { return '$name(${key.intValue})';
diff --git a/dev/defs/shapes/mesh.json b/dev/defs/shapes/mesh.json index e4986d5..857676b 100644 --- a/dev/defs/shapes/mesh.json +++ b/dev/defs/shapes/mesh.json
@@ -29,6 +29,7 @@ }, "triangleIndexBytes": { "type": "Bytes", + "encoded": true, "key": { "int": 223, "string": "triangleindexbytes"
diff --git a/include/rive/generated/core_registry.hpp b/include/rive/generated/core_registry.hpp index cef092c..d7d46a3 100644 --- a/include/rive/generated/core_registry.hpp +++ b/include/rive/generated/core_registry.hpp
@@ -784,9 +784,6 @@ static void setBytes(Core* object, int propertyKey, std::vector<uint8_t> value) { switch (propertyKey) { - case MeshBase::triangleIndexBytesPropertyKey: - object->as<MeshBase>()->triangleIndexBytes(value); - break; case FileAssetContentsBase::bytesPropertyKey: object->as<FileAssetContentsBase>()->bytes(value); break; @@ -1162,8 +1159,6 @@ } static std::vector<uint8_t> getBytes(Core* object, int propertyKey) { switch (propertyKey) { - case MeshBase::triangleIndexBytesPropertyKey: - return object->as<MeshBase>()->triangleIndexBytes(); case FileAssetContentsBase::bytesPropertyKey: return object->as<FileAssetContentsBase>()->bytes(); }
diff --git a/include/rive/generated/shapes/mesh_base.hpp b/include/rive/generated/shapes/mesh_base.hpp index 5a2aa1e..ff9b93d 100644 --- a/include/rive/generated/shapes/mesh_base.hpp +++ b/include/rive/generated/shapes/mesh_base.hpp
@@ -28,31 +28,21 @@ static const uint16_t triangleIndexBytesPropertyKey = 223; - private: - std::vector<uint8_t> m_TriangleIndexBytes; - public: - inline const std::vector<uint8_t>& triangleIndexBytes() const { - return m_TriangleIndexBytes; - } - void triangleIndexBytes(std::vector<uint8_t> value) { - if (m_TriangleIndexBytes == value) { - return; - } - m_TriangleIndexBytes = value; - triangleIndexBytesChanged(); - } + virtual void decodeTriangleIndexBytes(std::vector<uint8_t> value) = 0; + virtual void copyTriangleIndexBytes(const MeshBase& object) = 0; Core* clone() const override; void copy(const MeshBase& object) { - m_TriangleIndexBytes = object.m_TriangleIndexBytes; + copyTriangleIndexBytes(object); ContainerComponent::copy(object); } bool deserialize(uint16_t propertyKey, BinaryReader& reader) override { switch (propertyKey) { case triangleIndexBytesPropertyKey: - m_TriangleIndexBytes = CoreBytesType::deserialize(reader); + decodeTriangleIndexBytes( + CoreBytesType::deserialize(reader)); return true; } return ContainerComponent::deserialize(propertyKey, reader);
diff --git a/include/rive/shapes/mesh.hpp b/include/rive/shapes/mesh.hpp index ee3b0f2..1b531e5 100644 --- a/include/rive/shapes/mesh.hpp +++ b/include/rive/shapes/mesh.hpp
@@ -12,7 +12,8 @@ StatusCode onAddedDirty(CoreContext* context) override; void markDrawableDirty(); void addVertex(MeshVertex* vertex); - + void decodeTriangleIndexBytes(std::vector<uint8_t> value) override; + void copyTriangleIndexBytes(const MeshBase& object) override; #ifdef TESTING std::vector<MeshVertex*>& vertices() { return m_Vertices; } #endif
diff --git a/src/shapes/mesh.cpp b/src/shapes/mesh.cpp index 207410c..e84b27e 100644 --- a/src/shapes/mesh.cpp +++ b/src/shapes/mesh.cpp
@@ -21,4 +21,12 @@ parent()->as<Image>()->setMesh(this); return StatusCode::Ok; +} + +void Mesh::decodeTriangleIndexBytes(std::vector<uint8_t> value) { + // decode the triangle index bytes +} + +void Mesh::copyTriangleIndexBytes(const MeshBase& object) { + // copy the triangle indices from object } \ No newline at end of file