Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dafebf5b03 | |||
| e3f4fb07dc | |||
| 89cd7fff62 | |||
| 63649cd9a7 | |||
| a50809bc91 | |||
| 442b06dff7 | |||
| 71f32a5f71 | |||
| eb97eb1df8 | |||
| adc8558edf | |||
| 83c72a7131 | |||
| 658c40eecd | |||
| 345b23f801 | |||
| d563e5cfe5 | |||
| 2dc2d452e6 | |||
| 2ea6fdd32e | |||
| 8c770e1fbc | |||
| 30ae1b7420 | |||
| 66a1ccb8ba | |||
| 4bb2759be9 | |||
| 0a1a3e1627 |
@@ -1,36 +0,0 @@
|
|||||||
version: 2.1
|
|
||||||
|
|
||||||
orbs:
|
|
||||||
win: circleci/windows@2.2.0
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
publish_nuget:
|
|
||||||
executor: win/default
|
|
||||||
steps:
|
|
||||||
- checkout
|
|
||||||
- run:
|
|
||||||
name: Restore packages
|
|
||||||
command: nuget restore GrasshopperAsyncComponent.sln
|
|
||||||
- run:
|
|
||||||
name: Build solution
|
|
||||||
command: msbuild GrasshopperAsyncComponent.sln /p:Configuration=Release
|
|
||||||
- run:
|
|
||||||
name: Pack NuGet
|
|
||||||
command: cd GrasshopperAsyncComponent; nuget pack GrasshopperAsyncComponent.csproj -Prop Configuration=Release -Symbols -SymbolPackageFormat snupkg
|
|
||||||
- run:
|
|
||||||
name: Push NuGet
|
|
||||||
command: cd GrasshopperAsyncComponent; nuget push *.nupkg -Source https://api.nuget.org/v3/index.json -ApiKey $env:NUGET_AUTH_TOKEN -SkipDuplicate
|
|
||||||
|
|
||||||
|
|
||||||
workflows:
|
|
||||||
publish:
|
|
||||||
jobs:
|
|
||||||
- publish_nuget:
|
|
||||||
filters:
|
|
||||||
tags:
|
|
||||||
only: /^v.*/
|
|
||||||
branches:
|
|
||||||
ignore: /.*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
Directory.Build.targets
|
||||||
|
Directory.Build.props
|
||||||
|
|
||||||
|
**/bin/*
|
||||||
|
**/obj/*
|
||||||
|
_ReSharper.SharpCompress/
|
||||||
|
bin/
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
TestArchives/Scratch/
|
||||||
|
TestArchives/Scratch2/
|
||||||
|
TestResults/
|
||||||
|
*.nupkg
|
||||||
|
packages/*/
|
||||||
|
project.lock.json
|
||||||
|
tests/TestArchives/Scratch
|
||||||
|
.vs
|
||||||
|
tools
|
||||||
|
.vscode
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
.DS_Store
|
||||||
|
*.snupkg
|
||||||
|
coverage.xml
|
||||||
|
|
||||||
|
*.received.*
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
printWidth: 120
|
||||||
|
useTabs: false
|
||||||
|
indentSize: 2
|
||||||
|
preprocessorSymbolSets:
|
||||||
|
- ""
|
||||||
|
- "DEBUG"
|
||||||
|
- "DEBUG,CODE_STYLE"
|
||||||
+327
@@ -0,0 +1,327 @@
|
|||||||
|
root = true
|
||||||
|
# Don't use tabs for indentation.
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
# Microsoft .NET properties
|
||||||
|
csharp_using_directive_placement = outside_namespace:silent
|
||||||
|
|
||||||
|
dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none
|
||||||
|
dotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:none
|
||||||
|
dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none
|
||||||
|
|
||||||
|
|
||||||
|
# Standard properties
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
# (Please don't specify an indent_size here; that has too many unintended consequences.)
|
||||||
|
|
||||||
|
# Code files
|
||||||
|
[*.{cs,csx,vb,vbx}]
|
||||||
|
indent_size = 2
|
||||||
|
charset = utf-8
|
||||||
|
|
||||||
|
# Xml project files
|
||||||
|
[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
|
||||||
|
indent_size = 2
|
||||||
|
space_after_last_pi_attribute = false
|
||||||
|
# Xml config files
|
||||||
|
[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
|
||||||
|
indent_size = 2
|
||||||
|
space_after_last_pi_attribute = false
|
||||||
|
|
||||||
|
# JSON files
|
||||||
|
[*.json]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# Dotnet code style settings:
|
||||||
|
[*.{cs,vb}]
|
||||||
|
# Sort using and Import directives with System.* appearing first
|
||||||
|
dotnet_sort_system_directives_first = true
|
||||||
|
dotnet_separate_import_directive_groups = false
|
||||||
|
|
||||||
|
# Avoid "this." and "Me." if not necessary
|
||||||
|
dotnet_style_qualification_for_field = false:suggestion
|
||||||
|
dotnet_style_qualification_for_property = false:suggestion
|
||||||
|
dotnet_style_qualification_for_method = false:suggestion
|
||||||
|
dotnet_style_qualification_for_event = false:suggestion
|
||||||
|
|
||||||
|
# Use language keywords instead of framework type names for type references
|
||||||
|
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
||||||
|
dotnet_style_predefined_type_for_member_access = true:suggestion
|
||||||
|
# Parentheses preferences
|
||||||
|
dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:silent
|
||||||
|
dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:silent
|
||||||
|
dotnet_style_parentheses_in_other_binary_operators = never_if_unnecessary:silent
|
||||||
|
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
|
||||||
|
|
||||||
|
# Modifier preferences
|
||||||
|
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
|
||||||
|
dotnet_style_readonly_field = true:suggestion
|
||||||
|
|
||||||
|
# Expression-level preferences
|
||||||
|
dotnet_style_object_initializer = true:suggestion
|
||||||
|
dotnet_style_collection_initializer = true:suggestion
|
||||||
|
dotnet_style_coalesce_expression = true:suggestion
|
||||||
|
dotnet_style_null_propagation = true:suggestion
|
||||||
|
dotnet_style_explicit_tuple_names = true:suggestion
|
||||||
|
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
|
||||||
|
dotnet_style_prefer_inferred_tuple_names = true:suggestion
|
||||||
|
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
|
||||||
|
dotnet_style_prefer_auto_properties = true:warning
|
||||||
|
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
|
||||||
|
dotnet_style_prefer_conditional_expression_over_return = true:silent
|
||||||
|
|
||||||
|
|
||||||
|
# CSharp code style settings:
|
||||||
|
[*.cs]
|
||||||
|
# Prefer "var" everywhere
|
||||||
|
csharp_style_var_elsewhere = false:none
|
||||||
|
csharp_style_var_for_built_in_types = false:none
|
||||||
|
csharp_style_var_when_type_is_apparent = false:none
|
||||||
|
|
||||||
|
# Prefer method-like constructs to have a block body
|
||||||
|
csharp_style_expression_bodied_methods = true:suggestion
|
||||||
|
csharp_style_expression_bodied_constructors = false:suggestion
|
||||||
|
csharp_style_expression_bodied_operators = true:suggestion
|
||||||
|
|
||||||
|
# Prefer property-like constructs to have an expression-body
|
||||||
|
csharp_style_expression_bodied_properties = true:suggestion
|
||||||
|
csharp_style_expression_bodied_indexers = true:suggestion
|
||||||
|
csharp_style_expression_bodied_accessors = true:suggestion
|
||||||
|
|
||||||
|
# Suggest more modern language features when available
|
||||||
|
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||||
|
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||||
|
csharp_style_inlined_variable_declaration = true:suggestion
|
||||||
|
csharp_style_throw_expression = true:suggestion
|
||||||
|
csharp_style_conditional_delegate_call = true:suggestion
|
||||||
|
csharp_style_namespace_declarations = file_scoped
|
||||||
|
|
||||||
|
# Newline settings
|
||||||
|
csharp_new_line_before_open_brace = all
|
||||||
|
csharp_new_line_before_else = true
|
||||||
|
csharp_new_line_before_catch = true
|
||||||
|
csharp_new_line_before_finally = true
|
||||||
|
csharp_new_line_before_members_in_object_initializers = true
|
||||||
|
csharp_new_line_before_members_in_anonymous_types = true
|
||||||
|
|
||||||
|
# Space preferences
|
||||||
|
csharp_space_after_cast = false
|
||||||
|
csharp_space_after_keywords_in_control_flow_statements = true
|
||||||
|
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_parentheses = false
|
||||||
|
csharp_space_before_colon_in_inheritance_clause = true
|
||||||
|
csharp_space_after_colon_in_inheritance_clause = true
|
||||||
|
csharp_space_around_binary_operators = before_and_after
|
||||||
|
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||||
|
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||||
|
|
||||||
|
# Wrapping preferences
|
||||||
|
csharp_preserve_single_line_statements = true
|
||||||
|
csharp_preserve_single_line_blocks = true
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# SYMBOL NAMING RULES
|
||||||
|
# Copied from https://github.com/dotnet/roslyn/blob/main/.editorconfig
|
||||||
|
# Adapted rules:
|
||||||
|
# - Constants are ALL_UPPER
|
||||||
|
# - Non-private fields are PascalCase
|
||||||
|
|
||||||
|
# Non-private fields are PascalCase
|
||||||
|
dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.severity = warning
|
||||||
|
dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.symbols = non_private_readonly_fields
|
||||||
|
dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.style = non_private_readonly_field_style
|
||||||
|
|
||||||
|
dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field
|
||||||
|
dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected
|
||||||
|
|
||||||
|
dotnet_naming_style.non_private_readonly_field_style.capitalization = pascal_case
|
||||||
|
|
||||||
|
# Constants are ALL_UPPER
|
||||||
|
dotnet_naming_rule.constants_should_be_all_upper.severity = warning
|
||||||
|
dotnet_naming_rule.constants_should_be_all_upper.symbols = constants
|
||||||
|
dotnet_naming_rule.constants_should_be_all_upper.style = constant_style
|
||||||
|
|
||||||
|
dotnet_naming_symbols.constants.applicable_kinds = field, local
|
||||||
|
dotnet_naming_symbols.constants.required_modifiers = const
|
||||||
|
|
||||||
|
dotnet_naming_style.constant_style.capitalization = all_upper
|
||||||
|
|
||||||
|
# Private static fields are camelCase and start with s_
|
||||||
|
dotnet_naming_rule.static_fields_should_be_camel_case.severity = warning
|
||||||
|
dotnet_naming_rule.static_fields_should_be_camel_case.symbols = static_fields
|
||||||
|
dotnet_naming_rule.static_fields_should_be_camel_case.style = static_field_style
|
||||||
|
|
||||||
|
dotnet_naming_symbols.static_fields.applicable_accessibilities = private
|
||||||
|
dotnet_naming_symbols.static_fields.applicable_kinds = field
|
||||||
|
dotnet_naming_symbols.static_fields.required_modifiers = static
|
||||||
|
|
||||||
|
dotnet_naming_style.static_field_style.capitalization = camel_case
|
||||||
|
dotnet_naming_style.static_field_style.required_prefix = s_
|
||||||
|
|
||||||
|
|
||||||
|
# Instance fields are camelCase and start with _
|
||||||
|
dotnet_naming_rule.instance_fields_should_be_camel_case.severity = warning
|
||||||
|
dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields
|
||||||
|
dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style
|
||||||
|
|
||||||
|
dotnet_naming_symbols.instance_fields.applicable_kinds = field
|
||||||
|
|
||||||
|
dotnet_naming_style.instance_field_style.capitalization = camel_case
|
||||||
|
dotnet_naming_style.instance_field_style.required_prefix = _
|
||||||
|
|
||||||
|
# Locals and parameters are camelCase
|
||||||
|
dotnet_naming_rule.locals_should_be_camel_case.severity = warning
|
||||||
|
dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters
|
||||||
|
dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style
|
||||||
|
|
||||||
|
dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local
|
||||||
|
|
||||||
|
dotnet_naming_style.camel_case_style.capitalization = camel_case
|
||||||
|
|
||||||
|
# Local functions are PascalCase
|
||||||
|
dotnet_naming_rule.local_functions_should_be_pascal_case.severity = warning
|
||||||
|
dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions
|
||||||
|
dotnet_naming_rule.local_functions_should_be_pascal_case.style = local_function_style
|
||||||
|
|
||||||
|
dotnet_naming_symbols.local_functions.applicable_kinds = local_function
|
||||||
|
|
||||||
|
dotnet_naming_style.local_function_style.capitalization = pascal_case
|
||||||
|
|
||||||
|
# By default, name items with PascalCase
|
||||||
|
dotnet_naming_rule.members_should_be_pascal_case.severity = warning
|
||||||
|
dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members
|
||||||
|
dotnet_naming_rule.members_should_be_pascal_case.style = pascal_case_style
|
||||||
|
|
||||||
|
dotnet_naming_symbols.all_members.applicable_kinds = *
|
||||||
|
|
||||||
|
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
|
||||||
|
|
||||||
|
|
||||||
|
# Analyzer settings
|
||||||
|
dotnet_analyzer_diagnostic.category-Style.severity = warning # All rules will use this severity unless overriden
|
||||||
|
dotnet_diagnostic.ide0055.severity = none # Formatting rule: Incompatible with CSharpier
|
||||||
|
dotnet_diagnostic.ide0007.severity = none # Use var instead of explicit type: Preference
|
||||||
|
dotnet_diagnostic.ide0009.severity = none # Add this or Me qualification: Preference
|
||||||
|
dotnet_diagnostic.ide0200.severity = none # Remove unnecessary lambda expression: may be performance reasons not to
|
||||||
|
dotnet_diagnostic.ide0058.severity = none # Remove unnecessary expression value: Subjective
|
||||||
|
dotnet_diagnostic.ide0010.severity = none # Add missing cases to switch statement: Too verbose
|
||||||
|
dotnet_diagnostic.ide0200.severity = none # Remove unnecessary lambda expression: may be performance reasons not to
|
||||||
|
dotnet_diagnostic.ide0058.severity = none # Remove unnecessary expression value: Subjective
|
||||||
|
dotnet_diagnostic.ide0305.severity = none # Use collection expression for fluent: Can obfuscate intent
|
||||||
|
dotnet_diagnostic.ide0001.severity = suggestion # Name can be simplified: Non enforceable in build
|
||||||
|
dotnet_diagnostic.ide0046.severity = suggestion # Use conditional expression for return: Subjective
|
||||||
|
dotnet_diagnostic.ide0045.severity = suggestion # Use conditional expression for assignment: Subjective
|
||||||
|
dotnet_diagnostic.ide0078.severity = suggestion # Use pattern matching: Subjective
|
||||||
|
dotnet_diagnostic.ide0260.severity = suggestion # Use pattern matching: Subjective
|
||||||
|
dotnet_diagnostic.ide0022.severity = suggestion # Use expression body for method: Subjective
|
||||||
|
dotnet_diagnostic.ide0061.severity = suggestion # Use expression body for local functions: Subjective
|
||||||
|
dotnet_diagnostic.ide0063.severity = suggestion # Using directive can be simplified
|
||||||
|
dotnet_diagnostic.ide0066.severity = suggestion # Use switch expression: Subjective
|
||||||
|
dotnet_diagnostic.ide0029.severity = suggestion # Null check can be simplified: Subjective
|
||||||
|
dotnet_diagnostic.ide0030.severity = suggestion # Null check can be simplified: Subjective
|
||||||
|
dotnet_diagnostic.ide0270.severity = suggestion # Null check can be simplified: Subjective
|
||||||
|
dotnet_diagnostic.ide0042.severity = suggestion # Deconstruct variable declaration: Subjective
|
||||||
|
dotnet_diagnostic.ide0039.severity = suggestion # Use local function instead of lambda: Subjective
|
||||||
|
dotnet_diagnostic.ide0029.severity = suggestion # Null check can be simplified: Subjective
|
||||||
|
dotnet_diagnostic.ide0030.severity = suggestion # Null check can be simplified: Subjective
|
||||||
|
dotnet_diagnostic.ide0270.severity = suggestion # Null check can be simplified: Subjective
|
||||||
|
dotnet_diagnostic.ide0042.severity = suggestion # Deconstruct variable declaration: Subjective
|
||||||
|
dotnet_diagnostic.ide0028.severity = suggestion # Use collection initializers: Subjective
|
||||||
|
dotnet_diagnostic.ide0072.severity = suggestion # Populate switch statement: Subjective
|
||||||
|
dotnet_diagnostic.ide0074.severity = suggestion # Use compound assignment: Subjective
|
||||||
|
dotnet_diagnostic.ide0300.severity = suggestion # Use collection expression for array: Subjective, maybe aspirational
|
||||||
|
dotnet_diagnostic.ide0290.severity = suggestion # primary constructors: subjective, and readonly properties are not a thing
|
||||||
|
dotnet_diagnostic.ide0290.severity = suggestion # Use primary constructor: Subjective
|
||||||
|
dotnet_diagnostic.ide0037.severity = suggestion # Use inferred member names: Sometimes its nice to be explicit
|
||||||
|
dotnet_diagnostic.ide0301.severity = suggestion # Use collection expression for empty: Subjective, intent
|
||||||
|
dotnet_diagnostic.ide0021.severity = suggestion # Use expression body for constructors : Subjective
|
||||||
|
dotnet_diagnostic.ide0090.severity = suggestion # Simplify new expression : Subjective
|
||||||
|
|
||||||
|
dotnet_diagnostic.ide0047.severity = suggestion # Parentheses preferences: IDEs don't properly pick it up
|
||||||
|
dotnet_diagnostic.ide0130.severity = suggestion # Namespace does not match folder structure : Aspirational
|
||||||
|
dotnet_diagnostic.ide1006.severity = suggestion # Naming rule violation : Aspirational
|
||||||
|
|
||||||
|
# Maintainability rules
|
||||||
|
dotnet_diagnostic.ca1501.severity = warning # Avoid excessive inheritance
|
||||||
|
dotnet_diagnostic.ca1502.severity = warning # Avoid excessive complexity
|
||||||
|
dotnet_diagnostic.ca1505.severity = warning # Avoid unmaintainable code
|
||||||
|
dotnet_diagnostic.ca1506.severity = warning # Avoid excessive class coupling
|
||||||
|
dotnet_diagnostic.ca1507.severity = warning # Use nameof in place of string
|
||||||
|
dotnet_diagnostic.ca1508.severity = warning # Avoid dead conditional code
|
||||||
|
dotnet_diagnostic.ca1509.severity = warning # Invalid entry in code metrics configuration file
|
||||||
|
dotnet_diagnostic.ca1861.severity = suggestion # Prefer 'static readonly' fields over constant array arguments if the called method is called repeatedly and is not mutating the passed array (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1861)
|
||||||
|
|
||||||
|
|
||||||
|
# Performance rules
|
||||||
|
dotnet_diagnostic.ca1849.severity = suggestion # Call async methods when in an async method: May decrease performance
|
||||||
|
dotnet_diagnostic.ca1822.severity = suggestion # Mark member as static
|
||||||
|
dotnet_diagnostic.ca1859.severity = suggestion # Use concrete types when possible for improved performance
|
||||||
|
|
||||||
|
# Design rule
|
||||||
|
dotnet_diagnostic.ca1002.severity = suggestion # Do not expose generic lists
|
||||||
|
dotnet_diagnostic.ca1051.severity = warning # Do not declare visible instance fields
|
||||||
|
dotnet_diagnostic.ca1056.severity = suggestion # URI properties should not be strings
|
||||||
|
dotnet_diagnostic.ca1062.severity = none # Public method must check all parameters for null
|
||||||
|
|
||||||
|
# Naming
|
||||||
|
dotnet_diagnostic.ca1707.severity = none # Remove underscores in names
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
dotnet_diagnostic.ca2227.severity = suggestion # Collection props should be read-only
|
||||||
|
|
||||||
|
dotnet_code_quality.ca1051.exclude_structs = true # CA1051 is excluded in structs
|
||||||
|
dotnet_code_quality.dispose_ownership_transfer_at_constructor = true # CA2000 has a lot of false positives without this
|
||||||
|
dotnet_code_quality.dispose_ownership_transfer_at_method_call = true # CA2000 has a lot of false positives without this
|
||||||
|
dotnet_code_quality.dispose_analysis_kind = NonExceptionPathsOnlyNotDisposed # CA2000 has a lot of false positives without this
|
||||||
|
|
||||||
|
# NUnit
|
||||||
|
dotnet_diagnostic.NUnit2001.severity = warning # Consider using Assert.That(expr, Is.False) instead of Assert.False(expr)
|
||||||
|
dotnet_diagnostic.NUnit2002.severity = warning # Consider using Assert.That(expr, Is.False) instead of Assert.IsFalse(expr)
|
||||||
|
dotnet_diagnostic.NUnit2003.severity = warning # Consider using Assert.That(expr, Is.True) instead of Assert.IsTrue(expr)
|
||||||
|
dotnet_diagnostic.NUnit2004.severity = warning # Consider using Assert.That(expr, Is.True) instead of Assert.True(expr)
|
||||||
|
dotnet_diagnostic.NUnit2005.severity = warning # Consider using Assert.That(actual, Is.EqualTo(expected)) instead of Assert.AreEqual(expected, actual)
|
||||||
|
dotnet_diagnostic.NUnit2006.severity = warning # Consider using Assert.That(actual, Is.Not.EqualTo(expected)) instead of Assert.AreNotEqual(expected, actual)
|
||||||
|
|
||||||
|
dotnet_diagnostic.NUnit2010.severity = warning # Use EqualConstraint for better assertion messages in case of failure
|
||||||
|
dotnet_diagnostic.NUnit2011.severity = warning # Use ContainsConstraint for better assertion messages in case of failure
|
||||||
|
dotnet_diagnostic.NUnit2011.severity = warning # Use StartsWithConstraint for better assertion messages in case of failure
|
||||||
|
dotnet_diagnostic.NUnit2011.severity = warning # Use EndsWithConstraint for better assertion messages in case of failure
|
||||||
|
dotnet_diagnostic.NUnit2014.severity = warning # Use SomeItemsConstraint for better assertion messages in case of failure
|
||||||
|
|
||||||
|
dotnet_diagnostic.NUnit2015.severity = warning # Consider using Assert.That(actual, Is.SameAs(expected)) instead of Assert.AreSame(expected, actual)
|
||||||
|
dotnet_diagnostic.NUnit2016.severity = warning # Consider using Assert.That(expr, Is.Null) instead of Assert.Null(expr)
|
||||||
|
dotnet_diagnostic.NUnit2017.severity = warning # Consider using Assert.That(expr, Is.Null) instead of Assert.IsNull(expr)
|
||||||
|
dotnet_diagnostic.NUnit2018.severity = warning # Consider using Assert.That(expr, Is.Not.Null) instead of Assert.NotNull(expr)
|
||||||
|
dotnet_diagnostic.NUnit2028.severity = warning # Consider using Assert.That(actual, Is.GreaterThanOrEqualTo(expected)) instead of Assert.GreaterOrEqual(actual, expected)
|
||||||
|
dotnet_diagnostic.NUnit2027.severity = warning # Consider using Assert.That(actual, Is.GreaterThan(expected)) instead of Assert.Greater(actual, expected)
|
||||||
|
dotnet_diagnostic.NUnit2029.severity = warning # Consider using Assert.That(actual, Is.LessThan(expected)) instead of Assert.Less(actual, expected)
|
||||||
|
dotnet_diagnostic.NUnit2030.severity = warning # Consider using Assert.That(actual, Is.LessThanOrEqualTo(expected)) instead of Assert.LessOrEqual(actual, expected)
|
||||||
|
dotnet_diagnostic.NUnit2031.severity = warning # Consider using Assert.That(actual, Is.Not.SameAs(expected)) instead of Assert.AreNotSame(expected, actual)
|
||||||
|
dotnet_diagnostic.NUnit2032.severity = warning # Consider using Assert.That(expr, Is.Zero) instead of Assert.Zero(expr)
|
||||||
|
dotnet_diagnostic.NUnit2033.severity = warning # Consider using Assert.That(expr, Is.Not.Zero) instead of Assert.NotZero(expr)
|
||||||
|
dotnet_diagnostic.NUnit2034.severity = warning # Consider using Assert.That(expr, Is.NaN) instead of Assert.IsNaN(expr)
|
||||||
|
dotnet_diagnostic.NUnit2035.severity = warning # Consider using Assert.That(collection, Is.Empty) instead of Assert.IsEmpty(collection)
|
||||||
|
dotnet_diagnostic.NUnit2036.severity = warning # Consider using Assert.That(collection, Is.Not.Empty) instead of Assert.IsNotEmpty(collection)
|
||||||
|
dotnet_diagnostic.NUnit2037.severity = warning # Consider using Assert.That(collection, Does.Contain(instance)) instead of Assert.Contains(instance, collection)
|
||||||
|
dotnet_diagnostic.NUnit2038.severity = warning # Consider using Assert.That(actual, Is.InstanceOf(expected)) instead of Assert.IsInstanceOf(expected, actual)
|
||||||
|
dotnet_diagnostic.NUnit2039.severity = warning # Consider using Assert.That(actual, Is.Not.InstanceOf(expected)) instead of Assert.IsNotInstanceOf(expected, actual)
|
||||||
|
|
||||||
|
[*.{appxmanifest,asax,ascx,aspx,axaml,build,c,c++,cc,cginc,compute,cp,cpp,cs,cshtml,cu,cuh,cxx,dtd,fs,fsi,fsscript,fsx,fx,fxh,h,hh,hlsl,hlsli,hlslinc,hpp,hxx,inc,inl,ino,ipp,ixx,master,ml,mli,mpp,mq4,mq5,mqh,nuspec,paml,razor,resw,resx,shader,skin,tpp,usf,ush,vb,xaml,xamlx,xoml,xsd}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
tab_width = 2
|
||||||
|
|
||||||
|
# Verify
|
||||||
|
[*.{received,verified}.{json}]
|
||||||
|
charset = utf-8-bom
|
||||||
|
end_of_line = lf
|
||||||
|
indent_size = unset
|
||||||
|
indent_style = unset
|
||||||
|
insert_final_newline = false
|
||||||
|
tab_width = unset
|
||||||
|
trim_trailing_whitespace = false
|
||||||
@@ -14,22 +14,22 @@ appearance, race, religion, or sexual identity and orientation.
|
|||||||
Examples of behavior that contributes to creating a positive environment
|
Examples of behavior that contributes to creating a positive environment
|
||||||
include:
|
include:
|
||||||
|
|
||||||
* Using welcoming and inclusive language
|
- Using welcoming and inclusive language
|
||||||
* Being respectful of differing viewpoints and experiences
|
- Being respectful of differing viewpoints and experiences
|
||||||
* Gracefully accepting constructive criticism
|
- Gracefully accepting constructive criticism
|
||||||
* Focusing on what is best for the community
|
- Focusing on what is best for the community
|
||||||
* Showing empathy towards other community members
|
- Showing empathy towards other community members
|
||||||
|
|
||||||
Examples of unacceptable behavior by participants include:
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
- The use of sexualized language or imagery and unwelcome sexual attention or
|
||||||
advances
|
advances
|
||||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
- Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
* Public or private harassment
|
- Public or private harassment
|
||||||
* Publishing others' private information, such as a physical or electronic
|
- Publishing others' private information, such as a physical or electronic
|
||||||
address, without explicit permission
|
address, without explicit permission
|
||||||
* Other conduct which could reasonably be considered inappropriate in a
|
- Other conduct which could reasonably be considered inappropriate in a
|
||||||
professional setting
|
professional setting
|
||||||
|
|
||||||
## Our Responsibilities
|
## Our Responsibilities
|
||||||
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
# Speckle Contribution Guidelines
|
# Speckle Contribution Guidelines
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
Thank you for reading this! Speckle's a rather wide network of parts that depend on each other, either directly, indirectly or even just cosmetically.
|
Thank you for reading this! Speckle's a rather wide network of parts that depend on each other, either directly, indirectly or even just cosmetically.
|
||||||
@@ -42,8 +43,8 @@ Why? However trivial the changes might seem, there might be subtle reasons for t
|
|||||||
|
|
||||||
> **Examples**: modifying the colour of an UI element in one client may have a big hidden cost and need propagation in several other clients that implement a similar ui element. Changing the default port or specifiying `localhost` instead of `0.0.0.0` breaks cross-vm debugging and developing.
|
> **Examples**: modifying the colour of an UI element in one client may have a big hidden cost and need propagation in several other clients that implement a similar ui element. Changing the default port or specifiying `localhost` instead of `0.0.0.0` breaks cross-vm debugging and developing.
|
||||||
|
|
||||||
|
|
||||||
## Wrap up
|
## Wrap up
|
||||||
Don't worry if you get things wrong. We all do, including project owners: this document should've been here a long time ago. There's plenty of room for discussion either on our community [forum](https://discourse.speckle.works) or [chat](https://speckle-works.slack.com/join/shared_invite/enQtNjY5Mzk2NTYxNTA4LTU4MWI5ZjdhMjFmMTIxZDIzOTAzMzRmMTZhY2QxMmM1ZjVmNzJmZGMzMDVlZmJjYWQxYWU0MWJkYmY3N2JjNGI).
|
|
||||||
|
Don't worry if you get things wrong. We all do, including project owners: this document should've been here a long time ago. There's plenty of room for discussion on our community [forum](https://discourse.speckle.works).
|
||||||
|
|
||||||
🙌❤️💙💚💜🙌
|
🙌❤️💙💚💜🙌
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Help improve Speckle!
|
||||||
|
title: ''
|
||||||
|
labels: bug
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
<!---
|
||||||
|
|
||||||
|
Provide a short summary in the Title above. Examples of good Issue titles:
|
||||||
|
|
||||||
|
* "Bug: Error from server when reticulating splines"
|
||||||
|
* "Bug: Revit crashes when installing connector"
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
<!---
|
||||||
|
|
||||||
|
Please answer the following questions before submitting an issue.
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
- [ ] I read the [contribution guidelines](https://github.com/specklesystems/speckle-server/blob/main/CONTRIBUTING.md)
|
||||||
|
- [ ] I checked the [documentation](https://speckle.guide/) and found no answer.
|
||||||
|
- [ ] I checked [existing issues](../issues?q=is%3Aissue) and found no similar issue. <!-- If you do find an existing issue, please show your support by liking it :+1: instead of creating a new issue -->
|
||||||
|
- [ ] I checked the [community forum](https://speckle.community/) for related discussions and found no answer.
|
||||||
|
- [ ] I'm reporting the issue to the correct repository (see also [speckle-server](https://github.com/specklesystems/speckle-server), [speckle-sharp](https://github.com/specklesystems/speckle-sharp), [specklepy](https://github.com/specklesystems/specklepy), [speckle-docs](https://github.com/specklesystems/speckle-docs), and [others](https://github.com/orgs/specklesystems/repositories))
|
||||||
|
|
||||||
|
## What package are you referring to?
|
||||||
|
|
||||||
|
<!---
|
||||||
|
Is it related to the server (backend) only, or does this bug relate to the frontend, viewer, objectloader or any other package?
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Describe the bug
|
||||||
|
|
||||||
|
<!---
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## To Reproduce
|
||||||
|
|
||||||
|
<!---
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Expected behavior
|
||||||
|
|
||||||
|
<!---
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|
<!---
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## System Info
|
||||||
|
|
||||||
|
If applicable, please fill in the below details - they help a lot!
|
||||||
|
|
||||||
|
### Desktop (please complete the following information):
|
||||||
|
|
||||||
|
- OS: [e.g. iOS]
|
||||||
|
- Browser [e.g. chrome, safari]
|
||||||
|
- Version [e.g. 22]
|
||||||
|
|
||||||
|
### Smartphone (please complete the following information):
|
||||||
|
|
||||||
|
- Device: [e.g. iPhone6]
|
||||||
|
- OS: [e.g. iOS8.1]
|
||||||
|
- Browser [e.g. stock browser, safari]
|
||||||
|
- Version [e.g. 22]
|
||||||
|
|
||||||
|
## Failure Logs
|
||||||
|
|
||||||
|
<!---
|
||||||
|
Please include any relevant log snippets or files here, or upload as a file.
|
||||||
|
|
||||||
|
If including inline, please use markdown code block syntax. https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
your log output here
|
||||||
|
```
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Additional context
|
||||||
|
|
||||||
|
<!---
|
||||||
|
Add any other context about the problem here.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Proposed Solution (if any)
|
||||||
|
|
||||||
|
<!---
|
||||||
|
Let us know what how you would solve this.
|
||||||
|
-->
|
||||||
|
|
||||||
|
#### Optional: Affected Projects
|
||||||
|
|
||||||
|
<!---
|
||||||
|
Does this issue propagate to other dependencies or dependents? If so, list them here with links!
|
||||||
|
-->
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for Speckle!
|
||||||
|
title: ''
|
||||||
|
labels: enhancement, question
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
<!---
|
||||||
|
|
||||||
|
Provide a short summary in the Title above. Examples of good Issue titles:
|
||||||
|
|
||||||
|
* "Enhancement: Connector for Minecraft"
|
||||||
|
* "Enhancement: Web viewer should support tesseracts"
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
<!---
|
||||||
|
|
||||||
|
Please answer the following questions before submitting an issue.
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
- [ ] I read the [contribution guidelines](https://github.com/specklesystems/speckle-server/blob/main/CONTRIBUTING.md)
|
||||||
|
- [ ] I checked the [documentation](https://speckle.guide/) and found no answer.
|
||||||
|
- [ ] I checked [existing issues](../issues?q=is%3Aissue) and found no similar issue. <!-- If you do find an existing issue, please show your support by liking it :+1: instead of creating a new issue -->
|
||||||
|
- [ ] I checked the [community forum](https://speckle.community/) for related discussions and found no answer.
|
||||||
|
- [ ] I'm requesting the feature to the correct repository (see also [speckle-server](https://github.com/specklesystems/speckle-server), [speckle-sharp](https://github.com/specklesystems/speckle-sharp), [specklepy](https://github.com/specklesystems/specklepy), [speckle-docs](https://github.com/specklesystems/speckle-docs), and [others](https://github.com/orgs/specklesystems/repositories))
|
||||||
|
|
||||||
|
## What package are you referring to?
|
||||||
|
|
||||||
|
<!---
|
||||||
|
Is it related to the server (backend) only, or does this feature request relate to the frontend, viewer, objectloader or any other package?
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Is your feature request related to a problem? Please describe.
|
||||||
|
|
||||||
|
<!---
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Describe the solution you'd like
|
||||||
|
|
||||||
|
<!---
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Describe alternatives you've considered
|
||||||
|
|
||||||
|
<!---
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Additional context
|
||||||
|
|
||||||
|
<!---
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
|
|
||||||
|
Have you seen this feature implemented in any other software? Can you provide screenshots or links to video or documentation?
|
||||||
|
What works well about these existing features in other software? What doesn't work well?
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Related issues or community discussions
|
||||||
|
|
||||||
|
<!---
|
||||||
|
Is this feature request related to (but sufficiently distinct from) any existing issues?
|
||||||
|
Does this feature request require other features to be available beforehand?
|
||||||
|
Has this feature been discussed in the community forum, please link here? https://speckle.community/
|
||||||
|
-->
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
<!---
|
||||||
|
|
||||||
|
Provide a short summary in the Title above. Examples of good PR titles:
|
||||||
|
|
||||||
|
* "Feature: adds metrics to component"
|
||||||
|
|
||||||
|
* "Fix: resolves duplication in comment thread"
|
||||||
|
|
||||||
|
* "Update: apollo v2.34.0"
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Description & motivation
|
||||||
|
|
||||||
|
<!---
|
||||||
|
|
||||||
|
Describe your changes, and why you're making them. What benefit will this have to others?
|
||||||
|
|
||||||
|
Is this linked to an open Github issue, a thread in Speckle community,
|
||||||
|
or another pull request? Link it here.
|
||||||
|
|
||||||
|
If it is related to a Github issue, and resolves it, please link to the issue number, e.g.:
|
||||||
|
Fixes #85, Fixes #22, Fixes username/repo#123
|
||||||
|
Connects #123
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Changes:
|
||||||
|
|
||||||
|
<!---
|
||||||
|
|
||||||
|
- Item 1
|
||||||
|
- Item 2
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
## To-do before merge
|
||||||
|
|
||||||
|
<!---
|
||||||
|
|
||||||
|
(Optional -- remove this section if not needed)
|
||||||
|
|
||||||
|
Include any notes about things that need to happen before this PR is merged, e.g.:
|
||||||
|
|
||||||
|
- [ ] Change the base branch
|
||||||
|
|
||||||
|
- [ ] Ensure PR #56 is merged
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Screenshots:
|
||||||
|
|
||||||
|
<!---
|
||||||
|
|
||||||
|
Include a screenshot the before and after. This can be a screenshot of a plugin, web frontend, or output in a terminal.
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Validation of changes:
|
||||||
|
|
||||||
|
<!---
|
||||||
|
|
||||||
|
Describe what tests have been added or amended, and why these demonstrate it works and will prevent this feature being accidentally broken by future changes.
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Checklist:
|
||||||
|
|
||||||
|
<!---
|
||||||
|
|
||||||
|
This checklist is mostly useful as a reminder of small things that can easily be
|
||||||
|
|
||||||
|
forgotten – it is meant as a helpful tool rather than hoops to jump through.
|
||||||
|
|
||||||
|
Put an `x` in all the items that apply, make notes next to any that haven't been
|
||||||
|
|
||||||
|
addressed, and remove any items that are not relevant to this PR.
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
- [ ] My pull request follows the guidelines in the [Contributing guide](https://github.com/specklesystems/speckle-server/blob/main/CONTRIBUTING.md)?
|
||||||
|
- [ ] My pull request does not duplicate any other open [Pull Requests](../../pulls) for the same update/change?
|
||||||
|
- [ ] My commits are related to the pull request and do not amend unrelated code or documentation.
|
||||||
|
- [ ] My code follows a similar style to existing code.
|
||||||
|
- [ ] I have added appropriate tests.
|
||||||
|
- [ ] I have updated or added relevant documentation.
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
name: .NET Build and Publish
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
tags: ["v*.*.*"]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
env:
|
||||||
|
SOLUTION_NAME: "GrasshopperAsyncComponent.sln"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup .NET
|
||||||
|
uses: actions/setup-dotnet@v4
|
||||||
|
with:
|
||||||
|
dotnet-version: 8.x.x
|
||||||
|
|
||||||
|
- id: set-version
|
||||||
|
name: Set version to output
|
||||||
|
run: |
|
||||||
|
TAG=${{ github.ref_name }}
|
||||||
|
if [[ "${{ github.ref }}" != refs/tags/* ]]; then
|
||||||
|
TAG="v0.0.99.${{ github.run_number }}"
|
||||||
|
fi
|
||||||
|
SEMVER="${TAG#v}"
|
||||||
|
FILE_VERSION=$(echo "$TAG" | sed -E 's/^v([0-9]+\.[0-9]+\.[0-9]+).*/\1/')
|
||||||
|
FILE_VERSION="$FILE_VERSION.${{ github.run_number }}"
|
||||||
|
|
||||||
|
echo "semver=$SEMVER" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "fileVersion=$FILE_VERSION" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
echo $SEMVER
|
||||||
|
echo $FILE_VERSION
|
||||||
|
|
||||||
|
- name: restore
|
||||||
|
run: dotnet restore ${{env.SOLUTION_NAME}}
|
||||||
|
|
||||||
|
- name: build
|
||||||
|
run: |
|
||||||
|
dotnet build ${{env.SOLUTION_NAME}} \
|
||||||
|
--configuration release \
|
||||||
|
--no-restore \
|
||||||
|
-warnaserror \
|
||||||
|
-p:Version=${{steps.set-version.outputs.semver}} \
|
||||||
|
-p:FileVersion=${{steps.set-version.outputs.fileVersion}}
|
||||||
|
|
||||||
|
- name: pack
|
||||||
|
run: dotnet pack ${{env.SOLUTION_NAME}} --no-build -p:Version=${{steps.set-version.outputs.semver}} -p:FileVersion=${{steps.set-version.outputs.fileVersion}}
|
||||||
|
|
||||||
|
- name: Push to nuget.org
|
||||||
|
if: (github.ref_type == 'tag')
|
||||||
|
run: dotnet nuget push **/*.nupkg --source "https://api.nuget.org/v3/index.json" --api-key ${{secrets.CONNECTORS_NUGET_TOKEN }} --skip-duplicate
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
CA1502: 25
|
||||||
|
CA1501: 5
|
||||||
|
CA1506(Method): 50
|
||||||
|
CA1506(Type): 95
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
<Project>
|
||||||
|
<PropertyGroup Label="Compiler Properties">
|
||||||
|
<LangVersion>12</LangVersion>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Label="Nugetspec Package Properties">
|
||||||
|
<!-- Defines common Nugetspec properties -->
|
||||||
|
<!-- Inheriting packable projects should define the rest of the nugetspec properties (PackageId, Description) -->
|
||||||
|
<!-- and may, if needed, override/extend any of these (e.g. PackageTags) -->
|
||||||
|
<Authors>Speckle</Authors>
|
||||||
|
<Copyright>Copyright (c) AEC Systems Ltd</Copyright>
|
||||||
|
<PackageProjectUrl>https://speckle.systems/</PackageProjectUrl>
|
||||||
|
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||||
|
<RepositoryUrl>https://github.com/specklesystems/GrasshopperAsyncComponent</RepositoryUrl>
|
||||||
|
<RepositoryType>git</RepositoryType>
|
||||||
|
<PackageTags>speckle</PackageTags>
|
||||||
|
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Label="Nuget Package Properties">
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<!--Can be set to true in inheriting .props/.csproj files for projects that should be packed-->
|
||||||
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
|
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||||
|
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
|
||||||
|
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Label="Analyers">
|
||||||
|
<EnableNetAnalyzers>true</EnableNetAnalyzers>
|
||||||
|
<AnalysisLevel>latest-AllEnabledByDefault</AnalysisLevel>
|
||||||
|
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||||
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
|
<!-- Ingored warnings, some aspirational but too noisy for now, some by design. -->
|
||||||
|
<NoWarn>
|
||||||
|
<!--XML comment-->
|
||||||
|
CS1591;CS1573;
|
||||||
|
<!-- Globalization rules -->
|
||||||
|
CA1303;CA1304;CA1305;CA1307;CA1308;CA1309;CA1310;CA1311;
|
||||||
|
<!-- Logging -->
|
||||||
|
CA1848;CA1727;
|
||||||
|
$(NoWarn)
|
||||||
|
</NoWarn
|
||||||
|
>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<!-- Expose the repository root to all projects -->
|
||||||
|
<RepositoryRoot>$(MSBuildThisFileDirectory)</RepositoryRoot>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="..\README.md" Pack="true" PackagePath="\" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<!-- This file contains the configuration for some analyzer warnings, such as cyclomatic
|
||||||
|
complexity threshold -->
|
||||||
|
<AdditionalFiles Include="$(RepositoryRoot)CodeMetricsConfig.txt" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@@ -7,6 +7,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GrasshopperAsyncComponent",
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GrasshopperAsyncComponentDemo", "GrasshopperAsyncComponentDemo\GrasshopperAsyncComponentDemo.csproj", "{695D2B91-DDB6-416E-8A99-DDE6253DA7AA}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GrasshopperAsyncComponentDemo", "GrasshopperAsyncComponentDemo\GrasshopperAsyncComponentDemo.csproj", "{695D2B91-DDB6-416E-8A99-DDE6253DA7AA}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "config", "config", "{B84A4AEC-CAA4-4065-89A4-E7FBB3889D25}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
Directory.Build.props = Directory.Build.props
|
||||||
|
.editorconfig = .editorconfig
|
||||||
|
.csharpierrc.yaml = .csharpierrc.yaml
|
||||||
|
CodeMetricsConfig.txt = CodeMetricsConfig.txt
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|||||||
@@ -1,249 +1,293 @@
|
|||||||
using Grasshopper.Kernel;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using Grasshopper.Kernel;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Timer = System.Timers.Timer;
|
using Timer = System.Timers.Timer;
|
||||||
|
|
||||||
namespace GrasshopperAsyncComponent
|
namespace GrasshopperAsyncComponent;
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Inherit your component from this class to make all the async goodness available.
|
|
||||||
/// </summary>
|
|
||||||
public abstract class GH_AsyncComponent : GH_Component
|
|
||||||
{
|
|
||||||
public override Guid ComponentGuid => throw new Exception("ComponentGuid should be overriden in any descendant of GH_AsyncComponent!");
|
|
||||||
|
|
||||||
|
internal sealed class Worker<T> : IDisposable
|
||||||
|
where T : GH_Component
|
||||||
|
{
|
||||||
|
public required WorkerInstance<T> Instance { get; init; }
|
||||||
|
|
||||||
|
public required Task Task { get; init; }
|
||||||
|
|
||||||
|
public required CancellationTokenSource CancellationSource { get; init; }
|
||||||
|
|
||||||
|
public void Cancel() => CancellationSource.Cancel();
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (Task.IsCompleted)
|
||||||
|
{
|
||||||
|
Task.Dispose();
|
||||||
|
}
|
||||||
|
CancellationSource.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inherit your component from this class to make all the async goodness available.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class GH_AsyncComponent<T> : GH_Component, IDisposable
|
||||||
|
where T : GH_Component
|
||||||
|
{
|
||||||
//List<(string, GH_RuntimeMessageLevel)> Errors;
|
//List<(string, GH_RuntimeMessageLevel)> Errors;
|
||||||
|
|
||||||
Action<string, double> ReportProgress;
|
private readonly Action<string, double> _reportProgress;
|
||||||
|
|
||||||
public ConcurrentDictionary<string, double> ProgressReports;
|
public ConcurrentDictionary<string, double> ProgressReports { get; }
|
||||||
|
|
||||||
Action Done;
|
private readonly Timer _displayProgressTimer;
|
||||||
|
|
||||||
Timer DisplayProgressTimer;
|
/// <summary>
|
||||||
|
/// a counter, used to count up the number of workers that have completed,
|
||||||
|
/// until _setData is set true, when it starts to count down the workers as their data is set.
|
||||||
|
/// </summary>
|
||||||
|
private volatile int _state;
|
||||||
|
|
||||||
int State = 0;
|
/// <summary>
|
||||||
|
/// functionally, a boolean, 1 or 0;
|
||||||
|
/// it will be set to 1 once all workers are ready for SetData to be called on them, then set back to 0.
|
||||||
|
/// </summary>
|
||||||
|
private volatile int _setData;
|
||||||
|
|
||||||
int SetData = 0;
|
private readonly List<Worker<T>> _workers;
|
||||||
|
|
||||||
public List<WorkerInstance> Workers;
|
public int WorkerCount => _workers.Count;
|
||||||
|
|
||||||
List<Task> Tasks;
|
|
||||||
|
|
||||||
public readonly List<CancellationTokenSource> CancellationSources;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set this property inside the constructor of your derived component.
|
/// Set this property inside the constructor of your derived component.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public WorkerInstance BaseWorker { get; set; }
|
public WorkerInstance<T>? BaseWorker { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Optional: if you have opinions on how the default system task scheduler should treat your workers, set it here.
|
/// Optional: if you have opinions on how the default system task scheduler should treat your workers, set it here.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TaskCreationOptions? TaskCreationOptions { get; set; } = null;
|
public TaskCreationOptions TaskCreationOptions { get; set; } = TaskCreationOptions.None;
|
||||||
|
|
||||||
protected GH_AsyncComponent(string name, string nickname, string description, string category, string subCategory) : base(name, nickname, description, category, subCategory)
|
protected GH_AsyncComponent(string name, string nickname, string description, string category, string subCategory)
|
||||||
|
: base(name, nickname, description, category, subCategory)
|
||||||
{
|
{
|
||||||
|
_workers = new List<Worker<T>>();
|
||||||
|
|
||||||
DisplayProgressTimer = new Timer(333) { AutoReset = false };
|
ProgressReports = new ConcurrentDictionary<string, double>();
|
||||||
DisplayProgressTimer.Elapsed += DisplayProgress;
|
|
||||||
|
|
||||||
ReportProgress = (id, value) =>
|
_displayProgressTimer = new Timer(333) { AutoReset = false };
|
||||||
{
|
_displayProgressTimer.Elapsed += DisplayProgress;
|
||||||
ProgressReports[id] = value;
|
|
||||||
if (!DisplayProgressTimer.Enabled)
|
_reportProgress = (id, value) =>
|
||||||
{
|
{
|
||||||
DisplayProgressTimer.Start();
|
ProgressReports[id] = value;
|
||||||
}
|
if (!_displayProgressTimer.Enabled)
|
||||||
};
|
{
|
||||||
|
_displayProgressTimer.Start();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Done = () =>
|
private void Done()
|
||||||
{
|
{
|
||||||
Interlocked.Increment(ref State);
|
Interlocked.Increment(ref _state);
|
||||||
if (State == Workers.Count && SetData == 0)
|
if (_state == _workers.Count && _setData == 0)
|
||||||
{
|
{
|
||||||
Interlocked.Exchange(ref SetData, 1);
|
Interlocked.Exchange(ref _setData, 1);
|
||||||
|
|
||||||
// We need to reverse the workers list to set the outputs in the same order as the inputs.
|
// We need to reverse the workers list to set the outputs in the same order as the inputs.
|
||||||
Workers.Reverse();
|
_workers.Reverse();
|
||||||
|
|
||||||
Rhino.RhinoApp.InvokeOnUiThread((Action)delegate
|
Rhino.RhinoApp.InvokeOnUiThread(
|
||||||
{
|
(Action)
|
||||||
ExpireSolution(true);
|
delegate
|
||||||
});
|
{
|
||||||
|
ExpireSolution(true);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
ProgressReports = new ConcurrentDictionary<string, double>();
|
|
||||||
|
|
||||||
Workers = new List<WorkerInstance>();
|
|
||||||
CancellationSources = new List<CancellationTokenSource>();
|
|
||||||
Tasks = new List<Task>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void DisplayProgress(object sender, System.Timers.ElapsedEventArgs e)
|
public virtual void DisplayProgress(object sender, System.Timers.ElapsedEventArgs e)
|
||||||
{
|
{
|
||||||
if (Workers.Count == 0 || ProgressReports.Values.Count == 0)
|
if (_workers.Count == 0 || ProgressReports.Values.Count == 0)
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Workers.Count == 1)
|
|
||||||
{
|
|
||||||
Message = ProgressReports.Values.Last().ToString("0.00%");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
double total = 0;
|
|
||||||
foreach (var kvp in ProgressReports)
|
|
||||||
{
|
{
|
||||||
total += kvp.Value;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Message = (total / Workers.Count).ToString("0.00%");
|
if (_workers.Count == 1)
|
||||||
}
|
{
|
||||||
|
Message = ProgressReports.Values.Last().ToString("0.00%");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double total = 0;
|
||||||
|
foreach (var kvp in ProgressReports)
|
||||||
|
{
|
||||||
|
total += kvp.Value;
|
||||||
|
}
|
||||||
|
|
||||||
Rhino.RhinoApp.InvokeOnUiThread((Action)delegate
|
Message = (total / _workers.Count).ToString("0.00%");
|
||||||
{
|
}
|
||||||
OnDisplayExpired(true);
|
|
||||||
});
|
Rhino.RhinoApp.InvokeOnUiThread(
|
||||||
|
(Action)
|
||||||
|
delegate
|
||||||
|
{
|
||||||
|
OnDisplayExpired(true);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void BeforeSolveInstance()
|
protected override void BeforeSolveInstance()
|
||||||
{
|
{
|
||||||
if (State != 0 && SetData == 1)
|
if (_state != 0 && _setData == 1)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.WriteLine("Killing");
|
Debug.WriteLine("Killing");
|
||||||
|
|
||||||
foreach (var source in CancellationSources)
|
foreach (var currentWorker in _workers)
|
||||||
{
|
{
|
||||||
source.Cancel();
|
currentWorker.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
CancellationSources.Clear();
|
ResetState();
|
||||||
Workers.Clear();
|
|
||||||
ProgressReports.Clear();
|
|
||||||
Tasks.Clear();
|
|
||||||
|
|
||||||
Interlocked.Exchange(ref State, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void AfterSolveInstance()
|
protected override void AfterSolveInstance()
|
||||||
{
|
{
|
||||||
System.Diagnostics.Debug.WriteLine("After solve instance was called " + State + " ? " + Workers.Count);
|
Debug.WriteLine("After solve instance was called " + _state + " ? " + _workers.Count);
|
||||||
// We need to start all the tasks as close as possible to each other.
|
// We need to start all the tasks as close as possible to each other.
|
||||||
if (State == 0 && Tasks.Count > 0 && SetData == 0)
|
if (_state == 0 && _workers.Count > 0 && _setData == 0)
|
||||||
{
|
|
||||||
System.Diagnostics.Debug.WriteLine("After solve INVOKATIONM");
|
|
||||||
foreach (var task in Tasks)
|
|
||||||
{
|
{
|
||||||
task.Start();
|
Debug.WriteLine("After solve INVOCATION");
|
||||||
|
foreach (var worker in _workers)
|
||||||
|
{
|
||||||
|
worker.Task.Start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ExpireDownStreamObjects()
|
protected override void ExpireDownStreamObjects()
|
||||||
{
|
{
|
||||||
// Prevents the flash of null data until the new solution is ready
|
// Prevents the flash of null data until the new solution is ready
|
||||||
if (SetData == 1)
|
if (_setData == 1)
|
||||||
{
|
{
|
||||||
base.ExpireDownStreamObjects();
|
base.ExpireDownStreamObjects();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void SolveInstance(IGH_DataAccess DA)
|
protected override void SolveInstance(IGH_DataAccess DA)
|
||||||
{
|
{
|
||||||
//return;
|
//return;
|
||||||
if (State == 0)
|
if (_state == 0)
|
||||||
{
|
|
||||||
if (BaseWorker == null)
|
|
||||||
{
|
{
|
||||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Worker class not provided.");
|
if (BaseWorker == null)
|
||||||
return;
|
{
|
||||||
|
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Worker class not provided.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add cancellation source to our bag
|
||||||
|
var tokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
|
var currentWorker = BaseWorker.Duplicate($"Worker-{DA.Iteration}", tokenSource.Token);
|
||||||
|
|
||||||
|
// Let the worker collect data.
|
||||||
|
currentWorker.GetData(DA, Params);
|
||||||
|
|
||||||
|
var currentRun = new Task<Task>(
|
||||||
|
async () =>
|
||||||
|
{
|
||||||
|
await currentWorker.DoWork(_reportProgress, Done).ConfigureAwait(true);
|
||||||
|
},
|
||||||
|
tokenSource.Token,
|
||||||
|
TaskCreationOptions
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add the worker to our list
|
||||||
|
_workers.Add(
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Instance = currentWorker,
|
||||||
|
Task = currentRun,
|
||||||
|
CancellationSource = tokenSource,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentWorker = BaseWorker.Duplicate();
|
if (_setData == 0)
|
||||||
if (currentWorker == null)
|
|
||||||
{
|
{
|
||||||
AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Could not get a worker instance.");
|
return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the worker collect data.
|
if (_workers.Count > 0)
|
||||||
currentWorker.GetData(DA, Params);
|
{
|
||||||
|
Interlocked.Decrement(ref _state);
|
||||||
|
_workers[_state].Instance.SetData(DA);
|
||||||
|
}
|
||||||
|
|
||||||
// Create the task
|
if (_state != 0)
|
||||||
var tokenSource = new CancellationTokenSource();
|
{
|
||||||
currentWorker.CancellationToken = tokenSource.Token;
|
return;
|
||||||
currentWorker.Id = $"Worker-{DA.Iteration}";
|
}
|
||||||
|
|
||||||
var currentRun = TaskCreationOptions != null
|
foreach (var worker in _workers)
|
||||||
? new Task(() => currentWorker.DoWork(ReportProgress, Done), tokenSource.Token, (TaskCreationOptions)TaskCreationOptions)
|
{
|
||||||
: new Task(() => currentWorker.DoWork(ReportProgress, Done), tokenSource.Token);
|
worker?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
// Add cancellation source to our bag
|
ResetState();
|
||||||
CancellationSources.Add(tokenSource);
|
|
||||||
|
|
||||||
// Add the worker to our list
|
Message = "Done";
|
||||||
Workers.Add(currentWorker);
|
OnDisplayExpired(true);
|
||||||
|
}
|
||||||
|
|
||||||
Tasks.Add(currentRun);
|
private void ResetState()
|
||||||
|
{
|
||||||
|
_workers.Clear();
|
||||||
|
ProgressReports.Clear();
|
||||||
|
|
||||||
return;
|
Interlocked.Exchange(ref _state, 0);
|
||||||
}
|
Interlocked.Exchange(ref _setData, 0);
|
||||||
|
|
||||||
if (SetData == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Workers.Count > 0)
|
|
||||||
{
|
|
||||||
Interlocked.Decrement(ref State);
|
|
||||||
Workers[State].SetData(DA);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (State != 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CancellationSources.Clear();
|
|
||||||
Workers.Clear();
|
|
||||||
ProgressReports.Clear();
|
|
||||||
Tasks.Clear();
|
|
||||||
|
|
||||||
Interlocked.Exchange(ref SetData, 0);
|
|
||||||
|
|
||||||
Message = "Done";
|
|
||||||
OnDisplayExpired(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RequestCancellation()
|
public void RequestCancellation()
|
||||||
{
|
{
|
||||||
foreach (var source in CancellationSources)
|
foreach (var worker in _workers)
|
||||||
{
|
{
|
||||||
source.Cancel();
|
worker.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
CancellationSources.Clear();
|
ResetState();
|
||||||
Workers.Clear();
|
Message = "Cancelled";
|
||||||
ProgressReports.Clear();
|
OnDisplayExpired(true);
|
||||||
Tasks.Clear();
|
|
||||||
|
|
||||||
Interlocked.Exchange(ref State, 0);
|
|
||||||
Interlocked.Exchange(ref SetData, 0);
|
|
||||||
Message = "Cancelled";
|
|
||||||
OnDisplayExpired(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
private bool _isDisposed;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!_isDisposed)
|
||||||
|
{
|
||||||
|
_isDisposed = true;
|
||||||
|
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
foreach (var worker in _workers)
|
||||||
|
{
|
||||||
|
worker?.Dispose();
|
||||||
|
}
|
||||||
|
_displayProgressTimer?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,68 +1,43 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<PropertyGroup Label="Compiler Properties">
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
<TargetFrameworks>net462;net48</TargetFrameworks>
|
||||||
<PropertyGroup>
|
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
|
||||||
<ProjectGuid>{114D5E49-AC13-47F7-A70E-B4289579F4E3}</ProjectGuid>
|
|
||||||
<OutputType>Library</OutputType>
|
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
|
||||||
<RootNamespace>GrasshopperAsyncComponent</RootNamespace>
|
<RootNamespace>GrasshopperAsyncComponent</RootNamespace>
|
||||||
<AssemblyName>GrasshopperAsyncComponent</AssemblyName>
|
<AssemblyName>GrasshopperAsyncComponent</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
|
||||||
<FileAlignment>512</FileAlignment>
|
|
||||||
<TargetFrameworkProfile />
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
|
||||||
|
<PropertyGroup Label="Nugetspec Package Properties">
|
||||||
|
<PackageId>GrasshopperAsyncComponent</PackageId>
|
||||||
|
<Title>Grasshopper Async Component</Title>
|
||||||
|
<Description>Jankless Grasshopper Components</Description>
|
||||||
|
<PackageTags>grasshopper rhino mcneel gh_component</PackageTags>
|
||||||
|
<ProjectGuid>{114D5E49-AC13-47F7-A70E-B4289579F4E3}</ProjectGuid>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Label="Nuget Package Properties">
|
||||||
|
<IsPackable>true</IsPackable>
|
||||||
<IncludeSymbols>true</IncludeSymbols>
|
<IncludeSymbols>true</IncludeSymbols>
|
||||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
<ItemGroup Label="Package References">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<PackageReference Include="PolySharp" Version="1.14.1" />
|
||||||
<DebugType>full</DebugType>
|
</ItemGroup>
|
||||||
<Optimize>false</Optimize>
|
|
||||||
<OutputPath>bin\Debug\</OutputPath>
|
<ItemGroup Condition=" '$(TargetFramework)' == 'net462'">
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<PackageReference Include="Grasshopper" Version="6.28.20199.17141" IncludeAssets="compile;build" PrivateAssets="all" />
|
||||||
<ErrorReport>prompt</ErrorReport>
|
</ItemGroup>
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
|
<ItemGroup Condition=" '$(TargetFramework)' == 'net48'">
|
||||||
|
<PackageReference Include="Grasshopper" Version="7.4.21078.1001" IncludeAssets="compile;build" PrivateAssets="all" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System.Windows.Forms" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="$(Configuration) == 'Debug' AND $([MSBuild]::IsOSPlatform(Windows))">
|
||||||
|
<StartProgram>C:\Program Files\Rhino 7\System\Rhino.exe</StartProgram>
|
||||||
|
<StartAction>Program</StartAction>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<OutputPath>bin\Release\</OutputPath>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="System" />
|
|
||||||
<Reference Include="System.Core" />
|
|
||||||
<Reference Include="System.Data" />
|
|
||||||
<Reference Include="System.Xml" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="GH_AsyncComponent.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
|
||||||
<Compile Include="WorkerInstance.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Grasshopper">
|
|
||||||
<Version>6.33.20343.16431</Version>
|
|
||||||
<IncludeAssets>compile; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="RhinoCommon">
|
|
||||||
<Version>6.33.20343.16431</Version>
|
|
||||||
<IncludeAssets>compile; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
</PackageReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
|
||||||
<Target Name="BeforeBuild">
|
|
||||||
</Target>
|
|
||||||
<Target Name="AfterBuild">
|
|
||||||
</Target>
|
|
||||||
-->
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<package >
|
|
||||||
<metadata>
|
|
||||||
<id>GrasshopperAsyncComponent</id>
|
|
||||||
<version>1.2.2.0</version>
|
|
||||||
<title>GrasshopperAsyncComponent</title>
|
|
||||||
<authors>Speckle Systems</authors>
|
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
|
||||||
<license type="expression">Apache-2.0</license>
|
|
||||||
<projectUrl>https://github.com/specklesystems/GrasshopperAsyncComponent</projectUrl>
|
|
||||||
<description>Jankless Grasshopper Component</description>
|
|
||||||
<releaseNotes>Adds cancellation methods.</releaseNotes>
|
|
||||||
<copyright>Speckle Systems</copyright>
|
|
||||||
<tags>grasshopper rhino mcneel gh_component</tags>
|
|
||||||
</metadata>
|
|
||||||
</package>
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
|
||||||
// set of attributes. Change these attribute values to modify the information
|
|
||||||
// associated with an assembly.
|
|
||||||
[assembly: AssemblyTitle("GrasshopperAsyncComponent")]
|
|
||||||
[assembly: AssemblyDescription("Asyncronous Implementation of GH_Component for Grassshopper")]
|
|
||||||
[assembly: AssemblyConfiguration("")]
|
|
||||||
[assembly: AssemblyCompany("Speckle Systems")]
|
|
||||||
[assembly: AssemblyProduct("GrasshopperAsyncComponent")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright AEC Systems © 2020, 2021")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
|
|
||||||
// Setting ComVisible to false makes the types in this assembly not visible
|
|
||||||
// to COM components. If you need to access a type in this assembly from
|
|
||||||
// COM, set the ComVisible attribute to true on that type.
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
|
|
||||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
|
||||||
[assembly: Guid("114D5E49-AC13-47F7-A70E-B4289579F4E3")]
|
|
||||||
|
|
||||||
// Version information for an assembly consists of the following four values:
|
|
||||||
//
|
|
||||||
// Major Version
|
|
||||||
// Minor Version
|
|
||||||
// Build Number
|
|
||||||
// Revision
|
|
||||||
//
|
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
|
||||||
// by using the '*' as shown below:
|
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
|
||||||
[assembly: AssemblyVersion("1.2.2.0")]
|
|
||||||
[assembly: AssemblyFileVersion("1.2.2.0")]
|
|
||||||
@@ -1,66 +1,53 @@
|
|||||||
using Grasshopper.Kernel;
|
using Grasshopper.Kernel;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace GrasshopperAsyncComponent
|
namespace GrasshopperAsyncComponent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A class that holds the actual compute logic and encapsulates the state it needs. Every <see cref="GH_AsyncComponent{T}"/> needs to have one.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class WorkerInstance<T>(T parent, string id, CancellationToken cancellationToken)
|
||||||
|
where T : GH_Component
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A class that holds the actual compute logic and encapsulates the state it needs. Every <see cref="GH_AsyncComponent"/> needs to have one.
|
|
||||||
/// </summary>
|
|
||||||
public abstract class WorkerInstance
|
|
||||||
{
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The parent component. Useful for passing state back to the host component.
|
/// The parent component. Useful for passing state back to the host component.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public GH_Component Parent { get; set; }
|
public T Parent { get; set; } = parent;
|
||||||
|
|
||||||
/// <summary>
|
public CancellationToken CancellationToken { get; } = cancellationToken;
|
||||||
/// This token is set by the parent <see cref="GH_AsyncComponent"/>.
|
|
||||||
/// </summary>
|
|
||||||
public CancellationToken CancellationToken { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
public string Id { get; set; } = id;
|
||||||
/// This is set by the parent <see cref="GH_AsyncComponent"/>. You can set it yourself, but it's not really worth it.
|
|
||||||
/// </summary>
|
|
||||||
public string Id { get; set; }
|
|
||||||
|
|
||||||
protected WorkerInstance(GH_Component _parent)
|
|
||||||
{
|
|
||||||
Parent = _parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is a "factory" method. It should return a fresh instance of this class, but with all the necessary state that you might have passed on directly from your component.
|
/// This is a "factory" method. It should return a fresh instance of this class, but with all the necessary state that you might have passed on directly from your component.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="id">A Unique id for the new duplicate</param>
|
||||||
|
/// <param name="cancellationToken">A cancellationToken to be passed to the new duplicate</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public abstract WorkerInstance Duplicate();
|
public abstract WorkerInstance<T> Duplicate(string id, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This method is where the actual calculation/computation/heavy lifting should be done.
|
/// This method is where the actual calculation/computation/heavy lifting should be done.
|
||||||
/// <b>Make sure you always check as frequently as you can if <see cref="WorkerInstance.CancellationToken"/> is cancelled. For an example, see the <see cref="PrimeCalculatorWorker"/>.</b>
|
/// <b>Make sure you always check as frequently as you can if <see cref="WorkerInstance{T}.CancellationToken"/> is cancelled. For an example, see the PrimeCalculatorWorker example.</b>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ReportProgress">Call this to report progress up to the parent component.</param>
|
/// <remarks>
|
||||||
/// <param name="Done">Call this when everything is <b>done</b>. It will tell the parent component that you're ready to <see cref="SetData(IGH_DataAccess)"/>.</param>
|
/// If you don't need <see langword="async"/> function, then you can simply return <see cref="Task.CompletedTask"/>
|
||||||
public abstract void DoWork(Action<string, double> ReportProgress, Action Done);
|
/// Either way, you should be sure to handle exceptions in this function. Otherwise, they will be Unobserved!
|
||||||
|
/// You can call <paramref name="done"/> on <see cref="Exception"/>s, but avoid calling it when cancellation is has been observed.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="reportProgress">Call this to report progress up to the parent component.</param>
|
||||||
|
/// <param name="done">Call this when everything is <b>done</b>. It will tell the parent component that you're ready to <see cref="SetData(IGH_DataAccess)"/>.</param>
|
||||||
|
public abstract Task DoWork(Action<string, double> reportProgress, Action done);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Write your data setting logic here. <b>Do not call this function directly from this class. It will be invoked by the parent <see cref="GH_AsyncComponent"/> after you've called `Done` in the <see cref="DoWork(Action{string}, Action{string, GH_RuntimeMessageLevel}, Action)"/> function.</b>
|
/// Write your data setting logic here. <b>Do not call this function directly from this class. It will be invoked by the parent <see cref="GH_AsyncComponent{T}"/> after you've called `Done` in the <see cref="DoWork"/> function.</b>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="DA"></param>
|
/// <param name="da"></param>
|
||||||
public abstract void SetData(IGH_DataAccess DA);
|
public abstract void SetData(IGH_DataAccess da);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Write your data collection logic here. <b>Do not call this method directly. It will be invoked by the parent <see cref="GH_AsyncComponent"/>.</b>
|
/// Write your data collection logic here. <b>Do not call this method directly. It will be invoked by the parent <see cref="GH_AsyncComponent{T}"/>.</b>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="DA"></param>
|
/// <param name="da"></param>
|
||||||
/// <param name="Params"></param>
|
/// <param name="parameters"></param>
|
||||||
public abstract void GetData(IGH_DataAccess DA, GH_ComponentParamServer Params);
|
public abstract void GetData(IGH_DataAccess da, GH_ComponentParamServer parameters);
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,99 +1,32 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<TargetFramework>net48</TargetFramework>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<Version>1.0</Version>
|
||||||
<ProductVersion>8.0.30703</ProductVersion>
|
<Title>GrasshopperAsyncComponentDemo</Title>
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
<Description>Jankless Grasshopper Components Demo</Description>
|
||||||
<ProjectGuid>{695D2B91-DDB6-416E-8A99-DDE6253DA7AA}</ProjectGuid>
|
<TargetExt>.gha</TargetExt>
|
||||||
<OutputType>Library</OutputType>
|
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
|
||||||
<RootNamespace>GrasshopperAsyncComponentDemo</RootNamespace>
|
<RootNamespace>GrasshopperAsyncComponentDemo</RootNamespace>
|
||||||
<AssemblyName>GrasshopperAsyncComponentDemo</AssemblyName>
|
<AssemblyName>GrasshopperAsyncComponentDemo</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
<GenerateResourceUsePreserializedResources>true</GenerateResourceUsePreserializedResources>
|
||||||
<FileAlignment>512</FileAlignment>
|
<NeutralLanguage>en</NeutralLanguage>
|
||||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
|
||||||
<NuGetPackageImportStamp>
|
|
||||||
</NuGetPackageImportStamp>
|
|
||||||
<TargetFrameworkProfile />
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<Optimize>false</Optimize>
|
|
||||||
<OutputPath>bin\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<Optimize>true</Optimize>
|
|
||||||
<OutputPath>bin\</OutputPath>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Grasshopper" Version="7.4.21078.1001" IncludeAssets="compile;build" />
|
||||||
|
<PackageReference Include="System.Resources.Extensions" Version="7.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\GrasshopperAsyncComponent\GrasshopperAsyncComponent.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
|
||||||
<Reference Include="System.Core" />
|
|
||||||
<Reference Include="System.Data" />
|
|
||||||
<Reference Include="System.Xml" />
|
|
||||||
<Reference Include="System.Xml.Linq" />
|
|
||||||
<Reference Include="System.Drawing" />
|
|
||||||
<Reference Include="System.Windows.Forms" />
|
<Reference Include="System.Windows.Forms" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="Info\GrasshopperAsyncComponentInfo.cs" />
|
<PropertyGroup Condition="$(Configuration) == 'Debug' AND $([MSBuild]::IsOSPlatform(Windows))">
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<StartProgram>C:\Program Files\Rhino 7\System\Rhino.exe</StartProgram>
|
||||||
<Compile Include="Properties\Resources.Designer.cs">
|
|
||||||
<AutoGen>True</AutoGen>
|
|
||||||
<DesignTime>True</DesignTime>
|
|
||||||
<DependentUpon>Resources.resx</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="SampleImplementations\Sample_PrimeCalculatorAsyncComponent.cs" />
|
|
||||||
<Compile Include="SampleImplementations\Sample_UslessCyclesComponent.cs" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Grasshopper" Version="6.33.20343.16431" />
|
|
||||||
<PackageReference Include="RhinoCommon" Version="6.33.20343.16431" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\GrasshopperAsyncComponent\GrasshopperAsyncComponent.csproj">
|
|
||||||
<Project>{114d5e49-ac13-47f7-a70e-b4289579f4e3}</Project>
|
|
||||||
<Name>GrasshopperAsyncComponent</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedResource Include="Properties\Resources.resx">
|
|
||||||
<Generator>ResXFileCodeGenerator</Generator>
|
|
||||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
|
||||||
</EmbeddedResource>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Resources\logo32.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
|
||||||
<Target Name="BeforeBuild">
|
|
||||||
</Target>
|
|
||||||
<Target Name="AfterBuild">
|
|
||||||
</Target>
|
|
||||||
-->
|
|
||||||
<PropertyGroup Condition="$([MSBuild]::IsOsPlatform('Windows'))">
|
|
||||||
<PostBuildEvent>Copy "$(TargetPath)" "$(TargetDir)$(ProjectName).gha"</PostBuildEvent>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="$([MSBuild]::IsOsPlatform('OSX'))">
|
|
||||||
<PostBuildEvent>cp "$(TargetPath)" "$(TargetDir)$(ProjectName).gha"</PostBuildEvent>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup>
|
|
||||||
<FallbackCulture>en-US</FallbackCulture>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
|
|
||||||
<StartProgram>C:\Program Files\Rhino 6\System\Rhino.exe</StartProgram>
|
|
||||||
<StartArguments>
|
|
||||||
</StartArguments>
|
|
||||||
<StartAction>Program</StartAction>
|
<StartAction>Program</StartAction>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,57 +1,21 @@
|
|||||||
using System;
|
using Grasshopper.Kernel;
|
||||||
using System.Drawing;
|
|
||||||
using Grasshopper.Kernel;
|
|
||||||
|
|
||||||
namespace GrasshopperAsyncComponentDemo
|
namespace GrasshopperAsyncComponentDemo;
|
||||||
|
|
||||||
|
public class GrasshopperAsyncComponentInfo : GH_AssemblyInfo
|
||||||
{
|
{
|
||||||
public class GrasshopperAsyncComponentInfo : GH_AssemblyInfo
|
public override string Name => "GrasshopperAsyncComponentDemo";
|
||||||
{
|
|
||||||
public override string Name
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return "GrasshopperAsyncComponentDemo";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override Bitmap Icon
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
//Return a 24x24 pixel bitmap to represent this GHA library.
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override string Description
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
//Return a short string describing the purpose of this GHA library.
|
|
||||||
return "A base for async & less janky grasshopper components.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public override Guid Id
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return new Guid("9c8808bc-ddee-45ca-8c66-05ca3cf4d394");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string AuthorName
|
//Return a short string describing the purpose of this GHA library.
|
||||||
{
|
|
||||||
get
|
public override string Description => "A base for async & less janky grasshopper components.";
|
||||||
{
|
|
||||||
//Return a string identifying you or your company.
|
public override Guid Id => new("9c8808bc-ddee-45ca-8c66-05ca3cf4d394");
|
||||||
return "";
|
|
||||||
}
|
//Return a string identifying you or your company.
|
||||||
}
|
|
||||||
public override string AuthorContact
|
public override string AuthorName => "";
|
||||||
{
|
|
||||||
get
|
//Return a string representing your preferred contact details.
|
||||||
{
|
public override string AuthorContact => "";
|
||||||
//Return a string representing your preferred contact details.
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
// General Information about an assembly is controlled through the following
|
|
||||||
// set of attributes. Change these attribute values to modify the information
|
|
||||||
// associated with an assembly.
|
|
||||||
[assembly: AssemblyTitle("GrasshopperAsyncComponentDemo")]
|
|
||||||
[assembly: AssemblyDescription("")]
|
|
||||||
[assembly: AssemblyConfiguration("")]
|
|
||||||
[assembly: AssemblyCompany("Aec systems")]
|
|
||||||
[assembly: AssemblyProduct("GrasshopperAsyncComponentDemo")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © 2020")]
|
|
||||||
[assembly: AssemblyTrademark("")]
|
|
||||||
[assembly: AssemblyCulture("")]
|
|
||||||
|
|
||||||
// Setting ComVisible to false makes the types in this assembly not visible
|
|
||||||
// to COM components. If you need to access a type in this assembly from
|
|
||||||
// COM, set the ComVisible attribute to true on that type.
|
|
||||||
[assembly: ComVisible(false)]
|
|
||||||
|
|
||||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
|
||||||
[assembly: Guid("695d2b91-ddb6-416e-8a99-dde6253da7aa")]
|
|
||||||
|
|
||||||
// Version information for an assembly consists of the following four values:
|
|
||||||
//
|
|
||||||
// Major Version
|
|
||||||
// Minor Version
|
|
||||||
// Build Number
|
|
||||||
// Revision
|
|
||||||
//
|
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
|
||||||
// by using the '*' as shown below:
|
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
|
||||||
[assembly: AssemblyVersion("1.0.0.0")]
|
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
||||||
+111
-82
@@ -1,116 +1,145 @@
|
|||||||
using Grasshopper.Kernel;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using GrasshopperAsyncComponent;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using Grasshopper.Kernel;
|
||||||
|
using GrasshopperAsyncComponent;
|
||||||
|
|
||||||
namespace GrasshopperAsyncComponentDemo.SampleImplementations
|
namespace GrasshopperAsyncComponentDemo.SampleImplementations;
|
||||||
|
|
||||||
|
public class Sample_PrimeCalculatorAsyncComponent : GH_AsyncComponent<Sample_PrimeCalculatorAsyncComponent>
|
||||||
{
|
{
|
||||||
public class Sample_PrimeCalculatorAsyncComponent : GH_AsyncComponent
|
public override Guid ComponentGuid => new Guid("22C612B0-2C57-47CE-B9FE-E10621F18933");
|
||||||
{
|
|
||||||
public override Guid ComponentGuid { get => new Guid("22C612B0-2C57-47CE-B9FE-E10621F18933"); }
|
|
||||||
|
|
||||||
protected override System.Drawing.Bitmap Icon { get => Properties.Resources.logo32; }
|
protected override System.Drawing.Bitmap Icon => Properties.Resources.logo32;
|
||||||
|
|
||||||
public override GH_Exposure Exposure => GH_Exposure.primary;
|
public override GH_Exposure Exposure => GH_Exposure.primary;
|
||||||
|
|
||||||
public Sample_PrimeCalculatorAsyncComponent() : base("The N-th Prime Calculator", "PRIME", "Calculates the nth prime number.", "Samples", "Async")
|
public Sample_PrimeCalculatorAsyncComponent()
|
||||||
|
: base("The N-th Prime Calculator", "PRIME", "Calculates the nth prime number.", "Samples", "Async")
|
||||||
{
|
{
|
||||||
BaseWorker = new PrimeCalculatorWorker();
|
BaseWorker = new PrimeCalculatorWorker(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
||||||
{
|
{
|
||||||
pManager.AddIntegerParameter("N", "N", "Which n-th prime number. Minimum 1, maximum one million. Take care, it can burn your CPU.", GH_ParamAccess.item);
|
pManager.AddIntegerParameter(
|
||||||
|
"N",
|
||||||
|
"N",
|
||||||
|
"Which n-th prime number. Minimum 1, maximum one million. Take care, it can burn your CPU.",
|
||||||
|
GH_ParamAccess.item
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||||
{
|
{
|
||||||
pManager.AddNumberParameter("Output", "O", "The n-th prime number.", GH_ParamAccess.item);
|
pManager.AddNumberParameter("Output", "O", "The n-th prime number.", GH_ParamAccess.item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void AppendAdditionalMenuItems(ToolStripDropDown menu)
|
public override void AppendAdditionalMenuItems(ToolStripDropDown menu)
|
||||||
{
|
{
|
||||||
base.AppendAdditionalMenuItems(menu);
|
base.AppendAdditionalMenuItems(menu);
|
||||||
Menu_AppendItem(menu, "Cancel", (s, e) =>
|
Menu_AppendItem(
|
||||||
{
|
menu,
|
||||||
RequestCancellation();
|
"Cancel",
|
||||||
});
|
(s, e) =>
|
||||||
|
{
|
||||||
|
RequestCancellation();
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public class PrimeCalculatorWorker : WorkerInstance
|
private sealed class PrimeCalculatorWorker : WorkerInstance<Sample_PrimeCalculatorAsyncComponent>
|
||||||
{
|
|
||||||
int TheNthPrime { get; set; } = 100;
|
|
||||||
long ThePrime { get; set; } = -1;
|
|
||||||
|
|
||||||
public PrimeCalculatorWorker() : base(null) { }
|
|
||||||
|
|
||||||
public override void DoWork(Action<string, double> ReportProgress, Action Done)
|
|
||||||
{
|
{
|
||||||
// 👉 Checking for cancellation!
|
private int TheNthPrime { get; set; } = 100;
|
||||||
if (CancellationToken.IsCancellationRequested) { return; }
|
private long ThePrime { get; set; } = -1;
|
||||||
|
|
||||||
int count = 0;
|
public PrimeCalculatorWorker(
|
||||||
long a = 2;
|
Sample_PrimeCalculatorAsyncComponent parent,
|
||||||
|
string id = "baseworker",
|
||||||
|
CancellationToken cancellationToken = default
|
||||||
|
)
|
||||||
|
: base(parent, id, cancellationToken) { }
|
||||||
|
|
||||||
// Thanks Steak Overflow (TM) https://stackoverflow.com/a/13001749/
|
public override Task DoWork(Action<string, double> reportProgress, Action done)
|
||||||
while (count < TheNthPrime)
|
|
||||||
{
|
|
||||||
// 👉 Checking for cancellation!
|
|
||||||
if (CancellationToken.IsCancellationRequested) { return; }
|
|
||||||
|
|
||||||
long b = 2;
|
|
||||||
int prime = 1;// to check if found a prime
|
|
||||||
while (b * b <= a)
|
|
||||||
{
|
{
|
||||||
// 👉 Checking for cancellation!
|
try
|
||||||
if (CancellationToken.IsCancellationRequested) {return; }
|
{
|
||||||
|
CalculatePrimes(reportProgress);
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException) when (CancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
//No need to call `done()` - GrasshopperAsyncComponent assumes immediate cancel,
|
||||||
|
//thus it has already performed clean-up actions that would normally be done on `done()`
|
||||||
|
}
|
||||||
|
|
||||||
if (a % b == 0)
|
return Task.CompletedTask;
|
||||||
{
|
|
||||||
prime = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
b++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReportProgress(Id, ((double)count) / TheNthPrime);
|
public void CalculatePrimes(Action<string, double> reportProgress)
|
||||||
|
|
||||||
if (prime > 0)
|
|
||||||
{
|
{
|
||||||
count++;
|
// 👉 Checking for cancellation!
|
||||||
|
CancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
long a = 2;
|
||||||
|
|
||||||
|
// Thanks Steak Overflow (TM) https://stackoverflow.com/a/13001749/
|
||||||
|
while (count < TheNthPrime)
|
||||||
|
{
|
||||||
|
// 👉 Checking for cancellation!
|
||||||
|
CancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
long b = 2;
|
||||||
|
int prime = 1; // to check if found a prime
|
||||||
|
while (b * b <= a)
|
||||||
|
{
|
||||||
|
// 👉 Checking for cancellation!
|
||||||
|
CancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
if (a % b == 0)
|
||||||
|
{
|
||||||
|
prime = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
b++;
|
||||||
|
}
|
||||||
|
|
||||||
|
reportProgress(Id, (double)count / TheNthPrime);
|
||||||
|
|
||||||
|
if (prime > 0)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
a++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThePrime = --a;
|
||||||
}
|
}
|
||||||
a++;
|
|
||||||
}
|
|
||||||
|
|
||||||
ThePrime = --a;
|
public override WorkerInstance<Sample_PrimeCalculatorAsyncComponent> Duplicate(
|
||||||
Done();
|
string id,
|
||||||
|
CancellationToken cancellationToken
|
||||||
|
) => new PrimeCalculatorWorker(Parent, id, cancellationToken);
|
||||||
|
|
||||||
|
public override void GetData(IGH_DataAccess da, GH_ComponentParamServer parameters)
|
||||||
|
{
|
||||||
|
int nthPrime = 100;
|
||||||
|
da.GetData(0, ref nthPrime);
|
||||||
|
if (nthPrime > 1000000)
|
||||||
|
{
|
||||||
|
nthPrime = 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nthPrime < 1)
|
||||||
|
{
|
||||||
|
nthPrime = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TheNthPrime = nthPrime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetData(IGH_DataAccess da)
|
||||||
|
{
|
||||||
|
da.SetData(0, ThePrime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override WorkerInstance Duplicate() => new PrimeCalculatorWorker();
|
|
||||||
|
|
||||||
public override void GetData(IGH_DataAccess DA, GH_ComponentParamServer Params)
|
|
||||||
{
|
|
||||||
int _nthPrime = 100;
|
|
||||||
DA.GetData(0, ref _nthPrime);
|
|
||||||
if (_nthPrime > 1000000) _nthPrime = 1000000;
|
|
||||||
if (_nthPrime < 1) _nthPrime = 1;
|
|
||||||
|
|
||||||
TheNthPrime = _nthPrime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetData(IGH_DataAccess DA)
|
|
||||||
{
|
|
||||||
// 👉 Checking for cancellation!
|
|
||||||
if (CancellationToken.IsCancellationRequested) { return; }
|
|
||||||
|
|
||||||
DA.SetData(0, ThePrime);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Executable → Regular
+103
-71
@@ -1,93 +1,125 @@
|
|||||||
using Grasshopper.Kernel;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using GrasshopperAsyncComponent;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using Grasshopper.Kernel;
|
||||||
|
using GrasshopperAsyncComponent;
|
||||||
|
|
||||||
namespace GrasshopperAsyncComponentDemo.SampleImplementations
|
namespace GrasshopperAsyncComponentDemo.SampleImplementations;
|
||||||
|
|
||||||
|
public class Sample_UselessCyclesAsyncComponent : GH_AsyncComponent<Sample_UselessCyclesAsyncComponent>
|
||||||
{
|
{
|
||||||
public class Sample_UselessCyclesAsyncComponent : GH_AsyncComponent
|
public override Guid ComponentGuid => new Guid("DF2B93E2-052D-4BE4-BC62-90DC1F169BF6");
|
||||||
{
|
|
||||||
public override Guid ComponentGuid { get => new Guid("DF2B93E2-052D-4BE4-BC62-90DC1F169BF6"); }
|
|
||||||
|
|
||||||
protected override System.Drawing.Bitmap Icon { get => Properties.Resources.logo32; }
|
protected override System.Drawing.Bitmap Icon => Properties.Resources.logo32;
|
||||||
|
|
||||||
public override GH_Exposure Exposure => GH_Exposure.primary;
|
public override GH_Exposure Exposure => GH_Exposure.primary;
|
||||||
|
|
||||||
public Sample_UselessCyclesAsyncComponent() : base("Sample Async Component", "CYCLOMATRON-X", "Spins uselessly.", "Samples", "Async")
|
public Sample_UselessCyclesAsyncComponent()
|
||||||
|
: base("Sample Async Component", "CYCLOMATRON-X", "Spins uselessly.", "Samples", "Async")
|
||||||
{
|
{
|
||||||
BaseWorker = new UselessCyclesWorker();
|
BaseWorker = new UselessCyclesWorker(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class UselessCyclesWorker(
|
||||||
|
Sample_UselessCyclesAsyncComponent parent,
|
||||||
|
string id = "baseworker",
|
||||||
|
CancellationToken cancellationToken = default
|
||||||
|
) : WorkerInstance<Sample_UselessCyclesAsyncComponent>(parent, id, cancellationToken)
|
||||||
|
{
|
||||||
|
private int MaxIterations { get; set; } = 100;
|
||||||
|
|
||||||
|
public override Task DoWork(Action<string, double> reportProgress, Action done)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
RunUselessCycles(reportProgress);
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException) when (CancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
//No need to call `done()` - GrasshopperAsyncComponent assumes immediate cancel,
|
||||||
|
//thus it has already performed clean-up actions that would normally be done on `done()`
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RunUselessCycles(Action<string, double> reportProgress)
|
||||||
|
{
|
||||||
|
// Checking for cancellation
|
||||||
|
CancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
for (int i = 0; i <= MaxIterations; i++)
|
||||||
|
{
|
||||||
|
var sw = new SpinWait();
|
||||||
|
for (int j = 0; j <= 100; j++)
|
||||||
|
{
|
||||||
|
sw.SpinOnce();
|
||||||
|
}
|
||||||
|
|
||||||
|
reportProgress(Id, (i + 1) / (double)MaxIterations);
|
||||||
|
|
||||||
|
// Checking for cancellation
|
||||||
|
CancellationToken.ThrowIfCancellationRequested();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override WorkerInstance<Sample_UselessCyclesAsyncComponent> Duplicate(
|
||||||
|
string id,
|
||||||
|
CancellationToken cancellationToken
|
||||||
|
) => new UselessCyclesWorker(Parent, id, cancellationToken);
|
||||||
|
|
||||||
|
public override void GetData(IGH_DataAccess da, GH_ComponentParamServer parameters)
|
||||||
|
{
|
||||||
|
if (CancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int maxIterations = 100;
|
||||||
|
da.GetData(0, ref maxIterations);
|
||||||
|
if (maxIterations > 1000)
|
||||||
|
{
|
||||||
|
maxIterations = 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxIterations < 10)
|
||||||
|
{
|
||||||
|
maxIterations = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaxIterations = maxIterations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetData(IGH_DataAccess da)
|
||||||
|
{
|
||||||
|
if (CancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
da.SetData(0, $"Hello world. Worker {Id} has spun for {MaxIterations} iterations.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
protected override void RegisterInputParams(GH_InputParamManager pManager)
|
||||||
{
|
{
|
||||||
pManager.AddIntegerParameter("N", "N", "Number of spins.", GH_ParamAccess.item);
|
pManager.AddIntegerParameter("N", "N", "Number of spins.", GH_ParamAccess.item);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
protected override void RegisterOutputParams(GH_OutputParamManager pManager)
|
||||||
{
|
{
|
||||||
pManager.AddTextParameter("Output", "O", "Nothing really interesting.", GH_ParamAccess.item);
|
pManager.AddTextParameter("Output", "O", "Nothing really interesting.", GH_ParamAccess.item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void AppendAdditionalMenuItems(ToolStripDropDown menu)
|
public override void AppendAdditionalMenuItems(ToolStripDropDown menu)
|
||||||
{
|
{
|
||||||
base.AppendAdditionalMenuItems(menu);
|
base.AppendAdditionalMenuItems(menu);
|
||||||
Menu_AppendItem(menu, "Cancel", (s, e) =>
|
Menu_AppendItem(
|
||||||
{
|
menu,
|
||||||
RequestCancellation();
|
"Cancel",
|
||||||
});
|
(s, e) =>
|
||||||
|
{
|
||||||
|
RequestCancellation();
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public class UselessCyclesWorker : WorkerInstance
|
|
||||||
{
|
|
||||||
int MaxIterations { get; set; } = 100;
|
|
||||||
|
|
||||||
public UselessCyclesWorker() : base(null) { }
|
|
||||||
|
|
||||||
public override void DoWork(Action<string, double> ReportProgress, Action Done)
|
|
||||||
{
|
|
||||||
// Checking for cancellation
|
|
||||||
if (CancellationToken.IsCancellationRequested) { return; }
|
|
||||||
|
|
||||||
for (int i = 0; i <= MaxIterations; i++)
|
|
||||||
{
|
|
||||||
var sw = new SpinWait();
|
|
||||||
for (int j = 0; j <= 100; j++)
|
|
||||||
sw.SpinOnce();
|
|
||||||
|
|
||||||
ReportProgress(Id, ((double)(i + 1) / (double)MaxIterations));
|
|
||||||
|
|
||||||
// Checking for cancellation
|
|
||||||
if (CancellationToken.IsCancellationRequested) { return; }
|
|
||||||
}
|
|
||||||
|
|
||||||
Done();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override WorkerInstance Duplicate() => new UselessCyclesWorker();
|
|
||||||
|
|
||||||
public override void GetData(IGH_DataAccess DA, GH_ComponentParamServer Params)
|
|
||||||
{
|
|
||||||
if (CancellationToken.IsCancellationRequested) return;
|
|
||||||
|
|
||||||
int _maxIterations = 100;
|
|
||||||
DA.GetData(0, ref _maxIterations);
|
|
||||||
if (_maxIterations > 1000) _maxIterations = 1000;
|
|
||||||
if (_maxIterations < 10) _maxIterations = 10;
|
|
||||||
|
|
||||||
MaxIterations = _maxIterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void SetData(IGH_DataAccess DA)
|
|
||||||
{
|
|
||||||
if (CancellationToken.IsCancellationRequested) return;
|
|
||||||
DA.SetData(0, $"Hello world. Worker {Id} has spun for {MaxIterations} iterations.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,7 +186,7 @@
|
|||||||
same "printed page" as the copyright notice for easier
|
same "printed page" as the copyright notice for easier
|
||||||
identification within third-party archives.
|
identification within third-party archives.
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
Copyright 2020 AEC Systems
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
|||||||
@@ -76,11 +76,16 @@ Quite easy:
|
|||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Before embarking on submitting a patch, please make sure you read:
|
Please make sure you read the [contribution guidelines](.github/CONTRIBUTING.md) and [Code of Conduct](.github/CODE_OF_CONDUCT.md) for an overview of the best practices we try to follow.
|
||||||
|
|
||||||
- [Contribution Guidelines](CONTRIBUTING.md),
|
## Community
|
||||||
- [Code of Conduct](CODE_OF_CONDUCT.md)
|
|
||||||
|
The Speckle Community hangs out on [the forum](https://discourse.speckle.works), do join and introduce yourself & feel free to ask us questions!
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
For any security vulnerabilities or concerns, please contact us directly at security[at]speckle.systems.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Unless otherwise described, the code in this repository is licensed under the Apache-2.0 license.
|
Unless otherwise described, the code in this repository is licensed under the Apache-2.0 License. Please note that some modules, extensions or code herein might be otherwise licensed. This is indicated either in the root of the containing folder under a different license file, or in the respective file's header. If you have any questions, don't hesitate to get in touch with us via [email](mailto:hello@speckle.systems).
|
||||||
|
|||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
| Version | Supported |
|
||||||
|
| ------- | ------------------ |
|
||||||
|
| 2.2.+ | :white_check_mark: |
|
||||||
|
| < 2.2 | :x: |
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
Hi! If you've found something off, we'd be more than happy if you would report it via security@speckle.systems. We will work together with you to correctly identify the cause and implement a fix. Thanks for helping make Speckle safer!
|
||||||
Reference in New Issue
Block a user