Compare commits

...

58 Commits

Author SHA1 Message Date
Oğuzhan Koral 8b824f5342 Update innosetup workflow
There were issues with innosetup workflow which does not run one powershell.exe,
so workflows splitted into chunks according to shells
2023-02-08 21:20:17 +03:00
oguzhankoral d052d5e8a1 Change set env variable to run with powershell 2023-02-08 21:12:00 +03:00
oguzhankoral 610c22dd02 Update innosetup workflow 2023-02-08 21:05:02 +03:00
Oğuzhan Koral a5496ab6a9 Feat (CI): Run CI step to create env variables for innosetup 2023-02-08 20:14:23 +03:00
oguzhankoral c29c8f009c Remove duplicated context: innosetup on yaml file 2023-02-02 10:34:34 +02:00
oguzhankoral fb7e9f2a6c Run CI step to create env variables for innosetup 2023-02-01 23:42:25 +02:00
Oğuzhan Koral 62c2bbb9fa Chore (Notification): Add error notification to GlobalToast 2023-01-23 15:34:03 +03:00
oguzhankoral 7656772194 Add error notification to GlobalToast 2023-01-23 15:31:13 +03:00
Oğuzhan Koral f22ff050e0 Fix (Stream, Attributes): Follow up fixes add stream by url and attributes 2023-01-23 12:35:22 +03:00
oguzhankoral 708f0b44fd Check face entity attributes settings before merging faces into mesh 2023-01-23 12:01:47 +03:00
oguzhankoral 2ee4581f17 Check stream role is null first before split 2023-01-23 12:00:13 +03:00
Oğuzhan Koral e337fb869f Feat (Settings) Advanced settings for entity specific attributes 2023-01-22 00:09:05 +03:00
oguzhankoral 4a8b0147e1 Create UI components for entity specific settings 2023-01-22 00:03:18 +03:00
oguzhankoral c95a1c7e1f Consider entity settings on speckle objects 2023-01-22 00:02:51 +03:00
oguzhankoral a07cd5c3f5 Extend model preferences with entity specific settings 2023-01-22 00:02:24 +03:00
Oğuzhan Koral 4d1473582e Feat (Stream): Add streams by URL or id 2023-01-21 17:33:35 +03:00
oguzhankoral 3bc9f4c452 Fix rubocop issue 2023-01-21 17:33:15 +03:00
oguzhankoral 11377038a0 Implement and make functional adding streams by url 2023-01-20 22:26:36 +03:00
Oğuzhan Koral 6053d3eac1 Fix (Attributes): Rescue from problematic dictionaries 2023-01-20 11:50:18 +03:00
oguzhankoral 529830f36b Rescue from problematic dictionaries 2023-01-20 11:47:34 +03:00
Oğuzhan Koral 505cf6265c Feat (Scene): Send and receive scenes 2023-01-19 20:09:19 +03:00
oguzhankoral 8cd9673eec Send scenes to speckle 2023-01-19 20:05:44 +03:00
oguzhankoral ac9cb28558 Receive named views as scene 2023-01-19 16:38:32 +03:00
Oğuzhan Koral 6eefe0698c Fix (Branch): Activate created branch 2023-01-19 12:17:58 +03:00
oguzhankoral d0113532b6 Activate created branch 2023-01-19 11:09:23 +03:00
Oğuzhan Koral 5a1d2ad5f4 Feat (Branch): Create branch button
Thanks Fabians for helps
2023-01-18 17:02:20 +03:00
oguzhankoral dfe02f4c74 Rename CreateBranchDialog 2023-01-18 16:58:05 +03:00
oguzhankoral 5349d556b9 Group dialogs to folder 2023-01-18 16:21:43 +03:00
oguzhankoral 7f7d8a501b Add notes about refresh 2023-01-18 15:58:43 +03:00
oguzhankoral cbee0e465b Remove unused combineFacesByMaterialHandler method 2023-01-18 15:44:20 +03:00
oguzhankoral faf00f0b0d Refetch stream on StreamCard whenever branch created 2023-01-18 15:42:33 +03:00
oguzhankoral fa97da5781 Track create stream and branch via mixpanel 2023-01-18 15:03:14 +03:00
oguzhankoral e7bab546db Remove loggings 2023-01-18 14:16:52 +03:00
oguzhankoral e2f4a30b5b Fix updating problem on created branch
- Thanks to Fabians
2023-01-18 11:53:50 +03:00
oguzhankoral ccff1df041 Add tooltip to create branch method 2023-01-18 11:53:11 +03:00
oguzhankoral 2037cfc25a Import and use CreateBranchDialog per stream card 2023-01-17 19:24:53 +03:00
oguzhankoral 268a091d8a Add dialog for branch creation 2023-01-17 19:23:44 +03:00
Oğuzhan Koral 6b52dfab3e Chore (Theming): Store light mode setting separately 2023-01-17 16:16:39 +03:00
oguzhankoral 839999851f Correct preference hash for theming 2023-01-17 16:12:21 +03:00
oguzhankoral a87470b7b5 Split Sketchup settings 2023-01-17 16:11:56 +03:00
Oğuzhan Koral e76aeb80fd Fix (attributes): Use from_face method to face consider attributes 2023-01-11 12:05:47 +03:00
oguzhankoral 28292e59e2 Use from_face method to consider attributes 2023-01-11 11:59:50 +03:00
Oğuzhan Koral 25dda481b2 Comment out vertex count log 2023-01-10 16:47:42 +03:00
Oğuzhan Koral bbda233fd8 Comment out vertex count log 2023-01-10 16:46:56 +03:00
Oğuzhan Koral 349218f0b5 Feat (Mesh): mesh improvements
Mesh grouping methods are improved with options:

Shared vertices (It is not supported by viewer currently, but when available it is ready to approach)
Separated vertices
2023-01-10 14:36:11 +03:00
oguzhankoral f18d00a69d Remove disable rubocop issues 2023-01-10 14:30:28 +03:00
oguzhankoral 25ea6504de Note about when viewer supports shared vertices 2023-01-10 11:33:56 +03:00
oguzhankoral 43081c70e2 Send vertices separately 2023-01-10 10:51:03 +03:00
oguzhankoral 0fde1c2026 Optimize meshes with dynamic vertex adding 2023-01-10 09:14:11 +03:00
Oğuzhan Koral b35383571e Merge pull request #126 from specklesystems/gergo/updateCiContext
use innosetup context in the windows build
2023-01-09 14:57:18 +03:00
Oğuzhan Koral 45a84847a2 Fix (block): Base point for block definition 2023-01-08 17:41:56 +03:00
oguzhankoral 70d92f26d6 Note for reason to having block definition base points 2023-01-08 17:40:57 +03:00
oguzhankoral 737ed86e69 Comparison method for point object 2023-01-08 15:15:17 +03:00
oguzhankoral 3865057b7a Fallback geometry for block definition 2023-01-08 14:50:47 +03:00
oguzhankoral 42a84dcd86 Receive blocks from rhino 2023-01-07 00:35:02 +03:00
Gergő Jedlicska e2d819c59d Merge branch 'main' of github.com:specklesystems/speckle-sketchup into gergo/updateCiContext 2023-01-06 14:30:16 +01:00
oguzhankoral bfee6a88dc Add base point for block definition 2023-01-06 16:28:32 +03:00
Gergő Jedlicska 46e740154e use innosetup context in the windows build 2023-01-06 14:03:50 +01:00
23 changed files with 766 additions and 160 deletions
+33 -11
View File
@@ -36,19 +36,41 @@ jobs:
- attach_workspace:
at: ./
- run:
name: Patch
name: Create Innosetup signing cert
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 }
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 }
$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
$version = "$($ver).$($env:WORKFLOW_NUM)"
python patch_version.py $semver
speckle-sharp-ci-tools\InnoSetup\ISCC.exe speckle-sharp-ci-tools\sketchup.iss
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:
@@ -65,7 +87,6 @@ jobs:
name: I know Github as a host
command: |
mkdir ~/.ssh
touch ~/.ssh/known_hosts
ssh-keyscan github.com >> ~/.ssh/known_hosts
- run:
name: Clone
@@ -123,6 +144,7 @@ workflows:
filters:
tags:
only: /.*/
context: innosetup
- deploy-manager2:
context: do-spaces-speckle-releases
@@ -9,7 +9,8 @@ module SpeckleConnector
# @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)
(saved_streams = state.sketchup_state.sketchup_model.attribute_dictionary('speckle', true)['streams']) or []
(saved_streams = state.sketchup_state.sketchup_model
.attribute_dictionary('Speckle', true)['saved_streams']) or []
state.with_add_queue('setSavedStreams', saved_streams, [])
end
end
@@ -18,10 +18,10 @@ 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)
speckle_dict = state.sketchup_state.sketchup_model.attribute_dictionary('speckle', true)
saved = speckle_dict['streams'] || []
speckle_dict = state.sketchup_state.sketchup_model.attribute_dictionary('Speckle', true)
saved = speckle_dict['saved_streams'] || []
saved -= [@stream_id]
speckle_dict['streams'] = saved
speckle_dict['saved_streams'] = saved
state
end
end
+3 -3
View File
@@ -16,10 +16,10 @@ 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)
speckle_dict = state.sketchup_state.sketchup_model.attribute_dictionary('speckle', true)
saved = speckle_dict['streams'] || []
speckle_dict = state.sketchup_state.sketchup_model.attribute_dictionary('Speckle', true)
saved = speckle_dict['saved_streams'] || []
saved = saved.empty? ? [@stream_id] : saved.unshift(@stream_id)
speckle_dict['streams'] = saved
speckle_dict['saved_streams'] = saved
state
end
end
@@ -16,11 +16,10 @@ module SpeckleConnector
# @return [States::State] the new updated state object
def update_state(state)
to_send_stream_id = state.speckle_state.stream_queue[:stream_id]
return state if to_send_stream_id == @stream_id
return state if to_send_stream_id == @stream_id || to_send_stream_id.nil?
to_send_converted = state.speckle_state.stream_queue[:converted].to_json
new_state = state.with_add_queue('convertedFromSketchup', to_send_stream_id, [to_send_converted])
new_state = new_state.with_add_queue('oneClickSend', to_send_stream_id, [])
new_state.with_empty_stream_queue
end
end
+39 -3
View File
@@ -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)
@@ -198,16 +217,30 @@ module SpeckleConnector
# rubocop:enable Metrics/MethodLength
# Creates a component definition and instance from a speckle object with a display value
# rubocop:disable Metrics/PerceivedComplexity
# rubocop:disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/MethodLength
def display_value_to_native_component(obj, layer, entities, model_preferences, &convert)
obj_id = obj['applicationId'].to_s.empty? ? obj['id'] : obj['applicationId']
block_definition = obj['@blockDefinition'] || obj['blockDefinition']
definition = BLOCK_DEFINITION.to_native(
sketchup_model,
obj['displayValue'],
layer,
"def::#{obj_id}",
obj['@blockDefinition']['always_face_camera'],
if block_definition.nil?
false
else
block_definition['always_face_camera'].nil? ? false : block_definition['always_face_camera']
end,
model_preferences,
obj['@blockDefinition']['sketchup_attributes'],
if block_definition.nil?
nil
else
block_definition['sketchup_attributes'].nil? ? nil : block_definition['sketchup_attributes']
end,
obj_id,
&convert
)
@@ -219,6 +252,9 @@ module SpeckleConnector
instance.name = obj_id
instance
end
# rubocop:enable Metrics/PerceivedComplexity
# rubocop:enable Metrics/CyclomaticComplexity
# rubocop:enable Metrics/MethodLength
# Takes a component definition and finds and erases the first instance with the matching name
# (and optionally the applicationId)
@@ -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
@@ -35,12 +41,41 @@ module SpeckleConnector
dark_theme: dark_theme
},
model: {
combine_faces_by_material: DICT_HANDLER.get_attribute(sketchup_model,
:combine_faces_by_material, 'Speckle'),
include_entity_attributes: DICT_HANDLER.get_attribute(sketchup_model,
:include_entity_attributes, 'Speckle'),
merge_coplanar_faces: DICT_HANDLER.get_attribute(sketchup_model,
:merge_coplanar_faces, 'Speckle')
combine_faces_by_material: DICT_HANDLER.get_attribute(
sketchup_model,
:combine_faces_by_material,
'Speckle'
),
include_entity_attributes: DICT_HANDLER.get_attribute(
sketchup_model,
:include_entity_attributes,
'Speckle'
),
include_face_entity_attributes: DICT_HANDLER.get_attribute(
sketchup_model,
:include_face_entity_attributes,
'Speckle'
),
include_edge_entity_attributes: DICT_HANDLER.get_attribute(
sketchup_model,
:include_edge_entity_attributes,
'Speckle'
),
include_group_entity_attributes: DICT_HANDLER.get_attribute(
sketchup_model,
:include_group_entity_attributes,
'Speckle'
),
include_component_entity_attributes: DICT_HANDLER.get_attribute(
sketchup_model,
:include_component_entity_attributes,
'Speckle'
),
merge_coplanar_faces: DICT_HANDLER.get_attribute(
sketchup_model,
:merge_coplanar_faces,
'Speckle'
)
}
}
)
@@ -62,6 +97,10 @@ module SpeckleConnector
{
combine_faces_by_material: true,
include_entity_attributes: true,
include_face_entity_attributes: true,
include_edge_entity_attributes: true,
include_group_entity_attributes: true,
include_component_entity_attributes: true,
merge_coplanar_faces: true
}
end
@@ -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
@@ -40,7 +40,7 @@ module SpeckleConnector
# @param edge [Sketchup::Edge] edge to convert line.
def self.from_edge(edge, units, model_preferences)
dictionaries = {}
if model_preferences[:include_entity_attributes]
if model_preferences[:include_entity_attributes] && model_preferences[:include_edge_entity_attributes]
dictionaries = SketchupModel::Dictionary::DictionaryHandler.attribute_dictionaries_to_speckle(edge)
end
att = dictionaries.any? ? { dictionaries: dictionaries } : {}
@@ -14,27 +14,37 @@ module SpeckleConnector
class Mesh < Base
SPECKLE_TYPE = 'Objects.Geometry.Mesh'
# @return [Array<Geom::Point3d>] points that construct mesh.
attr_accessor :vertices
# @return [Array] polygons
attr_accessor :polygons
# @return [String] speckle units.
attr_reader :units
# @param units [String] units of the speckle mesh.
# @param render_material [Other::RenderMaterial, nil] render material of the speckle mesh.
# @param bbox [Geometry::BoundingBox] bounding box speckle object of the speckle mesh.
# @param vertices [Array] vertices of the speckle mesh.
# @param faces [Array] faces of the speckle mesh.
# @param face_edge_flags [Array] face edge flags of the speckle mesh.
# @param sketchup_attributes [Hash] additional information about speckle mesh.
# rubocop:disable Metrics/ParameterLists
def initialize(units:, render_material:, bbox:, vertices:, faces:, face_edge_flags:, sketchup_attributes:)
def initialize(units:, render_material:, bbox:, vertices:, faces:, sketchup_attributes:)
super(
speckle_type: SPECKLE_TYPE,
total_children_count: 0,
application_id: nil,
id: nil
)
@vertices = []
@polygons = []
@units = units
self[:units] = units
self[:renderMaterial] = render_material
self[:bbox] = bbox
self[:'@(31250)vertices'] = vertices
self[:'@(62500)faces'] = faces
self[:'@(31250)faceEdgeFlags'] = face_edge_flags
self[:sketchup_attributes] = sketchup_attributes if sketchup_attributes.any?
end
# rubocop:enable Metrics/ParameterLists
@@ -80,36 +90,41 @@ module SpeckleConnector
# @param face [Sketchup::Face] face to convert mesh
# rubocop:disable Style/MultilineTernaryOperator
# rubocop:disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/PerceivedComplexity
def self.from_face(face, units, model_preferences)
dictionaries = {}
if model_preferences[:include_entity_attributes]
if model_preferences[:include_entity_attributes] && model_preferences[:include_face_entity_attributes]
dictionaries = SketchupModel::Dictionary::DictionaryHandler.attribute_dictionaries_to_speckle(face)
end
mesh = face.loops.count > 1 ? face.mesh : nil
has_any_soften_edge = face.edges.any?(&:soft?)
att = dictionaries.any? ? { is_soften: has_any_soften_edge, dictionaries: dictionaries }
: { is_soften: has_any_soften_edge }
Mesh.new(
speckle_mesh = Mesh.new(
units: units,
render_material: face.material.nil? && face.back_material.nil? ? nil : Other::RenderMaterial
.from_material(face.material || face.back_material),
bbox: Geometry::BoundingBox.from_bounds(face.bounds, units),
vertices: mesh.nil? ? face_vertices_to_array(face, units) : mesh_points_to_array(mesh, units),
faces: mesh.nil? ? face_indices_to_array(face, 0) : mesh_faces_to_array(mesh, -1),
face_edge_flags: mesh.nil? ? face_edge_flags_to_array(face) : mesh_edge_flags_to_array(mesh),
vertices: [], # mesh.nil? ? face_vertices_to_array(face, units) : mesh_points_to_array(mesh, units),
faces: [], # mesh.nil? ? face_indices_to_array(face, 0) : mesh_faces_to_array(mesh, -1),
# face_edge_flags: [], # mesh.nil? ? face_edge_flags_to_array(face) : mesh_edge_flags_to_array(mesh),
sketchup_attributes: att
)
speckle_mesh.face_to_mesh(face)
speckle_mesh.update_mesh
speckle_mesh
end
# rubocop:enable Style/MultilineTernaryOperator
# rubocop:enable Metrics/CyclomaticComplexity
# rubocop:enable Metrics/PerceivedComplexity
# get a flat array of vertices from a list of sketchup vertices
def self.face_vertices_to_array(face, units)
def face_to_mesh(face)
mesh = face.loops.count > 1 ? face.mesh : nil
mesh.nil? ? face_vertices_to_array(face) : mesh_points_to_array(mesh)
mesh.nil? ? face_indices_to_array(face) : mesh_faces_to_array(mesh)
end
# Collects indexed Sketchup vertices into flat array for Speckle use.
def vertices_to_array(units)
pts_array = []
face.vertices.each do |v|
pt = v.position
vertices.each do |pt|
pts_array.push(Geometry.length_to_speckle(pt[0], units),
Geometry.length_to_speckle(pt[1], units),
Geometry.length_to_speckle(pt[2], units))
@@ -117,49 +132,58 @@ module SpeckleConnector
pts_array
end
# get a flat array of vertices from a sketchup polygon mesh
def self.mesh_points_to_array(mesh, units)
pts_array = []
def update_mesh
# puts "Vertex count on mesh #{vertices.length}"
self['@(31250)vertices'] = vertices_to_array(units)
self[:'@(62500)faces'] = polygons
end
# Get a flat array of vertices from a list of sketchup vertices
# @param face [Sketchup::Face] face to get vertices.
def face_vertices_to_array(face)
face.vertices.each do |v|
pt = v.position
# FIXME: Enable previous line when viewer supports shared vertices
# vertices.push(pt) unless vertices.any? { |point| point == pt }
vertices.push(pt)
end
end
# Get a flat array of face indices from a sketchup face
def face_indices_to_array(face)
polygons.push(face.vertices.count)
face.vertices.each do |v|
pt = v.position
# FIXME: Enable previous line when viewer supports shared vertices
# global_vertex_index = vertices.reverse.find_index(pt)
global_vertex_index = vertices.length - vertices.reverse.find_index(pt) - 1
polygons.push(global_vertex_index)
end
end
# Get a flat array of vertices from a sketchup polygon mesh
# @param mesh [Geom::PolygonMesh] mesh to get points.
def mesh_points_to_array(mesh)
mesh.points.each do |pt|
pts_array.push(
Geometry.length_to_speckle(pt[0], units),
Geometry.length_to_speckle(pt[1], units),
Geometry.length_to_speckle(pt[2], units)
)
# FIXME: Enable previous line when viewer supports shared vertices
# vertices.push(pt) unless vertices.any? { |point| point == pt }
vertices.push(pt)
end
pts_array
end
# get a flat array of face indices from a sketchup face
def self.face_indices_to_array(face, offset)
face_array = [face.vertices.count]
face_array.push(*face.vertices.count.times.map { |index| index + offset })
face_array
end
# get an array of face indices from a sketchup polygon mesh
def self.mesh_faces_to_array(mesh, offset = 0)
faces = []
# Get an array of face indices from a sketchup polygon mesh
# @param mesh [Geom::PolygonMesh] mesh to convert into polygons.
def mesh_faces_to_array(mesh)
mesh.polygons.each do |poly|
faces.push(
poly.count, *poly.map { |index| index.abs + offset }
)
global_polygon_array = [poly.count]
poly.each do |index|
# FIXME: Enable previous line when viewer supports shared vertices
# global_vertex_index = vertices.reverse.find_index(mesh.points[index.abs - 1])
global_vertex_index = vertices.length - vertices.reverse.find_index(mesh.points[index.abs - 1]) - 1
global_polygon_array.push(global_vertex_index)
end
polygons.push(*global_polygon_array)
end
faces
end
def self.face_edge_flags_to_array(face)
face.outer_loop.edges.map(&:soft?)
end
def self.mesh_edge_flags_to_array(mesh)
edge_flags = []
mesh.polygons.each do |poly|
edge_flags.push(
*poly.map(&:negative?)
)
end
edge_flags
end
def self.get_soften_setting(mesh)
@@ -28,6 +28,17 @@ module SpeckleConnector
self[:units] = units
end
# Compare this point with other point those are reference to same coordinate.
# @param other [SpeckleObjects::Geometry::Point] other point to compare.
def ==(other, tolerance: 1e-15)
return false if (self[:x] - other[:x]).abs > tolerance
return false if (self[:y] - other[:y]).abs > tolerance
return false if (self[:z] - other[:z]).abs > tolerance
return false if self[:units] != other[:units]
true
end
# @param vertex [Geom::Point3d] sketchup point to convert speckle point.
# @param units [String] unit of the point.
def self.from_vertex(vertex, units)
@@ -17,11 +17,13 @@ module SpeckleConnector
SPECKLE_TYPE = 'Objects.Other.BlockDefinition'
# @param geometry [Object] geometric definition of the block.
# @param base_point [Geometry::Point] base point of the block definition.
# @param name [String] name of the block definition.
# @param units [String] units of the block definition.
# @param application_id [String, NilClass] application id of the block definition.
# rubocop:disable Metrics/ParameterLists
def initialize(geometry:, name:, units:, always_face_camera:, sketchup_attributes: {}, application_id: nil)
def initialize(geometry:, base_point:, name:, units:, always_face_camera:, sketchup_attributes: {},
application_id: nil)
super(
speckle_type: SPECKLE_TYPE,
total_children_count: 0,
@@ -30,8 +32,10 @@ module SpeckleConnector
)
self[:units] = units
self[:name] = name
self[:basePoint] = base_point
self[:always_face_camera] = always_face_camera
self[:sketchup_attributes] = sketchup_attributes if sketchup_attributes.any?
# FIXME: Since geometry sends with @ as detached, block basePlane renders on viewer.
self['@geometry'] = geometry
end
# rubocop:enable Metrics/ParameterLists
@@ -43,13 +47,21 @@ module SpeckleConnector
# rubocop:disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/PerceivedComplexity
# rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/AbcSize
def self.from_definition(definition, units, definitions, preferences, &convert)
guid = definition.guid
return definitions[guid] if definitions.key?(guid)
dictionaries = {}
if preferences[:model][:include_entity_attributes]
dictionaries = SketchupModel::Dictionary::DictionaryHandler.attribute_dictionaries_to_speckle(definition)
if definition.group?
if preferences[:model][:include_group_entity_attributes]
dictionaries = SketchupModel::Dictionary::DictionaryHandler
.attribute_dictionaries_to_speckle(definition)
end
elsif preferences[:model][:include_component_entity_attributes]
dictionaries = SketchupModel::Dictionary::DictionaryHandler.attribute_dictionaries_to_speckle(definition)
end
end
att = dictionaries.any? ? { dictionaries: dictionaries } : {}
@@ -66,6 +78,7 @@ module SpeckleConnector
BlockDefinition.new(
units: units,
name: definition.name,
base_point: Geometry::Point.new(0, 0, 0, units),
geometry: geometry,
always_face_camera: definition.behavior.always_face_camera?,
sketchup_attributes: att,
@@ -75,6 +88,7 @@ module SpeckleConnector
# rubocop:enable Metrics/CyclomaticComplexity
# rubocop:enable Metrics/PerceivedComplexity
# rubocop:enable Metrics/MethodLength
# rubocop:enable Metrics/AbcSize
# Finds or creates a component definition from the geometry and the given name
# @param sketchup_model [Sketchup::Model] sketchup model to check block definitions.
@@ -129,8 +143,10 @@ module SpeckleConnector
if preferences[:model][:combine_faces_by_material]
mesh_groups = {}
definition.entities.grep(Sketchup::Face).collect do |face|
group_meshes_by_material(definition, face, mesh_groups, units, preferences[:model])
group_meshes_by_material(face, mesh_groups, units, preferences[:model])
end
# Update mesh overwrites points and polygons into base object.
mesh_groups.each { |_, mesh| mesh.update_mesh }
lines + nested_blocks + nested_groups + mesh_groups.values
else
@@ -146,45 +162,18 @@ module SpeckleConnector
# rubocop:enable Metrics/CyclomaticComplexity
# rubocop:enable Metrics/PerceivedComplexity
# rubocop:disable Metrics/AbcSize
def self.group_meshes_by_material(definition, face, mat_groups, units, model_preferences)
def self.group_meshes_by_material(face, mat_groups, units, model_preferences)
# convert material
mat_id = get_mesh_group_id(face, model_preferences)
mat_groups[mat_id] = initialise_group_mesh(face, definition.bounds, units) unless mat_groups.key?(mat_id)
mat_groups[mat_id] = Geometry::Mesh.from_face(face, units, model_preferences) unless mat_groups.key?(mat_id)
mat_group = mat_groups[mat_id]
if face.loops.size > 1
mesh = face.mesh
mat_group[:'@(31250)vertices'].push(*Geometry::Mesh.mesh_points_to_array(mesh, units))
mat_group[:'@(62500)faces'].push(*Geometry::Mesh.mesh_faces_to_array(mesh, mat_group[:pt_count] - 1))
mat_group[:'@(31250)faceEdgeFlags'].push(*Geometry::Mesh.mesh_edge_flags_to_array(mesh))
else
mat_group[:'@(31250)vertices'].push(*Geometry::Mesh.face_vertices_to_array(face, units))
mat_group[:'@(62500)faces'].push(*Geometry::Mesh.face_indices_to_array(face, mat_group[:pt_count]))
mat_group[:'@(31250)faceEdgeFlags'].push(*Geometry::Mesh.face_edge_flags_to_array(face))
end
mat_group[:pt_count] += face.vertices.count
end
# rubocop:enable Metrics/AbcSize
def self.initialise_group_mesh(face, bounds, units)
has_any_soften_edge = face.edges.any?(&:soft?)
mesh = Geometry::Mesh.new(
units: units,
render_material: face.material.nil? ? nil : RenderMaterial.from_material(face.material),
bbox: Geometry::BoundingBox.from_bounds(bounds, units),
vertices: [],
faces: [],
face_edge_flags: [],
sketchup_attributes: { is_soften: has_any_soften_edge }
)
mesh[:pt_count] = 0
mesh
mat_group.face_to_mesh(face)
end
# Mesh group id helps to determine how to group faces into meshes.
# @param face [Sketchup::Face] face to get mesh group id.
def self.get_mesh_group_id(face, model_preferences)
if model_preferences[:include_entity_attributes]
if model_preferences[:include_entity_attributes] && model_preferences[:include_face_entity_attributes]
has_attribute_dictionary = !(face.attribute_dictionaries.nil? || face.attribute_dictionaries.first.nil?)
return face.persistent_id.to_s if has_attribute_dictionary
end
@@ -37,6 +37,7 @@ module SpeckleConnector
self[:renderMaterial] = render_material
self[:transform] = transform
self[:sketchup_attributes] = sketchup_attributes if sketchup_attributes.any?
# FIXME: Since blockDefinition sends with @ as detached, block basePlane renders on viewer.
self['@blockDefinition'] = block_definition
end
# rubocop:enable Metrics/ParameterLists
@@ -44,7 +45,7 @@ module SpeckleConnector
# @param group [Sketchup::Group] group to convert Speckle BlockInstance
def self.from_group(group, units, component_defs, preferences, &convert)
dictionaries = {}
if preferences[:model][:include_entity_attributes]
if preferences[:model][:include_entity_attributes] && preferences[:model][:include_group_entity_attributes]
dictionaries = SketchupModel::Dictionary::DictionaryHandler.attribute_dictionaries_to_speckle(group)
end
att = dictionaries.any? ? { dictionaries: dictionaries } : {}
@@ -65,7 +66,8 @@ module SpeckleConnector
# rubocop:disable Metrics/MethodLength
def self.from_component_instance(component_instance, units, component_defs, preferences, &convert)
dictionaries = {}
if preferences[:model][:include_entity_attributes]
if preferences[:model][:include_entity_attributes] &&
preferences[:model][:include_component_entity_attributes]
dictionaries = SketchupModel::Dictionary::DictionaryHandler
.attribute_dictionaries_to_speckle(component_instance)
end
@@ -104,15 +106,17 @@ module SpeckleConnector
# so this is set to false always until I can figure this out
is_group = false
# is_group = block['is_sketchup_group']
block_definition = block['@blockDefinition'] || block['blockDefinition']
geometry = block_definition['@geometry'] || block_definition['geometry']
definition = BlockDefinition.to_native(
sketchup_model,
block['@blockDefinition']['@geometry'],
geometry,
layer,
block['@blockDefinition']['name'],
block['@blockDefinition']['always_face_camera'],
block_definition['name'],
block_definition['always_face_camera'].nil? ? false : block_definition['always_face_camera'],
model_preferences,
block['@blockDefinition']['sketchup_attributes'],
block['@blockDefinition']['applicationId'],
block_definition['sketchup_attributes'],
block_definition['applicationId'],
&convert
)
+10 -4
View File
@@ -80,7 +80,11 @@
</v-menu>
</v-app-bar>
<create-stream v-if="accounts().length !== 0"/>
<create-stream-dialog
v-if="accounts().length !== 0"
:account-id="activeAccount().userInfo.id"
:server-url="activeAccount().serverInfo.url"
/>
<v-container v-if="accounts().length !== 0" fluid>
<router-view :stream-search-query="streamSearchQuery" />
@@ -129,8 +133,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: {
@@ -181,10 +185,12 @@ export default {
sketchup.exec({name: "init_local_accounts", data: {}})
},
methods: {
accounts() {
return JSON.parse(localStorage.getItem('localAccounts'))
},
activeAccount(){
return this.accounts().find((account) => account['isDefault'])
},
switchAccount(account) {
this.$mixpanel.track('Connector Action', { name: 'Account Select' })
global.setSelectedAccount(account)
+13 -2
View File
@@ -1,6 +1,8 @@
<template>
<v-snackbar v-model="snack" app bottom color="primary">
{{ text }}
<v-snackbar v-if="text" v-model="snack" app bottom :color="color">
<div v-for="(line, index) in text.split('\n')" :key="index">
{{ line }}
</div>
<template #action="{}">
<v-btn v-if="actionName" small outlined @click="openUrl(url)" @click:append="snack = false">
{{ actionName }}
@@ -16,6 +18,7 @@ export default {
data() {
return {
snack: false,
color: "primary",
text: null,
actionName: null,
url: null
@@ -33,6 +36,14 @@ export default {
mounted() {
this.$eventHub.$on('notification', (args) => {
this.snack = true
this.color = "primary"
this.text = args.text
this.actionName = args.action ? args.action.name : null
this.url = args.action ? args.action.url : null
})
this.$eventHub.$on('error', (args) => {
this.snack = true
this.color = "#CC3300"
this.text = args.text
this.actionName = args.action ? args.action.name : null
this.url = args.action ? args.action.url : null
+31 -10
View File
@@ -55,16 +55,22 @@
<timeago class="mr-1" :datetime="stream.updatedAt" />
|
<v-icon class="ml-1" small>mdi-account-key-outline</v-icon>
{{ stream.role.split(':')[1] }}
{{ stream.role === null ? "" : stream.role.split(':')[1] }}
</v-card-text>
<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,11 +397,11 @@ 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', {
text: 'No objects selected. Nothing was sent.'
text: 'No objects selected. Nothing was sent.\n'
})
return
}
@@ -434,7 +455,7 @@ export default {
})
console.log('>>> SpeckleSketchUp: Sent to stream: ' + this.streamId, commit)
this.$eventHub.$emit('notification', {
text: 'Model selection sent!',
text: 'Model selection sent!\n',
action: {
name: 'View in Web',
url: `${localStorage.getItem('serverUrl')}/streams/${this.streamId}/commits/${
@@ -0,0 +1,134 @@
<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
}
},
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>
@@ -92,7 +92,6 @@
</v-dialog>
<!-- DIALOG: Add a Stream by ID or URL -->
<!--
<v-dialog v-model="showCreateStreamById">
<template #activator="{ on, attrs }">
<v-btn
@@ -141,14 +140,13 @@
:disabled="createStreamByIdText === ''"
color="blue darken-1"
text
@click="showCreateStreamById = false"
@click="getStream"
>
Add
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
-->
</v-col>
</v-row>
</v-container>
@@ -159,9 +157,20 @@
import gql from "graphql-tag";
import {bus} from "@/main";
import userQuery from "@/graphql/user.gql";
import {StreamWrapper} from "@/utils/streamWrapper";
export default {
name: "CreateStream",
name: "CreateStreamDialog",
props: {
accountId: {
type: String,
default: null
},
serverUrl: {
type: String,
default: null
}
},
data() {
return {
showCreateNewStream: false,
@@ -177,10 +186,7 @@ export default {
computed: {
loggedIn() {
return localStorage.getItem('SpeckleSketchup.AuthToken') !== null
},
accounts() {
return JSON.parse(localStorage.getItem('localAccounts'))
},
}
},
apollo: {
user: {
@@ -188,16 +194,70 @@ export default {
}
},
methods: {
activeAccount(){
return JSON.parse(localStorage.getItem('selectedAccount'))
},
switchAccountToCreateStream(account) {
this.accountToCreateStream = account
},
refresh() {
this.$apollo.queries.user.refetch()
bus.$emit('refresh-streams')
},
async getStream(){
try {
const streamWrapper = new StreamWrapper(this.createStreamByIdText, this.accountId, this.serverUrl)
let res = await this.$apollo.query({
query: gql`
query Stream($id: String!){
stream(id: $id){
id
name
description
isPublic
role
createdAt
updatedAt
commentCount
favoritedDate
favoritesCount
collaborators {
id
name
role
avatar
},
branches (limit: ${10}){
totalCount,
cursor,
items {
id,
name,
description,
commits {
totalCount
}
}
}
}
}
`,
variables: {
id: streamWrapper.streamId
}
})
let stream = res.data.stream
this.$eventHub.$emit('notification', {
text: 'Stream Added by URL!\n',
})
bus.$emit('stream-added-by-id-or-url', stream.id)
}
catch (e){
this.$eventHub.$emit('error', {
text: 'The stream you are trying to add might;\n' +
'- lies on different server, \n' +
'- be private, \n' +
'- not be existed anymore.',
})
}
this.showCreateStreamById = false
},
async createStream(){
let res = await this.$apollo.mutate({
mutation: gql`
@@ -216,6 +276,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
@@ -35,6 +35,35 @@
class="pt-1 my-n5"
:label="'Include entity attributes'"
/>
<v-icon class="ml-3" style="line-height: 0;">mdi-arrow-right-bottom</v-icon>
<v-switch
v-model="includeEdgeAttributes"
class="pt-1 my-n5 ml-10"
:label="'Edge'"
:disabled="!includeAttributes"
/>
<v-icon class="ml-3" style="line-height: 0;">mdi-arrow-right-bottom</v-icon>
<v-switch
v-model="includeFaceAttributes"
class="pt-1 my-n5 ml-10"
:label="'Face'"
:disabled="!includeAttributes"
/>
<v-icon class="ml-3" style="line-height: 0;">mdi-arrow-right-bottom</v-icon>
<v-switch
v-model="includeGroupAttributes"
class="pt-1 my-n5 ml-10"
:label="'Group'"
:disabled="!includeAttributes"
/>
<v-icon class="ml-3" style="line-height: 0;">mdi-arrow-right-bottom</v-icon>
<v-switch
v-model="includeComponentAttributes"
class="pt-1 my-n5 ml-10"
:label="'Component'"
:disabled="!includeAttributes"
/>
<div class="sm1 mt-3">Receive Strategy</div>
<v-divider class="mb-2"/>
<v-switch
@@ -78,6 +107,10 @@ export default {
description: "",
combineFacesByMaterial: this.preferences.model.combine_faces_by_material,
includeAttributes: this.preferences.model.include_entity_attributes,
includeFaceAttributes: this.preferences.model.include_face_entity_attributes,
includeEdgeAttributes: this.preferences.model.include_edge_entity_attributes,
includeGroupAttributes: this.preferences.model.include_group_entity_attributes,
includeComponentAttributes: this.preferences.model.include_component_entity_attributes,
mergeCoplanarFaces: this.preferences.model.merge_coplanar_faces,
}
},
@@ -110,6 +143,46 @@ export default {
},
deep: true
},
'includeFaceAttributes': {
handler(newValue) {
sketchup.exec({
name: "model_preferences_updated",
data: {preference: "include_face_entity_attributes", value: newValue}
})
this.$mixpanel.track('Connector Action', { name: 'Include Face Entity Attributes Option' })
},
deep: true
},
'includeEdgeAttributes': {
handler(newValue) {
sketchup.exec({
name: "model_preferences_updated",
data: {preference: "include_edge_entity_attributes", value: newValue}
})
this.$mixpanel.track('Connector Action', { name: 'Include Edge Entity Attributes Option' })
},
deep: true
},
'includeGroupAttributes': {
handler(newValue) {
sketchup.exec({
name: "model_preferences_updated",
data: {preference: "include_group_entity_attributes", value: newValue}
})
this.$mixpanel.track('Connector Action', { name: 'Include Group Entity Attributes Option' })
},
deep: true
},
'includeComponentAttributes': {
handler(newValue) {
sketchup.exec({
name: "model_preferences_updated",
data: {preference: "include_component_entity_attributes", value: newValue}
})
this.$mixpanel.track('Connector Action', { name: 'Include Component Entity Attributes Option' })
},
deep: true
},
'mergeCoplanarFaces': {
handler(newValue) {
sketchup.exec({
@@ -122,14 +195,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' })
},
+77
View File
@@ -0,0 +1,77 @@
require('url')
export class StreamWrapper {
constructor(streamIdOrUrl, accountId, serverUrl) {
this.originalOutput = streamIdOrUrl
try {
this.streamWrapperFromUrl(streamIdOrUrl)
}
catch (e){
this.serverUrl = serverUrl
this.userId = accountId
this.streamId = streamIdOrUrl
}
}
streamWrapperFromUrl(streamUrl){
this.url = new URL(streamUrl)
this.segments = this.url.pathname.split('/').map((segment) => segment + '/')
this.serverUrl = this.url.origin
if (this.segments.length >= 4 && this.segments[3]?.toLowerCase() === "branches/"){
this.streamId = this.segments[2].replace("/", "")
if (this.segments.length > 5)
{
let branchSegments = this.segments.slice(4, this.segments.length - 1);
this.branchName = branchSegments.join("")
}
else
{
this.branchName = this.segments[4]
}
} else {
switch (this.segments.length){
case 3: // ie http://speckle.server/streams/8fecc9aa6d
if (this.segments[1].toLowerCase() === "streams/")
this.streamId = this.segments[2].replace("/", "");
else
throw new Error(`Cannot parse ${this.originalOutput} into a stream wrapper class`);
break;
case 4: // ie https://speckle.server/streams/0c6ad366c4/globals/
if (this.segments[3].toLowerCase().startsWith("globals"))
{
this.streamId = this.segments[2].replace("/", "");
this.branchName = this.segments[3].replace("/", "");
}
else
throw new Error(`Cannot parse ${this.originalOutput} into a stream wrapper class`);
break;
case 5: // ie http://speckle.server/streams/8fecc9aa6d/commits/76a23d7179
switch (this.segments[3].toLowerCase()){
case "commits/":
this.streamId = this.segments[2].replace("/", "");
this.commitId = this.segments[4].replace("/", "");
break;
case "globals/":
this.streamId = this.segments[2].replace("/", "");
this.branchName = this.segments[3].replace("/", "");
this.commitId = this.segments[4].replace("/", "");
break;
case "branches/":
this.streamId = this.segments[2].replace("/", "");
this.branchName = this.segments[4].replace("/", "");
break;
case "objects/":
this.streamId = this.segments[2].replace("/", "");
this.objectId = this.segments[4].replace("/", "");
break;
default:
throw new Error(`Cannot parse ${this.originalOutput} into a stream wrapper class`);
}
break;
default:
throw new Error(`Cannot parse ${this.originalOutput} into a stream wrapper class`);
}
}
}
}
+13 -1
View File
@@ -73,12 +73,24 @@ 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) => {
this.savedStreams = streamIds
})
bus.$on('stream-added-by-id-or-url', (streamId) => {
if (!this.savedStreams){
this.savedStreams = []
this.savedStreams.push(streamId)
} else {
if (!this.savedStreams.includes(streamId)){
this.savedStreams.push(streamId)
}
}
sketchup.exec({name: "save_stream", data: {stream_id: streamId}})
})
sketchup.exec({name: "load_saved_streams", data: {}})
console.log('LAUNCHED')
this.$mixpanel.track('Connector Action', { name: 'Launched' })