├── ui
├── public
│ ├── robots.txt
│ ├── favicon.ico
│ ├── img
│ │ └── icons
│ │ │ ├── favicon-16x16.png
│ │ │ ├── favicon-32x32.png
│ │ │ ├── mstile-150x150.png
│ │ │ ├── apple-touch-icon.png
│ │ │ ├── android-chrome-192x192.png
│ │ │ ├── android-chrome-512x512.png
│ │ │ ├── apple-touch-icon-120x120.png
│ │ │ ├── apple-touch-icon-152x152.png
│ │ │ ├── apple-touch-icon-180x180.png
│ │ │ ├── apple-touch-icon-60x60.png
│ │ │ ├── apple-touch-icon-76x76.png
│ │ │ ├── msapplication-icon-144x144.png
│ │ │ ├── android-chrome-maskable-192x192.png
│ │ │ ├── android-chrome-maskable-512x512.png
│ │ │ └── safari-pinned-tab.svg
│ └── index.html
├── .browserslistrc
├── babel.config.js
├── src
│ ├── assets
│ │ ├── Sender.png
│ │ ├── Receiver.png
│ │ ├── SenderWhite.png
│ │ ├── brick_white.png
│ │ ├── ReceiverWhite.png
│ │ └── logo.svg
│ ├── graphql
│ │ ├── serverInfo.gql
│ │ ├── userById.gql
│ │ ├── user.gql
│ │ ├── stream.gql
│ │ └── streams.gql
│ ├── router
│ │ └── index.js
│ ├── utils
│ │ └── groupBy.js
│ ├── views
│ │ └── Login.vue
│ ├── main.js
│ └── plugins
│ │ └── vuetify.js
├── .env.example
├── vue.config.js
├── .gitignore
├── .prettierrc
├── README.md
├── .eslintrc.js
├── apollo.config.js
└── package.json
├── .DS_Store
├── .gitmodules
├── _tools
├── jf_RubyPanel
│ ├── reload.png
│ ├── Delete24.png
│ ├── doc_ruby.png
│ ├── rubypanel.png
│ └── open_folder.png
├── su_attributes
│ ├── extension_info.txt
│ └── su_attributes.susig
├── debugger
│ └── skippy_exec_2024.rb
├── README.md
└── jf_RubyPanel.rb
├── speckle_connector_3
├── .DS_Store
├── src
│ ├── .DS_Store
│ ├── ext
│ │ ├── sqlite3
│ │ │ ├── sqlite3_27.so
│ │ │ ├── sqlite3_32.so
│ │ │ ├── sqlite3_27.bundle
│ │ │ └── sqlite3_32.bundle
│ │ ├── immutable_ruby
│ │ │ ├── undefined.rb
│ │ │ ├── json.rb
│ │ │ ├── core.rb
│ │ │ └── LICENSE
│ │ └── sqlite3.rb
│ ├── constants
│ │ ├── geo_constants.rb
│ │ ├── observer_constants.rb
│ │ ├── dict_constants.rb
│ │ ├── mat_constants.rb
│ │ ├── platform_constants.rb
│ │ ├── path_constants.rb
│ │ └── pref_constants.rb
│ ├── convertors
│ │ ├── units.rb
│ │ ├── conversion_error.rb
│ │ ├── converter.rb
│ │ └── converter_v2.rb
│ ├── log
│ │ └── log.rb
│ ├── ui_data
│ │ ├── sketchup
│ │ │ └── selection_info.rb
│ │ └── components
│ │ │ └── selections
│ │ │ ├── selection.rb
│ │ │ ├── list_selection_item.rb
│ │ │ └── list_selection.rb
│ ├── commands
│ │ ├── send_selection.rb
│ │ ├── activate_diffing.rb
│ │ ├── save_stream.rb
│ │ ├── notify_connected.rb
│ │ ├── clear_mappings.rb
│ │ ├── model_preferences_updated.rb
│ │ ├── remove_stream.rb
│ │ ├── mapper_source_updated.rb
│ │ ├── user_preferences_updated.rb
│ │ ├── reset_window_location.rb
│ │ ├── action_command.rb
│ │ ├── receive_objects.rb
│ │ ├── apply_mappings.rb
│ │ └── command.rb
│ ├── speckle_objects
│ │ ├── data
│ │ │ ├── data_object.rb
│ │ │ └── revit_data_object.rb
│ │ ├── available_speckle_objects.rb
│ │ ├── geometry
│ │ │ ├── polycurve.rb
│ │ │ ├── length.rb
│ │ │ ├── vector.rb
│ │ │ ├── plane.rb
│ │ │ └── circle.rb
│ │ ├── built_elements
│ │ │ ├── revit
│ │ │ │ ├── parameter.rb
│ │ │ │ ├── family_instance.rb
│ │ │ │ └── revit_element_type.rb
│ │ │ ├── network.rb
│ │ │ ├── default_beam.rb
│ │ │ ├── default_duct.rb
│ │ │ ├── default_pipe.rb
│ │ │ └── default_column.rb
│ │ ├── other
│ │ │ ├── mapped_block_wrapper.rb
│ │ │ ├── rendering_options.rb
│ │ │ └── display_style.rb
│ │ ├── object_reference.rb
│ │ ├── gis
│ │ │ └── utils.rb
│ │ ├── speckle
│ │ │ └── core
│ │ │ │ └── models
│ │ │ │ ├── gis_layer_collection.rb
│ │ │ │ └── collection.rb
│ │ ├── revit
│ │ │ └── revit_definition.rb
│ │ ├── base.rb
│ │ ├── primitive
│ │ │ └── interval.rb
│ │ ├── color_proxy.rb
│ │ └── render_material_proxy.rb
│ ├── actions
│ │ ├── connected.rb
│ │ ├── action.rb
│ │ ├── clear_queue.rb
│ │ ├── events
│ │ │ ├── on_document_changed.rb
│ │ │ └── event_action.rb
│ │ ├── config_actions
│ │ │ ├── get_is_dev_mode.rb
│ │ │ ├── set_user_selected_account_id.rb
│ │ │ ├── get_config.rb
│ │ │ ├── get_user_selected_account_id.rb
│ │ │ └── update_config.rb
│ │ ├── test_actions
│ │ │ ├── go_away.rb
│ │ │ ├── get_complex_type.rb
│ │ │ ├── say_hi.rb
│ │ │ └── trigger_event.rb
│ │ ├── base_actions
│ │ │ ├── get_source_app_name.rb
│ │ │ ├── get_connector_version.rb
│ │ │ ├── get_source_app_version.rb
│ │ │ ├── highlight_objects.rb
│ │ │ ├── get_send_filters.rb
│ │ │ ├── update_send_filter.rb
│ │ │ ├── get_send_settings.rb
│ │ │ ├── add_model.rb
│ │ │ ├── highlight_model.rb
│ │ │ ├── remove_model.rb
│ │ │ └── remove_models.rb
│ │ ├── show_all_entities.rb
│ │ ├── collect_preferences.rb
│ │ ├── sketchup_config_actions
│ │ │ ├── update_user_config.rb
│ │ │ └── get_user_config.rb
│ │ ├── load_saved_streams.rb
│ │ ├── receive_actions
│ │ │ ├── before_receive.rb
│ │ │ └── after_receive.rb
│ │ ├── collect_versions.rb
│ │ ├── init_local_accounts.rb
│ │ ├── account_actions
│ │ │ ├── remove_account.rb
│ │ │ ├── add_account.rb
│ │ │ └── get_accounts.rb
│ │ ├── mapped_entities_updated.rb
│ │ ├── mapper_initialized.rb
│ │ ├── get_document_info.rb
│ │ ├── reload_accounts.rb
│ │ ├── save_stream.rb
│ │ ├── remove_stream.rb
│ │ ├── send_from_queue.rb
│ │ ├── deactivate_diffing.rb
│ │ ├── send_actions
│ │ │ ├── activate_send_filter.rb
│ │ │ ├── activate_send_filter_tag.rb
│ │ │ └── send_card_expiration_check.rb
│ │ ├── queue_send.rb
│ │ ├── initialize_materials.rb
│ │ ├── clear_mapper_source.rb
│ │ ├── selection_actions
│ │ │ └── get_selection.rb
│ │ ├── receive_bindings
│ │ │ └── receive.rb
│ │ ├── model_preference_updated.rb
│ │ ├── activate_diffing.rb
│ │ ├── handle_error.rb
│ │ ├── on_events_action.rb
│ │ └── hide_mappings_from_table.rb
│ ├── filters
│ │ ├── filter.rb
│ │ ├── tag.rb
│ │ ├── search_filter.rb
│ │ ├── tag_filter.rb
│ │ └── send
│ │ │ ├── everything_filter.rb
│ │ │ ├── layer_filter.rb
│ │ │ └── selection_filter.rb
│ ├── observers
│ │ ├── model_observer.rb
│ │ ├── entity_observer.rb
│ │ ├── event_handler.rb
│ │ ├── event_hash.rb
│ │ ├── app_observer.rb
│ │ ├── entities_observer.rb
│ │ ├── factory.rb
│ │ └── event_observer.rb
│ ├── ui
│ │ ├── bindings
│ │ │ ├── selection_binding.rb
│ │ │ ├── receive_binding.rb
│ │ │ ├── binding.rb
│ │ │ ├── accounts_binding.rb
│ │ │ ├── send_binding.rb
│ │ │ └── config_binding.rb
│ │ ├── send_binding_old.rb
│ │ ├── sketchup_config_binding.rb
│ │ ├── sketchup_ui.rb
│ │ ├── receive_binding.rb
│ │ ├── command_data.rb
│ │ ├── ui_controller.rb
│ │ └── test_binding.rb
│ ├── states
│ │ ├── initial_state.rb
│ │ ├── user_state.rb
│ │ └── speckle_mapper_state.rb
│ ├── cards
│ │ └── send_card_multiple_filters.rb
│ ├── speckle_entities
│ │ └── speckle_entity_status.rb
│ ├── sketchup_model
│ │ ├── dictionary
│ │ │ ├── speckle_model_dictionary_handler.rb
│ │ │ ├── speckle_schema_dictionary_handler.rb
│ │ │ └── speckle_entity_dictionary_handler.rb
│ │ ├── colors
│ │ │ └── color_manager.rb
│ │ └── utils
│ │ │ └── view_utils.rb
│ ├── operations
│ │ └── receive.rb
│ ├── immutable
│ │ └── immutable.rb
│ └── mapper
│ │ └── mapper_source.rb
├── img
│ ├── Sender.png
│ ├── s2logo.png
│ ├── Receiver.png
│ ├── s2logo_dui3.png
│ ├── ReceiverWhite32.png
│ ├── SenderWhite32.png
│ ├── SenderWhite@20.png
│ ├── ReceiverWhite@20.png
│ ├── CreateStreamWhite@32.png
│ └── CreateStreamWhite@64.png
├── debug.rb
└── bootstrap.rb
├── tests
├── test_helper.rb
└── src
│ ├── speckle_objects
│ ├── geometry
│ │ ├── point_test.rb
│ │ └── vector_test.rb
│ └── test_base.rb
│ ├── converters
│ └── test_base_object_serializer.rb
│ └── operations
│ └── test_receive.rb
├── .solargraph.yml
├── GitVersion.yml
├── .circleci
└── config.yml
├── .github
├── PULL_REQUEST_TEMPLATE
│ └── PR_TEMPLATE.md
├── ISSUE_TEMPLATE
│ └── ISSUE_TEMPLATE.md
└── workflows
│ └── deploy.yml
├── .vscode
├── launch.json
└── tasks.json
├── speckle_connector_3.rb
└── Gemfile
/ui/public/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
3 |
--------------------------------------------------------------------------------
/ui/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/.DS_Store
--------------------------------------------------------------------------------
/ui/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['@vue/cli-plugin-babel/preset']
3 | }
4 |
--------------------------------------------------------------------------------
/ui/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/public/favicon.ico
--------------------------------------------------------------------------------
/ui/src/assets/Sender.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/src/assets/Sender.png
--------------------------------------------------------------------------------
/ui/src/graphql/serverInfo.gql:
--------------------------------------------------------------------------------
1 | query{
2 | serverInfo {
3 | name
4 | canonicalUrl
5 | }
6 | }
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "_sqlite3"]
2 | path = _sqlite3
3 | url = git@github.com:specklesystems/sketchup-sqlite3.git
4 |
--------------------------------------------------------------------------------
/ui/src/assets/Receiver.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/src/assets/Receiver.png
--------------------------------------------------------------------------------
/_tools/jf_RubyPanel/reload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/_tools/jf_RubyPanel/reload.png
--------------------------------------------------------------------------------
/speckle_connector_3/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/speckle_connector_3/.DS_Store
--------------------------------------------------------------------------------
/ui/.env.example:
--------------------------------------------------------------------------------
1 | VUE_APP_DEV_TOKEN=
2 | VUE_APP_SPECKLE_NAME=SpeckleSketchup
3 | VUE_APP_DEFAULT_SERVER=https://latest.speckle.dev
--------------------------------------------------------------------------------
/ui/src/assets/SenderWhite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/src/assets/SenderWhite.png
--------------------------------------------------------------------------------
/ui/src/assets/brick_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/src/assets/brick_white.png
--------------------------------------------------------------------------------
/_tools/jf_RubyPanel/Delete24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/_tools/jf_RubyPanel/Delete24.png
--------------------------------------------------------------------------------
/_tools/jf_RubyPanel/doc_ruby.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/_tools/jf_RubyPanel/doc_ruby.png
--------------------------------------------------------------------------------
/_tools/jf_RubyPanel/rubypanel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/_tools/jf_RubyPanel/rubypanel.png
--------------------------------------------------------------------------------
/speckle_connector_3/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/speckle_connector_3/src/.DS_Store
--------------------------------------------------------------------------------
/ui/src/assets/ReceiverWhite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/src/assets/ReceiverWhite.png
--------------------------------------------------------------------------------
/_tools/jf_RubyPanel/open_folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/_tools/jf_RubyPanel/open_folder.png
--------------------------------------------------------------------------------
/_tools/su_attributes/extension_info.txt:
--------------------------------------------------------------------------------
1 | ID=f4d9d053-4479-4a9a-90da-b79fa16e28c4
2 | VERSION_ID=b787af5e-8e8e-4932-92ef-a3c99681795d
3 |
--------------------------------------------------------------------------------
/speckle_connector_3/img/Sender.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/speckle_connector_3/img/Sender.png
--------------------------------------------------------------------------------
/speckle_connector_3/img/s2logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/speckle_connector_3/img/s2logo.png
--------------------------------------------------------------------------------
/speckle_connector_3/img/Receiver.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/speckle_connector_3/img/Receiver.png
--------------------------------------------------------------------------------
/ui/public/img/icons/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/public/img/icons/favicon-16x16.png
--------------------------------------------------------------------------------
/ui/public/img/icons/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/public/img/icons/favicon-32x32.png
--------------------------------------------------------------------------------
/ui/public/img/icons/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/public/img/icons/mstile-150x150.png
--------------------------------------------------------------------------------
/_tools/su_attributes/su_attributes.susig:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/_tools/su_attributes/su_attributes.susig
--------------------------------------------------------------------------------
/speckle_connector_3/img/s2logo_dui3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/speckle_connector_3/img/s2logo_dui3.png
--------------------------------------------------------------------------------
/ui/public/img/icons/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/public/img/icons/apple-touch-icon.png
--------------------------------------------------------------------------------
/speckle_connector_3/img/ReceiverWhite32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/speckle_connector_3/img/ReceiverWhite32.png
--------------------------------------------------------------------------------
/speckle_connector_3/img/SenderWhite32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/speckle_connector_3/img/SenderWhite32.png
--------------------------------------------------------------------------------
/speckle_connector_3/img/SenderWhite@20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/speckle_connector_3/img/SenderWhite@20.png
--------------------------------------------------------------------------------
/speckle_connector_3/img/ReceiverWhite@20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/speckle_connector_3/img/ReceiverWhite@20.png
--------------------------------------------------------------------------------
/speckle_connector_3/img/CreateStreamWhite@32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/speckle_connector_3/img/CreateStreamWhite@32.png
--------------------------------------------------------------------------------
/speckle_connector_3/img/CreateStreamWhite@64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/speckle_connector_3/img/CreateStreamWhite@64.png
--------------------------------------------------------------------------------
/ui/public/img/icons/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/public/img/icons/android-chrome-192x192.png
--------------------------------------------------------------------------------
/ui/public/img/icons/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/public/img/icons/android-chrome-512x512.png
--------------------------------------------------------------------------------
/ui/public/img/icons/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/public/img/icons/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/ui/public/img/icons/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/public/img/icons/apple-touch-icon-152x152.png
--------------------------------------------------------------------------------
/ui/public/img/icons/apple-touch-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/public/img/icons/apple-touch-icon-180x180.png
--------------------------------------------------------------------------------
/ui/public/img/icons/apple-touch-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/public/img/icons/apple-touch-icon-60x60.png
--------------------------------------------------------------------------------
/ui/public/img/icons/apple-touch-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/public/img/icons/apple-touch-icon-76x76.png
--------------------------------------------------------------------------------
/speckle_connector_3/src/ext/sqlite3/sqlite3_27.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/speckle_connector_3/src/ext/sqlite3/sqlite3_27.so
--------------------------------------------------------------------------------
/speckle_connector_3/src/ext/sqlite3/sqlite3_32.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/speckle_connector_3/src/ext/sqlite3/sqlite3_32.so
--------------------------------------------------------------------------------
/ui/public/img/icons/msapplication-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/public/img/icons/msapplication-icon-144x144.png
--------------------------------------------------------------------------------
/speckle_connector_3/src/constants/geo_constants.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | VECTOR_Z = Geom::Vector3d.new(0, 0, 1)
5 | end
6 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ext/sqlite3/sqlite3_27.bundle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/speckle_connector_3/src/ext/sqlite3/sqlite3_27.bundle
--------------------------------------------------------------------------------
/speckle_connector_3/src/ext/sqlite3/sqlite3_32.bundle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/speckle_connector_3/src/ext/sqlite3/sqlite3_32.bundle
--------------------------------------------------------------------------------
/tests/test_helper.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # Require this file in all tests
4 | require 'simplecov'
5 | SimpleCov.start
6 |
7 | require 'minitest/autorun'
8 |
--------------------------------------------------------------------------------
/ui/public/img/icons/android-chrome-maskable-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/public/img/icons/android-chrome-maskable-192x192.png
--------------------------------------------------------------------------------
/ui/public/img/icons/android-chrome-maskable-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/specklesystems/speckle-sketchup/HEAD/ui/public/img/icons/android-chrome-maskable-512x512.png
--------------------------------------------------------------------------------
/speckle_connector_3/src/ext/immutable_ruby/undefined.rb:
--------------------------------------------------------------------------------
1 | module SpeckleConnector3
2 | module Immutable
3 | # @private
4 | module Undefined
5 | end
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/.solargraph.yml:
--------------------------------------------------------------------------------
1 | require_paths:
2 | - "C:/Program Files/SketchUp/SketchUp 2021/Tools"
3 | - speckle_connector_3
4 |
5 | require:
6 | - sketchup-api-stubs
7 |
8 | reporters:
9 | - rubocop
--------------------------------------------------------------------------------
/ui/src/graphql/userById.gql:
--------------------------------------------------------------------------------
1 | query User($id: String!) {
2 | user(id: $id) {
3 | id
4 | email
5 | name
6 | bio
7 | company
8 | avatar
9 | verified
10 | profiles
11 | role
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/GitVersion.yml:
--------------------------------------------------------------------------------
1 | workflow: GitFlow/v1
2 | next-version: 3.0.0
3 | mode: ManualDeployment
4 | branches:
5 | main:
6 | label: rc
7 | develop:
8 | regex: ^dui3/alpha$
9 | label: beta
10 | unknown:
11 | increment: None
12 |
--------------------------------------------------------------------------------
/ui/vue.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | module.exports = {
4 | publicPath: './',
5 | outputDir: path.resolve(__dirname, '../speckle_connector_3', 'vue_ui'),
6 | transpileDependencies: ['vuetify', '@speckle/objectloader']
7 | }
8 |
--------------------------------------------------------------------------------
/ui/public/img/icons/safari-pinned-tab.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/ui/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/ui/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "none",
3 | "tabWidth": 2,
4 | "semi": false,
5 | "endOfLine": "auto",
6 | "bracketSpacing": true,
7 | "eslintIntegration": true,
8 | "jsxBracketSameLine": true,
9 | "vueIndentScriptAndStyle": false,
10 | "htmlWhitespaceSensitivity": "ignore",
11 | "printWidth": 100,
12 | "singleQuote": true
13 | }
14 |
--------------------------------------------------------------------------------
/ui/src/graphql/user.gql:
--------------------------------------------------------------------------------
1 | query {
2 | user {
3 | id
4 | email
5 | name
6 | bio
7 | company
8 | avatar
9 | verified
10 | profiles
11 | role
12 | streams {
13 | totalCount
14 | }
15 | commits(limit: 1) {
16 | totalCount
17 | items {
18 | id
19 | createdAt
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 |
3 | # Define the jobs we want to run for this project
4 | jobs:
5 | build:
6 | docker:
7 | - image: cimg/base:2023.03
8 | steps:
9 | - run: echo "so long and thanks for all the fish"
10 |
11 | # Orchestrate our job run sequence
12 | workflows:
13 | build_and_test:
14 | when:
15 | false
16 | jobs:
17 | - build
18 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/convertors/units.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | module Converters
5 | SKETCHUP_UNITS = { 0 => 'in', 1 => 'ft', 2 => 'mm', 3 => 'cm', 4 => 'm', 5 => 'yd' }.freeze
6 | SKETCHUP_UNIT_STRINGS = { 'm' => 'm', 'mm' => 'mm', 'ft' => 'feet', 'in' => 'inch', 'yd' => 'yard',
7 | 'cm' => 'cm' }.freeze
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/log/log.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | # Helper module for logging.
5 | module Log
6 | def self.write_to_file(text, file_name = 'log', path = "#{ENV['HOME']}/Desktop")
7 | file_path = path + "/#{file_name}.json"
8 | File.delete(file_path) if File.exist?(file_path)
9 | File.write(file_path, text)
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/ui/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import VueRouter from 'vue-router'
3 |
4 | Vue.use(VueRouter)
5 |
6 | const routes = [
7 | {
8 | path: '*',
9 | name: 'Streams',
10 | component: () => import('../views/Streams.vue')
11 | },
12 | ]
13 |
14 | const router = new VueRouter({
15 | mode: 'history',
16 | base: process.env.BASE_URL,
17 | routes
18 | })
19 |
20 | export default router
21 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ext/sqlite3.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../constants/platform_constants'
4 |
5 | module SpeckleConnector3
6 | extension = if OPERATING_SYSTEM == OS_WIN
7 | 'so'
8 | else
9 | 'bundle'
10 | end
11 | sqlite3_file = "sqlite3_#{RUBY_VERSION_NUMBER}.#{extension}"
12 | require_relative(File.join('sqlite3', sqlite3_file))
13 | end
14 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ui_data/sketchup/selection_info.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | module UiData
5 | module Sketchup
6 | class SelectionInfo < Hash
7 | def initialize(selected_object_ids, summary)
8 | super()
9 | self[:selectedObjectIds] = selected_object_ids
10 | self[:summary] = summary
11 | end
12 | end
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/ui/README.md:
--------------------------------------------------------------------------------
1 | # ui
2 |
3 | ## Project setup
4 |
5 | ```
6 | npm install
7 | ```
8 |
9 | ### Compiles and hot-reloads for development
10 |
11 | ```
12 | npm run serve
13 | ```
14 |
15 | ### Compiles and minifies for production
16 |
17 | ```
18 | npm run build
19 | ```
20 |
21 | ### Lints and fixes files
22 |
23 | ```
24 | npm run lint
25 | ```
26 |
27 | ### Customize configuration
28 |
29 | See [Configuration Reference](https://cli.vuejs.org/config/).
30 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/constants/observer_constants.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | APP_OBSERVER = 'SpeckleConnector3::Observers::AppObserver'
5 | ENTITIES_OBSERVER = 'SpeckleConnector3::Observers::EntitiesObserver'
6 | ENTITY_OBSERVER = 'SpeckleConnector3::Observers::EntityObserver'
7 | MODEL_OBSERVER = 'SpeckleConnector3::Observers::ModelObserver'
8 | SELECTION_OBSERVER = 'SpeckleConnector3::Observers::SelectionObserver'
9 | end
10 |
--------------------------------------------------------------------------------
/ui/.eslintrc.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 |
3 | /** @type {import("eslint").Linter.Config} */
4 | const config = {
5 | env: {
6 | browser: true,
7 | es2021: true,
8 | commonjs: false
9 | },
10 | ignorePatterns: ['nginx'],
11 | extends: ['plugin:vue/recommended', 'eslint:recommended', 'prettier', 'prettier/vue'],
12 | parserOptions: {
13 | sourceType: 'module'
14 | },
15 | plugins: ['vue'],
16 | rules: { 'no-console': 1 }
17 | }
18 |
19 | module.exports = config
20 |
--------------------------------------------------------------------------------
/ui/src/utils/groupBy.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Group by function definition to call it on demand.
3 | * @example
4 | * const groupByBrand = groupBy('brand')
5 | * const groupedByBrands1 = groupByBrand(array1)
6 | * const groupedByBrands2 = groupByBrand(array2)
7 | */
8 | export const groupBy = key => array =>
9 | array.reduce((objectsByKeyValue, obj) => {
10 | const value = obj[key];
11 | objectsByKeyValue[value] = (objectsByKeyValue[value] || []).concat(obj);
12 | return objectsByKeyValue;
13 | }, {});
--------------------------------------------------------------------------------
/speckle_connector_3/src/commands/send_selection.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'command'
4 | require_relative '../actions/send_selection'
5 |
6 | module SpeckleConnector3
7 | module Commands
8 | # Command to send selection to Speckle Server.
9 | class SendSelection < Command
10 | def _run(_resolve_id, data)
11 | stream_id = data['stream_id']
12 | action = Actions::SendSelection.new(stream_id)
13 | app.update_state!(action)
14 | end
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/commands/activate_diffing.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'command'
4 | require_relative '../actions/activate_diffing'
5 |
6 | module SpeckleConnector3
7 | module Commands
8 | # Command to activate diffing for stream.
9 | class ActivateDiffing < Command
10 | def _run(_resolve_id, data)
11 | stream_id = data['stream_id']
12 | action = Actions::ActivateDiffing.new(stream_id)
13 | app.update_state!(action)
14 | end
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/data/data_object.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../base'
4 | require_relative '../../constants/type_constants'
5 |
6 | module SpeckleConnector3
7 | module SpeckleObjects
8 | class DataObject < Base
9 | SPECKLE_TYPE = SPECKLE_OBJECT_DATA_OBJECT
10 |
11 | def self.to_native(state, data_object, layer, _entities, &convert_to_native)
12 | properties = data_object['properties']
13 | return state
14 | end
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/connected.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | module Actions
5 | # Action to update connected state of application.
6 | class Connected < Action
7 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
8 | # @return [States::State] the new updated state object
9 | def self.update_state(state)
10 | puts 'Speckle connected!'
11 | state.with(:@connected => true)
12 | end
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/action.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | module Actions
5 | # State changer object.
6 | class Action
7 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
8 | # @param parameters [Array] parameters that the action takes
9 | # @return [States::State] the new updated state object
10 | def self.update_state(_state, *_parameters)
11 | raise NotImplementedError, 'Implement in subclass.'
12 | end
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/commands/save_stream.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'command'
4 | require_relative '../accounts/accounts'
5 | require_relative '../actions/save_stream'
6 | require_relative '../actions/load_saved_streams'
7 |
8 | module SpeckleConnector3
9 | module Commands
10 | # Command to saved stream.
11 | class SaveStream < Command
12 | def _run(_resolve_id, data)
13 | stream_id = data['stream_id']
14 | app.update_state!(Actions::SaveStream.new(stream_id))
15 | end
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/filters/filter.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 |
4 | module SpeckleConnector3
5 | module Filters
6 | # Base filters for sketchup connector.
7 | class Filter < Hash
8 | # @return [String] id of the filter
9 | attr_reader :id
10 |
11 | # @return [String] name of the filter
12 | attr_reader :name
13 |
14 | def initialize(id, name)
15 | super()
16 | @id = id
17 | @name = name
18 | self[:id] = id
19 | self[:name] = name
20 | end
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/filters/tag.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | module Filters
5 | # Tag definition for filters for sketchup connector.
6 | class Tag < Hash
7 | attr_reader :id
8 | attr_reader :name
9 | attr_reader :color
10 |
11 | def initialize(id, name, color)
12 | super()
13 | @id = id
14 | @name = name
15 | @color = color
16 | self[:id] = id
17 | self[:name] = name
18 | self[:color] = color
19 | end
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/observers/model_observer.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'event_observer'
4 |
5 | module SpeckleConnector3
6 | module Observers
7 | # Model related event observers.
8 | class ModelObserver < Sketchup::ModelObserver
9 | include EventObserver
10 |
11 | # rubocop:disable Naming/MethodName
12 | # @param model (Sketchup::Model)
13 | def onActivePathChanged(model)
14 | push_event(:onActivePathChanged, model)
15 | end
16 | # rubocop:enable Naming/MethodName
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/commands/notify_connected.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'command'
4 | require_relative '../actions/connected'
5 | require_relative '../actions/send_from_queue'
6 |
7 | module SpeckleConnector3
8 | module Commands
9 | # Command to notify connected.
10 | class NotifyConnected < Command
11 | def _run(_resolve_id, data)
12 | stream_id = data['stream_id']
13 | app.update_state!(Actions::Connected)
14 | app.update_state!(Actions::SendFromQueue.new(stream_id))
15 | end
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/filters/search_filter.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'filter'
4 |
5 | module SpeckleConnector3
6 | module Filters
7 | # Search filters for sketchup connector.
8 | # TODO: LATER!
9 | class SearchFilter < Filter
10 | # @return [Array] id of the filter
11 | attr_reader :tags
12 |
13 | def initialize(id, name, input, duplicable, tags, active_tags)
14 | super(id, name, input, duplicable)
15 | @tags = tags
16 | @active_tags = active_tags
17 | end
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ui/bindings/selection_binding.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'binding'
4 | require_relative '../../actions/selection_actions/get_selection'
5 |
6 | module SpeckleConnector3
7 | module Ui
8 | SELECTION_BINDING_NAME = 'selectionBinding'
9 |
10 | # Selection binding that provided for DUI.
11 | class SelectionBinding < Binding
12 | def commands
13 | @commands ||= {
14 | getSelection: Commands::ActionCommand.new(@app, self, Actions::GetSelection)
15 | }.freeze
16 | end
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/clear_queue.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 |
5 | module SpeckleConnector3
6 | module Actions
7 | # Clear queue from state.
8 | class ClearQueue < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state)
12 | new_speckle_state = state.speckle_state.with(:@message_queue => {})
13 | state.with(:@speckle_state => new_speckle_state)
14 | end
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/events/on_document_changed.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | module Actions
5 | # Triggers whenever document has changed.
6 | class OnDocumentChanged < Action
7 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
8 | # @return [States::State] the new updated state object
9 | def self.update_state(state)
10 | js_command = "baseBinding.emit('documentChanged')"
11 | state.with_add_queue_js_command('documentChanged', js_command)
12 | end
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/observers/entity_observer.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'event_observer'
4 |
5 | module SpeckleConnector3
6 | module Observers
7 | # Entity observer.
8 | class EntityObserver < Sketchup::EntityObserver
9 | include EventObserver
10 |
11 | # rubocop:disable Naming/MethodName
12 | # @param entity (Sketchup::Entity)
13 | def onChangeEntity(entity)
14 | puts "onChangeEntity: #{entity}"
15 | push_event(:onChangeEntity, entity)
16 | end
17 | # rubocop:enable Naming/MethodName
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/commands/clear_mappings.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'command'
4 | require_relative '../actions/clear_mappings'
5 |
6 | module SpeckleConnector3
7 | module Commands
8 | # Command to clear mapping for selected entities.
9 | class ClearMappings < Command
10 | def _run(_resolve_id, data)
11 | entities_to_map = data['entitiesToClearMap']
12 | is_definition = data['isDefinition']
13 | action = Actions::ClearMappings.new(entities_to_map, is_definition)
14 | app.update_state!(action)
15 | end
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/commands/model_preferences_updated.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'command'
4 | require_relative '../accounts/accounts'
5 | require_relative '../actions/model_preference_updated'
6 |
7 | module SpeckleConnector3
8 | module Commands
9 | # Command to update theme.
10 | class ModelPreferencesUpdated < Command
11 | def _run(_resolve_id, data)
12 | preference = data['preference']
13 | new_value = data['value']
14 | app.update_state!(Actions::ModelPreferencesUpdated.new(preference, new_value))
15 | end
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/commands/remove_stream.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'command'
4 | require_relative '../actions/remove_stream'
5 | require_relative '../actions/load_saved_streams'
6 |
7 | module SpeckleConnector3
8 | module Commands
9 | # Command to remove stream.
10 | class RemoveStream < Command
11 | def _run(_resolve_id, data)
12 | stream_id = data['stream_id']
13 | action = Actions::RemoveStream.new(stream_id)
14 | app.update_state!(action)
15 | app.update_state!(Actions::LoadSavedStreams)
16 | end
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE/PR_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Description of PR...
2 |
3 | ## Changes
4 |
5 | - Item 1
6 | - Item 2
7 |
8 | ## Checklist
9 |
10 | - [ ] Unit tests
11 | - [ ] Documentation
12 |
13 | ## References
14 |
15 | (optional)
16 |
17 | Include **important** links regarding the implementation of this PR.
18 | This usually includes and RFC or an aggregation of issues and/or individual conversations
19 | that helped put this solution together. This helps ensure there is a good aggregation
20 | of resources regarding the implementation.
21 |
22 | ```text
23 | Fixes #85, Fixes #22, Fixes username/repo#123
24 | Connects #123
25 | ```
26 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/commands/mapper_source_updated.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'command'
4 | require_relative '../actions/mapper_source_updated'
5 |
6 | module SpeckleConnector3
7 | module Commands
8 | # Command to update mapper source.
9 | class MapperSourceUpdated < Command
10 | def _run(_resolve_id, data)
11 | base = data['base']
12 | stream_id = data['stream_id']
13 | commit_id = data['commit_id']
14 | action = Actions::MapperSourceUpdated.new(base, stream_id, commit_id)
15 | app.update_state!(action)
16 | end
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/constants/dict_constants.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | SPECKLE_BASE_OBJECT = 'Speckle_Base_Object'
5 | SPECKLE_MAPPING_TOOL_SCHEMA = 'Speckle_Mapping_Tool_Schema'
6 | SPECKLE_SCHEMA = 'Speckle_Schema'
7 |
8 | SPECKLE_SEND_CARDS = 'Speckle_Send_Cards'
9 | SPECKLE_RECEIVE_CARDS = 'Speckle_Receive_Cards'
10 |
11 | SPECKLE_ID = 'speckle_id'
12 | SPECKLE_TYPE = 'speckle_type'
13 | APPLICATION_ID = 'application_id'
14 | CHILDREN = 'children'
15 | PARENT = 'parent'
16 | VALID_STREAM_IDS = 'valid_stream_ids'
17 | INVALID_STREAM_IDS = 'invalid_stream_ids'
18 | end
19 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/config_actions/get_is_dev_mode.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 |
5 | module SpeckleConnector3
6 | module Actions
7 | # Action to get is dev mode.
8 | class GetIsDevMode < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state, resolve_id)
12 | js_script = "configBinding.receiveResponse('#{resolve_id}', #{DEV_MODE})"
13 | state.with_add_queue_js_command('getIsDevMode', js_script)
14 | end
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/test_actions/go_away.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 |
5 | module SpeckleConnector3
6 | module Actions
7 | # Test purpose action.
8 | class GoAway < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state, resolve_id)
12 | puts 'SketchUp went away :('
13 | js_script = "testBinding.receiveResponse('#{resolve_id}')"
14 | state.with_add_queue_js_command('goAway', js_script)
15 | end
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/states/initial_state.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | module States
5 | # Initial state of the application.
6 | class InitialState
7 | # @return [UserState] the user specific part of the states
8 | attr_reader :user_state
9 |
10 | # @return [Boolean] application is connector to server or not
11 | attr_reader :is_connected
12 |
13 | def initialize(user_state)
14 | @user_state = user_state
15 | @is_connected = false
16 | freeze
17 | end
18 |
19 | def speckle_state?
20 | false
21 | end
22 | end
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/base_actions/get_source_app_name.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 |
5 | module SpeckleConnector3
6 | module Actions
7 | # Get source app name.
8 | class GetSourceAppName < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state, resolve_id)
12 | js_command = "baseBinding.receiveResponse('#{resolve_id}', 'sketchup')"
13 | state.with_add_queue_js_command('getSourceAppName', js_command)
14 | end
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/cards/send_card_multiple_filters.rb:
--------------------------------------------------------------------------------
1 | # # frozen_string_literal: true
2 | #
3 | # require_relative 'card'
4 | #
5 | # module SpeckleConnector3
6 | # module Cards
7 | # # Send card for sketchup connector to communicate speckle.
8 | # class SendCardMultipleFilters < Card
9 | # # @return [Hash{String=>Filter}] filters of the card.
10 | # attr_reader :filters
11 | #
12 | # def initialize(card_id, account_id, project_id, model_id, filters)
13 | # super(card_id, account_id, project_id, model_id)
14 | # @filters = filters
15 | # self[:filters] = filters
16 | # end
17 | # end
18 | # end
19 | # end
20 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/convertors/conversion_error.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | module Converters
5 | class ConverterError < StandardError
6 | # @return [UiData::Report::ConversionStatus::WARNING] level of the error.
7 | attr_reader :level
8 |
9 | # @param message [String] message for error.
10 | # @param level [UiData::Report::ConversionStatus::WARNING] level of the error.
11 | def initialize(message = "An error occurred on conversion", level)
12 | @level = level
13 | super(message) # Calls the parent class's initialize method with the message
14 | end
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/base_actions/get_connector_version.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 |
5 | module SpeckleConnector3
6 | module Actions
7 | # Get connector version.
8 | class GetConnectorVersion < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state, resolve_id)
12 | js_command = "baseBinding.receiveResponse('#{resolve_id}', '#{CONNECTOR_VERSION}')"
13 | state.with_add_queue_js_command('getConnectorVersion', js_command)
14 | end
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/base_actions/get_source_app_version.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 |
5 | module SpeckleConnector3
6 | module Actions
7 | # Get source app version.
8 | class GetSourceAppVersion < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state, resolve_id)
12 | js_command = "baseBinding.receiveResponse('#{resolve_id}', #{SKETCHUP_VERSION})"
13 | state.with_add_queue_js_command('getSourceAppVersion', js_command)
14 | end
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/show_all_entities.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 |
5 | module SpeckleConnector3
6 | module Actions
7 | # Show all entities on the model.
8 | class ShowAllEntities < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state, _resolve_id, _data)
12 | # Show all entities first
13 | state.sketchup_state.sketchup_model.entities.each do |ent|
14 | ent.hidden = false
15 | end
16 | state
17 | end
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/commands/user_preferences_updated.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'command'
4 | require_relative '../accounts/accounts'
5 | require_relative '../actions/user_preferences_updated'
6 |
7 | module SpeckleConnector3
8 | module Commands
9 | # Command to update preferences.
10 | class UserPreferencesUpdated < Command
11 | def _run(_resolve_id, data)
12 | preference_hash = data['preference_hash']
13 | preference = data['preference']
14 | new_value = data['value']
15 | app.update_state!(Actions::UserPreferencesUpdated.new(preference_hash, preference, new_value))
16 | end
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/constants/mat_constants.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | MAT_DICTIONARY = 'Speckle_Connector_Materials'
5 | MAT_ID = 'Speckle_Connector_Material_Id'
6 |
7 | MAT_ADD = :speckle_connector_add_material
8 | MAT_EDIT = :speckle_connector_edit_material
9 | MAT_REMOVE = :speckle_connector_remove_material
10 |
11 | DEFAULT_COLORS = {
12 | MAT_ADD => '#66FF66',
13 | MAT_EDIT => '#FFFF9F',
14 | MAT_REMOVE => '#FF6666'
15 | }.freeze
16 |
17 | DEFAULT_NAMES = {
18 | MAT_ADD => 'Speckle_Material_Add',
19 | MAT_EDIT => 'Speckle_Material_Edit',
20 | MAT_REMOVE => 'Speckle_Material_Remove'
21 | }.freeze
22 | end
23 |
--------------------------------------------------------------------------------
/ui/apollo.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | // Load .env files
4 | const { loadEnv } = require('vue-cli-plugin-apollo/utils/load-env')
5 | const env = loadEnv([path.resolve(__dirname, '.env'), path.resolve(__dirname, '.env.local')])
6 |
7 | module.exports = {
8 | client: {
9 | service: env.VUE_APP_APOLLO_ENGINE_SERVICE,
10 | includes: ['src/**/*.{js,jsx,ts,tsx,vue,gql}']
11 | },
12 | service: {
13 | name: env.VUE_APP_APOLLO_ENGINE_SERVICE,
14 | localSchemaFile: path.resolve(__dirname, './node_modules/.temp/graphql/schema.json')
15 | },
16 | engine: {
17 | endpoint: process.env.APOLLO_ENGINE_API_ENDPOINT,
18 | apiKey: env.VUE_APP_APOLLO_ENGINE_KEY
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/commands/reset_window_location.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'command'
4 | require_relative '../states/initial_state'
5 | require_relative '../actions/initialize_speckle'
6 | require_relative '../observers/factory'
7 |
8 | module SpeckleConnector3
9 | module Commands
10 | # Command to reset Speckle UI window location onto center of SketchUp window.
11 | class ResetWindowLocation < Command
12 |
13 | private
14 |
15 | def _run
16 | app = self.app
17 | app.ui_controller.user_interfaces.values.each do |interface|
18 | interface.reset_dialog_location
19 | end
20 | end
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/collect_preferences.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 | require_relative '../ext/sqlite3'
5 | require_relative '../constants/path_constants'
6 |
7 | module SpeckleConnector3
8 | module Actions
9 | # Action to collect preferences from database to UI.
10 | class CollectPreferences < Action
11 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
12 | # @return [States::State] the new updated state object
13 | def self.update_state(state, _resolve_id, _data)
14 | state.with_add_queue('collectPreferences', state.user_state.preferences.to_json, [])
15 | end
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/constants/platform_constants.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # rubocop:disable Style/Documentation
4 | module SpeckleConnector3
5 | host_os = RbConfig::CONFIG['host_os']
6 | OS_WIN = :windows
7 | OS_MAC = :macos
8 | OPERATING_SYSTEM = case host_os
9 | when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
10 | OS_WIN
11 | when /darwin|mac os/
12 | OS_MAC
13 | else
14 | raise "Unsupported OS: #{host_os.inspect}"
15 | end
16 | RUBY_VERSION_NUMBER = RUBY_VERSION.split('.')[0..1].join.to_i
17 | end
18 | # rubocop:enable Style/Documentation
19 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/observers/event_handler.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'event_hash'
4 | require_relative '../actions/on_events_action'
5 |
6 | module SpeckleConnector3
7 | module Observers
8 | # Event handler class.
9 | class EventHandler
10 | # @return [SpeckleConnectorApp] an object that contains current state of speckle objects
11 | attr_reader :app
12 |
13 | def initialize(app)
14 | @app = app
15 | end
16 |
17 | def handle_events(events)
18 | run_handlers(events)
19 | end
20 |
21 | def run_handlers(events)
22 | app.update_state!(Actions::OnEventsAction, events)
23 | end
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ui_data/components/selections/selection.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | module UiData
5 | module Components
6 | module Selections
7 | # Selections data for UI.
8 | class Selection < Hash
9 | # @return [String] id of the selection.
10 | attr_reader :id
11 |
12 | # @return [String] name of the selection.
13 | attr_reader :name
14 |
15 | def initialize(id, name)
16 | super()
17 | @id = id
18 | @name = name
19 | self[:id] = id
20 | self[:name] = name
21 | end
22 | end
23 | end
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/sketchup_config_actions/update_user_config.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 |
5 | module SpeckleConnector3
6 | module Actions
7 | # Action to get user config.
8 | class UpdateUserConfig < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state, resolve_id, new_config)
12 | puts new_config.values
13 | js_script = "connectorConfigBinding.receiveResponse('#{resolve_id}')"
14 | state.with_add_queue_js_command('updateUserConfig', js_script)
15 | end
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/observers/event_hash.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../ext/immutable_ruby/core'
4 |
5 | module SpeckleConnector3
6 | module Observers
7 | # Collection of events.
8 | class EventHash < Immutable::Hash
9 | def push_event(observer_class, event_name, data)
10 | observer_events = self[observer_class] || Immutable::EmptyHash
11 | name_events = observer_events[event_name] || Immutable::EmptyVector
12 | name_events = name_events.add(data)
13 | observer_events = observer_events.put(event_name, name_events)
14 | put(observer_class, observer_events)
15 | end
16 | end
17 |
18 | EMPTY_EVENT_HASH = EventHash.new([])
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_entities/speckle_entity_status.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../immutable/immutable'
4 | require_relative '../convertors/units'
5 | require_relative '../sketchup_model/dictionary/speckle_entity_dictionary_handler'
6 |
7 | module SpeckleConnector3
8 | module SpeckleEntities
9 | module SpeckleEntityStatus
10 | # Speckle Entity created first time with {Sketchup::Entity} before sent to server.
11 | UP_TO_DATE = 0
12 | # {Sketchup::Entity} that corresponds to Speckle Entity is edited after created by user.
13 | EDITED = 1
14 | # {Sketchup::Entity} that corresponds to Speckle Entity is removed.
15 | REMOVED = 2
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ui/bindings/receive_binding.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'binding'
4 | require_relative '../../actions/receive_bindings/receive'
5 | require_relative '../../actions/receive_bindings/after_get_objects'
6 |
7 | module SpeckleConnector3
8 | module Ui
9 | RECEIVE_BINDING_NAME = 'receiveBinding'
10 |
11 | # Receive Binding that provided for DUI.
12 | class ReceiveBinding < Binding
13 | def commands
14 | @commands ||= {
15 | receive: Commands::ActionCommand.new(@app, self, Actions::Receive),
16 | afterGetObjects: Commands::ActionCommand.new(@app, self, Actions::AfterGetObjects)
17 | }.freeze
18 | end
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/load_saved_streams.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 |
5 | module SpeckleConnector3
6 | module Actions
7 | # Action to load saved streams.
8 | class LoadSavedStreams < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state, _request_id, _data)
12 | (saved_streams = state.sketchup_state.sketchup_model
13 | .attribute_dictionary('Speckle', true)['saved_streams']) or []
14 | state.with_add_queue('setSavedStreams', saved_streams, [])
15 | end
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "Debug Local File",
9 | "type": "Ruby",
10 | "request": "launch",
11 | "cwd": "${workspaceRoot}",
12 | "program": "scratch.rb"
13 | },
14 | {
15 | "name": "Listen for rdebug-ide",
16 | "type": "Ruby",
17 | "request": "attach",
18 | "remoteHost": "127.0.0.1",
19 | "remotePort": "7000",
20 | "cwd": "${workspaceRoot}",
21 | "remoteWorkspaceRoot": "${workspaceRoot}"
22 | }
23 | ]
24 | }
--------------------------------------------------------------------------------
/speckle_connector_3/src/filters/tag_filter.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'tag'
4 | require_relative 'filter'
5 |
6 | module SpeckleConnector3
7 | module Filters
8 | # Tag filters for sketchup connector.
9 | class TagFilter < Filter
10 | # @return [Array] id of the filter
11 | attr_reader :tags
12 |
13 | # @return [Array] id of the filter
14 | attr_reader :active_tags
15 |
16 | def initialize(id, name, input, duplicable, tags, active_tags)
17 | super(id, name, input, duplicable)
18 | @tags = tags
19 | @active_tags = active_tags
20 | self[:tags] = tags
21 | self[:activeTags] = active_tags
22 | end
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/receive_actions/before_receive.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 |
5 | module SpeckleConnector3
6 | module Actions
7 | # Action to let sketchup know receive will be started.
8 | class BeforeReceive < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state, resolve_id, stream_id, root_id)
12 | puts "receive started for: #{root_id}"
13 | js_script = "sketchupReceiveBinding.receiveResponse('#{resolve_id}')"
14 | state.with_add_queue_js_command('beforeReceive', js_script)
15 | end
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/receive_actions/after_receive.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 |
5 | module SpeckleConnector3
6 | module Actions
7 | # Action to let sketchup know receive from server is finished..
8 | class AfterReceive < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state, resolve_id, stream_id, root_id)
12 | puts "receive finished for: #{root_id}"
13 | js_script = "sketchupReceiveBinding.receiveResponse('#{resolve_id}')"
14 | state.with_add_queue_js_command('afterReceive', js_script)
15 | end
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/available_speckle_objects.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | module SpeckleObjects
5 | # @return [Array] available speckle object types.
6 | AVAILABLE_SPECKLE_OBJECTS = %w[
7 | Objects.Geometry.Point
8 | Objects.Geometry.Vector
9 | Objects.Geometry.Line
10 | Objects.Geometry.Polyline
11 | Objects.Geometry.Mesh
12 | Objects.Geometry.Brep
13 | Objects.Geometry.Box
14 | Objects.Geometry.Plane
15 | Objects.Other.BlockInstance
16 | Objects.Other.BlockDefinition
17 | Objects.Other.RenderMaterial
18 | Objects.Other.Transform
19 | Objects.Primitive.Interval
20 | Speckle.Reference
21 | ].freeze
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/geometry/polycurve.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../base'
4 | require_relative '../../constants/type_constants'
5 |
6 | module SpeckleConnector3
7 | module SpeckleObjects
8 | module Geometry
9 | # Polycurve object definition for Speckle.
10 | # It basically groups the lines-curves under it's `segments` property.
11 | class Polycurve < Base
12 | SPECKLE_TYPE = OBJECTS_GEOMETRY_POLYCURVE
13 |
14 | def self.to_native(state, polycurve, layer, entities, &convert_to_native)
15 | polycurve['displayValue'] = polycurve['segments']
16 | convert_to_native.call(state, polycurve, layer, entities)
17 | end
18 | end
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ui/send_binding_old.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'bindings/binding'
4 | require_relative '../actions/send_actions/activate_send_filter'
5 | require_relative '../actions/send_actions/activate_send_filter_tag'
6 |
7 | module SpeckleConnector3
8 | module Ui
9 | SEND_BINDING_NAME = 'sendBindingOld'
10 |
11 | # Send binding that provided for DUI.
12 | class SendBindingOld < Binding
13 | def commands
14 | @commands ||= {
15 | activateSendFilter: Commands::ActionCommand.new(@app, self, Actions::ActivateSendFilter),
16 | activateSendFilterTag: Commands::ActionCommand.new(@app, self, Actions::ActivateSendFilterTag)
17 | }.freeze
18 | end
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/_tools/debugger/skippy_exec_2024.rb:
--------------------------------------------------------------------------------
1 | # This is for automated pre-debugger configuration.
2 | # We run skippy first, then activate debugger.
3 | # The purpose of this file to wait till skp is live
4 |
5 | # To establish a configuration
6 | # 1. Create 'Run External Tool' before lunch step
7 | # 2. Program -> C:\Ruby32-x64\bin\ruby.exe or whatever
8 | # 3. Arguments -> C:\Users\KORAL\Documents\Git\Speckle\speckle-sketchup\_tools\debugger\bundle_exec_2024.rb or whatever
9 | # 4. Working directory -> C:\Users\KORAL\Documents\Git\Speckle\speckle-sketchup or whatever
10 |
11 | # Add a delay of 10 seconds, it is arbitrary, do not hesitate to change for what works best for you
12 | sleep(10)
13 |
14 | # Execute the original command
15 | exec('bundle exec skippy sketchup:debug 2024')
16 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/base_actions/highlight_objects.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 | require_relative '../../sketchup_model/query/entity'
5 | require_relative '../../sketchup_model/utils/view_utils'
6 |
7 | module SpeckleConnector3
8 | module Actions
9 | # Action to add send card.
10 | class HighlightObjects < Action
11 | def self.update_state(state, resolve_id, object_ids)
12 | SketchupModel::Utils::ViewUtils.highlight_entities(state.sketchup_state.sketchup_model, object_ids)
13 |
14 | # Resolve promise
15 | js_script = "baseBinding.receiveResponse('#{resolve_id}')"
16 | state.with_add_queue_js_command('highlightObjects', js_script)
17 | end
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/test_actions/get_complex_type.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 |
5 | module SpeckleConnector3
6 | module Actions
7 | # Test purpose action.
8 | class GetComplexType < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state, resolve_id)
12 | complex_type = {
13 | id: 'complex_type_id',
14 | count: 3
15 | }
16 | js_script = "testBinding.receiveResponse('#{resolve_id}', #{complex_type.to_json})"
17 | state.with_add_queue_js_command('getComplexType', js_script)
18 | end
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/built_elements/revit/parameter.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../../base'
4 | require_relative '../../../constants/type_constants'
5 |
6 | module SpeckleConnector3
7 | module SpeckleObjects
8 | module BuiltElements
9 | module Revit
10 | # Revit parameter.
11 | class Parameter < Base
12 | SPECKLE_TYPE = OBJECTS_BUILTELEMENTS_REVIT_PARAMETER
13 | def initialize(name:, application_id: nil)
14 | super(
15 | speckle_type: SPECKLE_TYPE,
16 | application_id: application_id,
17 | id: id
18 | )
19 | self[:name] = name
20 | end
21 | end
22 | end
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/config_actions/set_user_selected_account_id.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 | require_relative '../../preferences/preferences'
5 |
6 | module SpeckleConnector3
7 | module Actions
8 | class SetUserSelectedAccountId < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state, resolve_id, account_id)
12 | Preferences.set_user_selected_account_id(account_id)
13 | js_script = "configBinding.receiveResponse('#{resolve_id}')"
14 | state.with_add_queue_js_command('setUserSelectedAccountId', js_script)
15 | end
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/filters/send/everything_filter.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../../ui_data/components/selections/list_selection_item'
4 |
5 | module SpeckleConnector3
6 | module Filters
7 | module Send
8 | # Everything filter for sketchup connector to send all.
9 | class EverythingFilter < UiData::Components::Selections::ListSelectionItem
10 | def initialize
11 | super('everything', 'Everything', nil,
12 | 'All supported objects in the currently opened file.')
13 | end
14 |
15 | def self.from_json(_data)
16 | EverythingFilter.new
17 | end
18 |
19 | def check_expiry(_ids)
20 | true
21 | end
22 | end
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/collect_versions.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 |
5 | module SpeckleConnector3
6 | module Actions
7 | # Action to collect versions from sketchup and connector to track user's version by mixpanel.
8 | class CollectVersions < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state, _resolve_id, _data)
12 | versions = {
13 | sketchup: Sketchup.version.to_i,
14 | speckle: SpeckleConnector3::CONNECTOR_VERSION
15 | }
16 | state.with_add_queue('collectVersions', versions.to_json, [])
17 | end
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/built_elements/network.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../base'
4 | require_relative '../../constants/type_constants'
5 |
6 | module SpeckleConnector3
7 | module SpeckleObjects
8 | module BuiltElements
9 | # Network object represents scenes on Sketchup.
10 | class Network < Base
11 | SPECKLE_TYPE = OBJECTS_BUILTELEMENTS_NETWORK
12 |
13 | def self.to_native(state, network, layer, entities, &convert_to_native)
14 | network['elements'].each do |element|
15 | state, _converted_entities = convert_to_native.call(state, element['elements'], layer, entities)
16 | end
17 |
18 | return state, []
19 | end
20 | end
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ui/bindings/binding.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | module Ui
5 | # The abstract class for binding to send data to a user interface.
6 | class Binding
7 | # @return [String] name of the binding.
8 | attr_reader :name
9 |
10 | # @return [App::SpeckleConnectorApp] the reference to the app object
11 | attr_reader :app
12 |
13 | # @param app [App::SpeckleConnectorApp] the reference to the app object
14 | # @param name [String] name of the binding.
15 | def initialize(app, name)
16 | @app = app
17 | @name = name
18 | end
19 |
20 | def commands
21 | raise NotImplementedError, 'Implement in a subclass'
22 | end
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/ui/src/views/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Hello!
7 |
8 | Welcome to the Speckle connector for SketchUp!
9 |
10 |
11 |
12 |
13 | You have no logged in account.
14 | Please login or register via Speckle Manager then refresh UI.
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: New issue
3 | about: Create a report to help us improve
4 | title:
5 | labels:
6 | assignees:
7 | ---
8 |
9 | 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!
10 |
11 | ### Expected vs. Actual Behavior
12 |
13 | Describe the problem here.
14 |
15 | ### Reproduction Steps & System Config (win, osx, web, etc.)
16 |
17 | Let us know how we can reproduce this, and attach relevant files (if any).
18 |
19 | ### Proposed Solution (if any)
20 |
21 | Let us know what how you would solve this.
22 |
23 | #### Optional: Affected Projects
24 |
25 | Does this issue propagate to other dependencies or dependents? If so, list them here!
26 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/other/mapped_block_wrapper.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../base'
4 |
5 | module SpeckleConnector3
6 | module SpeckleObjects
7 | module Other
8 | # MappedBlockWrapper object definition for Speckle.
9 | class MappedBlockWrapper < Base
10 | SPECKLE_TYPE = 'Objects.Other.MappedBlockWrapper'
11 | def initialize(category:, units:, instance:, application_id: nil)
12 | super(
13 | speckle_type: SPECKLE_TYPE,
14 | application_id: application_id,
15 | id: nil
16 | )
17 | self[:category] = category
18 | self[:units] = units
19 | self[:instance] = instance
20 | end
21 | end
22 | end
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ui/sketchup_config_binding.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'bindings/binding'
4 | require_relative '../actions/sketchup_config_actions/get_user_config'
5 | require_relative '../actions/sketchup_config_actions/update_user_config'
6 |
7 | module SpeckleConnector3
8 | module Ui
9 | CONNECTOR_CONFIG_BINDING_NAME = 'connectorConfigBinding'
10 |
11 | # Config binding that provided for DUI.
12 | class SketchupConfigBinding < Binding
13 | def commands
14 | @commands ||= {
15 | getUserConfig: Commands::ActionCommand.new(@app, self, Actions::GetUserConfig),
16 | updateUserConfig: Commands::ActionCommand.new(@app, self, Actions::UpdateUserConfig)
17 | }.freeze
18 | end
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/ui/src/main.js:
--------------------------------------------------------------------------------
1 | import 'regenerator-runtime/runtime'
2 |
3 | import Vue from 'vue'
4 | import App from './App.vue'
5 | import router from './router'
6 | import vuetify from './plugins/vuetify'
7 | import { createProvider } from './vue-apollo'
8 |
9 | Vue.prototype.$eventHub = new Vue()
10 |
11 | Vue.config.productionTip = false
12 |
13 | import VueTimeago from 'vue-timeago'
14 | Vue.use(VueTimeago, { locale: 'en' })
15 |
16 | import VueTooltip from 'v-tooltip'
17 | Vue.use(VueTooltip)
18 |
19 | import SpeckleMetrics from './plugins/speckle-metrics'
20 | Vue.use(SpeckleMetrics, { token: 'acd87c5a50b56df91a795e999812a3a4' })
21 |
22 | export const bus = new Vue()
23 |
24 | new Vue({
25 | router,
26 | vuetify,
27 | apolloProvider: createProvider(),
28 | render: (h) => h(App)
29 | }).$mount('#app')
30 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/test_actions/say_hi.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 |
5 | module SpeckleConnector3
6 | module Actions
7 | # Test purpose action.
8 | class SayHi < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state, resolve_id, name, count, say_hello_not_hi)
12 | said_hi = []
13 | count.times do
14 | said_hi.append("#{say_hello_not_hi ? 'Hello' : 'Hi'} #{name}!")
15 | end
16 | js_script = "testBinding.receiveResponse('#{resolve_id}', #{said_hi})"
17 | state.with_add_queue_js_command('sayHi', js_script)
18 | end
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/commands/action_command.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'command'
4 |
5 | module SpeckleConnector3
6 | module Commands
7 | # Command to update state of the application.
8 | class ActionCommand < Command
9 | # @param app [App::SpeckleConnectorApp] the app object to run command on
10 | # @param binding [Ui::Binding] binding object holds commands to call
11 | # @param action [#update_state] the action that knows how to change the state of the speckle app
12 | def initialize(app, binding, action)
13 | super(app, binding)
14 | @action = action
15 | end
16 |
17 | private
18 |
19 | def _run(*parameters)
20 | app.update_state!(@action, *parameters)
21 | end
22 | end
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/geometry/length.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../../convertors/units'
4 |
5 | module SpeckleConnector3
6 | module SpeckleObjects
7 | # Geometric objects to convert speckle.
8 | module Geometry
9 | def self.length_to_speckle(length, units)
10 | length.__send__("to_#{SpeckleConnector3::Converters::SKETCHUP_UNIT_STRINGS[units]}")
11 | end
12 |
13 | def self.length_to_native(length, units)
14 | if units == 'none'
15 | units = SpeckleConnector3::Converters::
16 | SKETCHUP_UNITS[Sketchup.active_model.options['UnitsOptions']['LengthUnit']]
17 | end
18 | length.__send__(SpeckleConnector3::Converters::SKETCHUP_UNIT_STRINGS[units])
19 | end
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/states/user_state.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../immutable/immutable'
4 |
5 | module SpeckleConnector3
6 | module States
7 | # User specific states.
8 | class UserState
9 | include Immutable::ImmutableUtils
10 |
11 | # @return [Immutable::Hash{Symbol => Object}] user specific preferences
12 | attr_reader :preferences
13 |
14 | def initialize(preferences)
15 | @preferences = preferences
16 | end
17 |
18 | def user_preferences
19 | @preferences[:user]
20 | end
21 |
22 | def model_preferences
23 | @preferences[:model]
24 | end
25 |
26 | def with_preferences(new_preferences)
27 | with(:@preferences => new_preferences)
28 | end
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/init_local_accounts.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 | require_relative '../accounts/accounts'
5 | require_relative 'load_saved_streams'
6 |
7 | module SpeckleConnector3
8 | module Actions
9 | # Action to initialize local accounts from database.
10 | class InitLocalAccounts < Action
11 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
12 | # @return [States::State] the new updated state object
13 | def self.update_state(state, _request_id, _data)
14 | puts 'Initialisation of Speckle accounts requested by plugin'
15 | accounts_data = state.speckle_state.accounts
16 | state.with_add_queue('loadAccounts', accounts_data.to_json, [])
17 | end
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/base_actions/get_send_filters.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 | require_relative '../../filters/send_filters'
5 |
6 | module SpeckleConnector3
7 | module Actions
8 | # Action to get send filter.
9 | class GetSendFilters < Action
10 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
11 | # @return [States::State] the new updated state object
12 | def self.update_state(state, resolve_id)
13 | default_filters = Filters::SendFilters.get_default(state.sketchup_state.sketchup_model)
14 | js_script = "sendBinding.receiveResponse('#{resolve_id}', #{default_filters.to_json})"
15 | state.with_add_queue_js_command('getSendFilter', js_script)
16 | end
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/account_actions/remove_account.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 | require_relative '../../accounts/accounts'
5 | require_relative '../load_saved_streams'
6 |
7 | module SpeckleConnector3
8 | module Actions
9 | # Action to remove account from database.
10 | class RemoveAccount < Action
11 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
12 | # @return [States::State] the new updated state object
13 | def self.update_state(state, resolve_id, account_id)
14 | SpeckleConnector3::Accounts.remove_account(account_id)
15 | js_script = "accountsBinding.receiveResponse('#{resolve_id}')"
16 | state.with_add_queue_js_command('removeAccount', js_script)
17 | end
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/account_actions/add_account.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 | require_relative '../../accounts/accounts'
5 | require_relative '../load_saved_streams'
6 |
7 | module SpeckleConnector3
8 | module Actions
9 | # Action to add account to local Account db.
10 | class AddAccount < Action
11 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
12 | # @return [States::State] the new updated state object
13 | def self.update_state(state, resolve_id, account_id, account)
14 | SpeckleConnector3::Accounts.add_account(account_id, account)
15 | js_script = "accountsBinding.receiveResponse('#{resolve_id}')"
16 | state.with_add_queue_js_command('addAccount', js_script)
17 | end
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/_tools/README.md:
--------------------------------------------------------------------------------
1 | # Tools
2 |
3 | This folder stores the external tools and helper scripts to make easier life of the developer,
4 | they are not the part of the main functionality of the Speckle.
5 |
6 | Tools and scripts inside the folder will be loaded with `sketchup_connector_loader.rb` file.
7 | In order to load your own `.rb` files please add this file names into list in the loader.
8 |
9 | ````ruby
10 | ...
11 |
12 | files = %w[speckle_connector jf_RubyPanel su_attributes ]
13 | # This line placed before loading started.
14 |
15 | files.each do |ruby_file|
16 | puts "Loading #{ruby_file}"
17 | begin
18 | require ruby_file
19 | rescue LoadError
20 | puts "Could not load #{ruby_file}"
21 | end
22 | end
23 | ````
24 |
25 | Track load status of your tools and scripts on the ruby console when SketchUp UI initializing.
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/mapped_entities_updated.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 | require_relative '../sketchup_model/reader/mapper_reader'
5 |
6 | module SpeckleConnector3
7 | module Actions
8 | # Triggers when mapped entities updated.
9 | class MappedEntitiesUpdated < Action
10 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
11 | # @return [States::State] the new updated state object
12 | def self.update_state(state, _resolve_id = nil, _data = nil)
13 | mapped_entities = SketchupModel::Reader::MapperReader
14 | .mapped_entity_details(state.speckle_state.speckle_mapper_state.mapped_entities.values.to_a)
15 |
16 | state.with_mapped_entities_queue(mapped_entities)
17 | end
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/commands/receive_objects.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'command'
4 | require_relative '../actions/receive_objects'
5 |
6 | module SpeckleConnector3
7 | module Commands
8 | # Command to receive objects from Speckle Server.
9 | class ReceiveObjects < Command
10 | def _run(_resolve_id, data)
11 | stream_id = data['stream_id']
12 | base = data['base']
13 | branch_name = data['branch_name']
14 | branch_id = data['branch_id']
15 | stream_name = data['stream_name']
16 | source_app = data['source_app']
17 | object_id = data['object_id']
18 | action = Actions::ReceiveObjects.new(stream_id, base, stream_name, branch_name, branch_id, source_app, object_id)
19 | app.update_state!(action)
20 | end
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/mapper_initialized.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 | require_relative '../mapper/category/revit_category'
5 | require_relative '../mapper/category/revit_family_category'
6 |
7 | module SpeckleConnector3
8 | module Actions
9 | # Collects mapper selection info.
10 | class MapperInitialized < Action
11 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
12 | # @return [States::State] the new updated state object
13 | def self.update_state(state, _data)
14 | init_parameters = {
15 | categories: Mapper::Category::RevitCategory.to_a,
16 | familyCategories: Mapper::Category::RevitFamilyCategory.to_a
17 | }.freeze
18 | state.with_mapper_init_queue(init_parameters)
19 | end
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/config_actions/get_config.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 |
5 | module SpeckleConnector3
6 | module Actions
7 | # Action to get config.
8 | class GetConfig < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state, resolve_id)
12 | # Previously it was stored in user state
13 | # config = state.user_state.preferences.to_json
14 | config = {
15 | darkTheme: state.user_state.user_preferences[:dark_theme]
16 | }
17 | js_script = "configBinding.receiveResponse('#{resolve_id}', #{config.to_json})"
18 | state.with_add_queue_js_command('getConfig', js_script)
19 | end
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/other/rendering_options.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'color'
4 |
5 | module SpeckleConnector3
6 | module SpeckleObjects
7 | module Other
8 | # Rendering options for scenes.
9 | class RenderingOptions
10 | # @param options [Sketchup::RenderingOptions] rendering options to convert speckle object
11 | def self.to_speckle(options)
12 | options.to_h.collect do |option_prop, option_value|
13 | speckle_value = if option_value.is_a?(Sketchup::Color)
14 | Color.to_speckle(option_value)
15 | else
16 | option_value
17 | end
18 | [option_prop.to_sym, speckle_value]
19 | end.to_h
20 | end
21 | end
22 | end
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ui/bindings/accounts_binding.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'binding'
4 | require_relative '../../actions/account_actions/get_accounts'
5 | require_relative '../../actions/account_actions/add_account'
6 | require_relative '../../actions/account_actions/remove_account'
7 |
8 | module SpeckleConnector3
9 | module Ui
10 | ACCOUNTS_BINDING_NAME = 'accountsBinding'
11 |
12 | # Binding that provided for DUI.
13 | class AccountsBinding < Binding
14 | def commands
15 | @commands ||= {
16 | getAccounts: Commands::ActionCommand.new(@app, self, Actions::GetAccounts),
17 | addAccount: Commands::ActionCommand.new(@app, self, Actions::AddAccount),
18 | removeAccount: Commands::ActionCommand.new(@app, self, Actions::RemoveAccount)
19 | }.freeze
20 | end
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/base_actions/update_send_filter.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 | require_relative '../../sketchup_model/dictionary/model_card_dictionary_handler'
5 |
6 | module SpeckleConnector3
7 | module Actions
8 | # Action to update send filter.
9 | class UpdateSendFilter < Action
10 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
11 | # @return [States::State] the new updated state object
12 | def self.update_state(state, resolve_id, data, value)
13 | SketchupModel::Dictionary::ModelCardDictionaryHandler.update_filter(state.sketchup_state.sketchup_model, data, value)
14 |
15 | js_script = "sendBinding.receiveResponse('#{resolve_id}')"
16 | state.with_add_queue_js_command('updateSendFilter', js_script)
17 | end
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/get_document_info.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 |
5 | module SpeckleConnector3
6 | module Actions
7 | # Get document info.
8 | class GetDocumentInfo < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state, resolve_id)
12 | document_info = {
13 | location: state.sketchup_state.sketchup_model.path,
14 | name: state.sketchup_state.sketchup_model.name,
15 | id: state.sketchup_state.sketchup_model.guid
16 | }
17 | js_command = "baseBinding.receiveResponse('#{resolve_id}', #{document_info.to_json})"
18 | state.with_add_queue_js_command('getDocumentInfo', js_command)
19 | end
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ui/sketchup_ui.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | module Ui
5 | # An interface to Sketchup user interface. This object controls the menu `Extensions->Speckle` in Sketchup's menu,
6 | # the Speckle toolbar and sending message to the user via Sketchup.
7 | class SketchupUi
8 | MENU_TITLE = 'Speckle'
9 | BEFORE_NEVER_SHOWN = -1
10 |
11 | # @return [Sketchup::Menu] the menu of the Speckle
12 | attr_reader :speckle_menu
13 |
14 | # @return [UI::Toolbar] the Speckle toolbar
15 | attr_reader :speckle_toolbar
16 |
17 | def initialize
18 | @speckle_menu = UI.menu.add_submenu(MENU_TITLE)
19 | @speckle_toolbar = UI::Toolbar.new(MENU_TITLE)
20 | @speckle_toolbar.show if @speckle_toolbar.get_last_state == BEFORE_NEVER_SHOWN
21 | end
22 | end
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ui/receive_binding.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'bindings/binding'
4 | require_relative '../actions/receive_actions/before_receive'
5 | require_relative '../actions/receive_actions/receive_single_object'
6 | require_relative '../actions/receive_actions/after_receive'
7 |
8 | module SpeckleConnector3
9 | module Ui
10 | RECEIVE_BINDING_NAME = 'sketchupReceiveBinding'
11 |
12 | # Binding that provided for DUI.
13 | class ReceiveBinding < Binding
14 | def commands
15 | @commands ||= {
16 | beforeReceive: Commands::ActionCommand.new(@app, self, Actions::BeforeReceive),
17 | receiveObject: Commands::ActionCommand.new(@app, self, Actions::ReceiveSingleObject),
18 | afterReceive: Commands::ActionCommand.new(@app, self, Actions::AfterReceive)
19 | }.freeze
20 | end
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/config_actions/get_user_selected_account_id.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 | require_relative '../../preferences/preferences'
5 |
6 | module SpeckleConnector3
7 | module Actions
8 | class GetUserSelectedAccountId < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state, resolve_id)
12 | user_selected_account_id = Preferences.get_user_selected_account_id
13 | accountsConfig = {
14 | userSelectedAccountId: user_selected_account_id
15 | }
16 | js_script = "configBinding.receiveResponse('#{resolve_id}', #{accountsConfig.to_json})"
17 | state.with_add_queue_js_command('getUserSelectedAccountId', js_script)
18 | end
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/speckle_connector_3/debug.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # Speckle connector module to enable multiplayer mode ON!
4 | module SpeckleConnector3
5 | # from thomthom
6 | # https://github.com/thomthom/true-bend/blob/master/src/tt_truebend/debug.rb
7 |
8 | # @note Debug method to reload the plugin.
9 | #
10 | # @example
11 | # SpeckleConnector.reload
12 | #
13 | # @return [Integer] Number of files reloaded.
14 | # rubocop:disable SketchupSuggestions/FileEncoding
15 | def self.reload
16 | load(__FILE__)
17 | pattern = File.join(__dir__, '**/*.rb')
18 | # TODO: Here is a opportunity to improve reloading process.
19 | # We can cache last edited time of the each file later to check which file need to be reloaded.
20 | Dir.glob(pattern).each { |file| load(file) unless file.include?('bootstrap') }
21 | .size
22 | end
23 | # rubocop:enable SketchupSuggestions/FileEncoding
24 | end
25 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/account_actions/get_accounts.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 | require_relative '../../accounts/accounts'
5 | require_relative '../load_saved_streams'
6 |
7 | module SpeckleConnector3
8 | module Actions
9 | # Action to initialize local accounts from database.
10 | class GetAccounts < Action
11 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
12 | # @return [States::State] the new updated state object
13 | def self.update_state(state, resolve_id)
14 | puts 'Initialisation of Speckle accounts requested by plugin'
15 | accounts_data = SpeckleConnector3::Accounts.load_accounts
16 | js_script = "accountsBinding.receiveResponse('#{resolve_id}', #{accounts_data.to_json})"
17 | state.with_add_queue_js_command('getAccounts', js_script)
18 | end
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/sketchup_model/dictionary/speckle_model_dictionary_handler.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'base_dictionary_handler'
4 | require_relative '../../constants/dict_constants'
5 | require_relative '../../constants/type_constants'
6 |
7 | module SpeckleConnector3
8 | module SketchupModel
9 | module Dictionary
10 | # Dictionary handler of the speckle model.
11 | class SpeckleModelDictionaryHandler < BaseDictionaryHandler
12 | DICTIONARY_NAME = 'Speckle'
13 | # Writes initial data while speckle entity is creating first time.
14 | # @param sketchup_model [Sketchup::Model] Sketchup model to write data into it's attribute dictionary.
15 | def self.write_initial_model_data(sketchup_model, default_preferences)
16 | set_hash(sketchup_model, default_preferences, DICTIONARY_NAME)
17 | end
18 | end
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/commands/apply_mappings.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'command'
4 | require_relative '../actions/apply_mappings'
5 |
6 | module SpeckleConnector3
7 | module Commands
8 | # Command to apply mapping for selected entities.
9 | class ApplyMappings < Command
10 | def _run(_resolve_id, data)
11 | entities_to_map = data['entitiesToMap']
12 | method = data['method']
13 | category = data['category']
14 | family = data['family']
15 | family_type = data['familyType']
16 | level = data['level']
17 | name = data['name']
18 | is_definition = data['isDefinition']
19 | action = Actions::ApplyMappings.new(entities_to_map, method, category, family,
20 | family_type, level, name, is_definition)
21 | app.update_state!(action)
22 | end
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/object_reference.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'json'
4 | require_relative '../immutable/immutable'
5 | require_relative 'base'
6 |
7 | module SpeckleConnector3
8 | module SpeckleObjects
9 | # Object reference to send it to Speckle server. It contains closure table to store children objects.
10 | class ObjectReference < Base
11 |
12 | attr_reader :closure, :referenced_id, :application_id
13 |
14 | def initialize(referenced_id, application_id, closure)
15 | @speckle_type = 'reference'
16 | @closure = closure
17 | @referenced_id = referenced_id
18 | @application_id = application_id
19 | super()
20 | update(
21 | {
22 | speckle_type: 'reference',
23 | referencedId: referenced_id,
24 | __closure: closure
25 | }
26 | )
27 | end
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/reload_accounts.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 | require_relative '../accounts/accounts'
5 | require_relative 'load_saved_streams'
6 |
7 | module SpeckleConnector3
8 | module Actions
9 | # Action to reload accounts from database.
10 | class ReloadAccounts < Action
11 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
12 | # @return [States::State] the new updated state object
13 | def self.update_state(state, _resolve_id, _data)
14 | puts 'Reload of Speckle accounts requested by plugin'
15 | new_speckle_state = state.speckle_state.with_accounts(Accounts.load_accounts)
16 | state = state.with_speckle_state(new_speckle_state)
17 | accounts_data = state.speckle_state.accounts
18 | state.with_add_queue('loadAccounts', accounts_data.to_json, [])
19 | end
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/save_stream.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 | require_relative '../accounts/accounts'
5 |
6 | module SpeckleConnector3
7 | module Actions
8 | # Save stream.
9 | # Currently it is not a state changer.
10 | class SaveStream < Action
11 | def initialize(stream_id)
12 | super()
13 | @stream_id = stream_id
14 | end
15 |
16 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
17 | # @return [States::State] the new updated state object
18 | def update_state(state)
19 | speckle_dict = state.sketchup_state.sketchup_model.attribute_dictionary('Speckle', true)
20 | saved = speckle_dict['saved_streams'] || []
21 | saved = saved.empty? ? [@stream_id] : saved.unshift(@stream_id)
22 | speckle_dict['saved_streams'] = saved
23 | state
24 | end
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ext/immutable_ruby/json.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # Define the method to export immutable structures to JSON. Default exporter would only export the name of the class as
4 | # a string. In order to export it properly, we need to add `to_json` methods to the classes we want to serialize as JSON.
5 | module SpeckleConnector3
6 | module Immutable
7 | class Vector
8 | # Convert the object to JSON
9 | # @return [String] json encoded string
10 | # @param args [Array] the arguments that will be passed to JSON.to_json method
11 | def to_json(*args)
12 | to_a.to_json(*args)
13 | end
14 | end
15 | class Hash
16 | # Convert the object to JSON
17 | # @return [String] json encoded string
18 | # @param args [Array] the arguments that will be passed to JSON.to_json method
19 | def to_json(*args)
20 | to_h.to_json(*args)
21 | end
22 | end
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/config_actions/update_config.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 | require_relative '../user_preferences_updated'
5 |
6 | module SpeckleConnector3
7 | module Actions
8 | # Action to update config.
9 | class UpdateConfig < Action
10 | KEY_VALUES = {
11 | 'darkTheme' => 'dark_theme'
12 | }.freeze
13 |
14 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
15 | # @return [States::State] the new updated state object
16 | def self.update_state(state, resolve_id, config)
17 | config.each do |key, value|
18 | state = Actions::UserPreferencesUpdated.new('Sketchup', KEY_VALUES[key], value).update_state(state)
19 | end
20 |
21 | js_script = "configBinding.receiveResponse('#{resolve_id}')"
22 | state.with_add_queue_js_command('updateConfig', js_script)
23 | end
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | // See https://go.microsoft.com/fwlink/?LinkId=733558
3 | // for the documentation about the tasks.json format
4 | // note that default shell needs to be powershell
5 | "version": "2.0.0",
6 | "tasks": [
7 | {
8 | "label": "Debug SketchUp 2021",
9 | "type": "shell",
10 | "command": "open -a '/Applications/SketchUp 2021/SketchUp.app' --args -rdebug 'ide port=7000'",
11 | "windows": {
12 | "command": "&'C:/Program Files/SketchUp/SketchUp 2021/SketchUp.exe' -rdebug 'ide port=7000'",
13 | },
14 | "problemMatcher": []
15 | },
16 | {
17 | "label": "Debug SketchUp 2022",
18 | "type": "shell",
19 | "command": "open -a '/Applications/SketchUp 2022/SketchUp.app' --args -rdebug 'ide port=7000'",
20 | "windows": {
21 | "command": "&'C:/Program Files/SketchUp/SketchUp 2022/SketchUp.exe' -rdebug 'ide port=7000'",
22 | },
23 | "problemMatcher": []
24 | },
25 | ]
26 | }
--------------------------------------------------------------------------------
/speckle_connector_3/src/filters/send/layer_filter.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../../ui_data/components/selections/list_selection'
4 |
5 | module SpeckleConnector3
6 | module Filters
7 | module Send
8 | # Layer (tag) filter for sketchup connector to send all.
9 | class LayerFilter < UiData::Components::Selections::ListSelection
10 | def initialize(items, selected_items)
11 | super('tags', 'Tags', items, selected_items, true)
12 | end
13 |
14 | def self.from_json(data)
15 | items = data['items'].collect do |key, item|
16 | [key, [UiData::Components::Selections::ListSelectionItem.new(item['id'], item['name'], item['color'], '')]]
17 | end.to_h
18 | LayerFilter.new(items, data['selectedItems'])
19 | end
20 |
21 | def check_expiry(_ids)
22 | # TODO: Implement!
23 | false
24 | end
25 | end
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/operations/receive.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../accounts/accounts'
4 |
5 | module SpeckleConnector3
6 | # Operations between server and connector.
7 | module Operations
8 | # Receive operation. (WIP)
9 | def self.receive(stream_id, object_id)
10 | default_account = Accounts.default_account
11 | url = default_account['serverInfo']['url']
12 | token = default_account['token']
13 | uri = URI.parse("#{url}/objects/#{stream_id}/#{object_id}/single")
14 |
15 | headers = {}
16 | headers['Authorization'] = "Bearer #{token}"
17 | headers['Accept'] = 'text/plain'
18 | content = nil
19 |
20 | @request = Sketchup::Http::Request.new(uri.to_s, Sketchup::Http::GET)
21 | @request.headers = headers
22 |
23 | # Can't catch here content as sync...!
24 | @request.start do |req, res|
25 | content = res.body
26 | end
27 |
28 | content
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/gis/utils.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../base'
4 | require_relative '../other/transform'
5 | require_relative '../other/block_definition'
6 | require_relative '../other/block_instance'
7 | require_relative '../../constants/type_constants'
8 | require_relative '../../sketchup_model/dictionary/dictionary_handler'
9 |
10 | module SpeckleConnector3
11 | module SpeckleObjects
12 | module GIS
13 | def self.get_definition_name(obj, attributes)
14 | return obj['name'] unless obj['name'].nil?
15 |
16 | return attributes['name'] unless attributes['name'].nil?
17 |
18 | return "def::#{obj['id']}"
19 | end
20 |
21 | def self.get_qgis_attributes(obj)
22 | attributes = obj['attributes'].to_h
23 | speckle_properties = %w[id speckle_type units applicationId]
24 | speckle_properties.each { |key| attributes.delete(key) }
25 | attributes
26 | end
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/remove_stream.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 | require_relative '../accounts/accounts'
5 | require_relative '../convertors/units'
6 | require_relative '../convertors/converter'
7 |
8 | module SpeckleConnector3
9 | module Actions
10 | # Action to remove stream.
11 | # Currently it is not a state changer.
12 | class RemoveStream < Action
13 | def initialize(stream_id)
14 | super()
15 | @stream_id = stream_id
16 | end
17 |
18 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
19 | # @return [States::State] the new updated state object
20 | def update_state(state)
21 | speckle_dict = state.sketchup_state.sketchup_model.attribute_dictionary('Speckle', true)
22 | saved = speckle_dict['saved_streams'] || []
23 | saved -= [@stream_id]
24 | speckle_dict['saved_streams'] = saved
25 | state
26 | end
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ui/command_data.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'json'
4 |
5 | module SpeckleConnector3
6 | module Ui
7 | # Command structure to handle it with dialog.exec_callback
8 | CommandData = Struct.new(:name, :binding_name, :resolve_id, :data)
9 |
10 | # Parser class for commands that comes from dialog to ruby engine.
11 | class CommandParser
12 | # @return [Array] parsed commands.
13 | def self.parse_commands(data)
14 | data = JSON.parse(data) if data.is_a? String
15 | return [parse(data)].compact unless data.is_a?(Array)
16 |
17 | data.collect { |command| parse(command) }.compact
18 | end
19 |
20 | def self.parse(command)
21 | return nil unless command.is_a?(Hash)
22 |
23 | name = command['name']
24 |
25 | return nil unless name.is_a?(String)
26 |
27 | CommandData.new(name.to_sym, command['binding_name'], command['request_id'], command['data'])
28 | end
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/tests/src/speckle_objects/geometry/point_test.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'json'
4 | require_relative '../../../test_helper'
5 | require_relative '../../../../speckle_connector_3/src/speckle_objects/geometry/point'
6 |
7 | module SpeckleConnector3
8 | module SpeckleObjects
9 | module Geometry
10 | class PointTest < Minitest::Test
11 | def setup
12 | # Do nothing
13 | end
14 |
15 | def teardown
16 | # Do nothing
17 | end
18 |
19 | def test_point_to_json
20 | point = Point.new(1.0, 1.0, 1.0, 'm')
21 | serialized_point = {
22 | speckle_type: 'Objects.Geometry.Point',
23 | units: 'm',
24 | x: 1.0,
25 | y: 1.0,
26 | z: 1.0
27 | }
28 | serialized = point.to_json
29 | hash = JSON.parse(serialized, { symbolize_names: true })
30 |
31 | assert_equal(serialized_point, hash)
32 | end
33 | end
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ext/immutable_ruby/core.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'hash'
4 | require_relative 'set'
5 | require_relative 'vector'
6 | # Add json conversion methods
7 | require_relative 'json'
8 |
9 | module SpeckleConnector3
10 | module Immutable
11 | class Hash
12 | # Return a new {Set} containing the keys from this `Hash`.
13 | #
14 | # @example
15 | # Immutable::Hash["A" => 1, "B" => 2, "C" => 3, "D" => 2].keys
16 | # # => Immutable::Set["D", "C", "B", "A"]
17 | #
18 | # @return [Set]
19 | def keys
20 | Set.alloc(@trie)
21 | end
22 |
23 | # Return a new {Vector} populated with the values from this `Hash`.
24 | #
25 | # @example
26 | # Immutable::Hash["A" => 1, "B" => 2, "C" => 3, "D" => 2].values
27 | # # => Immutable::Vector[2, 3, 2, 1]
28 | #
29 | # @return [Vector]
30 | def values
31 | Vector.new(each_value.to_a.freeze)
32 | end
33 | end
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ui/ui_controller.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | module Ui
5 | # The class that handle communication between ruby code and different user interfaces.
6 | class UiController
7 | # @return [Immutable::Hash] the registered user interfaces that will receive notifications when Speckle states
8 | # is updated.
9 | attr_reader :user_interfaces
10 |
11 | # @return [Ui::SketchupUi] the interface to Sketchup UI features
12 | attr_reader :sketchup_ui
13 |
14 | # @param sketchup_ui [Ui::SketchupUi] the interface to Sketchup UI features
15 | def initialize(sketchup_ui)
16 | @user_interfaces = {}
17 | @sketchup_ui = sketchup_ui
18 | end
19 |
20 | # Register user interface to receive notifications about states changes
21 | def register_ui(interface_id, user_interface)
22 | # FIXME: Mutable alert!
23 | @user_interfaces[interface_id] = user_interface
24 | end
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/sketchup_model/dictionary/speckle_schema_dictionary_handler.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'delegate'
4 | require_relative 'dictionary_handler'
5 | require_relative '../../constants/dict_constants'
6 |
7 | module SpeckleConnector3
8 | module SketchupModel
9 | module Dictionary
10 | # Read and write attributes for Speckle objects' schema on SketchUp model.
11 | class SpeckleSchemaDictionaryHandler < DictionaryHandler
12 | def self.speckle_schema_to_speckle(entity)
13 | schema = {}
14 | return schema if entity.attribute_dictionaries.nil?
15 |
16 | schema_dict = entity.attribute_dictionaries.find { |dict| dict.name == dictionary_name }
17 | return schema if schema_dict.nil?
18 |
19 | schema_dict.to_h
20 | end
21 |
22 | # @return [String] the name of the dictionary to read from
23 | def self.dictionary_name
24 | SPECKLE_MAPPING_TOOL_SCHEMA
25 | end
26 | end
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ui/test_binding.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'bindings/binding'
4 | require_relative '../constants/path_constants'
5 |
6 | require_relative '../actions/test_actions/say_hi'
7 | require_relative '../actions/test_actions/go_away'
8 | require_relative '../actions/test_actions/get_complex_type'
9 | require_relative '../actions/test_actions/trigger_event'
10 |
11 |
12 | module SpeckleConnector3
13 | module Ui
14 | TEST_BINDINGS_NAME = 'testBinding'
15 |
16 | # View that provided by vue.js
17 | class TestBinding < Binding
18 | def commands
19 | @commands ||= {
20 | sayHi: Commands::ActionCommand.new(@app, self, Actions::SayHi),
21 | goAway: Commands::ActionCommand.new(@app, self, Actions::GoAway),
22 | getComplexType: Commands::ActionCommand.new(@app, self, Actions::GetComplexType),
23 | triggerEvent: Commands::ActionCommand.new(@app, self, Actions::TriggerEvent)
24 | }.freeze
25 | end
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/tests/src/speckle_objects/geometry/vector_test.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'json'
4 | require_relative '../../../test_helper'
5 | require_relative '../../../../speckle_connector_3/src/speckle_objects/geometry/vector'
6 |
7 | module SpeckleConnector3
8 | module SpeckleObjects
9 | module Geometry
10 | class VectorTest < Minitest::Test
11 | def setup
12 | # Do nothing
13 | end
14 |
15 | def teardown
16 | # Do nothing
17 | end
18 |
19 | def test_vector_to_json
20 | point = Vector.new(1.0, 1.0, 1.0, 'm')
21 | serialized_point = {
22 | speckle_type: 'Objects.Geometry.Vector',
23 | units: 'm',
24 | x: 1.0,
25 | y: 1.0,
26 | z: 1.0
27 | }
28 | serialized = JSON.generate(point)
29 | hash = JSON.parse(serialized, { symbolize_names: true })
30 |
31 | assert_equal(serialized_point, hash)
32 | end
33 | end
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/speckle/core/models/gis_layer_collection.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'collection'
4 |
5 | module SpeckleConnector3
6 | module SpeckleObjects
7 | module Speckle
8 | module Core
9 | module Models
10 | # VectorLayerCollection object that collect GIS vector elements under it's elements.
11 | class GisLayerCollection < Collection
12 | # @param state [States::State] state of the Speckle application.
13 | def self.to_native(state, vector_layer_collection, layer_or_folder, entities, &convert_to_native)
14 | elements = vector_layer_collection['elements']
15 |
16 | elements.each do |element|
17 | new_state, _converted_entities = convert_to_native.call(state, element, layer_or_folder, entities)
18 | state = new_state
19 | end
20 |
21 | return state, []
22 | end
23 | end
24 | end
25 | end
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/send_from_queue.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 | require_relative '../accounts/accounts'
5 |
6 | module SpeckleConnector3
7 | module Actions
8 | # Send already converted objects from queue if exist on stream.
9 | class SendFromQueue < Action
10 | def initialize(stream_id)
11 | super()
12 | @stream_id = stream_id
13 | end
14 |
15 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
16 | # @return [States::State] the new updated state object
17 | def update_state(state)
18 | to_send_stream_id = state.speckle_state.stream_queue[:stream_id]
19 | return state if to_send_stream_id == @stream_id || to_send_stream_id.nil?
20 |
21 | to_send_converted = state.speckle_state.stream_queue[:converted].to_json
22 | new_state = state.with_add_queue('convertedFromSketchup', to_send_stream_id, [to_send_converted])
23 | new_state.with_empty_stream_queue
24 | end
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/observers/app_observer.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'event_observer'
4 |
5 | module SpeckleConnector3
6 | module Observers
7 | # App observer.
8 | class AppObserver < Sketchup::AppObserver
9 | include EventObserver
10 |
11 | # rubocop:disable Naming/MethodName
12 | # SketchUp observer method triggered when new empty model is created.
13 | #
14 | # @param model (Sketchup::Model): The active model object.
15 | def onNewModel(model)
16 | push_event(:onNewModel, model)
17 | end
18 |
19 | # SketchUp observer method triggered when previously saved model is opened.
20 | #
21 | # @param model (Sketchup::Model) - The active model object.
22 | def onOpenModel(model)
23 | push_event(:onOpenModel, model)
24 | end
25 |
26 | # SketchUp observer method triggered when user exists SketchUp.
27 | def onQuit
28 | push_event(:onQuit)
29 | end
30 | # rubocop:enable Naming/MethodName
31 | end
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/test_actions/trigger_event.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 |
5 | module SpeckleConnector3
6 | module Actions
7 | # Test purpose action.
8 | class TriggerEvent < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state, resolve_id, event_name)
12 | if event_name == 'emptyTestEvent'
13 | js_script = "testBinding.emit('#{event_name}')"
14 | else
15 | args = {
16 | name: 'Oguzhan',
17 | isOk: true,
18 | count: 3
19 | }
20 | js_script = "testBinding.emit('#{event_name}', #{args.to_json})"
21 | end
22 | resolve_js_script = "testBinding.receiveResponse('#{resolve_id}')"
23 | state = state.with_add_queue_js_command('triggerEventResolve', resolve_js_script)
24 | state.with_add_queue_js_command('triggerEvent', js_script)
25 | end
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/ui/src/graphql/stream.gql:
--------------------------------------------------------------------------------
1 | query Stream($id: String!, $limit: Int!) {
2 | stream(id: $id) {
3 | id
4 | name
5 | description
6 | role
7 | isPublic
8 | createdAt
9 | updatedAt
10 | collaborators {
11 | id
12 | name
13 | company
14 | avatar
15 | role
16 | }
17 | commits(limit: 1) {
18 | totalCount
19 | items {
20 | id
21 | createdAt
22 | message
23 | authorId
24 | branchName
25 | authorName
26 | authorAvatar
27 | referencedObject
28 | }
29 | }
30 | branches (limit: $limit) {
31 | totalCount
32 | items {
33 | id
34 | name
35 | commits(limit: 10) {
36 | totalCount
37 | items {
38 | id
39 | createdAt
40 | message
41 | authorId
42 | branchName
43 | authorName
44 | authorAvatar
45 | sourceApplication
46 | referencedObject
47 | }
48 | }
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/base_actions/get_send_settings.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 | require_relative '../../settings/card_settings'
5 |
6 | module SpeckleConnector3
7 | module Actions
8 | # Action to get send settings.
9 | class GetSendSettings < Action
10 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
11 | # @return [States::State] the new updated state object
12 | def self.update_state(state, resolve_id)
13 | # NOTE: below code is tested and works!
14 | # default_settings = [
15 | # Settings::CardSetting.new(id: "includeAttributes", title: "Include Attributes", type: "boolean", value: true),
16 | # Settings::CardSetting.new(id: "test", title: "Test", type: "string", value: "a", enum: %w[a b c])
17 | # ]
18 | default_settings = []
19 | js_script = "sendBinding.receiveResponse('#{resolve_id}', #{default_settings.to_json})"
20 | state.with_add_queue_js_command('getSendSettings', js_script)
21 | end
22 | end
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/observers/entities_observer.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'event_observer'
4 |
5 | module SpeckleConnector3
6 | module Observers
7 | # Entities observer.
8 | class EntitiesObserver < Sketchup::EntitiesObserver
9 | include EventObserver
10 |
11 | # rubocop:disable Naming/MethodName
12 | # @param entities (Sketchup::Entities)
13 | # @param entity (Sketchup::Entity)
14 | def onElementAdded(entities, entity)
15 | push_event(:onElementAdded, entities, entity)
16 | end
17 |
18 | # @param entities (Sketchup::Entities)
19 | # @param entity (Sketchup::Entity)
20 | def onElementModified(entities, entity)
21 | push_event(:onElementModified, entities, entity)
22 | end
23 |
24 | # @param entities (Sketchup::Entities)
25 | # @param entity_id (Integer) id of the removed entity.
26 | def onElementRemoved(entities, entity_id)
27 | push_event(:onElementRemoved, entities, entity_id)
28 | end
29 | # rubocop:enable Naming/MethodName
30 | end
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/other/display_style.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'color'
4 | require_relative '../base'
5 | require_relative '../../constants/type_constants'
6 |
7 | module SpeckleConnector3
8 | module SpeckleObjects
9 | module Other
10 | # DisplayStyle object for layer.
11 | class DisplayStyle < Base
12 | def initialize(name:, color:, line_type:)
13 | super(
14 | speckle_type: OBJECTS_OTHER_DISPLAYSTYLE,
15 | application_id: nil,
16 | id: nil
17 | )
18 | self[:name] = name
19 | self[:color] = color
20 | self[:linetype] = line_type unless line_type.nil?
21 | end
22 |
23 | # @param layer [Sketchup::Layer] layer to get display style.
24 | def self.from_layer(layer)
25 | DisplayStyle.new(
26 | name: '',
27 | color: Color.to_int(layer.color),
28 | line_type: layer.line_style.nil? ? nil : layer.line_style.name
29 | )
30 | end
31 | end
32 | end
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/deactivate_diffing.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 |
5 | module SpeckleConnector3
6 | module Actions
7 | # Deactivate diffing.
8 | class DeactivateDiffing < Action
9 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
10 | # @return [States::State] the new updated state object
11 | def self.update_state(state, _resolve_id, _data)
12 | puts 'Diffing deactivated!'
13 | speckle_entities = state.speckle_state.speckle_entities
14 | diffing_activated_speckle_entities = speckle_entities.reject do |_id, entity|
15 | entity.active_diffing_stream_id.nil?
16 | end
17 | diffing_activated_speckle_entities.each do |id, entity|
18 | new_entity = entity.deactivate_diffing
19 | speckle_entities = speckle_entities.put(id, new_entity)
20 | end
21 | new_speckle_state = state.speckle_state.with_speckle_entities(speckle_entities)
22 | state.with_speckle_state(new_speckle_state)
23 | end
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/send_actions/activate_send_filter.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 | require_relative '../../sketchup_model/dictionary/model_card_dictionary_handler'
5 |
6 | module SpeckleConnector3
7 | module Actions
8 | # Action to activate send filter.
9 | class ActivateSendFilter < Action
10 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
11 | # @return [States::State] the new updated state object
12 | def self.update_state(state, resolve_id, data, value)
13 | SketchupModel::Dictionary::ModelCardDictionaryHandler.update_filter(state.sketchup_state.sketchup_model, data, value)
14 | card_id = "#{data['accountId']}-#{data['projectId']}-#{data['modelId']}"
15 | send_card = state.speckle_state.send_cards[card_id]
16 | puts "Send card filter updated -> #{card_id} -> #{send_card}"
17 | js_script = "sendBindingOld.receiveResponse('#{resolve_id}')"
18 | state.with_add_queue_js_command('activateSendFilter', js_script)
19 | end
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/data/revit_data_object.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../base'
4 | require_relative '../../constants/type_constants'
5 | require_relative '../other/display_value'
6 | require_relative '../../sketchup_model/dictionary/base_dictionary_handler'
7 |
8 | module SpeckleConnector3
9 | module SpeckleObjects
10 | class RevitDataObject < Base
11 | SPECKLE_TYPE = SPECKLE_OBJECT_DATA_OBJECT_REVIT
12 |
13 | def self.to_native(state, revit_data_object, layer, entities, &convert_to_native)
14 | properties = revit_data_object['properties']
15 |
16 | new_state, instance_and_definition = SpeckleObjects::Other::DisplayValue.to_native(state, revit_data_object, layer, entities, &convert_to_native)
17 | instance, _definition = instance_and_definition
18 | attr = instance.attribute_dictionary('Speckle', true)
19 |
20 | SketchupModel::Dictionary::BaseDictionaryHandler.hash_to_dict('Revit Parameters', properties, attr) if properties
21 | return new_state, instance_and_definition
22 | end
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/send_actions/activate_send_filter_tag.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 | require_relative '../../sketchup_model/dictionary/model_card_dictionary_handler'
5 |
6 | module SpeckleConnector3
7 | module Actions
8 | # Action to activate send filter tag.
9 | class ActivateSendFilterTag < Action
10 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
11 | # @return [States::State] the new updated state object
12 | def self.update_state(state, resolve_id, data, value)
13 | SketchupModel::Dictionary::ModelCardDictionaryHandler.update_tag_filter(state.sketchup_state.sketchup_model, data, value)
14 | card_id = "#{data['accountId']}-#{data['projectId']}-#{data['modelId']}"
15 | send_card = state.speckle_state.send_cards[card_id]
16 | puts "Send card filter updated -> #{card_id} -> #{send_card}"
17 | js_script = "sendBindingOld.receiveResponse('#{resolve_id}')"
18 | state.with_add_queue_js_command('activateSendFilterTag', js_script)
19 | end
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/observers/factory.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'app_observer'
4 | require_relative 'entity_observer'
5 | require_relative 'entities_observer'
6 | require_relative 'observer_handler'
7 | require_relative 'model_observer'
8 | require_relative 'event_handler'
9 | require_relative 'selection_observer'
10 | require_relative '../constants/observer_constants'
11 |
12 | module SpeckleConnector3
13 | module Observers
14 | # Factory class to create observers and it's handler
15 | module Factory
16 | module_function
17 |
18 | def create_handler(app)
19 | event_handler = EventHandler.new(app)
20 | ObserverHandler.new(event_handler)
21 | end
22 |
23 | def create_observers(handler)
24 | {
25 | APP_OBSERVER => AppObserver.new(handler),
26 | ENTITIES_OBSERVER => EntitiesObserver.new(handler),
27 | ENTITY_OBSERVER => EntityObserver.new(handler),
28 | MODEL_OBSERVER => ModelObserver.new(handler),
29 | SELECTION_OBSERVER => SelectionObserver.new(handler)
30 | }.freeze
31 | end
32 | end
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ui_data/components/selections/list_selection_item.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | module UiData
5 | module Components
6 | module Selections
7 | # Item of the list selection data for UI.
8 | class ListSelectionItem < Hash
9 | # @return [String] id of the selection item.
10 | attr_reader :id
11 |
12 | # @return [String] name of the selection item.
13 | attr_reader :name
14 |
15 | # @return [String, NilClass] color of the selection item.
16 | attr_reader :color
17 |
18 | # @return [String] summary of the selection item.
19 | attr_reader :summary
20 |
21 | def initialize(id, name, color, summary)
22 | super()
23 | @id = id
24 | @name = name
25 | @color = color
26 | @summary = summary
27 | self[:id] = id
28 | self[:name] = name
29 | self[:color] = color unless color.nil?
30 | self[:summary] = summary
31 | end
32 | end
33 | end
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/built_elements/revit/family_instance.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../../base'
4 | require_relative '../../../constants/type_constants'
5 |
6 | module SpeckleConnector3
7 | module SpeckleObjects
8 | module BuiltElements
9 | module Revit
10 | # Family instance for Revit mappings.
11 | class FamilyInstance < Base
12 | SPECKLE_TYPE = OBJECTS_BUILTELEMENTS_REVIT_FAMILY_INSTANCE
13 |
14 | # rubocop:disable Metrics/ParameterLists
15 | def initialize(family:, type:, level:, units:, base_point:, rotation:, application_id: nil)
16 | super(
17 | speckle_type: SPECKLE_TYPE,
18 | application_id: application_id,
19 | id: nil
20 | )
21 | self[:family] = family
22 | self[:type] = type
23 | self[:level] = level
24 | self[:units] = units
25 | self[:basePoint] = base_point
26 | self[:rotation] = rotation
27 | end
28 | # rubocop:enable Metrics/ParameterLists
29 | end
30 | end
31 | end
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/queue_send.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 | require_relative '../states/state'
5 | require_relative '../states/speckle_state'
6 | require_relative '../actions/send_from_queue'
7 |
8 | module SpeckleConnector3
9 | module Actions
10 | # Send queue from state.
11 | class QueueSend < Action
12 | def initialize(stream_id, converted)
13 | super()
14 | @stream_id = stream_id
15 | @converted = converted
16 | end
17 |
18 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
19 | # @return [States::State] the new updated state object
20 | def update_state(state)
21 | to_send = { stream_id: @stream_id, converted: @converted }
22 | new_speckle_state = state.speckle_state.with(:@stream_queue => to_send)
23 | new_state = state.with(:@speckle_state => new_speckle_state)
24 | if new_state.is_connected
25 | action = Actions::SendFromQueue.new(@stream_id)
26 | new_state = action.update_state(new_state)
27 | end
28 | new_state
29 | end
30 | end
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/ui/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
13 |
17 |
21 |
22 |
23 |
24 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/base_actions/add_model.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'add_send_model_card'
4 | require_relative 'add_receive_model_card'
5 | require_relative '../action'
6 | require_relative '../../cards/send_card'
7 | require_relative '../../cards/receive_card'
8 | require_relative '../../filters/send/everything_filter'
9 | require_relative '../../filters/send/selection_filter'
10 | require_relative '../../filters/send_filters'
11 | require_relative '../../sketchup_model/dictionary/model_card_dictionary_handler'
12 |
13 | module SpeckleConnector3
14 | module Actions
15 | # Action to add send card.
16 | class AddModel < Action
17 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
18 | # @return [States::State] the new updated state object
19 | def self.update_state(state, resolve_id, data)
20 | if data['typeDiscriminator'] == 'SenderModelCard'
21 | Actions::AddSendModelCard.update_state(state, resolve_id, data)
22 | else
23 | Actions::AddReceiveModelCard.update_state(state, resolve_id, data)
24 | end
25 | end
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ui/bindings/send_binding.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'binding'
4 | require_relative '../../actions/send_actions/send'
5 | require_relative '../../actions/send_actions/after_send_objects'
6 | require_relative '../../actions/base_actions/get_send_filters'
7 | require_relative '../../actions/base_actions/get_send_settings'
8 | require_relative '../../actions/base_actions/update_send_filter'
9 |
10 | module SpeckleConnector3
11 | module Ui
12 | SEND_BINDING_NAME = 'sendBinding'
13 |
14 | # Send Binding that provided for DUI.
15 | class SendBinding < Binding
16 | def commands
17 | @commands ||= {
18 | send: Commands::ActionCommand.new(@app, self, Actions::Send),
19 | getSendFilters: Commands::ActionCommand.new(@app, self, Actions::GetSendFilters),
20 | getSendSettings: Commands::ActionCommand.new(@app, self, Actions::GetSendSettings),
21 | updateSendFilter: Commands::ActionCommand.new(@app, self, Actions::UpdateSendFilter),
22 | afterSendObjects: Commands::ActionCommand.new(@app, self, Actions::AfterSendObjects)
23 | }.freeze
24 | end
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/ui/src/graphql/streams.gql:
--------------------------------------------------------------------------------
1 | query Streams($cursor: String) {
2 | streams(cursor: $cursor) {
3 | totalCount
4 | cursor
5 | items {
6 | id
7 | name
8 | description
9 | role
10 | isPublic
11 | createdAt
12 | updatedAt
13 | collaborators {
14 | id
15 | name
16 | company
17 | avatar
18 | role
19 | }
20 | commits(limit: 1) {
21 | totalCount
22 | items {
23 | id
24 | createdAt
25 | message
26 | authorId
27 | branchName
28 | authorName
29 | authorAvatar
30 | referencedObject
31 | }
32 | }
33 | branches {
34 | totalCount
35 | items {
36 | id
37 | name
38 | commits(limit: 10) {
39 | totalCount
40 | items {
41 | id
42 | createdAt
43 | message
44 | authorId
45 | branchName
46 | authorName
47 | authorAvatar
48 | referencedObject
49 | }
50 | }
51 | }
52 | }
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ext/immutable_ruby/LICENSE:
--------------------------------------------------------------------------------
1 | Licensing
2 | =========
3 |
4 | Copyright (c) 2009-2014 Simon Harris
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining
7 | a copy of this software and associated documentation files (the
8 | "Software"), to deal in the Software without restriction, including
9 | without limitation the rights to use, copy, modify, merge, publish,
10 | distribute, sublicense, and/or sell copies of the Software, and to
11 | permit persons to whom the Software is furnished to do so, subject to
12 | the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be
15 | included in all copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/constants/path_constants.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'pathname'
4 | require_relative 'platform_constants'
5 |
6 | # Speckle connector module to enable multiplayer mode ON!
7 | module SpeckleConnector3
8 | dir = __dir__.dup
9 | dir.force_encoding('UTF-8') if dir.respond_to?(:force_encoding)
10 | HOME_PATH = (ENV['HOME']).to_s
11 | SPECKLE_SRC_PATH = Pathname.new(File.expand_path('..', dir)).cleanpath.to_s
12 | SPECKLE_APPDATA_PATH = case OPERATING_SYSTEM
13 | when OS_WIN
14 | path = ENV.fetch('APPDATA')
15 | Pathname.new(File.join(path, 'Speckle')).cleanpath.to_s
16 | when OS_MAC
17 | File.join(Dir.home, 'Library/Application Support/Speckle')
18 | else
19 | raise 'Speckle could not determine your Appdata path'
20 | end
21 | SPECKLE_ACCOUNTS_DB_PATH = File.join(SPECKLE_APPDATA_PATH, 'Accounts.db')
22 | SPECKLE_CONFIG_DB_PATH = File.join(SPECKLE_APPDATA_PATH, 'DUI3Config.db')
23 | SPECKLE_TEST_DB_PATH = File.join(SPECKLE_APPDATA_PATH, 'sketchup_test.db')
24 | end
25 |
--------------------------------------------------------------------------------
/tests/src/speckle_objects/test_base.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../../test_helper'
4 | require_relative '../../../speckle_connector_3/src/speckle_objects/base'
5 |
6 | module SpeckleConnector3
7 | module SpeckleObjects
8 | class BaseTest < Minitest::Test
9 | def setup
10 | # Do nothing
11 | end
12 |
13 | def teardown
14 | # Do nothing
15 | end
16 |
17 | def test_base_init
18 | base = Base.new
19 | json = base.to_json
20 |
21 | base_obj = {"speckle_type":"Base","applicationId":nil,"id":nil}
22 | serialized = JSON.generate(base_obj)
23 |
24 | assert_equal(json, serialized)
25 | end
26 |
27 | def test_base_set_property
28 | base = Base.new
29 | base[:sketchup_attributes] = {soften_edge: true}
30 | base[:id] = 'idididididid'
31 |
32 | base_obj = {"speckle_type":"Base","applicationId":nil,"id":'idididididid', "sketchup_attributes": {"soften_edge": true }}
33 | serialized = JSON.generate(base_obj)
34 | hash = JSON.parse(serialized, { symbolize_names: true })
35 |
36 | assert_equal(base, hash)
37 | end
38 | end
39 | end
40 | end
41 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ui_data/components/selections/list_selection.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'selection'
4 |
5 | module SpeckleConnector3
6 | module UiData
7 | module Components
8 | module Selections
9 | # Selections data for UI.
10 | class ListSelection < Selection
11 | # @return [Hash{Symbol=>ListSelectionItem}, Hash{Symbol=>ListSelection}] items of the selection.
12 | attr_reader :options
13 |
14 | # @return [Array] selected items of the selection.
15 | attr_reader :selected_options
16 |
17 | # @return [Boolean] whether is multiple selection or not.
18 | attr_reader :multiple_selection
19 |
20 | def initialize(id, name, options, selected_options, multiple_selection)
21 | super(id, name)
22 | @options = options
23 | @selected_options = selected_options
24 | @multiple_selection = multiple_selection
25 | self[:options] = options
26 | self[:selectedOptions] = selected_options
27 | self[:multipleSelection] = multiple_selection
28 | end
29 | end
30 | end
31 | end
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/initialize_materials.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 | require_relative 'add_material'
5 | require_relative '../constants/mat_constants'
6 |
7 | module SpeckleConnector3
8 | module Actions
9 | # Action to initialize materials (legacy for diff colors)
10 | class InitializeMaterials < Action
11 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
12 | # @return [States::State] the new updated state object
13 | def self.update_state(state)
14 | new_state = recreate_material(state, DEFAULT_NAMES[MAT_ADD], DEFAULT_COLORS[MAT_ADD], MAT_ADD)
15 | new_state = recreate_material(new_state, DEFAULT_NAMES[MAT_EDIT], DEFAULT_COLORS[MAT_EDIT], MAT_EDIT)
16 | recreate_material(new_state, DEFAULT_NAMES[MAT_REMOVE], DEFAULT_COLORS[MAT_REMOVE], MAT_REMOVE)
17 | end
18 |
19 | def self.recreate_material(state, name, color, id, alpha: nil)
20 | Actions::AddMaterial.update_state(
21 | state,
22 | material_name: name,
23 | color: color,
24 | material_id: id,
25 | alpha: alpha
26 | )
27 | end
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/send_actions/send_card_expiration_check.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 | require_relative '../../sketchup_model/dictionary/model_card_dictionary_handler'
5 |
6 | module SpeckleConnector3
7 | module Actions
8 | # Action to check send card expirations.
9 | class SendCardExpirationCheck < Action
10 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
11 | # @return [States::State] the new updated state object
12 | def self.update_state(state)
13 | return state unless state.speckle_state.changed_entity_persistent_ids.any? || state.speckle_state.changed_entity_ids.any?
14 |
15 | expired_send_cards_ids = state.speckle_state.send_cards.select do |_id, send_card|
16 | send_card.send_filter.check_expiry(state.speckle_state.changed_entity_persistent_ids) ||
17 | send_card.send_filter.check_expiry(state.speckle_state.changed_entity_ids)
18 | end.keys.to_a
19 | js_script = "sendBinding.emit('setModelsExpired', #{expired_send_cards_ids.to_json})"
20 | state.with_add_queue_js_command('setModelsExpired', js_script)
21 | end
22 | end
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/geometry/vector.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'length'
4 | require_relative '../base'
5 |
6 | module SpeckleConnector3
7 | module SpeckleObjects
8 | module Geometry
9 | # Vector object definition for Speckle.
10 | class Vector < Base
11 | SPECKLE_TYPE = 'Objects.Geometry.Vector'
12 |
13 | # @param x [Numeric] x coordinate of the vector.
14 | # @param y [Numeric] y coordinate of the vector.
15 | # @param z [Numeric] z coordinate of the vector.
16 | # @param units [String] unit of the vector.
17 | def initialize(x, y, z, units)
18 | super(
19 | speckle_type: SPECKLE_TYPE,
20 | application_id: nil,
21 | id: nil
22 | )
23 | self[:x] = x
24 | self[:y] = y
25 | self[:z] = z
26 | self[:units] = units
27 | end
28 |
29 | def self.to_native(x, y, z, units)
30 | Geom::Vector3d.new(
31 | Geometry.length_to_native(x, units),
32 | Geometry.length_to_native(y, units),
33 | Geometry.length_to_native(z, units)
34 | )
35 | end
36 | end
37 | end
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/ui/bindings/config_binding.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'binding'
4 | require_relative '../../actions/config_actions/get_is_dev_mode'
5 | require_relative '../../actions/config_actions/get_config'
6 | require_relative '../../actions/config_actions/update_config'
7 | require_relative '../../actions/config_actions/get_user_selected_account_id'
8 | require_relative '../../actions/config_actions/set_user_selected_account_id'
9 |
10 | module SpeckleConnector3
11 | module Ui
12 | CONFIG_BINDING_NAME = 'configBinding'
13 |
14 | # Config binding that provided for DUI.
15 | class ConfigBinding < Binding
16 | def commands
17 | @commands ||= {
18 | getIsDevMode: Commands::ActionCommand.new(@app, self, Actions::GetIsDevMode),
19 | getConfig: Commands::ActionCommand.new(@app, self, Actions::GetConfig),
20 | updateConfig: Commands::ActionCommand.new(@app, self, Actions::UpdateConfig),
21 | getUserSelectedAccountId: Commands::ActionCommand.new(@app, self, Actions::GetUserSelectedAccountId),
22 | setUserSelectedAccountId: Commands::ActionCommand.new(@app, self, Actions::SetUserSelectedAccountId)
23 | }.freeze
24 | end
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/clear_mapper_source.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 | require_relative '../sketchup_model/dictionary/speckle_entity_dictionary_handler'
5 |
6 | module SpeckleConnector3
7 | module Actions
8 | # Clear mapper source.
9 | class ClearMapperSource < Action
10 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
11 | # @return [States::State] the new updated state object
12 | def self.update_state(state, _resolve_id, _data)
13 | new_speckle_state = state.speckle_state.with_removed_mapper_source
14 | erase_levels(state)
15 | state.with_speckle_state(new_speckle_state)
16 | end
17 |
18 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
19 | def self.erase_levels(state)
20 | levels = state.sketchup_state.sketchup_model.definitions.select do |definition|
21 | SketchupModel::Dictionary::SpeckleEntityDictionaryHandler.get_attribute(definition, :speckle_type) ==
22 | OBJECTS_BUILTELEMENTS_REVIT_LEVEL
23 | end
24 | levels.each do |level|
25 | level.entities.clear!
26 | level.instances.each(&:erase!)
27 | end
28 | end
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/immutable/immutable.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | module Immutable
5 | # Mixin module with utilities for immutable objects
6 | module ImmutableUtils
7 | # Create a copy of the object with some of its instance variables changed
8 | # @param kw_args [{Symbol=>Object}] names and values for the instance variables that need to be changed
9 | # @return [Object] the same kind of object with some of the instance variables changed
10 | def with(**kw_args)
11 | return self if instance_variables_equal(**kw_args)
12 |
13 | new_object = dup
14 | kw_args.each do |var_name, value|
15 | new_object.instance_variable_set(var_name, value)
16 | end
17 | new_object
18 | end
19 |
20 | # Check if the given arguments are the same objects as the corresponding instance variables
21 | # @param kw_args [{Symbol=>Object}] names and values for the instance variables to be compared
22 | # @return [Boolean] true if all the objects are equal (using {eql?}) operator
23 | def instance_variables_equal(**kw_args)
24 | kw_args.all? do |var_name, value|
25 | value.eql?(instance_variable_get(var_name))
26 | end
27 | end
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/revit/revit_definition.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../other/block_definition'
4 | require_relative '../base'
5 |
6 | module SpeckleConnector3
7 | module SpeckleObjects
8 | module Revit
9 | module Other
10 | # RevitDefinition for Speckle.
11 | class RevitDefinition < Base
12 | SPECKLE_TYPE = OBJECTS_OTHER_REVIT_REVITINSTANCE
13 |
14 | def self.get_definition_name(def_obj)
15 | family = def_obj['family']
16 | type = def_obj['type']
17 | category = def_obj['category']
18 | element_id = def_obj['elementId']
19 | id = def_obj['id']
20 |
21 | return "#{family}-#{type}-#{category}-#{element_id}-#{id}"
22 | end
23 |
24 | def self.to_native(state, definition, layer, entities, &convert_to_native)
25 | definition_name = get_definition_name(definition)
26 | definition['name'] = definition_name
27 | definition['displayValue'] += definition['elements'] unless definition['elements'].nil?
28 | SpeckleObjects::Other::BlockDefinition.to_native(state, definition, layer, entities, &convert_to_native)
29 | end
30 | end
31 | end
32 | end
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/convertors/converter.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | module Converters
5 | # Helper class to convert geometries between server and Sketchup.
6 | class Converter
7 | # @return [States::State] the current state of the {SpeckleConnector3::App}
8 | attr_reader :state
9 |
10 | # @return [States::SpeckleState] the current speckle state of the {States::State}
11 | attr_reader :speckle_state
12 |
13 | # @return [Sketchup::Model] active sketchup model.
14 | attr_reader :sketchup_model
15 |
16 | # @return [String] stream id that conversion happening with it
17 | attr_reader :stream_id
18 |
19 | # @return [String] speckle units
20 | attr_reader :units
21 |
22 | attr_accessor :definitions
23 |
24 | # @param state [States::State] the current state of the {SpeckleConnector3::App}
25 | def initialize(state, stream_id)
26 | @state = state
27 | @speckle_state = state.speckle_state
28 | @sketchup_model = state.sketchup_state.sketchup_model
29 | @stream_id = stream_id
30 | su_unit = state.sketchup_state.length_units
31 | @units = Converters::SKETCHUP_UNITS[su_unit]
32 | @definitions = {}
33 | end
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/base.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'json'
4 | require_relative '../immutable/immutable'
5 |
6 | module SpeckleConnector3
7 | module SpeckleObjects
8 | # Dynamic Base object to send it to Speckle server.
9 | class Base < Hash
10 | include Immutable::ImmutableUtils
11 |
12 | attr_reader :speckle_type, :application_id, :id
13 |
14 | def initialize(speckle_type: 'Base', application_id: nil, id: '')
15 | @speckle_type = speckle_type
16 | @application_id = application_id
17 | @id = id
18 | super()
19 | update(
20 | {
21 | speckle_type: speckle_type,
22 | applicationId: application_id,
23 | id: id
24 | }
25 | )
26 | end
27 |
28 | def self.with_detached_layers(detached_layers)
29 | Base.new.merge(detached_layers)
30 | end
31 |
32 | def []=(key, val)
33 | # Clear if setting string or symbol
34 | if ((key.is_a? String) || (key.is_a? Symbol)) && include?(key)
35 | delete key.to_sym
36 | delete key.to_s
37 | end
38 | # TODO: Control here if we have conditions to add dynamic property to
39 | merge!({ key => val })
40 | end
41 | end
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/speckle_connector_3.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'sketchup'
4 | require 'extensions'
5 |
6 | # Speckle connector module to enable multiplayer mode ON!
7 | module SpeckleConnector3
8 | # Version - patched by CI
9 | CONNECTOR_VERSION = '0.0.0'
10 |
11 | file = __FILE__.dup
12 |
13 | # Account for Ruby encoding bug under Windows.
14 | file.force_encoding('UTF-8') if file.respond_to?(:force_encoding)
15 |
16 | # Support folder should be named the same as the root .rb file.
17 | folder_name = File.basename(file, '.*')
18 |
19 | # Path to the root .rb file (this file).
20 | PATH_ROOT = File.dirname(file).freeze
21 |
22 | # Path to the support folder.
23 | PATH = File.join(PATH_ROOT, folder_name).freeze
24 |
25 | # Run from localhost or from build files
26 | DEV_MODE = true
27 | puts("Loading Speckle Connector v#{CONNECTOR_VERSION} from #{DEV_MODE ? 'dev' : 'build'}")
28 |
29 | unless file_loaded?(__FILE__)
30 | ex = SketchupExtension.new('Speckle SketchUp v3', File.join(PATH, 'bootstrap'))
31 | ex.description = 'Speckle Connector for SketchUp'
32 | ex.version = CONNECTOR_VERSION
33 | ex.copyright = 'AEC Systems Ltd.'
34 | ex.creator = 'Speckle Systems'
35 | Sketchup.register_extension(ex, true)
36 |
37 | file_loaded(__FILE__)
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/sketchup_model/colors/color_manager.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../../speckle_objects/other/color'
4 | require_relative '../../speckle_objects/color_proxy'
5 |
6 | module SpeckleConnector3
7 | # Operations related to {SketchupModel}.
8 | module SketchupModel
9 | # Color related utilities.
10 | module Colors
11 | # Handle colors for layers.
12 | class ColorManager
13 | # @return [Hash{String=>SpeckleObjects::ColorProxy}] render material proxies.
14 | attr_reader :color_proxies
15 |
16 | def initialize
17 | @color_proxies = {}
18 | end
19 |
20 | # @param sketchup_model [Sketchup::Model] sketchup model to get colors from layers
21 | def unpack_colors(sketchup_model)
22 | sketchup_model.layers.each do |layer|
23 | value = SpeckleObjects::Other::Color.to_int(layer.color)
24 | if color_proxies[value.to_s].nil?
25 | color_proxies[value.to_s] = SpeckleObjects::ColorProxy.new(layer.color, value, [layer.persistent_id.to_s])
26 | else
27 | color_proxies[value.to_s].add_object_id(layer.persistent_id.to_s)
28 | end
29 | end
30 |
31 | color_proxies.values
32 | end
33 | end
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/selection_actions/get_selection.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 | require_relative '../../ui_data/sketchup/selection_info'
5 |
6 | module SpeckleConnector3
7 | module Actions
8 | # Action to get selection.
9 | class GetSelection < Action
10 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
11 | # @return [States::State] the new updated state object
12 | def self.update_state(state, resolve_id)
13 | # POC: Not happy with it. We log also entity.entityID property since
14 | # onElementRemoved observer only return them! :/ Reconsider this in BETA!
15 | selected_object_ids = state.sketchup_state.sketchup_model.selection.collect(&:persistent_id).collect(&:to_s) +
16 | state.sketchup_state.sketchup_model.selection.collect(&:entityID).collect(&:to_s) # That's bad
17 | summary = "Selected #{selected_object_ids.length / 2} objects." # POC: OFFF. I'll fix it
18 | selection_info = UiData::Sketchup::SelectionInfo.new(selected_object_ids, summary)
19 | js_script = "selectionBinding.receiveResponse('#{resolve_id}', #{selection_info.to_json})"
20 | state.with_add_queue_js_command('getSelection', js_script)
21 | end
22 | end
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/built_elements/default_beam.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../base'
4 | require_relative '../geometry/line'
5 | require_relative '../../constants/type_constants'
6 | require_relative '../../sketchup_model/dictionary/speckle_schema_dictionary_handler'
7 |
8 | module SpeckleConnector3
9 | module SpeckleObjects
10 | module BuiltElements
11 | # Default Beam object.
12 | class DefaultBeam < Base
13 | SPECKLE_TYPE = OBJECTS_BUILTELEMENTS_DEFAULT_BEAM
14 |
15 | def initialize(base_line:, units:, application_id: nil)
16 | super(
17 | speckle_type: SPECKLE_TYPE,
18 | application_id: application_id,
19 | id: nil
20 | )
21 | self[:baseLine] = base_line
22 | self[:units] = units
23 | end
24 |
25 | # @param edge [Sketchup::Edge] edge to get speckle schema for beam.
26 | def self.to_speckle_schema(_speckle_state, edge, units, global_transformation: nil)
27 | base_line = Geometry::Line.to_speckle_schema(edge: edge, units: units)
28 |
29 | DefaultBeam.new(
30 | base_line: base_line,
31 | units: units,
32 | application_id: edge.persistent_id.to_s
33 | )
34 | end
35 | end
36 | end
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/built_elements/default_duct.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../base'
4 | require_relative '../geometry/line'
5 | require_relative '../../constants/type_constants'
6 | require_relative '../../sketchup_model/dictionary/speckle_schema_dictionary_handler'
7 |
8 | module SpeckleConnector3
9 | module SpeckleObjects
10 | module BuiltElements
11 | # Default Duct object.
12 | class DefaultDuct < Base
13 | SPECKLE_TYPE = OBJECTS_BUILTELEMENTS_DEFAULT_DUCT
14 |
15 | def initialize(base_line:, units:, application_id: nil)
16 | super(
17 | speckle_type: SPECKLE_TYPE,
18 | application_id: application_id,
19 | id: nil
20 | )
21 | self[:baseLine] = base_line
22 | self[:units] = units
23 | end
24 |
25 | # @param edge [Sketchup::Edge] edge to get speckle schema for duct.
26 | def self.to_speckle_schema(_speckle_state, edge, units, global_transformation: nil)
27 | base_line = Geometry::Line.to_speckle_schema(edge: edge, units: units)
28 |
29 | DefaultDuct.new(
30 | base_line: base_line,
31 | units: units,
32 | application_id: edge.persistent_id.to_s
33 | )
34 | end
35 | end
36 | end
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/built_elements/default_pipe.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../base'
4 | require_relative '../geometry/line'
5 | require_relative '../../constants/type_constants'
6 | require_relative '../../sketchup_model/dictionary/speckle_schema_dictionary_handler'
7 |
8 | module SpeckleConnector3
9 | module SpeckleObjects
10 | module BuiltElements
11 | # Default Pipe object.
12 | class DefaultPipe < Base
13 | SPECKLE_TYPE = OBJECTS_BUILTELEMENTS_DEFAULT_PIPE
14 |
15 | def initialize(base_line:, units:, application_id: nil)
16 | super(
17 | speckle_type: SPECKLE_TYPE,
18 | application_id: application_id,
19 | id: nil
20 | )
21 | self[:baseLine] = base_line
22 | self[:units] = units
23 | end
24 |
25 | # @param edge [Sketchup::Edge] edge to get speckle schema for pipe.
26 | def self.to_speckle_schema(_speckle_state, edge, units, global_transformation: nil)
27 | base_line = Geometry::Line.to_speckle_schema(edge: edge, units: units)
28 |
29 | DefaultPipe.new(
30 | base_line: base_line,
31 | units: units,
32 | application_id: edge.persistent_id.to_s
33 | )
34 | end
35 | end
36 | end
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/receive_bindings/receive.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 | require_relative '../../accounts/accounts'
5 | require_relative '../../convertors/units'
6 | require_relative '../../convertors/to_speckle'
7 | require_relative '../../operations/send'
8 |
9 | module SpeckleConnector3
10 | module Actions
11 | # Receive from server.
12 | class Receive < Action
13 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
14 | # @return [States::State] the new updated state object
15 | def self.update_state(state, resolve_id, model_card_id)
16 | model_card = state.speckle_state.receive_cards[model_card_id]
17 | resolve_js_script = "receiveBinding.receiveResponse('#{resolve_id}')"
18 | state = state.with_add_queue_js_command('receive', resolve_js_script)
19 | args = {
20 | modelCardId: model_card_id,
21 | projectId: model_card.project_id,
22 | accountId: model_card.account_id,
23 | modelId: model_card.model_id,
24 | selectedVersionId: model_card.selected_version_id
25 | }
26 | js_script = "receiveBinding.emit('receiveViaBrowser', #{args.to_json})"
27 | state.with_add_queue_js_command('receiveViaBrowser', js_script)
28 | end
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/built_elements/default_column.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../base'
4 | require_relative '../geometry/line'
5 | require_relative '../../constants/type_constants'
6 | require_relative '../../sketchup_model/dictionary/speckle_schema_dictionary_handler'
7 |
8 | module SpeckleConnector3
9 | module SpeckleObjects
10 | module BuiltElements
11 | # Default Column object.
12 | class DefaultColumn < Base
13 | SPECKLE_TYPE = OBJECTS_BUILTELEMENTS_DEFAULT_COLUMN
14 |
15 | def initialize(base_line:, units:, application_id: nil)
16 | super(
17 | speckle_type: SPECKLE_TYPE,
18 | application_id: application_id,
19 | id: nil
20 | )
21 | self[:baseLine] = base_line
22 | self[:units] = units
23 | end
24 |
25 | # @param edge [Sketchup::Edge] edge to get speckle schema for column.
26 | def self.to_speckle_schema(_speckle_state, edge, units, global_transformation: nil)
27 | base_line = Geometry::Line.to_speckle_schema(edge: edge, units: units)
28 |
29 | DefaultColumn.new(
30 | base_line: base_line,
31 | units: units,
32 | application_id: edge.persistent_id.to_s
33 | )
34 | end
35 | end
36 | end
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/ui/src/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
19 |
--------------------------------------------------------------------------------
/ui/src/plugins/vuetify.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuetify from 'vuetify/lib/framework'
3 | import '@/scss/styles.css'
4 | Vue.use(Vuetify)
5 |
6 | export default new Vuetify({
7 | theme: {
8 | dark: false,
9 | themes: {
10 | light: {
11 | primary: '#0480FB', //speckle blue
12 | secondary: '#01D1FD', //spark blue
13 | accent: '#46B958', //data yellow
14 | mappingEntity: '#B9d8b5',
15 | error: '#FF5555', //red
16 | warning: '#D8BF16', //lightning yellow
17 | info: '#2D2ADA', //majestic blue
18 | success: '#22966C', //mantis green
19 | environment: '#AF02CB', //environment purple
20 | background: '#eeeeee',
21 | background2: '#ffffff',
22 | text: '#FFFFFF'
23 | },
24 | dark: {
25 | primary: '#0480FB', //speckle blue
26 | secondary: '#01D1FD', //spark blue
27 | accent: '#46B958', //data yellow
28 | mappingEntity: '#46B958',
29 | error: '#FF5555', //red
30 | warning: '#D8BF16', //lightning yellow
31 | info: '#2D2ADA', //majestic blue
32 | success: '#22966C', //mantis green
33 | environment: '#AF02CB', //environment purple
34 | background: '#3a3b3c',
35 | background2: '#303132'
36 | }
37 | }
38 | },
39 | icons: {
40 | iconfont: 'mdi'
41 | }
42 | })
43 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/mapper/mapper_source.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../immutable/immutable'
4 | require_relative '../speckle_objects/built_elements/level'
5 | require_relative '../speckle_objects/built_elements/revit/revit_element_type'
6 |
7 | module SpeckleConnector3
8 | # Mapper is a tool to convert SketchUp entities to other applications' native objects.
9 | module Mapper
10 | # Mapper source object that collects information about stream id and commit id to identify source in the branch,
11 | # also contains levels and family types to be able to map objects with them.
12 | class MapperSource
13 | # @return [String] stream id of the mapper source.
14 | attr_reader :stream_id
15 |
16 | # @return [String] commit id of the mapper source.
17 | attr_reader :commit_id
18 |
19 | # @return [Array] levels in the source branch.
20 | attr_reader :levels
21 |
22 | # @return [Immutable::Hash{String=>Array}] revit element
23 | # types.
24 | attr_reader :types
25 |
26 | def initialize(stream_id, commit_id, levels, types)
27 | @stream_id = stream_id
28 | @commit_id = commit_id
29 | @levels = levels
30 | @types = types
31 | end
32 | end
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/tests/src/converters/test_base_object_serializer.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../../test_helper'
4 | require_relative '../../../speckle_connector_3/src/states/speckle_state'
5 | require_relative '../../../speckle_connector_3/src/speckle_objects/geometry/point'
6 | require_relative '../../../speckle_connector_3/src/speckle_objects/geometry/line'
7 | require_relative '../../../speckle_connector_3/src/convertors/base_object_serializer'
8 | require_relative '../../../speckle_connector_3/src/convertors/base_object_serializer_v2'
9 |
10 | module SpeckleConnector3
11 | module Converters
12 | class BaseObjectSerializerTest < Minitest::Test
13 | def setup
14 | # Do nothing
15 | end
16 |
17 | def teardown
18 | # Do nothing
19 | end
20 |
21 | def test_base_initialize
22 | speckle_state = States::SpeckleState.new({}, {}, {}, {})
23 | start_point = SpeckleObjects::Geometry::Point.new(0.0, 0.0, 0.0, 'm')
24 | end_point = SpeckleObjects::Geometry::Point.new(10.0, 10.0, 0.0, 'm')
25 | line = SpeckleObjects::Geometry::Line.test_line(start_point, end_point, 'm')
26 | serializer = Converters::BaseObjectSerializerV2.new
27 |
28 | id, traversed = serializer.serialize(line)
29 | assert_equal(id, "a53c02860be04238514f1a5b00883fe2")
30 | end
31 | end
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/model_preference_updated.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 | require_relative '../ext/sqlite3'
5 | require_relative '../accounts/accounts'
6 | require_relative '../constants/path_constants'
7 | require_relative '../sketchup_model/dictionary/speckle_model_dictionary_handler'
8 |
9 | module SpeckleConnector3
10 | module Actions
11 | # When preference updated by UI.
12 | class ModelPreferencesUpdated < Action
13 | def initialize(pref, value)
14 | super()
15 | @preference = pref
16 | @value = value
17 | end
18 |
19 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
20 | # @return [States::State] the new updated state object
21 | def update_state(state)
22 | model = state.user_state.preferences[:model].dup
23 | model[@preference.to_sym] = @value
24 | new_preferences = state.user_state.preferences.put(:model, model)
25 | SketchupModel::Dictionary::SpeckleModelDictionaryHandler.set_attribute(
26 | state.sketchup_state.sketchup_model,
27 | @preference.to_sym,
28 | @value,
29 | 'Speckle'
30 | )
31 | new_user_state = state.user_state.with_preferences(new_preferences)
32 | state.with_user_state(new_user_state)
33 | end
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/events/event_action.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | module Actions
5 | # This module contains actions that are performed to handle events triggered by observers in Sketchup.
6 | module Events
7 | # Base action for Handling events
8 | class EventAction
9 | def self.actions
10 | raise NoMethodError, 'Implement in a subclass'
11 | end
12 |
13 | # Handle the events that were collected by the observer. In case of the selection observer,
14 | # we only need to handle the events once if any of the events actually happened.
15 | # @param state [States::State] the current state of the SpeckleConnector Application
16 | # @param events [Hash{Symbol=>Array}] the event data grouped by the event name
17 | # @return [States::State] the transformed state
18 | def self.update_state(state, events)
19 | # Don't do anything if there are no events for this action
20 | return state unless events
21 |
22 | actions = self.actions
23 | actions.each do |event_name, action|
24 | next unless events.key?(event_name)
25 |
26 | event_data = events[event_name]
27 | state = action.update_state(state, event_data)
28 | end
29 | state
30 | end
31 | end
32 | end
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | source 'https://rubygems.org'
4 |
5 | group :development do
6 | # mini tests for ruby classes
7 | gem 'minitest'
8 | # Git hooks manager
9 | gem 'overcommit', require: false
10 | # Pry is a runtime developer console and IRB alternative with powerful introspection capabilities.
11 | # Pry aims to be more than an IRB replacement. It is an attempt to bring REPL driven programming to the Ruby language.
12 | gem 'pry'
13 | # Make-like program implemented in Ruby. Tasks and dependencies are specified in standard Ruby syntax.
14 | gem 'rake'
15 | # RuboCop is a Ruby static code analyzer (a.k.a. linter) and code formatter.
16 | gem 'rubocop'
17 | # A RuboCop extension focused on enforcing Minitest best practices and coding conventions.
18 | gem 'rubocop-minitest'
19 | # A RuboCop plugin for Rake.
20 | gem 'rubocop-rake'
21 | # Code analysis for SketchUp extensions using the SketchUp Ruby API.
22 | gem 'rubocop-sketchup'
23 | # wraps around static analysis gems such as Reek, Flay and Flog to provide a quality report of your Ruby code.
24 | gem 'rubycritic', '~> 4.3', '>= 4.3.3', require: false
25 | # Auto completions for SketchUp API.
26 | gem 'sketchup-api-stubs'
27 | # Runtime dependency of skippy for Ruby 3.2. Have it!
28 | gem 'sorted_set', '~> 1.0'
29 | # Aid with common SketchUp extension tasks.
30 | gem 'skippy', '~> 0.5.2.a'
31 | end
32 |
--------------------------------------------------------------------------------
/tests/src/operations/test_receive.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'net/http'
4 |
5 | require_relative '../../test_helper'
6 | require_relative '../../../speckle_connector_3/src/accounts/accounts'
7 |
8 | module SpeckleConnector3
9 | module Converters
10 | class ReceiveTest < Minitest::Test
11 |
12 | # Replace here test stream id on your local server account
13 | TEST_STREAM_ID = 'f0b4392dc8'
14 |
15 | # Replace here test object id
16 | TEST_OBJECT_ID = '76de2dc989ccab95c3c5ee2d977587b4'
17 |
18 | def setup
19 | # Do nothing
20 | end
21 |
22 | def teardown
23 | # Do nothing
24 | end
25 |
26 | def test_receive
27 | local_server_account = Accounts.try_get_local_server_account
28 | uri = URI.parse("https://speckle.xyz/objects/1ce562e99a/745ea505d154c09e2317121bd263a2b2/single")
29 | # uri = URI.parse("#{local_server_account['serverInfo']['url']}/objects/#{TEST_STREAM_ID}/#{TEST_OBJECT_ID}/single")
30 | http = Net::HTTP.new(uri.host, uri.port)
31 | req = Net::HTTP::Get.new(uri)
32 | req["Authorization"] = "Bearer #{local_server_account['token']}"
33 | res = http.request(req)
34 | object_id = JSON.parse(res.body)["id"]
35 | assert_equal(TEST_OBJECT_ID, object_id)
36 | rescue => e
37 | puts "failed #{e}"
38 | end
39 | end
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/constants/pref_constants.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../speckle_objects/geometry/length'
4 |
5 | module SpeckleConnector3
6 | COMBINE_FACES_BY_MATERIAL = :combine_faces_by_material
7 | INCLUDE_ENTITY_ATTRIBUTES = :include_entity_attributes
8 | INCLUDE_FACE_ENTITY_ATTRIBUTES = :include_face_entity_attributes
9 | INCLUDE_EDGE_ENTITY_ATTRIBUTES = :include_edge_entity_attributes
10 | INCLUDE_GROUP_ENTITY_ATTRIBUTES = :include_group_entity_attributes
11 | INCLUDE_COMPONENT_ENTITY_ATTRIBUTES = :include_component_entity_attributes
12 | MERGE_COPLANAR_FACES = :merge_coplanar_faces
13 |
14 | ENTITY_KEYS_FOR_INCLUDING_ATTRIBUTES = {
15 | Sketchup::ComponentInstance => INCLUDE_COMPONENT_ENTITY_ATTRIBUTES,
16 | Sketchup::Group => INCLUDE_GROUP_ENTITY_ATTRIBUTES,
17 | Sketchup::Face => INCLUDE_FACE_ENTITY_ATTRIBUTES,
18 | Sketchup::Edge => INCLUDE_EDGE_ENTITY_ATTRIBUTES
19 | }.freeze
20 |
21 | LEVEL_SHIFT_VALUE = SpeckleObjects::Geometry.length_to_native(1.5, 'm')
22 |
23 | DEFAULT_MODEL_PREFERENCES = {
24 | COMBINE_FACES_BY_MATERIAL => true,
25 | INCLUDE_ENTITY_ATTRIBUTES => true,
26 | INCLUDE_FACE_ENTITY_ATTRIBUTES => true,
27 | INCLUDE_EDGE_ENTITY_ATTRIBUTES => true,
28 | INCLUDE_GROUP_ENTITY_ATTRIBUTES => true,
29 | INCLUDE_COMPONENT_ENTITY_ATTRIBUTES => true,
30 | MERGE_COPLANAR_FACES => true
31 | }.freeze
32 | end
33 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/activate_diffing.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 | require_relative 'deactivate_diffing'
5 |
6 | module SpeckleConnector3
7 | module Actions
8 | # Deactivate diffing for stream.
9 | class ActivateDiffing < Action
10 | def initialize(stream_id)
11 | super()
12 | @stream_id = stream_id
13 | end
14 |
15 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
16 | # @return [States::State] the new updated state object
17 | def update_state(state)
18 | state = DeactivateDiffing.update_state(state, nil, {})
19 | puts "Diffing activated for #{@stream_id}"
20 | speckle_entities = state.speckle_state.speckle_entities
21 | invalid_speckle_entities = speckle_entities.select do |_id, entity|
22 | entity.invalid_stream_ids.include?(@stream_id) && entity.sketchup_entity.is_a?(Sketchup::Face)
23 | end
24 | invalid_speckle_entities.each do |id, entity|
25 | new_entity = entity.activate_diffing(@stream_id, state.sketchup_state.materials.by_id(MAT_EDIT))
26 | speckle_entities = speckle_entities.put(id, new_entity)
27 | end
28 | new_speckle_state = state.speckle_state.with_speckle_entities(speckle_entities)
29 | state.with_speckle_state(new_speckle_state)
30 | end
31 | end
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/handle_error.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module SpeckleConnector3
4 | module Actions
5 | # Action to return error message to UI.
6 | # It is "TopLevelExceptionHandler" equivalent of C#.
7 | class HandleError < Action
8 | # @return [StandardError] error
9 | attr_reader :error
10 |
11 | # @param error [StandardError] error
12 | # @param view_name [String] name of the view (binding)
13 | # @param action [Action] action that error happened
14 | # @param parameters [Array] arguments
15 | def initialize(error, view_name, action, parameters)
16 | super()
17 | @error = error
18 | @view_name = view_name
19 | @action = action
20 | @args = parameters
21 | end
22 |
23 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
24 | # @return [States::State] the new updated state object
25 | def update_state(state)
26 | # TODO: Log here when it is ready!!!
27 | host_app_error = {
28 | message: error.message,
29 | error: error,
30 | stackTrace: error.backtrace
31 | }
32 | js_error_script = "#{@view_name}.receiveResponse('#{@args.first}', #{host_app_error.to_json})"
33 | state.with_add_queue_js_command("error_#{@view_name}", js_error_script)
34 | end
35 | end
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/on_events_action.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 | require_relative 'events/app_event_action'
5 | require_relative 'events/entities_event_action'
6 | require_relative 'events/entity_event_action'
7 | require_relative 'events/model_event_action'
8 | require_relative 'events/selection_event_action'
9 | require_relative '../constants/observer_constants'
10 |
11 | module SpeckleConnector3
12 | module Actions
13 | # Handle events that were collected by observers
14 | class OnEventsAction < Action
15 | RUN_ORDER = {
16 | APP_OBSERVER => Events::AppEventAction,
17 | ENTITY_OBSERVER => Events::EntityEventAction,
18 | ENTITIES_OBSERVER => Events::EntitiesEventAction,
19 | MODEL_OBSERVER => Events::ModelEventAction,
20 | # MATERIALS_OBSERVER => Events::MaterialsEventAction,
21 | # LAYERS_OBSERVER => Events::LayerEventAction,
22 | # PAGES_OBSERVER => Events::PagesEventAction,
23 | SELECTION_OBSERVER => Events::SelectionEventAction
24 | }.freeze
25 |
26 | def self.update_state(state, events)
27 | RUN_ORDER.each do |observer_name, action|
28 | next unless events.key?(observer_name)
29 |
30 | parameters = events[observer_name]
31 | state = action.update_state(state, parameters)
32 | end
33 | state
34 | end
35 | end
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/base_actions/highlight_model.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 | require_relative '../../sketchup_model/query/entity'
5 |
6 | module SpeckleConnector3
7 | module Actions
8 | # Action to add send card.
9 | class HighlightModel < Action
10 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
11 | # @return [States::State] the new updated state object
12 | def self.update_state(state, resolve_id, model_card_id)
13 | receiver_card = state.speckle_state.receive_cards[model_card_id]
14 | sender_card = state.speckle_state.send_cards[model_card_id]
15 | card = receiver_card || sender_card
16 |
17 | objects_to_highlight = if card.type_discriminator == 'ReceiverModelCard'
18 | state.speckle_state.receive_cards[model_card_id].baked_object_ids
19 | else
20 | state.speckle_state.send_cards[model_card_id].send_filter.selected_object_ids
21 | end
22 |
23 | SketchupModel::Utils::ViewUtils.highlight_entities(state.sketchup_state.sketchup_model, objects_to_highlight)
24 |
25 | # Resolve promise
26 | js_script = "baseBinding.receiveResponse('#{resolve_id}')"
27 | state.with_add_queue_js_command('highlightModel', js_script)
28 | end
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/geometry/plane.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'point'
4 | require_relative 'vector'
5 | require_relative '../base'
6 |
7 | module SpeckleConnector3
8 | module SpeckleObjects
9 | module Geometry
10 | # Plane object definition for Speckle.
11 | class Plane < Base
12 | SPECKLE_TYPE = 'Objects.Geometry.Plane'
13 |
14 | # @param x_dir [Geometry::Vector] vector on the x direction
15 | # @param y_dir [Geometry::Vector] vector on the y direction
16 | # @param normal [Geometry::Vector] normal vector
17 | # @param origin [Geometry::Point] origin point
18 | # @param units [String] units of the Sketchup model
19 | def initialize(x_dir, y_dir, normal, origin, units)
20 | super(
21 | speckle_type: SPECKLE_TYPE,
22 | application_id: nil,
23 | id: nil
24 | )
25 | self[:xdir] = x_dir
26 | self[:ydir] = y_dir
27 | self[:normal] = normal
28 | self[:origin] = origin
29 | self[:units] = units
30 | end
31 |
32 | def self.origin(units)
33 | Plane.new(
34 | Vector.new(1, 0, 0, units),
35 | Vector.new(0, 1, 0, units),
36 | Vector.new(0, 0, 1, units),
37 | Point.new(0, 0, 0, units),
38 | units
39 | )
40 | end
41 | end
42 | end
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/sketchup_model/utils/view_utils.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../../sketchup_model/query/entity'
4 |
5 | module SpeckleConnector3
6 | # Operations related to {SketchupModel}.
7 | module SketchupModel
8 | # Works directly with/on SketchUp Entities of different kinds (Groups, Faces, Edges, ...).
9 | module Utils
10 | # View related utils
11 | class ViewUtils
12 | def self.highlight_entities(sketchup_model, entity_ids)
13 | sketchup_model.selection.clear
14 |
15 | # below code causing huge performance bottleneck since iterate nestedly, I was initially considering to cover all cases,
16 | # but not worth to have highlighting sub elements since we already highlight the parent. This can be only an issue when user sends
17 | # only the sub elements
18 | # Flat entities to select entities on card
19 | # flat_entities = SketchupModel::Query::Entity.flat_entities(sketchup_model.entities)
20 |
21 | sketchup_model.entities.each do |entity|
22 | next unless entity_ids.include?(entity.persistent_id.to_s)
23 |
24 | sketchup_model.selection.add(entity.instances) if entity.is_a?(Sketchup::ComponentDefinition)
25 | sketchup_model.selection.add(entity)
26 | end
27 |
28 | sketchup_model.active_view.zoom(sketchup_model.selection)
29 | end
30 | end
31 | end
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/geometry/circle.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'point'
4 | require_relative 'vector'
5 | require_relative 'length'
6 | require_relative '../base'
7 | require_relative '../../constants/type_constants'
8 |
9 | module SpeckleConnector3
10 | module SpeckleObjects
11 | module Geometry
12 | # Circle object definition for Speckle.
13 | class Circle < Base
14 | SPECKLE_TYPE = OBJECTS_GEOMETRY_CIRCLE
15 |
16 | # @param [States::State] state of the current application.
17 | # @param circle [Object] object represents Speckle Circle.
18 | # @param layer [Sketchup::Layer] layer to add {Sketchup::Edge} into it.
19 | # @param entities [Sketchup::Entities] entities collection to add {Sketchup::Edge} into it.
20 | def self.to_native(state, circle, layer, entities, &_convert_to_native)
21 | plane = circle['plane']
22 | units = circle['units']
23 | origin = Point.to_native(plane['origin']['x'], plane['origin']['y'], plane['origin']['z'], units)
24 | normal = Vector.to_native(plane['normal']['x'], plane['normal']['y'], plane['normal']['z'], units)
25 | radius = Geometry.length_to_native(circle['radius'], units)
26 | edges = entities.add_circle(origin, normal, radius)
27 | edges.each { |edge| edge.layer = layer }
28 | return state, edges
29 | end
30 | end
31 | end
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/built_elements/revit/revit_element_type.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../../base'
4 |
5 | module SpeckleConnector3
6 | module SpeckleObjects
7 | module BuiltElements
8 | module Revit
9 | # Revit element type.
10 | class RevitElementType < Base
11 | SPECKLE_TYPE = OBJECTS_BUILTELEMENTS_REVIT_REVITELEMENTTYPE
12 |
13 | # rubocop:disable Metrics/ParameterLists
14 | def initialize(category:, family:, type:, element_id:, application_id: nil, id: nil)
15 | super(
16 | speckle_type: SPECKLE_TYPE,
17 | application_id: application_id,
18 | id: id
19 | )
20 | self[:category] = category
21 | self[:family] = family
22 | self[:type] = type
23 | self[:elementId] = element_id
24 | end
25 | # rubocop:enable Metrics/ParameterLists
26 |
27 | def self.to_native(revit_element_type)
28 | RevitElementType.new(
29 | category: revit_element_type['category'],
30 | family: revit_element_type['family'],
31 | type: revit_element_type['type'],
32 | element_id: revit_element_type['elementId'],
33 | application_id: revit_element_type['applicationId'],
34 | id: revit_element_type['id']
35 | )
36 | end
37 | end
38 | end
39 | end
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/primitive/interval.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../base'
4 | require_relative '../../speckle_objects/geometry/length'
5 |
6 | module SpeckleConnector3
7 | module SpeckleObjects
8 | module Primitive
9 | # Interval object definition for Speckle.
10 | class Interval < Base
11 | SPECKLE_TYPE = 'Objects.Primitive.Interval'
12 |
13 | # @param units [String] units of the interval.
14 | # @param start_value [Numeric] start value of the transform.
15 | # @param end_value [Numeric] end value of the transform.
16 | def initialize(units:, start_value:, end_value:)
17 | super(
18 | speckle_type: SPECKLE_TYPE,
19 | application_id: nil,
20 | id: nil
21 | )
22 | self[:units] = units
23 | self[:start] = start_value
24 | self[:end] = end_value
25 | end
26 |
27 | def self.from_numeric(start_value, end_value, units)
28 | Interval.new(
29 | units: units,
30 | start_value: start_value,
31 | end_value: end_value
32 | )
33 | end
34 |
35 | def self.from_lengths(length_1, length_2, units)
36 | start_value = Geometry.length_to_speckle(length_1, units)
37 | end_value = Geometry.length_to_speckle(length_2, units)
38 | from_numeric(start_value, end_value, units)
39 | end
40 | end
41 | end
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/speckle_connector_3/bootstrap.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'sketchup'
4 | require 'pathname'
5 | require 'speckle_connector_3/debug'
6 | require_relative 'src/log/log'
7 | require_relative 'src/ui/sketchup_ui'
8 | require_relative 'src/ui/ui_controller'
9 | require_relative 'src/commands/menu_command_handler'
10 | require_relative 'src/app/speckle_connector_app'
11 | require_relative 'src/states/user_state'
12 | require_relative 'src/states/initial_state'
13 | require_relative 'src/commands/speckle_menu_commands'
14 |
15 | # Speckle Connector on SketchUp to enable Multiplayer mode ON!
16 | module SpeckleConnector3
17 | SKETCHUP_VERSION = Sketchup.version.to_i
18 |
19 | dir = __dir__.dup
20 | dir.force_encoding('UTF-8') if dir.respond_to?(:force_encoding)
21 | SPECKLE_CONNECTOR_SRC_PATH = Pathname.new(File.expand_path(dir)).cleanpath.to_s
22 |
23 | def self.initialize_app
24 | sketchup_ui = Ui::SketchupUi.new
25 | ui_controller = Ui::UiController.new(sketchup_ui)
26 | menu_commands = Commands::MenuCommandHandler.new
27 | user_state = SpeckleConnector3::States::UserState.new({})
28 | initial_state = SpeckleConnector3::States::InitialState.new(user_state)
29 | app = SpeckleConnector3::App::SpeckleConnectorApp.new(menu_commands, initial_state, ui_controller)
30 | # Add menu commands to SketchUp and Speckle application
31 | Commands::SpeckleMenuCommands.add_initial_commands!(app)
32 | app
33 | end
34 |
35 | app = initialize_app
36 | SPECKLE_APP = app
37 | end
38 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/base_actions/remove_model.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../action'
4 | require_relative '../../cards/send_card'
5 | require_relative '../../cards/receive_card'
6 | require_relative '../../filters/send/everything_filter'
7 | require_relative '../../filters/send/selection_filter'
8 | require_relative '../../filters/send_filters'
9 | require_relative '../../sketchup_model/dictionary/model_card_dictionary_handler'
10 |
11 | module SpeckleConnector3
12 | module Actions
13 | # Action to remove send card.
14 | class RemoveModel < Action
15 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
16 | # @return [States::State] the new updated state object
17 | def self.update_state(state, resolve_id, data)
18 | SketchupModel::Dictionary::ModelCardDictionaryHandler.remove_card_dict(state.sketchup_state.sketchup_model, data)
19 | new_speckle_state = if data['typeDiscriminator'] == 'ReceiverModelCard'
20 | state.speckle_state.without_receive_card(data['id'])
21 | else
22 | state.speckle_state.without_send_card(data['id'])
23 | end
24 | state = state.with_speckle_state(new_speckle_state)
25 | # Resolve promise
26 | js_script = "baseBinding.receiveResponse('#{resolve_id}')"
27 | state.with_add_queue_js_command('removeModel', js_script)
28 | end
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/actions/hide_mappings_from_table.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'action'
4 | require_relative 'events/selection_event_action'
5 | require_relative '../sketchup_model/dictionary/speckle_schema_dictionary_handler'
6 |
7 | module SpeckleConnector3
8 | module Actions
9 | # Hide entities that selected from mapped elements table.
10 | class HideMappingsFromTable < Action
11 | # @param state [States::State] the current state of the {App::SpeckleConnectorApp}
12 | # @return [States::State] the new updated state object
13 | def self.update_state(state, _resolve_id, data)
14 | # Flat entities to clear mappings
15 | flat_entities = SketchupModel::Query::Entity.flat_entities(state.sketchup_state.sketchup_model.entities)
16 |
17 | # Collect entity ids to clear mappings
18 | entity_ids = data.collect { |_, entities| entities['selectedElements'].collect { |e| e['entityId'] } }.flatten
19 |
20 | # Store speckle state to update with mapped entities.
21 | flat_entities.each do |entity|
22 | next unless entity_ids.include?(entity.persistent_id.to_s)
23 |
24 | if entity.is_a?(Sketchup::ComponentDefinition)
25 | entity.instances.each do |instance|
26 | instance.hidden = true
27 | end
28 | end
29 | entity.hidden = true
30 | end
31 |
32 | Events::SelectionEventAction.update_state(state, { clear: true })
33 | end
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/_tools/jf_RubyPanel.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # #-------------------------------------------------------------------------------------------------
4 | # *************************************************************************************************
5 | # RubyPanel Toolbar (C) 2007 jim.foltz@gmail.com
6 | #
7 | # With special thanks to Chris Phillips (Sketchy Physics)
8 | # for the Win32API code examples.
9 | #
10 | # 2011-01-05
11 | # * Changed Toolbar name from "Ruby COnsole" to "Ruby Toolbar" (TT)
12 | # http://forums.sketchucation.com/viewtopic.php?f=323&t=1542&p=298587#p298587
13 | # * Wrapped in addition module RubyToolbar
14 | # * Use $suString.GetSting to get proper "Ruby Console" name string.
15 | # * Better check if TB was previously visible
16 | # * Use UI.start_timer to restore Toolbar
17 | # ICONS: located in the subfolder "rubytoolbar"
18 | # MODIFICATION: by Fredo6 for compliance with SU 2014 (and no dependency on Win32API) - 18 Sep 2013
19 | # *************************************************************************************************
20 | #-------------------------------------------------------------------------------------------------
21 |
22 | require 'sketchup'
23 | require 'extensions'
24 |
25 | ext = SketchupExtension.new('Ruby Toolbar', 'jf_RubyPanel/rubytoolbar.rb')
26 | ext.creator = 'Jim Foltz '
27 | ext.description = 'Toolbar for manipulating the Ruby Console. Compatible with SketchUp 2014'
28 | ext.version = '2014'
29 | Sketchup.register_extension(ext, true)
30 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/observers/event_observer.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative 'event_hash'
4 | require_relative '../actions/on_events_action'
5 |
6 | module SpeckleConnector3
7 | module Observers
8 | # Observer classes includes it to check common operations for all observer classes.
9 | module EventObserver
10 | # @return [ObserverHandler] handler for observer events
11 | attr_reader :observer_handler
12 |
13 | def initialize(observer_handler)
14 | super()
15 | @observer_handler = observer_handler
16 | end
17 |
18 | def push_event(event_name, *event_data)
19 | return if observers_disabled?
20 |
21 | @observer_handler.handle_event!(self.class.name, event_name, event_data)
22 | end
23 |
24 | def observers_disabled?
25 | @observer_handler.observers_disabled?
26 | end
27 |
28 | # Push event only once. If the event is already registered, don't push it again
29 | # @param event_name [Symbol] the name of the event
30 | # @param event_data [Array] the optional data that comes with the event
31 | def push_once(event_name, *event_data)
32 | return if observers_disabled?
33 |
34 | # Don't push anything if the selection event was already registered
35 | class_events = @observer_handler.events[self.class]
36 | events = class_events && class_events[event_name]
37 | return if events&.any?
38 |
39 | push_event(event_name, *event_data)
40 | end
41 | end
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/speckle_connector_3/src/speckle_objects/speckle/core/models/collection.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require_relative '../../../base'
4 | require_relative '../../../../constants/type_constants'
5 |
6 | module SpeckleConnector3
7 | module SpeckleObjects
8 | module Speckle
9 | module Core
10 | module Models
11 | # Collection object that collect other speckle objects under it's elements.
12 | class Collection < Base
13 | # @param name [String] name of the collection.
14 | # @param collection_type [String] type of the collection like, layers, categories etc..
15 | # @param elements [Array