Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4d1333c302 | |||
| 9ca55f6f0e | |||
| 4698799b43 | |||
| 5d4e6ac89a | |||
| b1c09c62d9 | |||
| 2b7b74dbdd | |||
| 42f3ae8490 | |||
| 479cd9584a |
+52
-18
@@ -9,18 +9,15 @@ orbs:
|
||||
jobs:
|
||||
build-ui:
|
||||
docker:
|
||||
- image: 'circleci/node:14'
|
||||
- image: "circleci/node:16"
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
command: 'rm package-lock.json'
|
||||
working_directory: 'ui'
|
||||
command: "npm install"
|
||||
working_directory: "ui"
|
||||
- run:
|
||||
command: 'npm install'
|
||||
working_directory: 'ui'
|
||||
- run:
|
||||
command: 'npm run build'
|
||||
working_directory: 'ui'
|
||||
command: "npm run build"
|
||||
working_directory: "ui"
|
||||
- persist_to_workspace:
|
||||
root: ./
|
||||
paths:
|
||||
@@ -43,15 +40,14 @@ jobs:
|
||||
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.1" } else { $env:CIRCLE_TAG }
|
||||
$semver = $tag.replace("-beta","")
|
||||
$version = "$($semver).$($env:CIRCLE_BUILD_NUM)"
|
||||
$channel = "latest"
|
||||
if($tag -like "*-beta") { $channel = "beta" }
|
||||
# only create the yml if we have a tag
|
||||
New-Item -Force "speckle-sharp-ci-tools/Installers/sketchup/$channel.yml" -ItemType File -Value "version: $version"
|
||||
$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 $version
|
||||
python patch_version.py $semver
|
||||
speckle-sharp-ci-tools\InnoSetup\ISCC.exe speckle-sharp-ci-tools\sketchup.iss
|
||||
- persist_to_workspace:
|
||||
root: ./
|
||||
@@ -62,7 +58,7 @@ jobs:
|
||||
docker:
|
||||
- image: cimg/base:2021.01
|
||||
steps:
|
||||
- run:
|
||||
- run:
|
||||
name: Clone
|
||||
command: git clone https://$GITHUB_TOKEN@github.com/specklesystems/speckle-sharp-ci-tools.git speckle-sharp-ci-tools
|
||||
- persist_to_workspace:
|
||||
@@ -91,6 +87,30 @@ jobs:
|
||||
from: '"speckle-sharp-ci-tools/Installers/"'
|
||||
to: s3://speckle-releases/installers/
|
||||
|
||||
deploy-manager2:
|
||||
docker:
|
||||
- image: mcr.microsoft.com/dotnet/sdk:6.0
|
||||
parameters:
|
||||
slug:
|
||||
type: string
|
||||
os:
|
||||
type: string
|
||||
extension:
|
||||
type: string
|
||||
steps:
|
||||
- checkout
|
||||
- attach_workspace:
|
||||
at: ./
|
||||
- run:
|
||||
name: Install Manager Feed CLI
|
||||
command: dotnet tool install --global Speckle.Manager.Feed
|
||||
- run:
|
||||
name: Upload new version
|
||||
command: |
|
||||
TAG=$(if [ "${CIRCLE_TAG}" ]; then echo $CIRCLE_TAG; else echo "0.0.0"; fi;)
|
||||
SEMVER=$(echo "$TAG" | sed -e 's/\/[a-zA-Z-]*//')
|
||||
/root/.dotnet/tools/Speckle.Manager.Feed deploy -s << parameters.slug >> -v ${SEMVER} -u https://releases.speckle.dev/installers/<< parameters.slug >>/<< parameters.slug >>-${SEMVER}.<< parameters.extension >> -o << parameters.os >> -f speckle-sharp-ci-tools/Installers/<< parameters.slug >>/<< parameters.slug >>-${SEMVER}.<< parameters.extension >>
|
||||
|
||||
workflows:
|
||||
build-and-deploy:
|
||||
jobs:
|
||||
@@ -120,6 +140,20 @@ workflows:
|
||||
- build-connector
|
||||
filters:
|
||||
tags:
|
||||
only: /[0-9]+(\.[0-9]+)*/
|
||||
only: /([0-9]+)\.([0-9]+)\.([0-9]+)(?:-\w+)?$/
|
||||
branches:
|
||||
ignore: /.*/ # For testing only! /ci\/.*/
|
||||
|
||||
- deploy-manager2:
|
||||
slug: sketchup
|
||||
os: Win
|
||||
extension: exe
|
||||
requires:
|
||||
- get-ci-tools
|
||||
- build-ui
|
||||
- deploy
|
||||
filters:
|
||||
tags:
|
||||
only: /([0-9]+)\.([0-9]+)\.([0-9]+)(?:-\w+)?$/
|
||||
branches:
|
||||
ignore: /.*/ # For testing only! /ci\/.*/
|
||||
|
||||
@@ -24,6 +24,9 @@ speckle_connector/html
|
||||
/test/version_tmp/
|
||||
/tmp/
|
||||
|
||||
# IDE
|
||||
.idea
|
||||
|
||||
# Used by dotenv library to load environment variables.
|
||||
.env
|
||||
|
||||
|
||||
@@ -2,15 +2,13 @@
|
||||
|
||||
source "https://rubygems.org"
|
||||
|
||||
# gem "rake", "~> 13.0"
|
||||
|
||||
gem "rubocop", "~> 1.7"
|
||||
|
||||
|
||||
group :development do
|
||||
gem "minitest"
|
||||
gem 'pry' # ruby console and debugger
|
||||
gem "sketchup-api-stubs"
|
||||
gem 'rake' # ruby make
|
||||
gem 'rubycritic', '~> 4.3', '>= 4.3.3', require: false
|
||||
gem "solargraph"
|
||||
gem "rubocop"
|
||||
gem 'skippy', '~> 0.4.1.a' # Aid with common SketchUp extension tasks.
|
||||
end
|
||||
|
||||
gem "sqlite3", "~> 1.4"
|
||||
|
||||
+112
-45
@@ -1,74 +1,141 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
addressable (2.8.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
ast (2.4.2)
|
||||
axiom-types (0.1.1)
|
||||
descendants_tracker (~> 0.0.4)
|
||||
ice_nine (~> 0.11.0)
|
||||
thread_safe (~> 0.3, >= 0.3.1)
|
||||
backport (1.2.0)
|
||||
benchmark (0.1.1)
|
||||
diff-lcs (1.4.4)
|
||||
e2mmap (0.1.0)
|
||||
coderay (1.1.3)
|
||||
coercible (1.0.0)
|
||||
descendants_tracker (~> 0.0.1)
|
||||
descendants_tracker (0.0.4)
|
||||
thread_safe (~> 0.3, >= 0.3.1)
|
||||
docile (1.4.0)
|
||||
equalizer (0.0.11)
|
||||
erubi (1.11.0)
|
||||
flay (2.13.0)
|
||||
erubi (~> 1.10)
|
||||
path_expander (~> 1.0)
|
||||
ruby_parser (~> 3.0)
|
||||
sexp_processor (~> 4.0)
|
||||
flog (4.6.6)
|
||||
path_expander (~> 1.0)
|
||||
ruby_parser (~> 3.1, > 3.1.0)
|
||||
sexp_processor (~> 4.8)
|
||||
git (1.11.0)
|
||||
rchardet (~> 1.8)
|
||||
ice_nine (0.11.2)
|
||||
jaro_winkler (1.5.4)
|
||||
kramdown (2.3.1)
|
||||
rexml
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
kramdown (~> 2.0)
|
||||
minitest (5.14.4)
|
||||
nokogiri (1.12.5-x64-mingw32)
|
||||
kwalify (0.7.2)
|
||||
launchy (2.5.0)
|
||||
addressable (~> 2.7)
|
||||
maruku (0.7.3)
|
||||
method_source (1.0.0)
|
||||
minitest (5.16.2)
|
||||
naturally (2.2.1)
|
||||
nokogiri (1.13.8-x64-mingw32)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.12.5-x86_64-linux)
|
||||
racc (~> 1.4)
|
||||
parallel (1.20.1)
|
||||
parser (3.0.2.0)
|
||||
parallel (1.22.1)
|
||||
parser (2.7.2.0)
|
||||
ast (~> 2.4.1)
|
||||
path_expander (1.1.1)
|
||||
pry (0.14.1)
|
||||
coderay (~> 1.1)
|
||||
method_source (~> 1.0)
|
||||
psych (3.3.2)
|
||||
public_suffix (4.0.7)
|
||||
racc (1.6.0)
|
||||
rainbow (3.0.0)
|
||||
regexp_parser (2.1.1)
|
||||
reverse_markdown (2.0.0)
|
||||
rainbow (3.1.1)
|
||||
rake (13.0.6)
|
||||
rchardet (1.8.0)
|
||||
reek (6.0.2)
|
||||
kwalify (~> 0.7.0)
|
||||
parser (>= 2.5.0.0, < 2.8, != 2.5.1.1)
|
||||
psych (~> 3.1)
|
||||
rainbow (>= 2.0, < 4.0)
|
||||
regexp_parser (2.5.0)
|
||||
reverse_markdown (1.4.0)
|
||||
nokogiri
|
||||
rexml (3.2.5)
|
||||
rubocop (1.19.1)
|
||||
rubocop (0.93.1)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 3.0.0.0)
|
||||
parser (>= 2.7.1.5)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 1.8, < 3.0)
|
||||
regexp_parser (>= 1.8)
|
||||
rexml
|
||||
rubocop-ast (>= 1.9.1, < 2.0)
|
||||
rubocop-ast (>= 0.6.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 1.4.0, < 3.0)
|
||||
rubocop-ast (1.11.0)
|
||||
parser (>= 3.0.1.1)
|
||||
unicode-display_width (>= 1.4.0, < 2.0)
|
||||
rubocop-ast (1.4.1)
|
||||
parser (>= 2.7.1.5)
|
||||
ruby-progressbar (1.11.0)
|
||||
sketchup-api-stubs (0.7.7)
|
||||
solargraph (0.43.0)
|
||||
backport (~> 1.2)
|
||||
benchmark
|
||||
ruby_parser (3.19.1)
|
||||
sexp_processor (~> 4.16)
|
||||
rubycritic (4.7.0)
|
||||
flay (~> 2.8)
|
||||
flog (~> 4.4)
|
||||
launchy (>= 2.0.0)
|
||||
parser (>= 2.6.0)
|
||||
rainbow (~> 3.0)
|
||||
reek (~> 6.0, < 7.0)
|
||||
ruby_parser (~> 3.8)
|
||||
simplecov (>= 0.17.0)
|
||||
tty-which (~> 0.4.0)
|
||||
virtus (~> 1.0)
|
||||
sexp_processor (4.16.1)
|
||||
simplecov (0.21.2)
|
||||
docile (~> 1.1)
|
||||
simplecov-html (~> 0.11)
|
||||
simplecov_json_formatter (~> 0.1)
|
||||
simplecov-html (0.12.3)
|
||||
simplecov_json_formatter (0.1.4)
|
||||
sketchup-api-stubs (0.7.8)
|
||||
skippy (0.4.3.a)
|
||||
git (~> 1.3)
|
||||
naturally (~> 2.1)
|
||||
thor (~> 0.19)
|
||||
solargraph (0.38.0)
|
||||
backport (~> 1.1)
|
||||
bundler (>= 1.17.2)
|
||||
diff-lcs (~> 1.4)
|
||||
e2mmap
|
||||
jaro_winkler (~> 1.5)
|
||||
kramdown (~> 2.3)
|
||||
kramdown-parser-gfm (~> 1.1)
|
||||
parser (~> 3.0)
|
||||
reverse_markdown (>= 1.0.5, < 3)
|
||||
rubocop (>= 0.52)
|
||||
thor (~> 1.0)
|
||||
maruku (~> 0.7, >= 0.7.3)
|
||||
nokogiri (~> 1.9, >= 1.9.1)
|
||||
parser (~> 2.3)
|
||||
reverse_markdown (~> 1.0, >= 1.0.5)
|
||||
rubocop (~> 0.52)
|
||||
thor (~> 0.19, >= 0.19.4)
|
||||
tilt (~> 2.0)
|
||||
yard (~> 0.9, >= 0.9.24)
|
||||
sqlite3 (1.4.2)
|
||||
thor (1.1.0)
|
||||
tilt (2.0.10)
|
||||
unicode-display_width (2.0.0)
|
||||
yard (0.9.26)
|
||||
yard (~> 0.9)
|
||||
thor (0.20.3)
|
||||
thread_safe (0.3.6)
|
||||
tilt (2.0.11)
|
||||
tty-which (0.4.2)
|
||||
unicode-display_width (1.8.0)
|
||||
virtus (1.0.5)
|
||||
axiom-types (~> 0.1)
|
||||
coercible (~> 1.0)
|
||||
descendants_tracker (~> 0.0, >= 0.0.3)
|
||||
equalizer (~> 0.0, >= 0.0.9)
|
||||
webrick (1.7.0)
|
||||
yard (0.9.28)
|
||||
webrick (~> 1.7.0)
|
||||
|
||||
PLATFORMS
|
||||
x64-mingw32
|
||||
x86_64-linux
|
||||
|
||||
DEPENDENCIES
|
||||
minitest
|
||||
rubocop (~> 1.7)
|
||||
pry
|
||||
rake
|
||||
rubocop
|
||||
rubycritic (~> 4.3, >= 4.3.3)
|
||||
sketchup-api-stubs
|
||||
skippy (~> 0.4.1.a)
|
||||
solargraph
|
||||
sqlite3 (~> 1.4)
|
||||
|
||||
BUNDLED WITH
|
||||
2.2.26
|
||||
2.3.20
|
||||
|
||||
+3
-2
@@ -25,7 +25,8 @@ def patch_installer(tag):
|
||||
|
||||
with open(iss_file, "r") as file:
|
||||
lines = file.readlines()
|
||||
lines.insert(11, f'#define AppVersion "{tag}"\n')
|
||||
lines.insert(11, f'#define AppVersion "{tag.split("-")[0]}"\n')
|
||||
lines.insert(12, f'#define AppInfoVersion "{tag}"\n')
|
||||
|
||||
with open(iss_file, "w") as file:
|
||||
file.writelines(lines)
|
||||
@@ -39,7 +40,7 @@ def main():
|
||||
return
|
||||
|
||||
tag = sys.argv[1]
|
||||
if not re.match(r"[0-9]+(\.[0-9]+)*$", tag):
|
||||
if not re.match(r"([0-9]+)\.([0-9]+)\.([0-9]+)", tag):
|
||||
raise ValueError(f"Invalid tag provided: {tag}")
|
||||
|
||||
print(f"Patching version: {tag}")
|
||||
|
||||
@@ -8,9 +8,14 @@ module SpeckleSystems::SpeckleConnector::ToNative
|
||||
elsif obj.is_a?(Hash) && obj.key?("speckle_type")
|
||||
return if is_ignored_speckle_type(obj)
|
||||
|
||||
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]) }
|
||||
if obj["displayValue"].nil?
|
||||
puts(">>> Found #{obj["speckle_type"]}: #{obj["id"]}. Continuing traversal.")
|
||||
props = obj.keys.filter_map { |key| key unless key.start_with?("_") }
|
||||
props.each { |prop| traverse_commit_object(obj[prop]) }
|
||||
else
|
||||
puts(">>> Found #{obj["speckle_type"]}: #{obj["id"]} with displayValue.")
|
||||
convert_to_native(obj)
|
||||
end
|
||||
elsif obj.is_a?(Hash)
|
||||
obj.each_value { |value| traverse_commit_object(value) }
|
||||
elsif obj.is_a?(Array)
|
||||
@@ -39,32 +44,14 @@ module SpeckleSystems::SpeckleConnector::ToNative
|
||||
end
|
||||
|
||||
def convert_to_native(obj, entities = Sketchup.active_model.entities)
|
||||
puts(">>> Converting #{obj["speckle_type"]}: #{obj["id"]}")
|
||||
return display_value_to_native_component(obj, entities) unless obj["displayValue"].nil?
|
||||
|
||||
case obj["speckle_type"]
|
||||
when "Objects.Geometry.Line", "Objects.Geometry.Polyline" then if entities == Sketchup.active_model.entities
|
||||
edge_to_native_component(obj, entities)
|
||||
else
|
||||
edge_to_native(obj, entities)
|
||||
end
|
||||
when "Objects.Geometry.Line", "Objects.Geometry.Polyline" then edge_to_native(obj, entities)
|
||||
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 if entities == Sketchup.active_model.entities
|
||||
mesh_to_native_component(obj, entities)
|
||||
else
|
||||
mesh_to_native(obj, entities)
|
||||
end
|
||||
when "Objects.Geometry.Brep" then if entities == Sketchup.active_model.entities
|
||||
mesh_to_native_component(obj["displayMesh"], entities)
|
||||
else
|
||||
mesh_to_native(obj["displayMesh"], entities)
|
||||
end
|
||||
when obj.key?["displayValue"]
|
||||
parent_id = obj["applicationId"] || obj["id"]
|
||||
obj["displayValue"].each do |o|
|
||||
o["applicationId"] = "#{parent_id}::#{o["id"]}" if o["applicationId"].nil?
|
||||
convert_to_native(o, entities)
|
||||
end
|
||||
when "Objects.Geometry.Mesh" then mesh_to_native(obj, entities)
|
||||
when "Objects.Geometry.Brep" then mesh_to_native(obj["displayValue"], entities)
|
||||
else
|
||||
nil
|
||||
end
|
||||
@@ -74,20 +61,6 @@ module SpeckleSystems::SpeckleConnector::ToNative
|
||||
nil
|
||||
end
|
||||
|
||||
# def register_receive(entity, id)
|
||||
# # entity.add_observer(@entity_observer)
|
||||
# # entity.set_attribute("speckle", "applicationId", id)
|
||||
# @registry[id] = entity.persistent_id
|
||||
# end
|
||||
|
||||
# def get_received_entity(app_id)
|
||||
# return if @registry[app_id].nil?
|
||||
# end
|
||||
|
||||
# def received?(id)
|
||||
# !@registry[id].nil?
|
||||
# end
|
||||
|
||||
def length_to_native(length, units = @units)
|
||||
length.__send__(SpeckleSystems::SpeckleConnector::SKETCHUP_UNIT_STRINGS[units])
|
||||
end
|
||||
@@ -106,7 +79,7 @@ module SpeckleSystems::SpeckleConnector::ToNative
|
||||
end
|
||||
|
||||
def edge_to_native_component(line, entities)
|
||||
line_id = line["applicationId"] || line["id"]
|
||||
line_id = line["applicationId"].to_s.empty? ? line["id"] : line["applicationId"]
|
||||
definition = component_definition_to_native([line], "def::#{line_id}")
|
||||
find_and_erase_existing_instance(definition, line_id)
|
||||
instance = entities.add_instance(definition, Geom::Transformation.new)
|
||||
@@ -122,8 +95,16 @@ module SpeckleSystems::SpeckleConnector::ToNative
|
||||
Geom::Point3d.new(length_to_native(x, units), length_to_native(y, units), length_to_native(z, units))
|
||||
end
|
||||
|
||||
def point_to_native_array(x ,y ,z ,units)
|
||||
[length_to_native(x, units), length_to_native(y, units), length_to_native(z, units)]
|
||||
end
|
||||
|
||||
# converts a mesh to a native mesh and adds the faces to the given entities collection
|
||||
def mesh_to_native(mesh, entities)
|
||||
_speckle_mesh_to_native_mesh(mesh, entities)
|
||||
end
|
||||
|
||||
def _speckle_mesh_to_native_mesh(mesh, entities)
|
||||
native_mesh = Geom::PolygonMesh.new(mesh["vertices"].count / 3)
|
||||
points = []
|
||||
mesh["vertices"].each_slice(3) do |pt|
|
||||
@@ -138,18 +119,170 @@ module SpeckleSystems::SpeckleConnector::ToNative
|
||||
native_mesh.add_polygon(indices.map { |index| points[index] })
|
||||
end
|
||||
entities.add_faces_from_mesh(native_mesh, 4, material_to_native(mesh["renderMaterial"]))
|
||||
merge_coplanar_faces(entities)
|
||||
native_mesh
|
||||
end
|
||||
|
||||
# Removes coplanar entities from the given entities.
|
||||
# @param entities [Sketchup::Entities] entities to remove edges between that make entities coplanar.
|
||||
# @note Merging coplanar faces idea originated from [CleanUp](https://github.com/thomthom/cleanup) plugin
|
||||
# which is developed by [Thomas Thomassen](https://github.com/thomthom).
|
||||
def merge_coplanar_faces(entities)
|
||||
edges = []
|
||||
faces = entities.collect { |entity| entity if entity.is_a? Sketchup::Face }.compact
|
||||
faces.each { |face| face.edges.each { |edge| edges << edge } }
|
||||
edges.compact!
|
||||
edges.each { |edge| remove_edge_have_coplanar_faces(edge, false ) }
|
||||
end
|
||||
|
||||
# Detect edges to remove by checking following controls respectively;
|
||||
# - Upcoming Sketchup entity is Sketchup::Edge or not.
|
||||
# - Whether edge has 2 face or not.
|
||||
# - Whether faces are duplicated or not.
|
||||
# - Whether edges safe to merge or not.
|
||||
# - Whether faces have same material or not.
|
||||
# - Whether UV texture map is aligned between faces or not.
|
||||
# - Finally, if faces are coplanar by correcting these checks, then removes edge from Sketchup.active_model.
|
||||
# @param edge [Sketchup::Edge] edge to check.
|
||||
# @param ignore_materials [Boolean] whether ignore materials or not.
|
||||
# Returns true if the given edge separating two coplanar faces.
|
||||
# Return false otherwise.
|
||||
def remove_edge_have_coplanar_faces(edge, ignore_materials)
|
||||
return false unless edge.valid? && edge.is_a?(Sketchup::Edge)
|
||||
return false unless edge.faces.size == 2
|
||||
|
||||
face1, face2 = edge.faces
|
||||
|
||||
return false if face_duplicate?(face1, face2)
|
||||
# Check for troublesome faces which might lead to missing geometry if merged.
|
||||
return false unless edge_safe_to_merge?(edge)
|
||||
|
||||
# Check materials match.
|
||||
unless ignore_materials
|
||||
if face1.material == face2.material && face1.back_material == face2.back_material
|
||||
# Verify UV mapping match.
|
||||
unless face1.material.nil? || face1.material.texture.nil?
|
||||
return false unless continuous_uv?(face1, face2, edge)
|
||||
end
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
# Check faces are coplanar or not.
|
||||
return false unless faces_coplanar?(face1, face2)
|
||||
edge.erase!
|
||||
true
|
||||
end
|
||||
|
||||
# Determines if two faces are overlapped.
|
||||
def face_duplicate?(face1, face2, overlapping = false)
|
||||
return false if face1 == face2
|
||||
|
||||
v1 = face1.outer_loop.vertices
|
||||
v2 = face2.outer_loop.vertices
|
||||
return true if (v1 - v2).empty? && (v2 - v1).empty?
|
||||
|
||||
if overlapping && (v2 - v1).empty?
|
||||
edges = (face2.outer_loop.edges - face1.outer_loop.edges)
|
||||
unless edges.empty?
|
||||
point = edges[0].start.position.offset(edges[0].line[1], 0.01)
|
||||
return true if face1.classify_point(point) <= 4
|
||||
end
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
# Checks the given edge for potential problems if the connected faces would
|
||||
# be merged.
|
||||
def edge_safe_to_merge?(edge)
|
||||
edge.faces.all? { |face| self.face_safe_to_merge?(face) }
|
||||
end
|
||||
|
||||
# Returns true if the two faces connected by the edge has continuous UV mapping.
|
||||
# UV's are normalized to 0.0..1.0 before comparison.
|
||||
def continuous_uv?(face1, face2, edge)
|
||||
tw = Sketchup.create_texture_writer
|
||||
uvh1 = face1.get_UVHelper(true, true, tw)
|
||||
uvh2 = face2.get_UVHelper(true, true, tw)
|
||||
p1 = edge.start.position
|
||||
p2 = edge.end.position
|
||||
self.uv_equal?(uvh1.get_front_UVQ(p1), uvh2.get_front_UVQ(p1)) &&
|
||||
self.uv_equal?(uvh1.get_front_UVQ(p2), uvh2.get_front_UVQ(p2)) &&
|
||||
self.uv_equal?(uvh1.get_back_UVQ(p1), uvh2.get_back_UVQ(p1)) &&
|
||||
self.uv_equal?(uvh1.get_back_UVQ(p2), uvh2.get_back_UVQ(p2))
|
||||
end
|
||||
|
||||
# Normalize UV's to 0.0..1.0 and compare them.
|
||||
def uv_equal?(uvq1, uvq2)
|
||||
uv1 = uvq1.to_a.map { |n| n % 1 }
|
||||
uv2 = uvq2.to_a.map { |n| n % 1 }
|
||||
uv1 == uv2
|
||||
end
|
||||
|
||||
# Validates that the given face can be merged with other faces without causing
|
||||
# problems.
|
||||
def face_safe_to_merge?(face)
|
||||
stack = face.outer_loop.edges
|
||||
edge = stack.shift
|
||||
direction = edge.line[1]
|
||||
until stack.empty?
|
||||
edge = stack.shift
|
||||
return true unless edge.line[1].parallel?(direction)
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
# Determines if two faces are coplanar.
|
||||
def faces_coplanar?(face1, face2)
|
||||
vertices = face1.vertices + face2.vertices
|
||||
plane = Geom.fit_plane_to_points(vertices)
|
||||
vertices.all? { |v| v.position.on_plane?(plane) }
|
||||
end
|
||||
|
||||
|
||||
def _hidden_edges_mesh_to_native_mesh(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
|
||||
edge_flags = mesh["faceEdgeFlags"]
|
||||
faces = mesh["faces"]
|
||||
loops = []
|
||||
flags = []
|
||||
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)
|
||||
current_edge_flags = edge_flags.shift(num_pts)
|
||||
outer_loop = indices.map { |index| points[index] }
|
||||
if current_edge_flags.include?(true)
|
||||
loops << outer_loop
|
||||
flags << current_edge_flags
|
||||
else
|
||||
native_mesh.add_polygon(outer_loop)
|
||||
end
|
||||
end
|
||||
entities.add_faces_from_mesh(native_mesh, 0, material_to_native(mesh["renderMaterial"]))
|
||||
|
||||
loops.each do |l|
|
||||
loop_flags = flags.shift
|
||||
face = entities.add_face(l)
|
||||
face.edges.each_with_index { |edge, index| edge.soft = edge.smooth = loop_flags[index] }
|
||||
end
|
||||
|
||||
native_mesh
|
||||
end
|
||||
|
||||
# creates a component definition and instance from a mesh
|
||||
def mesh_to_native_component(mesh, entities)
|
||||
mesh_id = mesh["applicationId"] || mesh["id"]
|
||||
definition = component_definition_to_native([mesh], "def::#{mesh_id}")
|
||||
find_and_erase_existing_instance(definition, mesh_id)
|
||||
instance = entities.add_instance(definition, Geom::Transformation.new)
|
||||
instance.name = mesh_id
|
||||
instance.material = material_to_native(mesh["renderMaterial"])
|
||||
# creates a component definition and instance from a speckle object with a display value
|
||||
def display_value_to_native_component(obj, entities)
|
||||
obj_id = obj["applicationId"].to_s.empty? ? obj["id"] : obj["applicationId"]
|
||||
definition = component_definition_to_native(obj["displayValue"], "def::#{obj_id}")
|
||||
find_and_erase_existing_instance(definition, obj_id)
|
||||
transform = obj["transform"].nil? ? Geom::Transformation.new : transform_to_native(obj["transform"])
|
||||
instance = entities.add_instance(definition, transform)
|
||||
instance.name = obj_id
|
||||
instance
|
||||
end
|
||||
|
||||
@@ -162,7 +295,7 @@ module SpeckleSystems::SpeckleConnector::ToNative
|
||||
definition ||= Sketchup.active_model.definitions.add(name)
|
||||
geometry.each { |obj| convert_to_native(obj, definition.entities) }
|
||||
puts("definition finished: #{name} (#{application_id})")
|
||||
puts(" entity count: #{definition.entities.count}")
|
||||
# puts(" entity count: #{definition.entities.count}")
|
||||
definition
|
||||
end
|
||||
|
||||
@@ -184,7 +317,6 @@ module SpeckleSystems::SpeckleConnector::ToNative
|
||||
block["blockDefinition"]["applicationId"]
|
||||
)
|
||||
name = block["name"].nil? || block["name"].empty? ? block["id"] : block["name"]
|
||||
find_and_erase_existing_instance(definition, name, block["applicationId"])
|
||||
transform = transform_to_native(
|
||||
block["transform"].is_a?(Hash) ? block["transform"]["value"] : block["transform"],
|
||||
block["units"]
|
||||
@@ -195,6 +327,8 @@ module SpeckleSystems::SpeckleConnector::ToNative
|
||||
else
|
||||
entities.add_instance(definition, transform)
|
||||
end
|
||||
# erase existing instances after creation and before rename because you can't have definitions without instances
|
||||
find_and_erase_existing_instance(definition, name, block["applicationId"])
|
||||
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"])
|
||||
|
||||
@@ -63,27 +63,25 @@ module SpeckleSystems::SpeckleConnector::ToSpeckle
|
||||
|
||||
component_def.entities.each do |entity|
|
||||
nested_blocks.push(component_instance_to_speckle(entity)) if entity.typename == "ComponentInstance"
|
||||
next unless %w[Edge Face].include?(entity.typename)
|
||||
next unless %w[Face].include?(entity.typename)
|
||||
|
||||
if entity.typename == "Edge"
|
||||
lines.push(edge_to_speckle(entity))
|
||||
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)
|
||||
|
||||
if face.loops.size > 1
|
||||
mesh = face.mesh
|
||||
mat_groups[mat_id]["@(31250)vertices"].push(*mesh_points_to_array(mesh))
|
||||
mat_groups[mat_id]["@(62500)faces"].push(*mesh_faces_to_array(mesh, mat_groups[mat_id][:pt_count] - 1))
|
||||
mat_groups[mat_id]["@(31250)faceEdgeFlags"].push(*mesh_edge_flags_to_array(mesh))
|
||||
else
|
||||
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)
|
||||
|
||||
if face.loops.size > 1
|
||||
mesh = face.mesh
|
||||
mat_groups[mat_id]["@(31250)vertices"].push(*mesh_points_to_array(mesh))
|
||||
mat_groups[mat_id]["@(62500)faces"].push(*mesh_faces_to_array(mesh, mat_groups[mat_id][:pt_count] - 1))
|
||||
else
|
||||
mat_groups[mat_id]["@(31250)vertices"].push(*face_vertices_to_array(face))
|
||||
mat_groups[mat_id]["@(62500)faces"].push(*face_indices_to_array(face, mat_groups[mat_id][:pt_count]))
|
||||
end
|
||||
mat_groups[mat_id][:pt_count] += face.vertices.count
|
||||
|
||||
mat_groups[mat_id]["@(31250)vertices"].push(*face_vertices_to_array(face))
|
||||
mat_groups[mat_id]["@(62500)faces"].push(*face_indices_to_array(face, mat_groups[mat_id][:pt_count]))
|
||||
mat_groups[mat_id]["@(31250)faceEdgeFlags"].push(*face_edge_flags_to_array(face))
|
||||
end
|
||||
mat_groups[mat_id][:pt_count] += face.vertices.count
|
||||
|
||||
end
|
||||
|
||||
mat_groups.values.map { |group| group.delete(:pt_count) }
|
||||
@@ -123,6 +121,7 @@ module SpeckleSystems::SpeckleConnector::ToSpeckle
|
||||
bbox: bounds_to_speckle(bounds),
|
||||
"@(31250)vertices" => [],
|
||||
"@(62500)faces" => [],
|
||||
"@(31250)faceEdgeFlags" => [],
|
||||
"@(31250)textureCoordinates" => [],
|
||||
pt_count: 0,
|
||||
renderMaterial: face.material.nil? ? nil : material_to_speckle(face.material)
|
||||
@@ -130,9 +129,8 @@ module SpeckleSystems::SpeckleConnector::ToSpeckle
|
||||
end
|
||||
|
||||
# get an array of face indices from a sketchup polygon mesh
|
||||
def mesh_faces_to_array(mesh, offset)
|
||||
def mesh_faces_to_array(mesh, offset = 0)
|
||||
faces = []
|
||||
puts(faces)
|
||||
mesh.polygons.each do |poly|
|
||||
faces.push(
|
||||
poly.count, *poly.map { |index| index.abs + offset }
|
||||
@@ -141,6 +139,17 @@ module SpeckleSystems::SpeckleConnector::ToSpeckle
|
||||
faces
|
||||
end
|
||||
|
||||
# get an array of face indices from a sketchup polygon mesh INCLUDING negative indices for hidden meshes
|
||||
def mesh_faces_with_edges_to_array(mesh, offset)
|
||||
faces = []
|
||||
mesh.polygons.each do |poly|
|
||||
faces.push(
|
||||
poly.count, *poly.map { |index| index.positive? ? index + offset : index - offset }
|
||||
)
|
||||
end
|
||||
faces
|
||||
end
|
||||
|
||||
# get a flat array of vertices from a sketchup polygon mesh
|
||||
def mesh_points_to_array(mesh)
|
||||
pts_array = []
|
||||
@@ -154,6 +163,16 @@ module SpeckleSystems::SpeckleConnector::ToSpeckle
|
||||
pts_array
|
||||
end
|
||||
|
||||
def mesh_edge_flags_to_array(mesh)
|
||||
edge_flags = []
|
||||
mesh.polygons.each do |poly|
|
||||
edge_flags.push(
|
||||
*poly.map(&:negative?)
|
||||
)
|
||||
end
|
||||
edge_flags
|
||||
end
|
||||
|
||||
# get a flat array of face indices from a sketchup face
|
||||
def face_indices_to_array(face, offset)
|
||||
face_array = [face.vertices.count]
|
||||
@@ -161,6 +180,18 @@ module SpeckleSystems::SpeckleConnector::ToSpeckle
|
||||
face_array
|
||||
end
|
||||
|
||||
# get a flat array of face indices from a sketchup face
|
||||
def face_indices_with_edges_to_array(face, offset = 1)
|
||||
soft_edges = face.outer_loop.edges.map(&:soft?)
|
||||
face_array = [face.vertices.count]
|
||||
face_array.push(*face.vertices.count.times.map { |index| soft_edges[index] ? -(index + offset) : index + offset })
|
||||
face_array
|
||||
end
|
||||
|
||||
def face_edge_flags_to_array(face)
|
||||
face.outer_loop.edges.map(&:soft?)
|
||||
end
|
||||
|
||||
# get a flat array of vertices from a list of sketchup vertices
|
||||
def face_vertices_to_array(face)
|
||||
pts_array = []
|
||||
@@ -171,7 +202,6 @@ module SpeckleSystems::SpeckleConnector::ToSpeckle
|
||||
pts_array
|
||||
end
|
||||
|
||||
|
||||
|
||||
def uvs_to_array(mesh)
|
||||
uvs_array = []
|
||||
@@ -192,7 +222,8 @@ module SpeckleSystems::SpeckleConnector::ToSpeckle
|
||||
renderMaterial: face.material.nil? ? nil : material_to_speckle(face.material),
|
||||
bbox: bounds_to_speckle(face.bounds),
|
||||
"@(31250)vertices" => mesh.nil? ? face_vertices_to_array(face) : mesh_points_to_array(mesh),
|
||||
"@(62500)faces" => mesh.nil? ? face_indices_to_array(face, 0) : mesh_faces_to_array(mesh, -1)
|
||||
"@(62500)faces" => mesh.nil? ? face_indices_to_array(face, 0) : mesh_faces_to_array(mesh, -1),
|
||||
"@(31250)faceEdgeFlags" => mesh.nil? ? face_edge_flags_to_array(face) : mesh_edge_flags_to_array(mesh),
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
Generated
+7370
-4742
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -13,9 +13,9 @@
|
||||
"dependencies": {
|
||||
"@speckle/objectloader": "^2.6.0",
|
||||
"aws-sdk": "^2.981.0",
|
||||
"core-js": "^3.6.5",
|
||||
"debounce": "^1.2.1",
|
||||
"mixpanel-browser": "^2.45.0",
|
||||
"regenerator-runtime": "^0.13.9",
|
||||
"register-service-worker": "^1.7.1",
|
||||
"sqlite3": "^5.0.2",
|
||||
"v-tooltip": "^2.1.3",
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'regenerator-runtime/runtime'
|
||||
|
||||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
||||
Reference in New Issue
Block a user