Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6053d3eac1 | |||
| 529830f36b | |||
| 505cf6265c | |||
| 8cd9673eec | |||
| ac9cb28558 | |||
| 6eefe0698c | |||
| d0113532b6 | |||
| 5a1d2ad5f4 | |||
| dfe02f4c74 | |||
| 5349d556b9 | |||
| 7f7d8a501b | |||
| cbee0e465b | |||
| faf00f0b0d | |||
| fa97da5781 | |||
| e7bab546db | |||
| e2f4a30b5b | |||
| ccff1df041 | |||
| 2037cfc25a | |||
| 268a091d8a | |||
| 6b52dfab3e | |||
| 839999851f | |||
| a87470b7b5 |
@@ -48,7 +48,9 @@ module SpeckleConnector
|
||||
# @param obj [Object] speckle commit object.
|
||||
def receive_commit_object(obj, model_preferences)
|
||||
# First create layers on the sketchup before starting traversing
|
||||
create_layers(obj.keys.filter_map { |key| key if key.start_with?('@') }, sketchup_model.layers)
|
||||
filtered_layer_containers = obj.keys.filter_map { |key| key if key.start_with?('@') && key != '@Named Views' }
|
||||
create_layers(filtered_layer_containers, sketchup_model.layers)
|
||||
create_views(obj.filter_map { |key, value| value if key == '@Named Views' }, sketchup_model)
|
||||
# Define default commit layer which is the fallback
|
||||
default_commit_layer = sketchup_model.layers.layers.find { |layer| layer.display_name == '@Untagged' }
|
||||
traverse_commit_object(obj, sketchup_model.layers, default_commit_layer, model_preferences)
|
||||
@@ -70,6 +72,23 @@ module SpeckleConnector
|
||||
create_folder_layers(folder_layer_arrays, folder)
|
||||
end
|
||||
|
||||
# @param views [Array] views.
|
||||
# @param sketchup_model [Sketchup::Model] active sketchup model.
|
||||
def create_views(views, sketchup_model)
|
||||
return if views.empty?
|
||||
|
||||
views.first.each do |view|
|
||||
origin = view['origin']
|
||||
target = view['target']
|
||||
origin = SpeckleObjects::Geometry::Point.to_native(origin['x'], origin['y'], origin['z'], origin['units'])
|
||||
target = SpeckleObjects::Geometry::Point.to_native(target['x'], target['y'], target['z'], target['units'])
|
||||
# Set camera position before creating scene on it.
|
||||
my_camera = Sketchup::Camera.new(origin, target, [0, 0, 1], !view['isOrthogonal'], view['lens'])
|
||||
sketchup_model.active_view.camera = my_camera
|
||||
sketchup_model.pages.add(view['name'])
|
||||
end
|
||||
end
|
||||
|
||||
# @param headless_layers [Array<String>] headless layer names.
|
||||
# @param folder [Sketchup::Layers, Sketchup::LayerFolder] layer folder to create commit layers under it.
|
||||
def create_headless_layers(headless_layers, folder)
|
||||
|
||||
@@ -4,9 +4,11 @@ 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/built_elements/view3d'
|
||||
|
||||
module SpeckleConnector
|
||||
module Converters
|
||||
@@ -30,9 +32,48 @@ module SpeckleConnector
|
||||
end
|
||||
# send only layers that have any object
|
||||
base_object_properties = layers.reject { |_layer_name, objects| objects.empty? }
|
||||
add_views(base_object_properties) if sketchup_model.pages.any?
|
||||
SpeckleObjects::Base.with_detached_layers(base_object_properties)
|
||||
end
|
||||
|
||||
# Add views from pages.
|
||||
# @param base_object_properties [Hash] dynamically attached base object properties.
|
||||
# rubocop:disable Metrics/AbcSize
|
||||
# rubocop:disable Metrics/MethodLength
|
||||
def add_views(base_object_properties)
|
||||
views = []
|
||||
sketchup_model.pages.each do |page|
|
||||
cam = page.camera
|
||||
origin = SpeckleObjects::Geometry::Point.new(
|
||||
SpeckleObjects::Geometry.length_to_speckle(cam.eye[0], @units),
|
||||
SpeckleObjects::Geometry.length_to_speckle(cam.eye[1], @units),
|
||||
SpeckleObjects::Geometry.length_to_speckle(cam.eye[2], @units),
|
||||
@units
|
||||
)
|
||||
target = SpeckleObjects::Geometry::Point.new(
|
||||
SpeckleObjects::Geometry.length_to_speckle(cam.target[0], @units),
|
||||
SpeckleObjects::Geometry.length_to_speckle(cam.target[1], @units),
|
||||
SpeckleObjects::Geometry.length_to_speckle(cam.target[2], @units),
|
||||
@units
|
||||
)
|
||||
direction = SpeckleObjects::Geometry::Vector.new(
|
||||
SpeckleObjects::Geometry.length_to_speckle(cam.direction[0], @units),
|
||||
SpeckleObjects::Geometry.length_to_speckle(cam.direction[1], @units),
|
||||
SpeckleObjects::Geometry.length_to_speckle(cam.direction[2], @units),
|
||||
@units
|
||||
)
|
||||
view = SpeckleObjects::BuiltElements::View3d.new(
|
||||
page.name,
|
||||
origin, target, direction, SpeckleObjects::Geometry::Vector.new(0, 0, 1, @units),
|
||||
cam.perspective?, cam.fov, @units, page.name
|
||||
)
|
||||
views.append(view)
|
||||
end
|
||||
base_object_properties['@Named Views'] = views
|
||||
end
|
||||
# rubocop:enable Metrics/AbcSize
|
||||
# rubocop:enable Metrics/MethodLength
|
||||
|
||||
# Serialized and traversed information to send batches.
|
||||
# @param base [SpeckleObjects::Base] base object to serialize.
|
||||
# @return [String, Integer, Array<Object>] base id, total_children_count of base and batches
|
||||
|
||||
@@ -10,6 +10,7 @@ module SpeckleConnector
|
||||
module Preferences
|
||||
include Immutable::ImmutableUtils
|
||||
DICT_HANDLER = SketchupModel::Dictionary::SpeckleModelDictionaryHandler
|
||||
DEFAULT_PREFERENCES = "('configSketchup', '{\"DarkTheme\":false}');"
|
||||
|
||||
# @param sketchup_model [Sketchup::Model] active model.
|
||||
# rubocop:disable Metrics/MethodLength
|
||||
@@ -17,8 +18,13 @@ module SpeckleConnector
|
||||
# Init sqlite database
|
||||
db = Sqlite3::Database.new(SPECKLE_CONFIG_DB_PATH)
|
||||
|
||||
# Check configSketchup key is valid or not, otherwise init with default settings
|
||||
if db.exec("SELECT content FROM 'objects' WHERE hash = 'configSketchup'").empty?
|
||||
db.exec("INSERT INTO 'objects' VALUES #{DEFAULT_PREFERENCES}")
|
||||
end
|
||||
|
||||
# Select data
|
||||
data = db.exec("SELECT content FROM 'objects' WHERE hash = 'configDUI'").first.first
|
||||
data = db.exec("SELECT content FROM 'objects' WHERE hash = 'configSketchup'").first.first
|
||||
|
||||
# Parse string to hash
|
||||
data_hash = JSON.parse(data).to_h
|
||||
|
||||
@@ -28,7 +28,10 @@ module SpeckleConnector
|
||||
dictionaries.each do |dict_name, entries|
|
||||
dict_name = dict_name == 'empty_dictionary_name' ? '' : dict_name
|
||||
JSON.parse(entries).each do |key, value|
|
||||
entity.set_attribute(dict_name, key, value)
|
||||
set_attribute(entity, key, value, dict_name)
|
||||
rescue StandardError => e
|
||||
puts("Failed to write key: #{key} value: #{value} to dictionary #{dict_name}")
|
||||
puts(e)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../base'
|
||||
require_relative '../../speckle_objects/geometry/point'
|
||||
require_relative '../../speckle_objects/geometry/vector'
|
||||
|
||||
module SpeckleConnector
|
||||
module SpeckleObjects
|
||||
module BuiltElements
|
||||
# View3d object represents scenes on Sketchup.
|
||||
class View3d < Base
|
||||
SPECKLE_TYPE = 'Objects.BuiltElements.View:Objects.BuiltElements.View3D'
|
||||
|
||||
# @param name [String] name of the scene
|
||||
# @param origin [SpeckleObjects::Geometry::Point] origin (eye) of the view.
|
||||
# @param target [SpeckleObjects::Geometry::Point] target of the view.
|
||||
# @param direction [SpeckleObjects::Geometry::Vector] direction of the view from eye to target.
|
||||
# @param up_direction [SpeckleObjects::Geometry::Vector] up direction of the view.
|
||||
# @param is_perspective [Boolean] whether view is perspective or not.
|
||||
# @param lens [Boolean] fov value of the view camera.
|
||||
# @param units [String] units of the camera.
|
||||
# @param application_id [String] application_id of the view.
|
||||
# rubocop:disable Metrics/ParameterLists
|
||||
def initialize(name, origin, target, direction, up_direction,
|
||||
is_perspective, lens, units, application_id)
|
||||
super(
|
||||
speckle_type: SPECKLE_TYPE,
|
||||
total_children_count: 0,
|
||||
application_id: application_id,
|
||||
id: nil
|
||||
)
|
||||
self[:name] = name
|
||||
self[:origin] = origin
|
||||
self[:target] = target
|
||||
self[:forwardDirection] = direction
|
||||
self[:upDirection] = up_direction
|
||||
self[:isOrthogonal] = !is_perspective
|
||||
self[:lens] = lens
|
||||
self[:units] = units
|
||||
end
|
||||
# rubocop:enable Metrics/ParameterLists
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
+3
-3
@@ -80,7 +80,7 @@
|
||||
</v-menu>
|
||||
</v-app-bar>
|
||||
|
||||
<create-stream v-if="accounts().length !== 0"/>
|
||||
<create-stream-dialog v-if="accounts().length !== 0"/>
|
||||
|
||||
<v-container v-if="accounts().length !== 0" fluid>
|
||||
<router-view :stream-search-query="streamSearchQuery" />
|
||||
@@ -129,8 +129,8 @@ export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
Login,
|
||||
CreateStream: () => import('@/components/CreateStream'),
|
||||
SettingsDialog: () => import('@/components/SettingsDialog'),
|
||||
CreateStreamDialog: () => import('@/components/dialogs/CreateStreamDialog'),
|
||||
SettingsDialog: () => import('@/components/dialogs/SettingsDialog'),
|
||||
GlobalToast: () => import('@/components/GlobalToast')
|
||||
},
|
||||
props: {
|
||||
|
||||
@@ -60,11 +60,17 @@
|
||||
<v-card-text class="d-flex align-center pb-5 mb-5 -mt-2" style="height: 50px">
|
||||
<v-menu offset-y>
|
||||
<template #activator="{ on, attrs }">
|
||||
<v-slide-x-transition>
|
||||
<div v-show="hover">
|
||||
<create-branch-dialog :stream-name="stream.name" :stream-id="streamId"/>
|
||||
</div>
|
||||
</v-slide-x-transition>
|
||||
<v-chip v-if="stream.branches" small v-bind="attrs" class="mr-1" v-on="on">
|
||||
<v-icon small class="mr-1 float-left">mdi-source-branch</v-icon>
|
||||
{{ branchName }}
|
||||
</v-chip>
|
||||
</template>
|
||||
<!-- Branch list -->
|
||||
<v-list dense>
|
||||
<v-list-item
|
||||
v-for="(branch, index) in stream.branches.items"
|
||||
@@ -73,7 +79,7 @@
|
||||
@click="switchBranch(branch.name)"
|
||||
>
|
||||
<v-list-item-title class="text-caption font-weight-regular">
|
||||
<v-icon v-if="branch.name == branchName" small class="mr-1 float-left">
|
||||
<v-icon v-if="branch.name === branchName" small class="mr-1 float-left">
|
||||
mdi-check
|
||||
</v-icon>
|
||||
<v-icon v-else small class="mr-1 float-left">mdi-source-branch</v-icon>
|
||||
@@ -171,6 +177,9 @@ global.oneClickSend = function (streamId) {
|
||||
|
||||
export default {
|
||||
name: 'StreamCard',
|
||||
components: {
|
||||
CreateBranchDialog: () => import('@/components/dialogs/CreateBranchDialog'),
|
||||
},
|
||||
props: {
|
||||
streamId: {
|
||||
type: String,
|
||||
@@ -261,16 +270,28 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
selectedBranch() {
|
||||
if (this.$apollo.loading) return
|
||||
return this.stream.branches.items.find((branch) => branch.name == this.branchName)
|
||||
if (!this.stream) return
|
||||
return this.stream.branches.items.find((branch) => branch.name === this.branchName)
|
||||
},
|
||||
selectedCommit() {
|
||||
if (this.$apollo.loading) return
|
||||
if (this.commitId == 'latest') return this.selectedBranch.commits.items[0]
|
||||
return this.selectedBranch.commits.items.find((commit) => commit.id == this.commitId)
|
||||
if (!this.selectedBranch) return
|
||||
if (this.commitId === 'latest') return this.selectedBranch.commits.items[0]
|
||||
return this.selectedBranch.commits.items.find((commit) => commit.id === this.commitId)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
bus.$on(`refresh-stream-${this.streamId}`, () => {
|
||||
let oldBranchName = this.branchName
|
||||
let oldCommitId = this.commitId
|
||||
this.$apollo.queries.stream.refetch()
|
||||
this.branchName = oldBranchName
|
||||
this.commitId = oldCommitId
|
||||
})
|
||||
bus.$on(`create-branch-${this.streamId}`, (branchName) => {
|
||||
this.$apollo.queries.stream.refetch()
|
||||
this.branchName = branchName
|
||||
this.commitId = 'latest'
|
||||
})
|
||||
bus.$on(`sketchup-objects-${this.streamId}`, async (batches, commitId, totalChildrenCount) => {
|
||||
console.log('>>> SpeckleSketchUp: Received objects from sketchup')
|
||||
|
||||
@@ -376,7 +397,7 @@ export default {
|
||||
await this.sleep(2000)
|
||||
},
|
||||
async createCommit(batches, commitId, totalChildrenCount) {
|
||||
if (batches.length == 0) {
|
||||
if (batches.length === 0) {
|
||||
this.loadingSend = false
|
||||
this.loadingStage = null
|
||||
this.$eventHub.$emit('notification', {
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
<template>
|
||||
<!-- DIALOG: Create Branch -->
|
||||
<v-dialog v-model="showCreateBranch">
|
||||
<template #activator="{ on: dialog, attrs }">
|
||||
<v-btn
|
||||
v-tooltip="'Create Branch'"
|
||||
icon x-small class="ml-0 mr-1"
|
||||
v-bind="attrs"
|
||||
v-on="{...dialog}"
|
||||
>
|
||||
<v-icon>
|
||||
mdi-plus-circle
|
||||
</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-card>
|
||||
<v-card-title class="text-h5 mb-1">
|
||||
Create a New Branch
|
||||
</v-card-title>
|
||||
<v-card-subtitle class="py-0 my-0 font-italic">
|
||||
under {{ streamName }} stream
|
||||
</v-card-subtitle>
|
||||
<v-container class="px-6" pb-0>
|
||||
<v-text-field
|
||||
v-model="branchName"
|
||||
xxxclass="small-text-field"
|
||||
hide-details
|
||||
dense
|
||||
flat
|
||||
placeholder="Branch Name"
|
||||
/>
|
||||
<v-text-field
|
||||
v-model="description"
|
||||
xxxclass="small-text-field"
|
||||
hide-details
|
||||
dense
|
||||
flat
|
||||
placeholder="Description (Optional)"
|
||||
/>
|
||||
</v-container>
|
||||
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn
|
||||
color="blue darken-1"
|
||||
text
|
||||
@click="showCreateBranch = false"
|
||||
>
|
||||
Cancel
|
||||
</v-btn>
|
||||
<v-btn
|
||||
:disabled="branchName === ''"
|
||||
color="blue darken-1"
|
||||
text
|
||||
@click="createBranch"
|
||||
>
|
||||
Create
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import gql from "graphql-tag";
|
||||
import {bus} from "@/main";
|
||||
|
||||
export default {
|
||||
name: "CreateBranchDialog",
|
||||
props: {
|
||||
streamId: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
streamName: {
|
||||
type: String,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showCreateBranch: false,
|
||||
branchName: "",
|
||||
description: "",
|
||||
defaultDescription: "Stream created from SketchUp",
|
||||
accountToCreateStream: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
loggedIn() {
|
||||
return localStorage.getItem('SpeckleSketchup.AuthToken') !== null
|
||||
},
|
||||
accounts() {
|
||||
return JSON.parse(localStorage.getItem('localAccounts'))
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async createBranch(){
|
||||
let res = await this.$apollo.mutate({
|
||||
mutation: gql`
|
||||
mutation branchCreate($branch: BranchCreateInput!) {
|
||||
branchCreate(branch: $branch)
|
||||
}
|
||||
`,
|
||||
variables: {
|
||||
branch: {
|
||||
streamId: this.streamId,
|
||||
name: this.branchName,
|
||||
description: this.description === '' ? this.defaultDescription : this.description,
|
||||
}
|
||||
}
|
||||
})
|
||||
bus.$emit(`create-branch-${this.streamId}`, this.branchName)
|
||||
this.showCreateBranch = false
|
||||
this.branchName = ""
|
||||
this.description = ""
|
||||
this.$mixpanel.track('Connector Action', { name: 'Create Branch' })
|
||||
return res
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
.v-dialog {
|
||||
max-width: 390px
|
||||
}
|
||||
|
||||
.v-text-field >>> input {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.v-text-field >>> label {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
</style>
|
||||
+2
-1
@@ -161,7 +161,7 @@ import {bus} from "@/main";
|
||||
import userQuery from "@/graphql/user.gql";
|
||||
|
||||
export default {
|
||||
name: "CreateStream",
|
||||
name: "CreateStreamDialog",
|
||||
data() {
|
||||
return {
|
||||
showCreateNewStream: false,
|
||||
@@ -216,6 +216,7 @@ export default {
|
||||
this.showCreateNewStream = false
|
||||
this.streamName = ""
|
||||
this.description = ""
|
||||
this.$mixpanel.track('Connector Action', { name: 'Create Stream' })
|
||||
sketchup.exec({name: "save_stream", data: {stream_id: res["data"]["streamCreate"]}})
|
||||
this.refresh()
|
||||
return res
|
||||
@@ -122,14 +122,11 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
combineFacesByMaterialHandler() {
|
||||
|
||||
},
|
||||
switchTheme() {
|
||||
this.$vuetify.theme.dark = !this.$vuetify.theme.dark
|
||||
sketchup.exec({
|
||||
name: "user_preferences_updated",
|
||||
data: {preference_hash: "configDUI", preference: "DarkTheme", value: this.$vuetify.theme.dark}
|
||||
data: {preference_hash: "configSketchup", preference: "DarkTheme", value: this.$vuetify.theme.dark}
|
||||
})
|
||||
this.$mixpanel.track('Connector Action', { name: 'Toggle Theme' })
|
||||
},
|
||||
@@ -73,7 +73,9 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
bus.$on('refresh-streams', () => {
|
||||
// TODO: We should remember selected branches and commits before refetch
|
||||
this.$apollo.queries.streams.refetch()
|
||||
// TODO: We should set previously selected branches and commits after refetch
|
||||
})
|
||||
|
||||
bus.$on('set-saved-streams', (streamIds) => {
|
||||
|
||||
Reference in New Issue
Block a user