diff --git a/.csharpierrc.yaml b/.csharpierrc.yaml
new file mode 100644
index 00000000..152a7153
--- /dev/null
+++ b/.csharpierrc.yaml
@@ -0,0 +1,7 @@
+printWidth: 120
+useTabs: false
+tabWidth: 2
+preprocessorSymbolSets:
+ - ""
+ - "DEBUG"
+ - "DEBUG,CODE_STYLE"
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..aad43bcb
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,305 @@
+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.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
+
+# 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 = none # 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
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..0a96b77c
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,5 @@
+# Set the default behavior, in case people don't have core.autocrlf set.
+* text=auto
+
+# need original files to be windows
+*.txt text eol=crlf
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..d6a5a1d1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,21 @@
+**/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
+/tests/TestArchives/6d23a38c-f064-4ef1-ad89-b942396f53b9/Scratch
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000..b7fa3e30
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,50 @@
+# Speckle Contribution Guidelines
+
+## 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.
+
+> **Speckle** is a quite large ecosystem of moving parts. Any changes may have unintended effects, that can cause problems quickly for many people (and processes) that rely on Speckle.
+
+This means that what might look like a simple quick change in one repo may have a big hidden cost that propagates around other parts of the project. We're all here to help each other, and this guide is meant to help you get started and promote a framework that can untangle all these dependecies through discussion!
+
+## Bugs & Issues 🐞
+
+### Found a new bug?
+
+- First step is to check whether this is a new bug! We encourage you to search through the issues of the project in question **and** associated repos!
+
+- If you come up with nothing, **open a new issue with a clear title and description**, as much relevant information as possible: system configuration, code samples & steps to reproduce the problem.
+
+- Can't mention this often enough: tells us how to reproduce the problem! We will ignore or flag as such issues without reproduction steps.
+
+- Try to reference & note all potentially affected projects.
+
+### Sending a PR for Bug Fixes
+
+You fixed something! Great! We hope you logged it first :) Make sure though that you've covered the lateral thinking needed for a bug report, as described above, also in your implementation! If there any tests, make sure they all pass. If there are none, it means they're missing - so add them!
+
+## New Features 🎉
+
+The golden rule is to Discuss First!
+
+- Before embarking on adding a new feature, suggest it first as an issue with the `enhancement` label and/or title - this will allow relevant people to pitch in
+- We'll now discuss your requirements and see how and if they fit within the Speckle ecosystem.
+- The last step is to actually start writing code & submit a PR so we can follow along!
+- All new features should, if and where possible, come with tests. We won't merge without!
+
+> Many clients may potentially have overlapping scopes, some features might already be in dev somewhere else, or might have been postponed to the next major release due to api instability in that area. For example, adding a delete stream button in the accounts panel in rhino: this feature was planned for speckle admin, and the whole functionality of the accounts panel in rhino is to be greatly reduced!
+
+## Cosmetic Patches ✨
+
+Changes that are cosmetic in nature and do not add anything substantial to the stability or functionality of Speckle **will generally not be accepted**.
+
+Why? However trivial the changes might seem, there might be subtle reasons for the original code to be as it is. Furthermore, there are a lot of potential hidden costs (that even maintainers themselves are not aware of fully!) and they eat up review time unncessarily.
+
+> **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
+
+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).
+
+🙌❤️💙💚💜🙌
diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 00000000..465817cf
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,30 @@
+
+
+ Speckle
+ Speckle
+ Copyright (c) AEC Systems Ltd
+
+
+
+ latest
+ enable
+ enable
+ Recommended
+ true
+ true
+ true
+ true
+ true
+ False
+ False
+ true
+ true
+
+
+
+ preview.0
+
+
+
+
+
diff --git a/Directory.Packages.props b/Directory.Packages.props
new file mode 100644
index 00000000..1b4645b0
--- /dev/null
+++ b/Directory.Packages.props
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
new file mode 100644
index 00000000..715765d3
--- /dev/null
+++ b/ISSUE_TEMPLATE.md
@@ -0,0 +1,17 @@
+If it's your first time here - or you forgot about them - make sure you read the [contribution guidelines](CONTRIBUTING.md), and then feel free to delete this line!
+
+### Expected vs. Actual Behavior
+
+Describe the problem here.
+
+### Reproduction Steps & System Config (win, osx, web, etc.)
+
+Let us know how we can reproduce this, and attach relevant files (if any).
+
+### 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!
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 00000000..f83b45e3
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2020 AEC Systems
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
index 234b90f0..20fe2c06 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,110 @@
-# speckle-sharp-sdk
-The speckle core
+# Core
+
+[](https://twitter.com/SpeckleSystems) [](https://discourse.speckle.works) [](https://speckle.systems) [](https://speckle.guide/dev/)
+
+### **Disclaimer**
+
+This is an early alpha release, not meant for use in production! We're working to stabilise the 2.0 API, and until then there will be breaking changes. You have been warned!
+
+## Introduction
+
+### Core
+
+Core is the .NET SDK for Speckle 2.0. It uses .NET Standard 2.0 and has been tested on Windows and MacOS.
+
+## Documentation
+
+Comprehensive developer and user documentation can be found in our:
+
+#### 📚 [Speckle Docs website](https://speckle.guide/dev/)
+
+## Developing & Debugging
+
+### Building
+
+Make sure you clone this repository together with its submodules: `git clone https://github.com/specklesystems/Core.git -recursive`.
+Afterwards, just restore all the NuGet packages and hit Build!
+
+### Developing
+
+This project is evolving fast, to better understand how to use Core we suggest checking out the Unit and Integration tests. Running the integration tests locally requires a local server running on your computer.
+
+We'll be also adding [preliminary documentation on our forum](https://discourse.speckle.works/c/speckle-insider/10).
+
+### Tests
+
+There are two test projects, one for unit tests and one for integration tests. The latter needs a server running locally in order to run.
+
+## Contributing
+
+Before embarking on submitting a patch, please make sure you read:
+
+- [Contribution Guidelines](CONTRIBUTING.md),
+- [Code of Conduct](CODE_OF_CONDUCT.md)
+
+## Community
+
+The Speckle Community hangs out on [the forum](https://discourse.speckle.works), do join and introduce yourself & feel free to ask us questions!
+
+## License
+
+Unless otherwise described, the code in this repository is licensed under the Apache-2.0 license.
+
+# Objects
+
+[](https://twitter.com/SpeckleSystems) [](https://discourse.speckle.works) [](https://speckle.systems) [](https://speckle.guide/dev/)
+
+**Status**
+
+
+
+
+## Introduction
+
+Before venturing any further please make sure to check the following:
+
+- [Code of Conduct](CODE_OF_CONDUCT.md),
+- [Contribution Guidelines](CONTRIBUTING.md),
+- [License](LICENSE)
+
+### Objects
+
+The Speckle 2.0 object model: geometry and element base classes. It uses .NET Standard 2.0 and has been tested on Windows and MacOS.
+
+**NOTE:** this is the default object model we ship with Speckle. You can develop your own or fork this and extend it too!
+
+More info on Objects and Kits 2.0 can be found in [this community forum thread](https://discourse.speckle.works/t/introducing-kits-2-0/710/34).
+
+## Documentation
+
+Comprehensive developer and user documentation can be found in our:
+
+#### 📚 [Speckle Docs website](https://speckle.guide/dev/)
+
+## Developing & Debugging
+
+### Building
+
+Just restore all the NuGet packages and hit Build!
+
+### Developing
+
+Objects is just a set of Data Transfer Objects, it's quite straightforward to understand how they work!
+
+#### Host application support
+
+In order to better support interop between the various AEC host applications and Speckle, Objects also contains classes that help to deal with native object types and their properties.
+
+For example, you'll see a `\Revit` folder. That contains a series of classes that extend the basic ones with a series of default Revit properties. This is the approach we'll follow with other host applications as well.
+
+## Contributing
+
+Please make sure you read the [contribution guidelines](CONTRIBUTING.md) for an overview of the best practices we try to follow.
+
+## Community
+
+The Speckle Community hangs out on [the forum](https://discourse.speckle.works), do join and introduce yourself & feel free to ask us questions!
+
+## License
+
+Unless otherwise described, the code in this repository is licensed under the Apache-2.0 license.
diff --git a/Speckle.Sdk.sln b/Speckle.Sdk.sln
new file mode 100644
index 00000000..557ff598
--- /dev/null
+++ b/Speckle.Sdk.sln
@@ -0,0 +1,32 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Core", "src\Speckle.Core\Speckle.Core.csproj", "{A413E196-3696-4F48-B635-04B5F76BF9C9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Core.Tests.Unit", "tests\Speckle.Core.Tests.Unit\Speckle.Core.Tests.Unit.csproj", "{99AE2273-12C5-4A9D-9FDD-19F8B394B5E2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Speckle.Core.Transports", "src\Speckle.Core.Transports\Speckle.Core.Transports.csproj", "{6845F190-036C-4AEF-B267-23EE84DBD2A6}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {8781B61F-0308-488A-BEB2-1939E7CEEBE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8781B61F-0308-488A-BEB2-1939E7CEEBE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8781B61F-0308-488A-BEB2-1939E7CEEBE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8781B61F-0308-488A-BEB2-1939E7CEEBE9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A413E196-3696-4F48-B635-04B5F76BF9C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A413E196-3696-4F48-B635-04B5F76BF9C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A413E196-3696-4F48-B635-04B5F76BF9C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A413E196-3696-4F48-B635-04B5F76BF9C9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {99AE2273-12C5-4A9D-9FDD-19F8B394B5E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {99AE2273-12C5-4A9D-9FDD-19F8B394B5E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {99AE2273-12C5-4A9D-9FDD-19F8B394B5E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {99AE2273-12C5-4A9D-9FDD-19F8B394B5E2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6845F190-036C-4AEF-B267-23EE84DBD2A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6845F190-036C-4AEF-B267-23EE84DBD2A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6845F190-036C-4AEF-B267-23EE84DBD2A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6845F190-036C-4AEF-B267-23EE84DBD2A6}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/global.json b/global.json
new file mode 100644
index 00000000..c19a2e05
--- /dev/null
+++ b/global.json
@@ -0,0 +1,6 @@
+{
+ "sdk": {
+ "version": "8.0.100",
+ "rollForward": "latestMinor"
+ }
+}
diff --git a/notes/sqlite-performance.md b/notes/sqlite-performance.md
new file mode 100644
index 00000000..a9488682
--- /dev/null
+++ b/notes/sqlite-performance.md
@@ -0,0 +1,356 @@
+
+
+## Storage Size
+1 million objects => 540mb ( based on ~= 4.2 million objects => 2.3GB not gzipped)
+
+1 million objects => 127mb gzipped
+
+4x reduction in space
+
+## Local storage takeaways:
+
+SQLite optimisations make a difference in insertion speed. Insertion speed does slow down on large tables (+1m rows).
+
+Partioned tables (by, for example, the first two decimals of the hash) have slower but predictable insertion speed. Not sure if compromise is worth it?
+
+## Even More Optimised single object table
+Optimisations are:
+- `PRAGMA journal_mode = MEMORY;`
+- `PRAGMA synchronous = OFF;`
+- `PRAGMA count_changes=OFF;`
+- `PRAGMA temp_store=MEMORY;`
+
+
+### Test 1
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 2286 ms -> 50000 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 1426 ms -> 100000 objects per second
+-------------------------------------------------
+
+### Test 2
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 3052 ms -> 33333.333333333336 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 2244 ms -> 50000 objects per second
+-------------------------------------------------
+
+### Test 3
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 4941 ms -> 25000 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 2555 ms -> 50000 objects per second
+-------------------------------------------------
+
+### Test 4
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 8022 ms -> 12500 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 3350 ms -> 33333.333333333336 objects per second
+-------------------------------------------------
+
+
+### Test 5
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 6602 ms -> 16666.666666666668 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 3445 ms -> 33333.333333333336 objects per second
+-------------------------------------------------
+
+### Test 5+: A couple of more rounds, pushing objs to 2.000k
+
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 7332 ms -> 14285.714285714286 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 7625 ms -> 14285.714285714286 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 7539 ms -> 14285.714285714286 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 4249 ms -> 25000 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 8300 ms -> 12500 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 7289 ms -> 14285.714285714286 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 8668 ms -> 12500 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 8060 ms -> 12500 objects per second
+-------------------------------------------------
+
+
+
+Starting to save 100000 of objects
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 10228 ms -> 10000 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 11475 ms -> 9090.90909090909 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+
+Starting to save 100000 of objects
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 12540 ms -> 8333.333333333334 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 7113 ms -> 14285.714285714286 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+
+Starting to save 100000 of objects
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 17153 ms -> 5882.35294117647 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 5997 ms -> 20000 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+
+Starting to save 100000 of objects
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 20841 ms -> 5000 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 9195 ms -> 11111.111111111111 objects per second
+-------------------------------------------------
+
+Starting to save 100000 of objects
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 13404 ms -> 7692.307692307692 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 7529 ms -> 14285.714285714286 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+
+Starting to save 100000 of objects
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 19806 ms -> 5263.1578947368425 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 7318 ms -> 14285.714285714286 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+
+Starting to save 100000 of objects
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 24612 ms -> 4166.666666666667 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 7410 ms -> 14285.714285714286 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+
+Starting to save 100000 of objects
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 22257 ms -> 4545.454545454545 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 18699 ms -> 5555.555555555556 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+
+Starting to save 100000 of objects
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 20947 ms -> 5000 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 14089 ms -> 7142.857142857143 objects per second
+-------------------------------------------------
+
+
+## Optimised single object table
+Optimisations are: `PRAGMA journal_mode = MEMORY;` and `PRAGMA synchronous = OFF;`
+
+### Test 1:
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 2267 ms -> 50000 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 1327 ms -> 100000 objects per second
+-------------------------------------------------
+
+### Test 2:
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 4532 ms -> 25000 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 2243 ms -> 50000 objects per second
+-------------------------------------------------
+
+### Test 3:
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 3768 ms -> 33333.333333333336 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 5295 ms -> 20000 objects per second
+-------------------------------------------------
+
+### Test 4:
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 4033 ms -> 25000 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 3126 ms -> 33333.333333333336 objects per second
+-------------------------------------------------
+
+### Test 5:
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 4432 ms -> 25000 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 3527 ms -> 33333.333333333336 objects per second
+-------------------------------------------------
+
+
+## Single object table
+
+### Test 1:
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 11964 ms -> 9090.90909090909 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 6875 ms -> 16666.666666666668 objects per second
+-------------------------------------------------
+200k total in db
+
+### Test 2:
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 21956 ms -> 4761.9047619047615 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 8904 ms -> 12500 objects per second
+-------------------------------------------------
+400k total in db
+
+### Test 3:
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 25532 ms -> 4000 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 10124 ms -> 10000 objects per second
+-------------------------------------------------
+600k total in db
+
+### Test 4:
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 26629 ms -> 3846.153846153846 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 10610 ms -> 10000 objects per second
+-------------------------------------------------
+800k total in db
+
+### Test 5:
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 26956 ms -> 3846.153846153846 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 11007 ms -> 9090.90909090909 objects per second
+-------------------------------------------------
+
+1000k total in db
+
+
+## Bucketed Object Table (256 individual tables for objects):
+Pre-generate 256 tables, of form `objs${prefix}`, where prefix is the cartesian product of all the valid hex decimals (`0-9, a-f`).
+
+### Test 1:
+Forgot to copy paste.
+200k total in db
+
+### Test 2:
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 19096 ms -> 5263.1578947368425 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 7401 ms -> 14285.714285714286 objects per second
+-------------------------------------------------
+400k total in db
+
+### Test 3:
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 22477 ms -> 4545.454545454545 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 8668 ms -> 12500 objects per second
+-------------------------------------------------
+600k total in db
+
+### Test 4:
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 23438 ms -> 4347.826086956522 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 9288 ms -> 11111.111111111111 objects per second
+-------------------------------------------------
+800k total in db
+
+### Test 5:
+-------------------------------------------------
+BufferedWriteTest: Wrote 100000 in 23735 ms -> 4347.826086956522 objects per second
+-------------------------------------------------
+
+-------------------------------------------------
+BulkWriteMany: Wrote 100000 in 9944 ms -> 11111.111111111111 objects per second
+-------------------------------------------------
+1mil total in db
\ No newline at end of file
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
new file mode 100644
index 00000000..a9c5b063
--- /dev/null
+++ b/src/Directory.Build.props
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+ true
+
+
diff --git a/src/MongoDBTransport/MongoDB.cs b/src/MongoDBTransport/MongoDB.cs
new file mode 100644
index 00000000..fd3d77a3
--- /dev/null
+++ b/src/MongoDBTransport/MongoDB.cs
@@ -0,0 +1,272 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Timers;
+using MongoDB.Bson;
+using MongoDB.Driver;
+using Speckle.Core.Logging;
+using Timer = System.Timers.Timer;
+
+namespace Speckle.Core.Transports;
+
+// If data storage accessed by transports will always use the hash and content field names, move this enum to ITransport instead.
+public enum Field
+{
+ hash,
+ content
+}
+
+// Question: the benefit of noSQL is the use of unstructured collections of variable documents.
+// Explore storing partially serialized Speckle objects with dynamically generated fields instead of just a content string?
+[Obsolete("This Transport is no longer maintained or routinely tested, use with caution")]
+public class MongoDBTransport : IDisposable, ITransport
+{
+ private bool IS_WRITING;
+ private int MAX_TRANSACTION_SIZE = 1000;
+ private int PollInterval = 500;
+
+ private ConcurrentQueue<(string, string, int)> Queue = new();
+
+ ///
+ /// Timer that ensures queue is consumed if less than MAX_TRANSACTION_SIZE objects are being sent.
+ ///
+ /// Is this to prevent requests to read an object before it is written, or to handle read/write locks?
+ /// If this is can differ per transport, better to use Database.currentOp() to determine if write operations are waiting for a lock.
+ private Timer WriteTimer;
+
+ public MongoDBTransport(
+ string connectionString = "mongodb://localhost:27017",
+ string applicationName = "Speckle",
+ string scope = "Objects"
+ )
+ {
+ SpeckleLog.Logger.Information("Creating new MongoDB Transport");
+
+ ConnectionString = connectionString;
+ Client = new MongoClient(ConnectionString);
+ Database = (MongoDatabaseBase)Client.GetDatabase(applicationName);
+ Collection = Database.GetCollection(scope);
+
+ Initialize();
+
+ WriteTimer = new Timer
+ {
+ AutoReset = true,
+ Enabled = false,
+ Interval = PollInterval
+ };
+ WriteTimer.Elapsed += WriteTimerElapsed;
+ }
+
+ public string ConnectionString { get; set; }
+
+ private MongoClient Client { get; set; }
+ private IMongoDatabase Database { get; set; }
+ private IMongoCollection Collection { get; set; }
+
+ public void Dispose()
+ {
+ // MongoDB collection connection should dispose automatically
+
+ // Time out locking could be added if an expected use case is multiple clients writing to the same server
+ }
+
+ public string TransportName { get; set; } = "MongoTransport";
+
+ public Dictionary TransportContext => new() { { "name", TransportName }, { "type", GetType().Name } };
+
+ public CancellationToken CancellationToken { get; set; }
+
+ public Action OnProgressAction { get; set; }
+
+ public Action OnErrorAction { get; set; }
+ public int SavedObjectCount { get; private set; }
+
+ // not implementing this properly
+ public TimeSpan Elapsed => TimeSpan.Zero;
+
+ public void BeginWrite()
+ {
+ SavedObjectCount = 0;
+ }
+
+ public void EndWrite() { }
+
+ public Task> HasObjects(IReadOnlyList objectIds)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void Initialize()
+ {
+ // Assumes mongoDB server is running
+ // Mongo database and collection should be created automatically if it doesn't already exist
+
+ // Check if the connection is successful
+ bool isMongoLive = Database.RunCommandAsync((Command)"{ping:1}").Wait(1000);
+ if (!isMongoLive)
+ {
+ OnErrorAction(TransportName, new Exception("The Mongo database could not be reached."));
+ }
+ }
+
+ ///
+ /// Returns all the objects in the store.
+ ///
+ ///
+ internal IEnumerable GetAllObjects()
+ {
+ var documents = Collection.Find(new BsonDocument()).ToList();
+ List documentContents = new();
+ foreach (BsonDocument document in documents)
+ {
+ documentContents.Add(document[Field.content.ToString()].AsString);
+ }
+
+ return documentContents;
+ }
+
+ ///
+ /// Deletes an object. Note: do not use for any speckle object transport, as it will corrupt the database.
+ ///
+ ///
+ internal void DeleteObject(string hash)
+ {
+ var filter = Builders.Filter.Eq(Field.hash.ToString(), hash);
+ Collection.DeleteOne(filter);
+ }
+
+ #region Writes
+
+ ///
+ /// Awaits until write completion (ie, the current queue is fully consumed).
+ ///
+ ///
+ public async Task WriteComplete()
+ {
+ await Utilities
+ .WaitUntil(
+ () =>
+ {
+ return GetWriteCompletionStatus();
+ },
+ 500
+ )
+ .ConfigureAwait(false);
+ }
+
+ ///
+ /// Returns true if the current write queue is empty and committed.
+ ///
+ ///
+ ///
+ /// Mongo has intent shared and intent exclusive client operations.
+ /// Each category shares a lock, with intent exclusive operations prioritized.
+ /// Would change to Database.currentOp() to determine if write operations are waiting for a lock, if the WriteTimer is deprecated
+ ///
+ public bool GetWriteCompletionStatus()
+ {
+ Console.WriteLine($"write completion {Queue.Count == 0 && !IS_WRITING}");
+ return Queue.Count == 0 && !IS_WRITING;
+ }
+
+ private void WriteTimerElapsed(object sender, ElapsedEventArgs e)
+ {
+ WriteTimer.Enabled = false;
+ if (!IS_WRITING && Queue.Count != 0)
+ {
+ ConsumeQueue();
+ }
+ }
+
+ private void ConsumeQueue()
+ {
+ IS_WRITING = true;
+ var i = 0;
+ ValueTuple result;
+
+ while (i < MAX_TRANSACTION_SIZE && Queue.TryPeek(out result))
+ {
+ Queue.TryDequeue(out result);
+ var document = new BsonDocument
+ {
+ { Field.hash.ToString(), result.Item1 },
+ { Field.content.ToString(), result.Item2 }
+ };
+ Collection.InsertOne(document);
+ }
+
+ if (Queue.Count > 0)
+ {
+ ConsumeQueue();
+ }
+
+ IS_WRITING = false;
+ }
+
+ ///
+ /// Adds an object to the saving queue.
+ ///
+ ///
+ ///
+ public void SaveObject(string hash, string serializedObject)
+ {
+ Queue.Enqueue((hash, serializedObject, Encoding.UTF8.GetByteCount(serializedObject)));
+
+ WriteTimer.Enabled = true;
+ WriteTimer.Start();
+ }
+
+ public void SaveObject(string hash, ITransport sourceTransport)
+ {
+ var serializedObject = sourceTransport.GetObject(hash);
+ Queue.Enqueue((hash, serializedObject, Encoding.UTF8.GetByteCount(serializedObject)));
+ }
+
+ ///
+ /// Directly saves the object in the db.
+ ///
+ ///
+ ///
+ public void SaveObjectSync(string hash, string serializedObject)
+ {
+ var document = new BsonDocument { { Field.hash.ToString(), hash }, { Field.content.ToString(), serializedObject } };
+ Collection.InsertOne(document);
+ }
+
+ #endregion
+
+ #region Reads
+
+ ///
+ /// Gets an object.
+ ///
+ ///
+ ///
+ public string GetObject(string hash)
+ {
+ var filter = Builders.Filter.Eq(Field.hash.ToString(), hash);
+ BsonDocument objectDocument = Collection.Find(filter).FirstOrDefault();
+ if (objectDocument != null)
+ {
+ return objectDocument[Field.content.ToString()].AsString;
+ }
+
+ // pass on the duty of null checks to consumers
+ return null;
+ }
+
+ public async Task CopyObjectAndChildren(
+ string hash,
+ ITransport targetTransport,
+ Action onTotalChildrenCountKnown = null
+ )
+ {
+ throw new NotImplementedException();
+ }
+
+ #endregion
+}
diff --git a/src/MongoDBTransport/MongoDBTransport.csproj b/src/MongoDBTransport/MongoDBTransport.csproj
new file mode 100644
index 00000000..1d9bc43a
--- /dev/null
+++ b/src/MongoDBTransport/MongoDBTransport.csproj
@@ -0,0 +1,26 @@
+
+
+ netstandard2.0
+ Speckle.Transports.MongoDB
+ MongoDBTransport
+ A MongoDB transport for Speckle
+ $(PackageTags) mongodb transport
+ true
+ disable
+ Speckle.Core.Transports
+
+
+
+ 0
+ false
+ false
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Objects/.editorconfig b/src/Objects/.editorconfig
new file mode 100644
index 00000000..28981d89
--- /dev/null
+++ b/src/Objects/.editorconfig
@@ -0,0 +1,10 @@
+
+[*.{cs,vb}]
+
+# Name properties with camelCase
+dotnet_naming_rule.properties_should_be_camel_case.severity = none
+dotnet_naming_rule.properties_should_be_camel_case.symbols = properties
+dotnet_naming_rule.properties_should_be_camel_case.style = property_style
+
+dotnet_naming_symbols.properties.applicable_kinds = property
+dotnet_naming_style.property_style.capitalization = camel_case
\ No newline at end of file
diff --git a/src/Objects/BuiltElements/AdvanceSteel/AsteelBeam.cs b/src/Objects/BuiltElements/AdvanceSteel/AsteelBeam.cs
new file mode 100644
index 00000000..83db3e1c
--- /dev/null
+++ b/src/Objects/BuiltElements/AdvanceSteel/AsteelBeam.cs
@@ -0,0 +1,36 @@
+using System.Collections.Generic;
+using Objects.Geometry;
+using Objects.Structural.Materials;
+using Objects.Structural.Properties.Profiles;
+using Speckle.Core.Kits;
+using Speckle.Core.Models;
+
+namespace Objects.BuiltElements.AdvanceSteel;
+
+public class AsteelBeam : Beam, IDisplayValue>, IHasVolume, IHasArea, IAsteelObject
+{
+ [DetachProperty]
+ public SectionProfile profile { get; set; }
+
+ [DetachProperty]
+ public StructuralMaterial material { get; set; }
+
+ [DetachProperty]
+ public AsteelSectionProfile asteelProfile { get; set; }
+
+ public double volume { get; set; }
+ public double area { get; set; }
+ public Base userAttributes { get; set; }
+
+ public Base asteelProperties { get; set; }
+
+ public AsteelBeam() { }
+
+ [SchemaInfo("AsteelBeam", "Creates a Advance Steel beam by curve.", "Advance Steel", "Structure")]
+ public AsteelBeam([SchemaMainParam] ICurve baseLine, SectionProfile profile, StructuralMaterial material)
+ {
+ this.baseLine = baseLine;
+ this.profile = profile;
+ this.material = material;
+ }
+}
diff --git a/src/Objects/BuiltElements/AdvanceSteel/AsteelBolt.cs b/src/Objects/BuiltElements/AdvanceSteel/AsteelBolt.cs
new file mode 100644
index 00000000..e474b51a
--- /dev/null
+++ b/src/Objects/BuiltElements/AdvanceSteel/AsteelBolt.cs
@@ -0,0 +1,27 @@
+using System.Collections.Generic;
+using Objects.Geometry;
+using Speckle.Core.Models;
+
+namespace Objects.BuiltElements.AdvanceSteel;
+
+public abstract class AsteelBolt : Base, IAsteelObject
+{
+ [DetachProperty]
+ public List displayValue { get; set; }
+
+ public Base userAttributes { get; set; }
+
+ public Base asteelProperties { get; set; }
+}
+
+public class AsteelCircularBolt : AsteelBolt
+{
+ //[SchemaInfo("AsteelCircularBolt", "Creates a Advance Steel circular bolt.", "Advance Steel", "Structure")]
+ public AsteelCircularBolt() { }
+}
+
+public class AsteelRectangularBolt : AsteelBolt
+{
+ //[SchemaInfo("AsteelRectangularBolt", "Creates a Advance Steel rectangular bolt.", "Advance Steel", "Structure")]
+ public AsteelRectangularBolt() { }
+}
diff --git a/src/Objects/BuiltElements/AdvanceSteel/AsteelGrating.cs b/src/Objects/BuiltElements/AdvanceSteel/AsteelGrating.cs
new file mode 100644
index 00000000..d0b94c46
--- /dev/null
+++ b/src/Objects/BuiltElements/AdvanceSteel/AsteelGrating.cs
@@ -0,0 +1,18 @@
+using System.Collections.Generic;
+using Objects.Geometry;
+using Speckle.Core.Models;
+
+namespace Objects.BuiltElements.AdvanceSteel;
+
+public class AsteelGrating : Base, IAsteelObject
+{
+ [DetachProperty]
+ public List displayValue { get; set; }
+
+ public Base userAttributes { get; set; }
+
+ public Base asteelProperties { get; set; }
+
+ //[SchemaInfo("AsteelGrating", "Creates a Advance Steel grating.", "Advance Steel", "Structure")]
+ public AsteelGrating() { }
+}
diff --git a/src/Objects/BuiltElements/AdvanceSteel/AsteelPlate.cs b/src/Objects/BuiltElements/AdvanceSteel/AsteelPlate.cs
new file mode 100644
index 00000000..a8335933
--- /dev/null
+++ b/src/Objects/BuiltElements/AdvanceSteel/AsteelPlate.cs
@@ -0,0 +1,27 @@
+using System.Collections.Generic;
+using Objects.Geometry;
+using Objects.Structural.Materials;
+using Speckle.Core.Kits;
+using Speckle.Core.Models;
+
+namespace Objects.BuiltElements.AdvanceSteel;
+
+public class AsteelPlate : Area, IDisplayValue>, IHasArea, IHasVolume, IAsteelObject
+{
+ [DetachProperty]
+ public StructuralMaterial? material { get; set; }
+
+ public Base userAttributes { get; set; }
+
+ public Base asteelProperties { get; set; }
+
+ [SchemaInfo("AsteelPlate", "Creates a Advance Steel plate.", "Advance Steel", "Structure")]
+ public AsteelPlate(Polyline outline, string units, StructuralMaterial? material = null)
+ {
+ this.outline = outline;
+ this.material = material;
+ this.units = units;
+ }
+
+ public AsteelPlate() { }
+}
diff --git a/src/Objects/BuiltElements/AdvanceSteel/AsteelPolyBeam.cs b/src/Objects/BuiltElements/AdvanceSteel/AsteelPolyBeam.cs
new file mode 100644
index 00000000..8ba194b0
--- /dev/null
+++ b/src/Objects/BuiltElements/AdvanceSteel/AsteelPolyBeam.cs
@@ -0,0 +1,7 @@
+namespace Objects.BuiltElements.AdvanceSteel;
+
+public class AsteelPolyBeam : AsteelBeam
+{
+ //[SchemaInfo("AsteelPolyBeam", "Creates a Advance Steel polybeam.", "Advance Steel", "Structure")]
+ public AsteelPolyBeam() { }
+}
diff --git a/src/Objects/BuiltElements/AdvanceSteel/AsteelSectionProfile.cs b/src/Objects/BuiltElements/AdvanceSteel/AsteelSectionProfile.cs
new file mode 100644
index 00000000..069a0d30
--- /dev/null
+++ b/src/Objects/BuiltElements/AdvanceSteel/AsteelSectionProfile.cs
@@ -0,0 +1,12 @@
+using Speckle.Core.Models;
+
+namespace Objects.BuiltElements.AdvanceSteel;
+
+public class AsteelSectionProfile : Base
+{
+ public string ProfSectionType { get; set; }
+
+ public string ProfSectionName { get; set; }
+
+ public AsteelSectionProfileDB SectionProfileDB { get; set; }
+}
diff --git a/src/Objects/BuiltElements/AdvanceSteel/AsteelSectionProfileDB.cs b/src/Objects/BuiltElements/AdvanceSteel/AsteelSectionProfileDB.cs
new file mode 100644
index 00000000..cdbf61e7
--- /dev/null
+++ b/src/Objects/BuiltElements/AdvanceSteel/AsteelSectionProfileDB.cs
@@ -0,0 +1,5 @@
+using Speckle.Core.Models;
+
+namespace Objects.BuiltElements.AdvanceSteel;
+
+public class AsteelSectionProfileDB : Base { }
diff --git a/src/Objects/BuiltElements/AdvanceSteel/AsteelSlab.cs b/src/Objects/BuiltElements/AdvanceSteel/AsteelSlab.cs
new file mode 100644
index 00000000..bed8a7c8
--- /dev/null
+++ b/src/Objects/BuiltElements/AdvanceSteel/AsteelSlab.cs
@@ -0,0 +1,27 @@
+using System.Collections.Generic;
+using Objects.Geometry;
+using Objects.Structural.Materials;
+using Speckle.Core.Kits;
+using Speckle.Core.Models;
+
+namespace Objects.BuiltElements.AdvanceSteel;
+
+public class AsteelSlab : Area, IDisplayValue>, IHasArea, IHasVolume, IAsteelObject
+{
+ [DetachProperty]
+ public StructuralMaterial? material { get; set; }
+
+ public Base userAttributes { get; set; }
+
+ public Base asteelProperties { get; set; }
+
+ [SchemaInfo("AsteelSlab", "Creates a Advance Steel slab.", "Advance Steel", "Structure")]
+ public AsteelSlab(Polyline outline, string units, StructuralMaterial? material = null)
+ {
+ this.outline = outline;
+ this.material = material;
+ this.units = units;
+ }
+
+ public AsteelSlab() { }
+}
diff --git a/src/Objects/BuiltElements/AdvanceSteel/AsteelSpecialPart.cs b/src/Objects/BuiltElements/AdvanceSteel/AsteelSpecialPart.cs
new file mode 100644
index 00000000..f05b8155
--- /dev/null
+++ b/src/Objects/BuiltElements/AdvanceSteel/AsteelSpecialPart.cs
@@ -0,0 +1,18 @@
+using System.Collections.Generic;
+using Objects.Geometry;
+using Speckle.Core.Models;
+
+namespace Objects.BuiltElements.AdvanceSteel;
+
+public class AsteelSpecialPart : Base, IAsteelObject
+{
+ [DetachProperty]
+ public List displayValue { get; set; }
+
+ public Base userAttributes { get; set; }
+
+ public Base asteelProperties { get; set; }
+
+ //[SchemaInfo("AsteelSpecialPart", "Creates a Advance Steel special part.", "Advance Steel", "Structure")]
+ public AsteelSpecialPart() { }
+}
diff --git a/src/Objects/BuiltElements/AdvanceSteel/AsteelStraightBeam.cs b/src/Objects/BuiltElements/AdvanceSteel/AsteelStraightBeam.cs
new file mode 100644
index 00000000..0e548aae
--- /dev/null
+++ b/src/Objects/BuiltElements/AdvanceSteel/AsteelStraightBeam.cs
@@ -0,0 +1,7 @@
+namespace Objects.BuiltElements.AdvanceSteel;
+
+public class AsteelStraightBeam : AsteelBeam
+{
+ //[SchemaInfo("AsteelStraightBeam", "Creates a Advance Steel straightBeam.", "Advance Steel", "Structure")]
+ public AsteelStraightBeam() { }
+}
diff --git a/src/Objects/BuiltElements/AdvanceSteel/Enums.cs b/src/Objects/BuiltElements/AdvanceSteel/Enums.cs
new file mode 100644
index 00000000..42200752
--- /dev/null
+++ b/src/Objects/BuiltElements/AdvanceSteel/Enums.cs
@@ -0,0 +1 @@
+namespace Objects.BuiltElements.AdvanceSteel;
diff --git a/src/Objects/BuiltElements/AdvanceSteel/IAsteelObject.cs b/src/Objects/BuiltElements/AdvanceSteel/IAsteelObject.cs
new file mode 100644
index 00000000..c648867c
--- /dev/null
+++ b/src/Objects/BuiltElements/AdvanceSteel/IAsteelObject.cs
@@ -0,0 +1,10 @@
+using Speckle.Core.Models;
+
+namespace Objects.BuiltElements.AdvanceSteel;
+
+public interface IAsteelObject
+{
+ Base userAttributes { get; set; }
+
+ Base asteelProperties { get; set; }
+}
diff --git a/src/Objects/BuiltElements/Alignment.cs b/src/Objects/BuiltElements/Alignment.cs
new file mode 100644
index 00000000..476ee520
--- /dev/null
+++ b/src/Objects/BuiltElements/Alignment.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using Objects.Geometry;
+using Speckle.Core.Models;
+using Speckle.Newtonsoft.Json;
+
+namespace Objects.BuiltElements;
+
+public class Alignment : Base, IDisplayValue
+{
+ [JsonIgnore, Obsolete("Use curves property")]
+ public ICurve baseCurve { get; set; }
+
+ public List curves { get; set; }
+
+ public string name { get; set; }
+
+ public double startStation { get; set; }
+
+ public double endStation { get; set; }
+
+ public List profiles { get; set; }
+
+ ///
+ /// Station equation list contains doubles indicating raw station back, station back, and station ahead for each station equation
+ ///
+ public List stationEquations { get; set; }
+
+ ///
+ /// Station equation direction for the corresponding station equation should be true for increasing or false for decreasing
+ ///
+ public List stationEquationDirections { get; set; }
+
+ public string units { get; set; }
+
+ [DetachProperty]
+ public Polyline displayValue { get; set; }
+}
diff --git a/src/Objects/BuiltElements/Archicad/ArchicadBeam.cs b/src/Objects/BuiltElements/Archicad/ArchicadBeam.cs
new file mode 100644
index 00000000..4964a78b
--- /dev/null
+++ b/src/Objects/BuiltElements/Archicad/ArchicadBeam.cs
@@ -0,0 +1,134 @@
+using System;
+using System.Collections.Generic;
+using Objects.Geometry;
+using Speckle.Core.Kits;
+using Speckle.Core.Models;
+using Speckle.Newtonsoft.Json;
+
+namespace Objects.BuiltElements.Archicad;
+
+/*
+For further informations about given the variables, visit:
+https://archicadapi.graphisoft.com/documentation/api_beamtype
+*/
+public class ArchicadBeam : Beam
+{
+ [SchemaInfo("ArchicadBeam", "Creates an Archicad beam by curve.", "Archicad", "Structure")]
+ public ArchicadBeam() { }
+
+ // Element base
+ public string? elementType { get; set; } /*APINullabe*/
+
+ public List? classifications { get; set; } /*APINullabe*/
+ public Base? elementProperties { get; set; }
+ public Base? componentProperties { get; set; }
+
+ public override Level? level
+ {
+ get => archicadLevel;
+ internal set
+ {
+ if (value is ArchicadLevel or null)
+ {
+ archicadLevel = value as ArchicadLevel;
+ }
+ else
+ {
+ throw new ArgumentException($"Expected object of type {nameof(ArchicadLevel)}");
+ }
+ }
+ }
+
+ [JsonIgnore]
+ public ArchicadLevel? archicadLevel { get; set; } /*APINullabe*/
+
+ public string? layer { get; set; } /*APINullabe*/
+
+ // Positioning
+ public Point begC { get; set; }
+ public Point endC { get; set; }
+ public bool? isSlanted { get; set; } /*APINullabe*/
+ public double? slantAngle { get; set; } /*APINullabe*/
+ public string? beamShape { get; set; } /*APINullabe*/
+ public int? sequence { get; set; } /*APINullabe*/
+ public double? curveAngle { get; set; } /*APINullabe*/
+ public double? verticalCurveHeight { get; set; } /*APINullabe*/
+ public bool? isFlipped { get; set; } /*APINullabe*/
+
+ // End Cuts
+ public uint? nCuts { get; set; } /*APINullabe*/
+ public Dictionary? Cuts { get; set; }
+
+ // Reference Axis
+ public short? anchorPoint { get; set; } /*APINullabe*/
+ public double? offset { get; set; }
+ public double? profileAngle { get; set; }
+
+ // Segment
+ public uint? nSegments { get; set; } /*APINullabe*/
+ public uint? nProfiles { get; set; } /*APINullabe*/
+ public Dictionary? segments { get; set; } /*APINullabe*/
+
+ // Scheme
+ public uint? nSchemes { get; set; }
+ public Dictionary? Schemes { get; set; }
+
+ // Hole
+ public Dictionary? Holes { get; set; }
+
+ // Floor Plan and Section - Floor Plan Display
+ public string? showOnStories { get; set; } /*APINullabe*/
+ public string? displayOptionName { get; set; } /*APINullabe*/
+ public string? uncutProjectionMode { get; set; } /*APINullabe*/
+ public string? overheadProjectionMode { get; set; } /*APINullabe*/
+ public string? showProjectionName { get; set; } /*APINullabe*/
+
+ // Floor Plan and Section - Cut Surfaces
+ public short? cutContourLinePen { get; set; }
+ public string? cutContourLineType { get; set; }
+ public short? overrideCutFillPen { get; set; }
+ public short? overrideCutFillBackgroundPen { get; set; }
+
+ // Floor Plan and Section - Outlines
+ public string? showOutline { get; set; } /*APINullabe*/
+ public short? uncutLinePen { get; set; } /*APINullabe*/
+ public string? uncutLinetype { get; set; } /*APINullabe*/
+ public short? overheadLinePen { get; set; } /*APINullabe*/
+ public string? overheadLinetype { get; set; } /*APINullabe*/
+ public short? hiddenLinePen { get; set; } /*APINullabe*/
+ public string? hiddenLinetype { get; set; } /*APINullabe*/
+
+ // Floor Plan and Section - Symbol
+ public string? showReferenceAxis { get; set; } /*APINullabe*/
+ public short? referencePen { get; set; } /*APINullabe*/
+ public string? referenceLinetype { get; set; } /*APINullabe*/
+
+ // Floor Plan and Section - Cover Fills
+ public bool? useCoverFill { get; set; } /*APINullabe*/
+ public bool? useCoverFillFromSurface { get; set; }
+ public short? coverFillForegroundPen { get; set; }
+ public short? coverFillBackgroundPen { get; set; }
+ public string? coverFillType { get; set; }
+ public string? coverFillTransformationType { get; set; }
+ public double? coverFillTransformationOrigoX { get; set; }
+ public double? coverFillTransformationOrigoY { get; set; }
+ public double? coverFillTransformationXAxisX { get; set; }
+ public double? coverFillTransformationXAxisY { get; set; }
+ public double? coverFillTransformationYAxisX { get; set; }
+ public double? coverFillTransformationYAxisY { get; set; }
+
+ public class BeamSegment : Base
+ {
+ // Segment override materials
+ public string? leftMaterial { get; set; }
+ public string? topMaterial { get; set; }
+ public string? rightMaterial { get; set; }
+ public string? bottomMaterial { get; set; }
+
+ public string? endsMaterial { get; set; }
+
+ // Segment - The overridden materials are chained
+ public bool? materialChained { get; set; }
+ public AssemblySegment assemblySegmentData { get; set; }
+ }
+}
diff --git a/src/Objects/BuiltElements/Archicad/ArchicadColumn.cs b/src/Objects/BuiltElements/Archicad/ArchicadColumn.cs
new file mode 100644
index 00000000..59693a90
--- /dev/null
+++ b/src/Objects/BuiltElements/Archicad/ArchicadColumn.cs
@@ -0,0 +1,144 @@
+using System;
+using System.Collections.Generic;
+using Objects.Geometry;
+using Speckle.Core.Kits;
+using Speckle.Core.Models;
+using Speckle.Newtonsoft.Json;
+
+namespace Objects.BuiltElements.Archicad;
+
+/*
+For further informations about given the variables, visit:
+https://archicadapi.graphisoft.com/documentation/api_columntype
+*/
+public class ArchicadColumn : Column
+{
+ [SchemaInfo("ArchicadColumn", "Creates an Archicad Column by curve.", "Archicad", "Structure")]
+ public ArchicadColumn() { }
+
+ // Element base
+ public string? elementType { get; set; } /*APINullabe*/
+
+ public List? classifications { get; set; } /*APINullabe*/
+ public Base? elementProperties { get; set; }
+ public Base? componentProperties { get; set; }
+
+ public override Level? level
+ {
+ get => archicadLevel;
+ internal set
+ {
+ if (value is ArchicadLevel or null)
+ {
+ archicadLevel = value as ArchicadLevel;
+ }
+ else
+ {
+ throw new ArgumentException($"Expected object of type {nameof(ArchicadLevel)}");
+ }
+ }
+ }
+
+ [JsonIgnore]
+ public ArchicadLevel? archicadLevel { get; set; } /*APINullabe*/
+
+ public string? layer { get; set; } /*APINullabe*/
+
+ // Wall geometry
+ public Point origoPos { get; set; }
+ public double height { get; set; }
+
+ // Positioning - story relation
+ public double? bottomOffset { get; set; } /*APINullabe*/
+ public double? topOffset { get; set; } /*APINullabe*/
+ public short? relativeTopStory { get; set; } /*APINullabe*/
+
+ // Positioning - slanted column
+ public bool? isSlanted { get; set; } /*APINullabe*/
+ public double? slantAngle { get; set; } /*APINullabe*/
+ public double? slantDirectionAngle { get; set; } /*APINullabe*/
+ public bool? isFlipped { get; set; } /*APINullabe*/
+
+ // Positioning - wrapping
+ public bool? wrapping { get; set; } /*APINullabe*/
+
+ // Positioning - Defines the relation of column to zones (Zone Boundary, Reduce Zone Area Only, No Effect on Zones)
+ public string? columnRelationToZoneName { get; set; } /*APINullabe*/
+
+ // End Cuts
+ public uint? nCuts { get; set; } /*APINullabe*/
+ public Dictionary? Cuts { get; set; } /*APINullabe*/
+
+ // Reference Axis
+ public short? coreAnchor { get; set; }
+ public double? axisRotationAngle { get; set; }
+
+ // Segment
+ public uint? nSegments { get; set; } /*APINullabe*/
+ public uint? nProfiles { get; set; } /*APINullabe*/
+ public Dictionary? segments { get; set; } /*APINullabe*/
+
+ // Scheme
+ public uint? nSchemes { get; set; }
+ public Dictionary? Schemes { get; set; }
+
+ // Floor Plan and Section - Floor Plan Display
+ public string? showOnStories { get; set; } /*APINullabe*/
+ public string? displayOptionName { get; set; } /*APINullabe*/
+ public string? showProjectionName { get; set; } /*APINullabe*/
+
+ // Floor Plan and Section - Cut Surfaces
+ public short? corePen { get; set; }
+ public string? contLtype { get; set; }
+ public short? venLinePen { get; set; }
+ public string? venLineType { get; set; }
+ public short? overrideCutFillPen { get; set; }
+ public short? overrideCutFillBackgroundPen { get; set; }
+
+ // Floor Plan and Section - Outlines
+ public short? uncutLinePen { get; set; } /*APINullabe*/
+ public string? uncutLinetype { get; set; } /*APINullabe*/
+ public short? overheadLinePen { get; set; } /*APINullabe*/
+ public string? overheadLinetype { get; set; } /*APINullabe*/
+ public short? hiddenLinePen { get; set; } /*APINullabe*/
+ public string? hiddenLinetype { get; set; } /*APINullabe*/
+
+ // Floor Plan and Section - Floor Plan Symbol
+ public string? coreSymbolTypeName { get; set; } /*APINullabe*/
+ public double? coreSymbolPar1 { get; set; } /*APINullabe*/
+ public double? coreSymbolPar2 { get; set; } /*APINullabe*/
+ public short? coreSymbolPen { get; set; } /*APINullabe*/
+
+ // Floor Plan and Section - Cover Fills
+ public bool? useCoverFill { get; set; } /*APINullabe*/
+ public bool? useCoverFillFromSurface { get; set; }
+ public short? coverFillForegroundPen { get; set; }
+ public short? coverFillBackgroundPen { get; set; }
+ public string? coverFillType { get; set; }
+ public string? coverFillTransformationType { get; set; }
+ public double? coverFillTransformationOrigoX { get; set; }
+ public double? coverFillTransformationOrigoY { get; set; }
+ public double? coverFillTransformationXAxisX { get; set; }
+ public double? coverFillTransformationXAxisY { get; set; }
+ public double? coverFillTransformationYAxisX { get; set; }
+ public double? coverFillTransformationYAxisY { get; set; }
+
+ public class ColumnSegment : Base
+ {
+ // Segment - Veneer attributes
+ public string? veneerType { get; set; }
+ public string? veneerBuildingMaterial { get; set; }
+
+ public double? veneerThick { get; set; }
+
+ // Segment - The extrusion overridden material name
+ public string? extrusionSurfaceMaterial { get; set; }
+
+ // Segment - The ends overridden material name
+ public string? endsSurfaceMaterial { get; set; }
+
+ // Segment - The overridden materials are chained
+ public bool? materialChained { get; set; }
+ public AssemblySegment assemblySegmentData { get; set; }
+ }
+}
diff --git a/src/Objects/BuiltElements/Archicad/ArchicadFloor.cs b/src/Objects/BuiltElements/Archicad/ArchicadFloor.cs
new file mode 100644
index 00000000..734ad06d
--- /dev/null
+++ b/src/Objects/BuiltElements/Archicad/ArchicadFloor.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+using Speckle.Core.Models;
+using Speckle.Newtonsoft.Json;
+
+namespace Objects.BuiltElements.Archicad;
+
+/*
+For further informations about given the variables, visit:
+https://archicadapi.graphisoft.com/documentation/api_slabtype
+*/
+public sealed class ArchicadFloor : Floor
+{
+ // Element base
+ public string? elementType { get; set; } /*APINullable*/
+
+ public List? classifications { get; set; } /*APINullable*/
+ public Base? elementProperties { get; set; }
+ public Base? componentProperties { get; set; }
+
+ public override Level? level
+ {
+ get => archicadLevel;
+ internal set
+ {
+ if (value is ArchicadLevel or null)
+ {
+ archicadLevel = value as ArchicadLevel;
+ }
+ else
+ {
+ throw new ArgumentException($"Expected object of type {nameof(ArchicadLevel)}");
+ }
+ }
+ }
+
+ [JsonIgnore]
+ public ArchicadLevel? archicadLevel { get; set; } /*APINullabe*/
+
+ public string? layer { get; set; } /*APINullabe*/
+
+ // Geometry and positioning
+ public double? thickness { get; set; }
+ public ElementShape shape { get; set; }
+ public string? structure { get; set; } /*APINullabe*/
+ public string? compositeName { get; set; }
+ public string? buildingMaterialName { get; set; }
+ public string? referencePlaneLocation { get; set; } /*APINullabe*/
+
+ // EdgeTrims
+ public string? edgeAngleType { get; set; }
+ public double? edgeAngle { get; set; }
+
+ // Floor Plan and Section - Floor Plan Display
+ public string? showOnStories { get; set; } /*APINullabe*/
+ public Visibility? visibilityCont { get; set; }
+ public Visibility? visibilityFill { get; set; }
+
+ // Floor Plan and Section - Cut Surfaces
+ public short? sectContPen { get; set; }
+ public string? sectContLtype { get; set; }
+ public short? cutFillPen { get; set; }
+ public short? cutFillBackgroundPen { get; set; }
+
+ // Floor Plan and Section - Outlines
+ public short? contourPen { get; set; }
+ public string? contourLineType { get; set; }
+ public short? hiddenContourLinePen { get; set; }
+ public string? hiddenContourLineType { get; set; }
+
+ // Floor Plan and Section - Cover Fills
+ public bool? useFloorFill { get; set; }
+ public short? floorFillPen { get; set; }
+ public short? floorFillBGPen { get; set; }
+ public string? floorFillName { get; set; }
+ public bool? use3DHatching { get; set; }
+ public string? hatchOrientation { get; set; }
+ public double? hatchOrientationOrigoX { get; set; }
+ public double? hatchOrientationOrigoY { get; set; }
+ public double? hatchOrientationXAxisX { get; set; }
+ public double? hatchOrientationXAxisY { get; set; }
+ public double? hatchOrientationYAxisX { get; set; }
+ public double? hatchOrientationYAxisY { get; set; }
+
+ // Model
+ public string? topMat { get; set; }
+ public string? sideMat { get; set; }
+ public string? botMat { get; set; }
+ public bool? materialsChained { get; set; }
+
+ public class Visibility : Base
+ {
+ public bool? showOnHome { get; set; }
+ public bool? showAllAbove { get; set; }
+ public bool? showAllBelow { get; set; }
+ public short? showRelAbove { get; set; }
+ public short? showRelBelow { get; set; }
+ }
+}
diff --git a/src/Objects/BuiltElements/Archicad/ArchicadLevel.cs b/src/Objects/BuiltElements/Archicad/ArchicadLevel.cs
new file mode 100644
index 00000000..92f33df8
--- /dev/null
+++ b/src/Objects/BuiltElements/Archicad/ArchicadLevel.cs
@@ -0,0 +1,24 @@
+namespace Objects.BuiltElements.Archicad;
+
+/*
+For further informations about given the variables, visit:
+https://archicadapi.graphisoft.com/documentation/api_storytype
+*/
+public class ArchicadLevel : Level
+{
+ public short index { get; set; }
+
+ public ArchicadLevel() { }
+
+ public ArchicadLevel(string name, double elevation, short index)
+ {
+ this.name = name;
+ this.elevation = elevation;
+ this.index = index;
+ }
+
+ public ArchicadLevel(string name)
+ {
+ this.name = name;
+ }
+}
diff --git a/src/Objects/BuiltElements/Archicad/ArchicadRoof.cs b/src/Objects/BuiltElements/Archicad/ArchicadRoof.cs
new file mode 100644
index 00000000..6cf965b9
--- /dev/null
+++ b/src/Objects/BuiltElements/Archicad/ArchicadRoof.cs
@@ -0,0 +1,277 @@
+using System;
+using System.Collections.Generic;
+using Objects.Geometry;
+using Objects.Other;
+using Speckle.Core.Models;
+using Speckle.Newtonsoft.Json;
+
+namespace Objects.BuiltElements.Archicad;
+
+/*
+For further informations about given the variables, visit:
+https://archicadapi.graphisoft.com/documentation/api_shellbasetype
+*/
+public class ArchicadShellBase : BuiltElements.Roof
+{
+ public class Visibility : Base
+ {
+ public bool? showOnHome { get; set; }
+ public bool? showAllAbove { get; set; }
+ public bool? showAllBelow { get; set; }
+ public short? showRelAbove { get; set; }
+ public short? showRelBelow { get; set; }
+ }
+
+ // Element base
+ public string? elementType { get; set; } /*APINullabe*/
+
+ public List? classifications { get; set; } /*APINullabe*/
+ public Base? elementProperties { get; set; }
+ public Base? componentProperties { get; set; }
+
+ public override Level? level
+ {
+ get => archicadLevel;
+ internal set
+ {
+ if (value is ArchicadLevel or null)
+ {
+ archicadLevel = value as ArchicadLevel;
+ }
+ else
+ {
+ throw new ArgumentException($"Expected object of type {nameof(ArchicadLevel)}");
+ }
+ }
+ }
+
+ [JsonIgnore]
+ public ArchicadLevel? archicadLevel { get; set; } /*APINullabe*/
+
+ public string? layer { get; set; } /*APINullabe*/
+
+ // Geometry and positioning
+ public double? thickness { get; set; }
+ public string? structure { get; set; } /*APINullabe*/
+ public string? compositeName { get; set; }
+ public string? buildingMaterialName { get; set; }
+
+ // EdgeTrims
+ public string? edgeAngleType { get; set; }
+ public double? edgeAngle { get; set; }
+
+ // Floor Plan and Section - Floor Plan Display
+ public string? showOnStories { get; set; } /*APINullabe*/
+ public Visibility? visibilityCont { get; set; }
+ public Visibility? visibilityFill { get; set; }
+ public string? displayOptionName { get; set; } /*APINullabe*/
+ public string? showProjectionName { get; set; } /*APINullabe*/
+
+ // Floor Plan and Section - Cut Surfaces
+ public short? sectContPen { get; set; } /*APINullabe*/
+ public string? sectContLtype { get; set; } /*APINullabe*/
+ public short? cutFillPen { get; set; }
+ public short? cutFillBackgroundPen { get; set; }
+
+ // Floor Plan and Section - Outlines
+ public short? contourPen { get; set; } /*APINullabe*/
+ public string? contourLineType { get; set; } /*APINullabe*/
+ public short? overheadLinePen { get; set; } /*APINullabe*/
+ public string? overheadLinetype { get; set; } /*APINullabe*/
+
+ // Floor Plan and Section - Cover Fills
+ public bool? useFloorFill { get; set; } /*APINullabe*/
+ public short? floorFillPen { get; set; }
+ public short? floorFillBGPen { get; set; }
+ public string? floorFillName { get; set; }
+ public bool? use3DHatching { get; set; }
+ public bool? useFillLocBaseLine { get; set; }
+ public bool? useSlantedFill { get; set; }
+ public string? hatchOrientation { get; set; }
+ public double? hatchOrientationOrigoX { get; set; }
+ public double? hatchOrientationOrigoY { get; set; }
+ public double? hatchOrientationXAxisX { get; set; }
+ public double? hatchOrientationXAxisY { get; set; }
+ public double? hatchOrientationYAxisX { get; set; }
+ public double? hatchOrientationYAxisY { get; set; }
+
+ // Model
+ public string? topMat { get; set; }
+ public string? sideMat { get; set; }
+ public string? botMat { get; set; }
+ public bool? materialsChained { get; set; }
+ public string? trimmingBodyName { get; set; } /*APINullabe*/
+}
+
+/*
+For further informations about given the variables, visit:
+https://archicadapi.graphisoft.com/documentation/api_rooftype
+*/
+public sealed class ArchicadRoof : ArchicadShellBase
+{
+ public class BaseLine : Base
+ {
+ public Point begC { get; set; }
+ public Point endC { get; set; }
+ }
+
+ public class RoofLevel : Base
+ {
+ public double? levelHeight { get; set; }
+ public double? levelAngle { get; set; }
+ }
+
+ public class LevelEdge : Base
+ {
+ public double? edgeLevelAngle { get; set; }
+ public double? eavesOverhang { get; set; }
+ public string? topMaterial { get; set; }
+ public string? bottomMaterial { get; set; }
+ public string? coverFillType { get; set; }
+ public string? angleType { get; set; }
+ }
+
+ public class PivotPolyEdge : Base
+ {
+ public int? nLevelEdgeData { get; set; }
+ public Dictionary? roofLevels { get; set; }
+ }
+
+ // Geometry and positioning
+ public string roofClassName { get; set; }
+ public double? planeRoofAngle { get; set; }
+ public ElementShape shape { get; set; }
+ public BaseLine? baseLine { get; set; }
+ public bool? posSign { get; set; }
+ public ElementShape? pivotPolygon { get; set; } /*APINullabe*/
+ public short? levelNum { get; set; }
+ public Dictionary? levels { get; set; } /*APINullabe*/
+ public Dictionary? roofPivotPolyEdges { get; set; }
+}
+
+/*
+For further informations about given the variables, visit:
+https://archicadapi.graphisoft.com/documentation/api_shelltype
+*/
+public sealed class ArchicadShell : ArchicadShellBase
+{
+ public class ShellContourEdgeData : Base
+ {
+ public string? sideTypeName { get; set; }
+ public double? sideAngle { get; set; }
+ public string? edgeTypeName { get; set; }
+ public string? edgeSideMaterial { get; set; }
+ }
+
+ public class ShellContourData : Base
+ {
+ public ElementShape? shellContourPoly { get; set; }
+ public Transform shellContourPlane { get; set; }
+ public double? shellContourHeight { get; set; }
+ public int? shellContourID { get; set; }
+ public Dictionary? shellContourEdges { get; set; }
+ }
+
+ // Geometry and positioning
+ public string? shellClassName { get; set; } /*APINullabe*/
+ public Transform? basePlane { get; set; } /*APINullabe*/
+ public bool? flipped { get; set; } /*APINullabe*/
+ public bool? hasContour { get; set; } /*APINullabe*/
+ public int? numHoles { get; set; } /*APINullabe*/
+ public Dictionary? shellContours { get; set; }
+ public string? defaultEdgeType { get; set; } /*APINullabe*/
+
+ public double? slantAngle { get; set; }
+ public double? revolutionAngle { get; set; }
+ public double? distortionAngle { get; set; }
+ public bool? segmentedSurfaces { get; set; }
+ public double? shapePlaneTilt { get; set; }
+ public double? begPlaneTilt { get; set; }
+ public double? endPlaneTilt { get; set; }
+ public ElementShape shape { get; set; }
+ public ElementShape? shape1 { get; set; } /*APINullabe*/
+ public ElementShape? shape2 { get; set; } /*APINullabe*/
+ public Transform? axisBase { get; set; } /*APINullabe*/
+ public Transform? plane1 { get; set; } /*APINullabe*/
+ public Transform? plane2 { get; set; } /*APINullabe*/
+ public Point? begC { get; set; }
+ public double? begAngle { get; set; }
+ public Vector? extrusionVector { get; set; }
+ public Vector? shapeDirection { get; set; }
+ public Vector? distortionVector { get; set; }
+ public string? morphingRuleName { get; set; }
+
+ // Model
+ public class BegShapeEdge : Base
+ {
+ public string? begShapeEdgeTrimSideType { get; set; }
+ public double? begShapeEdgeTrimSideAngle { get; set; }
+ public string? begShapeEdgeSideMaterial { get; set; }
+ public string? begShapeEdgeType { get; set; }
+ }
+
+ public class EndShapeEdge : Base
+ {
+ public string? endShapeEdgeTrimSideType { get; set; }
+ public double? endShapeEdgeTrimSideAngle { get; set; }
+ public string? endShapeEdgeSideMaterial { get; set; }
+ public string? endShapeEdgeType { get; set; }
+ }
+
+ public class ExtrudedEdge1 : Base
+ {
+ public string? extrudedEdgeTrimSideType1 { get; set; }
+ public double? extrudedEdgeTrimSideAngle1 { get; set; }
+ public string? extrudedEdgeSideMaterial1 { get; set; }
+ public string? extrudedEdgeType1 { get; set; }
+ }
+
+ public class ExtrudedEdge2 : Base
+ {
+ public string? extrudedEdgeTrimSideType2 { get; set; }
+ public double? extrudedEdgeTrimSideAngle2 { get; set; }
+ public string? extrudedEdgeSideMaterial2 { get; set; }
+ public string? extrudedEdgeType2 { get; set; }
+ }
+
+ public class RevolvedEdge1 : Base
+ {
+ public string? revolvedEdgeTrimSideType1 { get; set; }
+ public double? revolvedEdgeTrimSideAngle1 { get; set; }
+ public string? revolvedEdgeSideMaterial1 { get; set; }
+ public string? revolvedEdgeType1 { get; set; }
+ }
+
+ public class RevolvedEdge2 : Base
+ {
+ public string? revolvedEdgeTrimSideType2 { get; set; }
+ public double? revolvedEdgeTrimSideAngle2 { get; set; }
+ public string? revolvedEdgeSideMaterial2 { get; set; }
+ public string? revolvedEdgeType2 { get; set; }
+ }
+
+ public class RuledEdge1 : Base
+ {
+ public string? ruledEdgeTrimSideType1 { get; set; }
+ public double? ruledEdgeTrimSideAngle1 { get; set; }
+ public string? ruledEdgeSideMaterial1 { get; set; }
+ public string? ruledEdgeType1 { get; set; }
+ }
+
+ public class RuledEdge2 : Base
+ {
+ public string? ruledEdgeTrimSideType2 { get; set; }
+ public double? ruledEdgeTrimSideAngle2 { get; set; }
+ public string? ruledEdgeSideMaterial2 { get; set; }
+ public string? ruledEdgeType2 { get; set; }
+ }
+
+ public BegShapeEdge? begShapeEdge { get; set; }
+ public EndShapeEdge? endShapeEdge { get; set; }
+ public ExtrudedEdge1? extrudedEdge1 { get; set; }
+ public ExtrudedEdge2? extrudedEdge2 { get; set; }
+ public RevolvedEdge1? revolvedEdge1 { get; set; }
+ public RevolvedEdge2? revolvedEdge2 { get; set; }
+ public RuledEdge1? ruledEdge1 { get; set; }
+ public RuledEdge2? ruledEdge2 { get; set; }
+}
diff --git a/src/Objects/BuiltElements/Archicad/ArchicadRoom.cs b/src/Objects/BuiltElements/Archicad/ArchicadRoom.cs
new file mode 100644
index 00000000..993ba553
--- /dev/null
+++ b/src/Objects/BuiltElements/Archicad/ArchicadRoom.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using Speckle.Core.Models;
+using Speckle.Newtonsoft.Json;
+
+namespace Objects.BuiltElements.Archicad;
+
+/*
+For further informations about given the variables, visit:
+https://archicadapi.graphisoft.com/documentation/api_zonetype
+*/
+public class ArchicadRoom : Room
+{
+ // Element base
+ public string elementType { get; set; }
+
+ public List classifications { get; set; }
+ public Base? elementProperties { get; set; }
+ public Base? componentProperties { get; set; }
+
+ public override Level? level
+ {
+ get => archicadLevel;
+ set => archicadLevel = value as ArchicadLevel ?? null;
+ }
+
+ [JsonIgnore]
+ public ArchicadLevel? archicadLevel { get; set; }
+
+ public string? layer { get; set; } /*APINullabe*/
+
+ public ElementShape shape { get; set; }
+}
diff --git a/src/Objects/BuiltElements/Archicad/ArchicadWall.cs b/src/Objects/BuiltElements/Archicad/ArchicadWall.cs
new file mode 100644
index 00000000..30471504
--- /dev/null
+++ b/src/Objects/BuiltElements/Archicad/ArchicadWall.cs
@@ -0,0 +1,123 @@
+using System;
+using System.Collections.Generic;
+using Objects.Geometry;
+using Speckle.Core.Kits;
+using Speckle.Core.Models;
+using Speckle.Newtonsoft.Json;
+
+namespace Objects.BuiltElements.Archicad;
+
+/*
+For further informations about given the variables, visit:
+https://archicadapi.graphisoft.com/documentation/api_walltype
+*/
+public class ArchicadWall : Wall
+{
+ [SchemaInfo("ArchicadWall", "Creates an Archicad wall.", "Archicad", "Structure")]
+ public ArchicadWall() { }
+
+ // Element base
+ public string? elementType { get; set; } /*APINullabe*/
+
+ public List? classifications { get; set; } /*APINullabe*/
+ public Base? elementProperties { get; set; }
+ public Base? componentProperties { get; set; }
+
+ public override Level? level
+ {
+ get => archicadLevel;
+ internal set
+ {
+ if (value is ArchicadLevel or null)
+ {
+ archicadLevel = value as ArchicadLevel;
+ }
+ else
+ {
+ throw new ArgumentException($"Expected object of type {nameof(ArchicadLevel)}");
+ }
+ }
+ }
+
+ [JsonIgnore]
+ public ArchicadLevel? archicadLevel { get; set; } /*APINullabe*/
+
+ public string? layer { get; set; } /*APINullabe*/
+
+ // Wall geometry
+ public double? baseOffset { get; set; } /*APINullabe*/
+ public Point startPoint { get; set; }
+ public Point endPoint { get; set; }
+
+ public string? structure { get; set; } /*APINullabe*/
+ public string? geometryMethod { get; set; } /*APINullabe*/
+ public string? wallComplexity { get; set; } /*APINullabe*/
+
+ public string? buildingMaterialName { get; set; }
+ public string? compositeName { get; set; }
+ public string? profileName { get; set; }
+ public double? arcAngle { get; set; }
+
+ public ElementShape? shape { get; set; }
+
+ public double? thickness { get; set; } /*APINullabe*/
+
+ public double? outsideSlantAngle { get; set; }
+ public double? insideSlantAngle { get; set; }
+
+ public bool? polyWalllCornersCanChange { get; set; }
+
+ // Wall and stories relation
+ public double? topOffset { get; set; } /*APINullabe*/
+ public short? relativeTopStory { get; set; } /*APINullabe*/
+ public string? referenceLineLocation { get; set; } /*APINullabe*/
+ public double? referenceLineOffset { get; set; }
+ public double? offsetFromOutside { get; set; } /*APINullabe*/
+ public int? referenceLineStartIndex { get; set; } /*APINullabe*/
+ public int? referenceLineEndIndex { get; set; } /*APINullabe*/
+ public bool flipped { get; set; }
+
+ // Floor Plan and Section - Floor Plan Display
+ public string? showOnStories { get; set; } /*APINullabe*/
+ public string? displayOptionName { get; set; } /*APINullabe*/
+ public string? showProjectionName { get; set; } /*APINullabe*/
+
+ // Floor Plan and Section - Cut Surfaces parameters
+ public short? cutLinePen { get; set; }
+ public string? cutLinetype { get; set; }
+ public short? overrideCutFillPen { get; set; }
+ public short? overrideCutFillBackgroundPen { get; set; }
+
+ // Floor Plan and Section - Outlines parameters
+ public short? uncutLinePen { get; set; } /*APINullabe*/
+ public string? uncutLinetype { get; set; } /*APINullabe*/
+ public short? overheadLinePen { get; set; } /*APINullabe*/
+ public string? overheadLinetype { get; set; } /*APINullabe*/
+
+ // Model - Override Surfaces
+ public string? referenceMaterialName { get; set; }
+ public int? referenceMaterialStartIndex { get; set; }
+ public int? referenceMaterialEndIndex { get; set; }
+ public string? oppositeMaterialName { get; set; }
+ public int? oppositeMaterialStartIndex { get; set; }
+ public int? oppositeMaterialEndIndex { get; set; }
+ public string? sideMaterialName { get; set; }
+ public bool? materialsChained { get; set; } /*APINullabe*/
+ public bool? inheritEndSurface { get; set; } /*APINullabe*/
+ public bool? alignTexture { get; set; } /*APINullabe*/
+ public int? sequence { get; set; } /*APINullabe*/
+
+ // Model - Log Details (log height, start with half log, surface of horizontal edges, log shape)
+ public double? logHeight { get; set; }
+ public bool? startWithHalfLog { get; set; }
+ public string? surfaceOfHorizontalEdges { get; set; }
+ public string? logShape { get; set; }
+
+ // Model - Defines the relation of wall to zones (Zone Boundary, Reduce Zone Area Only, No Effect on Zones)
+ public string? wallRelationToZoneName { get; set; } /*APINullabe*/
+
+ // Does it have any embedded object?
+ public bool? hasDoor { get; set; } /*APINullabe*/
+
+ public bool? hasWindow { get; set; } /*APINullabe*/
+}
diff --git a/src/Objects/BuiltElements/Archicad/AssemblySegment.cs b/src/Objects/BuiltElements/Archicad/AssemblySegment.cs
new file mode 100644
index 00000000..b3224562
--- /dev/null
+++ b/src/Objects/BuiltElements/Archicad/AssemblySegment.cs
@@ -0,0 +1,61 @@
+using Speckle.Core.Models;
+
+namespace Objects.BuiltElements.Archicad;
+
+public class AssemblySegment : Base
+{
+ public bool circleBased { get; set; }
+
+ public string modelElemStructureType { get; set; }
+
+ public double nominalHeight { get; set; }
+
+ public double nominalWidth { get; set; }
+
+ public bool isHomogeneous { get; set; }
+
+ public double endWidth { get; set; }
+
+ public double endHeight { get; set; }
+
+ public bool isEndWidthAndHeightLinked { get; set; }
+
+ public bool isWidthAndHeightLinked { get; set; }
+
+ public string profileAttrName { get; set; }
+
+ public string buildingMaterial { get; set; }
+}
+
+public class AssemblySegmentScheme : Base
+{
+ public string lengthType { get; set; }
+
+ public double fixedLength { get; set; }
+
+ public double lengthProportion { get; set; }
+}
+
+public class AssemblySegmentCut : Base
+{
+ public string cutType { get; set; }
+
+ public double customAngle { get; set; }
+}
+
+public class Hole : Base
+{
+ public string holeType { get; set; }
+
+ public bool holeContourOn { get; set; }
+
+ public int holeId { get; set; }
+
+ public double centerx { get; set; }
+
+ public double centerz { get; set; }
+
+ public double width { get; set; }
+
+ public double height { get; set; }
+}
diff --git a/src/Objects/BuiltElements/Archicad/Classification.cs b/src/Objects/BuiltElements/Archicad/Classification.cs
new file mode 100644
index 00000000..ef78cd14
--- /dev/null
+++ b/src/Objects/BuiltElements/Archicad/Classification.cs
@@ -0,0 +1,21 @@
+using Speckle.Core.Kits;
+using Speckle.Core.Models;
+
+namespace Objects.BuiltElements.Archicad;
+
+public class Classification : Base
+{
+ public Classification() { }
+
+ [SchemaInfo("Classification", "A classification to set on an element", "BIM", "All")]
+ public Classification(string system, string? code = null, string? name = null)
+ {
+ this.system = system;
+ this.code = code;
+ this.name = name;
+ }
+
+ public string system { get; set; }
+ public string? code { get; set; }
+ public string? name { get; set; }
+}
diff --git a/src/Objects/BuiltElements/Archicad/ComponentProperties.cs b/src/Objects/BuiltElements/Archicad/ComponentProperties.cs
new file mode 100644
index 00000000..8183626f
--- /dev/null
+++ b/src/Objects/BuiltElements/Archicad/ComponentProperties.cs
@@ -0,0 +1,50 @@
+using System.Collections.Generic;
+using Speckle.Core.Kits;
+using Speckle.Core.Models;
+
+namespace Objects.BuiltElements.Archicad;
+
+public class ComponentProperties : Base
+{
+ public ComponentProperties() { }
+
+ [SchemaInfo("ComponentProperties", "An Archicad element component properties", "Archicad", "Elements")]
+ public ComponentProperties(
+ string name,
+ List propertyGroups,
+ [SchemaParamInfo("(Optional) Speckle units.")] string units = ""
+ )
+ {
+ this.name = name;
+ this.propertyGroups = propertyGroups;
+ this.units = units;
+ }
+
+ public string name { get; set; }
+ public List? propertyGroups { get; set; }
+ public string units { get; set; }
+
+ ///
+ /// Turns a List of ComponentProperties into a Base so that it can be used with the Speckle properties prop
+ ///
+ ///
+ ///
+ public static Base? ToBase(List? componentPropertiesList)
+ {
+ if (componentPropertiesList == null || componentPropertiesList.Count == 0)
+ {
+ return null;
+ }
+
+ var @base = new Base();
+
+ foreach (ComponentProperties componentProperties in componentPropertiesList)
+ {
+ @base[RemoveDisallowedPropNameChars(componentProperties.name)] = PropertyGroup.ToBase(
+ componentProperties.propertyGroups
+ );
+ }
+
+ return @base;
+ }
+}
diff --git a/src/Objects/BuiltElements/Archicad/DirectShape.cs b/src/Objects/BuiltElements/Archicad/DirectShape.cs
new file mode 100644
index 00000000..8b2f11ca
--- /dev/null
+++ b/src/Objects/BuiltElements/Archicad/DirectShape.cs
@@ -0,0 +1,27 @@
+using System.Collections.Generic;
+using Objects.Geometry;
+using Speckle.Core.Models;
+
+namespace Objects.BuiltElements.Archicad;
+
+public class DirectShape : Base
+{
+ public DirectShape() { }
+
+ public DirectShape(string applicationId, List displayValue)
+ {
+ this.applicationId = applicationId;
+ this.displayValue = displayValue;
+ }
+
+ // Element base
+ public string elementType { get; set; }
+ public List classifications { get; set; }
+
+ public ArchicadLevel level { get; set; }
+
+ public string units { get; set; }
+
+ [DetachProperty]
+ public List displayValue { get; set; }
+}
diff --git a/src/Objects/BuiltElements/Archicad/ElementShape.cs b/src/Objects/BuiltElements/Archicad/ElementShape.cs
new file mode 100644
index 00000000..4da45cb3
--- /dev/null
+++ b/src/Objects/BuiltElements/Archicad/ElementShape.cs
@@ -0,0 +1,55 @@
+using System.Collections.Generic;
+using Objects.Geometry;
+using Objects.Primitive;
+using Speckle.Core.Models;
+
+namespace Objects.BuiltElements.Archicad;
+
+public sealed class ElementShape : Base
+{
+ public ElementShape() { }
+
+ public ElementShape(Polyline contourPolyline, List? holePolylines = null)
+ {
+ this.contourPolyline = contourPolyline;
+ this.holePolylines = holePolylines;
+ }
+
+ public Polyline contourPolyline { get; set; }
+
+ public List? holePolylines { get; set; }
+
+ public sealed class PolylineSegment : Base, ICurve
+ {
+ public PolylineSegment() { }
+
+ public PolylineSegment(Point startPoint, Point endPoint, double? arcAngle = null, bool? bodyFlag = null)
+ {
+ this.startPoint = startPoint;
+ this.endPoint = endPoint;
+ this.arcAngle = arcAngle ?? 0;
+ this.bodyFlag = bodyFlag;
+ }
+
+ public Point startPoint { get; set; }
+ public Point endPoint { get; set; }
+ public double arcAngle { get; set; }
+ public bool? bodyFlag { get; set; }
+ public double length { get; set; }
+ public Interval domain { get; set; } = new(0, 1);
+ }
+
+ public sealed class Polyline : Base, ICurve
+ {
+ public Polyline() { }
+
+ public Polyline(List segments)
+ {
+ polylineSegments = segments;
+ }
+
+ public List polylineSegments { get; set; } = new();
+ public double length { get; set; }
+ public Interval domain { get; set; } = new(0, 1);
+ }
+}
diff --git a/src/Objects/BuiltElements/Archicad/Fenestration.cs b/src/Objects/BuiltElements/Archicad/Fenestration.cs
new file mode 100644
index 00000000..ce262f92
--- /dev/null
+++ b/src/Objects/BuiltElements/Archicad/Fenestration.cs
@@ -0,0 +1,77 @@
+using System.Collections.Generic;
+using Objects.Geometry;
+using Speckle.Core.Models;
+
+namespace Objects.BuiltElements.Archicad;
+
+public class ArchicadFenestration : Base, IDisplayValue>
+{
+ public string parentApplicationId { get; set; }
+
+ // Element base
+ public string? elementType { get; set; } /*APINullabe*/
+
+ public List? classifications { get; set; } /*APINullabe*/
+ public Base? elementProperties { get; set; }
+ public Base? componentProperties { get; set; }
+
+ public double? width { get; set; } /*APINullabe*/
+ public double? height { get; set; } /*APINullabe*/
+ public double? subFloorThickness { get; set; } /*APINullabe*/
+ public bool? reflected { get; set; } /*APINullabe*/
+ public bool? oSide { get; set; } /*APINullabe*/
+ public bool? refSide { get; set; } /*APINullabe*/
+ public string? verticalLinkTypeName { get; set; }
+ public short? verticalLinkStoryIndex { get; set; }
+ public bool? wallCutUsing { get; set; }
+ public short? pen { get; set; } /*APINullabe*/
+ public string? lineTypeName { get; set; } /*APINullabe*/
+ public string? buildingMaterial { get; set; } /*APINullabe*/
+ public string? sectFill { get; set; } /*APINullabe*/
+ public short? sectFillPen { get; set; } /*APINullabe*/
+ public short? sectBackgroundPen { get; set; } /*APINullabe*/
+ public short? sectContPen { get; set; } /*APINullabe*/
+ public string? cutLineType { get; set; } /*APINullabe*/
+ public string? aboveViewLineType { get; set; } /*APINullabe*/
+ public short? aboveViewLinePen { get; set; } /*APINullabe*/
+ public short? belowViewLinePen { get; set; } /*APINullabe*/
+ public string? belowViewLineType { get; set; } /*APINullabe*/
+ public bool? useObjectPens { get; set; } /*APINullabe*/
+ public bool? useObjLinetypes { get; set; } /*APINullabe*/
+ public bool? useObjMaterials { get; set; } /*APINullabe*/
+ public bool? useObjSectAttrs { get; set; } /*APINullabe*/
+ public string? libraryPart { get; set; } /*APINullabe*/
+ public string? displayOptionName { get; set; } /*APINullabe*/
+
+ [DetachProperty]
+ public List displayValue { get; set; }
+}
+
+public class ArchicadDoorWindowBase : ArchicadFenestration
+{
+ public double? revealDepthFromSide { get; set; } /*APINullabe*/
+ public double? jambDepthHead { get; set; } /*APINullabe*/
+ public double? jambDepth { get; set; } /*APINullabe*/
+ public double? jambDepth2 { get; set; } /*APINullabe*/
+ public double? objLoc { get; set; } /*APINullabe*/
+ public double? lower { get; set; } /*APINullabe*/
+ public string? directionType { get; set; } /*APINullabe*/
+
+ public Point? startPoint { get; set; } /*APINullabe*/
+ public Point? dirVector { get; set; } /*APINullabe*/
+}
+
+public sealed class ArchicadDoor : ArchicadDoorWindowBase { }
+
+public sealed class ArchicadWindow : ArchicadDoorWindowBase { }
+
+public sealed class ArchicadSkylight : ArchicadFenestration
+{
+ public uint? vertexID { get; set; } /*APINullabe*/
+ public string? skylightFixMode { get; set; } /*APINullabe*/
+ public string? skylightAnchor { get; set; } /*APINullabe*/
+ public Point? anchorPosition { get; set; } /*APINullabe*/
+ public double? anchorLevel { get; set; } /*APINullabe*/
+ public double? azimuthAngle { get; set; } /*APINullabe*/
+ public double? elevationAngle { get; set; } /*APINullabe*/
+}
diff --git a/src/Objects/BuiltElements/Archicad/Property.cs b/src/Objects/BuiltElements/Archicad/Property.cs
new file mode 100644
index 00000000..d7682bce
--- /dev/null
+++ b/src/Objects/BuiltElements/Archicad/Property.cs
@@ -0,0 +1,54 @@
+using System.Collections.Generic;
+using Speckle.Core.Kits;
+using Speckle.Core.Models;
+
+namespace Objects.BuiltElements.Archicad;
+
+public class Property : Base
+{
+ public Property() { }
+
+ [SchemaInfo("Property", "An Archicad element property", "Archicad", "Elements")]
+ public Property(string name, object value, [SchemaParamInfo("(Optional) Speckle units.")] string units = "")
+ {
+ this.name = name;
+ this.value = value;
+ this.units = units;
+ }
+
+ public string name { get; set; }
+ public object? value { get; set; }
+ public List