From 9bd2ebcf3d9669e6c09d95db9c7aa6bd9491e7ac Mon Sep 17 00:00:00 2001 From: Alex Fernandez Date: Mon, 13 Jul 2026 22:45:24 -0400 Subject: [PATCH 1/2] support assetImage, artboard and dedupe --- src/main.cpp | 107 +++++++++++++++++++++++++-------------------------- 1 file changed, 52 insertions(+), 55 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 80d3a75..49bcf54 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -260,7 +260,7 @@ static std::string sanitizeString(const std::string& input) return output; } -static std::unique_ptr openFile(const char name[]) +static rive::rcp openFile(const char name[]) { FILE* f = fopen(name, "rb"); if (!f) @@ -378,7 +378,7 @@ static std::vector findRiveFiles(const std::string& path) } static std::string makeUnique(const std::string& base, - std::unordered_set& usedNames) + std::unordered_set& usedNames) { std::string uniqueName = base; int counter = 1; @@ -423,9 +423,8 @@ static std::vector getTextValueRunsFromArtboard( } static std::vector -getNestedTextValueRunPathsFromArtboard( - rive::ArtboardInstance* artboard, - const std::string& currentPath = "") +getNestedTextValueRunPathsFromArtboard(rive::ArtboardInstance* artboard, + const std::string& currentPath = "") { std::vector nestedTextValueRunsInfo; auto count = artboard->nestedArtboards().size(); @@ -435,8 +434,7 @@ getNestedTextValueRunPathsFromArtboard( auto textRuns = getTextValueRunsFromArtboard(artboard); for (const auto& textRun : textRuns) { - nestedTextValueRunsInfo.push_back( - {textRun.name, currentPath}); + nestedTextValueRunsInfo.push_back({textRun.name, currentPath}); } } @@ -449,16 +447,15 @@ getNestedTextValueRunPathsFromArtboard( { // Only process nested artboards that have an exported name std::string newPath = currentPath.empty() - ? nested->name() - : currentPath + "/" + nested->name(); + ? nested->name() + : currentPath + "/" + nested->name(); auto nestedResults = getNestedTextValueRunPathsFromArtboard( nested->artboardInstance(), newPath); - nestedTextValueRunsInfo.insert( - nestedTextValueRunsInfo.end(), - nestedResults.begin(), - nestedResults.end()); + nestedTextValueRunsInfo.insert(nestedTextValueRunsInfo.end(), + nestedResults.begin(), + nestedResults.end()); } } @@ -531,18 +528,20 @@ static std::string dataTypeToString(rive::DataType type) return "symbolListIndex"; case rive::DataType::assetImage: return "assetImage"; + case rive::DataType::artboard: + return "artboard"; default: return "unknown"; } } -static std::optional processRiveFile(const std::string& riveFilePath) +static std::optional processRiveFile( + const std::string& riveFilePath) { // Check if the file is empty if (std::filesystem::is_empty(riveFilePath)) { - std::cerr << "Error: Rive file is empty: " << riveFilePath - << std::endl; + std::cerr << "Error: Rive file is empty: " << riveFilePath << std::endl; return std::nullopt; } @@ -644,8 +643,7 @@ static std::optional processRiveFile(const std::string& riveFilePa std::string artboardKebabCase = toKebabCase(artboardName); // Ensure unique artboard variable names - artboardCameCase = - makeUnique(artboardCameCase, usedArtboardNames); + artboardCameCase = makeUnique(artboardCameCase, usedArtboardNames); std::vector animations = getAnimationsFromArtboard(artboard.get()); @@ -657,14 +655,14 @@ static std::optional processRiveFile(const std::string& riveFilePa getNestedTextValueRunPathsFromArtboard(artboard.get()); fileData.artboards.push_back({artboardName, - artboardPascalCase, - artboardCameCase, - artboardSnakeCase, - artboardKebabCase, - animations, - stateMachines, - textValueRuns, - nestedTextValueRuns}); + artboardPascalCase, + artboardCameCase, + artboardSnakeCase, + artboardKebabCase, + animations, + stateMachines, + textValueRuns, + nestedTextValueRuns}); } return fileData; @@ -768,8 +766,7 @@ int main(int argc, char* argv[]) kainjow::mustache::data templateData; std::vector riveFileList; - for (size_t fileIndex = 0; fileIndex < riveFileDataList.size(); - fileIndex++) + for (size_t fileIndex = 0; fileIndex < riveFileDataList.size(); fileIndex++) { const auto& fileData = riveFileDataList[fileIndex]; kainjow::mustache::data riveFileData; @@ -781,10 +778,18 @@ int main(int argc, char* argv[]) // Add enums to template data std::vector enums; + std::unordered_set seenEnums; for (size_t enumIndex = 0; enumIndex < fileData.enums.size(); enumIndex++) { const auto& enumInfo = fileData.enums[enumIndex]; + // The generator collects one enum entry per reference, so an enum + // shared by several view models appears multiple times. Emit each + // enum only once to avoid duplicate Dart declarations. + if (!seenEnums.insert(enumInfo.name).second) + { + continue; + } kainjow::mustache::data enumData; enumData["enum_name"] = enumInfo.name; enumData["enum_camel_case"] = toCamelCase(enumInfo.name); @@ -804,8 +809,7 @@ int main(int argc, char* argv[]) valueData["enum_value_pascal_case"] = toPascalCase(value.key); valueData["enum_value_snake_case"] = toSnakeCase(value.key); valueData["enum_value_kebab_case"] = toKebabCase(value.key); - valueData["last"] = - (valueIndex == enumInfo.values.size() - 1); + valueData["last"] = (valueIndex == enumInfo.values.size() - 1); enumValues.push_back(valueData); } enumData["enum_values"] = enumValues; @@ -829,12 +833,10 @@ int main(int argc, char* argv[]) toSnakeCase(viewModel.name); viewmodelData["view_model_kebab_case"] = toKebabCase(viewModel.name); - viewmodelData["last"] = - (vmIndex == fileData.viewmodels.size() - 1); + viewmodelData["last"] = (vmIndex == fileData.viewmodels.size() - 1); std::vector properties; - for (size_t propIndex = 0; - propIndex < viewModel.properties.size(); + for (size_t propIndex = 0; propIndex < viewModel.properties.size(); propIndex++) { const auto& property = viewModel.properties[propIndex]; @@ -853,27 +855,27 @@ int main(int argc, char* argv[]) // Add property type information for the viewmodel template kainjow::mustache::data propertyTypeData; propertyTypeData.set("is_view_model", - property.type == "viewModel"); + property.type == "viewModel"); propertyTypeData.set("is_enum", property.type == "enum"); propertyTypeData.set("is_string", property.type == "string"); propertyTypeData.set("is_number", property.type == "number"); - propertyTypeData.set("is_integer", - property.type == "integer"); - propertyTypeData.set("is_boolean", - property.type == "boolean"); + propertyTypeData.set("is_integer", property.type == "integer"); + propertyTypeData.set("is_boolean", property.type == "boolean"); propertyTypeData.set("is_color", property.type == "color"); propertyTypeData.set("is_list", property.type == "list"); - propertyTypeData.set("is_trigger", - property.type == "trigger"); + propertyTypeData.set("is_trigger", property.type == "trigger"); + propertyTypeData.set("is_image", property.type == "assetImage"); + propertyTypeData.set("is_artboard", + property.type == "artboard"); propertyTypeData.set("backing_name", property.backingName); propertyTypeData.set("backing_camel_case", - toCamelCase(property.backingName)); + toCamelCase(property.backingName)); propertyTypeData.set("backing_pascal_case", - toPascalCase(property.backingName)); + toPascalCase(property.backingName)); propertyTypeData.set("backing_snake_case", - toSnakeCase(property.backingName)); + toSnakeCase(property.backingName)); propertyTypeData.set("backing_kebab_case", - toKebabCase(property.backingName)); + toKebabCase(property.backingName)); propertyData.set("property_type", propertyTypeData); propertyData["last"] = @@ -913,8 +915,7 @@ int main(int argc, char* argv[]) const auto& artboard = fileData.artboards[artboardIndex]; kainjow::mustache::data artboardData; artboardData["artboard_name"] = artboard.artboardName; - artboardData["artboard_pascal_case"] = - artboard.artboardPascalCase; + artboardData["artboard_pascal_case"] = artboard.artboardPascalCase; artboardData["artboard_camel_case"] = artboard.artboardCameCase; artboardData["artboard_snake_case"] = artboard.artboardSnakeCase; artboardData["artboard_kebab_case"] = artboard.artboardKebabCase; @@ -989,22 +990,18 @@ int main(int argc, char* argv[]) std::unordered_set usedTextValueRunNames; std::vector textValueRuns; - for (size_t tvrIndex = 0; - tvrIndex < artboard.textValueRuns.size(); + for (size_t tvrIndex = 0; tvrIndex < artboard.textValueRuns.size(); tvrIndex++) { const auto& tvr = artboard.textValueRuns[tvrIndex]; kainjow::mustache::data tvrData; auto uniqueName = makeUnique(tvr.name, usedTextValueRunNames); tvrData["text_value_run_name"] = tvr.name; - tvrData["text_value_run_camel_case"] = - toCamelCase(uniqueName); + tvrData["text_value_run_camel_case"] = toCamelCase(uniqueName); tvrData["text_value_run_pascal_case"] = toPascalCase(uniqueName); - tvrData["text_value_run_snake_case"] = - toSnakeCase(uniqueName); - tvrData["text_value_run_kebab_case"] = - toKebabCase(uniqueName); + tvrData["text_value_run_snake_case"] = toSnakeCase(uniqueName); + tvrData["text_value_run_kebab_case"] = toKebabCase(uniqueName); tvrData["text_value_run_default"] = tvr.defaultValue; tvrData["text_value_run_default_sanitized"] = sanitizeString(tvr.defaultValue); From be811a542e41d3122657edfbbe9382edad32ac4a Mon Sep 17 00:00:00 2001 From: Alex Fernandez Date: Mon, 13 Jul 2026 22:48:45 -0400 Subject: [PATCH 2/2] new submodules --- rive-runtime | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rive-runtime b/rive-runtime index 1a9350e..9a9bf40 160000 --- a/rive-runtime +++ b/rive-runtime @@ -1 +1 @@ -Subproject commit 1a9350e4ae1b7d0652757e9425c2b74a6c3b2992 +Subproject commit 9a9bf409b754b6c337f6705fcd893374b65b22f0