From d2394274eb3b1998c895e952df3d4ce007111d52 Mon Sep 17 00:00:00 2001 From: oguzhankoral Date: Fri, 24 Feb 2023 19:14:13 +0300 Subject: [PATCH 1/3] Simplify speckle entity object - So entity specific objects removed --- .../src/convertors/to_speckle.rb | 1 - .../speckle_block_definition_entity.rb | 23 ------------ .../speckle_block_instance_entity.rb | 27 -------------- .../src/speckle_entities/speckle_entities.rb | 36 ------------------- .../speckle_entities/speckle_line_entity.rb | 23 ------------ .../speckle_entities/speckle_mesh_entity.rb | 23 ------------ 6 files changed, 133 deletions(-) delete mode 100644 speckle_connector/src/speckle_entities/speckle_block_definition_entity.rb delete mode 100644 speckle_connector/src/speckle_entities/speckle_block_instance_entity.rb delete mode 100644 speckle_connector/src/speckle_entities/speckle_entities.rb delete mode 100644 speckle_connector/src/speckle_entities/speckle_line_entity.rb delete mode 100644 speckle_connector/src/speckle_entities/speckle_mesh_entity.rb diff --git a/speckle_connector/src/convertors/to_speckle.rb b/speckle_connector/src/convertors/to_speckle.rb index ce5b3b6..74e2521 100644 --- a/speckle_connector/src/convertors/to_speckle.rb +++ b/speckle_connector/src/convertors/to_speckle.rb @@ -3,7 +3,6 @@ require_relative 'converter' require_relative 'base_object_serializer' require_relative '../relations/many_to_one_relation' -require_relative '../speckle_entities/speckle_entities' require_relative '../speckle_objects/base' require_relative '../speckle_objects/geometry/line' require_relative '../speckle_objects/geometry/length' diff --git a/speckle_connector/src/speckle_entities/speckle_block_definition_entity.rb b/speckle_connector/src/speckle_entities/speckle_block_definition_entity.rb deleted file mode 100644 index b4b5046..0000000 --- a/speckle_connector/src/speckle_entities/speckle_block_definition_entity.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -require_relative 'speckle_entity' -require_relative '../immutable/immutable' - -module SpeckleConnector - module SpeckleEntities - # Speckle block definition entity is the state object for Sketchup::Entity and it's converted (or not yet) state. - class SpeckleBlockDefinitionEntity < SpeckleEntities::SpeckleEntity - include Immutable::ImmutableUtils - - # @return [Hash{String=>SpeckleObjects::Base}] speckle objects belongs to block instance - attr_reader :children - - def initialize(sketchup_group_or_component_instance, traversed_speckle_object, stream_id) - @children = traversed_speckle_object[:__closure].nil? ? {} : traversed_speckle_object[:__closure] - super(sketchup_group_or_component_instance, traversed_speckle_object, children, stream_id) - end - - alias sketchup_edge sketchup_entity - end - end -end diff --git a/speckle_connector/src/speckle_entities/speckle_block_instance_entity.rb b/speckle_connector/src/speckle_entities/speckle_block_instance_entity.rb deleted file mode 100644 index b87c799..0000000 --- a/speckle_connector/src/speckle_entities/speckle_block_instance_entity.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true - -require_relative 'speckle_entity' -require_relative '../immutable/immutable' - -module SpeckleConnector - module SpeckleEntities - # Speckle block instance entity is the state object for Sketchup::Entity and it's converted (or not yet) state. - class SpeckleBlockInstanceEntity < SpeckleEntities::SpeckleEntity - include Immutable::ImmutableUtils - - # @return [Hash{String=>SpeckleObjects::Base}] speckle objects belongs to block instance - attr_reader :children - - # @return [Boolean] whether block instance represented as sketchup group or component instance - attr_reader :is_sketchup_group - - def initialize(sketchup_group_or_component_instance, traversed_speckle_object, stream_id) - @children = traversed_speckle_object[:__closure].nil? ? {} : traversed_speckle_object[:__closure] - @is_sketchup_group = traversed_speckle_object[:is_sketchup_group] - super(sketchup_group_or_component_instance, traversed_speckle_object, children, stream_id) - end - - alias sketchup_edge sketchup_entity - end - end -end diff --git a/speckle_connector/src/speckle_entities/speckle_entities.rb b/speckle_connector/src/speckle_entities/speckle_entities.rb deleted file mode 100644 index 0014894..0000000 --- a/speckle_connector/src/speckle_entities/speckle_entities.rb +++ /dev/null @@ -1,36 +0,0 @@ -# frozen_string_literal: true - -require_relative 'speckle_entity' -require_relative 'speckle_line_entity' -require_relative 'speckle_mesh_entity' -require_relative 'speckle_block_instance_entity' -require_relative 'speckle_block_definition_entity' - -module SpeckleConnector - # Speckle entities are the state holder objects to achieve diffing, caching and updating. - # They are created whenever user send/receive objects between SketchUp and Speckle XYZ server. - # When Sketchup Entity is sent, by checking objects attributes, allow us to understand this object is sent previously? - # If yes, then use it for caching purpose only if object hasn't changed since it's previous sent state. - # If object has sent before but changed after, then update the SpeckleEntity with new traversed object. - # If no, then create SpeckleEntity and add it to the SpeckleState to check later. - module SpeckleEntities - # Speckle entity is the state object for Sketchup::Entity and it's converted (or not yet) state. - def self.with_converted(skp_entity, traversed, stream_id) - # return the same object if it is already SpeckleEntity - return skp_entity if skp_entity.is_a?(SpeckleEntity) - return SpeckleBlockInstanceEntity.new(skp_entity, traversed, stream_id) if skp_entity.is_a?(Sketchup::Group) - - if skp_entity.is_a?(Sketchup::ComponentInstance) - return SpeckleBlockInstanceEntity.new(skp_entity, traversed, - stream_id) - end - if skp_entity.is_a?(Sketchup::ComponentDefinition) - return SpeckleBlockDefinitionEntity.new(skp_entity, traversed, - stream_id) - end - return SpeckleMeshEntity.new(skp_entity, traversed, stream_id) if skp_entity.is_a?(Sketchup::Face) - - SpeckleLineEntity.new(skp_entity, traversed, stream_id) if skp_entity.is_a?(Sketchup::Edge) - end - end -end diff --git a/speckle_connector/src/speckle_entities/speckle_line_entity.rb b/speckle_connector/src/speckle_entities/speckle_line_entity.rb deleted file mode 100644 index e1a19ee..0000000 --- a/speckle_connector/src/speckle_entities/speckle_line_entity.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -require_relative 'speckle_entity' -require_relative '../immutable/immutable' - -module SpeckleConnector - module SpeckleEntities - # Speckle line entity is the state object for Sketchup::Entity and it's converted (or not yet) state. - class SpeckleLineEntity < SpeckleEntities::SpeckleEntity - include Immutable::ImmutableUtils - - # @return [Hash{String=>SpeckleObjects::Base}] speckle objects belongs to edge - attr_reader :children - - def initialize(sketchup_edge, traversed_speckle_object, stream_id) - @children = traversed_speckle_object[:__closure].nil? ? {} : traversed_speckle_object[:__closure] - super(sketchup_edge, traversed_speckle_object, children, stream_id) - end - - alias sketchup_edge sketchup_entity - end - end -end diff --git a/speckle_connector/src/speckle_entities/speckle_mesh_entity.rb b/speckle_connector/src/speckle_entities/speckle_mesh_entity.rb deleted file mode 100644 index 2a00c9c..0000000 --- a/speckle_connector/src/speckle_entities/speckle_mesh_entity.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -require_relative 'speckle_entity' -require_relative '../immutable/immutable' - -module SpeckleConnector - module SpeckleEntities - # Speckle mesh entity is the state object for Sketchup::Entity and it's converted (or not yet) state. - class SpeckleMeshEntity < SpeckleEntities::SpeckleEntity - include Immutable::ImmutableUtils - - # @return [Hash{String=>SpeckleObjects::Base}] speckle objects belongs to edge - attr_reader :children - - def initialize(sketchup_face, traversed_speckle_object, stream_id) - @children = traversed_speckle_object[:__closure].nil? ? {} : traversed_speckle_object[:__closure] - super(sketchup_face, traversed_speckle_object, children, stream_id) - end - - alias sketchup_edge sketchup_entity - end - end -end From a54f44d22a98d56b94ca88e59a8b8beea2925e5f Mon Sep 17 00:00:00 2001 From: oguzhankoral Date: Fri, 24 Feb 2023 19:18:03 +0300 Subject: [PATCH 2/3] Update init method of speckle entity with more general way --- .../src/constants/dict_constants.rb | 1 + .../src/convertors/base_object_serializer.rb | 23 +++++++++++---- .../speckle_entity_dictionary_handler.rb | 5 ++-- .../src/speckle_entities/speckle_entity.rb | 28 ++++++++----------- 4 files changed, 34 insertions(+), 23 deletions(-) diff --git a/speckle_connector/src/constants/dict_constants.rb b/speckle_connector/src/constants/dict_constants.rb index 93aa17d..505e04b 100644 --- a/speckle_connector/src/constants/dict_constants.rb +++ b/speckle_connector/src/constants/dict_constants.rb @@ -6,6 +6,7 @@ module SpeckleConnector SPECKLE_TYPE = 'speckle_type' APPLICATION_ID = 'application_id' TOTAL_CHILDREN_COUNT = 'total_children_count' + CHILDREN = 'children' PARENT = 'parent' VALID_STREAM_IDS = 'valid_stream_ids' INVALID_STREAM_IDS = 'invalid_stream_ids' diff --git a/speckle_connector/src/convertors/base_object_serializer.rb b/speckle_connector/src/convertors/base_object_serializer.rb index 52b5328..0bce2b0 100644 --- a/speckle_connector/src/convertors/base_object_serializer.rb +++ b/speckle_connector/src/convertors/base_object_serializer.rb @@ -5,6 +5,7 @@ require 'securerandom' # rubocop:enable SketchupPerformance/OpenSSL require 'digest' require_relative 'converter' +require_relative '../speckle_entities/speckle_entity' require_relative '../relations/many_to_one_relation' module SpeckleConnector @@ -117,11 +118,7 @@ module SpeckleConnector if @preferences[:user][:diffing] && !entities.nil? entities.uniq.each do |entity| - speckle_entity = if speckle_state.speckle_entities.keys.include?(entity.persistent_id) - speckle_state.speckle_entities[entity.persistent_id].with_valid_stream_id(stream_id) - else - SpeckleEntities.with_converted(entity, traversed_base, stream_id) - end + speckle_entity = create_or_update_speckle_entity(entity, id, traversed_base) @speckle_state = speckle_state.with_speckle_entity(speckle_entity) end end @@ -345,6 +342,22 @@ module SpeckleConnector speckle_state.speckle_entities[entity.persistent_id].valid_stream_ids.include?(stream_id) end + + # Creates or updates speckle entity. + # If speckle entity exist in state, creates new one by updating old one. + # Else creates new one + # @return [SpeckleEntity] speckle entity that collects both speckle and sketchup information. + def create_or_update_speckle_entity(entity, id, traversed_base) + if speckle_state.speckle_entities.keys.include?(entity.persistent_id) + speckle_state.speckle_entities[entity.persistent_id].with_valid_stream_id(stream_id) + else + children = traversed_base[:__closure].nil? ? {} : traversed_base[:__closure] + speckle_entity = SpeckleEntities::SpeckleEntity.new(entity, id, traversed_base[:speckle_type], + children.keys, [stream_id]) + speckle_entity.write_initial_base_data + speckle_entity + end + end end end end diff --git a/speckle_connector/src/sketchup_model/dictionary/speckle_entity_dictionary_handler.rb b/speckle_connector/src/sketchup_model/dictionary/speckle_entity_dictionary_handler.rb index 172bdff..65a055f 100644 --- a/speckle_connector/src/sketchup_model/dictionary/speckle_entity_dictionary_handler.rb +++ b/speckle_connector/src/sketchup_model/dictionary/speckle_entity_dictionary_handler.rb @@ -12,13 +12,14 @@ module SpeckleConnector # Writes initial data while speckle entity is creating first time. # @param sketchup_entity [Sketchup::Entity] Sketchup entity to write data into it's attribute dictionary. # rubocop:disable Metrics/ParameterLists - def self.write_initial_base_data(sketchup_entity, application_id, id, speckle_type, children_count, stream_id) + def self.write_initial_base_data(sketchup_entity, application_id, id, speckle_type, children, stream_id) initial_dict_data = { # Add here more if you want to write here initial data SPECKLE_ID => id, APPLICATION_ID => application_id, SPECKLE_TYPE => speckle_type, - TOTAL_CHILDREN_COUNT => children_count, + TOTAL_CHILDREN_COUNT => children.length, + CHILDREN => children.keys, VALID_STREAM_IDS => [stream_id], INVALID_STREAM_IDS => [] } diff --git a/speckle_connector/src/speckle_entities/speckle_entity.rb b/speckle_connector/src/speckle_entities/speckle_entity.rb index 2e224fa..6f30a26 100644 --- a/speckle_connector/src/speckle_entities/speckle_entity.rb +++ b/speckle_connector/src/speckle_entities/speckle_entity.rb @@ -13,9 +13,6 @@ module SpeckleConnector # @return [Sketchup::Entity] Sketchup Entity represents {SpeckleEntity} on the model. attr_reader :sketchup_entity - # @return [SpeckleObjects::Base] Speckle object that represented on server. - attr_reader :speckle_object - # @return [String] Speckle object type. attr_reader :speckle_type @@ -43,27 +40,26 @@ module SpeckleConnector attr_reader :source_material, :active_diffing_stream_id # @param sketchup_entity [Sketchup::Entity] sketchup entity represents {SpeckleEntity} on the model. - def initialize(sketchup_entity, traversed_speckle_object, children, stream_id) + # rubocop:disable Metrics/ParameterLists + def initialize(sketchup_entity, speckle_id, speckle_type, children, valid_stream_ids, invalid_stream_ids = []) @status = SpeckleEntityStatus::UP_TO_DATE @source_material = sketchup_entity.material @active_diffing_stream_id = nil - @valid_stream_ids = [stream_id] - @invalid_stream_ids = [] + @valid_stream_ids = valid_stream_ids + @invalid_stream_ids = invalid_stream_ids @sketchup_entity = sketchup_entity @application_id = @sketchup_entity.persistent_id - @id = traversed_speckle_object[:id] - @total_children_count = traversed_speckle_object[:totalChildrenCount] - @speckle_object = traversed_speckle_object - @speckle_type = speckle_object[:speckle_type] + @id = speckle_id + @total_children_count = children.length + @speckle_type = speckle_type @speckle_children_objects = children + end + # rubocop:enable Metrics/ParameterLists + + def write_initial_base_data SketchupModel::Dictionary::SpeckleEntityDictionaryHandler .write_initial_base_data(@sketchup_entity, application_id, id, speckle_type, - @speckle_children_objects.length, stream_id) - - # FIXME: Understand why below condition does not match for same cases. I guess it is a typo bug. - # unless total_children_count == speckle_children_objects.length - # raise StandardError "total children count mismatch for #{application_id}" - # end + @speckle_children_objects, valid_stream_ids.first) end def with_up_to_date From 1b1ae59ed7eb52d56eddaa655c80755da3c8d94d Mon Sep 17 00:00:00 2001 From: oguzhankoral Date: Fri, 24 Feb 2023 19:18:16 +0300 Subject: [PATCH 3/3] Read speckle entities from sketchup model --- .../src/actions/load_sketchup_model.rb | 6 ++- .../reader/speckle_entities_reader.rb | 51 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 speckle_connector/src/sketchup_model/reader/speckle_entities_reader.rb diff --git a/speckle_connector/src/actions/load_sketchup_model.rb b/speckle_connector/src/actions/load_sketchup_model.rb index aca4008..7724af9 100644 --- a/speckle_connector/src/actions/load_sketchup_model.rb +++ b/speckle_connector/src/actions/load_sketchup_model.rb @@ -2,6 +2,7 @@ require_relative 'action' require_relative 'initialize_materials' +require_relative '../sketchup_model/reader/speckle_entities_reader' require_relative '../preferences/preferences' require_relative '../states/state' require_relative '../states/sketchup_state' @@ -23,7 +24,10 @@ module SpeckleConnector # Init materials again new_state = InitializeMaterials.update_state(new_state) - # TODO: Read here SpeckleEntities if they exist in model. + # Read speckle entities + new_speckle_entities = SketchupModel::Reader::SpeckleEntitiesReader.read(sketchup_model.entities) + new_speckle_state = new_state.speckle_state.with_speckle_entities(Immutable::Hash.new(new_speckle_entities)) + new_state = new_state.with_speckle_state(new_speckle_state) # Read preferences from database and model. preferences = Preferences.read_preferences(new_state.sketchup_state.sketchup_model) diff --git a/speckle_connector/src/sketchup_model/reader/speckle_entities_reader.rb b/speckle_connector/src/sketchup_model/reader/speckle_entities_reader.rb new file mode 100644 index 0000000..f8a5243 --- /dev/null +++ b/speckle_connector/src/sketchup_model/reader/speckle_entities_reader.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require_relative '../../speckle_entities/speckle_entity' +require_relative '../../constants/dict_constants' + +module SpeckleConnector + # Operations related to {SketchupModel}. + module SketchupModel + # Reader model for sketchup model. + module Reader + # Reader module for speckle entities. + module SpeckleEntitiesReader + # @param entities [Sketchup::Entities] entities to collect speckle entities. + def self.read(entities) + speckle_entities = {} + entities.each do |entity| + speckle_entities[entity.persistent_id] = read_speckle_entity(entity) if speckle_entity?(entity) + next unless entity.is_a?(Sketchup::Group) || entity.is_a?(Sketchup::ComponentInstance) + + if speckle_entity?(entity.definition) + speckle_entities[entity.definition.persistent_id] = read_speckle_entity(entity.definition) + end + definition_speckle_entities = read(entity.definition.entities) + speckle_entities = speckle_entities.merge(definition_speckle_entities) + end + speckle_entities + end + + # @param entity [Sketchup::Entity] sketchup entity to read from attribute dictionary. + def self.read_speckle_entity(entity) + dict = entity.attribute_dictionaries.to_a.find { |dict| dict.name == SPECKLE_BASE_OBJECT } + speckle_id = dict[:speckle_id] + speckle_type = dict[:speckle_type] + children = dict[:children] + valid_stream_ids = dict[:valid_stream_ids] + invalid_stream_ids = dict[:invalid_stream_ids] + SpeckleEntities::SpeckleEntity.new(entity, speckle_id, speckle_type, children, + valid_stream_ids, invalid_stream_ids) + end + + # @param entity [Sketchup::Entity] sketchup entity to check if it was speckle entity once. + def self.speckle_entity?(entity) + return false if entity.attribute_dictionaries.nil? + return false if entity.attribute_dictionaries.to_a.empty? + + entity.attribute_dictionaries.to_a.any? { |dict| dict.name == SPECKLE_BASE_OBJECT } + end + end + end + end +end