Compare commits
214 Commits
2.17.2-alpha2
...
v3.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
| d0b234bf3d | |||
| 981fe05c15 | |||
| 918550465b | |||
| 963d4f1738 | |||
| d809732280 | |||
| c4e38a11b7 | |||
| 7abe215bc2 | |||
| 0f269430bc | |||
| b8a298c54b | |||
| e1d33cd250 | |||
| 4563dec9bc | |||
| de284083fd | |||
| 85ee66ca4d | |||
| 5365dc858e | |||
| 69f9544638 | |||
| bf5409cf90 | |||
| bd4f668526 | |||
| d21df0c6fd | |||
| d808fdaa09 | |||
| b32d23b9d6 | |||
| d1b8ba95df | |||
| 5e6825bbdb | |||
| 3e5ba136be | |||
| 294b49a11c | |||
| 9e0cca447f | |||
| bc3f23d8dd | |||
| 4fcf11eaa8 | |||
| 1f45902837 | |||
| bc55543e23 | |||
| c1b8ec7036 | |||
| abe9de1b4a | |||
| 09cc83eb14 | |||
| 8f7b3fce0c | |||
| f121f1adfe | |||
| 522ace443a | |||
| 8f97f59a9a | |||
| 8e9d98cd55 | |||
| 746230caa0 | |||
| 03e80c6361 | |||
| bc547c13db | |||
| 173df6128e | |||
| 666d882ec6 | |||
| 6ea13c4edc | |||
| 39bdff1c02 | |||
| 45fc851722 | |||
| ede81f3a7d | |||
| bae9f30445 | |||
| 527cefa3ef | |||
| 830aee116e | |||
| 243fbea769 | |||
| 9c885258d9 | |||
| 0ad4e15f0a | |||
| a2ba6823a3 | |||
| 3713abd860 | |||
| 5ae78fb192 | |||
| 0b694833fb | |||
| dfd82e6d40 | |||
| 1694786177 | |||
| ec72cc1454 | |||
| 37ba4d9a80 | |||
| 526e497037 | |||
| a81a723ba8 | |||
| 5976898f07 | |||
| 09fec26841 | |||
| 165eb238b5 | |||
| de305a3508 | |||
| d124478a92 | |||
| d9acc5b39d | |||
| 5b91a04e1e | |||
| d145ce52f7 | |||
| ec598bf4a8 | |||
| 568e679e3f | |||
| 85cc49f4d9 | |||
| 65b07d44ab | |||
| f87bc98169 | |||
| 04270a8abc | |||
| 65fa47c9ac | |||
| 9367ea7e17 | |||
| b7ac9d1fee | |||
| f20b26045c | |||
| 4bcbc5131b | |||
| eeea2d7c8d | |||
| 68e9468294 | |||
| 694da73b77 | |||
| 15657bf0ec | |||
| 78c6898ff0 | |||
| 836e97a57c | |||
| 7f708108f2 | |||
| 2d3e282150 | |||
| 75b933ef0a | |||
| c19799f081 | |||
| 848ed922b5 | |||
| 16e96b69a4 | |||
| fbdd7ee7b6 | |||
| d3df5fceec | |||
| 948925d156 | |||
| 7ab6b1b167 | |||
| ca3a109bc8 | |||
| ebe9551e72 | |||
| d2836189c3 | |||
| 3703963ec8 | |||
| 02ca8e3a59 | |||
| 7c73658fa5 | |||
| e03b448618 | |||
| c8d635752b | |||
| df9a5600d9 | |||
| dd730ea517 | |||
| 5bbfe1be59 | |||
| dd04bd8792 | |||
| 20bc1f41f0 | |||
| 9e838734c0 | |||
| 17aeca5e70 | |||
| 98852d8c22 | |||
| 674d9cd37d | |||
| c35f9c22ae | |||
| e5f861c0dc | |||
| 7a31143ef4 | |||
| 9daa0e4059 | |||
| eaedeb4f8b | |||
| bd2f1d2777 | |||
| 52e43bac2d | |||
| daef503970 | |||
| 4d0ba3cd13 | |||
| bd111a2106 | |||
| 22daade5d2 | |||
| a39d72a59d | |||
| 3a2e523589 | |||
| 8bd27c6ad1 | |||
| 4c20cf67c8 | |||
| 337da3d523 | |||
| 3050803e68 | |||
| beb803fc63 | |||
| b056bcae2c | |||
| 6a2c297640 | |||
| 8b3127eda4 | |||
| b63d51ab1d | |||
| 3b2dfd27d6 | |||
| b8753195df | |||
| e76eb113a5 | |||
| d285e10565 | |||
| 66803f9036 | |||
| d7cff48374 | |||
| d66ed0566b | |||
| fde2b3bf0f | |||
| dcc8270cc6 | |||
| 23b6ca7552 | |||
| 437173e6a4 | |||
| 1274facbed | |||
| 180fc2ca59 | |||
| 187cf8f55e | |||
| dd8868b2a2 | |||
| 921e8ea1a8 | |||
| 54e8782e12 | |||
| 9e690dd304 | |||
| 373b42041b | |||
| 30ead47fb9 | |||
| 2dc7206f17 | |||
| ab7594bd23 | |||
| 710a22aea7 | |||
| 2c7c801efc | |||
| 41ebe058e7 | |||
| 288c71b3e0 | |||
| d7a8afcb31 | |||
| a1d120ee22 | |||
| b58d6d0d82 | |||
| 5ab65391ca | |||
| 2b40d58996 | |||
| 96129388ec | |||
| 6f6058a2d1 | |||
| 063ef91613 | |||
| 5233072099 | |||
| cd063b0e8a | |||
| 719d796e20 | |||
| 9767bf5261 | |||
| a9998bf12d | |||
| 2b7dc899e1 | |||
| cbc3f51d4c | |||
| ff1c8c1bfe | |||
| 6d4222bb1a | |||
| 7692a6f258 | |||
| ed8e6b00c6 | |||
| 85db9570dd | |||
| be174b9cce | |||
| f0099090b4 | |||
| b72bdfcbf0 | |||
| e1f5addddc | |||
| 87d3145317 | |||
| 84fc89cbbe | |||
| fbbddd8365 | |||
| dcfb787563 | |||
| 6822b2db9b | |||
| d89b3772de | |||
| e4a4eb0455 | |||
| 759efa7da3 | |||
| bf1c271784 | |||
| 9754893181 | |||
| 5b05182a1c | |||
| 20528f72df | |||
| 7de08d9f24 | |||
| d047f5e6d2 | |||
| 71071f817c | |||
| ad9af9bb3d | |||
| c7c864b8c0 | |||
| 67d4862f6b | |||
| 6a16327c30 | |||
| 060b1b8f41 | |||
| da2e228293 | |||
| ab7397bf55 | |||
| f79547f781 | |||
| 2152f1c90e | |||
| 503fb4d246 | |||
| 2befefa752 | |||
| 85e64c5076 | |||
| 133308141b |
@@ -1,276 +1,15 @@
|
||||
version: 2.1
|
||||
|
||||
orbs:
|
||||
# Using windows for builds
|
||||
win: circleci/windows@2.4.0
|
||||
# Upload artifacts to s3
|
||||
aws-s3: circleci/aws-s3@2.0.0
|
||||
|
||||
# Define the jobs we want to run for this project
|
||||
jobs:
|
||||
build-ui:
|
||||
build:
|
||||
docker:
|
||||
- image: "circleci/node:16"
|
||||
- image: cimg/base:2023.03
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: "npm install"
|
||||
working_directory: "ui"
|
||||
- run:
|
||||
command: "npm run build"
|
||||
working_directory: "ui"
|
||||
- persist_to_workspace:
|
||||
root: ./
|
||||
paths:
|
||||
- speckle_connector/vue_ui
|
||||
|
||||
build-connector: # Reusable job for basic connectors
|
||||
executor:
|
||||
name: win/default # comes with python 3.7.3
|
||||
shell: cmd.exe
|
||||
parameters:
|
||||
slug:
|
||||
type: string
|
||||
default: ""
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: ./
|
||||
- run:
|
||||
name: Create Innosetup signing cert
|
||||
shell: powershell.exe
|
||||
command: |
|
||||
echo $env:PFX_B64 > "speckle-sharp-ci-tools\SignTool\AEC Systems Ltd.txt"
|
||||
certutil -decode "speckle-sharp-ci-tools\SignTool\AEC Systems Ltd.txt" "speckle-sharp-ci-tools\SignTool\AEC Systems Ltd.pfx"
|
||||
- run:
|
||||
name: Set Environment Variable
|
||||
shell: powershell.exe
|
||||
command: |
|
||||
$tag = if([string]::IsNullOrEmpty($env:CIRCLE_TAG)) { "2.0.999" } else { $env:CIRCLE_TAG }
|
||||
$semver = if($tag.Contains('/')) {$tag.Split("/")[0] } else { $tag }
|
||||
$ver = if($semver.Contains('-')) {$semver.Split("-")[0] } else { $semver }
|
||||
$version = "$($ver).$($env:WORKFLOW_NUM)"
|
||||
python patch_version.py $semver
|
||||
environment:
|
||||
WORKFLOW_NUM: << pipeline.number >>
|
||||
- run:
|
||||
name: Build Installer
|
||||
command: speckle-sharp-ci-tools\InnoSetup\ISCC.exe speckle-sharp-ci-tools\sketchup.iss /Sbyparam=$p
|
||||
shell: cmd.exe #does not work in powershell
|
||||
|
||||
#- run:
|
||||
# name: Patch
|
||||
# shell: powershell.exe
|
||||
# command:
|
||||
# | # If no tag, use 0.0.0.1 and don't make any YML (for testing only!)
|
||||
# $tag = if([string]::IsNullOrEmpty($env:CIRCLE_TAG)) { "0.0.0" } else { $env:CIRCLE_TAG }
|
||||
# $semver = if($tag.Contains('/')) {$tag.Split("/")[1] } else { $tag }
|
||||
# $ver = if($semver.Contains('-')) {$semver.Split("-")[0] } else { $semver }
|
||||
# $channel = if($semver.Contains('-')) {$semver.Split("-")[1] } else { "latest" }
|
||||
# $version = "$($ver).$($env:CIRCLE_BUILD_NUM)"
|
||||
# New-Item -Force "speckle-sharp-ci-tools/Installers/sketchup/$channel.yml" -ItemType File -Value "version: $semver"
|
||||
# echo $version
|
||||
# python patch_version.py $semver
|
||||
# speckle-sharp-ci-tools\InnoSetup\ISCC.exe speckle-sharp-ci-tools\sketchup.iss
|
||||
- persist_to_workspace:
|
||||
root: ./
|
||||
paths:
|
||||
- speckle-sharp-ci-tools/Installers
|
||||
|
||||
build-connector-mac:
|
||||
macos:
|
||||
xcode: 12.5.1
|
||||
parameters:
|
||||
projname:
|
||||
type: string
|
||||
default: ""
|
||||
slug:
|
||||
type: string
|
||||
default: ""
|
||||
installer:
|
||||
type: boolean
|
||||
default: false
|
||||
converter-files:
|
||||
type: string
|
||||
default: ""
|
||||
installername:
|
||||
type: string
|
||||
default: ""
|
||||
build-config:
|
||||
type: string
|
||||
default: Release
|
||||
bundlename:
|
||||
type: string
|
||||
default: ""
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: ./
|
||||
- run:
|
||||
name: Install dotnet
|
||||
command: |
|
||||
curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel Current
|
||||
|
||||
$HOME/.dotnet/dotnet --version
|
||||
$HOME/.dotnet/dotnet --list-runtimes
|
||||
$HOME/.dotnet/dotnet --list-sdks
|
||||
- run:
|
||||
name: Create installer target dir
|
||||
command: |
|
||||
mkdir -p speckle-sharp-ci-tools/Installers/<< parameters.slug >>
|
||||
- run:
|
||||
name: Set Environment Variable
|
||||
command: |
|
||||
TAG=$(if [ "${CIRCLE_TAG}" ]; then echo $CIRCLE_TAG; else echo "2.0.999"; fi;)
|
||||
SEMVER=$(echo "$TAG" | sed -e 's/\/[a-zA-Z-]*//')
|
||||
VER=$(echo "$SEMVER" | sed -e 's/-.*//')
|
||||
VERSION=$(echo $VER.$WORKFLOW_NUM)
|
||||
python3 patch_version.py $SEMVER
|
||||
environment:
|
||||
WORKFLOW_NUM: << pipeline.number >>
|
||||
- run:
|
||||
name: Zip Connector files
|
||||
command: |
|
||||
zip -r << parameters.slug >>-mac.zip "./speckle_connector" "./speckle_connector.rb"
|
||||
# Copy installer files
|
||||
- run:
|
||||
name: Copy files to installer
|
||||
command: |
|
||||
mkdir -p speckle-sharp-ci-tools/Mac/<< parameters.installername >>/.installationFiles/
|
||||
cp << parameters.slug >>-mac.zip speckle-sharp-ci-tools/Mac/<<parameters.installername>>/.installationFiles
|
||||
# Create installer
|
||||
- run:
|
||||
name: Exit if External PR
|
||||
command: if [ "$CIRCLE_PR_REPONAME" ]; then circleci-agent step halt; fi
|
||||
- run:
|
||||
name: Build Mac installer
|
||||
command: ~/.dotnet/dotnet publish speckle-sharp-ci-tools/Mac/<<parameters.installername>>/<<parameters.installername>>.sln -r osx-x64 -c Release
|
||||
- run:
|
||||
name: Zip installer
|
||||
command: |
|
||||
cd speckle-sharp-ci-tools/Mac/<<parameters.installername>>/bin/Release/net6.0/osx-x64/publish/
|
||||
zip -r <<parameters.slug>>.zip ./
|
||||
- store_artifacts:
|
||||
path: speckle-sharp-ci-tools/Mac/<<parameters.installername>>/bin/Release/net6.0/osx-x64/publish/<<parameters.slug>>.zip
|
||||
- run:
|
||||
name: Copy to installer location
|
||||
command: |
|
||||
TAG=$(if [ "${CIRCLE_TAG}" ]; then echo $CIRCLE_TAG; else echo "2.0.999"; fi;)
|
||||
SEMVER=$(echo "$TAG" | sed -e 's/\/[a-zA-Z-]*//')
|
||||
VER=$(echo "$SEMVER" | sed -e 's/-.*//')
|
||||
VERSION=$(echo $VER.$WORKFLOW_NUM)
|
||||
cp speckle-sharp-ci-tools/Mac/<<parameters.installername>>/bin/Release/net6.0/osx-x64/publish/<<parameters.slug>>.zip speckle-sharp-ci-tools/Installers/<< parameters.slug >>/<<parameters.slug>>-$SEMVER.zip
|
||||
environment:
|
||||
WORKFLOW_NUM: << pipeline.number >>
|
||||
- when:
|
||||
condition: << pipeline.git.tag >>
|
||||
steps:
|
||||
- persist_to_workspace:
|
||||
root: ./
|
||||
paths:
|
||||
- speckle-sharp-ci-tools/Installers
|
||||
|
||||
get-ci-tools: # Clones our ci tools and persists them to the workspace
|
||||
docker:
|
||||
- image: cimg/base:2021.01
|
||||
steps:
|
||||
- add_ssh_keys:
|
||||
fingerprints:
|
||||
- "03:2e:ee:4f:14:67:2b:88:32:e8:cc:f0:cb:df:92:29"
|
||||
- run:
|
||||
name: I know Github as a host
|
||||
command: |
|
||||
mkdir ~/.ssh
|
||||
ssh-keyscan github.com >> ~/.ssh/known_hosts
|
||||
- run:
|
||||
name: Clone
|
||||
command: git clone git@github.com:specklesystems/speckle-sharp-ci-tools.git speckle-sharp-ci-tools
|
||||
- persist_to_workspace:
|
||||
root: ./
|
||||
paths:
|
||||
- speckle-sharp-ci-tools
|
||||
- persist_to_workspace:
|
||||
root: ./
|
||||
paths:
|
||||
- speckle-sharp-ci-tools
|
||||
|
||||
deploy-manager2:
|
||||
docker:
|
||||
- image: mcr.microsoft.com/dotnet/sdk:6.0
|
||||
parameters:
|
||||
slug:
|
||||
type: string
|
||||
os:
|
||||
type: string
|
||||
extension:
|
||||
type: string
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: ./
|
||||
- run:
|
||||
name: Install Manager Feed CLI
|
||||
command: dotnet tool install --global Speckle.Manager.Feed
|
||||
- run:
|
||||
name: Upload new version
|
||||
command: |
|
||||
TAG=$(if [ "${CIRCLE_TAG}" ]; then echo $CIRCLE_TAG; else echo "0.0.0"; fi;)
|
||||
SEMVER=$(echo "$TAG" | sed -e 's/\/[a-zA-Z-]*//')
|
||||
/root/.dotnet/tools/Speckle.Manager.Feed deploy -s << parameters.slug >> -v ${SEMVER} -u https://releases.speckle.dev/installers/<< parameters.slug >>/<< parameters.slug >>-${SEMVER}.<< parameters.extension >> -o << parameters.os >> -f speckle-sharp-ci-tools/Installers/<< parameters.slug >>/<< parameters.slug >>-${SEMVER}.<< parameters.extension >>
|
||||
- run: echo "so long and thanks for all the fish"
|
||||
|
||||
# Orchestrate our job run sequence
|
||||
workflows:
|
||||
build-and-deploy:
|
||||
build_and_test:
|
||||
jobs:
|
||||
- get-ci-tools:
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
|
||||
- build-ui:
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
|
||||
- build-connector:
|
||||
slug: sketchup
|
||||
requires:
|
||||
- get-ci-tools
|
||||
- build-ui
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
context: innosetup
|
||||
|
||||
- build-connector-mac:
|
||||
slug: sketchup
|
||||
requires:
|
||||
- get-ci-tools
|
||||
- build-ui
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
installername: SpeckleSketchUpInstall
|
||||
|
||||
- deploy-manager2:
|
||||
context: do-spaces-speckle-releases
|
||||
slug: sketchup
|
||||
os: Win
|
||||
extension: exe
|
||||
requires:
|
||||
- build-connector
|
||||
filters:
|
||||
tags:
|
||||
only: /([0-9]+)\.([0-9]+)\.([0-9]+)(?:-\w+)?$/
|
||||
branches:
|
||||
ignore: /.*/ # For testing only! /ci\/.*/
|
||||
- deploy-manager2:
|
||||
context: do-spaces-speckle-releases
|
||||
slug: sketchup
|
||||
os: OSX
|
||||
extension: zip
|
||||
requires:
|
||||
- build-connector-mac
|
||||
filters:
|
||||
tags:
|
||||
only: /([0-9]+)\.([0-9]+)\.([0-9]+)(?:-\w+)?$/
|
||||
branches:
|
||||
ignore: /.*/ # For testing only! /ci\/.*/
|
||||
- build
|
||||
@@ -0,0 +1,61 @@
|
||||
# This workflow will install Python dependencies, run tests and lint with a single version of Python
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
|
||||
|
||||
name: Build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
workflow_call:
|
||||
outputs:
|
||||
semver:
|
||||
description: "The computed version number for this run"
|
||||
value: ${{ jobs.build.outputs.semver }}
|
||||
file_version:
|
||||
description: "The assembly info version for this run"
|
||||
value: ${{ jobs.build.outputs.file_version }}
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
semver: ${{ steps.set-version.outputs.semver }}
|
||||
file_version: ${{ steps.set-info-version.outputs.file-version }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Python 3.10
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Install GitVersion
|
||||
uses: gittools/actions/gitversion/setup@v3.0.0
|
||||
with:
|
||||
versionSpec: 6.0.5 # github actions doesnt like 6.1.0 onwards https://github.com/GitTools/actions/blob/main/docs/versions.md
|
||||
|
||||
- name: Determine Version
|
||||
id: gitversion
|
||||
uses: gittools/actions/gitversion/execute@v3.0.0
|
||||
|
||||
- name: Set connector version
|
||||
run: |
|
||||
python patch_version.py ${{steps.gitversion.outputs.semVer}}
|
||||
|
||||
- uses: montudor/action-zip@v1
|
||||
with:
|
||||
args: zip -q -r sketchup.zip vendor speckle_connector_3/ speckle_connector_3.rb
|
||||
- name: ⬆️ Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: output-${{steps.gitversion.outputs.semVer}}
|
||||
path: sketchup.zip
|
||||
retention-days: 1
|
||||
if-no-files-found: error
|
||||
compression-level: 0 # no compression
|
||||
- id: set-version
|
||||
name: Set version to output
|
||||
run: echo "semver=${{steps.gitversion.outputs.semVer}}" >> "$GITHUB_OUTPUT" # version will be retrieved from tag?
|
||||
- id: set-info-version
|
||||
name: Set version to output
|
||||
run: echo "file-version=${{steps.gitversion.outputs.AssemblySemVer}}" >> "$GITHUB_OUTPUT" # version will be retrieved from tag?
|
||||
@@ -0,0 +1,36 @@
|
||||
# This workflow will install Python dependencies, run tests and lint with a single version of Python
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
|
||||
|
||||
name: Build and deploy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"] # Continuous delivery on every long-lived branch
|
||||
tags: ["v3.*"] # Manual delivery on every 3.x tag
|
||||
|
||||
jobs:
|
||||
build:
|
||||
uses: ./.github/workflows/build.yml
|
||||
|
||||
deploy-installers:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
env:
|
||||
IS_TAG_BUILD: ${{ github.ref_type == 'tag' }}
|
||||
steps:
|
||||
- name: 🔫 Trigger Build Installers
|
||||
uses: ALEEF02/workflow-dispatch@v3.0.0
|
||||
with:
|
||||
workflow: Build Sketchup
|
||||
repo: specklesystems/connector-installers
|
||||
token: ${{ secrets.CONNECTORS_GH_TOKEN }}
|
||||
inputs: '{ "run_id": "${{ github.run_id }}", "semver": "${{ needs.build.outputs.semver }}", "file_version": "${{ needs.build.outputs.file_version }}", "public_release": ${{ env.IS_TAG_BUILD }} }'
|
||||
ref: main
|
||||
wait-for-completion: true
|
||||
wait-for-completion-interval: 10s
|
||||
wait-for-completion-timeout: 10m
|
||||
display-workflow-run-url: true
|
||||
display-workflow-run-url-interval: 10s
|
||||
- uses: geekyeggo/delete-artifact@v5
|
||||
with:
|
||||
name: output-*
|
||||
@@ -1,38 +0,0 @@
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
||||
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
||||
|
||||
name: Ruby
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
ruby-version: ['2.7']
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Ruby
|
||||
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
||||
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
||||
# uses: ruby/setup-ruby@v1
|
||||
uses: ruby/setup-ruby@0a29871fe2b0200a17a4497bae54fe5df0d973aa # v1.115.3
|
||||
with:
|
||||
ruby-version: ${{ matrix.ruby-version }}
|
||||
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
||||
- name: Run tests
|
||||
run: bundle exec rake
|
||||
@@ -10,8 +10,8 @@
|
||||
settings.json
|
||||
|
||||
# vue app build dist folder
|
||||
speckle_connector/vue_ui
|
||||
speckle_connector/html
|
||||
speckle_connector_3/vue_ui
|
||||
speckle_connector_3/html
|
||||
|
||||
# speckle-sharp-ci-tools
|
||||
/speckle-sharp-ci-tools
|
||||
|
||||
@@ -18,7 +18,7 @@ AllCops:
|
||||
- '_tools/su_attributes/**/*.rb'
|
||||
- '_sqlite3/**/*.rb'
|
||||
- 'ui/**/*'
|
||||
- 'speckle_connector/src/ext/**/*.rb'
|
||||
- 'speckle_connector_3/src/ext/**/*.rb'
|
||||
- 'vendor/bundle/**/*'
|
||||
- 'tests/**/*.rb'
|
||||
SketchUp:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
require_paths:
|
||||
- "C:/Program Files/SketchUp/SketchUp 2021/Tools"
|
||||
- speckle_connector
|
||||
- speckle_connector_3
|
||||
|
||||
require:
|
||||
- sketchup-api-stubs
|
||||
|
||||
@@ -24,6 +24,8 @@ group :development do
|
||||
gem 'rubycritic', '~> 4.3', '>= 4.3.3', require: false
|
||||
# Auto completions for SketchUp API.
|
||||
gem 'sketchup-api-stubs'
|
||||
# Runtime dependency of skippy for Ruby 3.2. Have it!
|
||||
gem 'sorted_set', '~> 1.0'
|
||||
# Aid with common SketchUp extension tasks.
|
||||
gem 'skippy', '~> 0.4.1.a'
|
||||
gem 'skippy', '~> 0.5.2.a'
|
||||
end
|
||||
|
||||
@@ -26,7 +26,7 @@ GEM
|
||||
path_expander (~> 1.0)
|
||||
ruby_parser (~> 3.1, > 3.1.0)
|
||||
sexp_processor (~> 4.8)
|
||||
git (1.18.0)
|
||||
git (1.19.1)
|
||||
addressable (~> 2.8)
|
||||
rchardet (~> 1.8)
|
||||
ice_nine (0.11.2)
|
||||
@@ -51,6 +51,7 @@ GEM
|
||||
public_suffix (5.0.1)
|
||||
rainbow (3.1.1)
|
||||
rake (13.0.6)
|
||||
rbtree (0.4.6)
|
||||
rchardet (1.8.0)
|
||||
reek (6.1.1)
|
||||
kwalify (~> 0.7.0)
|
||||
@@ -89,6 +90,7 @@ GEM
|
||||
simplecov (>= 0.17.0)
|
||||
tty-which (~> 0.4.0)
|
||||
virtus (~> 1.0)
|
||||
set (1.1.0)
|
||||
sexp_processor (4.16.1)
|
||||
simplecov (0.21.2)
|
||||
docile (~> 1.1)
|
||||
@@ -97,11 +99,15 @@ GEM
|
||||
simplecov-html (0.12.3)
|
||||
simplecov_json_formatter (0.1.4)
|
||||
sketchup-api-stubs (0.7.8)
|
||||
skippy (0.4.3.a)
|
||||
skippy (0.5.2.a)
|
||||
git (~> 1.3)
|
||||
naturally (~> 2.1)
|
||||
thor (~> 0.19)
|
||||
thor (0.20.3)
|
||||
sorted_set (~> 1.0)
|
||||
thor (>= 0.19, < 2.0)
|
||||
sorted_set (1.0.3)
|
||||
rbtree
|
||||
set (~> 1.0)
|
||||
thor (1.3.1)
|
||||
thread_safe (0.3.6)
|
||||
tty-which (0.4.2)
|
||||
unicode-display_width (1.8.0)
|
||||
@@ -112,6 +118,7 @@ GEM
|
||||
equalizer (~> 0.0, >= 0.0.9)
|
||||
|
||||
PLATFORMS
|
||||
x64-mingw-ucrt
|
||||
x64-mingw32
|
||||
x64-unknown
|
||||
x86_64-linux
|
||||
@@ -127,7 +134,8 @@ DEPENDENCIES
|
||||
rubocop-sketchup
|
||||
rubycritic (~> 4.3, >= 4.3.3)
|
||||
sketchup-api-stubs
|
||||
skippy (~> 0.4.1.a)
|
||||
skippy (~> 0.5.2.a)
|
||||
sorted_set (~> 1.0)
|
||||
|
||||
BUNDLED WITH
|
||||
2.3.25
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
workflow: GitFlow/v1
|
||||
next-version: 3.0.0
|
||||
mode: ManualDeployment
|
||||
branches:
|
||||
main:
|
||||
label: rc
|
||||
develop:
|
||||
regex: ^dui3/alpha$
|
||||
label: beta
|
||||
unknown:
|
||||
increment: None
|
||||
@@ -49,9 +49,9 @@ This repo is split into three parts:
|
||||
### 1. **Speckle Connector extension**
|
||||
|
||||
Includes the `ruby` source files to run extension on SketchUp environment. SketchUp Extensions are composed of
|
||||
a **.rb** file as entry and **folder** that .rb file refers to. In our case entry file is `speckle_connector.rb`
|
||||
a **.rb** file as entry and **folder** that .rb file refers to. In our case entry file is `speckle_connector_3.rb`
|
||||
that responsible to register Speckle Connector extension to SketchUp and also it shows address to where extension
|
||||
will start to read extension. Source folder is `speckle_connector`.
|
||||
will start to read extension. Source folder is `speckle_connector_3`.
|
||||
|
||||
### 2. **User Interface**
|
||||
|
||||
@@ -64,7 +64,7 @@ This repo is split into three parts:
|
||||
we use extensions as native part of the source `ruby` code.
|
||||
|
||||
After building `sqlite3.sln` file, compiled `sqlite3.so` (for Windows) and `sqlite3.bundle` (for OSX) dynamic library files are created
|
||||
by solution to place them into source code into `speckle_connector/src/ext`. Building this project should be only
|
||||
by solution to place them into source code into `speckle_connector_3/src/ext`. Building this project should be only
|
||||
happen when SketchUp starts to support newer Ruby versions (currently it is `2.7`).
|
||||
|
||||
## Contribution Guide
|
||||
@@ -115,9 +115,23 @@ You can now open up the repo in VS Code or you can use JetBrains' tools RubyMine
|
||||
|
||||
If you will use VS Code, make sure you've installed the Ruby extension for VS Code.
|
||||
|
||||
#### RubyMine
|
||||
|
||||
To debug:
|
||||
- Add configuration as **'Ruby remote debug'**
|
||||
- Remote host: localhost
|
||||
- Remote port: 7000
|
||||
- Remote root folder: <repo_path>
|
||||
- Local port: 26162
|
||||
- Local root folder: <repo_path>
|
||||
- Run below script
|
||||
|
||||
bundle exec skippy sketchup:debug 2024
|
||||
- When sketchup opened, click Debug button on RubyMine
|
||||
|
||||
### Loading the Speckle Connector Plugin
|
||||
|
||||
1. Find already prepared `speckle_connector_loader.rb` file on the `_tools`
|
||||
1. Find already prepared `speckle_connector_3_loader.rb` file on the `_tools`
|
||||
folder.
|
||||
2. Copy this Ruby file into your SketchUp Plugins directory. You will likely find this at:
|
||||
`C:\Users\{YOU}\AppData\Roaming\SketchUp\SketchUp 20XX\SketchUp\Plugins`
|
||||
|
||||
@@ -32,12 +32,12 @@ end
|
||||
|
||||
# Glob pattern to match source files. Defaults to FileList['.'].
|
||||
ruby_critic_paths = FileList[
|
||||
'speckle_connector/**/*.rb',
|
||||
'speckle_connector.rb',
|
||||
'speckle_connector_3/**/*.rb',
|
||||
'speckle_connector_3.rb',
|
||||
'tests/**/*.rb'] -
|
||||
FileList[
|
||||
'_tools/**/*.rb',
|
||||
'speckle_connector/src/ext/**/*.rb',
|
||||
'speckle_connector_3/src/ext/**/*.rb',
|
||||
]
|
||||
|
||||
# for local
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# This is for automated pre-debugger configuration.
|
||||
# We run skippy first, then activate debugger.
|
||||
# The purpose of this file to wait till skp is live
|
||||
|
||||
# To establish a configuration
|
||||
# 1. Create 'Run External Tool' before lunch step
|
||||
# 2. Program -> C:\Ruby32-x64\bin\ruby.exe or whatever
|
||||
# 3. Arguments -> C:\Users\KORAL\Documents\Git\Speckle\speckle-sketchup\_tools\debugger\bundle_exec_2024.rb or whatever
|
||||
# 4. Working directory -> C:\Users\KORAL\Documents\Git\Speckle\speckle-sketchup or whatever
|
||||
|
||||
# Add a delay of 10 seconds, it is arbitrary, do not hesitate to change for what works best for you
|
||||
sleep(10)
|
||||
|
||||
# Execute the original command
|
||||
exec('bundle exec skippy sketchup:debug 2024')
|
||||
@@ -24,7 +24,7 @@ module JF_RubyToolbar
|
||||
def self.load_toolbar
|
||||
@last_dir = "#{$LOAD_PATH[0]}/"
|
||||
@last_dir = @last_dir.gsub('/', '\\\\\\\\')
|
||||
@last_dir = File.join($JF_RUBYTOOLBAR, 'speckle_connector')
|
||||
@last_dir = File.join($JF_RUBYTOOLBAR, 'speckle_connector_3')
|
||||
curdir = File.dirname __FILE__
|
||||
|
||||
# create toolbar
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
# Create a link to Plugins folder with this command
|
||||
|
||||
# rubocop:disable Layout/LineLength
|
||||
# New-Item -ItemType SymbolicLink -Path '~\AppData\Roaming\SketchUp\SketchUp 2022\SketchUp\Plugins\speckle_connector_loader.rb' -Target ~\Git\Speckle\speckle-sketchup\_tools\speckle_connector_loader.rb
|
||||
# New-Item -ItemType SymbolicLink -Path '~\AppData\Roaming\SketchUp\SketchUp 2022\SketchUp\Plugins\speckle_connector_3_loader.rb' -Target ~\Git\Speckle\speckle-sketchup\_tools\speckle_connector_3_loader.rb
|
||||
# rubocop:enable Layout/LineLength
|
||||
|
||||
SKETCHUP_CONSOLE.show # if you want to show Ruby console on startup
|
||||
@@ -32,7 +32,7 @@ $LOAD_PATH << File.join(speckle_path, '_tools')
|
||||
$JF_RUBYTOOLBAR = speckle_path
|
||||
# rubocop:enable Style/GlobalVars
|
||||
|
||||
files = %w[speckle_connector jf_RubyPanel su_attributes]
|
||||
files = %w[speckle_connector_3 jf_RubyPanel su_attributes]
|
||||
|
||||
files.each do |ruby_file|
|
||||
puts "Loading #{ruby_file}"
|
||||
@@ -4,7 +4,7 @@ import sys
|
||||
|
||||
def patch_connector(tag):
|
||||
"""Patches the connector version within the connector file"""
|
||||
rb_file = "speckle_connector.rb"
|
||||
rb_file = "speckle_connector_3.rb"
|
||||
|
||||
with open(rb_file, "r") as file:
|
||||
lines = file.readlines()
|
||||
@@ -15,6 +15,12 @@ def patch_connector(tag):
|
||||
print(f"Patched connector version number in {rb_file}")
|
||||
break
|
||||
|
||||
for (index, line) in enumerate(lines):
|
||||
if 'DEV_MODE = ' in line:
|
||||
lines[index] = f' DEV_MODE = false\n'
|
||||
print(f"Patched dev mode to false in {rb_file}")
|
||||
break
|
||||
|
||||
with open(rb_file, "w") as file:
|
||||
file.writelines(lines)
|
||||
|
||||
@@ -45,7 +51,7 @@ def main():
|
||||
|
||||
print(f"Patching version: {tag}")
|
||||
patch_connector(tag)
|
||||
patch_installer(tag)
|
||||
# patch_installer(tag)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
|
Before Width: | Height: | Size: 2.4 KiB |
@@ -1,31 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'JSON'
|
||||
require_relative '../ext/sqlite3'
|
||||
require_relative '../constants/path_constants'
|
||||
|
||||
module SpeckleConnector
|
||||
# Accounts to communicate with models on user's account.
|
||||
module Accounts
|
||||
def self.load_accounts
|
||||
db_path = SPECKLE_ACCOUNTS_DB_PATH
|
||||
unless File.exist?(db_path)
|
||||
raise(
|
||||
IOError,
|
||||
"No Accounts db found. Please read the guide for different options for adding your account:\n
|
||||
https://speckle.guide/user/manager.html#adding-accounts"
|
||||
)
|
||||
end
|
||||
|
||||
db = Sqlite3::Database.new(db_path)
|
||||
rows = db.exec('SELECT * FROM objects')
|
||||
db.close
|
||||
rows.map { |row| JSON.parse(row[1]) }
|
||||
end
|
||||
|
||||
def self.default_account
|
||||
accounts = load_accounts
|
||||
accounts.select { |acc| acc['isDefault'] }[0] || accounts[0]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,84 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'event_action'
|
||||
require_relative '../../sketchup_model/utils/face_utils'
|
||||
require_relative '../../constants/dict_constants'
|
||||
|
||||
module SpeckleConnector
|
||||
module Actions
|
||||
module Events
|
||||
# Event actions related to entities.
|
||||
class EntitiesEventAction < EventAction
|
||||
# Event action when element added.
|
||||
class OnElementAdded
|
||||
# @param state [States::State] the current state of the SpeckleConnector Application
|
||||
def self.update_state(state, event_data)
|
||||
modified_entities = event_data.to_a.collect { |e| e[1] }
|
||||
# do not copy speckle base object specific attributes, because they are entity specific
|
||||
modified_entities.each { |entity| entity.delete_attribute(SPECKLE_BASE_OBJECT) }
|
||||
state
|
||||
end
|
||||
end
|
||||
|
||||
# Event action when element modified.
|
||||
class OnElementModified
|
||||
# @param state [States::State] the current state of the SpeckleConnector Application
|
||||
def self.update_state(state, event_data)
|
||||
speckle_state = state.speckle_state
|
||||
modified_entity = event_data[0][1]
|
||||
if modified_entity.is_a?(Sketchup::Face)
|
||||
path = state.sketchup_state.sketchup_model.active_path
|
||||
modified_faces = SketchupModel::Utils::FaceUtils.near_faces(modified_entity.edges)
|
||||
path_objects = path.nil? ? [] : path + path.collect(&:definition)
|
||||
parent_ids = path_objects.collect(&:persistent_id)
|
||||
ids_to_invalidate = modified_faces.collect(&:persistent_id) + parent_ids
|
||||
entities_to_invalidate = speckle_entities_to_invalidate(speckle_state, ids_to_invalidate)
|
||||
new_speckle_state = invalidate_speckle_entities(speckle_state, entities_to_invalidate)
|
||||
# This is the place we can send information to UI for diffing check
|
||||
diffing = state.user_state.preferences[:user][:diffing]
|
||||
new_speckle_state = new_speckle_state.with_invalid_streams_queue if diffing
|
||||
return state.with_speckle_state(new_speckle_state)
|
||||
end
|
||||
|
||||
state
|
||||
end
|
||||
|
||||
# @param speckle_state [States::SpeckleState] the current state of the Speckle
|
||||
def self.speckle_entities_to_invalidate(speckle_state, ids)
|
||||
speckle_state.speckle_entities.to_h.select { |id, _| ids.include?(id) }
|
||||
end
|
||||
|
||||
# @param speckle_state [States::SpeckleState] the current state of the Speckle
|
||||
def self.invalidate_speckle_entities(speckle_state, entities_to_invalidate)
|
||||
speckle_entities = speckle_state.speckle_entities
|
||||
entities_to_invalidate.each do |id, speckle_entity|
|
||||
edited_speckle_entity = speckle_entity.with_invalid
|
||||
speckle_entities = speckle_entities.put(id, edited_speckle_entity)
|
||||
end
|
||||
speckle_state.with_speckle_entities(speckle_entities)
|
||||
end
|
||||
end
|
||||
|
||||
# Event action when element removed.
|
||||
class OnElementRemoved
|
||||
# @param state [States::State] the current state of the SpeckleConnector Application
|
||||
def self.update_state(state, _event_data)
|
||||
# TODO: Do state updates when element removed
|
||||
state
|
||||
end
|
||||
end
|
||||
|
||||
# Handlers that are used to handle specific events
|
||||
ACTIONS = {
|
||||
onElementRemoved: OnElementRemoved,
|
||||
onElementAdded: OnElementAdded,
|
||||
onElementModified: OnElementModified
|
||||
}.freeze
|
||||
|
||||
def self.actions
|
||||
ACTIONS
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,45 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'action'
|
||||
require_relative '../accounts/accounts'
|
||||
require_relative '../actions/create_stream'
|
||||
require_relative '../actions/queue_send'
|
||||
require_relative '../convertors/to_speckle'
|
||||
|
||||
module SpeckleConnector
|
||||
module Actions
|
||||
# Sends to speckle.
|
||||
class OneClickSend < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state)
|
||||
puts 'send to speckle'
|
||||
default_account = Accounts.default_account
|
||||
if default_account.nil?
|
||||
puts 'No local account found. Please refer to speckle.guide for more information.'
|
||||
return state
|
||||
end
|
||||
sketchup_model = state.sketchup_state.sketchup_model
|
||||
to_convert = sketchup_model.selection.count > 0 ? sketchup_model.selection : sketchup_model.entities
|
||||
first_saved_stream = first_saved_stream(sketchup_model)
|
||||
action = if first_saved_stream.nil?
|
||||
Actions::CreateStream.new
|
||||
else
|
||||
Actions::QueueSend.new(first_saved_stream, convert_to_speckle(sketchup_model, to_convert))
|
||||
end
|
||||
|
||||
action.update_state(state)
|
||||
end
|
||||
|
||||
def self.first_saved_stream(model)
|
||||
(saved_streams = model.attribute_dictionary('speckle', true)['streams']) or []
|
||||
saved_streams.nil? || saved_streams.empty? ? nil : saved_streams[0]
|
||||
end
|
||||
|
||||
def self.convert_to_speckle(sketchup_model, to_convert)
|
||||
converter = Converters::ToSpeckle.new(sketchup_model)
|
||||
to_convert.map { |entity| converter.convert(entity) }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,42 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module SpeckleConnector
|
||||
module Commands
|
||||
# Base command schema to wrap common operations for all commands.
|
||||
class Command
|
||||
# @return [App::SpeckleConnectorApp] the main app object
|
||||
attr_reader :app
|
||||
|
||||
# @return [Ui::View] view object holds dialog and it's state
|
||||
attr_reader :view
|
||||
|
||||
# @@param app [App::SpeckleConnectorApp] the main app object
|
||||
def initialize(app)
|
||||
@app = app
|
||||
@view = app.ui_controller.user_interfaces[Ui::SPECKLE_UI_ID]
|
||||
end
|
||||
|
||||
def run(*parameters)
|
||||
# Run here common operations that same for each command.
|
||||
with_observers_disabled do
|
||||
_run(*parameters)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def with_observers_disabled(&block)
|
||||
observer_handler = @app.observer_handler
|
||||
if observer_handler
|
||||
observer_handler.with_observers_disabled(&block)
|
||||
else
|
||||
block.call
|
||||
end
|
||||
end
|
||||
|
||||
def _run(*_parameters)
|
||||
raise NotImplementedError, 'Implement in subclass'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,15 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'command'
|
||||
|
||||
module SpeckleConnector
|
||||
module Commands
|
||||
# Run this command when the UI is ready to get data
|
||||
class DialogReady < Command
|
||||
# Update the selected user interface
|
||||
def _run(_data)
|
||||
view.update_view(app.state)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,58 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'menu_command_handler'
|
||||
require_relative 'action_command'
|
||||
require_relative 'initialize_speckle'
|
||||
require_relative '../actions/one_click_send'
|
||||
|
||||
module SpeckleConnector
|
||||
module Commands
|
||||
# Speckle menu commands that adds them to Sketchup menu and toolbar.
|
||||
class SpeckleMenuCommands
|
||||
CMD_INITIALIZE_SPECKLE = :initialize_speckle
|
||||
CMD_SEND_TO_SPECKLE = :send_to_speckle
|
||||
CMD_RECEIVE_FROM_SPECKLE = :receive_from_speckle
|
||||
|
||||
# Add initial set of commands to Speckle application object and to Sketchup menu and toolbar
|
||||
# @param app [App::SpeckleConnectorApp] the application object
|
||||
def self.add_initial_commands!(app)
|
||||
commands = app.menu_commands
|
||||
ui_controller = app.ui_controller
|
||||
sketchup_ui = ui_controller.sketchup_ui
|
||||
speckle_menu = sketchup_ui.speckle_menu
|
||||
speckle_toolbar = sketchup_ui.speckle_toolbar
|
||||
|
||||
commands[CMD_INITIALIZE_SPECKLE] = initialize_speckle_command(app)
|
||||
commands.add_to_menu!(CMD_INITIALIZE_SPECKLE, speckle_menu)
|
||||
commands.add_to_toolbar!(CMD_INITIALIZE_SPECKLE, speckle_toolbar)
|
||||
|
||||
# commands[CMD_SEND_TO_SPECKLE] = send_command(app)
|
||||
# commands.add_to_menu!(CMD_SEND_TO_SPECKLE, speckle_menu)
|
||||
# commands.add_to_toolbar!(CMD_SEND_TO_SPECKLE, speckle_toolbar)
|
||||
end
|
||||
|
||||
def self.initialize_speckle_command(app)
|
||||
cmd = MenuCommandHandler.sketchup_command(
|
||||
InitializeSpeckle.new(app), 'Initialize Speckle'
|
||||
)
|
||||
cmd.tooltip = 'Launch Connector'
|
||||
cmd.status_bar_text = 'Opens the Speckle Connector window'
|
||||
cmd.small_icon = '../../img/s2logo.png'
|
||||
cmd.large_icon = '../../img/s2logo.png'
|
||||
cmd
|
||||
end
|
||||
|
||||
def self.send_command(app)
|
||||
cmd = MenuCommandHandler.sketchup_command(
|
||||
ActionCommand.new(app, Actions::OneClickSend), 'Send to Speckle'
|
||||
)
|
||||
cmd.tooltip = 'Send to Speckle'
|
||||
cmd.status_bar_text = 'Send to Speckle'
|
||||
cmd.small_icon = '../../img/Sender.png'
|
||||
cmd.large_icon = '../../img/Sender.png'
|
||||
cmd.set_validation_proc { MenuCommandHandler.speckle_started(app) }
|
||||
cmd
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,8 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module SpeckleConnector
|
||||
APP_OBSERVER = 'SpeckleConnector::Observers::AppObserver'
|
||||
ENTITIES_OBSERVER = 'SpeckleConnector::Observers::EntitiesObserver'
|
||||
MODEL_OBSERVER = 'SpeckleConnector::Observers::ModelObserver'
|
||||
SELECTION_OBSERVER = 'SpeckleConnector::Observers::SelectionObserver'
|
||||
end
|
||||
@@ -1,126 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'converter'
|
||||
require_relative 'base_object_serializer'
|
||||
require_relative '../speckle_objects/base'
|
||||
require_relative '../speckle_objects/geometry/line'
|
||||
require_relative '../speckle_objects/geometry/length'
|
||||
require_relative '../speckle_objects/geometry/mesh'
|
||||
require_relative '../speckle_objects/other/block_instance'
|
||||
require_relative '../speckle_objects/other/block_definition'
|
||||
require_relative '../speckle_objects/other/rendering_options'
|
||||
require_relative '../speckle_objects/built_elements/view3d'
|
||||
require_relative '../speckle_objects/built_elements/revit/direct_shape'
|
||||
require_relative '../speckle_objects/relations/layers'
|
||||
require_relative '../speckle_objects/speckle/core/models/model_collection'
|
||||
require_relative '../constants/path_constants'
|
||||
require_relative '../sketchup_model/reader/speckle_entities_reader'
|
||||
require_relative '../sketchup_model/reader/mapper_reader'
|
||||
require_relative '../sketchup_model/query/entity'
|
||||
|
||||
module SpeckleConnector
|
||||
module Converters
|
||||
# Converts sketchup entities to speckle objects.
|
||||
class ToSpeckle < Converter
|
||||
MODEL_COLLECTION = SpeckleObjects::Speckle::Core::Models::ModelCollection
|
||||
DIRECT_SHAPE = SpeckleObjects::BuiltElements::Revit::DirectShape
|
||||
SPECKLE_ENTITIES_READER = SketchupModel::Reader::SpeckleEntitiesReader
|
||||
VIEW3D = SpeckleObjects::BuiltElements::View3d
|
||||
|
||||
# Convert selected objects by putting them into related array that grouped by layer.
|
||||
# @return [Hash{Symbol=>Array}] layers -which only have objects- to hold it's objects under the base object.
|
||||
def convert_selection_to_base(preferences)
|
||||
convert = method(:convert)
|
||||
new_speckle_state, model_collection = MODEL_COLLECTION.from_sketchup_model(sketchup_model, speckle_state,
|
||||
@units, preferences, &convert)
|
||||
|
||||
return new_speckle_state, model_collection
|
||||
end
|
||||
|
||||
# Serialized and traversed information to send batches.
|
||||
# @param base_and_entity [SpeckleObjects::Base] base object to serialize.
|
||||
# @return [String, Integer, Array<Object>] base id, total_children_count of base and batches
|
||||
def serialize(base_and_entity, speckle_state, preferences)
|
||||
serializer = SpeckleConnector::Converters::BaseObjectSerializer.new(speckle_state, stream_id, preferences)
|
||||
t = Time.now.to_f
|
||||
id = serializer.serialize(base_and_entity)
|
||||
batches = serializer.batch_objects
|
||||
# write_to_speckle_folder(id, batches)
|
||||
puts "Generating traversed object elapsed #{Time.now.to_f - t} s"
|
||||
base_total_children_count = serializer.total_children_count(id)
|
||||
return id, base_total_children_count, batches, serializer.speckle_state
|
||||
end
|
||||
|
||||
def write_to_speckle_folder(id, batches)
|
||||
folder_path = "#{HOME_PATH}/Speckle"
|
||||
file_path = "#{folder_path}/#{id}.json"
|
||||
FileUtils.mkdir_p(folder_path) unless File.exist?(folder_path)
|
||||
File.write(file_path, batches.first)
|
||||
end
|
||||
|
||||
# @param entity [Sketchup::Entity] sketchup entity to convert Speckle.
|
||||
# @param speckle_state [States::SpeckleState] the current speckle state of the {States::State}
|
||||
# @param parent [Symbol, String] parent of the Sketchup Entity to be converted.
|
||||
def convert(entity, preferences, speckle_state, parent = :base)
|
||||
convert = method(:convert)
|
||||
|
||||
unless SketchupModel::Reader::MapperReader.mapped_with_schema?(entity)
|
||||
return from_native_to_speckle(entity, preferences, speckle_state, parent, &convert)
|
||||
end
|
||||
|
||||
return speckle_state, nil
|
||||
end
|
||||
|
||||
def from_mapped_to_speckle(entity, path, preferences)
|
||||
direct_shape = SpeckleObjects::BuiltElements::Revit::DirectShape
|
||||
.from_entity(speckle_state, entity, path, @units, preferences)
|
||||
return [direct_shape, [entity]]
|
||||
end
|
||||
|
||||
# rubocop:disable Metrics/MethodLength
|
||||
def from_native_to_speckle(entity, preferences, speckle_state, parent, &convert)
|
||||
if entity.is_a?(Sketchup::Edge)
|
||||
line = SpeckleObjects::Geometry::Line.from_edge(entity, @units, preferences[:model]).to_h
|
||||
return speckle_state, [line, [entity]]
|
||||
end
|
||||
|
||||
if entity.is_a?(Sketchup::Face)
|
||||
mesh = SpeckleObjects::Geometry::Mesh.from_face(speckle_state: speckle_state, face: entity, units: @units,
|
||||
model_preferences: preferences[:model])
|
||||
return speckle_state, [mesh, [entity]]
|
||||
end
|
||||
|
||||
if entity.is_a?(Sketchup::Group)
|
||||
new_speckle_state, block_instance = SpeckleObjects::Other::BlockInstance.from_group(
|
||||
entity, @units, preferences, speckle_state, &convert
|
||||
)
|
||||
speckle_state = new_speckle_state
|
||||
return speckle_state, [block_instance, [entity]]
|
||||
end
|
||||
|
||||
if entity.is_a?(Sketchup::ComponentInstance)
|
||||
new_speckle_state, block_instance = SpeckleObjects::Other::BlockInstance.from_component_instance(
|
||||
entity, @units, preferences, speckle_state, &convert
|
||||
)
|
||||
speckle_state = new_speckle_state
|
||||
return speckle_state, [block_instance, [entity]]
|
||||
end
|
||||
|
||||
if entity.is_a?(Sketchup::ComponentDefinition)
|
||||
# Local caching
|
||||
return speckle_state, [definitions[entity.guid], [entity]] if definitions.key?(entity.guid)
|
||||
|
||||
new_speckle_state, block_definition = SpeckleObjects::Other::BlockDefinition.from_definition(
|
||||
entity, @units, preferences, speckle_state, parent, &convert
|
||||
)
|
||||
definitions[entity.guid] = block_definition
|
||||
speckle_state = new_speckle_state
|
||||
return speckle_state, [block_definition, [entity]]
|
||||
end
|
||||
|
||||
return speckle_state, nil
|
||||
end
|
||||
# rubocop:enable Metrics/MethodLength
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,61 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../speckle_objects/built_elements/revit/revit_floor'
|
||||
require_relative '../speckle_objects/built_elements/revit/revit_wall'
|
||||
require_relative '../speckle_objects/built_elements/default_floor'
|
||||
require_relative '../speckle_objects/built_elements/default_wall'
|
||||
require_relative '../sketchup_model/query/entity'
|
||||
require_relative '../sketchup_model/reader/mapper_reader'
|
||||
require_relative '../sketchup_model/dictionary/speckle_schema_dictionary_handler'
|
||||
|
||||
module SpeckleConnector
|
||||
# Mapper is a tool to convert SketchUp entities to other applications' native objects.
|
||||
module Mapper
|
||||
# Collects mapped entities on selection as flat list.
|
||||
def self.mapped_entities_on_selection(sketchup_model)
|
||||
flat_selection_with_path = SketchupModel::Query::Entity.flat_entities_with_path(
|
||||
sketchup_model.selection,
|
||||
[Sketchup::Face, Sketchup::ComponentInstance, Sketchup::Group], [sketchup_model]
|
||||
)
|
||||
mapped_selection = []
|
||||
flat_selection_with_path.each do |entities|
|
||||
entity = entities[0]
|
||||
is_entity_mapped = SketchupModel::Reader::MapperReader.mapped_with_schema?(entity)
|
||||
if entity.respond_to?(:definition)
|
||||
is_definition_mapped = SketchupModel::Reader::MapperReader.mapped_with_schema?(entity.definition)
|
||||
mapped_selection.append(entities) if is_entity_mapped || is_definition_mapped
|
||||
next
|
||||
end
|
||||
mapped_selection.append(entities) if is_entity_mapped
|
||||
end
|
||||
mapped_selection
|
||||
end
|
||||
|
||||
def self.to_speckle(speckle_state, entity, units, global_transformation: nil)
|
||||
speckle_schema = SketchupModel::Dictionary::SpeckleSchemaDictionaryHandler.speckle_schema_to_speckle(entity)
|
||||
return speckle_schema if speckle_schema.nil?
|
||||
|
||||
if speckle_schema['method'] == 'Default Floor'
|
||||
return SpeckleObjects::BuiltElements::DefaultFloor
|
||||
.to_speckle_schema(entity, units, global_transformation: global_transformation)
|
||||
end
|
||||
|
||||
if speckle_schema['method'] == 'Floor'
|
||||
return SpeckleObjects::BuiltElements::RevitFloor
|
||||
.to_speckle_schema(speckle_state, entity, units, global_transformation: global_transformation)
|
||||
end
|
||||
|
||||
if speckle_schema['method'] == 'Default Wall'
|
||||
return SpeckleObjects::BuiltElements::DefaultWall
|
||||
.to_speckle_schema(entity, units, global_transformation: global_transformation)
|
||||
end
|
||||
|
||||
if speckle_schema['method'] == 'Wall'
|
||||
return SpeckleObjects::BuiltElements::RevitWall
|
||||
.to_speckle_schema(speckle_state, entity, units, global_transformation: global_transformation)
|
||||
end
|
||||
|
||||
return speckle_schema
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,47 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../../constants/dict_constants'
|
||||
|
||||
module SpeckleConnector
|
||||
# Operations related to {SketchupModel}.
|
||||
module SketchupModel
|
||||
# Definitions to store for entities.
|
||||
class Definitions
|
||||
def self.from_sketchup_model(model)
|
||||
definitions = model.definitions
|
||||
definitions = definitions.select do |definition|
|
||||
!definition.attribute_dictionaries.nil? &&
|
||||
definition.attribute_dictionaries.any? { |dict| dict.name == SPECKLE_BASE_OBJECT }
|
||||
end
|
||||
Definitions.new(definitions)
|
||||
end
|
||||
|
||||
def add_definition(definition)
|
||||
old_definition = @definitions_by_guid[definition.guid]
|
||||
return self if definition == old_definition
|
||||
|
||||
new_definitions = @definitions.append(definition)
|
||||
Definitions.new(new_definitions)
|
||||
end
|
||||
|
||||
def initialize(definitions = [])
|
||||
@definitions = definitions
|
||||
@definitions_by_name = definitions.collect do |definition|
|
||||
[definition.name, definition]
|
||||
end.to_h.freeze
|
||||
@definitions_by_guid = definitions.collect do |definition|
|
||||
[definition.guid, definition]
|
||||
end.to_h.freeze
|
||||
freeze
|
||||
end
|
||||
|
||||
def by_guid(guid)
|
||||
@definitions_by_guid[guid]
|
||||
end
|
||||
|
||||
def by_name(name)
|
||||
@definitions_by_name[name]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,55 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../../constants/mat_constants'
|
||||
|
||||
module SpeckleConnector
|
||||
# Operations related to {SketchupModel}.
|
||||
module SketchupModel
|
||||
# Materials to store for entities.
|
||||
class Materials
|
||||
def self.from_sketchup_model(model)
|
||||
materials = model.materials
|
||||
materials = materials.select do |material|
|
||||
!material.attribute_dictionaries.nil? &&
|
||||
material.attribute_dictionaries.any? { |dict| dict.name == MAT_DICTIONARY }
|
||||
end
|
||||
mat_hash = materials.collect { |material| [material.get_attribute(MAT_DICTIONARY, MAT_ID), material] }.to_h
|
||||
Materials.new(mat_hash)
|
||||
end
|
||||
|
||||
def initialize(material_hash = {})
|
||||
@materials_by_id = material_hash.freeze
|
||||
@id_by_materials = material_hash.collect { |id, material| [material, id] }.to_h.freeze
|
||||
freeze
|
||||
end
|
||||
|
||||
def add_material(id, material)
|
||||
old_material = @materials_by_id[id.to_sym]
|
||||
return self if material == old_material
|
||||
|
||||
new_material_hash = @materials_by_id.merge({ id.to_sym => material })
|
||||
Materials.new(new_material_hash)
|
||||
end
|
||||
|
||||
def by_id(id)
|
||||
@materials_by_id[id.to_sym]
|
||||
end
|
||||
|
||||
def material_id(material)
|
||||
@id_by_materials[material]
|
||||
end
|
||||
|
||||
def add_speckle_material
|
||||
@materials_by_id[MAT_ADD]
|
||||
end
|
||||
|
||||
def edit_speckle_material
|
||||
@materials_by_id[MAT_EDIT]
|
||||
end
|
||||
|
||||
def remove_speckle_material
|
||||
@materials_by_id[MAT_REMOVE]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,44 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module SpeckleConnector
|
||||
module SketchupModel
|
||||
# Query operations in sketchup model.
|
||||
module Query
|
||||
# Queries for layer and it's parents.
|
||||
class Layer
|
||||
class << self
|
||||
# @param layer [Sketchup::Layer] layer to get folder path of the layer
|
||||
# @return [Array<Sketchup::Folder>] path of the layer
|
||||
def path(layer)
|
||||
parent_folders = []
|
||||
folder = layer.folder
|
||||
until folder.nil?
|
||||
parent_folders.append(folder)
|
||||
folder = folder.folder
|
||||
end
|
||||
parent_folders.reverse
|
||||
end
|
||||
|
||||
# @param entity [Sketchup::Entity] entity to find path.
|
||||
def entity_path(entity, separation = '::')
|
||||
path = path(entity.layer)
|
||||
full_path = path.append(entity.layer)
|
||||
full_path_string = ''
|
||||
full_path.each_with_index do |layer, i|
|
||||
full_path_string += layer.display_name
|
||||
full_path_string += separation unless i == full_path.length - 1
|
||||
end
|
||||
full_path_string
|
||||
end
|
||||
|
||||
# @param string_layer_path [String] string layer path to split.
|
||||
def entity_layer_from_path(string_layer_path, separation = '::')
|
||||
return string_layer_path if string_layer_path.nil?
|
||||
|
||||
string_layer_path.split(separation).last
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,110 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'collection'
|
||||
require_relative 'layer_collection'
|
||||
require_relative '../../../built_elements/view3d'
|
||||
require_relative '../../../built_elements/revit/direct_shape'
|
||||
require_relative '../../../../mapper/mapper'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleObjects
|
||||
module Speckle
|
||||
module Core
|
||||
module Models
|
||||
# ModelCollection object that collect other speckle objects under it's elements.
|
||||
class ModelCollection < Collection
|
||||
DIRECT_SHAPE = SpeckleObjects::BuiltElements::Revit::DirectShape
|
||||
QUERY = SketchupModel::Query
|
||||
VIEW3D = SpeckleObjects::BuiltElements::View3d
|
||||
SPECKLE_SCHEMA_DICTIONARY_HANDLER = SketchupModel::Dictionary::SpeckleSchemaDictionaryHandler
|
||||
def initialize(name:, active_layer:, elements: [], application_id: nil)
|
||||
super(
|
||||
name: name,
|
||||
collection_type: 'sketchup model',
|
||||
elements: elements,
|
||||
application_id: application_id
|
||||
)
|
||||
self[:active_layer] = active_layer
|
||||
end
|
||||
|
||||
def self.from_sketchup_model(sketchup_model, speckle_state, units, preferences, &convert)
|
||||
model_collection = ModelCollection.new(
|
||||
name: 'Sketchup Model', active_layer: sketchup_model.active_layer.display_name,
|
||||
application_id: sketchup_model.guid
|
||||
)
|
||||
|
||||
# Direct shapes will pass directly to elements which are already flattened with all children
|
||||
model_collection[:elements] += collect_mapped_entities(speckle_state, sketchup_model, units,
|
||||
preferences, &convert)
|
||||
|
||||
# Views will pass directly to elements since they don't have any relation with layers and geometries.
|
||||
model_collection[:elements] += VIEW3D.from_model(sketchup_model, units) if sketchup_model.pages.any?
|
||||
|
||||
# Add layer collections.
|
||||
model_collection[:elements] += LayerCollection.create_layer_collections(sketchup_model)
|
||||
|
||||
sketchup_model.selection.each do |entity|
|
||||
layer_collection = LayerCollection.get_or_create_layer_collection(entity.layer, model_collection)
|
||||
new_speckle_state, converted_object_with_entity = convert.call(entity, preferences, speckle_state)
|
||||
speckle_state = new_speckle_state
|
||||
unless converted_object_with_entity.nil?
|
||||
layer_collection[:elements] = [] if layer_collection[:elements].nil?
|
||||
layer_collection[:elements].append(converted_object_with_entity)
|
||||
end
|
||||
end
|
||||
|
||||
return speckle_state, model_collection
|
||||
end
|
||||
|
||||
# @param sketchup_model [Sketchup::Model] active model to retrieve and convert mapped entities.
|
||||
def self.collect_mapped_entities(speckle_state, sketchup_model, units, preferences, &convert)
|
||||
mapped_entities = Mapper.mapped_entities_on_selection(sketchup_model)
|
||||
mapped_entities.collect do |entity_with_path|
|
||||
convert_mapped_entity(speckle_state, entity_with_path, preferences, units)
|
||||
end
|
||||
end
|
||||
|
||||
def self.to_native(state, model_collection, layer, entities, &convert_to_native)
|
||||
elements = model_collection['elements']
|
||||
views = model_collection['@Views']
|
||||
if views
|
||||
views.each do |view|
|
||||
new_state, _converted_entities = convert_to_native.call(state, view, layer, entities)
|
||||
state = new_state
|
||||
end
|
||||
end
|
||||
|
||||
elements.each do |element|
|
||||
new_state, _converted_entities = convert_to_native.call(state, element, layer, entities)
|
||||
state = new_state
|
||||
end
|
||||
|
||||
active_layer = model_collection['active_layer']
|
||||
state.sketchup_state.sketchup_model.active_layer = active_layer unless active_layer.nil?
|
||||
|
||||
return state, []
|
||||
end
|
||||
|
||||
def self.convert_mapped_entity(speckle_state, entity_with_path, preferences, units)
|
||||
entity = entity_with_path[0]
|
||||
path = entity_with_path[1..-1]
|
||||
|
||||
method = SPECKLE_SCHEMA_DICTIONARY_HANDLER.get_attribute(entity, 'method')
|
||||
|
||||
if !method.nil? && (method.include?('Floor') || method.include?('Wall')) && entity.is_a?(Sketchup::Face)
|
||||
global_transformation = QUERY::Entity.global_transformation(entity, path)
|
||||
floor = SpeckleObjects::Geometry::Mesh.from_face(speckle_state: speckle_state, face: entity,
|
||||
units: units, model_preferences: preferences,
|
||||
global_transform: global_transformation)
|
||||
return [floor, [entity]]
|
||||
end
|
||||
|
||||
direct_shape = DIRECT_SHAPE.from_entity(speckle_state, entity, path, units, preferences)
|
||||
return [direct_shape, [entity]]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,12 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module SpeckleConnector
|
||||
module Ui
|
||||
# The abstract class for view to send data to a user interface.
|
||||
class View
|
||||
def update_view(_state)
|
||||
raise NotImplementedError, 'Implement in a subclass'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -4,7 +4,7 @@ require 'sketchup'
|
||||
require 'extensions'
|
||||
|
||||
# Speckle connector module to enable multiplayer mode ON!
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
# Version - patched by CI
|
||||
CONNECTOR_VERSION = '0.0.0'
|
||||
|
||||
@@ -23,11 +23,11 @@ module SpeckleConnector
|
||||
PATH = File.join(PATH_ROOT, folder_name).freeze
|
||||
|
||||
# Run from localhost or from build files
|
||||
DEV_MODE = false
|
||||
DEV_MODE = true
|
||||
puts("Loading Speckle Connector v#{CONNECTOR_VERSION} from #{DEV_MODE ? 'dev' : 'build'}")
|
||||
|
||||
unless file_loaded?(__FILE__)
|
||||
ex = SketchupExtension.new('Speckle SketchUp', File.join(PATH, 'bootstrap'))
|
||||
ex = SketchupExtension.new('Speckle SketchUp v3', File.join(PATH, 'bootstrap'))
|
||||
ex.description = 'Speckle Connector for SketchUp'
|
||||
ex.version = CONNECTOR_VERSION
|
||||
ex.copyright = 'AEC Systems Ltd.'
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
require 'sketchup'
|
||||
require 'pathname'
|
||||
require 'speckle_connector/debug'
|
||||
require 'speckle_connector_3/debug'
|
||||
require_relative 'src/log/log'
|
||||
require_relative 'src/ui/sketchup_ui'
|
||||
require_relative 'src/ui/ui_controller'
|
||||
@@ -13,7 +13,7 @@ require_relative 'src/states/initial_state'
|
||||
require_relative 'src/commands/speckle_menu_commands'
|
||||
|
||||
# Speckle Connector on SketchUp to enable Multiplayer mode ON!
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
SKETCHUP_VERSION = Sketchup.version.to_i
|
||||
|
||||
dir = __dir__.dup
|
||||
@@ -24,9 +24,9 @@ module SpeckleConnector
|
||||
sketchup_ui = Ui::SketchupUi.new
|
||||
ui_controller = Ui::UiController.new(sketchup_ui)
|
||||
menu_commands = Commands::MenuCommandHandler.new
|
||||
user_state = SpeckleConnector::States::UserState.new({})
|
||||
initial_state = SpeckleConnector::States::InitialState.new(user_state)
|
||||
app = SpeckleConnector::App::SpeckleConnectorApp.new(menu_commands, initial_state, ui_controller)
|
||||
user_state = SpeckleConnector3::States::UserState.new({})
|
||||
initial_state = SpeckleConnector3::States::InitialState.new(user_state)
|
||||
app = SpeckleConnector3::App::SpeckleConnectorApp.new(menu_commands, initial_state, ui_controller)
|
||||
# Add menu commands to SketchUp and Speckle application
|
||||
Commands::SpeckleMenuCommands.add_initial_commands!(app)
|
||||
app
|
||||
@@ -1,7 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Speckle connector module to enable multiplayer mode ON!
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
# from thomthom
|
||||
# https://github.com/thomthom/true-bend/blob/master/src/tt_truebend/debug.rb
|
||||
|
||||
|
Before Width: | Height: | Size: 798 B After Width: | Height: | Size: 798 B |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 665 B After Width: | Height: | Size: 665 B |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 639 B After Width: | Height: | Size: 639 B |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 18 KiB |
@@ -0,0 +1,65 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'JSON'
|
||||
require_relative '../ext/sqlite3'
|
||||
require_relative '../constants/path_constants'
|
||||
|
||||
module SpeckleConnector3
|
||||
# Accounts to communicate with models on user's account.
|
||||
module Accounts
|
||||
# Load accounts from user's app data.
|
||||
def self.load_accounts
|
||||
db_path = SPECKLE_ACCOUNTS_DB_PATH
|
||||
unless File.exist?(db_path)
|
||||
raise(
|
||||
IOError,
|
||||
"No Accounts db found. Please read the guide for different options for adding your account:\n
|
||||
https://speckle.guide/user/manager.html#adding-accounts"
|
||||
)
|
||||
end
|
||||
|
||||
db = Sqlite3::Database.new(db_path)
|
||||
rows = db.exec('SELECT * FROM objects')
|
||||
db.close
|
||||
rows.map { |row| JSON.parse(row[1]) }
|
||||
end
|
||||
|
||||
def self.remove_account(account_id)
|
||||
db_path = SPECKLE_ACCOUNTS_DB_PATH
|
||||
unless File.exist?(db_path)
|
||||
raise(
|
||||
IOError,
|
||||
"No Accounts db found. Please read the guide for different options for adding your account:\n
|
||||
https://speckle.guide/user/manager.html#adding-accounts"
|
||||
)
|
||||
end
|
||||
db = Sqlite3::Database.new(db_path)
|
||||
|
||||
begin
|
||||
db.exec("DELETE FROM objects WHERE hash = '#{account_id}'")
|
||||
puts "Account with hash #{account_id} has been removed."
|
||||
rescue StandardError => e
|
||||
puts "An error occurred: #{e}"
|
||||
ensure
|
||||
db.close
|
||||
end
|
||||
end
|
||||
|
||||
def self.get_account_by_id(id)
|
||||
accounts = load_accounts
|
||||
accounts.select { |acc| acc['id'] == id }[0]
|
||||
end
|
||||
|
||||
# Default account on the user computer.
|
||||
def self.default_account
|
||||
accounts = load_accounts
|
||||
accounts.select { |acc| acc['isDefault'] }[0] || accounts[0]
|
||||
end
|
||||
|
||||
# Try to get local server account for debug/test purposes.
|
||||
def self.try_get_local_server_account
|
||||
accounts = load_accounts
|
||||
accounts.select { |acc| acc['serverInfo']['url'].include?('localhost') }[0] || nil
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
require_relative '../../accounts/accounts'
|
||||
require_relative '../load_saved_streams'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to initialize local accounts from database.
|
||||
class GetAccounts < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id)
|
||||
puts 'Initialisation of Speckle accounts requested by plugin'
|
||||
accounts_data = SpeckleConnector3::Accounts.load_accounts
|
||||
js_script = "accountsBinding.receiveResponse('#{resolve_id}', #{accounts_data.to_json})"
|
||||
state.with_add_queue_js_command('getAccounts', js_script)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,20 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
require_relative '../../accounts/accounts'
|
||||
require_relative '../load_saved_streams'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to remove account from database.
|
||||
class RemoveAccount < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id, account_id)
|
||||
SpeckleConnector3::Accounts.remove_account(account_id)
|
||||
js_script = "accountsBinding.receiveResponse('#{resolve_id}')"
|
||||
state.with_add_queue_js_command('removeAccount', js_script)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,6 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# State changer object.
|
||||
class Action
|
||||
@@ -3,7 +3,7 @@
|
||||
require_relative 'action'
|
||||
require_relative 'deactivate_diffing'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Deactivate diffing for stream.
|
||||
class ActivateDiffing < Action
|
||||
@@ -15,7 +15,7 @@ module SpeckleConnector
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def update_state(state)
|
||||
state = DeactivateDiffing.update_state(state, {})
|
||||
state = DeactivateDiffing.update_state(state, nil, {})
|
||||
puts "Diffing activated for #{@stream_id}"
|
||||
speckle_entities = state.speckle_state.speckle_entities
|
||||
invalid_speckle_entities = speckle_entities.select do |_id, entity|
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
require_relative 'action'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Adds material to speckle state and Sketchup.
|
||||
class AddMaterial < Action
|
||||
@@ -5,7 +5,7 @@ require_relative 'mapped_entities_updated'
|
||||
require_relative 'events/selection_event_action'
|
||||
require_relative '../sketchup_model/dictionary/speckle_schema_dictionary_handler'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Apply mappings for selected entities.
|
||||
class ApplyMappings < Action
|
||||
@@ -37,7 +37,7 @@ module SpeckleConnector
|
||||
end
|
||||
|
||||
# Collect entities from entity ids that comes from UI as list
|
||||
entities_to_map = entities.select { |e| @entities_to_map.include?(e.persistent_id) }
|
||||
entities_to_map = entities.select { |e| @entities_to_map.include?(e.persistent_id.to_s) }
|
||||
|
||||
# Switch to definitions if all entities are component instance and UI flag shows that
|
||||
if entities_to_map.all? { |e| e.is_a?(Sketchup::ComponentInstance) } && @is_definition
|
||||
@@ -0,0 +1,28 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'add_send_model_card'
|
||||
require_relative 'add_receive_model_card'
|
||||
require_relative '../action'
|
||||
require_relative '../../cards/send_card'
|
||||
require_relative '../../cards/receive_card'
|
||||
require_relative '../../filters/send/everything_filter'
|
||||
require_relative '../../filters/send/selection_filter'
|
||||
require_relative '../../filters/send_filters'
|
||||
require_relative '../../sketchup_model/dictionary/model_card_dictionary_handler'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to add send card.
|
||||
class AddModel < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id, data)
|
||||
if data['typeDiscriminator'] == 'SenderModelCard'
|
||||
Actions::AddSendModelCard.update_state(state, resolve_id, data)
|
||||
else
|
||||
Actions::AddReceiveModelCard.update_state(state, resolve_id, data)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,50 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
require_relative '../../cards/send_card'
|
||||
require_relative '../../cards/receive_card'
|
||||
require_relative '../../filters/send/everything_filter'
|
||||
require_relative '../../filters/send/selection_filter'
|
||||
require_relative '../../filters/send_filters'
|
||||
require_relative '../../sketchup_model/dictionary/model_card_dictionary_handler'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to add receive model card.
|
||||
class AddReceiveModelCard < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id, data)
|
||||
model_card_id = data['modelCardId']
|
||||
account_id = data['accountId']
|
||||
workspace_id = data['workspaceId']
|
||||
project_id = data['projectId']
|
||||
model_id = data['modelId']
|
||||
project_name = data['projectName']
|
||||
model_name = data['modelName']
|
||||
expired = data['expired']
|
||||
selected_version_id = data['selectedVersionId']
|
||||
selected_version_source_app = data['selectedVersionSourceApp']
|
||||
selected_version_user_id = data['selectedVersionUserId']
|
||||
latest_version_id = data['latestVersionId']
|
||||
latest_version_source_app = data['latestVersionSourceApp']
|
||||
latest_version_user_id = data['latestVersionUserId']
|
||||
has_dismissed_update_warning = data['hasDismissedUpdateWarning']
|
||||
baked_object_ids = data['bakedObjectIds'].nil? ? nil : data['bakedObjectIds'].values
|
||||
|
||||
receive_card = Cards::ReceiveCard.new(model_card_id, account_id, workspace_id,
|
||||
project_id, model_id,
|
||||
project_name, model_name,
|
||||
selected_version_id, selected_version_source_app, selected_version_user_id,
|
||||
latest_version_id, latest_version_source_app, latest_version_user_id,
|
||||
has_dismissed_update_warning, expired, baked_object_ids)
|
||||
SketchupModel::Dictionary::ModelCardDictionaryHandler
|
||||
.save_receive_card_to_model(receive_card, state.sketchup_state.sketchup_model)
|
||||
new_speckle_state = state.speckle_state.with_receive_card(receive_card)
|
||||
state = state.with_speckle_state(new_speckle_state)
|
||||
js_script = "baseBinding.receiveResponse('#{resolve_id}')"
|
||||
return state.with_add_queue_js_command('addReceiveCard', js_script)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,46 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
require_relative '../../cards/send_card'
|
||||
require_relative '../../cards/receive_card'
|
||||
require_relative '../../filters/send/everything_filter'
|
||||
require_relative '../../filters/send/selection_filter'
|
||||
require_relative '../../filters/send_filters'
|
||||
require_relative '../../settings/card_settings'
|
||||
require_relative '../../sketchup_model/dictionary/model_card_dictionary_handler'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to add send model card.
|
||||
class AddSendModelCard < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id, data)
|
||||
send_filter = Filters::SendFilters.get_filter_from_ui_data(data['sendFilter'])
|
||||
# settings = Settings::CardSetting.get_setting_from_ui_data(data['settings'])
|
||||
# Init card and add to the state
|
||||
send_card = Cards::SendCard.new(
|
||||
data['modelCardId'],
|
||||
data['accountId'],
|
||||
data['workspaceId'],
|
||||
data['projectId'],
|
||||
data['projectName'],
|
||||
data['modelId'],
|
||||
data['modelName'],
|
||||
data['latestCreatedVersionId'],
|
||||
send_filter,
|
||||
data['settings']
|
||||
)
|
||||
|
||||
SketchupModel::Dictionary::ModelCardDictionaryHandler
|
||||
.save_send_card_to_model(send_card, state.sketchup_state.sketchup_model)
|
||||
|
||||
new_speckle_state = state.speckle_state.with_send_card(send_card)
|
||||
state = state.with_speckle_state(new_speckle_state)
|
||||
# Resolve promise
|
||||
js_script = "baseBinding.receiveResponse('#{resolve_id}')"
|
||||
state.with_add_queue_js_command('addSendCard', js_script)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,17 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Get connector version.
|
||||
class GetConnectorVersion < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id)
|
||||
js_command = "baseBinding.receiveResponse('#{resolve_id}', '#{CONNECTOR_VERSION}')"
|
||||
state.with_add_queue_js_command('getConnectorVersion', js_command)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,91 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
require_relative '../../filters/send_filters'
|
||||
require_relative '../../sketchup_model/dictionary/model_card_dictionary_handler'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Gets document state.
|
||||
class GetDocumentState < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id)
|
||||
send_cards_hash = SketchupModel::Dictionary::ModelCardDictionaryHandler
|
||||
.get_send_cards_from_dict(state.sketchup_state.sketchup_model)
|
||||
|
||||
# TODO: CONVERTER_V2: Extract into new actions
|
||||
send_cards = send_cards_hash.collect do |id, card|
|
||||
filter = Filters::SendFilters.get_filter_from_document(card['sendFilter'])
|
||||
settings = Settings::CardSetting.get_filter_from_document(card['sendSettings'])
|
||||
send_card = Cards::SendCard.new(
|
||||
id,
|
||||
card['account_id'],
|
||||
card['workspace_id'],
|
||||
card['project_id'],
|
||||
card['project_name'],
|
||||
card['model_id'],
|
||||
card['model_name'],
|
||||
card['latest_created_version_id'],
|
||||
filter,
|
||||
settings
|
||||
)
|
||||
|
||||
new_speckle_state = state.speckle_state.with_send_card(send_card)
|
||||
state = state.with_speckle_state(new_speckle_state)
|
||||
{
|
||||
modelCardId: send_card.model_card_id,
|
||||
accountId: send_card.account_id,
|
||||
workspaceId: send_card.workspace_id,
|
||||
projectId: send_card.project_id,
|
||||
modelId: send_card.model_id,
|
||||
sendFilter: send_card.send_filter,
|
||||
settings: send_card.send_settings,
|
||||
latestCreatedVersionId: send_card.latest_created_version_id,
|
||||
typeDiscriminator: send_card.type_discriminator
|
||||
}
|
||||
end
|
||||
|
||||
receive_cards_hash = SketchupModel::Dictionary::ModelCardDictionaryHandler
|
||||
.get_receive_cards_from_dict(state.sketchup_state.sketchup_model)
|
||||
|
||||
# TODO: CONVERTER_V2: Extract into new actions
|
||||
receive_cards = receive_cards_hash.collect do |id, card|
|
||||
receive_card = Cards::ReceiveCard.new(id, card['account_id'], card['workspace_id'], card['project_id'], card['model_id'],
|
||||
card['project_name'], card['model_name'], card['selected_version_id'],
|
||||
card['selected_version_source_app'], card['selected_version_user_id'],
|
||||
card['latest_version_id'], card['latest_version_source_app'],
|
||||
card['latest_version_user_id'], card['has_dismissed_update_warning'],
|
||||
card['expired'], card['baked_object_ids'])
|
||||
|
||||
new_speckle_state = state.speckle_state.with_receive_card(receive_card)
|
||||
state = state.with_speckle_state(new_speckle_state)
|
||||
{
|
||||
modelCardId: receive_card.model_card_id,
|
||||
accountId: receive_card.account_id,
|
||||
workspaceId: receive_card.workspace_id,
|
||||
projectId: receive_card.project_id,
|
||||
modelId: receive_card.model_id,
|
||||
projectName: receive_card.project_name,
|
||||
modelName: receive_card.model_name,
|
||||
selectedVersionId: receive_card.selected_version_id,
|
||||
selectedVersionSourceApp: receive_card.selected_version_source_app,
|
||||
selectedVersionUserId: receive_card.selected_version_user_id,
|
||||
latestVersionId: receive_card.latest_version_id,
|
||||
latestVersionSourceApp: receive_card.latest_version_source_app,
|
||||
latestVersionUserId: receive_card.latest_version_user_id,
|
||||
hasDismissedUpdateWarning: receive_card.has_dismissed_update_warning,
|
||||
expired: receive_card.expired,
|
||||
bakedObjectIds: receive_card.baked_object_ids,
|
||||
typeDiscriminator: receive_card.type_discriminator
|
||||
}
|
||||
end
|
||||
|
||||
model_state = { models: send_cards + receive_cards }
|
||||
|
||||
js_script = "baseBinding.receiveResponse('#{resolve_id}', #{model_state.to_json})"
|
||||
state.with_add_queue_js_command('getDocumentState', js_script)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,19 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
require_relative '../../filters/send_filters'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to get send filter.
|
||||
class GetSendFilters < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id)
|
||||
default_filters = Filters::SendFilters.get_default(state.sketchup_state.sketchup_model)
|
||||
js_script = "sendBinding.receiveResponse('#{resolve_id}', #{default_filters.to_json})"
|
||||
state.with_add_queue_js_command('getSendFilter', js_script)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,24 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
require_relative '../../settings/card_settings'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to get send settings.
|
||||
class GetSendSettings < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id)
|
||||
# NOTE: below code is tested and works!
|
||||
# default_settings = [
|
||||
# Settings::CardSetting.new(id: "includeAttributes", title: "Include Attributes", type: "boolean", value: true),
|
||||
# Settings::CardSetting.new(id: "test", title: "Test", type: "string", value: "a", enum: %w[a b c])
|
||||
# ]
|
||||
default_settings = []
|
||||
js_script = "sendBinding.receiveResponse('#{resolve_id}', #{default_settings.to_json})"
|
||||
state.with_add_queue_js_command('getSendSettings', js_script)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,17 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Get source app name.
|
||||
class GetSourceAppName < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id)
|
||||
js_command = "baseBinding.receiveResponse('#{resolve_id}', 'sketchup')"
|
||||
state.with_add_queue_js_command('getSourceAppName', js_command)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,17 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Get source app version.
|
||||
class GetSourceAppVersion < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id)
|
||||
js_command = "baseBinding.receiveResponse('#{resolve_id}', #{SKETCHUP_VERSION})"
|
||||
state.with_add_queue_js_command('getSourceAppVersion', js_command)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,31 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
require_relative '../../sketchup_model/query/entity'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to add send card.
|
||||
class HighlightModel < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id, model_card_id)
|
||||
receiver_card = state.speckle_state.receive_cards[model_card_id]
|
||||
sender_card = state.speckle_state.send_cards[model_card_id]
|
||||
card = receiver_card || sender_card
|
||||
|
||||
objects_to_highlight = if card.type_discriminator == 'ReceiverModelCard'
|
||||
state.speckle_state.receive_cards[model_card_id].baked_object_ids
|
||||
else
|
||||
state.speckle_state.send_cards[model_card_id].send_filter.selected_object_ids
|
||||
end
|
||||
|
||||
SketchupModel::Utils::ViewUtils.highlight_entities(state.sketchup_state.sketchup_model, objects_to_highlight)
|
||||
|
||||
# Resolve promise
|
||||
js_script = "baseBinding.receiveResponse('#{resolve_id}')"
|
||||
state.with_add_queue_js_command('highlightModel', js_script)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,20 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
require_relative '../../sketchup_model/query/entity'
|
||||
require_relative '../../sketchup_model/utils/view_utils'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to add send card.
|
||||
class HighlightObjects < Action
|
||||
def self.update_state(state, resolve_id, object_ids)
|
||||
SketchupModel::Utils::ViewUtils.highlight_entities(state.sketchup_state.sketchup_model, object_ids)
|
||||
|
||||
# Resolve promise
|
||||
js_script = "baseBinding.receiveResponse('#{resolve_id}')"
|
||||
state.with_add_queue_js_command('highlightObjects', js_script)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,31 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
require_relative '../../cards/send_card'
|
||||
require_relative '../../cards/receive_card'
|
||||
require_relative '../../filters/send/everything_filter'
|
||||
require_relative '../../filters/send/selection_filter'
|
||||
require_relative '../../filters/send_filters'
|
||||
require_relative '../../sketchup_model/dictionary/model_card_dictionary_handler'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to remove send card.
|
||||
class RemoveModel < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id, data)
|
||||
SketchupModel::Dictionary::ModelCardDictionaryHandler.remove_card_dict(state.sketchup_state.sketchup_model, data)
|
||||
new_speckle_state = if data['typeDiscriminator'] == 'ReceiverModelCard'
|
||||
state.speckle_state.without_receive_card(data['id'])
|
||||
else
|
||||
state.speckle_state.without_send_card(data['id'])
|
||||
end
|
||||
state = state.with_speckle_state(new_speckle_state)
|
||||
# Resolve promise
|
||||
js_script = "baseBinding.receiveResponse('#{resolve_id}')"
|
||||
state.with_add_queue_js_command('removeModel', js_script)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,34 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
require_relative '../../cards/send_card'
|
||||
require_relative '../../cards/receive_card'
|
||||
require_relative '../../filters/send/everything_filter'
|
||||
require_relative '../../filters/send/selection_filter'
|
||||
require_relative '../../filters/send_filters'
|
||||
require_relative '../../sketchup_model/dictionary/model_card_dictionary_handler'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to remove cards.
|
||||
class RemoveModels < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id, data)
|
||||
data.each do |model_card|
|
||||
SketchupModel::Dictionary::ModelCardDictionaryHandler.remove_card_dict(state.sketchup_state.sketchup_model, model_card)
|
||||
new_speckle_state = if model_card['typeDiscriminator'] == 'ReceiverModelCard'
|
||||
state.speckle_state.without_receive_card(model_card['id'])
|
||||
else
|
||||
state.speckle_state.without_send_card(model_card['id'])
|
||||
end
|
||||
state = state.with_speckle_state(new_speckle_state)
|
||||
end
|
||||
|
||||
# Resolve promise
|
||||
js_script = "baseBinding.receiveResponse('#{resolve_id}')"
|
||||
state.with_add_queue_js_command('removeModels', js_script)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,20 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
require_relative '../../sketchup_model/dictionary/model_card_dictionary_handler'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to update send filter.
|
||||
class UpdateSendFilter < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id, data, value)
|
||||
SketchupModel::Dictionary::ModelCardDictionaryHandler.update_filter(state.sketchup_state.sketchup_model, data, value)
|
||||
|
||||
js_script = "sendBinding.receiveResponse('#{resolve_id}')"
|
||||
state.with_add_queue_js_command('updateSendFilter', js_script)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3,13 +3,13 @@
|
||||
require_relative 'action'
|
||||
require_relative '../sketchup_model/dictionary/speckle_entity_dictionary_handler'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Clear mapper source.
|
||||
class ClearMapperSource < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, _data)
|
||||
def self.update_state(state, _resolve_id, _data)
|
||||
new_speckle_state = state.speckle_state.with_removed_mapper_source
|
||||
erase_levels(state)
|
||||
state.with_speckle_state(new_speckle_state)
|
||||
@@ -5,7 +5,7 @@ require_relative 'mapped_entities_updated'
|
||||
require_relative 'events/selection_event_action'
|
||||
require_relative '../sketchup_model/dictionary/speckle_schema_dictionary_handler'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Clear mappings for selected entities.
|
||||
class ClearMappings < Action
|
||||
@@ -28,7 +28,7 @@ module SpeckleConnector
|
||||
end
|
||||
|
||||
# Collect entities from entity ids that comes from UI as list
|
||||
entities_to_map = entities.select { |e| @entities_to_map.include?(e.persistent_id) }
|
||||
entities_to_map = entities.select { |e| @entities_to_map.include?(e.persistent_id.to_s) }
|
||||
|
||||
# Switch to definitions if all entities are component instance and UI flag shows that
|
||||
if entities_to_map.all? { |e| e.is_a?(Sketchup::ComponentInstance) } && @is_definition
|
||||
@@ -5,13 +5,13 @@ require_relative 'mapped_entities_updated'
|
||||
require_relative 'events/selection_event_action'
|
||||
require_relative '../sketchup_model/dictionary/speckle_schema_dictionary_handler'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Clear mappings for selected entities from mapped elements table.
|
||||
class ClearMappingsFromTable < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, data)
|
||||
def self.update_state(state, _resolve_id, data)
|
||||
# Flat entities to clear mappings
|
||||
flat_entities = SketchupModel::Query::Entity.flat_entities(state.sketchup_state.sketchup_model.entities)
|
||||
|
||||
@@ -20,7 +20,7 @@ module SpeckleConnector
|
||||
# Store speckle state to update with mapped entities.
|
||||
speckle_state = state.speckle_state
|
||||
flat_entities.each do |entity|
|
||||
next unless entity_ids.include?(entity.persistent_id)
|
||||
next unless entity_ids.include?(entity.persistent_id.to_s)
|
||||
|
||||
SketchupModel::Dictionary::SpeckleSchemaDictionaryHandler.remove_dictionary(entity)
|
||||
speckle_state = speckle_state.with_removed_mapped_entity(entity)
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
require_relative 'action'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Clear queue from state.
|
||||
class ClearQueue < Action
|
||||
@@ -4,13 +4,13 @@ require_relative 'action'
|
||||
require_relative '../ext/sqlite3'
|
||||
require_relative '../constants/path_constants'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to collect preferences from database to UI.
|
||||
class CollectPreferences < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, _data)
|
||||
def self.update_state(state, _resolve_id, _data)
|
||||
state.with_add_queue('collectPreferences', state.user_state.preferences.to_json, [])
|
||||
end
|
||||
end
|
||||
@@ -2,16 +2,16 @@
|
||||
|
||||
require_relative 'action'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to collect versions from sketchup and connector to track user's version by mixpanel.
|
||||
class CollectVersions < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, _data)
|
||||
def self.update_state(state, _resolve_id, _data)
|
||||
versions = {
|
||||
sketchup: Sketchup.version.to_i,
|
||||
speckle: SpeckleConnector::CONNECTOR_VERSION
|
||||
speckle: SpeckleConnector3::CONNECTOR_VERSION
|
||||
}
|
||||
state.with_add_queue('collectVersions', versions.to_json, [])
|
||||
end
|
||||
@@ -0,0 +1,22 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to get config.
|
||||
class GetConfig < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id)
|
||||
# Previously it was stored in user state
|
||||
# config = state.user_state.preferences.to_json
|
||||
config = {
|
||||
darkTheme: state.user_state.user_preferences[:dark_theme]
|
||||
}
|
||||
js_script = "configBinding.receiveResponse('#{resolve_id}', #{config.to_json})"
|
||||
state.with_add_queue_js_command('getConfig', js_script)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,17 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to get is dev mode.
|
||||
class GetIsDevMode < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id)
|
||||
js_script = "configBinding.receiveResponse('#{resolve_id}', #{DEV_MODE})"
|
||||
state.with_add_queue_js_command('getIsDevMode', js_script)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
require_relative '../../preferences/preferences'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
class GetUserSelectedAccountId < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id)
|
||||
user_selected_account_id = Preferences.get_user_selected_account_id
|
||||
accountsConfig = {
|
||||
userSelectedAccountId: user_selected_account_id
|
||||
}
|
||||
js_script = "configBinding.receiveResponse('#{resolve_id}', #{accountsConfig.to_json})"
|
||||
state.with_add_queue_js_command('getUserSelectedAccountId', js_script)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
require_relative '../../preferences/preferences'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
class SetUserSelectedAccountId < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id, account_id)
|
||||
Preferences.set_user_selected_account_id(account_id)
|
||||
js_script = "configBinding.receiveResponse('#{resolve_id}')"
|
||||
state.with_add_queue_js_command('setUserSelectedAccountId', js_script)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,26 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../action'
|
||||
require_relative '../user_preferences_updated'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to update config.
|
||||
class UpdateConfig < Action
|
||||
KEY_VALUES = {
|
||||
'darkTheme' => 'dark_theme'
|
||||
}.freeze
|
||||
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id, config)
|
||||
config.each do |key, value|
|
||||
state = Actions::UserPreferencesUpdated.new('Sketchup', KEY_VALUES[key], value).update_state(state)
|
||||
end
|
||||
|
||||
js_script = "configBinding.receiveResponse('#{resolve_id}')"
|
||||
state.with_add_queue_js_command('updateConfig', js_script)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,6 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to update connected state of application.
|
||||
class Connected < Action
|
||||
@@ -6,7 +6,7 @@ require_relative '../actions/save_stream'
|
||||
require_relative '../actions/queue_send'
|
||||
require_relative '../convertors/converter'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Create stream.
|
||||
class CreateStream < Action
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
require_relative 'action'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Deactivate diffing.
|
||||
class DeactivateDiffing < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, _data)
|
||||
def self.update_state(state, _resolve_id, _data)
|
||||
puts 'Diffing deactivated!'
|
||||
speckle_entities = state.speckle_state.speckle_entities
|
||||
diffing_activated_speckle_entities = speckle_entities.reject do |_id, entity|
|
||||
@@ -1,10 +1,11 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'event_action'
|
||||
require_relative 'on_document_changed'
|
||||
require_relative '../load_sketchup_model'
|
||||
require_relative '../collect_preferences'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
module Events
|
||||
# Handle events that are triggered by the {AppObserver}.
|
||||
@@ -25,7 +26,8 @@ module SpeckleConnector
|
||||
# Action to let UI to render itself with new preferences state
|
||||
# TODO: Later UI should be updated if any stream is invalid after
|
||||
# we collected speckle_entities appropriately
|
||||
CollectPreferences.update_state(new_state, {})
|
||||
new_state = CollectPreferences.update_state(new_state, nil, {})
|
||||
OnDocumentChanged.update_state(new_state)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'event_action'
|
||||
require_relative '../../actions/send_actions/send_card_expiration_check'
|
||||
require_relative '../../sketchup_model/utils/face_utils'
|
||||
require_relative '../../constants/dict_constants'
|
||||
require_relative '../../sketchup_model/query/path'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
module Events
|
||||
# Event actions related to entities.
|
||||
class EntitiesEventAction < EventAction
|
||||
PATH = SketchupModel::Query::Path
|
||||
# Event action when element added.
|
||||
class OnElementAdded
|
||||
# @param state [States::State] the current state of the SpeckleConnector Application
|
||||
def self.update_state(state, event_data)
|
||||
modified_entities = event_data.to_a.collect { |e| e[1] }
|
||||
# do not copy speckle base object specific attributes, because they are entity specific
|
||||
modified_entities.each { |entity| entity.delete_attribute(SPECKLE_BASE_OBJECT) }
|
||||
|
||||
# All parent ids on current active path
|
||||
parent_ids = PATH.parents_with_definitions(state.sketchup_state.sketchup_model).collect(&:persistent_id).collect(&:to_s)
|
||||
|
||||
# All instances that changed potentially because of potential definition update
|
||||
path_instance_ids = PATH.instances(state.sketchup_state.sketchup_model).collect(&:persistent_id).collect(&:to_s)
|
||||
wrapped_entity_ids = wrapped_entity_ids(modified_entities)
|
||||
ids_to_check = parent_ids + wrapped_entity_ids + path_instance_ids +
|
||||
modified_entities.collect(&:persistent_id).collect(&:to_s) # NOTE: It fixes the same weird face problems. Ideally the push-pull result should hit the OnElementModified but for some cases we found the edge here......
|
||||
state = EntitiesEventAction.run_expiration_checks(state, ids_to_check) if ids_to_check.any?
|
||||
|
||||
attach_edge_entity_observer(modified_entities.grep(Sketchup::Edge), state.speckle_state.observers[ENTITY_OBSERVER])
|
||||
state
|
||||
end
|
||||
|
||||
def self.wrapped_entity_ids(modified_entities)
|
||||
wrapped_entity_ids = []
|
||||
modified_entities.select { |e| e.respond_to?(:definition) }.each do |c|
|
||||
wrapped_entity_ids += c.definition.entities.collect(&:persistent_id).collect(&:to_s)
|
||||
end
|
||||
wrapped_entity_ids
|
||||
end
|
||||
|
||||
# It is needed for attaching EntityObserver to newly added edges to track them with a hacky way.
|
||||
# This hacky way is because of limitation on Sketchup API that observer cannot catch changes on Edges
|
||||
# with EntitiesObserver.
|
||||
def self.attach_edge_entity_observer(edges, observer)
|
||||
edges.each do |edge|
|
||||
edge.add_observer(observer)
|
||||
edge.start.add_observer(observer)
|
||||
edge.end.add_observer(observer)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Event action when element modified.
|
||||
class OnElementModified
|
||||
# @param state [States::State] the current state of the SpeckleConnector Application
|
||||
def self.update_state(state, event_data)
|
||||
modified_entities = event_data.collect { |data| data[1] }.to_a
|
||||
definition_faces = get_definition_faces(modified_entities)
|
||||
near_faces = get_near_faces(modified_entities)
|
||||
modified_persistent_ids = modified_entities.collect(&:persistent_id).collect(&:to_s) +
|
||||
definition_faces.collect(&:persistent_id).collect(&:to_s) +
|
||||
near_faces.collect(&:persistent_id).collect(&:to_s)
|
||||
|
||||
parent_ids = PATH.parents_with_definitions(state.sketchup_state.sketchup_model).collect(&:persistent_id).collect(&:to_s)
|
||||
|
||||
path_instance_ids = PATH.instances(state.sketchup_state.sketchup_model).collect(&:persistent_id).collect(&:to_s)
|
||||
modified_persistent_ids += parent_ids + path_instance_ids
|
||||
state = EntitiesEventAction.run_expiration_checks(state, modified_persistent_ids)
|
||||
# if modified_entity.is_a?(Sketchup::Face)
|
||||
# path = state.sketchup_state.sketchup_model.active_path
|
||||
# modified_faces = SketchupModel::Utils::FaceUtils.near_faces(modified_entity.edges)
|
||||
# path_objects = path.nil? ? [] : path + path.collect(&:definition)
|
||||
# parent_ids = path_objects.collect(&:persistent_id).collect(&:to_s)
|
||||
# ids_to_invalidate = modified_faces.collect(&:persistent_id).collect(&:to_s) + parent_ids
|
||||
# entities_to_invalidate = speckle_entities_to_invalidate(speckle_state, ids_to_invalidate)
|
||||
# new_speckle_state = invalidate_speckle_entities(speckle_state, entities_to_invalidate)
|
||||
# # This is the place we can send information to UI for diffing check
|
||||
# diffing = state.user_state.preferences[:user][:diffing]
|
||||
# new_speckle_state = new_speckle_state.with_invalid_streams_queue if diffing
|
||||
# return state.with_speckle_state(new_speckle_state)
|
||||
# end
|
||||
|
||||
state
|
||||
end
|
||||
|
||||
def self.get_near_faces(modified_entities)
|
||||
near_faces = []
|
||||
modified_entities.each do |modified_entity|
|
||||
if modified_entity.is_a?(Sketchup::Face)
|
||||
near_faces += SketchupModel::Utils::FaceUtils.near_faces(modified_entity.edges)
|
||||
elsif modified_entity.is_a?(Sketchup::Edge)
|
||||
near_faces += modified_entity.faces
|
||||
end
|
||||
end
|
||||
near_faces
|
||||
end
|
||||
|
||||
def self.get_definition_faces(modified_entities)
|
||||
definition_faces = []
|
||||
modified_entities.each do |modified_entity|
|
||||
next unless modified_entity.is_a?(Sketchup::Face)
|
||||
next unless modified_entity.parent.is_a?(Sketchup::ComponentDefinition)
|
||||
|
||||
definition_faces += modified_entity.parent.entities.grep(Sketchup::Face)
|
||||
end
|
||||
definition_faces
|
||||
end
|
||||
|
||||
# @param speckle_state [States::SpeckleState] the current state of the Speckle
|
||||
def self.speckle_entities_to_invalidate(speckle_state, ids)
|
||||
speckle_state.speckle_entities.to_h.select { |id, _| ids.include?(id) }
|
||||
end
|
||||
|
||||
# @param speckle_state [States::SpeckleState] the current state of the Speckle
|
||||
def self.invalidate_speckle_entities(speckle_state, entities_to_invalidate)
|
||||
speckle_entities = speckle_state.speckle_entities
|
||||
entities_to_invalidate.each do |id, speckle_entity|
|
||||
edited_speckle_entity = speckle_entity.with_invalid
|
||||
speckle_entities = speckle_entities.put(id, edited_speckle_entity)
|
||||
end
|
||||
speckle_state.with_speckle_entities(speckle_entities)
|
||||
end
|
||||
end
|
||||
|
||||
# Event action when element removed.
|
||||
class OnElementRemoved
|
||||
# @param state [States::State] the current state of the SpeckleConnector Application
|
||||
def self.update_state(state, event_data)
|
||||
modified_entity_ids = event_data.collect { |data| data[1] }.to_a.collect(&:to_s)
|
||||
new_speckle_state = state.speckle_state.with_changed_entity_ids(modified_entity_ids)
|
||||
state = state.with_speckle_state(new_speckle_state)
|
||||
Actions::SendCardExpirationCheck.update_state(state)
|
||||
end
|
||||
end
|
||||
|
||||
# @param state [States::State] the current state of the SpeckleConnector Application
|
||||
# @param changed_persistent_ids [Array<String>] list of changed persistent ids
|
||||
def self.run_expiration_checks(state, changed_persistent_ids)
|
||||
new_speckle_state = state.speckle_state.with_changed_entity_persistent_ids(changed_persistent_ids)
|
||||
state = state.with_speckle_state(new_speckle_state)
|
||||
Actions::SendCardExpirationCheck.update_state(state)
|
||||
end
|
||||
|
||||
# Handlers that are used to handle specific events
|
||||
ACTIONS = {
|
||||
onElementRemoved: OnElementRemoved,
|
||||
onElementAdded: OnElementAdded,
|
||||
onElementModified: OnElementModified
|
||||
}.freeze
|
||||
|
||||
def self.actions
|
||||
ACTIONS
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,51 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'event_action'
|
||||
require_relative '../../constants/dict_constants'
|
||||
require_relative '../../sketchup_model/query/path'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
module Events
|
||||
PATH = SketchupModel::Query::Path
|
||||
# Event actions related to entities.
|
||||
class EntityEventAction < EventAction
|
||||
# Event action when entity modified/changed.
|
||||
# PS: this handler action only triggers for edges and it's vertices since we attach EntityObserver to
|
||||
# only edge and vertex entities. This is a limitation of the Sketchup API that can't handles edges with
|
||||
# EntitiesObserver.
|
||||
class OnChangeEntity
|
||||
# @param state [States::State] the current state of the SpeckleConnector Application
|
||||
def self.update_state(state, event_data)
|
||||
edges = []
|
||||
event_data.each do |event_d|
|
||||
event_d.each do |d|
|
||||
next if d.deleted?
|
||||
|
||||
edges.append(d) if d.is_a?(Sketchup::Edge)
|
||||
edges += d.edges if d.is_a?(Sketchup::Vertex) && d.edges
|
||||
end
|
||||
end
|
||||
|
||||
parent_ids = PATH.parents_with_definitions(state.sketchup_state.sketchup_model).collect(&:persistent_id).collect(&:to_s)
|
||||
path_instance_ids = PATH.instances(state.sketchup_state.sketchup_model).collect(&:persistent_id).collect(&:to_s)
|
||||
|
||||
edges.uniq!
|
||||
edge_ids = edges.collect(&:persistent_id).collect(&:to_s)
|
||||
new_speckle_state = state.speckle_state.with_changed_entity_persistent_ids(edge_ids + parent_ids + path_instance_ids)
|
||||
state.with_speckle_state(new_speckle_state)
|
||||
end
|
||||
end
|
||||
|
||||
# Handlers that are used to handle specific events
|
||||
ACTIONS = {
|
||||
onChangeEntity: OnChangeEntity
|
||||
}.freeze
|
||||
|
||||
def self.actions
|
||||
ACTIONS
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,6 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# This module contains actions that are performed to handle events triggered by observers in Sketchup.
|
||||
module Events
|
||||
@@ -3,7 +3,7 @@
|
||||
require_relative 'event_action'
|
||||
require_relative '../load_sketchup_model'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
module Events
|
||||
# Handle events that are triggered by the {ModelObserver}.
|
||||
@@ -18,12 +18,21 @@ module SpeckleConnector
|
||||
sketchup_state = state.sketchup_state
|
||||
active_path = sketchup_state.sketchup_model.active_path
|
||||
observers = state.speckle_state.observers
|
||||
update_object_observers(active_path, observers)
|
||||
update_entity_observers(active_path, observers)
|
||||
return state
|
||||
end
|
||||
|
||||
def self.update_object_observers(path, observers)
|
||||
path[-1].definition.entities.add_observer(observers[ENTITIES_OBSERVER]) unless path.nil?
|
||||
def self.update_entity_observers(path, observers)
|
||||
unless path.nil?
|
||||
new_path_entities = path[-1].definition.entities
|
||||
new_path_entities.add_observer(observers[ENTITIES_OBSERVER])
|
||||
edges = new_path_entities.grep(Sketchup::Edge)
|
||||
edges.each do |edge|
|
||||
edge.add_observer(observers[ENTITY_OBSERVER])
|
||||
edge.start.add_observer(observers[ENTITY_OBSERVER])
|
||||
edge.end.add_observer(observers[ENTITY_OBSERVER])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Triggers whenever document has changed.
|
||||
class OnDocumentChanged < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state)
|
||||
js_command = "baseBinding.emit('documentChanged')"
|
||||
state.with_add_queue_js_command('documentChanged', js_command)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -2,12 +2,13 @@
|
||||
|
||||
require_relative 'event_action'
|
||||
require_relative '../mapper_selection_changed'
|
||||
require_relative '../selection_actions/get_selection'
|
||||
require_relative '../../mapper/category/revit_category'
|
||||
require_relative '../../sketchup_model/reader/speckle_entities_reader'
|
||||
require_relative '../../sketchup_model/reader/mapper_reader'
|
||||
require_relative '../../sketchup_model/query/entity'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
module Events
|
||||
# Update selected speckle objects when the selection changes for mapper tool.
|
||||
@@ -17,12 +18,18 @@ module SpeckleConnector
|
||||
def self.update_state(state, event_data)
|
||||
return state unless event_data&.any?
|
||||
|
||||
# Get sketchup selection
|
||||
sketchup_selection = state.sketchup_state.sketchup_model.selection
|
||||
# POC: Not happy with it. We log also entity.entityID property since
|
||||
# onElementRemoved observer only return them! :/ Reconsider this in BETA!
|
||||
selected_object_ids = state.sketchup_state.sketchup_model.selection.collect(&:persistent_id).collect(&:to_s) +
|
||||
state.sketchup_state.sketchup_model.selection.collect(&:entityID).collect(&:to_s)
|
||||
summary = "Selected #{selected_object_ids.length / 2} objects." # POC: OFFF. I'll fix it
|
||||
selection_info = UiData::Sketchup::SelectionInfo.new(selected_object_ids, summary)
|
||||
js_script = "selectionBinding.emit('setSelection', #{selection_info.to_json})"
|
||||
state.with_add_queue_js_command('setSelection', js_script)
|
||||
|
||||
# Collect and return mapper selection info.
|
||||
# Later we can add more selection info for different scopes.
|
||||
MapperSelectionChanged.new(sketchup_selection).update_state(state)
|
||||
# MapperSelectionChanged.new(sketchup_selection).update_state(state)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,22 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'action'
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Get document info.
|
||||
class GetDocumentInfo < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, resolve_id)
|
||||
document_info = {
|
||||
location: state.sketchup_state.sketchup_model.path,
|
||||
name: state.sketchup_state.sketchup_model.name,
|
||||
id: state.sketchup_state.sketchup_model.guid
|
||||
}
|
||||
js_command = "baseBinding.receiveResponse('#{resolve_id}', #{document_info.to_json})"
|
||||
state.with_add_queue_js_command('getDocumentInfo', js_command)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,37 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to return error message to UI.
|
||||
# It is "TopLevelExceptionHandler" equivalent of C#.
|
||||
class HandleError < Action
|
||||
# @return [StandardError] error
|
||||
attr_reader :error
|
||||
|
||||
# @param error [StandardError] error
|
||||
# @param view_name [String] name of the view (binding)
|
||||
# @param action [Action] action that error happened
|
||||
# @param parameters [Array<String>] arguments
|
||||
def initialize(error, view_name, action, parameters)
|
||||
super()
|
||||
@error = error
|
||||
@view_name = view_name
|
||||
@action = action
|
||||
@args = parameters
|
||||
end
|
||||
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def update_state(state)
|
||||
# TODO: Log here when it is ready!!!
|
||||
host_app_error = {
|
||||
message: error.message,
|
||||
error: error,
|
||||
stackTrace: error.backtrace
|
||||
}
|
||||
js_error_script = "#{@view_name}.receiveResponse('#{@args.first}', #{host_app_error.to_json})"
|
||||
state.with_add_queue_js_command("error_#{@view_name}", js_error_script)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -4,13 +4,13 @@ require_relative 'action'
|
||||
require_relative 'events/selection_event_action'
|
||||
require_relative '../sketchup_model/dictionary/speckle_schema_dictionary_handler'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Hide entities that selected from mapped elements table.
|
||||
class HideMappingsFromTable < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, data)
|
||||
def self.update_state(state, _resolve_id, data)
|
||||
# Flat entities to clear mappings
|
||||
flat_entities = SketchupModel::Query::Entity.flat_entities(state.sketchup_state.sketchup_model.entities)
|
||||
|
||||
@@ -19,7 +19,7 @@ module SpeckleConnector
|
||||
|
||||
# Store speckle state to update with mapped entities.
|
||||
flat_entities.each do |entity|
|
||||
next unless entity_ids.include?(entity.persistent_id)
|
||||
next unless entity_ids.include?(entity.persistent_id.to_s)
|
||||
|
||||
if entity.is_a?(Sketchup::ComponentDefinition)
|
||||
entity.instances.each do |instance|
|
||||
@@ -4,13 +4,13 @@ require_relative 'action'
|
||||
require_relative '../accounts/accounts'
|
||||
require_relative 'load_saved_streams'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to initialize local accounts from database.
|
||||
class InitLocalAccounts < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, _data)
|
||||
def self.update_state(state, _request_id, _data)
|
||||
puts 'Initialisation of Speckle accounts requested by plugin'
|
||||
accounts_data = state.speckle_state.accounts
|
||||
state.with_add_queue('loadAccounts', accounts_data.to_json, [])
|
||||
@@ -4,7 +4,7 @@ require_relative 'action'
|
||||
require_relative 'add_material'
|
||||
require_relative '../constants/mat_constants'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Action to initialize materials
|
||||
class InitializeMaterials < Action
|
||||
@@ -7,22 +7,25 @@ require_relative '../states/sketchup_state'
|
||||
require_relative '../accounts/accounts'
|
||||
require_relative '../preferences/preferences'
|
||||
require_relative '../constants/observer_constants'
|
||||
require_relative '../ext/worker'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Initialization of the real state of the speckle.
|
||||
class InitializeSpeckle < Action
|
||||
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
|
||||
# @return [States::State] the new updated state object
|
||||
def self.update_state(state, observers)
|
||||
def self.update_state(state, observers, instant_message_sender)
|
||||
worker = SpeckleConnector3::Worker.new([])
|
||||
attach_app_observer!(observers[APP_OBSERVER])
|
||||
accounts = SpeckleConnector::Accounts.load_accounts
|
||||
accounts = SpeckleConnector3::Accounts.load_accounts
|
||||
speckle_state = States::SpeckleState.new(accounts, observers, {}, {})
|
||||
# This should be the only point that `Sketchup_active_model` passed to application state.
|
||||
sketchup_state = States::SketchupState.new(Sketchup.active_model)
|
||||
preferences = Preferences.read_preferences(sketchup_state.sketchup_model)
|
||||
user_state_with_preferences = state.user_state.with_preferences(preferences)
|
||||
state = States::State.new(user_state_with_preferences, speckle_state, sketchup_state, false)
|
||||
state = States::State.new(user_state_with_preferences, speckle_state, sketchup_state, false,
|
||||
worker, &instant_message_sender)
|
||||
# This is where we attach observers to related model objects like selection, entities..
|
||||
Actions::LoadSketchupModel.update_state(state, sketchup_state.sketchup_model)
|
||||
end
|
||||
@@ -4,7 +4,7 @@ require_relative 'action'
|
||||
require_relative 'events/selection_event_action'
|
||||
require_relative '../sketchup_model/dictionary/speckle_schema_dictionary_handler'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleConnector3
|
||||
module Actions
|
||||
# Isolate entities that selected from mapped elements table.
|
||||
class IsolateMappingsFromTable < Action
|
||||
@@ -14,7 +14,7 @@ module SpeckleConnector
|
||||
# rubocop:disable Metrics/MethodLength
|
||||
# rubocop:disable Metrics/PerceivedComplexity
|
||||
# rubocop:disable Metrics/CyclomaticComplexity
|
||||
def self.update_state(state, data)
|
||||
def self.update_state(state, _resolve_id, data)
|
||||
sketchup_model = state.sketchup_state.sketchup_model
|
||||
|
||||
# Hide all entities first
|
||||
@@ -38,13 +38,13 @@ module SpeckleConnector
|
||||
|
||||
faces_or_edges_ids = faces_or_edges.collect { |e| e['entityId'] }
|
||||
|
||||
face_edge_flat_entities.select { |e| faces_or_edges_ids.include?(e.persistent_id) }.each do |entity|
|
||||
face_edge_flat_entities.select { |e| faces_or_edges_ids.include?(e.persistent_id.to_s) }.each do |entity|
|
||||
entity.hidden = false
|
||||
end
|
||||
|
||||
comps_or_groups_ids = comps_or_groups.collect { |e| e['entityId'] }
|
||||
|
||||
comp_flat_entities.select { |e| comps_or_groups_ids.include?(e.persistent_id) }.each do |entity|
|
||||
comp_flat_entities.select { |e| comps_or_groups_ids.include?(e.persistent_id.to_s) }.each do |entity|
|
||||
if entity.is_a?(Sketchup::ComponentDefinition)
|
||||
entity.instances.each do |instance|
|
||||
instance.hidden = false
|
||||