Compare commits

...

35 Commits

Author SHA1 Message Date
izzy lyseggen a8955a435f chore(deps): objectloader 2.3.0 and update others (#29)
closes 📨 Receiving fails if objects have nulls #28
2022-01-13 07:21:33 -08:00
izzylys 80f25eb1a2 fix(batching): simplify slightly
also fix a transition vs transition-group warning
2022-01-12 12:26:37 -08:00
izzylys 5716f92fbf fix(accts): sqlite gem loading 2022-01-06 09:13:45 -08:00
izzylys 63e7aaa661 feat(ui): send progress 2022-01-05 12:15:56 -08:00
izzylys 7234a4be79 feat(auth): log some info to see what's goin on 2022-01-05 12:15:31 -08:00
izzylys e1cceb9bba chore: readme typo and some clenaup 2022-01-05 07:09:53 -08:00
izzy lyseggen 30157b5ac2 feat(ui): animations were TOO FAST 4 ALA 🏃‍♀️ 2021-12-08 15:49:50 +00:00
izzy lyseggen f9b1628c18 Merge pull request #26 from specklesystems/izzy/ui-tweaks
feat(ui): cute lil animations 4 smooth commitmsgs
2021-12-08 15:33:21 +00:00
izzy lyseggen 9429a11fa7 feat(ui): cute lil animations 4 smooth commitmsgs 2021-12-08 15:31:53 +00:00
izzy lyseggen af4c6d9f71 Merge pull request #24 from specklesystems/izzy/nested-def-fix
fix(convert): `to_native` nested block fix
2021-12-03 18:04:22 +00:00
izzy lyseggen a4f23e060c fix(convert): to_native nested block fix
block definitions nested within definitions that also contain meshes
alongside those definitions were not getting picked up

fixes #23
2021-12-03 18:00:53 +00:00
izzy lyseggen d2099c98e0 Merge pull request #22 from specklesystems/izzy/ui
feat(ui): add commit messages
2021-12-03 11:40:01 +00:00
izzy lyseggen c21b51135a feat(ui): add commit messages
closes UI Improvements #4
2021-12-03 11:39:18 +00:00
izzy lyseggen c5c8bf6b6f Merge pull request #21 from specklesystems/izzy/transforms-rework
feat(converter): new transform style
2021-12-02 17:30:32 +00:00
izzy lyseggen d9a92e90ec feat(convert): receive both old and new transform blocsk 2021-12-02 17:28:38 +00:00
izzy lyseggen 79ae201646 feat(convert): new transform to speckle 2021-12-01 17:58:39 +00:00
izzy lyseggen 01b32d2558 Merge pull request #19 from specklesystems/izzy/platform-fix
fix(connector): speckle dir on macos
2021-11-24 11:34:54 +00:00
izzy lyseggen b3067aa346 fix(connector): speckle dir on macos
thanks @ruggieroguida !
addresses #18
2021-11-23 16:13:03 +00:00
izzy lyseggen d1349c5df1 Merge pull request #16 from specklesystems/izzy/kill-insertion-pt
feat(converter): depreciate insertion point
2021-11-17 15:30:03 +00:00
izzy lyseggen d44365a6d4 feat(converter): depreciate insertion point 2021-11-17 15:29:16 +00:00
izzy lyseggen c8c94184df Merge pull request #15 from specklesystems/izzy/blocks
fix(converter): receiving blocks
2021-11-16 15:57:51 +00:00
izzy lyseggen 62c436131c fix(converter): receiving blocks
WE OUT HERE BOIIIII
📦 Block Receive Failing #10
2021-11-16 15:52:52 +00:00
izzy lyseggen ac3579de46 Merge pull request #14 from specklesystems/izzy/blocks
fix(converter): revert mesh squish & fix closed polylines
2021-11-16 10:55:01 +00:00
izzy lyseggen e7a72b25d7 fix(converter): revert mesh squish 2021-11-16 10:54:00 +00:00
izzy lyseggen 6d155d987a fix(converter): only return component def if exists 2021-11-15 17:30:47 +00:00
izzy lyseggen e4a78e4c6e feat(converter): add explicit brep to native mesh 2021-11-15 17:30:27 +00:00
izzy lyseggen 35c819dab0 fix(convert): closed polylines 2021-11-15 16:55:50 +00:00
izzy lyseggen 3001a4af48 Merge pull request #13 from specklesystems/izzy/mesh-experiments
feat(converter): improved meshes!
2021-11-15 14:59:39 +00:00
izzy lyseggen eeaa69e7b4 feat(convert): mesh to native polycount cleanup 2021-11-15 14:58:51 +00:00
izzy lyseggen 5717022293 chore: pls leave me alone rubocop 2021-11-15 14:51:18 +00:00
izzy lyseggen b5c1ad1ea3 feat(convert): additional mesh improvements 2021-11-12 11:34:39 +00:00
izzy lyseggen ea56717594 fix(convert): simple line fixes 2021-11-12 11:33:58 +00:00
izzy lyseggen 2ffb4219fc feat(convert): initial mesh squish fix
🍙 Remove duplicate vertices when building meshes `to_speckle` #12
2021-11-11 17:48:56 +00:00
izzy lyseggen 08843689ec feat(ui): move read receipt to end of receive method 2021-11-10 16:22:33 +00:00
izzy lyseggen 299109505c feat(ui): Sketchup: Add Read receipts call #7 2021-11-10 16:06:54 +00:00
12 changed files with 7624 additions and 3369 deletions
+3
View File
@@ -26,6 +26,9 @@ Style/DocumentationMethod:
Metrics/AbcSize:
Enabled: false
Metrics/BlockLength:
Enabled: false
Metrics/ClassLength:
Enabled: false
+3 -3
View File
@@ -77,15 +77,15 @@ This should have also have set up the package installer `gem` and interactive ru
gem -v
irb -v
Let's also install our first gem `bundle` which is a package manager that will help us with development.
Let's also install our first gem `bundler` which is a package manager that will help us with development.
gem install bundle
gem install bundler
### Editor Setup
Clone this repo and run:
bundle install
bundler install
This will install all the necessary packages for the connector.
-59
View File
@@ -1,59 +0,0 @@
require "net/http"
require "json"
require "uri"
server = "https://latest.speckle.dev"
token = "1dc2e3330a56371dc9011e5bed406264c9e65dd355"
limit = 20
streams_list = "
query User {
user {
id
email
name
bio
company
avatar
verified
profiles
role
streams(limit: #{limit}) {
totalCount
cursor
items {
id
name
description
isPublic
createdAt
updatedAt
collaborators {
id
name
role
}
}
}
}
}
"
endpoint = URI("#{server}/graphql")
res =
::Net::HTTP.start(endpoint.host, endpoint.port, use_ssl: true) do |http|
req = ::Net::HTTP::Post.new(endpoint)
req["Content-Type"] = "application/json"
req["Authorization"] = "Bearer #{token}"
# The body needs to be a JSON string.
req.body = ::JSON[{ query: streams_list }]
puts(req.body)
http.request(req)
end
streams = ::JSON.parse(res.body)["data"]["user"]["streams"]["items"]
puts(streams)
+9 -12
View File
@@ -5,7 +5,6 @@ begin
rescue LoadError
# ty msp-greg! https://github.com/MSP-Greg/SUMisc/releases/tag/sqlite3-mingw-1
Gem.install(File.join(File.dirname(File.expand_path(__FILE__)), "utils/sqlite3-1.4.2.mspgreg-x64-mingw32.gem"))
else
require("sqlite3")
end
@@ -33,22 +32,20 @@ module SpeckleSystems::SpeckleConnector
end
def self._get_speckle_dir
platform = RUBY_PLATFORM.downcase
speckle_dir =
if platform =~ (/mingw/) || platform =~ (/win/)
# win
File.join(Dir.home, "AppData/Roaming/Speckle")
elsif platform =~ /linux/
# linux
File.expand_path("~/.local/share/Speckle")
case Sketchup.platform
when :platform_win then File.join(Dir.home, "AppData/Roaming/Speckle")
when :platform_osx then File.join(Dir.home, ".config", "Speckle")
else
# mac
File.expand_path("~/.config/Speckle")
nil
end
return speckle_dir if Dir.exist?(speckle_dir)
raise(IOError, "No Speckle Directory exists. Please read the guide to get Speckle set up on your machine: \nhttps://speckle.guide/user/manager.html")
raise(
IOError,
"No Speckle Directory exists. Please read the guide to get Speckle set up on your machine: \nhttps://speckle.guide/user/manager.html"
)
end
end
end
+42 -38
View File
@@ -6,6 +6,7 @@ module SpeckleSystems::SpeckleConnector::ToNative
if can_convert_to_native(obj)
convert_to_native(obj, Sketchup.active_model.entities)
elsif obj.is_a?(Hash) && obj.key?("speckle_type")
puts(">>> Found #{obj["speckle_type"]}: #{obj["id"]}")
props = obj.keys.filter_map { |key| key unless key.start_with?("_") }
props.each { |prop| traverse_commit_object(obj[prop]) }
elsif obj.is_a?(Hash)
@@ -24,6 +25,7 @@ module SpeckleSystems::SpeckleConnector::ToNative
"Objects.Geometry.Line",
"Objects.Geometry.Polyline",
"Objects.Geometry.Mesh",
"Objects.Geometry.Brep",
"Objects.Other.BlockInstance",
"Objects.Other.BlockDefinition",
"Objects.Other.RenderMaterial"
@@ -36,6 +38,7 @@ module SpeckleSystems::SpeckleConnector::ToNative
when "Objects.Other.BlockInstance" then component_instance_to_native(obj, entities)
when "Objects.Other.BlockDefinition" then component_definition_to_native(obj)
when "Objects.Geometry.Mesh" then mesh_to_native(obj, entities)
when "Objects.Geometry.Brep" then mesh_to_native(obj["displayMesh"], entities)
else
nil
end
@@ -50,11 +53,16 @@ module SpeckleSystems::SpeckleConnector::ToNative
end
def edge_to_native(line, entities)
return unless line.key?("value")
values = line["value"]
points = values.each_slice(3).to_a.map { |pt| point_to_native(pt[0], pt[1], pt[2], line["units"]) }
entities.add_edges(*points)
if line.key?("value")
values = line["value"]
points = values.each_slice(3).to_a.map { |pt| point_to_native(pt[0], pt[1], pt[2], line["units"]) }
points.push(points[0]) if line["closed"]
entities.add_edges(*points)
else
start_pt = point_to_native(line["start"]["x"], line["start"]["y"], line["start"]["z"], line["units"])
end_pt = point_to_native(line["end"]["x"], line["end"]["y"], line["end"]["z"], line["units"])
entities.add_edges(start_pt, end_pt)
end
end
def face_to_native
@@ -65,9 +73,28 @@ module SpeckleSystems::SpeckleConnector::ToNative
Geom::Point3d.new(length_to_native(x, units), length_to_native(y, units), length_to_native(z, units))
end
def mesh_to_native(mesh, entities)
native_mesh = Geom::PolygonMesh.new(mesh["vertices"].count / 3)
points = []
mesh["vertices"].each_slice(3) do |pt|
points.push(point_to_native(pt[0], pt[1], pt[2], mesh["units"]))
end
faces = mesh["faces"]
while faces.count.positive?
num_pts = faces.shift
# 0 -> 3, 1 -> 4 to preserve backwards compatibility
num_pts += 3 if num_pts < 3
indices = faces.shift(num_pts)
native_mesh.add_polygon(indices.map { |index| points[index] })
end
entities.add_faces_from_mesh(native_mesh, 4, material_to_native(mesh["renderMaterial"]))
native_mesh
end
def component_definition_to_native(block_def)
definition = Sketchup.active_model.definitions[block_def["name"]]
return definition if definition&.guid == block_def["applicationId"]
return definition if definition && (definition.name == block_def["name"] || definition.guid == block_def["applicationId"])
definition&.entities&.clear!
definition ||= Sketchup.active_model.definitions.add(block_def["name"])
@@ -77,47 +104,24 @@ module SpeckleSystems::SpeckleConnector::ToNative
definition
end
def mesh_to_native(mesh, entities)
native_mesh = Geom::PolygonMesh.new
points = [] # to preserve indices - duplicate points won't be added in `point_to_native`
mesh["vertices"].each_slice(3) do |pt|
points.push(point_to_native(pt[0], pt[1], pt[2], mesh["units"]))
end
faces = mesh["faces"]
while faces.count.positive?
size = faces.shift
num_pts =
case size
when 0 then 3
when 1 then 4
else size
end
indices = faces.shift(num_pts)
native_mesh.add_polygon(indices.map { |index| points[index] })
end
entities.add_faces_from_mesh(native_mesh, 4, material_to_native(mesh["renderMaterial"]))
native_mesh
end
def component_instance_to_native(block, entities)
is_group = block.key?("is_sketchup_group") && block["is_sketchup_group"]
# is_group = block.key?("is_sketchup_group") && block["is_sketchup_group"]
# something about this conversion is freaking out if nested block geo is a group
# so this is set to false always until I can figure this out
is_group = false
definition = component_definition_to_native(block["blockDefinition"])
# return unless definition.entities.count.positive?
transform = transform_to_native(block["transform"], block["units"])
transform = transform_to_native(
block["transform"].is_a?(Hash) ? block["transform"]["value"] : block["transform"],
block["units"]
)
instance =
if is_group
entities.add_group(definition.entities.to_a)
else
entities.add_instance(definition, transform)
end
puts("Failed to create instance for speckle object #{block["id"]}") if instance.nil?
if instance.nil?
p(definition.name)
p(definition.entities.to_a)
end
puts("Failed to create instance for speckle block instance #{block["id"]}") if instance.nil?
instance.transformation = transform if is_group
instance.material = material_to_native(block["renderMaterial"])
instance
+29 -12
View File
@@ -40,7 +40,6 @@ module SpeckleSystems::SpeckleConnector::ToSpeckle
def component_instance_to_speckle(instance, is_group: false)
transform = instance.transformation
origin = transform.origin
{
speckle_type: "Objects.Other.BlockInstance",
applicationId: instance.guid,
@@ -50,17 +49,19 @@ module SpeckleSystems::SpeckleConnector::ToSpeckle
name: instance.name,
renderMaterial: instance.material.nil? ? nil : material_to_speckle(instance.material),
transform: transform_to_speckle(transform),
insertionPoint: speckle_point(origin[0], origin[1], origin[2]),
"@blockDefinition" => component_definition_to_speckle(instance.definition)
}
end
def group_mesh_to_speckle(component_def)
mat_groups = {}
nested_blocks = []
component_def.entities.each do |face|
next unless face.typename == "Face"
component_def.entities.each do |entity|
nested_blocks.push(component_instance_to_speckle(entity)) if entity.typename == "ComponentInstance"
next unless entity.typename == "Face"
face = entity
# convert material
mat_id = face.material.nil? ? "none" : face.material.entityID
mat_groups[mat_id] = initialise_group_mesh(face, component_def.bounds) unless mat_groups.key?(mat_id)
@@ -76,17 +77,33 @@ module SpeckleSystems::SpeckleConnector::ToSpeckle
end
mat_groups.values.map { |group| group.delete(:pt_count) }
mat_groups.values
mat_groups.values + nested_blocks
end
def transform_to_speckle(transform)
t_arr = transform.to_a
[
t_arr[0], t_arr[4], t_arr[8], length_to_speckle(t_arr[12]),
t_arr[1], t_arr[5], t_arr[9], length_to_speckle(t_arr[13]),
t_arr[2], t_arr[6], t_arr[10], length_to_speckle(t_arr[14]),
t_arr[3], t_arr[7], t_arr[11], t_arr[15]
]
{
speckle_type: "Objects.Other.Transform",
units: @units,
value: [
t_arr[0],
t_arr[4],
t_arr[8],
length_to_speckle(t_arr[12]),
t_arr[1],
t_arr[5],
t_arr[9],
length_to_speckle(t_arr[13]),
t_arr[2],
t_arr[6],
t_arr[10],
length_to_speckle(t_arr[14]),
t_arr[3],
t_arr[7],
t_arr[11],
t_arr[15]
]
}
end
def initialise_group_mesh(face, bounds)
@@ -97,7 +114,7 @@ module SpeckleSystems::SpeckleConnector::ToSpeckle
"@(31250)vertices" => [],
"@(62500)faces" => [],
"@(31250)textureCoordinates" => [],
pt_count: -1, # faces are 1 indexed
pt_count: -1,
renderMaterial: face.material.nil? ? nil : material_to_speckle(face.material)
}
end
+2
View File
@@ -81,10 +81,12 @@ module SpeckleSystems::SpeckleConnector
end
def self.init_local_accounts
puts("Initialisation of Speckle accounts requested by plugin")
@dialog.execute_script("loadAccounts(#{Accounts.load_accounts.to_json}, #{Accounts.get_suuid.to_json})")
end
def self.reload_accounts
puts("Reload of Speckle accounts requested by plugin")
@dialog.execute_script("loadAccounts(#{Accounts.load_accounts.to_json})")
end
end
+7437 -3216
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -9,7 +9,7 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"@speckle/objectloader": "^2.1.1",
"@speckle/objectloader": "^2.3.0",
"aws-sdk": "^2.981.0",
"core-js": "^3.6.5",
"debounce": "^1.2.1",
+1
View File
@@ -96,6 +96,7 @@ import userQuery from './graphql/user.gql'
import { onLogin } from './vue-apollo'
global.loadAccounts = function (accounts, suuid) {
console.log('>>> SpeckleSketchup: Loading accounts', accounts, `suuid: ${suuid}`)
localStorage.setItem('localAccounts', JSON.stringify(accounts))
if (suuid) {
localStorage.setItem('suuid', suuid)
+92 -23
View File
@@ -15,14 +15,12 @@
<v-card-text class="transparent elevation-0 mt-0 pt-0" dense>
<div class="text-caption">
Updated
<timeago :datetime="stream.updatedAt" />
<timeago class="mr-1" :datetime="stream.updatedAt" />
|
<v-icon class="ml-1" small>mdi-account-key-outline</v-icon>
{{ stream.role.split(':')[1] }}
</div>
<v-toolbar-title>
<v-chip v-if="stream.role" small class="mr-1">
<v-icon small left>mdi-account-key-outline</v-icon>
{{ stream.role.split(':')[1] }}
</v-chip>
<v-menu offset-y>
<template #activator="{ on, attrs }">
<v-chip v-if="stream.branches" small v-bind="attrs" class="mr-1" v-on="on">
@@ -150,13 +148,29 @@
</v-tooltip>
</v-col>
</v-row>
<v-progress-linear
v-if="(loadingSend || loadingReceive) && loadingStage"
height="14"
indeterminate
>
<div class="text-caption">{{ loadingStage }}</div>
</v-progress-linear>
<transition-group name="expand">
<v-card-text v-if="hover && !$apollo.loading" key="commit-message-field" class="mt-0 pt-0">
<transition name="fade">
<v-text-field
v-model="commitMessage"
class="small-text-field"
hide-details
dense
flat
label="Commit Message"
placeholder="Write your commit message here"
></v-text-field>
</transition>
</v-card-text>
<v-progress-linear
v-if="(loadingSend || loadingReceive) && loadingStage"
key="progress-bar"
height="14"
indeterminate
>
<div class="text-caption">{{ loadingStage }}</div>
</v-progress-linear>
</transition-group>
</v-card>
</v-hover>
</template>
@@ -195,7 +209,8 @@ export default {
loadingReceive: false,
loadingStage: null,
branchName: 'main',
commitId: 'latest'
commitId: 'latest',
commitMessage: null
}
},
apollo: {
@@ -278,19 +293,19 @@ export default {
},
mounted() {
bus.$on(`sketchup-objects-${this.streamId}`, async (objects) => {
console.log('received objects from sketchup', objects)
console.log('>>> SpeckleSketchUp: Received objects from sketchup')
await this.createCommit(objects)
})
bus.$on(`sketchup-received-${this.streamId}`, () => {
console.log('finished receiving in sketchup', this.streamId)
console.log('>>> SpeckleSketchUp: Finished receiving in sketchup', this.streamId)
this.loadingReceive = false
this.loadingStage = null
})
bus.$on(`sketchup-fail-${this.streamId}`, () => {
this.$matomo && this.$matomo.setCustomUrl(`http://connectors/SketchUp/stream/fail`)
this.$matomo && this.$matomo.trackPageView(`stream/fail`)
console.log('sketchup operation failed', this.streamId)
console.log('>>> SpeckleSketchUp: operation failed', this.streamId)
this.loadingReceive = this.loadingSend = false
this.loadingStage = null
})
@@ -332,7 +347,24 @@ export default {
let rootObj = await loader.getAndConstructObject(this.updateLoadingStage)
console.log(rootObj)
sketchup.receive_objects(rootObj, this.streamId)
await this.$apollo.mutate({
mutation: gql`
mutation commitReceive($input: CommitReceivedInput!) {
commitReceive(input: $input)
}
`,
variables: {
input: {
sourceApplication: 'sketchup',
streamId: this.streamId,
commitId: this.selectedCommit.id
}
}
})
this.loadingStage = 'converting'
},
updateLoadingStage({ stage }) {
@@ -344,7 +376,7 @@ export default {
this.$matomo && this.$matomo.setCustomUrl(`http://connectors/SketchUp/send`)
this.$matomo && this.$matomo.trackPageView(`send`)
sketchup.send_selection(this.streamId)
console.log('request for data sent to sketchup')
console.log('>>> SpeckleSketchUp: Objects requested from SketchUp')
await this.sleep(2000)
},
async createCommit(objects) {
@@ -362,16 +394,21 @@ export default {
this.loadingStage = 'uploading'
this.loadingSend = true
let batches = s.batchObjects()
const totBatches = batches.length
console.log(`>>> SpeckleSketchUp: ${totBatches} batches ready for sending`)
let batchesSent = 0
for (const batch of batches) {
let res = await this.sendBatch(batch)
if (res.status !== 201) throw `Upload request failed: ${res}`
if (res.status !== 201) throw `Upload request failed: ${res.status}`
batchesSent++
this.loadingStage = `uploading: ${Math.round((batchesSent / totBatches) * 100)}%`
}
let commit = {
streamId: this.streamId,
branchName: this.branchName,
objectId: hash,
message: 'sent from sketchup',
message: this.commitMessage ?? 'sent from sketchup',
sourceApplication: 'sketchup',
totalChildrenCount: s.objects[hash].totalChildrenCount
}
@@ -385,7 +422,7 @@ export default {
commit: commit
}
})
console.log('sent to stream: ' + this.streamId, commit)
console.log('>>> SpeckleSketchUp: Sent to stream: ' + this.streamId, commit)
this.loadingSend = false
this.loadingStage = null
@@ -397,7 +434,7 @@ export default {
},
async sendBatch(batch) {
let formData = new FormData()
formData.append(`batch-1`, new Blob([JSON.stringify(batch)], { type: 'application/json' }))
formData.append(`batch-1`, new Blob([batch], { type: 'application/json' }))
let token = localStorage.getItem('SpeckleSketchup.AuthToken')
let res = await fetch(`${localStorage.getItem('serverUrl')}/objects/${this.streamId}`, {
method: 'POST',
@@ -410,7 +447,39 @@ export default {
}
</script>
<style>
<style scoped>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.2s ease-in;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
.expand-enter-active {
transition: all 0.2s ease;
max-height: 1200px;
overflow: hidden;
}
.expand-leave-active {
transition: all 0.3s ease;
max-height: 1200px;
overflow: hidden;
}
.expand-enter,
.expand-leave-to {
max-height: 0;
opacity: 0;
}
.v-text-field >>> input {
font-size: 0.9em;
}
.v-text-field >>> label {
font-size: 0.9em;
}
.btn-fix:focus::before {
opacity: 0 !important;
}
+5 -5
View File
@@ -170,21 +170,21 @@ export class BaseObjectSerializer {
batchObjects(maxBatchSizeMb = 1) {
const maxSize = maxBatchSizeMb * 1000 * 1000
let batches = []
let batch = []
let batch = '['
let batchSize = 0
let objects = Object.values(this.objects)
objects.forEach((obj) => {
let objString = JSON.stringify(obj)
if (batchSize + objString.length < maxSize) {
batch.push(obj)
batch += objString + ','
batchSize += objString.length
} else {
batches.push(batch)
batch = [obj]
batches.push(batch.slice(0, -1) + ']')
batch = '[' + objString + ','
batchSize = objString.length
}
})
batches.push(batch)
batches.push(batch.slice(0, -1) + ']')
return batches
}