Compare commits

..

38 Commits

Author SHA1 Message Date
David Kekesi 30163bfd9d export mesh, vertices, faces, colors 2024-10-11 12:44:55 +02:00
Ralph Wessel 21fc2cff25 Added FinishCollector interface as a serialisation manager to collect finishes from meshes as they are serialised
ProjectCollection is now a FinishCollector (accumulates the finishes to write the material proxies at the end)
2024-10-11 09:58:26 +01:00
Ralph Wessel 0c74a28982 Fixes to Storey attribute class 2024-10-10 13:45:36 +01:00
Ralph Wessel cc64d7df44 Added lookup for AC storeys using an element floor index 2024-10-10 13:02:57 +01:00
Ralph Wessel f7112a407c Set correct base class for RecordCollection
RecordCollection serialises name
2024-10-10 12:12:35 +01:00
Ralph Wessel 7ed4d8c807 Updated VS projects 2024-10-10 10:45:35 +01:00
Ralph Wessel b5447b263e NB: Interim commit - new code is untested at this point
Information sent to Speckle is now presented in hiearchical collections:
- Root level contains material proxies
- Second level is project storeys
- Third level is element type
Added database and record definitions for attributes including:
- Finishes (surface rendering material)
- Storeys
Element getters for storey and type name
Aligned some speckle_type names to Revit (where possible)
2024-10-10 08:52:18 +01:00
Ralph Wessel b51b0ecb13 Mesh serialises with speckle_type and units - now appears in 3D view 2024-10-04 22:13:32 +01:00
Ralph Wessel 72cd75d2e6 Added speckle_type and unit properties to Record, BIMRecord, Element and Mesh classes
Defined (de)serialisation for LengthType
2024-10-04 21:03:54 +01:00
Ralph Wessel 3e2777a38f Merge branch 'david/cnx-577-implement-mesh-class' into develop 2024-10-03 17:55:44 +01:00
Ralph Wessel 042a515dc4 Removed test code from palette 2024-10-03 17:54:01 +01:00
Ralph Wessel f5bb3dc454 Fix to element mesh face indices 2024-10-03 17:50:50 +01:00
Ralph Wessel f066b0ee02 Send bridge method injects the first selected element into the sent data for testing
Mesh vertices, faces and colours are all single arrays
2024-10-03 17:05:02 +01:00
Ralph Wessel 8dd00005b1 Element is a type of BIMRecord 2024-10-03 16:39:21 +01:00
Ralph Wessel 0592bcc947 BIMRecord is a type of Record (adds applicationID) 2024-10-03 16:31:58 +01:00
Ralph Wessel 76348c8fd1 Merge branch 'develop' into david/cnx-577-implement-mesh-class 2024-10-03 15:51:27 +01:00
Ralph Wessel 1a61608c42 Using preview interface for testing 2024-10-03 14:33:52 +01:00
Ralph Wessel 844ab3544b Commit working 2024-10-03 14:32:30 +01:00
Ralph Wessel 990a1ab9e1 Updated for VS 2024-10-03 13:48:22 +01:00
David Kekesi 6cf03010bd mesh export WIP 2024-10-03 14:39:09 +02:00
Ralph Wessel a0413d0d3a SendObject now holds and sends a Record 2024-10-03 13:12:57 +01:00
Ralph Wessel 8539129e7c SendObject now the owner of the object to be sent 2024-10-03 12:33:08 +01:00
Ralph Wessel 1a901b0a6c Send bridge is updated:
- total children removed
- rootObject replaces batches (sent as an object rather than a string)
2024-10-03 12:05:48 +01:00
Ralph Wessel cc034191b4 Updated with GetSendSettings 2024-10-02 12:54:48 +01:00
Ralph Wessel a6911fad1c Added GetSendSettings binding 2024-10-02 10:09:28 +01:00
Ralph Wessel fdf371732b Updated serialisation for send objects 2024-10-02 09:30:53 +01:00
Ralph Wessel e9f8e86f95 Dummy information in SendObject 2024-10-01 18:58:50 +01:00
Ralph Wessel 8eae1e9967 Updated VS projects 2024-10-01 18:24:33 +01:00
Ralph Wessel 8ed2abea04 Implemented skeleton of SendObject 2024-10-01 18:21:30 +01:00
Ralph Wessel e148094c81 ModelCardDatabase can retrieve a card by ID
Added numerous Send argument classes:
- ConversionResult (incomplete)
- SendError
- SendObject
- SendViaBrowserArgs (incomplete)
Send method looks up model card and account details, constructs send arguments
AccountDatabase can find an account by ID or server URL
Added DetachedMemoryStore
2024-10-01 17:24:59 +01:00
Ralph Wessel deee1e80c5 Added classes for managing detached objects:
- DetachmentManager: Manages detached objects during (de)serialisation
- DetachedWrap: Wrapper for detached objects, generating references on demand from serialised data
- DetachedReference: Wrapper for representation of wrapped objects with a reference
- DetachedObjectStore: Interface for filing/retrieving detached objects in storage
2024-09-30 10:50:24 +01:00
Ralph Wessel 4c8a2237bf Removed testing code 2024-09-26 13:28:14 +01:00
Ralph Wessel 5abc831473 Implemented Archicad element database functionality:
- Retrieving the database from the Project
- Gettting selected elements
- Getting an element from an index/link
2024-09-26 13:05:22 +01:00
Ralph Wessel b8d952c9a3 Updated Send method to trigger a browser event rather than throwing an exception
Added new resources
2024-09-25 13:29:33 +01:00
Ralph Wessel 7baedf707a Updated VS projects 2024-09-24 22:29:40 +01:00
Ralph Wessel 4dd0a1b1b6 Added skeleton BIM database, element, collection and Mesh classes to support sending model data 2024-09-24 21:50:28 +01:00
Ralph Wessel 29ece2282f Added DocumentStoreEngine::getUniqueID
Added ModelCardDatabase::getStoreID
2024-09-23 16:01:35 +01:00
Ralph Wessel f0fc7e8fec Merge tag '0.2.4' into develop
0.2.4
2024-09-23 14:10:34 +01:00
90 changed files with 6245 additions and 79 deletions
+16
View File
@@ -111,7 +111,12 @@
<ClCompile Include="Connector\Interface\Browser\Bridge\Config\GetConfig.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Config\GetIsDevMode.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Config\UpdateConfig.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\Arg\ConversionResult.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\Arg\SendError.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\Arg\SendObject.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\Arg\SendViaBrowserArgs.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\GetSendFilters.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\GetSendSettings.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\Send.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\SendBridge.cpp" />
<ClCompile Include="Connector\Interface\Browser\Bridge\Test\Arg\SayHiArg.cpp" />
@@ -122,6 +127,9 @@
<ClCompile Include="Connector\Interface\Browser\Bridge\Test\TriggerEvent.cpp" />
<ClCompile Include="Connector\Interface\ConnectorMenu.cpp" />
<ClCompile Include="Connector\Interface\ConnectorPalette.cpp" />
<ClCompile Include="Connector\Record\Collection\FinishProxy.cpp" />
<ClCompile Include="Connector\Record\Collection\ProjectCollection.cpp" />
<ClCompile Include="Connector\Record\Collection\RecordCollection.cpp" />
<ClCompile Include="Connector\Record\Model\CardMover.cpp" />
<ClCompile Include="Connector\Record\Model\CardSetting.cpp" />
<ClCompile Include="Connector\Record\Model\Filter\DirectSelectionSendFilter.cpp" />
@@ -155,7 +163,12 @@
<ClInclude Include="Connector\Interface\Browser\Bridge\Config\GetConfig.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Config\GetIsDevMode.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Config\UpdateConfig.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\Arg\ConversionResult.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\Arg\SendError.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\Arg\SendObject.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\Arg\SendViaBrowserArgs.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\GetSendFilters.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\GetSendSettings.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\Send.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\SendBridge.h" />
<ClInclude Include="Connector\Interface\Browser\Bridge\Test\Arg\SayHiArg.h" />
@@ -166,6 +179,9 @@
<ClInclude Include="Connector\Interface\Browser\Bridge\Test\TriggerEvent.h" />
<ClInclude Include="Connector\Interface\ConnectorMenu.h" />
<ClInclude Include="Connector\Interface\ConnectorPalette.h" />
<ClInclude Include="Connector\Record\Collection\FinishProxy.h" />
<ClInclude Include="Connector\Record\Collection\ProjectCollection.h" />
<ClInclude Include="Connector\Record\Collection\RecordCollection.h" />
<ClInclude Include="Connector\Record\Model\CardMover.h" />
<ClInclude Include="Connector\Record\Model\CardSetting.h" />
<ClInclude Include="Connector\Record\Model\Filter\ArchicadEverythingFilter.h" />
@@ -59,6 +59,12 @@
<Filter Include="Connector\Record\Model\Filter">
<UniqueIdentifier>{b6d6326c-77f4-414a-bda6-e3e587c7ded2}</UniqueIdentifier>
</Filter>
<Filter Include="Connector\Record\Collection">
<UniqueIdentifier>{0ac4b0a4-6a2a-4a48-9757-1172effc20e7}</UniqueIdentifier>
</Filter>
<Filter Include="Connector\Interface\Browser\Bridge\Send\Arg">
<UniqueIdentifier>{6693f9a9-5ece-4853-b008-4064d1c551ab}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="RFIX.win\Connector.rc2">
@@ -198,6 +204,30 @@
<ClCompile Include="Connector\Interface\Browser\Bridge\Base\UpdateModel.cpp">
<Filter>Connector\Interface\Browser\Bridge\Base</Filter>
</ClCompile>
<ClCompile Include="Connector\Record\Collection\RecordCollection.cpp">
<Filter>Connector\Record\Collection</Filter>
</ClCompile>
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\Arg\ConversionResult.cpp">
<Filter>Connector\Interface\Browser\Bridge\Send\Arg</Filter>
</ClCompile>
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\Arg\SendError.cpp">
<Filter>Connector\Interface\Browser\Bridge\Send\Arg</Filter>
</ClCompile>
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\Arg\SendViaBrowserArgs.cpp">
<Filter>Connector\Interface\Browser\Bridge\Send\Arg</Filter>
</ClCompile>
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\Arg\SendObject.cpp">
<Filter>Connector\Interface\Browser\Bridge\Send\Arg</Filter>
</ClCompile>
<ClCompile Include="Connector\Interface\Browser\Bridge\Send\GetSendSettings.cpp">
<Filter>Connector\Interface\Browser\Bridge\Send</Filter>
</ClCompile>
<ClCompile Include="Connector\Record\Collection\FinishProxy.cpp">
<Filter>Connector\Record\Collection</Filter>
</ClCompile>
<ClCompile Include="Connector\Record\Collection\ProjectCollection.cpp">
<Filter>Connector\Record\Collection</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Connector\ConnectorResource.h">
@@ -333,5 +363,29 @@
<ClInclude Include="Connector\Interface\Browser\Bridge\Base\UpdateModel.h">
<Filter>Connector\Interface\Browser\Bridge\Base</Filter>
</ClInclude>
<ClInclude Include="Connector\Record\Collection\RecordCollection.h">
<Filter>Connector\Record\Collection</Filter>
</ClInclude>
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\Arg\ConversionResult.h">
<Filter>Connector\Interface\Browser\Bridge\Send\Arg</Filter>
</ClInclude>
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\Arg\SendError.h">
<Filter>Connector\Interface\Browser\Bridge\Send\Arg</Filter>
</ClInclude>
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\Arg\SendObject.h">
<Filter>Connector\Interface\Browser\Bridge\Send\Arg</Filter>
</ClInclude>
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\Arg\SendViaBrowserArgs.h">
<Filter>Connector\Interface\Browser\Bridge\Send\Arg</Filter>
</ClInclude>
<ClInclude Include="Connector\Interface\Browser\Bridge\Send\GetSendSettings.h">
<Filter>Connector\Interface\Browser\Bridge\Send</Filter>
</ClInclude>
<ClInclude Include="Connector\Record\Collection\FinishProxy.h">
<Filter>Connector\Record\Collection</Filter>
</ClInclude>
<ClInclude Include="Connector\Record\Collection\ProjectCollection.h">
<Filter>Connector\Record\Collection</Filter>
</ClInclude>
</ItemGroup>
</Project>
@@ -29,7 +29,14 @@
215F082E2C94C5C000CD343B /* FilterMover.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 215F082C2C94C5C000CD343B /* FilterMover.cpp */; };
215F08372C95808B00CD343B /* ReceiverModelCard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 215F08362C95808B00CD343B /* ReceiverModelCard.cpp */; };
215F08462C9633A800CD343B /* EverythingSendFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 215F08452C9633A800CD343B /* EverythingSendFilter.cpp */; };
2192460D2CA3469D00CF5703 /* ProjectCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2192460B2CA3469D00CF5703 /* ProjectCollection.cpp */; };
219F30422C769283009834E9 /* ConfigTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219F30402C769282009834E9 /* ConfigTests.cpp */; };
21A0FB982CB723240023F24E /* FinishProxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21A0FB942CB723240023F24E /* FinishProxy.cpp */; };
21AEF9EB2CAB56E5000B8681 /* SendError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9E32CAB56E5000B8681 /* SendError.cpp */; };
21AEF9EC2CAB56E5000B8681 /* SendViaBrowserArgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9E52CAB56E5000B8681 /* SendViaBrowserArgs.cpp */; };
21AEF9EF2CAB5720000B8681 /* SendObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9EE2CAB5720000B8681 /* SendObject.cpp */; };
21AEF9FA2CAC3897000B8681 /* ConversionResult.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9F92CAC3897000B8681 /* ConversionResult.cpp */; };
21AEF9FD2CAD3FD8000B8681 /* GetSendSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9FB2CAD3FD8000B8681 /* GetSendSettings.cpp */; };
21B67CA32C769CB400FD64FC /* libActiveLib.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 21F69EF52C64FE91008B6A06 /* libActiveLib.a */; };
21B67CA42C769CB400FD64FC /* libArchicad27.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 21F69ECD2C64C035008B6A06 /* libArchicad27.a */; };
21B67CAC2C77329800FD64FC /* BaseBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21B67CA52C77329800FD64FC /* BaseBridge.cpp */; };
@@ -220,6 +227,7 @@
21F69F8D2C70D7EE008B6A06 /* GetAccounts.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69F8B2C70D7EE008B6A06 /* GetAccounts.cpp */; };
21F69FBB2C762EF0008B6A06 /* ConfigBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69FB42C762EF0008B6A06 /* ConfigBridge.cpp */; };
21F69FBC2C762EF0008B6A06 /* GetConfig.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21F69FB62C762EF0008B6A06 /* GetConfig.cpp */; };
21FF70492CA1A7F400AAD99A /* RecordCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21FF70462CA1A7F400AAD99A /* RecordCollection.cpp */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -298,10 +306,24 @@
215F08452C9633A800CD343B /* EverythingSendFilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EverythingSendFilter.cpp; sourceTree = "<group>"; };
215F084A2C9782F100CD343B /* ArchicadEverythingFilter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ArchicadEverythingFilter.h; sourceTree = "<group>"; };
2161FD902BF2600C006D9527 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
2192460B2CA3469D00CF5703 /* ProjectCollection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProjectCollection.cpp; sourceTree = "<group>"; };
2192460C2CA3469D00CF5703 /* ProjectCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProjectCollection.h; sourceTree = "<group>"; };
219388682C4E5DE2002A0180 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
219F30352C768F0A009834E9 /* Connector-AC27-Test.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Connector-AC27-Test.bundle"; sourceTree = BUILT_PRODUCTS_DIR; };
219F30402C769282009834E9 /* ConfigTests.cpp */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; path = ConfigTests.cpp; sourceTree = "<group>"; };
219F30432C7693B6009834E9 /* Connector-AC27-Debug.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = "Connector-AC27-Debug.xctestplan"; sourceTree = SOURCE_ROOT; };
21A0FB942CB723240023F24E /* FinishProxy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FinishProxy.cpp; sourceTree = "<group>"; };
21A0FB972CB723240023F24E /* FinishProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FinishProxy.h; sourceTree = "<group>"; };
21AEF9E32CAB56E5000B8681 /* SendError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SendError.cpp; sourceTree = "<group>"; };
21AEF9E42CAB56E5000B8681 /* SendError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SendError.h; sourceTree = "<group>"; };
21AEF9E52CAB56E5000B8681 /* SendViaBrowserArgs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SendViaBrowserArgs.cpp; sourceTree = "<group>"; };
21AEF9E62CAB56E5000B8681 /* SendViaBrowserArgs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SendViaBrowserArgs.h; sourceTree = "<group>"; };
21AEF9ED2CAB5720000B8681 /* SendObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SendObject.h; sourceTree = "<group>"; };
21AEF9EE2CAB5720000B8681 /* SendObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SendObject.cpp; sourceTree = "<group>"; };
21AEF9F82CAC3897000B8681 /* ConversionResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConversionResult.h; sourceTree = "<group>"; };
21AEF9F92CAC3897000B8681 /* ConversionResult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConversionResult.cpp; sourceTree = "<group>"; };
21AEF9FB2CAD3FD8000B8681 /* GetSendSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetSendSettings.cpp; sourceTree = "<group>"; };
21AEF9FC2CAD3FD8000B8681 /* GetSendSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetSendSettings.h; sourceTree = "<group>"; };
21B67CA52C77329800FD64FC /* BaseBridge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BaseBridge.cpp; sourceTree = "<group>"; };
21B67CA62C77329800FD64FC /* BaseBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseBridge.h; sourceTree = "<group>"; };
21B67CA72C77329800FD64FC /* GetSourceApplicationName.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetSourceApplicationName.cpp; sourceTree = "<group>"; };
@@ -534,6 +556,8 @@
21F69FB72C762EF0008B6A06 /* GetConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetConfig.h; sourceTree = "<group>"; };
21F69FBD2C7630B3008B6A06 /* UpdateConfig.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UpdateConfig.cpp; sourceTree = "<group>"; };
21F69FBE2C7630B3008B6A06 /* UpdateConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UpdateConfig.h; sourceTree = "<group>"; };
21FF70462CA1A7F400AAD99A /* RecordCollection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RecordCollection.cpp; sourceTree = "<group>"; };
21FF70472CA1A7F400AAD99A /* RecordCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecordCollection.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -939,6 +963,21 @@
path = ConnectorTests;
sourceTree = "<group>";
};
21AEF9E72CAB56E5000B8681 /* Arg */ = {
isa = PBXGroup;
children = (
21AEF9F92CAC3897000B8681 /* ConversionResult.cpp */,
21AEF9F82CAC3897000B8681 /* ConversionResult.h */,
21AEF9E32CAB56E5000B8681 /* SendError.cpp */,
21AEF9E42CAB56E5000B8681 /* SendError.h */,
21AEF9EE2CAB5720000B8681 /* SendObject.cpp */,
21AEF9ED2CAB5720000B8681 /* SendObject.h */,
21AEF9E52CAB56E5000B8681 /* SendViaBrowserArgs.cpp */,
21AEF9E62CAB56E5000B8681 /* SendViaBrowserArgs.h */,
);
path = Arg;
sourceTree = "<group>";
};
21B67CAB2C77329800FD64FC /* Base */ = {
isa = PBXGroup;
children = (
@@ -1023,8 +1062,11 @@
21D0BD5D2C89BFEA0077E104 /* Send */ = {
isa = PBXGroup;
children = (
21AEF9E72CAB56E5000B8681 /* Arg */,
21D0BD962C8F13F30077E104 /* GetSendFilters.cpp */,
21D0BD952C8F13F30077E104 /* GetSendFilters.h */,
21AEF9FB2CAD3FD8000B8681 /* GetSendSettings.cpp */,
21AEF9FC2CAD3FD8000B8681 /* GetSendSettings.h */,
21D0BD8D2C8EE4490077E104 /* Send.cpp */,
21D0BD8A2C8EE4490077E104 /* Send.h */,
21D0BD5B2C89BFEA0077E104 /* SendBridge.cpp */,
@@ -1036,6 +1078,7 @@
21D0BDD82C9387E60077E104 /* Record */ = {
isa = PBXGroup;
children = (
21FF70482CA1A7F400AAD99A /* Collection */,
21D0BDD92C9387F70077E104 /* Model */,
);
path = Record;
@@ -1188,6 +1231,19 @@
path = Config;
sourceTree = "<group>";
};
21FF70482CA1A7F400AAD99A /* Collection */ = {
isa = PBXGroup;
children = (
21A0FB942CB723240023F24E /* FinishProxy.cpp */,
21A0FB972CB723240023F24E /* FinishProxy.h */,
21FF70462CA1A7F400AAD99A /* RecordCollection.cpp */,
21FF70472CA1A7F400AAD99A /* RecordCollection.h */,
2192460B2CA3469D00CF5703 /* ProjectCollection.cpp */,
2192460C2CA3469D00CF5703 /* ProjectCollection.h */,
);
path = Collection;
sourceTree = "<group>";
};
7EA5F91E157FA18400693CEA /* EN-GB */ = {
isa = PBXGroup;
children = (
@@ -1393,8 +1449,10 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
21AEF9FA2CAC3897000B8681 /* ConversionResult.cpp in Sources */,
21D0BDAB2C8F363E0077E104 /* CardSetting.cpp in Sources */,
21B67CE32C78D1FB00FD64FC /* SayHiArg.cpp in Sources */,
21AEF9EB2CAB56E5000B8681 /* SendError.cpp in Sources */,
215F08462C9633A800CD343B /* EverythingSendFilter.cpp in Sources */,
21F69FBB2C762EF0008B6A06 /* ConfigBridge.cpp in Sources */,
21F69F8A2C70D2C4008B6A06 /* AccountBridge.cpp in Sources */,
@@ -1403,16 +1461,21 @@
21B67CF72C78D4DE00FD64FC /* GetComplexType.cpp in Sources */,
21D0BDDC2C93897B0077E104 /* SenderModelCard.cpp in Sources */,
21B67CAE2C77329800FD64FC /* GetSourceApplicationVersion.cpp in Sources */,
21A0FB982CB723240023F24E /* FinishProxy.cpp in Sources */,
21B67CC32C77649F00FD64FC /* GetDocumentState.cpp in Sources */,
21D0BD602C89BFEA0077E104 /* SendBridge.cpp in Sources */,
21D0BD972C8F13F30077E104 /* GetSendFilters.cpp in Sources */,
21B67CAC2C77329800FD64FC /* BaseBridge.cpp in Sources */,
2192460D2CA3469D00CF5703 /* ProjectCollection.cpp in Sources */,
21D0BD6A2C8A0DB40077E104 /* GetIsDevMode.cpp in Sources */,
210CC8832C80E6A300610F58 /* TriggerEvent.cpp in Sources */,
21B67CEB2C78D27200FD64FC /* DocumentInfo.cpp in Sources */,
21B67CB92C774BFA00FD64FC /* GetConnectorVersion.cpp in Sources */,
21B67CD92C78C83800FD64FC /* TestBridge.cpp in Sources */,
21AEF9FD2CAD3FD8000B8681 /* GetSendSettings.cpp in Sources */,
214B7A372C764BCD00D586C1 /* UpdateConfig.cpp in Sources */,
21AEF9EC2CAB56E5000B8681 /* SendViaBrowserArgs.cpp in Sources */,
21FF70492CA1A7F400AAD99A /* RecordCollection.cpp in Sources */,
21B67CC02C775A0D00FD64FC /* GetDocumentInfo.cpp in Sources */,
21D0BDD42C935D1A0077E104 /* UpdateModel.cpp in Sources */,
21B67CE72C78D23B00FD64FC /* ConnectorConfig.cpp in Sources */,
@@ -1422,6 +1485,7 @@
215F082A2C947F4400CD343B /* CardMover.cpp in Sources */,
215F08372C95808B00CD343B /* ReceiverModelCard.cpp in Sources */,
21D0BDD72C935DAE0077E104 /* RemoveModel.cpp in Sources */,
21AEF9EF2CAB5720000B8681 /* SendObject.cpp in Sources */,
21B67CDC2C78C88000FD64FC /* SayHi.cpp in Sources */,
215F082E2C94C5C000CD343B /* FilterMover.cpp in Sources */,
21F69F122C677BC0008B6A06 /* ConnectorMenu.cpp in Sources */,
+7 -7
View File
@@ -2,8 +2,8 @@
#include "ConnectorResource.h"
#include "Connector/Connector.h"
#include "Connector/Database/ModelCardDatabase.h"
#include "Interface/ConnectorMenu.h"
#include "Interface/ConnectorPalette.h"
#include "Connector/Interface/ConnectorMenu.h"
#include "Connector/Interface/ConnectorPalette.h"
#include "Speckle/Database/AccountDatabase.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/Utility/String.h"
@@ -35,16 +35,16 @@ namespace {
// MARK: Functions (const)
/*!
Get the model card database
@return The model card database
*/
const ModelCardDatabase* getModelCardDatabase() const override { return &m_modelCards; }
/*!
Get the account database
@return The account database
*/
const AccountDatabase* getAccountDatabase() const override;
/*!
Get the model card database
@return The model card database
*/
const ModelCardDatabase* getModelCardDatabase() const override { return &m_modelCards; }
private:
mutable std::unique_ptr<AccountDatabase> m_account;
+6 -5
View File
@@ -3,6 +3,7 @@
namespace speckle::database {
class AccountDatabase;
class BIMElementDatabase;
}
namespace connector::database {
class ModelCardDatabase;
@@ -16,16 +17,16 @@ namespace connector {
// MARK: Functions (const)
/*!
Get the model card database
@return The model card database
*/
const virtual database::ModelCardDatabase* getModelCardDatabase() const = 0;
/*!
Get the account database
@return The account database
*/
const virtual speckle::database::AccountDatabase* getAccountDatabase() const = 0;
/*!
Get the model card database
@return The model card database
*/
const virtual database::ModelCardDatabase* getModelCardDatabase() const = 0;
protected:
/*!
@@ -28,6 +28,7 @@ enum StringResource {
enum TitleString {
addonNameID = 1,
addonDescriptionID,
noStoreyID,
};
@@ -37,7 +38,7 @@ enum PromptString {
//Information strings (in UI content, logging, reports)
enum InfoString {
enum GeneralString {
};
@@ -53,6 +54,10 @@ enum WarningString {
//Error strings (errors displayed in alerts)
enum ErrorString {
noSelectedModelItemsID = 1,
modelCardNotFoundID,
noProjectOpenID,
accountNotFoundID,
};
#endif //CONNECTOR_RESOURCE
@@ -71,6 +71,16 @@ ModelCardDatabase::ModelCardDatabase() {
ModelCardDatabase::~ModelCardDatabase() {}
/*--------------------------------------------------------------------
Get a specified card from the database
return: The requested card (nullptr on failure)
--------------------------------------------------------------------*/
ModelCard::Unique ModelCardDatabase::getCard(const speckle::utility::String& cardID) const {
return m_store->getObject(cardID);
} //ModelCardDatabase::getCard
/*--------------------------------------------------------------------
Get all model cards
@@ -101,6 +111,16 @@ void ModelCardDatabase::erase(const String& cardID) const {
} //ModelCardDatabase::erase
/*--------------------------------------------------------------------
Get the unique ID of the engine storage
return: The databas unique ID
--------------------------------------------------------------------*/
RecordID ModelCardDatabase::getStoreID() const {
return m_engine->getUniqueID();
} //ModelCardDatabase::getStoreID
/*--------------------------------------------------------------------
Get a serialisation wrapper for the database
@@ -29,6 +29,11 @@ namespace connector::database {
// MARK: - Functions (const)
/*!
Get a specified card from the database
@return The requested card (nullptr on failure)
*/
record::ModelCard::Unique getCard(const speckle::utility::String& cardID) const;
/*!
Get all model cards
@return All the cards
@@ -49,6 +54,11 @@ namespace connector::database {
@return A database wrapper
*/
std::unique_ptr<active::serialise::Cargo> wrapper() const;
/*!
Get the unique ID of the engine storage
@return The database unique ID
*/
speckle::database::RecordID getStoreID() const;
// MARK: - Functions (mutating)
@@ -39,20 +39,20 @@ namespace connector::interfac::browser::bridge {
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
/*!
Set to the default package content
*/
Set to the default package content
*/
void setDefault() override;
};
@@ -2,6 +2,7 @@
#include "Active/Serialise/CargoHold.h"
#include "Connector/Connector.h"
#include "Connector/Database/ModelCardDatabase.h"
#include "Connector/Interface/Browser/Bridge/Base/Arg/DocumentInfo.h"
#include "Speckle/Environment/Project.h"
#include "Speckle/Utility/Guid.h"
@@ -37,7 +38,8 @@ std::unique_ptr<Cargo> GetDocumentInfo::run() const {
docInfo->name = info.name;
if (info.path)
docInfo->location = *info.path;
//TODO: No suitable project ID is currently available
if (auto cardDatabase = connector()->getModelCardDatabase(); cardDatabase != nullptr)
docInfo->ID = cardDatabase->getStoreID();
docInfo->ID = Guid{true}.operator String();
}
return std::make_unique<WrappedValue>(std::move(docInfo));
@@ -1,7 +1,6 @@
#include "Connector/Interface/Browser/Bridge/Base/GetDocumentState.h"
#include "Active/Serialise/CargoHold.h"
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
#include "Connector/Connector.h"
#include "Connector/Record/Model/ModelCard.h"
#include "Connector/Database/ModelCardDatabase.h"
@@ -0,0 +1,65 @@
#include "Connector/Interface/Browser/Bridge/Send/Arg/ConversionResult.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include <array>
using namespace active::serialise;
using namespace connector::interfac::browser::bridge;
using namespace speckle::utility;
namespace {
///Serialisation fields
enum FieldIndex {
errorID,
cardID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"error"},
Identity{"modelCardId"},
};
}
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool ConversionResult::fillInventory(active::serialise::Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[errorID], errorID, element },
{ fieldID[cardID], cardID, element },
},
}.withType(&typeid(ConversionResult)));
return true;
} //ConversionResult::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique ConversionResult::getCargo(const active::serialise::Inventory::Item& item) const {
if (item.ownerType != &typeid(ConversionResult))
return nullptr;
using namespace active::serialise;
switch (item.index) {
case errorID:
return std::make_unique<ValueWrap<String>>(message);
case cardID:
return std::make_unique<ValueWrap<String>>(modelCardID);
default:
return nullptr; //Requested an unknown index
}
} //ConversionResult::getCargo
@@ -0,0 +1,68 @@
#ifndef CONNECTOR_INTERFACE_BRIDGE_SEND_CONVERSION_RESULT
#define CONNECTOR_INTERFACE_BRIDGE_SEND_CONVERSION_RESULT
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendError.h"
#include "Speckle/Utility/String.h"
namespace connector::interfac::browser::bridge {
/*!
A send error to return to the JS in the event of an error
*/
class ConversionResult final : public active::serialise::Package {
public:
enum class Status {
success = 1,
info,
warning,
error,
};
// MARK: - Constructors
/*!
Constructor
@param errMess The error message
@param card The ID of the model card associated with the wrror
*/
ConversionResult(const speckle::utility::String& errMess, const speckle::utility::String& card) : message{errMess}, modelCardID{card} {}
// MARK: - Public variables
///The error message
speckle::utility::String message;
///The ID of the model card associated with the data
speckle::utility::String modelCardID;
///The element conversion status
Status status = Status::info;
///For receive conversion reports, this is the id of the speckle object. For send, it's the host app object id.
speckle::utility::String sourceId;
///For receive conversion reports, this is the type of the speckle object. For send, it's the host app object type.
speckle::utility::String sourceType;
///For receive conversion reports, this is the id of the host app object. For send, it's the speckle object id.
speckle::utility::String resultId;
///For receive conversion reports, this is the type of the host app object. For send, it's the speckle object type.
speckle::utility::String resultType;
///The exception (nullopt = no exception)
SendError::Option error;
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
};
}
#endif //CONNECTOR_INTERFACE_BRIDGE_SEND_CONVERSION_RESULT
@@ -0,0 +1,65 @@
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendError.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include <array>
using namespace active::serialise;
using namespace connector::interfac::browser::bridge;
using namespace speckle::utility;
namespace {
///Serialisation fields
enum FieldIndex {
errorID,
cardID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"error"},
Identity{"modelCardId"},
};
}
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool SendError::fillInventory(active::serialise::Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[errorID], errorID, element },
{ fieldID[cardID], cardID, element },
},
}.withType(&typeid(SendError)));
return true;
} //SendError::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique SendError::getCargo(const active::serialise::Inventory::Item& item) const {
if (item.ownerType != &typeid(SendError))
return nullptr;
using namespace active::serialise;
switch (item.index) {
case errorID:
return std::make_unique<ValueWrap<String>>(message);
case cardID:
return std::make_unique<ValueWrap<String>>(modelCardID);
default:
return nullptr; //Requested an unknown index
}
} //SendError::getCargo
@@ -0,0 +1,54 @@
#ifndef CONNECTOR_INTERFACE_BRIDGE_SEND_ERROR
#define CONNECTOR_INTERFACE_BRIDGE_SEND_ERROR
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Speckle/Utility/String.h"
namespace connector::interfac::browser::bridge {
/*!
A send error to return to the JS in the event of an error
*/
class SendError final : public active::serialise::Package {
public:
// MARK: Types
///Optional
using Option = std::optional<SendError>;
// MARK: - Constructors
/*!
Constructor
@param errMess The error message
@param card The ID of the model card associated with the wrror
*/
SendError(const speckle::utility::String& errMess, const speckle::utility::String& card) : message{errMess}, modelCardID{card} {}
// MARK: - Public variables
///The error message
speckle::utility::String message;
///The ID of the model card associated with the data
speckle::utility::String modelCardID;
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
};
}
#endif //CONNECTOR_INTERFACE_BRIDGE_SEND_ERROR
@@ -0,0 +1,69 @@
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendObject.h"
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include <array>
using namespace active::serialise;
using namespace connector::interfac::browser::bridge;
using namespace speckle::serialise;
using namespace speckle::utility;
namespace {
///Serialisation fields
enum FieldIndex {
idID,
rootObjID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"id"},
Identity{"rootObject"},
};
}
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool SendObject::fillInventory(active::serialise::Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[idID], idID, element },
{ fieldID[rootObjID], rootObjID, element },
},
}.withType(&typeid(SendObject)));
return true;
} //SendObject::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique SendObject::getCargo(const active::serialise::Inventory::Item& item) const {
if (item.ownerType != &typeid(SendObject))
return nullptr;
using namespace active::serialise;
switch (item.index) {
case idID:
return std::make_unique<StringWrap>(id);
case rootObjID:
if (m_object)
return std::make_unique<PackageWrap>(*m_object);
return std::make_unique<NullPackage>();
default:
return nullptr; //Requested an unknown index
}
} //SendObject::getCargo
@@ -0,0 +1,54 @@
#ifndef CONNECTOR_INTERFACE_BRIDGE_SEND_OBJECT
#define CONNECTOR_INTERFACE_BRIDGE_SEND_OBJECT
#include "Active/Serialise/CargoHold.h"
#include "Connector/Interface/Browser/Bridge/Config/Arg/ConnectorConfig.h"
#include "Speckle/Database/Content/Record.h"
#include "Speckle/Interface/Browser/Bridge/BridgeMethod.h"
namespace connector::interfac::browser::bridge {
/*!
Class defining the primary content of a send
*/
class SendObject final : public active::serialise::Package {
public:
using base = std::reference_wrapper<active::serialise::Package>;
// MARK: - Constructors
/*!
Default constructor
@param object The object to send
*/
SendObject(std::unique_ptr<speckle::database::Record> object) : m_object{std::move(object)} { id = m_object->getID(); }
// MARK: - Public variables
///The root object id which should be used for creating the version
speckle::utility::String id;
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
private:
///The object to send
std::unique_ptr<speckle::database::Record> m_object;
};
}
#endif //CONNECTOR_INTERFACE_BRIDGE_SEND_OBJECT
@@ -0,0 +1,114 @@
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendViaBrowserArgs.h"
#include "Connector/Record/Model/ModelCard.h"
#include "Speckle/Record/Credentials/Account.h"
#include <array>
using namespace active::serialise;
using namespace connector::record;
using namespace connector::interfac::browser::bridge;
using namespace speckle::database;
using namespace speckle::record::cred;
using namespace speckle::serialise;
using namespace speckle::utility;
namespace {
///Serialisation fields
enum FieldIndex {
cardID,
projID,
modID,
tokenID,
serverID,
accID,
messageID,
sendObjectID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"modelCardId"},
Identity{"projectId"},
Identity{"modelId"},
Identity{"token"},
Identity{"serverUrl"},
Identity{"accountId"},
Identity{"message"},
Identity{"sendObject"},
};
}
/*--------------------------------------------------------------------
Constructor
modelCard: The model card to populate into the send info for the browser
account: The account linked to the send
object: The object to be sent
--------------------------------------------------------------------*/
SendViaBrowserArgs::SendViaBrowserArgs(const ModelCard& modelCard, const Account& account, SendObject&& object) :
modelCardID(modelCard.getID()), projectID(modelCard.getProjectID()), modelID(modelCard.getModelID()), token{account.getToken()},
serverURL{account.getServerURL()}, accountID{account.getID()}, sendObject{std::move(object)} {
} //SendViaBrowserArgs::SendViaBrowserArgs
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool SendViaBrowserArgs::fillInventory(active::serialise::Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[cardID], cardID, element },
{ fieldID[projID], projID, element },
{ fieldID[modID], modID, element },
{ fieldID[tokenID], tokenID, element },
{ fieldID[serverID], serverID, element },
{ fieldID[accID], accID, element },
{ fieldID[messageID], messageID, element },
{ fieldID[sendObjectID], sendObjectID, element },
},
}.withType(&typeid(SendViaBrowserArgs)));
return true;
} //SendViaBrowserArgs::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique SendViaBrowserArgs::getCargo(const active::serialise::Inventory::Item& item) const {
if (item.ownerType != &typeid(SendViaBrowserArgs))
return nullptr;
using namespace active::serialise;
switch (item.index) {
case cardID:
return std::make_unique<StringWrap>(modelCardID);
case projID:
return std::make_unique<StringWrap>(projectID);
case modID:
return std::make_unique<StringWrap>(modelID);
case tokenID:
return std::make_unique<StringWrap>(token);
case serverID:
return std::make_unique<StringWrap>(serverURL);
case accID:
return std::make_unique<StringWrap>(accountID);
case messageID:
return std::make_unique<StringWrap>(message);
case sendObjectID:
return std::make_unique<PackageWrap>(sendObject);
default:
return nullptr; //Requested an unknown index
}
} //SendViaBrowserArgs::getCargo
@@ -0,0 +1,79 @@
#ifndef CONNECTOR_INTERFACE_BRIDGE_SEND_VIA_BROWSER_ARGS
#define CONNECTOR_INTERFACE_BRIDGE_SEND_VIA_BROWSER_ARGS
#include "Active/Serialise/Package/Package.h"
#include "Active/Utility/String.h"
#include "Connector/Interface/Browser/Bridge/Send/Arg/ConversionResult.h"
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendObject.h"
#include "Speckle/Database/Identity/RecordID.h"
namespace speckle::record::cred {
class Account;
}
namespace connector::record {
class ModelCard;
}
namespace connector::interfac::browser::bridge {
class ConnectorConfig;
/*!
A commit of a project version (model) to the Speckle server
An object of this type is prepared by the Send bridge method
*/
class SendViaBrowserArgs final : public active::serialise::Package {
public:
// MARK: - Constructors
/*!
Constructor
@param modelCard The model card to populate into the send info for the browser
@param account The account linked to the send
@param object The object to be sent
*/
SendViaBrowserArgs(const connector::record::ModelCard& modelCard, const speckle::record::cred::Account& account, SendObject&& object);
// MARK: - Public variables
///ID of the model card driving the send request
speckle::database::RecordID modelCardID;
///The source project ID (from the model card)
speckle::database::RecordID projectID;
///The model ID (from the model card)
speckle::database::RecordID modelID;
///The account token (from the user account info)
speckle::utility::String token;
///The server URL (from the user account info)
speckle::utility::String serverURL;
///The user account ID
speckle::utility::String accountID;
///The send message
speckle::utility::String message; //TODO: Clarify what this is used for
///The conversion report (summarising the conversion results on an element-by-element basis)
std::vector<ConversionResult> sendConversionResults;
///The commit content
SendObject sendObject;
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
};
}
#endif //CONNECTOR_INTERFACE_BRIDGE_SEND_VIA_BROWSER_ARGS
@@ -0,0 +1,36 @@
#include "Connector/Interface/Browser/Bridge/Send/GetSendSettings.h"
#include "Active/Container/Vector.h"
#include "Active/Serialise/CargoHold.h"
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
#include "Connector/Record/Model/CardSetting.h"
using namespace active::container;
using namespace active::serialise;
using namespace connector::record;
using namespace connector::interfac::browser::bridge;
using namespace speckle::utility;
namespace {
using WrappedValue = active::serialise::CargoHold<ContainerWrap<Vector<CardSetting>, PackageWrap>, Vector<CardSetting>>;
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
GetSendSettings::GetSendSettings() : BridgeMethod{"GetSendSettings", [&]() {
return run();
}} {}
/*--------------------------------------------------------------------
Get the send filters
return: The send filters
--------------------------------------------------------------------*/
std::unique_ptr<Cargo> GetSendSettings::run() const {
auto filters = std::make_unique<Vector<CardSetting>>();
return std::make_unique<WrappedValue>(std::move(filters));
} //GetSendSettings::run
@@ -0,0 +1,36 @@
#ifndef CONNECTOR_INTERFACE_BRIDGE_GET_SEND_SETTINGS
#define CONNECTOR_INTERFACE_BRIDGE_GET_SEND_SETTINGS
#include "Active/Serialise/CargoHold.h"
#include "Speckle/Interface/Browser/Bridge/BridgeMethod.h"
namespace connector::interfac::browser::bridge {
class ConnectorConfig;
/*!
JS Function class to retrieve the send filters
*/
class GetSendSettings : public speckle::interfac::browser::bridge::BridgeMethod<void, active::serialise::Cargo> {
public:
// MARK: - Constructors
/*!
Constructor
@param bridge The parent bridge object (provides access to bridge methods)
*/
GetSendSettings();
// MARK: - Functions (const)
/*!
Get the send filters
@return The send filters
*/
std::unique_ptr<active::serialise::Cargo> run() const;
};
}
#endif //CONNECTOR_INTERFACE_BRIDGE_GET_SEND_SETTINGS
@@ -2,12 +2,37 @@
#include "Active/Serialise/CargoHold.h"
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Connector/Connector.h"
#include "Connector/ConnectorResource.h"
#include "Connector/Database/ModelCardDatabase.h"
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendError.h"
#include "Connector/Interface/Browser/Bridge/Send/Arg/SendViaBrowserArgs.h"
#include "Connector/Record/Collection/ProjectCollection.h"
#include "Speckle/Database/AccountDatabase.h"
#include "Speckle/Database/Content/BIMRecord.h"
#include "Speckle/Interface/Browser/Bridge/BrowserBridge.h"
#include "Speckle/Record/Credentials/Account.h"
#include "Speckle/Serialise/Detached/Storage/DetachedMemoryStore.h"
#include "Speckle/Utility/Exception.h"
#include "Speckle/Database/BIMElementDatabase.h"
#include "Speckle/Environment/Project.h"
#include "Speckle/Record/Element/Element.h"
using namespace speckle::record::element;
#include <array>
using namespace active::serialise;
using namespace connector::interfac::browser::bridge;
using namespace connector::record;
using namespace speckle::database;
using namespace speckle::serialise;
using namespace speckle::utility;
namespace {
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
@@ -19,9 +44,46 @@ Send::Send() : BridgeMethod{"Send", [&](const SendArgs& args) {
/*--------------------------------------------------------------------
Send a specified model
modelCardID: The ID of the madel to send
modelCardID: The ID of the model to send
--------------------------------------------------------------------*/
void Send::run(const String& modelCardID) const {
///TODO: Find and send selected elements - the following is a placeholder
throw Exception{"No objects were found to convert. Please update your publish filter!"};
//Find the specified model card
auto modelCardDatabase = connector()->getModelCardDatabase();
auto modelCard = modelCardDatabase->getCard(modelCardID);
if (!modelCard) {
getBridge()->sendEvent("setModelError",
std::make_unique<SendError>(connector()->getLocalString(errorString, modelCardNotFoundID), modelCardID));
return;
}
//Get the user account
auto accountDatabase = connector()->getAccountDatabase();
auto account = accountDatabase->getAccount(modelCard->getAccountID(), modelCard->getServerURL());
if (!account) {
getBridge()->sendEvent("setModelError",
std::make_unique<SendError>(connector()->getLocalString(errorString, accountNotFoundID), modelCardID));
return;
}
//Get the active project
auto project = connector()->getActiveProject().lock();
if (!project) {
getBridge()->sendEvent("setModelError",
std::make_unique<SendError>(connector()->getLocalString(errorString, noProjectOpenID), modelCardID));
return;
}
//Build a collection from the selected elements
auto collection = std::make_unique<ProjectCollection>(project);
auto elementDatabase = project->getElementDatabase();
auto selected = elementDatabase->getSelection();
if (selected.empty()) {
getBridge()->sendEvent("setModelError",
std::make_unique<SendError>(connector()->getLocalString(errorString, noSelectedModelItemsID), modelCardID));
return;
}
for (const auto& link : selected) {
if (auto element = elementDatabase->getElement(link); element)
collection->addElement(*element);
}
//Send the collected information
auto result = std::make_unique<SendViaBrowserArgs>(*modelCard, *account, SendObject{std::move(collection)});
getBridge()->sendEvent("sendByBrowser", std::move(result));
} //Send::run
@@ -33,7 +33,7 @@ namespace connector::interfac::browser::bridge {
/*!
Send a specified model
@param modelCardID The ID of the madel to send
@param modelCardID The ID of the model to send
*/
void run(const speckle::utility::String& modelCardID) const;
};
@@ -1,6 +1,7 @@
#include "Connector/Interface/Browser/Bridge/Send/SendBridge.h"
#include "Connector/Interface/Browser/Bridge/Send/GetSendFilters.h"
#include "Connector/Interface/Browser/Bridge/Send/GetSendSettings.h"
#include "Connector/Interface/Browser/Bridge/Send/Send.h"
using namespace connector::interfac::browser::bridge;
@@ -11,5 +12,6 @@ using namespace connector::interfac::browser::bridge;
SendBridge::SendBridge() : BrowserBridge{"sendBinding"} {
//Add bridge methods
addMethod<GetSendFilters>();
addMethod<GetSendSettings>();
addMethod<Send>();
} //SendBridge::SendBridge
@@ -1,6 +1,9 @@
#include "Connector/Interface/ConnectorPalette.h"
#include "Active/Event/Event.h"
#include "Active/Utility/String.h"
#include "Active/Serialise/JSON/JSONTransport.h"
#include "Active/Utility/BufferOut.h"
#include "Connector/ConnectorResource.h"
#include "Connector/Event/ConnectorEventID.h"
#include "Connector/Interface/Browser/Bridge/Account/AccountBridge.h"
@@ -206,7 +209,8 @@ void BrowserPalette::Hide() {
void BrowserPalette::InitBrowserControl() {
#ifdef TESTING_MODE
browser->LoadURL("https://boisterous-douhua-e3cefb.netlify.app/test");
browser->LoadURL("https://deploy-preview-3180--boisterous-douhua-e3cefb.netlify.app/");
//browser->LoadURL("https://boisterous-douhua-e3cefb.netlify.app/test");
#else
browser->LoadURL("https://boisterous-douhua-e3cefb.netlify.app/");
#endif
@@ -0,0 +1,66 @@
#include "Connector/Record/Collection/FinishProxy.h"
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include <array>
using namespace active::serialise;
using namespace connector::record;
using namespace speckle::utility;
namespace {
///Serialisation fields
enum FieldIndex {
materialID,
linkedMeshID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"value"},
Identity{"objects"},
};
}
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool FinishProxy::fillInventory(active::serialise::Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[materialID], materialID, element },
{ fieldID[linkedMeshID], linkedMeshID, m_meshID.size(), std::nullopt },
},
}.withType(&typeid(FinishProxy)));
return true;
} //FinishProxy::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique FinishProxy::getCargo(const active::serialise::Inventory::Item& item) const {
if (item.ownerType != &typeid(FinishProxy))
return nullptr;
using namespace active::serialise;
switch (item.index) {
case materialID:
return std::make_unique<PackageWrap>(m_finish);
case linkedMeshID:
return std::make_unique<ContainerWrap<std::vector<active::utility::Guid>>>(m_meshID);
default:
return nullptr; //Requested an unknown index
}
} //FinishProxy::getCargo
@@ -0,0 +1,50 @@
#ifndef CONNECTOR_RECORD_COLLECTION_MATERIAL_PROXY
#define CONNECTOR_RECORD_COLLECTION_MATERIAL_PROXY
#include "Active/Serialise/Package/Package.h"
#include "Speckle/Record/Attribute/Finish.h"
#include "Speckle/Utility/String.h"
namespace connector::record {
/*!
A proxy record binding a surface finishes to meshes
*/
class FinishProxy : public active::serialise::Package {
public:
// MARK: - Constructors
/*!
Constructor
@param finish The proxy surface finish
@param meshID The list of mesh IDs the finish is applied to
*/
FinishProxy(const speckle::record::attribute::Finish& finish, const std::unordered_set<active::utility::Guid>& meshID) :
m_finish{finish} { std::copy(meshID.begin(), meshID.end(), std::back_inserter(m_meshID)); }
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
private:
///The proxy surface finish
speckle::record::attribute::Finish m_finish;
///The list of mesh IDs the finish is applied to
std::vector<active::utility::Guid> m_meshID;
};
}
#endif //CONNECTOR_RECORD_COLLECTION_MATERIAL_PROXY
@@ -0,0 +1,191 @@
#include "Connector/Record/Collection/ProjectCollection.h"
#include "Active/Serialise/CargoHold.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Connector/Connector.h"
#include "Connector/ConnectorResource.h"
#include "Connector/Record/Collection/FinishProxy.h"
#include "Speckle/Database/BIMAttributeDatabase.h"
#include "Speckle/Database/BIMElementDatabase.h"
#include "Speckle/Record/Element/Element.h"
#ifdef ARCHICAD
#include <ModelMaterial.hpp>
#endif
using namespace active::serialise;
using namespace connector::record;
using namespace speckle::database;
using namespace speckle::record::attribute;
using namespace speckle::utility;
#ifdef ARCHICAD
namespace connector::record {
class ProjectCollection::FinishCache : public std::unordered_map<active::utility::Guid, Finish::Unique> {};
}
#endif
namespace {
///Serialisation fields
enum FieldIndex {
finishProxyID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"renderMaterialProxies"},
};
using WrappedProxy = CargoHold<PackageWrap, FinishProxy>;
}
/*--------------------------------------------------------------------
Constructor
project: The source project
--------------------------------------------------------------------*/
ProjectCollection::ProjectCollection(speckle::environment::Project::Shared project) : base{project->getInfo().name, project} {
m_finishes = std::make_unique<FinishCache>();
} //ProjectCollection::ProjectCollection
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
ProjectCollection::~ProjectCollection() {
} //ProjectCollection::~ProjectCollection
/*--------------------------------------------------------------------
Add an element to the collection hierarchy
index The index of the element to add
return: True if the element was added (false typically means the element already exists)
--------------------------------------------------------------------*/
bool ProjectCollection::addElement(const speckle::database::BIMIndex& index) {
//Lookup the element in the element database of the active project
auto elementDbase = m_project->getElementDatabase();
if (elementDbase == nullptr)
return false;
if (auto element = elementDbase->getElement(index); element) {
addElement(*element); //Add the element to the collection hierarchy
return true;
}
return false;
} //ProjectCollection::addElement
/*--------------------------------------------------------------------
Add an element to the collection hierarchy
element: The element to add
return: True if the element was added (false typically means the element already exists)
--------------------------------------------------------------------*/
bool ProjectCollection::addElement(const speckle::record::element::Element& element) {
std::vector<String> collectionNames;
//The first collection hierarchy level is the element storey/level
auto storey = element.getStorey();
collectionNames.emplace_back(storey ? storey->getName() : connector()->getLocalString(titleString, noStoreyID));
//The next level is the name of the element type
collectionNames.emplace_back(element.getTypeName());
//Add any future levels here as required
RecordCollection* collection = this;
for (const auto& childName : collectionNames)
collection = collection->getChild(childName);
return collection->addIndex(BIMIndex{element.getBIMID(), element.getTableID()});
} //ProjectCollection::addElement
/*--------------------------------------------------------------------
Add a material proxy record to the collection
materialIndex: The index of the material to add
objectID: The object the material is applied to
return: True if the material proxy was added (false typically means the record already exists)
--------------------------------------------------------------------*/
bool ProjectCollection::addMaterialProxy(const speckle::database::BIMIndex& materialIndex, const speckle::database::BIMRecordID& objectID) {
auto iter = m_finishProxies.find(materialIndex);
if (iter == m_finishProxies.end())
iter = m_finishProxies.insert({materialIndex, {}}).first;
return iter->second.insert(objectID).second;
} //ProjectCollection::addMaterialProxy
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Add a ModelerAPI material to the collection (NB: These are not persistent so need to be captured by this method)
material: A material
objectID: The object the material is applied to
return: True if the material proxy was added (false typically means the record already exists)
--------------------------------------------------------------------*/
bool ProjectCollection::addMaterialProxy(const ModelerAPI::Material& material, const speckle::database::BIMRecordID& objectID) {
auto finishID = Guid::fromInt(material.GenerateHashValue());
if (m_finishes->find(finishID) != m_finishes->end())
return false;
auto finish = std::make_unique<Finish>(material);
return m_finishes->insert({finishID, std::move(finish)}).second;
} //ProjectCollection::addMaterialProxy
#endif
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool ProjectCollection::fillInventory(active::serialise::Inventory& inventory) const {
using enum Entry::Type;
base::fillInventory(inventory);
inventory.merge(Inventory{
{
{ Identity{fieldID[finishProxyID]}, finishProxyID, m_finishProxies.size(), std::nullopt },
},
}.withType(&typeid(ProjectCollection)));
return true;
} //ProjectCollection::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique ProjectCollection::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(ProjectCollection))
return base::getCargo(item);
using namespace active::serialise;
//TODO: This is only currently coded to write collection content - reading can be added as required in future
switch (item.index) {
case finishProxyID: {
if (item.available < m_finishProxies.size()) {
auto iter = m_finishProxies.begin();
std::advance(iter, item.available);
const Finish* finish = nullptr;
if (auto fin = m_finishes->find(iter->first); fin != m_finishes->end())
finish = fin->second.get();
else if (auto attribute = m_project->getAttributeDatabase()->getAttribute(iter->first, iter->first.tableID); attribute)
finish = dynamic_cast<const Finish*>(attribute.get());
if (finish != nullptr) {
auto proxy = std::make_unique<FinishProxy>(*finish, iter->second);
return std::make_unique<WrappedProxy>(std::move(proxy));
}
}
break;
}
default:
break;
}
return nullptr; //Requested an unknown index
} //ProjectCollection::getCargo
@@ -0,0 +1,108 @@
#ifndef CONNECTOR_RECORD_ROOT_COLLECTiON
#define CONNECTOR_RECORD_ROOT_COLLECTiON
#include "Connector/Record/Collection/RecordCollection.h"
#include "Speckle/Serialise/Collection/FinishCollector.h"
#include <stack>
namespace speckle::record::element {
class Element;
}
namespace connector::record {
/*!
Root collection for sending a project model to a Speckle server
Additional information is anticipated at the root level that will not apply at any other level in the container hierarchy, e.g.:
- Classification hierarchy
- Layers
- Other attributes, e.g. materials
Add all this supplementary data to the root container as required
*/
class ProjectCollection : public RecordCollection, public speckle::serialise::FinishCollector {
public:
// MARK: - Types
using base = RecordCollection;
// MARK: - Constructors
/*!
Constructor
@param project The source project
*/
ProjectCollection(speckle::environment::Project::Shared project);
ProjectCollection(const ProjectCollection&) = delete;
/*!
Destructor
*/
~ProjectCollection();
using base::base;
// MARK: - Functions (const)
// MARK: - Functions (mutating)
/*!
Add an element to the collection hierarchy
@param index The index of the element to add
@return True if the element was added (false typically means the element already exists)
*/
bool addElement(const speckle::database::BIMIndex& index);
/*!
Add an element to the collection hierarchy
@param element The element to add
@return True if the element was added (false typically means the element already exists)
*/
bool addElement(const speckle::record::element::Element& element);
/*!
Add a material proxy record to the collection
@param materialIndex The index of the material to add
@param objectID The object the material is applied to
@return True if the material proxy was added (false typically means the record already exists)
*/
bool addMaterialProxy(const speckle::database::BIMIndex& materialIndex, const speckle::database::BIMRecordID& objectID) override;
#ifdef ARCHICAD
/*!
Add a ModelerAPI material to the collection (NB: These are not persistent so need to be captured by this method)
@param material A material
@param objectID The object the material is applied to
@return True if the material proxy was added (false typically means the record already exists)
*/
bool addMaterialProxy(const ModelerAPI::Material& material, const speckle::database::BIMRecordID& objectID) override;
#endif
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
active::serialise::Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
private:
using FinishProxies = std::unordered_map<speckle::database::BIMIndex, std::unordered_set<active::utility::Guid>>;
///Finish proxies accumulated from meshes generated from the collection elements
FinishProxies m_finishProxies;
#ifdef ARCHICAD
class FinishCache;
///Finishes cached from ModelerAPI materials
std::unique_ptr<FinishCache> m_finishes;
#endif
};
}
#endif //CONNECTOR_RECORD_ROOT_COLLECTiON
@@ -0,0 +1,127 @@
#include "Connector/Record/Collection/RecordCollection.h"
#include "Active/Serialise/CargoHold.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Speckle/Database/BIMElementDatabase.h"
using namespace active::serialise;
using namespace connector::record;
using namespace speckle::database;
using namespace speckle::environment;
using namespace speckle::record::element;
using namespace speckle::utility;
#include <array>
namespace {
///Serialisation fields
enum FieldIndex {
nameID,
elementID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"name"},
Identity{"elements"},
};
using WrappedElement = CargoHold<PackageWrap, Element>;
}
/*--------------------------------------------------------------------
Constructor
name: The collection name
project: The source project
--------------------------------------------------------------------*/
RecordCollection::RecordCollection(const speckle::utility::String& name, Project::Shared project) : m_name{name}, m_project{project} {
} //RecordCollection::RecordCollection
/*--------------------------------------------------------------------
Get a child collection by name (adding if missing)
name: The child name
return: A pointer to the requested child (nullptr on failure, caller does not take ownership)
--------------------------------------------------------------------*/
RecordCollection* RecordCollection::getChild(const speckle::utility::String& name) {
//Return an existing child if possible
if (auto iter = m_children.find(name); iter != m_children.end())
return &iter->second;
//Otherwise insert and return a new collection with the requested name
return &m_children.insert({name, RecordCollection{name, m_project}}).first->second;
} //RecordCollection::getChild
/*--------------------------------------------------------------------
Add an index to the collection
index: The index to add
return: True if the index was added (false typically means the index already exists)
--------------------------------------------------------------------*/
bool RecordCollection::addIndex(const speckle::database::BIMIndex& index) {
return m_indices.insert(index).second;
} //RecordCollection::addIndex
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool RecordCollection::fillInventory(active::serialise::Inventory& inventory) const {
using enum Entry::Type;
base::fillInventory(inventory);
inventory.merge(Inventory{
{
{ Identity{fieldID[nameID]}, nameID, element },
{ Identity{fieldID[elementID]}, elementID, m_children.size() + m_indices.size(), std::nullopt },
},
}.withType(&typeid(RecordCollection)));
return true;
} //RecordCollection::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique RecordCollection::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(RecordCollection))
return base::getCargo(item);
using namespace active::serialise;
//TODO: This is only currently coded to write collection content - reading can be added as required in future
switch (item.index) {
case nameID:
return std::make_unique<StringWrap>(m_name);
case elementID: {
if (item.available < m_children.size()) {
auto iter = m_children.begin();
std::advance(iter, item.available);
return std::make_unique<PackageWrap>(iter->second);
}
auto index = item.available - m_children.size();
if (index < m_indices.size()) {
auto iter = m_indices.begin();
std::advance(iter, index);
if (auto element = m_project->getElementDatabase()->getElement(*iter, iter->tableID); element)
return std::make_unique<WrappedElement>(std::move(element));
}
break;
}
default:
break;
}
return nullptr; //Requested an unknown index
} //RecordCollection::getCargo
@@ -0,0 +1,122 @@
#ifndef CONNECTOR_RECORD_RECORD_COLLECTiON
#define CONNECTOR_RECORD_RECORD_COLLECTiON
#include "Speckle/Database/Content/Record.h"
#include "Speckle/Database/Identity/BIMIndex.h"
#include "Speckle/Environment/Project.h"
#include "Speckle/Utility/String.h"
#include <unordered_set>
#include <unordered_map>
namespace connector::record {
class ProjectCollection;
/*!
Container for a collection of elements (and potentially tables of associated attributes) for Speckle commits
The container only stores element indices - database operations (including serialisation) will lookup records from a specified BIMDatabase on
demand.
This container can used hierarchically, so an collection can be nested within another collection. The current structure is:
- Root
- Element containers dividing elements by level/storey
- Element containers dividing elements by classification
- [nested classification leaf nodes)
- Associated attributes, e.g. classification table (future)
Any level in the hierarchy may contain element indices, although this is currently unlikely at the root level (all elements have a level/storey)
Each container should be named appropriately, e.g. a level/storey collection should be named to match the level/storey.
Note that the serialisation is currently implemented for sending only. Receive can be added as required
*/
class RecordCollection : public speckle::database::Record {
public:
// MARK: - Types
using base = speckle::database::Record;
// MARK: - Constructors
/*!
Destructor
*/
~RecordCollection() {}
// MARK: - Functions (const)
/*!
Get the speckle type identifier
@return The speckle type (relevant objects should override as required, but "Base" is still considered a type on its own)
*/
speckle::utility::String getSpeckleType() const override { return "Speckle.Core.Models.Collections.Collection"; }
/*!
Get the container name
@return The container name
*/
const speckle::utility::String& getName() const { return m_name; }
/*!
Find a child by name
@param name The required child name
@return A pointer to the requested child (nullptr if not found)
*/
RecordCollection* findChild(const speckle::utility::String& name) const;
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
active::serialise::Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
private:
friend ProjectCollection;
// MARK: - Types
using Indices = std::unordered_set<speckle::database::BIMIndex>;
using Children = std::unordered_map<speckle::utility::String, RecordCollection>;
/*!
Constructor
@param name The collection name
@param project The source project
*/
RecordCollection(const speckle::utility::String& name, speckle::environment::Project::Shared project);
/*!
Get a child collection by name (adding if missing)
@param name The child name
@return A pointer to the requested child (nullptr on failure, caller does not take ownership)
*/
RecordCollection* getChild(const speckle::utility::String& name);
/*!
Add an index to the collection
@param index The index to add
@return True if the index was added (false typically means the index already exists)
*/
bool addIndex(const speckle::database::BIMIndex& index);
///The source project for the collection
speckle::environment::Project::Shared m_project;
///The collection name
speckle::utility::String m_name;
///Child nodes of this collection
Children m_children;
///Indices of records in this collection
Indices m_indices;
};
}
#endif //CONNECTOR_RECORD_RECORD_COLLECTiON
@@ -19,6 +19,8 @@ namespace connector::record {
// MARK: - Types
using base = speckle::database::Record;
///Unique pointer
using Unique = std::unique_ptr<ModelCard>;
//List of card settings
using SettingList = active::container::Vector<connector::record::CardSetting>;
@@ -67,6 +69,11 @@ namespace connector::record {
@return The setting type
*/
const speckle::utility::String& getAccountID() const { return m_accountID; }
/*!
Get the user commit message
@return The user commit message
*/
const speckle::utility::String& getMessage() const { return m_message; }
/*!
Get the setting type
@return The setting type
@@ -106,6 +113,8 @@ namespace connector::record {
speckle::database::RecordID m_accountID;
///The server URL
speckle::utility::String m_serverURL;
///The commit message from the user for the card
speckle::utility::String m_message;
///Settings for the model rendering, e.g. level of detail (LoD)
SettingList m_settings;
///True if the card has expired
+8
View File
@@ -1,4 +1,12 @@
'STR#' 32600 "Title strings" {
/* [ 1] */ "Speckle Connector"
/* [ 2] */ "Connector to share model content with Speckle"
/* [ 3] */ "No level"
}
'STR#' 32604 "Error strings" {
/* [ 1] */ "No objects were found to convert. Please update your publish filter!"
/* [ 2] */ "The specified model card cannot be found. Try another card or create a new one"
/* [ 3] */ "Please open a project first"
/* [ 4] */ "The specified Speckle account cannot be found. Check that you have logged into your Speckle account with the Speckle Manager"
}
+1
View File
@@ -1,3 +1,4 @@
'STR#' 32700 "Speckle Title strings" {
/* [ 1] */ "Untitled"
/* [ 2] */ "Unknown"
}
@@ -81,6 +81,27 @@ AccountDatabase::AccountDatabase(const active::file::Path& path) {
AccountDatabase::~AccountDatabase() {}
/*--------------------------------------------------------------------
Get a specified account. NB: The server URL is provided as a fallback for the search if the specified accountID is not found
accountID: The account ID (the primary search field)
serverURL: The server URL (a fallback search field if the account ID does not exist)
return: The requested account (nullptr on failure)
--------------------------------------------------------------------*/
std::unique_ptr<Account> AccountDatabase::getAccount(const String& accountID, const String& serverURL) const {
//First attempt to find a matching account ID
auto matchingAccount = m_store->getObjects([&accountID](const auto& acc) { return acc.getID() == accountID; });
if (!matchingAccount.empty())
return matchingAccount.release(matchingAccount.begin());
//Alternatively seek an account with a matching server URL
matchingAccount = m_store->getObjects([&serverURL](const auto& acc) { return acc.getServerURL() == serverURL; });
if (!matchingAccount.empty())
return matchingAccount.release(matchingAccount.begin());
return nullptr;
} //AccountDatabase::getAccount
/*--------------------------------------------------------------------
Get all accounts
@@ -4,6 +4,10 @@
#include "Active/File/Path.h"
#include "Speckle/Record/Credentials/Account.h"
namespace speckle::record::cred {
class Account;
}
namespace speckle::database {
/*!
@@ -27,6 +31,13 @@ namespace speckle::database {
// MARK: - Functions (const)
/*!
Get a specified account. NB: The server URL is provided as a fallback for the search if the specified accountID is not found
@param accountID The account ID (the primary search field)
@param serverURL The server URL (a fallback search field if the account ID does not exist)
@return The requested account (nullptr on failure)
*/
std::unique_ptr<record::cred::Account> getAccount(const speckle::utility::String& accountID, const speckle::utility::String& serverURL) const;
/*!
Get all accounts
@return All the accounts
@@ -0,0 +1,155 @@
#include "Speckle/Database/BIMAttributeDatabase.h"
#include "Active/Database/Storage/Storage.h"
#include "Active/Serialise/UnboxedTransport.h"
#include "Speckle/Database/Identity/RecordID.h"
#include "Speckle/Database/Storage/ArchicadDBase/Attribute/ArchicadAttributeDBaseEngine.h"
#include "Speckle/Record/Attribute/Attribute.h"
#include <array>
using namespace active::container;
using namespace active::database;
using namespace active::event;
using namespace active::serialise;
using namespace speckle::database;
using namespace speckle::record;
using namespace speckle::record::attribute;
using namespace speckle::database;
using namespace speckle::utility;
namespace speckle::database {
///Define other platform engines here as required
#ifdef ARCHICAD
using AttributeDatabaseEngine = ArchicadAttributeDBaseEngine;
#endif
///Attribute database engine declaration
class BIMAttributeDatabase::Engine : public AttributeDatabaseEngine {
using base = ArchicadAttributeDBaseEngine;
using base::base;
};
///Attribute database storage declaration
class BIMAttributeDatabase::Store : public Storage<Attribute, UnboxedTransport, BIMRecordID, BIMRecordID, BIMRecordID, BIMRecordID> {
using base = Storage<Attribute, UnboxedTransport, BIMRecordID, BIMRecordID, BIMRecordID, BIMRecordID>;
using base::base;
};
}
namespace {
///The database storage identifier for attributes
const char* attributeDBaseName = "speckle::database::BIMAttributeDatabase";
///The primary model table, e.g. floor plan in Archicad
const char* modelTableName = "Model";
}
/*--------------------------------------------------------------------
Constructor
--------------------------------------------------------------------*/
BIMAttributeDatabase::BIMAttributeDatabase() {
m_engine = std::make_shared<Engine>(attributeDBaseName,
//Schema
DBaseSchema{active::utility::String{attributeDBaseName},
//Tables
{
//Model attribute table
{
modelTableName, 0, 0, {} //The primary model. Additonal tables could be linked to other drawings/layouts in future
}
}
}
);
m_store = std::make_shared<Store>(m_engine);
} //BIMAttributeDatabase::BIMAttributeDatabase
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
BIMAttributeDatabase::~BIMAttributeDatabase() {}
/*--------------------------------------------------------------------
Get a specified attribute
attributeID: The ID of the target attribute
return: The requested attribute (nullptr on failure)
--------------------------------------------------------------------*/
Attribute::Unique BIMAttributeDatabase::getAttribute(const BIMRecordID& attributeID, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
return m_engine->getObject(attributeID, tableID, documentID);
} //BIMAttributeDatabase::getAttribute
/*--------------------------------------------------------------------
Get all attributes
return: All the attributes
--------------------------------------------------------------------*/
Vector<Attribute> BIMAttributeDatabase::getAttributes() const {
return m_store->getObjects();
} //BIMAttributeDatabase::getAttributes
/*--------------------------------------------------------------------
Write an attribute to storage
attribute: The attribute to write
--------------------------------------------------------------------*/
void BIMAttributeDatabase::write(const Attribute& attribute) const {
m_store->write(attribute);
} //BIMAttributeDatabase::write
/*--------------------------------------------------------------------
Erase an attribute
attributeID: The ID of the attribute to erase
--------------------------------------------------------------------*/
void BIMAttributeDatabase::erase(const Guid& attributeID) const {
m_store->erase(attributeID);
} //BIMAttributeDatabase::erase
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Get attribute data direct from the AC API. For internal use - avoid direct use
link: A link to the required attribute
return: The AC API attribute data
--------------------------------------------------------------------*/
std::optional<API_Attribute> BIMAttributeDatabase::getAPIData(const BIMLink& link) const {
return m_engine->getAPIData(link);
} //BIMAttributeDatabase::getAPIData
/*--------------------------------------------------------------------
Get storey data direct from the AC API. For internal use - avoid direct use
link: A link to the required storey
return: The AC API storey data
--------------------------------------------------------------------*/
std::optional<API_StoryType> BIMAttributeDatabase::getAPIStorey(const BIMLink& link) const {
return m_engine->getAPIStorey(link);
} //BIMAttributeDatabase::getAPIData
/*--------------------------------------------------------------------
Get the ID of a storey from a specified index
index: The storey index
return: The storey ID (nullopt on failure)
--------------------------------------------------------------------*/
std::optional<BIMRecordID> BIMAttributeDatabase::getStoreyID(short index) const {
return m_engine->getStoreyID(index);
} //BIMAttributeDatabase::getStoreyID
#endif
@@ -0,0 +1,101 @@
#ifndef CONNECTOR_DATABASE_BIM_ATTRIBUTE_DATABASE
#define CONNECTOR_DATABASE_BIM_ATTRIBUTE_DATABASE
#include "Speckle/Database/Identity/BIMLink.h"
#include "Speckle/Record/Attribute/Attribute.h"
#include "Speckle/Utility/Guid.h"
namespace active::event {
class Subscriber;
}
namespace speckle::database {
/*!
Database of model attributes relating to a specific project
*/
class BIMAttributeDatabase {
public:
// MARK: - Constructors
/*!
Constructor
*/
BIMAttributeDatabase();
BIMAttributeDatabase(const BIMAttributeDatabase&) = delete;
/*!
Destructor
*/
~BIMAttributeDatabase();
// MARK: - Functions (const)
/*!
Get the current user attribute selection
@return A list of selected attribute IDs
*/
BIMLinkList getSelection() const;
/*!
Get a specified attribute
@param attributeID The ID of the target attribute
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
@return The requested attribute (nullptr on failure)
*/
record::attribute::Attribute::Unique getAttribute(const BIMRecordID& attributeID, std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const;
/*!
Get a specified attribute
@param link A link to the target attribute
@return The requested attribute (nullptr on failure)
*/
record::attribute::Attribute::Unique getAttribute(const BIMLink& link) const { return getAttribute(link, link.tableID, link.docID); }
/*!
Get all model attributes
@return All the attributes
*/
active::container::Vector<record::attribute::Attribute> getAttributes() const;
/*!
Write an attribute to storage
@param attribute The attribute to write
*/
void write(const record::attribute::Attribute& attribute) const;
/*!
Erase an attribute
@param attributeID The ID of the attribute to erase
*/
void erase(const speckle::utility::Guid& attributeID) const;
#ifdef ARCHICAD
/*!
Get attribute data direct from the AC API. For internal use - avoid direct use
@param link A link to the required attribute
@return The AC API attribute data
*/
std::optional<API_Attribute> getAPIData(const BIMLink& link) const;
/*!
Get storey data direct from the AC API. For internal use - avoid direct use
@param link A link to the required storey
@return The AC API storey data
*/
std::optional<API_StoryType> getAPIStorey(const BIMLink& link) const;
/*!
Get the ID of a storey from a specified index
@param index The storey index
@return The storey ID (nullopt on failure)
*/
std::optional<BIMRecordID> getStoreyID(short index) const;
#endif
private:
class Engine;
class Store;
///Model attribute database storage
std::shared_ptr<Engine> m_engine;
std::shared_ptr<Store> m_store;
};
}
#endif //CONNECTOR_DATABASE_BIM_ATTRIBUTE_DATABASE
@@ -0,0 +1,127 @@
#include "Speckle/Database/BIMElementDatabase.h"
#include "Active/Database/Storage/Storage.h"
#include "Active/Serialise/UnboxedTransport.h"
#include "Speckle/Database/Identity/RecordID.h"
#include "Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.h"
#include "Speckle/Record/Element/Element.h"
#include <array>
using namespace active::container;
using namespace active::database;
using namespace active::event;
using namespace active::serialise;
using namespace speckle::database;
using namespace speckle::record;
using namespace speckle::record::element;
using namespace speckle::database;
using namespace speckle::utility;
namespace speckle::database {
///Define other platform engines here as required
#ifdef ARCHICAD
using ElementDatabaseEngine = ArchicadElementDBaseEngine;
#endif
///Element database engine declaration
class BIMElementDatabase::Engine : public ElementDatabaseEngine {
using base = ArchicadElementDBaseEngine;
using base::base;
};
///Element database storage declaration
class BIMElementDatabase::Store : public Storage<Element, UnboxedTransport, BIMRecordID, BIMRecordID, BIMRecordID, BIMRecordID> {
using base = Storage<Element, UnboxedTransport, BIMRecordID, BIMRecordID, BIMRecordID, BIMRecordID>;
using base::base;
};
}
namespace {
///The database storage identifier for elements
const char* elementDBaseName = "speckle::database::BIMElementDatabase";
///The primary model table, e.g. floor plan in Archicad
const char* modelTableName = "Model";
}
/*--------------------------------------------------------------------
Constructor
--------------------------------------------------------------------*/
BIMElementDatabase::BIMElementDatabase() {
m_engine = std::make_shared<Engine>(elementDBaseName,
//Schema
DBaseSchema{active::utility::String{elementDBaseName},
//Tables
{
//Model element table
{
modelTableName, 0, 0, {} //The primary model. Additonal tables could be linked to other drawings/layouts in future
}
}
}
);
m_store = std::make_shared<Store>(m_engine);
} //BIMElementDatabase::BIMElementDatabase
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
BIMElementDatabase::~BIMElementDatabase() {}
/*--------------------------------------------------------------------
Get the current user element selection
return: A list of selected element IDs
--------------------------------------------------------------------*/
BIMLinkList BIMElementDatabase::getSelection() const {
return m_engine->getSelection();
} //BIMElementDatabase::getSelection
/*--------------------------------------------------------------------
Get a specified element
elementID: The ID of the target element
return: The requested element (nullptr on failure)
--------------------------------------------------------------------*/
Element::Unique BIMElementDatabase::getElement(const BIMRecordID& elementID, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
return m_engine->getObject(elementID, tableID, documentID);
} //BIMElementDatabase::getElement
/*--------------------------------------------------------------------
Get all elements
return: All the elements
--------------------------------------------------------------------*/
Vector<Element> BIMElementDatabase::getElements() const {
return m_store->getObjects();
} //BIMElementDatabase::getElements
/*--------------------------------------------------------------------
Write an element to storage
element: The element to write
--------------------------------------------------------------------*/
void BIMElementDatabase::write(const Element& element) const {
m_store->write(element);
} //BIMElementDatabase::write
/*--------------------------------------------------------------------
Erase an element
elementID: The ID of the element to erase
--------------------------------------------------------------------*/
void BIMElementDatabase::erase(const Guid& elementID) const {
m_store->erase(elementID);
} //BIMElementDatabase::erase
@@ -0,0 +1,80 @@
#ifndef CONNECTOR_DATABASE_BIM_ELEMENT_DATABASE
#define CONNECTOR_DATABASE_BIM_ELEMENT_DATABASE
#include "Speckle/Database/Identity/BIMLink.h"
#include "Speckle/Record/Element/Element.h"
#include "Speckle/Utility/Guid.h"
namespace active::event {
class Subscriber;
}
namespace speckle::database {
/*!
Database of model elements relating to a specific project
*/
class BIMElementDatabase {
public:
// MARK: - Constructors
/*!
Constructor
*/
BIMElementDatabase();
BIMElementDatabase(const BIMElementDatabase&) = delete;
/*!
Destructor
*/
~BIMElementDatabase();
// MARK: - Functions (const)
/*!
Get the current user element selection
@return A list of selected element IDs
*/
BIMLinkList getSelection() const;
/*!
Get a specified element
@param elementID The ID of the target element
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
@return The requested element (nullptr on failure)
*/
record::element::Element::Unique getElement(const BIMRecordID& elementID, std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const;
/*!
Get a specified element
@param link A link to the target element
@return The requested element (nullptr on failure)
*/
record::element::Element::Unique getElement(const BIMLink& link) const { return getElement(link, link.tableID, link.docID); }
/*!
Get all model elements
@return All the elements
*/
active::container::Vector<record::element::Element> getElements() const;
/*!
Write an element to storage
@param element The element to write
*/
void write(const record::element::Element& element) const;
/*!
Erase an element
@param elementID The ID of the element to erase
*/
void erase(const speckle::utility::Guid& elementID) const;
private:
class Engine;
class Store;
///Model element database storage
std::shared_ptr<Engine> m_engine;
std::shared_ptr<Store> m_store;
};
}
#endif //CONNECTOR_DATABASE_BIM_ELEMENT_DATABASE
@@ -0,0 +1,78 @@
#include "Speckle/Database/Content/BIMRecord.h"
#include "Active/Serialise/Item/Wrapper/ValueOptionWrap.h"
#include "Speckle/Serialise/Units/LengthUnit.h"
#include "Speckle/Utility/Guid.h"
#include <array>
using namespace active::serialise;
using namespace speckle::database;
using namespace speckle::utility;
using enum active::measure::LengthType;
namespace {
///Serialisation fields
enum FieldIndex {
applicID,
unitID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"applicationId"},
Identity{"unit"},
};
}
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool BIMRecord::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ Identity{fieldID[applicID]}, applicID, element, !m_applicationID.empty() },
{ Identity{fieldID[unitID]}, unitID, element, m_unit.operator bool() },
},
}.withType(&typeid(BIMRecord)));
return base::fillInventory(inventory);
} //BIMRecord::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique BIMRecord::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(BIMRecord))
return base::getCargo(item);
using namespace active::serialise;
switch (item.index) {
case applicID:
return std::make_unique<ValueWrap<BIMRecordID>>(m_applicationID);
case unitID:
return std::make_unique<ValueOptionWrap<active::measure::LengthType>>(m_unit);
default:
return nullptr; //Requested an unknown index
}
} //BIMRecord::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void BIMRecord::setDefault() {
m_applicationID.clear();
m_unit.reset();
} //BIMRecord::setDefault
@@ -0,0 +1,120 @@
#ifndef SPECKLE_DATABASE_BIM_RECORD
#define SPECKLE_DATABASE_BIM_RECORD
#include "Active/Setting/Values/Measurement/Units/LengthUnit.h"
#include "Speckle/Database/Content/Record.h"
#include "Speckle/Database/Identity/BIMIndex.h"
#include "Speckle/Database/Identity/BIMLink.h"
#include "Speckle/Database/Identity/BIMRecordID.h"
namespace speckle::database {
/*!
Base class for a database record
*/
class BIMRecord : public Record {
public:
// MARK: - Types
using base = Record;
///Unique pointer
using Unique = std::unique_ptr<BIMRecord>;
///Shared pointer
using Shared = std::shared_ptr<BIMRecord>;
///Optional
using Option = std::optional<BIMRecord>;
// MARK: - Constructors
/*!
Default constructor
@param unit The recordc unit type
*/
BIMRecord(active::measure::LengthType unit = active::measure::LengthType::metre) : base{}, m_unit{unit} {}
/*!
Constructor
@param ID The record ID
@param tableID The parent table ID
@param unit The record unit type
*/
BIMRecord(const speckle::utility::Guid& ID, const speckle::utility::Guid& tableID,
active::measure::LengthType unit = active::measure::LengthType::metre) :
base{}, m_applicationID{ID}, m_applicationTableID{tableID}, m_unit{unit} {}
/*!
Destructor
*/
virtual ~BIMRecord() {}
// MARK: - Functions (const)
/*!
Get the BIM application ID
@return The BIM application ID
*/
BIMRecordID getBIMID() const { return m_applicationID; }
/*!
Get the BIM application parent table ID
@return The BIM table ID
*/
BIMRecordID getTableID() const { return m_applicationTableID; }
/*!
Get a link to the BIM record
@return The BIM record link
*/
BIMLink getBIMLink() const { return BIMLink{ BIMLink::base{m_applicationID, m_applicationTableID} }; }
// MARK: - Functions (mutating)
/*!
Set the BIM application ID
@param ID The BIM application ID
*/
void setBIMID(const BIMRecordID& ID) { m_applicationID = ID; }
/*!
Set the BIM application parent table ID
@param tableID The BIM table ID
*/
void setTableID(const BIMRecordID& tableID) { m_applicationTableID = tableID; }
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
active::serialise::Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
/*!
Set to the default package content
*/
void setDefault() override;
protected:
/*!
Reset the BIM index (used in lazy loading contexts where the index cannot otherwise be established)
@param index The BIM application index
*/
void resetIndex(const BIMIndex& index) const {
m_applicationID = index;
m_applicationTableID = index.tableID;
}
private:
///The BIM application record ID
mutable BIMRecordID m_applicationID;
///The BIM application parent table ID
mutable BIMRecordID m_applicationTableID;
///The BIM record unit of length measurement
std::optional<active::measure::LengthType> m_unit = active::measure::LengthType::metre;
};
}
#endif //SPECKLE_DATABASE_BIM_RECORD
+56 -1
View File
@@ -2,10 +2,28 @@
#include "Speckle/Utility/Guid.h"
#include <array>
using namespace active::serialise;
using namespace speckle::database;
using namespace speckle::utility;
namespace {
///Serialisation fields
enum FieldIndex {
speckleIDID,
speckleTypeID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"id"},
Identity{"speckle_type"},
};
}
/*--------------------------------------------------------------------
Fill an inventory with the package items
@@ -17,8 +35,45 @@ bool Record::fillInventory(active::serialise::Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ Identity{"id"}, active::database::record::FieldIndex::idIndex, element },
{ Identity{fieldID[speckleIDID]}, active::database::record::FieldIndex::idIndex, element, !getID().empty() },
},
}.withType(&typeid(base)));
inventory.merge(Inventory{
{
{ Identity{fieldID[speckleTypeID]}, speckleTypeID, element },
},
}.withType(&typeid(Record)));
return true;
} //Record::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique Record::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(Record))
return base::getCargo(item);
using namespace active::serialise;
switch (item.index) {
case speckleTypeID:
//If the type is undefined, we're in a serialisation process and should populate it with whatever the object says it is
if (!m_type)
m_type = getSpeckleType();
return std::make_unique<StringWrap>(*m_type);
default:
return nullptr; //Requested an unknown index
}
} //Record::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void Record::setDefault() {
//Ensure the content starts with an empty (defined) string for deserialisation so we can discover the incoming type
m_type = String{};
} //Record::setDefault
+27 -12
View File
@@ -27,22 +27,23 @@ namespace speckle::database {
/*!
Default constructor
*/
Record() : base{active::utility::Guid{true}.operator active::utility::String(),
active::utility::Guid{true}.operator active::utility::String()} {} //TODO: Implement a better default for the ID
/*!
Constructor
@param ID The record ID
@param globID The global ID
*/
Record(speckle::utility::String ID, speckle::utility::String::Option globID = std::nullopt) :
base{ID, globID.value_or(active::utility::Guid{true}.operator active::utility::String())} {}
Record(speckle::utility::String::Option ID = std::nullopt, speckle::utility::String::Option globID = std::nullopt) :
base{ID.value_or(speckle::utility::String{}), globID.value_or(speckle::utility::String{})} {}
/*!
Destructor
*/
virtual ~Record() {}
// MARK: - Functions (const)
/*!
Get the speckle type identifier
@return The speckle type (relevant objects should override as required, but "Base" is still considered a type on its own)
*/
virtual speckle::utility::String getSpeckleType() const { return "speckle::database::Record"; }
// MARK: - Functions (mutating)
@@ -50,11 +51,25 @@ namespace speckle::database {
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
active::serialise::Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
/*!
Set to the default package content
*/
void setDefault() override;
private:
///Cache for the speckle type during serialisation operations
mutable speckle::utility::String::Option m_type;
};
}
@@ -0,0 +1,42 @@
#ifndef SPECKLE_DATABASE_BIM_INDEX
#define SPECKLE_DATABASE_BIM_INDEX
#include "Active/Database/Identity/Index.h"
#include "Speckle/Database/Identity/BIMRecordID.h"
namespace speckle::database {
/*!
Record index class
A record index is the information required to uniquely identify (and locate) a specified record in some database/app context. For Archicad,
this is typically a guid, for Revit a string and for Vectorworks a handle. Note that this index is not necessarily persistent between
sessions.
*/
class BIMIndex : public active::database::Index<BIMRecordID, BIMRecordID> {
public:
// MARK: - Types
using base = active::database::Index<BIMRecordID, BIMRecordID>;
// MARK: - Constructors
using base::base;
};
}
///Hashing for BIMIndex class, e.g. to use as a key in unordered_map
template<>
struct std::hash<speckle::database::BIMIndex> {
std::size_t operator() (const speckle::database::BIMIndex& index) const {
std::size_t h1 = std::hash<active::utility::Guid>{}(index);
std::size_t h2 = std::hash<active::utility::Guid>{}(index.tableID);
return h1 ^ (h2 << 1);
}
};
#endif //SPECKLE_DATABASE_BIM_INDEX
@@ -1,5 +1,4 @@
#include "Speckle/Database/Identity/Link.h"
#include "Speckle/Utility/Guid.h"
#include "Speckle/Database/Identity/BIMLink.h"
using namespace speckle::database;
using namespace speckle::utility;
@@ -9,10 +8,11 @@ using namespace speckle::utility;
Constructor
selected: Information about a selected Archicad element
tableID: The ID of the parent table
--------------------------------------------------------------------*/
//Link::Link(const API_Neig& selected) : base{Guid{selected.guid}} {
//More info should be extracted from API_Neig in future (as required)
//} //Link::Link
BIMLink::BIMLink(const API_Neig& selected, const BIMRecordID& tableID) : base{Guid{selected.guid}, tableID} {
//More info should be extracted from API_Neig in future (as required) - extract into link settings, e.g. selection target etc
} //Link::Link
#endif
@@ -0,0 +1,48 @@
#ifndef SPECKLE_DATABASE_BIM_LINK
#define SPECKLE_DATABASE_BIM_LINK
#include "Active/Setting/SettingList.h"
#include "Active/Database/Identity/Link.h"
#include "Speckle/Database/Identity/BIMRecordID.h"
namespace speckle::database {
/*!
Record link class, binding an index to additional information
The essential part of a link is the index pointing to a target record. In some cases, e.g. where the user has selected something in a rendered
scene, the index is to a proxy object that represents another record in a specific context, e.g. a 2D representation of a 3D element rendered
in a cut plance section view. A tool working with the link might be interested in either the proxy or the original - passing a link allows
this distinction to be easily made.
A link may optionally carry any number of settings. In the context of a user selection (for example) there might be settings describing where
the user made the selection (e.g. the hole in a floor slab), allowing a tool working on that selection to be more precise.
*/
class BIMLink : public active::database::Link<BIMRecordID> {
public:
// MARK: - Types
using base = active::database::Link<BIMRecordID>;
// MARK: - Constructors
using base::base;
BIMLink() = default;
#ifdef ARCHICAD
/*!
Constructor
@param selected Information about a selected Archicad element
@param tableID The ID of the parent table
*/
BIMLink(const API_Neig& selected, const BIMRecordID& tableID);
#endif
};
//A list of links to BIM records
using BIMLinkList = std::vector<BIMLink>;
}
#endif //SPECKLE_DATABASE_BIM_LINK
@@ -0,0 +1,24 @@
#ifndef SPECKLE_DATABASE_BIM_ID
#define SPECKLE_DATABASE_BIM_ID
#include "Speckle/Utility/Guid.h"
namespace speckle::database {
#ifdef ARCHICAD
//Common BIM record identifier type (e.g. to BIM elements)
using BIMRecordID = speckle::utility::Guid;
//Common BIM table identifier type (e.g. primary model, views)
using BIMTableID = speckle::utility::Guid;
//Common BIM document identifier type (e.g. BIM drawing identifier, e.g. section, layout etc)
using BIMDocID = speckle::utility::Guid;
//Common BIM database identifier type (e.g. model database, library database, attribute database)
using BIMDBaseID = speckle::utility::Guid;
#endif
//A list of BIM record IDs
using BIMRecordIDList = std::vector<BIMRecordID>;
}
#endif //SPECKLE_DATABASE_BIM_ID
+1 -4
View File
@@ -1,11 +1,8 @@
#ifndef SPECKLE_DATABASE_INDEX
#define SPECKLE_DATABASE_INDEX
#include "Active/Database/Identity/Link.h"
#include "Active/Database/Identity/Index.h"
#include "Speckle/Database/Identity/RecordID.h"
#include "Speckle/Utility/String.h"
#include <any>
namespace speckle::database {
+1 -7
View File
@@ -2,6 +2,7 @@
#define SPECKLE_DATABASE_LINK
#include "Active/Setting/SettingList.h"
#include "Active/Database/Identity/Link.h"
#include "Speckle/Database/Identity/Index.h"
namespace speckle::database {
@@ -29,13 +30,6 @@ namespace speckle::database {
using base::base;
Link() = default;
#ifdef ARCHICAD
/*!
Constructor
@param selected Information about a selected Archicad element
*/
Link(const API_Neig& selected);
#endif
};
}
@@ -0,0 +1,95 @@
#include "Speckle/Database/Storage/ArchicadDBase/ArchicadDBaseCore.h"
#ifdef ARCHICAD
#include "Active/Utility/Defer.h"
#include "Active/Utility/Memory.h"
#include "Active/Utility/String.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/Environment/Project.h"
#include "Speckle/Event/Type/DocStoreMergeEvent.h"
#include "Speckle/Event/Type/ProjectEvent.h"
#include "Speckle/Utility/Guid.h"
#include "Speckle/Utility/String.h"
#include <ACAPinc.h>
#include <BM.hpp>
using namespace active::event;
using namespace active::setting;
using namespace speckle::database;
using namespace speckle::environment;
using namespace speckle::event;
using namespace speckle::utility;
using enum ArchicadDBaseCore::Status;
namespace {
/*--------------------------------------------------------------------
Convert an Archicad API error code to a ArchicadDBaseCore status
acErrorCode: The API error code
return: An equivalent status code
--------------------------------------------------------------------*/
ArchicadDBaseCore::Status convertArchicadError(long acErrorCode) {
using enum ArchicadDBaseCore::Status;
switch (acErrorCode) {
case NoError:
return nominal;
case APIERR_BADPARS:
return badParameter;
case APIERR_BADID:
return badID;
default:
break;
}
return error;
} //convertArchicadError
///Category for ArchicadElementDBase processing errors
class ArchicadDBaseCategory : public std::error_category {
public:
///Category name
const char* name() const noexcept override {
return "speckle::database::archicad::category";
}
/*!
Get a message for a specified error code
@param errorCode A ArchicadElementDBase processing code
@return The error message for the specified code
*/
std::string message(int errorCode) const override {
//TODO: These error messages are ok for developers - but can we help users more?
switch (static_cast<ArchicadDBaseCore::Status>(errorCode)) {
case nominal:
return "";
case badParameter:
return "An internal function has been incorrectly used";
case badID:
return "Internal data has been requested using an invalid identity";
case error:
return "A non-specific error occurred";
default:
return "An unknown error occurred";
}
}
};
///ArchicadElementDBase processing category error instance
static ArchicadDBaseCategory instance;
}
/*--------------------------------------------------------------------
Make an error code for ArchicadElementDBase processing
return: An STL error code
--------------------------------------------------------------------*/
std::error_code ArchicadDBaseCore::makeError(ArchicadDBaseCore::Status code) {
return std::error_code(static_cast<int>(code), instance);
} //ArchicadDBaseCore::makeError
#endif
@@ -0,0 +1,86 @@
#ifndef SPECKLE_DATABASE_ARCHICAD_DBASE_CORE
#define SPECKLE_DATABASE_ARCHICAD_DBASE_CORE
#ifdef ARCHICAD
#include "Active/File/Path.h"
#include "Active/Setting/SettingList.h"
#include "Active/Database/Storage/DBaseSchema.h"
#include "Active/Utility/NameID.h"
#include "Speckle/Event/Subscriber/DocStoreSubscriber.h"
#include "Speckle/Event/Subscriber/ProjectSubscriber.h"
namespace speckle::database {
using ArchicadDBaseSchema = active::database::DBaseSchema<>;
/*!
Core functionality and definitions for a mechanism to store data in a BIM (3rd-party) document/database
Currently implement for Archicad Add-On Objects
*/
class ArchicadDBaseCore {
public:
// MARK: - Types
///Status of of the ArchicadElementDBase database
enum class Status {
nominal, ///<No errors logged
badParameter, ///<The data supplied to an SDK function call was invalid
badID, ///<The ID for the stored data is invalid
error, ///<An unidentified error occurred
};
// MARK: - Static functions
/*!
Make an error code for ArchicadElementDBase processing
@return An STL error code
*/
static std::error_code makeError(ArchicadDBaseCore::Status code);
// MARK: - Constructors
/*!
Default constructor
@param id The document storage identifier
@param schema The document storage schema
*/
ArchicadDBaseCore(const active::utility::NameID& id, ArchicadDBaseSchema&& schema) : m_id(id), m_schema{schema} {}
ArchicadDBaseCore(const ArchicadDBaseCore&) = default;
/*!
Destructor
*/
virtual ~ArchicadDBaseCore() {}
// MARK: - Function (const)
/*!
Get the database schema
@return The database schema
*/
const ArchicadDBaseSchema& getSchema() const { return m_schema; }
/*!
Get the database id
@return The database id
*/
const active::utility::NameID& getID() const { return m_id; }
// MARK: - Functions (mutating)
protected:
private:
///The database schema
ArchicadDBaseSchema m_schema;
///The database ID (mutable to allow lazy loading when data is accessed)
mutable active::utility::NameID m_id;
};
}
#endif //ARCHICAD
#endif //SPECKLE_DATABASE_ARCHICAD_DBASE_CORE
@@ -0,0 +1,297 @@
#include "Speckle/Database/Storage/ArchicadDBase/Attribute/ArchicadAttributeDBaseEngine.h"
#ifdef ARCHICAD
#include "Active/Utility/Defer.h"
#include "Active/Utility/Memory.h"
#include "Active/Utility/String.h"
#include "Speckle/Record/Attribute/Finish.h"
#include "Speckle/Record/Attribute/Storey.h"
#include "Speckle/Database/Identity/BIMLink.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/Environment/Project.h"
#include "Speckle/Event/Type/DocStoreMergeEvent.h"
#include "Speckle/Event/Type/ProjectEvent.h"
#include "Speckle/Utility/Guid.h"
#include "Speckle/Utility/String.h"
#include <ACAPinc.h>
#include <ACAPI_Database.h>
#include <BM.hpp>
using namespace active::event;
using namespace active::setting;
using namespace speckle::database;
using namespace speckle::environment;
using namespace speckle::event;
using namespace speckle::record::attribute;
using namespace speckle::utility;
using enum ArchicadDBaseCore::Status;
namespace speckle::database {
#ifdef ARCHICAD
/*!
A class to collect and manage a list of active Archicad storeys
NB: This list has to be rebuilt every time a storey has changed because Archicad reindexes storeys each time
This class also has to release memory used by the API to hold storey data
*/
class ArchicadAttributeDBaseEngine::StoreyCache : public std::vector<API_StoryType> {
public:
/*!
Constructor (NB: This automatically gathers information about the current storeys)
*/
StoreyCache() { rebuild(); }
/*!
Rebuild the current storey list
*/
void rebuild() {
clear();
API_StoryInfo storeyInfo;
active::utility::Memory::erase(storeyInfo);
ACAPI_ProjectSetting_GetStorySettings(&storeyInfo);
auto storeyCount = storeyInfo.lastStory - storeyInfo.firstStory + 1;
for (auto i = 0; i < storeyCount; ++i)
push_back((*storeyInfo.data)[i]);
BMKillHandle(reinterpret_cast<GSHandle*>(&storeyInfo.data));
}
/*!
Find a storey by unique ID
@param id The storey unique ID
@return An iterator pointing to the found storey (end() on failure)
*/
const_iterator find(const Guid& id) const {
auto floorID = static_cast<short>(Guid::toInt(id));
return std::find_if(begin(), end(), [&](auto storey){ return storey.floorId == floorID; });
}
/*!
Find a storey by index
@param index The storey index
@return An iterator pointing to the found storey (end() on failure)
*/
const_iterator find(short index) const {
return std::find_if(begin(), end(), [&](auto storey){ return storey.index == index; });
}
};
#endif
}
namespace {
///Attribute factory
std::unordered_map<active::utility::Guid, std::function<Attribute::Unique(API_Attribute, const active::utility::Guid&)>> attributeFactory;
#ifdef ARCHICAD
/*!
Make a new attribute object
@param attributeData The API attribute representation
@return A new attribute object (nullptr on failure)
*/
Attribute::Unique makeAttribute(const API_Attribute& attributeData) {
auto tableID = active::utility::Guid::fromInt(static_cast<uint64_t>(attributeData.header.typeID));
if (attributeFactory.empty()) {
attributeFactory[active::utility::Guid::fromInt(static_cast<uint64_t>(attributeData.header.typeID))] =
[](API_Attribute attrData, const active::utility::Guid& tableID){ return std::make_unique<Finish>(attrData, tableID); };
}
if (auto iter = attributeFactory.find(tableID); iter != attributeFactory.end())
return iter->second(attributeData, tableID);
return nullptr;
}
/*!
Get the AC API data for a specified attribute
@param ID The attribute ID
@param tableID The parent table ID
@return A new attribute object (nullptr on failure)
*/
std::optional<API_Attribute> getAPIData(const BIMRecordID& ID, std::optional<BIMRecordID> tableID) {
API_Attribute attribute;
active::utility::Memory::erase(attribute);
attribute.header.index = ACAPI_CreateAttributeIndex(static_cast<int32_t>(Guid::toInt(ID)));
attribute.header.typeID = static_cast<API_AttrTypeID>(Guid::toInt(*tableID));
if (ACAPI_Attribute_Get(&attribute) != NoError)
return std::nullopt;
return attribute;
}
#endif
}
/*--------------------------------------------------------------------
Constructor
id: The document storage identifier
--------------------------------------------------------------------*/
ArchicadAttributeDBaseEngine::ArchicadAttributeDBaseEngine(const active::utility::NameID& id, ArchicadDBaseSchema&& schema) :
ArchicadDBaseCore{id, std::move(schema)} {
} //ArchicadAttributeDBaseEngine::ArchicadAttributeDBaseEngine
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
ArchicadAttributeDBaseEngine::~ArchicadAttributeDBaseEngine() {
} //ArchicadAttributeDBaseEngine::~ArchicadAttributeDBaseEngine
/*--------------------------------------------------------------------
Get an object by ID
objID: The object index
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (when the object is bound to a specific document)
return: The requested object (nullptr on failure)
--------------------------------------------------------------------*/
std::unique_ptr<Attribute> ArchicadAttributeDBaseEngine::getObject(const BIMRecordID& objID, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
if (!tableID)
return nullptr;
if (auto attrData = ::getAPIData(objID, *tableID); attrData)
return makeAttribute(*attrData);
return nullptr;
} //ArchicadAttributeDBaseEngine::getObject
/*--------------------------------------------------------------------
Get an object in a transportable form, e.g. packaged for serialisation
index: The object index
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (when the object is bound to a specific document)
return: The requested wrapped cargo (nullptr on failure)
--------------------------------------------------------------------*/
active::serialise::Cargo::Unique ArchicadAttributeDBaseEngine::getObjectCargo(const BIMRecordID& ID, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
return nullptr; //TODO: Implement
} //ArchicadAttributeDBaseEngine::getObject
/*--------------------------------------------------------------------
Get all objects
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (filter for this document only - nullopt = all objects)
return: The requested objects (nullptr on failure)
--------------------------------------------------------------------*/
active::container::Vector<Attribute> ArchicadAttributeDBaseEngine::getObjects(std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
return {}; //TODO: Implement
} //ArchicadAttributeDBaseEngine::getObjects
/*--------------------------------------------------------------------
Get all objects
filter: The object filter
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (filter for this document only - nullopt = all objects)
return: The requested objects (nullptr on failure)
--------------------------------------------------------------------*/
active::container::Vector<Attribute> ArchicadAttributeDBaseEngine::getObjects(const Filter& filter, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
return {}; //TODO: Implement
} //ArchicadAttributeDBaseEngine::getObjects
/*--------------------------------------------------------------------
Write an object to the database
object: The object to write
objID: The object ID
objDocID: The object document-specific ID (unique within a specific document - nullopt if not document-bound)
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (when the object is bound to a specific document)
--------------------------------------------------------------------*/
void ArchicadAttributeDBaseEngine::write(const Attribute& object, const BIMRecordID& objID, std::optional<BIMRecordID> objDocID,
std::optional<BIMRecordID> tableID, std::optional<BIMRecordID> documentID) const {
//TODO: Implement
} //ArchicadAttributeDBaseEngine::write
/*--------------------------------------------------------------------
Erase an object by index
objID: The object ID
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (when the object is bound to a specific document)
return: True if the object was successfully erased
--------------------------------------------------------------------*/
void ArchicadAttributeDBaseEngine::erase(const BIMRecordID& ID, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
//TODO: Implement
} //ArchicadAttributeDBaseEngine::erase
/*--------------------------------------------------------------------
Erase all objects
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (filter for this document only - nullopt = all objects)
--------------------------------------------------------------------*/
void ArchicadAttributeDBaseEngine::erase(std::optional<BIMRecordID> tableID, std::optional<BIMRecordID> documentID) const {
//TODO: Implement
} //ArchicadAttributeDBaseEngine::erase
/*--------------------------------------------------------------------
Get the database outline
return: The database outline
--------------------------------------------------------------------*/
ArchicadAttributeDBaseEngine::Outline ArchicadAttributeDBaseEngine::getOutline() const {
return {}; //TODO: Implement
} //ArchicadAttributeDBaseEngine::getOutline
/*--------------------------------------------------------------------
Get attribute data direct from the AC API. For internal use - avoid direct use
link: A link to the required attribute
return: The AC API attribute data
--------------------------------------------------------------------*/
std::optional<API_Attribute> ArchicadAttributeDBaseEngine::getAPIData(const BIMLink& link) const {
return ::getAPIData(link, link.tableID);
} //ArchicadAttributeDBaseEngine::getAPIData
/*--------------------------------------------------------------------
Get storey data direct from the AC API. For internal use - avoid direct use
link: A link to the required storey
return: The AC API storey data
--------------------------------------------------------------------*/
std::optional<API_StoryType> ArchicadAttributeDBaseEngine::getAPIStorey(const BIMLink& link) const {
if (!m_storeyCache)
m_storeyCache = std::make_unique<StoreyCache>();
if (auto iter = m_storeyCache->find(link); iter != m_storeyCache->end())
return *iter;
return std::nullopt;
} //ArchicadAttributeDBaseEngine::getAPIStorey
/*--------------------------------------------------------------------
Get the ID of a storey from a specified index
index: The storey index
return: The storey ID (nullopt on failure)
--------------------------------------------------------------------*/
std::optional<BIMRecordID> ArchicadAttributeDBaseEngine::getStoreyID(short index) const {
if (!m_storeyCache)
m_storeyCache = std::make_unique<StoreyCache>();
if (auto iter = m_storeyCache->find(index); iter != m_storeyCache->end())
return Guid::fromInt(iter->floorId);
return std::nullopt;
} //ArchicadAttributeDBaseEngine::getStoreyID
#endif
@@ -0,0 +1,148 @@
#ifndef SPECKLE_DATABASE_ARCHICAD_ATTRIBUTE_DBASE_ENGINE
#define SPECKLE_DATABASE_ARCHICAD_ATTRIBUTE_DBASE_ENGINE
#include "Active/Database/Storage/DBaseEngine.h"
#include "Active/Serialise/UnboxedTransport.h"
#include "Speckle/Database/Storage/ArchicadDBase/ArchicadDBaseCore.h"
#include "Speckle/Database/Identity/BIMLink.h"
#include "Speckle/Record/Attribute/Attribute.h"
#include "Speckle/Utility/Guid.h"
#include "Speckle/Utility/String.h"
#include <algorithm>
#include <ranges>
namespace speckle::database {
/*!
A database engine to read/write elements in an Archicad project database (local file or cloud-based)
For attribute indices:
- Each attribute type is considered to be stored in a dedicated table
- For Archicad:
- The table ID is typically the attribute type ID
- The record ID is the attribute index
- Storeys are also treated as an attribute (the API treats them separately, although application to elements is virtually the identical)
*/
class ArchicadAttributeDBaseEngine : public ArchicadDBaseCore,
public active::database::DBaseEngine<record::attribute::Attribute, BIMRecordID, BIMRecordID, BIMRecordID> {
public:
// MARK: - Types
using base = active::database::DBaseEngine<record::attribute::Attribute, BIMRecordID, BIMRecordID, BIMRecordID>;
using Attribute = record::attribute::Attribute;
using Filter = base::Filter;
using Outline = base::Outline;
// MARK: - Constructors
/*!
Constructor
@param id The document storage identifier
*/
ArchicadAttributeDBaseEngine(const active::utility::NameID& id, ArchicadDBaseSchema&& schema);
ArchicadAttributeDBaseEngine(const ArchicadAttributeDBaseEngine&) = delete;
/*!
Destructor
*/
~ArchicadAttributeDBaseEngine();
// MARK: - Functions (const)
/*!
Get an object by ID
@param objID The object ID
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
@return The requested object (nullptr on failure)
*/
std::unique_ptr<Attribute> getObject(const BIMRecordID& objID, std::optional<BIMRecordID> tableID = std::nullopt, std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Get an object in a transportable form, e.g. packaged for serialisation
@param objID The object ID
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
@return: The requested wrapped cargo (nullptr on failure)
*/
active::serialise::Cargo::Unique getObjectCargo(const BIMRecordID& objID, std::optional<BIMRecordID> tableID = std::nullopt, std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Get all objects
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return The requested objects (nullptr on failure)
*/
active::container::Vector<Attribute> getObjects(std::optional<BIMRecordID> tableID = std::nullopt, std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Get a filtered list of objects
@param filter The object filter
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return The filtered objects (nullptr on failure)
*/
active::container::Vector<Attribute> getObjects(const Filter& filter, std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Write an object to the database
@param object The object to write
@param objID The object ID
@param objDocID The object document-specific ID (unique within a specific document - nullopt if not document-bound)
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
*/
void write(const Attribute& object, const BIMRecordID& objID, std::optional<BIMRecordID> objDocID = std::nullopt,
std::optional<BIMRecordID> tableID = std::nullopt, std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Erase an object by index
@param ID The object ID
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
@throw Exception thrown on SQL error
*/
void erase(const BIMRecordID& ID, std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Erase all objects
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
@throw Exception thrown on SQL error
*/
void erase(std::optional<BIMRecordID> tableID = std::nullopt, std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Get the database outline
@return The database outline
*/
Outline getOutline() const override;
#ifdef ARCHICAD
/*!
Get attribute data direct from the AC API. For internal use - avoid direct use
@param link A link to the required attribute
@return The AC API attribute data
*/
std::optional<API_Attribute> getAPIData(const BIMLink& link) const;
/*!
Get storey data direct from the AC API. For internal use - avoid direct use
@param link A link to the required storey
@return The AC API storey data
*/
std::optional<API_StoryType> getAPIStorey(const BIMLink& link) const;
/*!
Get the ID of a storey from a specified index
@param index The storey index
@return The storey ID (nullopt on failure)
*/
std::optional<BIMRecordID> getStoreyID(short index) const;
#endif
private:
void setTable(std::optional<BIMRecordID> tableID = std::nullopt, std::optional<BIMRecordID> documentID = std::nullopt);
class StoreyCache;
///Cache of storeys in the database (saves repeated lookups)
mutable std::unique_ptr<StoreyCache> m_storeyCache;
};
}
#endif //SPECKLE_DATABASE_ARCHICAD_ATTRIBUTE_DBASE_ENGINE
@@ -0,0 +1,233 @@
#include "Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.h"
#ifdef ARCHICAD
#include "Active/Utility/Defer.h"
#include "Active/Utility/Memory.h"
#include "Active/Utility/String.h"
#include "Speckle/Database/Identity/BIMLink.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/Environment/Project.h"
#include "Speckle/Event/Type/DocStoreMergeEvent.h"
#include "Speckle/Event/Type/ProjectEvent.h"
#include "Speckle/Utility/Guid.h"
#include "Speckle/Utility/String.h"
#include <ACAPinc.h>
#include <ACAPI_Database.h>
#include <BM.hpp>
using namespace active::event;
using namespace active::setting;
using namespace speckle::database;
using namespace speckle::environment;
using namespace speckle::event;
using namespace speckle::record::element;
using namespace speckle::utility;
using enum ArchicadDBaseCore::Status;
namespace {
/*!
Get information about a specified Archicad table
@param tableID The ID of the target table
@return The requested table info (nullopt on failure)
*/
std::optional<API_DatabaseInfo> getTableInfo(const BIMRecordID& tableID) {
API_DatabaseInfo dbaseInfo;
dbaseInfo.databaseUnId.elemSetId = tableID;
if (auto err = ACAPI_Window_GetDatabaseInfo(&dbaseInfo); err == NoError)
return dbaseInfo;
return std::nullopt;
} //getTableInfo
/*!
Set the active Archicad table
@param tableID The target table ID
@return True on success
*/
bool setActiveTable(const BIMRecordID& tableID) {
if (!tableID)
return false; //Null guid doens't point to anything
if (auto activeTable = ArchicadElementDBaseEngine::getActiveTable(); activeTable && *activeTable == tableID)
return true;
auto dbaseInfo = getTableInfo(tableID);
if (!dbaseInfo)
return false;
return ACAPI_Database_ChangeCurrentDatabase(&*dbaseInfo) == NoError;
} //setActiveTable
/*!
Make a new element object
@param elementData The API element representation
@param tableID The ID of the parent table (defaults to the active drawing)
@return A new element object (nullptr on failure)
*/
Element::Unique makeElement(const API_Element& elementData, const BIMRecordID& tableID) {
//Implement an object factory in future as classes for specific element types are implemented, e.g. Wall, Roof etc. using hash map
//The fallback for undefined element types will always be the base Element class
return std::make_unique<Element>(elementData, tableID);
}
}
/*--------------------------------------------------------------------
Get the ID of the active Archicad table
return; The active table ID (nullopt on failure)
--------------------------------------------------------------------*/
std::optional<BIMRecordID> ArchicadElementDBaseEngine::getActiveTable() {
API_WindowInfo dbaseInfo;
active::utility::Memory::erase(dbaseInfo);
if (auto err = ACAPI_Database_GetCurrentDatabase(&dbaseInfo); err == NoError)
return dbaseInfo.databaseUnId.elemSetId;
return std::nullopt;
} //ArchicadElementDBaseEngine::getActiveTable
/*--------------------------------------------------------------------
Get the current user element selection
return: A list of selected element IDs
--------------------------------------------------------------------*/
BIMLinkList ArchicadElementDBaseEngine::getSelection() const {
auto tableID = getActiveTable();
if (!tableID)
return {};
BIMLinkList result;
API_SelectionInfo selectionInfo;
active::utility::Memory::erase(selectionInfo);
GS::Array<API_Neig> selection;
if (auto err = ACAPI_Selection_Get(&selectionInfo, &selection, true); err == NoError) {
for (const auto& item : selection)
result.push_back(BIMLink{item, *tableID});
}
return result;
} //ArchicadElementDBaseEngine::getSelection
/*--------------------------------------------------------------------
Get an object by index
index: The object index
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (when the object is bound to a specific document)
return: The requested object (nullptr on failure)
--------------------------------------------------------------------*/
std::unique_ptr<Element> ArchicadElementDBaseEngine::getObject(const BIMRecordID& ID, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
if (!tableID) {
tableID = getActiveTable();
if (!tableID)
return nullptr;
}
API_Element element;
active::utility::Memory::erase(element);
API_Guid guid{ID.operator API_Guid()};
if (ACAPI_Element_GetElementFromAnywhere(&guid, &element) != NoError)
return nullptr;
return makeElement(element, *tableID);
} //ArchicadElementDBaseEngine::getObject
/*--------------------------------------------------------------------
Get an object in a transportable form, e.g. packaged for serialisation
index: The object index
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (when the object is bound to a specific document)
return: The requested wrapped cargo (nullptr on failure)
--------------------------------------------------------------------*/
active::serialise::Cargo::Unique ArchicadElementDBaseEngine::getObjectCargo(const BIMRecordID& ID, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
return nullptr; //TODO: Implement
} //ArchicadElementDBaseEngine::getObject
/*--------------------------------------------------------------------
Get all objects
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (filter for this document only - nullopt = all objects)
return: The requested objects (nullptr on failure)
--------------------------------------------------------------------*/
active::container::Vector<Element> ArchicadElementDBaseEngine::getObjects(std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
if (tableID)
setActiveTable(*tableID);
return {}; //TODO: Implement
} //ArchicadElementDBaseEngine::getObjects
/*--------------------------------------------------------------------
Get all objects
filter: The object filter
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (filter for this document only - nullopt = all objects)
return: The requested objects (nullptr on failure)
--------------------------------------------------------------------*/
active::container::Vector<Element> ArchicadElementDBaseEngine::getObjects(const Filter& filter, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
return {};
} //ArchicadElementDBaseEngine::getObjects
/*--------------------------------------------------------------------
Write an object to the database
object: The object to write
objID: The object ID
objDocID: The object document-specific ID (unique within a specific document - nullopt if not document-bound)
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (when the object is bound to a specific document)
--------------------------------------------------------------------*/
void ArchicadElementDBaseEngine::write(const Element& object, const BIMRecordID& objID, std::optional<BIMRecordID> objDocID,
std::optional<BIMRecordID> tableID, std::optional<BIMRecordID> documentID) const {
} //ArchicadElementDBaseEngine::write
/*--------------------------------------------------------------------
Erase an object by index
objID: The object ID
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (when the object is bound to a specific document)
return: True if the object was successfully erased
--------------------------------------------------------------------*/
void ArchicadElementDBaseEngine::erase(const BIMRecordID& ID, std::optional<BIMRecordID> tableID,
std::optional<BIMRecordID> documentID) const {
} //ArchicadElementDBaseEngine::erase
/*--------------------------------------------------------------------
Erase all objects
tableID: Optional table ID (defaults to the floor plan)
documentID: Optional document ID (filter for this document only - nullopt = all objects)
--------------------------------------------------------------------*/
void ArchicadElementDBaseEngine::erase(std::optional<BIMRecordID> tableID, std::optional<BIMRecordID> documentID) const {
} //ArchicadElementDBaseEngine::erase
/*--------------------------------------------------------------------
Get the database outline
return: The database outline
--------------------------------------------------------------------*/
ArchicadElementDBaseEngine::Outline ArchicadElementDBaseEngine::getOutline() const {
return {};
} //ArchicadElementDBaseEngine::getOutline
#endif
@@ -0,0 +1,125 @@
#ifndef SPECKLE_DATABASE_ARCHICAD_ELEMENT_DBASE_ENGINE
#define SPECKLE_DATABASE_ARCHICAD_ELEMENT_DBASE_ENGINE
#include "Active/Database/Storage/DBaseEngine.h"
#include "Active/Serialise/UnboxedTransport.h"
#include "Speckle/Database/Storage/ArchicadDBase/ArchicadDBaseCore.h"
#include "Speckle/Database/Identity/BIMLink.h"
#include "Speckle/Record/Element/Element.h"
#include "Speckle/Utility/Guid.h"
#include "Speckle/Utility/String.h"
#include <algorithm>
#include <ranges>
namespace speckle::database {
/*!
A database engine to read/write elements in an Archicad project database (local file or cloud-based)
*/
class ArchicadElementDBaseEngine : public ArchicadDBaseCore,
public active::database::DBaseEngine<record::element::Element,BIMRecordID, BIMRecordID, BIMRecordID> {
public:
// MARK: - Types
using base = active::database::DBaseEngine<record::element::Element,BIMRecordID, BIMRecordID, BIMRecordID>;
using Element = record::element::Element;
using Filter = base::Filter;
using Outline = base::Outline;
// MARK: - Static functions
/*!
Get the ID of the active Archicad table
@return The active table ID (nullopt on failure)
*/
static std::optional<BIMRecordID> getActiveTable();
// MARK: - Constructors
/*!
Constructor
@param id The document storage identifier
*/
ArchicadElementDBaseEngine(const active::utility::NameID& id, ArchicadDBaseSchema&& schema) : ArchicadDBaseCore{id, std::move(schema)} {}
ArchicadElementDBaseEngine(const ArchicadElementDBaseEngine&) = delete;
// MARK: - Functions (const)
/*!
Get the current user element selection
@return A list of selected element IDs
*/
BIMLinkList getSelection() const;
/*!
Get an object by index
@param objID The object ID
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
@return The requested object (nullptr on failure)
*/
std::unique_ptr<Element> getObject(const BIMRecordID& objID, std::optional<BIMRecordID> tableID = std::nullopt, std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Get an object in a transportable form, e.g. packaged for serialisation
@param objID The object ID
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
@return: The requested wrapped cargo (nullptr on failure)
*/
active::serialise::Cargo::Unique getObjectCargo(const BIMRecordID& objID, std::optional<BIMRecordID> tableID = std::nullopt, std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Get all objects
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return The requested objects (nullptr on failure)
*/
active::container::Vector<Element> getObjects(std::optional<BIMRecordID> tableID = std::nullopt, std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Get a filtered list of objects
@param filter The object filter
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (filter for this document only - nullopt = all objects)
@return The filtered objects (nullptr on failure)
*/
active::container::Vector<Element> getObjects(const Filter& filter, std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Write an object to the database
@param object The object to write
@param objID The object ID
@param objDocID The object document-specific ID (unique within a specific document - nullopt if not document-bound)
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
*/
void write(const Element& object, const BIMRecordID& objID, std::optional<BIMRecordID> objDocID = std::nullopt,
std::optional<BIMRecordID> tableID = std::nullopt, std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Erase an object by index
@param ID The object ID
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
@throw Exception thrown on SQL error
*/
void erase(const BIMRecordID& ID, std::optional<BIMRecordID> tableID = std::nullopt,
std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Erase all objects
@param tableID Optional table ID (defaults to the floor plan)
@param documentID Optional document ID (when the object is bound to a specific document)
@throw Exception thrown on SQL error
*/
void erase(std::optional<BIMRecordID> tableID = std::nullopt, std::optional<BIMRecordID> documentID = std::nullopt) const override;
/*!
Get the database outline
@return The database outline
*/
Outline getOutline() const override;
private:
void setTable(std::optional<BIMRecordID> tableID = std::nullopt, std::optional<BIMRecordID> documentID = std::nullopt);
};
}
#endif //SPECKLE_DATABASE_ARCHICAD_ELEMENT_DBASE_ENGINE
@@ -105,7 +105,7 @@ namespace {
public:
///Category name
const char* name() const noexcept override {
return "active::database::sqlite::category";
return "speckle::database::docStore::category";
}
/*!
Get a message for a specified error code
@@ -122,6 +122,11 @@ namespace speckle::database {
@return The database outline
*/
Outline getOutline() const override;
/*!
Get the engine unique ID
@return The unique ID
*/
RecordID getUniqueID() const { return getCache()->getID(); }
protected:
/*!
@@ -1,5 +1,7 @@
#include "Speckle/Environment/Project.h"
#include "Speckle/Database/BIMAttributeDatabase.h"
#include "Speckle/Database/BIMElementDatabase.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/SpeckleResource.h"
@@ -7,6 +9,7 @@
#include <ACAPinc.h>
#endif
using namespace speckle::database;
using namespace speckle::environment;
using namespace speckle::utility;
@@ -20,6 +23,8 @@ namespace {
identity: Optional name/ID for the subscriber
--------------------------------------------------------------------*/
Project::Project() {
m_element = std::make_unique<BIMElementDatabase>();
m_attribute = std::make_unique<BIMAttributeDatabase>();
} //Project::Project
+21
View File
@@ -4,6 +4,11 @@
#include "Active/File/Path.h"
#include "Speckle/Utility/String.h"
namespace speckle::database {
class BIMAttributeDatabase;
class BIMElementDatabase;
}
namespace speckle::environment {
class Addon;
@@ -50,6 +55,16 @@ namespace speckle::environment {
@return Project information
*/
Info getInfo() const;
/*!
Get the account database
@return The account database
*/
const database::BIMElementDatabase* getElementDatabase() const { return m_element.get(); }
/*!
Get the account database
@return The account database
*/
const database::BIMAttributeDatabase* getAttributeDatabase() const { return m_attribute.get(); }
// MARK: - Functions (mutating)
@@ -62,6 +77,12 @@ namespace speckle::environment {
NB: Only the Addon class can create projects. Clients can get the active project from the running add-on.
*/
Project();
private:
///The BIM element database
std::unique_ptr<database::BIMElementDatabase> m_element;
///The BIM attribute database
std::unique_ptr<database::BIMAttributeDatabase> m_attribute;
};
}
@@ -1,7 +1,8 @@
#include "Speckle/Event/Subscriber/SelectionSubscriber.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/Database/Identity/Link.h"
#include "Speckle/Database/Identity/BIMLink.h"
#include "Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.h"
#include "Speckle/Event/Type/SelectionEvent.h"
#ifdef ARCHICAD
@@ -23,8 +24,10 @@ namespace {
*/
GSErrCode __ACENV_CALL selectionCallback(const API_Neig* params) {
if (addon() != nullptr) {
auto selection = (params == nullptr) ? Link{} : Link{*params};
addon()->publishExternal(SelectionEvent{selection});
if (auto tableID = ArchicadElementDBaseEngine::getActiveTable(); tableID) {
auto selection = (params == nullptr) ? BIMLink{} : BIMLink{*params, *tableID};
addon()->publishExternal(SelectionEvent{selection});
}
}
return NoError;
}
@@ -5,7 +5,7 @@
#include "Active/Utility/Guid.h"
#include "Active/Utility/String.h"
#include "Speckle/Database/Identity/Link.h"
#include "Speckle/Database/Identity/BIMLink.h"
namespace speckle::event {
@@ -24,7 +24,7 @@ namespace speckle::event {
Constructor
@param selected A link to a selected element (nullopt if the selection is empty)
*/
SelectionEvent(speckle::database::Link::Option selected) : m_selectedLink{selected} {}
SelectionEvent(speckle::database::BIMLink::Option selected) : m_selectedLink{selected} {}
/*!
Copy constructor
@param source The object to copy
@@ -46,10 +46,10 @@ namespace speckle::event {
Get a link to the last selected element
@return A link to the last selected element (nullopt if the event selection is empty)
*/
speckle::database::Link::Option getLastSelected() const { return m_selectedLink; }
speckle::database::BIMLink::Option getLastSelected() const { return m_selectedLink; }
private:
speckle::database::Link::Option m_selectedLink;
speckle::database::BIMLink::Option m_selectedLink;
};
}
@@ -0,0 +1,72 @@
#include "Speckle/Primitive/Mesh/Mesh.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
#include "Active/Serialise/Inventory/Identity.h"
#include <array>
using namespace active::serialise;
using namespace speckle::primitive;
namespace {
///Serialisation fields
enum FieldIndex {
vertexID,
faceID,
colorID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"vertices"},
Identity{"faces"},
Identity{"colors"},
};
}
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool Mesh::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[vertexID], vertexID, element },
{ fieldID[faceID], faceID, element },
{ fieldID[colorID], colorID, element },
},
}.withType(&typeid(Mesh)));
return base::fillInventory(inventory);
} //Mesh::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique Mesh::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(Mesh))
return base::getCargo(item);
using namespace active::serialise;
switch (item.index) {
case vertexID:
return std::make_unique<ContainerWrap<std::vector<double>>>(vertices);
case faceID:
return std::make_unique<ContainerWrap<std::vector<int>>>(faces);
case colorID:
return std::make_unique<ContainerWrap<std::vector<int>>>(colors);
default:
return nullptr; //Requested an unknown index
}
} //Mesh::getCargo
+68
View File
@@ -0,0 +1,68 @@
#ifndef SPECKLE_PRIMITIVE_MESH
#define SPECKLE_PRIMITIVE_MESH
#include "Speckle/Database/Content/BIMRecord.h"
#include "Speckle/Utility/String.h"
namespace speckle::primitive {
/*!
Class for a 3D mesh
*/
class Mesh : public speckle::database::BIMRecord {
public:
// MARK: - Types
using base = speckle::database::BIMRecord;
// MARK: - Constructors
/*!
Default constructor
@param unit The mesh unit type
*/
Mesh(active::measure::LengthType unit = active::measure::LengthType::metre) : base{unit} {}
/*!
Constructor
@param vertices The mesh vertices
@param faces The mesh faces (the number of indices in the face followed by the vertex indices)
@param colors The mesh face colours
@param unit The mesh unit type
*/
Mesh(std::vector<double>&& vertices, std::vector<int>&& faces, std::vector<int>&& colors,
active::measure::LengthType unit = active::measure::LengthType::metre) :
base{unit}, vertices {std::move(vertices)}, faces{std::move(faces)}, colors{std::move(colors)} {}
// MARK: - Functions (const)
/*!
Get the speckle type identifier
@return The speckle type (relevant objects should override as required)
*/
speckle::utility::String getSpeckleType() const override { return "speckle::primitive::Mesh"; }
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
active::serialise::Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
private:
std::vector<double> vertices;
std::vector<int> faces;
std::vector<int> colors;
};
}
#endif //SPECKLE_PRIMITIVE_MESH
@@ -0,0 +1,103 @@
#include "Speckle/Record/Attribute/Attribute.h"
#include "Speckle/Database/BIMAttributeDatabase.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/Environment/Project.h"
using namespace active::serialise;
using namespace speckle::database;
using namespace speckle::environment;
using namespace speckle::record::attribute;
using namespace speckle::utility;
#include <array>
#include <memory>
namespace {
///Serialisation fields
enum FieldIndex {
nameID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"name"},
};
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
Attribute::Attribute() {
} //Attribute::Attribute
/*--------------------------------------------------------------------
Get the attribute name
return: The attribute name
--------------------------------------------------------------------*/
speckle::utility::String Attribute::getName() const {
#ifdef ARCHICAD
return getHead().name;
#endif
} //Attribute::getName
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool Attribute::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[nameID], nameID, element },
},
}.withType(&typeid(Attribute)));
return base::fillInventory(inventory);
} //Attribute::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique Attribute::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(Attribute))
return base::getCargo(item);
using namespace active::serialise;
switch (item.index) {
case nameID:
//return std::make_unique<active::serialise::ContainerWrap>(*body);
return std::make_unique<StringWrap>(getHead().name);
default:
return nullptr; //Requested an unknown index
}
} //Attribute::getCargo
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Get the attribute data from the host BIM application
return: The attribute data (for internal use to populate derived classes)
--------------------------------------------------------------------*/
API_Attribute Attribute::getData() const {
if (auto project = addon()->getActiveProject().lock(); project) {
if (auto attr = project->getAttributeDatabase()->getAPIData(getBIMLink()); attr)
return *attr;
}
API_Attribute attr;
active::utility::Memory::erase(attr);
return attr;
} //Attribute::getData
#endif
@@ -0,0 +1,120 @@
#ifndef SPECKLE_RECORD_ATTRIBUTE
#define SPECKLE_RECORD_ATTRIBUTE
#include "Speckle/Database/Content/BIMRecord.h"
#include "Speckle/Utility/String.h"
namespace speckle::record::attribute {
/*!
Base BIM attribute class
*/
class Attribute : public speckle::database::BIMRecord {
public:
// MARK: - Types
using base = speckle::database::BIMRecord;
///Unique pointer
using Unique = std::unique_ptr<Attribute>;
///Shared pointer
using Shared = std::shared_ptr<Attribute>;
///Optional
using Option = std::optional<Attribute>;
// MARK: - Constants
#ifdef ARCHICAD
///Archicad type identifier for a storey attribute table
static constexpr int32_t storeyTableID = 0x200;
/*!
Get an attribute type ID from a table ID
@param tableID The table ID
@return The attribute type ID (NB: not strictly API_AttrTypeID - can be storeyTypeID)
*/
static API_AttrTypeID getTypeID(const active::utility::Guid& tableID) {
return static_cast<API_AttrTypeID>(active::utility::Guid::toInt(tableID));
}
/*!
Get an Archicad attribute index from a record ID
@param recordID The record ID
@return An attribute index
*/
static API_AttributeIndex getIndex(const active::utility::Guid& recordID) {
return ACAPI_CreateAttributeIndex(static_cast<int32_t>(active::utility::Guid::toInt(recordID)));
}
#endif
// MARK: - Constructors
using base::base;
/*!
Default constructor
*/
Attribute();
/*!
Constructor
@param ID The attribute ID
@param tableID The attribute table ID (attribute type)
*/
Attribute(const database::BIMRecordID& ID, const speckle::utility::Guid& tableID) : base{ID, tableID} {}
// MARK: - Functions (const)
/*!
Get the speckle type identifier
@return The speckle type (relevant objects should override as required)
*/
speckle::utility::String getSpeckleType() const override { return "speckle::record::attribute::Attribute"; }
/*!
Get the attribute name
@return The attribute name
*/
speckle::utility::String getName() const;
#ifdef ARCHICAD
/*!
Get the (immutable) API attribute header data
@return The attribute header data (only use this data for low-level operations - for normal code, call getters/setters)
*/
virtual const API_Attr_Head& getHead() const = 0;
#endif
// MARK: - Functions (mutating)
#ifdef ARCHICAD
/*!
Get the (mutable) API attribute header data
@return The attribute header data (only use this data for low-level operations - for normal code, call getters/setters)
*/
virtual API_Attr_Head& getHead() = 0;
#endif
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
protected:
#ifdef ARCHICAD
/*!
Get the attribute data from the host BIM application
@return The attribute data (for internal use to populate derived classes)
*/
API_Attribute getData() const;
#endif
};
}
#endif //SPECKLE_RECORD_ATTRIBUTE
@@ -0,0 +1,205 @@
#include "Speckle/Record/Attribute/Finish.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Utility/BufferOut.h"
#include "Speckle/Utility/Guid.h"
#ifdef ARCHICAD
#include <ModelMaterial.hpp>
#endif
using namespace active::serialise;
using namespace speckle::database;
using namespace speckle::record::attribute;
using namespace speckle::utility;
#include <array>
#include <memory>
namespace speckle::record::attribute {
class Finish::Data {
public:
#ifdef ARCHICAD
Data(const API_Attribute& attr) : root{attr.material} {}
Data(const Data& source) : root{source.root} {}
API_MaterialType root;
#endif
};
}
namespace {
///Serialisation fields
enum FieldIndex {
surfaceColourID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"surfaceColour"},
};
#ifdef ARCHICAD
/*!
Copy a ModelerAPI colour to an AC RGB colour
*/
void copyModelerColor(const ModelerAPI::Color& modelColour, API_RGBColor& colour) {
colour.f_red = modelColour.red;
colour.f_green = modelColour.green;
colour.f_blue = modelColour.blue;
} //copyModelerColor
#endif
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
Finish::Finish() {
} //Finish::Finish
/*--------------------------------------------------------------------
Constructor
ID: The attribute ID
--------------------------------------------------------------------*/
Finish::Finish(const database::BIMRecordID& ID) : base{ID, Finish::table} {
} //Finish::Finish
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Constructor
attrData: Archicad attribute data
tableID: The ID of the parent table
--------------------------------------------------------------------*/
Finish::Finish(const API_Attribute& attrData, const BIMRecordID& tableID) : base{attrData.header.guid, Finish::table} {
m_data = std::make_unique<Data>(attrData);
}
/*--------------------------------------------------------------------
Constructor
material: A ModelerAPI material definition
--------------------------------------------------------------------*/
Finish::Finish(const ModelerAPI::Material& material) {
API_Attribute attr;
active::utility::Memory::erase(attr);
String{material.GetName()}.writeUTF8(active::utility::BufferOut{attr.header.name});
attr.header.guid = Guid{Guid::fromInt(material.GenerateHashValue())};
attr.material.mtype = static_cast<API_MaterTypeID>(material.GetType());
attr.material.ambientPc = material.GetAmbientReflection();
attr.material.diffusePc = material.GetDiffuseReflection();
attr.material.specularPc = material.GetSpecularReflection();
attr.material.transpPc = material.GetTransparency();
attr.material.shine = material.GetShining();
attr.material.transpAtt = material.GetTransparencyAttenuation();
attr.material.emissionAtt = material.GetEmissionAttenuation();
copyModelerColor(material.GetSurfaceColor(), attr.material.surfaceRGB);
copyModelerColor(material.GetSpecularColor(), attr.material.specularRGB);
copyModelerColor(material.GetEmissionColor(), attr.material.emissionRGB);
m_data = std::make_unique<Data>(attr);
} //Finish::Finish
#endif
/*--------------------------------------------------------------------
Copy constructor
source: The object to copy
--------------------------------------------------------------------*/
Finish::Finish(const Finish& source) : base{source} {
m_data = source.m_data ? std::make_unique<Data>(*m_data) : nullptr;
} //Finish::Finish
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
Finish::~Finish() {}
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Get the (immutable) API attribute header data
return: The attribute header data (only use this data for low-level operations - for normal code, call getters/setters)
--------------------------------------------------------------------*/
const API_Attr_Head& Finish::getHead() const {
confirmData();
return m_data->root.head;
} //Finish::getHead
/*--------------------------------------------------------------------
Get the (mutable) API attribute header data
return: The attribute header data (only use this data for low-level operations - for normal code, call getters/setters)
--------------------------------------------------------------------*/
API_Attr_Head& Finish::getHead() {
confirmData();
return m_data->root.head;
} //Finish::getHead
#endif
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool Finish::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[surfaceColourID], surfaceColourID, element }, //TODO: implement other fields
},
}.withType(&typeid(Finish)));
return base::fillInventory(inventory);
} //Finish::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique Finish::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(Finish))
return base::getCargo(item);
confirmData();
using namespace active::serialise;
switch (item.index) {
case surfaceColourID:
return nullptr; //TODO: lookup surface colour
default:
return nullptr; //Requested an unknown index
}
} //Finish::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void Finish::setDefault() {
} //Finish::setDefault
/*--------------------------------------------------------------------
Confirm the internal data, either loading from the BIM application or setting a default
--------------------------------------------------------------------*/
void Finish::confirmData() const {
if (m_data)
return;
m_data = std::make_unique<Data>(getData());
} //Finish::confirmData
@@ -0,0 +1,139 @@
#ifndef SPECKLE_RECORD_ATTRIBUTE_FINISH
#define SPECKLE_RECORD_ATTRIBUTE_FINISH
#include "Speckle/Record/Attribute/Attribute.h"
#ifdef ARCHICAD
namespace ModelerAPI {
class Material;
}
#endif
namespace speckle::record::attribute {
/*!
Class to represent the rendered finish on a 3D body, i.e. the surface colour/texture etc.
In Archicad this attribute is represented by `API_MaterialType`
*/
class Finish : public Attribute {
public:
// MARK: - Types
using base = Attribute;
///Unique pointer
using Unique = std::unique_ptr<Finish>;
///Shared pointer
using Shared = std::shared_ptr<Finish>;
///Optional
using Option = std::optional<Finish>;
// MARK: - Constants
#ifdef ARCHICAD
///The finishes table identifier
static constexpr active::utility::Guid table{active::utility::Guid::fromInt(API_MaterialID)};
#endif
// MARK: - Constructors
using base::base;
/*!
Default constructor
*/
Finish();
/*!
Constructor
@param ID The attribute ID
*/
Finish(const database::BIMRecordID& ID);
#ifdef ARCHICAD
/*!
Constructor
@param attrData Archicad attribute data
@param tableID The ID of the parent table
*/
Finish(const API_Attribute& attrData, const database::BIMRecordID& tableID);
/*!
Constructor
@param material A ModelerAPI material definition
*/
Finish(const ModelerAPI::Material& material);
#endif
/*!
Copy constructor
@param source The object to copy
*/
Finish(const Finish& source);
/*!
Destructor
*/
~Finish();
/*!
Object cloning
@return A clone of this object
*/
Finish* clonePtr() const override { return new Finish{*this}; }
// MARK: - Functions (const)
/*!
Get the speckle type identifier
@return The speckle type (relevant objects should override as required)
*/
speckle::utility::String getSpeckleType() const override { return "Objects.Other.RenderMaterial"; }
#ifdef ARCHICAD
/*!
Get the (immutable) API attribute header data
@return The attribute header data (only use this data for low-level operations - for normal code, call getters/setters)
*/
const API_Attr_Head& getHead() const override;
#endif
// MARK: - Functions (mutating)
#ifdef ARCHICAD
/*!
Get the (mutable) API attribute header data
@return The attribute header data (only use this data for low-level operations - for normal code, call getters/setters)
*/
API_Attr_Head& getHead() override;
#endif
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
/*!
Set to the default package content
*/
void setDefault() override;
private:
/*!
Confirm the internal data, either loading from the BIM application or setting a default
*/
void confirmData() const;
class Data;
///The attribute data - mutable to support lazy loading
mutable std::unique_ptr<Data> m_data;
};
}
#endif //SPECKLE_RECORD_ATTRIBUTE_FINISH
@@ -0,0 +1,221 @@
#include "Speckle/Record/Attribute/Storey.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Utility/BufferOut.h"
#include "Speckle/Database/BIMAttributeDatabase.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/Environment/Project.h"
#include "Speckle/Utility/Guid.h"
using namespace active::serialise;
using namespace speckle::database;
using namespace speckle::environment;
using namespace speckle::record::attribute;
using namespace speckle::utility;
#include <array>
#include <memory>
namespace speckle::record::attribute {
class Storey::Data {
public:
#ifdef ARCHICAD
Data(const API_StoryType& storey) : root{storey} {}
Data(const Data& source) : root{source.root} {}
API_StoryType root;
API_Attr_Head header;
#endif
};
}
namespace {
///Serialisation fields
enum FieldIndex {
levelID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"level"},
};
#ifdef ARCHICAD
/*!
Fill in an Archicad API attribute header based on a storey
@param header The attribute header to be populated
@param storey The storey to be copied into the header
*/
void fillHeader(API_Attr_Head& header, const API_StoryType& storey) {
active::utility::Memory::erase(header);
//NB: This is not intended to be used for API attribute calls - it only transports core properties within this framework, e.g. name
header.typeID = static_cast<API_AttrTypeID>(Attribute::storeyTableID);
header.index = ACAPI_CreateAttributeIndex(storey.index);
header.guid = Guid{Guid::fromInt(storey.floorId)};
String{storey.uName}.writeUTF8(active::utility::BufferOut{header.name}, true);
}
#endif
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
Storey::Storey() {
} //Storey::Storey
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Constructor
index: An index into the Archicad storey array
--------------------------------------------------------------------*/
Storey::Storey(short index) {
m_storeyIndex = index;
} //Storey::Storey
#endif
/*--------------------------------------------------------------------
Constructor
ID: The attribute ID
--------------------------------------------------------------------*/
Storey::Storey(const database::BIMRecordID& ID) : base{ID, storeyTableID} {
} //Storey::Storey
/*--------------------------------------------------------------------
Copy constructor
source: The object to copy
--------------------------------------------------------------------*/
Storey::Storey(const Storey& source) : base{source} {
m_data = source.m_data ? std::make_unique<Data>(*m_data) : nullptr;
#ifdef ARCHICAD
m_storeyIndex = source.m_storeyIndex;
#endif
} //Storey::Storey
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
Storey::~Storey() {}
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Get the (immutable) API attribute header data
return: The attribute header data (only use this data for low-level operations - for normal code, call getters/setters)
--------------------------------------------------------------------*/
const API_Attr_Head& Storey::getHead() const {
confirmData();
fillHeader(m_data->header, m_data->root);
return m_data->header;
} //Storey::getHead
/*--------------------------------------------------------------------
Get the (mutable) API attribute header data
return: The attribute header data (only use this data for low-level operations - for normal code, call getters/setters)
--------------------------------------------------------------------*/
API_Attr_Head& Storey::getHead() {
confirmData();
fillHeader(m_data->header, m_data->root);
return m_data->header;
} //Storey::getHead
#endif
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool Storey::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[levelID], levelID, element }, //TODO: implement other fields
},
}.withType(&typeid(Storey)));
return base::fillInventory(inventory);
} //Storey::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique Storey::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(Storey))
return base::getCargo(item);
confirmData();
using namespace active::serialise;
switch (item.index) {
case levelID:
return std::make_unique<DoubleWrap>(m_data->root.level);
default:
return nullptr; //Requested an unknown index
}
} //Storey::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void Storey::setDefault() {
} //Storey::setDefault
/*--------------------------------------------------------------------
Confirm the internal data, either loading from the BIM application or setting a default
--------------------------------------------------------------------*/
void Storey::confirmData() const {
if (m_data)
return;
#ifdef ARCHICAD
m_data = std::make_unique<Data>(getStoreyData());
#endif
} //Storey::confirmData
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Get the storey data from the host BIM application
return: The storey data (for internal use to populate derived classes)
--------------------------------------------------------------------*/
API_StoryType Storey::getStoreyData() const {
do {
if (auto project = addon()->getActiveProject().lock(); project) {
auto attributeDatabase = project->getAttributeDatabase();
if (m_storeyIndex) {
auto storeyID = attributeDatabase->getStoreyID(*m_storeyIndex);
m_storeyIndex.reset();
if (!storeyID)
break;
resetIndex({*storeyID, Attribute::storeyTableID});
}
if (auto storey = attributeDatabase->getAPIStorey(getBIMLink()); storey)
return *storey;
}
} while (false);
API_StoryType storey;
active::utility::Memory::erase(storey);
return storey;
} //Storey::getStoreyData
#endif
@@ -0,0 +1,135 @@
#ifndef SPECKLE_RECORD_ATTRIBUTE_STOREY
#define SPECKLE_RECORD_ATTRIBUTE_STOREY
#include "Speckle/Record/Attribute/Attribute.h"
namespace speckle::record::attribute {
/*!
A storey or level in a building
Represented in Archicad by `API_StoryType`
*/
class Storey : public Attribute {
public:
// MARK: - Types
using base = Attribute;
///Unique pointer
using Unique = std::unique_ptr<Storey>;
///Shared pointer
using Shared = std::shared_ptr<Storey>;
///Optional
using Option = std::optional<Storey>;
// MARK: - Constructors
using base::base;
/*!
Default constructor
*/
Storey();
/*!
Constructor
@param ID The attribute ID
*/
Storey(const database::BIMRecordID& ID);
#ifdef ARCHICAD
/*!
Constructor
@param index An index into the Archicad storey array
*/
Storey(short index);
/*!
Constructor
@param attrData Archicad attribute data
*/
Storey(const API_StoryType& attrData);
#endif
/*!
Copy constructor
@param source The object to copy
*/
Storey(const Storey& source);
/*!
Destructor
*/
~Storey();
/*!
Object cloning
@return A clone of this object
*/
Storey* clonePtr() const override { return new Storey{*this}; }
// MARK: - Functions (const)
/*!
Get the speckle type identifier
@return The speckle type (relevant objects should override as required)
*/
speckle::utility::String getSpeckleType() const override { return "speckle::record::attribute::Storey"; }
#ifdef ARCHICAD
/*!
Get the (immutable) API attribute header data
@return The attribute header data (only use this data for low-level operations - for normal code, call getters/setters)
*/
const API_Attr_Head& getHead() const override;
#endif
// MARK: - Functions (mutating)
#ifdef ARCHICAD
/*!
Get the (mutable) API attribute header data
@return The attribute header data (only use this data for low-level operations - for normal code, call getters/setters)
*/
API_Attr_Head& getHead() override;
#endif
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
/*!
Set to the default package content
*/
void setDefault() override;
private:
/*!
Confirm the internal data, either loading from the BIM application or setting a default
*/
void confirmData() const;
#ifdef ARCHICAD
/*!
Get the storey data from the host BIM application
@return The storey data (for internal use to populate derived classes)
*/
API_StoryType getStoreyData() const;
///An index into the Archicad storey array - used temporarily for looking up the storey data on demand
mutable std::optional<short> m_storeyIndex;
#endif
class Data;
///The attribute data - mutable to support lazy loading
mutable std::unique_ptr<Data> m_data;
};
}
#endif //SPECKLE_RECORD_ATTRIBUTE_STOREY
@@ -48,6 +48,17 @@ namespace speckle::record::cred {
// MARK: - Functions (const)
/*!
Get the account server URL
@return The account server URL (nullopt if none specified)
*/
speckle::utility::String getServerURL() const { return m_serverInfo.getURL(); }
/*!
Get the account token
@return The account token
*/
speckle::utility::String getToken() const { return m_token; }
// MARK: - Functions (mutating)
// MARK: - Serialisation
@@ -89,7 +89,7 @@ Cargo::Unique ServerInfo::getCargo(const Inventory::Item& item) const {
case frontEndID:
return std::make_unique<ValueWrap<bool>>(m_frontend2);
case urlID:
return std::make_unique<StringOptWrap>(m_url);
return std::make_unique<StringWrap>(m_url);
case migrationID:
return std::make_unique<Mover>(PackageUniqueWrap{m_migration});
default:
@@ -32,7 +32,7 @@ namespace speckle::record::cred {
*/
ServerInfo(const utility::String& name, const utility::String::Option company = std::nullopt,
const utility::String::Option version = std::nullopt, const utility::String::Option contact = std::nullopt,
const utility::String::Option description = std::nullopt, const utility::String::Option url = std::nullopt,
const utility::String::Option description = std::nullopt, const utility::String url = {},
bool isFrontEnd = false, std::unique_ptr<ServerMigration> migration = nullptr) :
m_name{name}, m_company{company}, m_version{version}, m_adminContact{contact}, m_description{description},
m_url{url}, m_frontend2{isFrontEnd}, m_migration{std::move(migration)} {}
@@ -90,7 +90,7 @@ namespace speckle::record::cred {
Get the URL
@return The URL
*/
const utility::String::Option& getURL() const { return m_url; }
const utility::String& getURL() const { return m_url; }
/*!
Get the migration history
@return The migration history (nullptr = no history)
@@ -143,7 +143,7 @@ namespace speckle::record::cred {
This field is not returned from the GQL API, it should be populated after construction.
See "Speckle.Core.Credentials.AccountManager"
*/
utility::String::Option m_url;
utility::String m_url;
///Server migration record
std::unique_ptr<ServerMigration> m_migration;
};
@@ -0,0 +1,296 @@
#include "Speckle/Record/Element/Element.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
#include "Speckle/Environment/Addon.h"
#include "Speckle/Primitive/Mesh/Mesh.h"
#include "Speckle/SpeckleResource.h"
#include "Speckle/Utility/Guid.h"
#include "Sight.hpp"
#include "Model.hpp"
#include "ModelMaterial.hpp"
#include "ModelElement.hpp"
#include "exp.h"
#include "ModelMeshBody.hpp"
#include "ConvexPolygon.hpp"
using namespace active::serialise;
using namespace speckle::environment;
using namespace speckle::record::attribute;
using namespace speckle::record::element;
using namespace speckle::utility;
#include <array>
#include <memory>
namespace speckle::record::element {
class Element::Data {
public:
friend class Element;
#ifdef ARCHICAD
Data(const API_Element& elem) : root{ std::make_unique<API_Element>(elem) } {}
Data(const Data& source) : root{ std::make_unique<API_Element>(*source.root) } {}
#endif
private:
std::unique_ptr<API_Element> root;
std::unique_ptr<Element::Body> m_cache;
};
}
namespace {
///Serialisation fields
enum FieldIndex {
bodyID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"displayValue"},
};
int32_t ARGBToInt(double alpha, double red, double green, double blue) {
// Convert double (0.0 - 1.0) to uint8_t (0 - 255)
uint8_t a = static_cast<uint8_t>(std::round(alpha * 255.0));
uint8_t r = static_cast<uint8_t>(std::round(red * 255.0));
uint8_t g = static_cast<uint8_t>(std::round(green * 255.0));
uint8_t b = static_cast<uint8_t>(std::round(blue * 255.0));
// Pack ARGB into a single 32-bit integer
return (a << 24) | (r << 16) | (g << 8) | b;
}
}
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
Element::Element() {
} //Element::Element
/*--------------------------------------------------------------------
Constructor
elemData: Archicad element data
tableID: The attribute table ID (attribute type)
--------------------------------------------------------------------*/
Element::Element(const API_Element& elemData, const speckle::utility::Guid& tableID) : base{ elemData.header.guid, tableID } {
m_data = std::make_unique<Data>(elemData);
} //Element::Element
/*--------------------------------------------------------------------
Copy constructor
source: The object to copy
--------------------------------------------------------------------*/
Element::Element(const Element& source) : base{ source } {
m_data = source.m_data ? std::make_unique<Data>(*m_data) : nullptr;
} //Element::Element
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
Element::~Element() {}
/*--------------------------------------------------------------------
Get the element storey
return: The element storey (nullopt if the element isn't linked to a storey)
--------------------------------------------------------------------*/
Storey::Option Element::getStorey() const {
#ifdef ARCHICAD
return Storey{ getHead().floorInd };
#endif
} //Element::getStorey
/*--------------------------------------------------------------------
Get the element type name, e.g. "Wall", "Roof" etc
return: The type name
--------------------------------------------------------------------*/
String Element::getTypeName() const {
#ifdef ARCHICAD
GS::UniString typeName;
if (auto err = ACAPI_Element_GetElemTypeName(getHead().type, typeName); err != NoError)
return addon()->getLocalString(titleStringLib, unknownElementTypeID);
return typeName;
#endif
} //Element::getTypeName
/*--------------------------------------------------------------------
Get the element body as a list of faces or Meshes
return: A pointer to the element body
--------------------------------------------------------------------*/
Element::Body* Element::getBody() const {
#ifdef ARCHICAD
if (m_data->m_cache) {
return m_data->m_cache.get();
}
void* dummy = nullptr;
GSErrCode err = ACAPI_Sight_GetCurrentWindowSight(&dummy);
if (err != NoError)
{
// TODO: should this throw?
}
Modeler::SightPtr currentSightPtr((Modeler::Sight*)dummy); // init the shared ptr with the raw pointer
ModelerAPI::Model acModel;
Modeler::IAttributeReader* attrReader = ACAPI_Attribute_GetCurrentAttributeSetReader();
err = EXPGetModel(currentSightPtr, &acModel, attrReader);
if (err != NoError)
{
// TODO: should this throw?
}
auto elementBody = new Element::Body();
Int32 nElements = acModel.GetElementCount();
for (Int32 iElement = 1; iElement <= nElements; iElement++)
{
ModelerAPI::Element elem{};
acModel.GetElement(iElement, &elem);
if (elem.GetElemGuid() != getHead().guid)
continue;
Int32 nBodies = elem.GetTessellatedBodyCount();
for (Int32 bodyIndex = 1; bodyIndex <= nBodies; ++bodyIndex)
{
ModelerAPI::MeshBody body{};
elem.GetTessellatedBody(bodyIndex, &body);
Int32 polyCount = body.GetPolygonCount();
for (Int32 polyIndex = 1; polyIndex <= polyCount; ++polyIndex)
{
ModelerAPI::Polygon polygon{};
body.GetPolygon(polyIndex, &polygon);
ModelerAPI::Material material{};
polygon.GetMaterial(&material);
Int32 convexPolyCount = polygon.GetConvexPolygonCount();
for (Int32 convPolyIndex = 1; convPolyIndex <= convexPolyCount; ++convPolyIndex)
{
std::vector<double> vertices;
std::vector<int> faces;
std::vector<int> colors;
ModelerAPI::ConvexPolygon convexPolygon{};
polygon.GetConvexPolygon(convPolyIndex, &convexPolygon);
Int32 vertexCount = convexPolygon.GetVertexCount();
faces.push_back(vertexCount);
for (Int32 vertexIndex = 1; vertexIndex <= vertexCount; ++vertexIndex)
{
ModelerAPI::Vertex vertex{};
body.GetVertex(convexPolygon.GetVertexIndex(vertexIndex), &vertex);
// TODO: change vertices array to hold Vertex instead of double values
vertices.push_back(vertex.x);
vertices.push_back(vertex.y);
vertices.push_back(vertex.z);
double alpha = material.GetTransparency();
ModelerAPI::Color color = material.GetSurfaceColor();
colors.push_back(ARGBToInt(alpha, color.red, color.green, color.blue));
faces.push_back(vertexIndex - 1);
}
elementBody->push_back(primitive::Mesh(std::move(vertices), std::move(faces), std::move(colors)));
}
}
}
}
m_data->m_cache.reset(elementBody);
return m_data->m_cache.get();
#endif
}
#ifdef ARCHICAD
/*--------------------------------------------------------------------
Get the (immutable) API element header data
return: The element header data (only use this data for low-level operations - for normal code, call getters/setters)
--------------------------------------------------------------------*/
const API_Elem_Head& Element::getHead() const {
return m_data->root->header;
} //Element::getHead
/*--------------------------------------------------------------------
Get the (mutable) API element header data
return: The element header data (only use this data for low-level operations - for normal code, call getters/setters)
--------------------------------------------------------------------*/
API_Elem_Head& Element::getHead() {
return m_data->root->header;
} //Element::getHead
#endif
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool Element::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
auto body = getBody();
inventory.merge(Inventory{
{
{ fieldID[bodyID], bodyID, element }, //TODO: implement other fields
},
}.withType(&typeid(Element)));
return base::fillInventory(inventory);
} //Element::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique Element::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(Element))
return base::getCargo(item);
using namespace active::serialise;
switch (item.index) {
case bodyID:
if (auto body = getBody(); body != nullptr)
{
return Cargo::Unique{ new active::serialise::ContainerWrap{ *body } };
}
else
return nullptr;
default:
return nullptr; //Requested an unknown index
}
} //Element::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void Element::setDefault() {
base::setDefault();
m_data.reset();
} //Element::setDefault
+133
View File
@@ -0,0 +1,133 @@
#ifndef SPECKLE_RECORD_ELEMENT
#define SPECKLE_RECORD_ELEMENT
#include "Speckle/Database/Content/BIMRecord.h"
#include "Speckle/Record/Attribute/Storey.h"
#include "Speckle/Utility/String.h"
namespace speckle::primitive {
class Mesh;
}
namespace speckle::record::element {
/*!
Base BIM element class
*/
class Element : public speckle::database::BIMRecord {
public:
///An element 3D body primitive
using Body = std::vector<primitive::Mesh>;
// MARK: - Types
using base = speckle::database::BIMRecord;
///Unique pointer
using Unique = std::unique_ptr<Element>;
///Shared pointer
using Shared = std::shared_ptr<Element>;
///Optional
using Option = std::optional<Element>;
// MARK: - Constructors
using base::base;
/*!
Default constructor
*/
Element();
#ifdef ARCHICAD
/*!
Constructor
@param elemData Archicad element data
@param tableID The element table ID (AC database, e.g. floor plan, 3D)
*/
Element(const API_Element& elemData, const speckle::utility::Guid& tableID);
#endif
/*!
Copy constructor
@param source The object to copy
*/
Element(const Element& source);
/*!
Destructor
*/
~Element();
/*!
Object cloning
@return A clone of this object
*/
Element* clonePtr() const override { return new Element{*this}; }
// MARK: - Functions (const)
/*!
Get the speckle type identifier
@return The speckle type (relevant objects should override as required)
*/
virtual speckle::utility::String getSpeckleType() const override { return "Objects.BuiltElements.Element:Objects.BuiltElements.Element"; }
/*!
Get the elmeent type name, e.g. "Wall", "Roof" etc
@return The type name
*/
virtual speckle::utility::String getTypeName() const;
/*!
Get the element storey
@return The element storey (nullopt if the element isn't linked to a storey)
*/
virtual attribute::Storey::Option getStorey() const;
/*!
Get the element body
@return An array of meshes from the element body (nullptr if no body data is available)
*/
virtual Body* getBody() const;
#ifdef ARCHICAD
/*!
Get the (immutable) API element header data
@return The element header data (only use this data for low-level operations - for normal code, call getters/setters)
*/
virtual const API_Elem_Head& getHead() const;
#endif
// MARK: - Functions (mutating)
#ifdef ARCHICAD
/*!
Get the (mutable) API element header data
@return The element header data (only use this data for low-level operations - for normal code, call getters/setters)
*/
virtual API_Elem_Head& getHead();
#endif
// MARK: - Serialisation
/*!
Fill an inventory with the package items
@param inventory The inventory to receive the package items
@return True if the package has added items to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
/*!
Set to the default package content
*/
void setDefault() override;
private:
class Data;
///The element data
std::unique_ptr<Data> m_data;
};
}
#endif //SPECKLE_RECORD_ELEMENT
@@ -0,0 +1,48 @@
#ifndef SPECKLE_SERIALISE_FINISH_COLLECTOR
#define SPECKLE_SERIALISE_FINISH_COLLECTOR
#include "Active/Serialise/Management/Manager.h"
#ifdef ARCHICAD
namespace ModelerAPI {
class Material;
}
#endif
namespace speckle::serialise {
/*!
Collector for object finishes
Used as a serialisation manager to collect finishes from serialised objects
*/
class FinishCollector : public active::serialise::Manager {
public:
/*!
Destructor
*/
virtual ~FinishCollector() {}
// MARK: - Functions (mutating)
/*!
Add a material proxy record to the collection
@param materialIndex The index of the material to add
@param objectID The object the material is applied to
@return True if the material proxy was added (false typically means the record already exists)
*/
virtual bool addMaterialProxy(const speckle::database::BIMIndex& materialIndex, const speckle::database::BIMRecordID& objectID) = 0;
#ifdef ARCHICAD
/*!
Add a ModelerAPI material to the collection (NB: These are not persistent so need to be captured by this method)
@param material A material
@param objectID The object the material is applied to
@return True if the material proxy was added (false typically means the record already exists)
*/
virtual bool addMaterialProxy(const ModelerAPI::Material& material, const speckle::database::BIMRecordID& objectID) = 0;
#endif
};
}
#endif //SPECKLE_SERIALISE_FINISH_COLLECTOR
@@ -0,0 +1,90 @@
#include "Speckle/Serialise/Detached/DetachedReference.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Speckle/Serialise/Detached/DetachmentManager.h"
#include "Speckle/Utility/String.h"
using namespace active::serialise;
using namespace speckle::serialise;
using namespace speckle::utility;
#include <array>
namespace {
///Serialisation fields
enum FieldIndex {
refdID,
speckTypeID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"referencedId"},
Identity{"speckle_type"},
};
///Type signature for a reference to a detached object
String referenceType{"reference"};
}
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool DetachedReference::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
inventory.merge(Inventory{
{
{ fieldID[refdID], refdID, element },
{ fieldID[speckTypeID], speckTypeID, element },
},
}.withType(&typeid(DetachedReference)));
return true;
} //DetachedReference::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique DetachedReference::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(DetachedReference))
return base::get().getCargo(item);
using namespace active::serialise;
switch (item.index) {
case refdID: {
//If we don't have an allocated string for receiving a reference (from 'setDefault') then we need to create one
if (!m_reference) {
//Ask a manager to send the detached data and provide a reference
auto detachmentManager = (management() == nullptr) ? nullptr : management()->get<DetachmentManager>();
if (detachmentManager == nullptr)
return nullptr; //TODO: Discuss if this is a serious error - possibly throwing an exception is warranted
m_reference = detachmentManager->send(std::forward<Package&&>(base::get()), item.identity());
if (!m_reference)
throw; //TODO: Throw a more descriptive exception
}
std::make_unique<StringWrap>(*m_reference);
}
case speckTypeID:
return std::make_unique<StringWrap>(m_type);
default:
return nullptr; //Requested an unknown index
}
} //DetachedReference::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void DetachedReference::setDefault() {
m_type.clear();
m_reference = String{};
} //DetachedReference::setDefault
@@ -0,0 +1,77 @@
#ifndef SPECKLE_SERIALISE_DETACHED_REFERENCE
#define SPECKLE_SERIALISE_DETACHED_REFERENCE
#include "Active/Serialise/Package/Package.h"
#include "Speckle/Serialise/Detached/DetachedWrap.h"
#include "Speckle/Utility/String.h"
namespace speckle::serialise {
/*!
Wrapper for references to a detached (serialised) object
An object holding a child object that should be serialised as a detached object should wrap the child in this package for (de)serialisation
*/
class DetachedReference : public active::serialise::Package, std::reference_wrapper<active::serialise::Package> {
public:
// MARK: - Types
///Item reference base
using base = std::reference_wrapper<active::serialise::Package>;
// MARK: - Constructors
/*!
Constructor
@param source The source package to wrap
*/
DetachedReference(Package& source) : base{source} {}
/*!
Constructor
@param source The source package to wrap
*/
DetachedReference(const active::serialise::Package& source) : base(const_cast<active::serialise::Package&>(source)) {}
DetachedReference(const DetachedReference& source) = delete;
/*!
Destructor
*/
~DetachedReference() override = default;
// MARK: - Functions (const)
/*!
Fill an inventory with the cargo items
@param inventory The inventory to receive the cargo items
@return True if items have been added to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
// MARK: - Functions (mutating)
/*!
Set to the default package content
*/
void setDefault() override;
/*!
Validate the cargo data
@return True if the data has been validated
*/
bool validate() override;
private:
///The reference value, i.e. a hash of the object content
mutable std::optional<database::RecordID> m_reference;
///The reference type
utility::String m_type;
};
}
#endif //SPECKLE_SERIALISE_DETACHED_REFERENCE
@@ -0,0 +1,92 @@
#include "Speckle/Serialise/Detached/DetachedWrap.h"
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Utility/BufferOut.h"
#include "Active/Utility/SHA256.h"
#include "Speckle/Utility/String.h"
using namespace active::serialise;
using namespace speckle::database;
using namespace speckle::serialise;
using namespace speckle::utility;
#include <array>
namespace {
///Serialisation fields
enum FieldIndex {
refdID,
};
///Serialisation field IDs
static std::array fieldID = {
Identity{"id"},
};
}
/*--------------------------------------------------------------------
Fill an inventory with the package items
inventory: The inventory to receive the package items
return: True if the package has added items to the inventory
--------------------------------------------------------------------*/
bool DetachedWrap::fillInventory(Inventory& inventory) const {
using enum Entry::Type;
if (!base::get().fillInventory(inventory))
return false;
inventory.merge(Inventory{
{
{ fieldID[refdID], refdID, element },
},
}.withType(&typeid(DetachedWrap)));
return true;
} //DetachedWrap::fillInventory
/*--------------------------------------------------------------------
Get the specified cargo
item: The inventory item to retrieve
return: The requested cargo (nullptr on failure)
--------------------------------------------------------------------*/
Cargo::Unique DetachedWrap::getCargo(const Inventory::Item& item) const {
if (item.ownerType != &typeid(DetachedWrap))
return base::get().getCargo(item);
using namespace active::serialise;
switch (item.index) {
case refdID: {
if (!m_reference) {
if (m_bufferOut == nullptr)
return nullptr; //TODO: Consider throwing an exception here
auto serialisedData = m_bufferOut->getOutput();
//Produce a hash from the serialised object. NB: We are currently using only the first 32 chars of the SHA256 hash
m_reference = (active::utility::SHA256() << serialisedData << String{"}"}).base64Hash().substr(0, 32);
}
return std::make_unique<ValueWrap<RecordID>>(*m_reference);
}
default:
return nullptr; //Requested an unknown index
}
} //DetachedWrap::getCargo
/*--------------------------------------------------------------------
Set to the default package content
--------------------------------------------------------------------*/
void DetachedWrap::setDefault() {
m_reference = String{};
} //DetachedWrap::setDefault
/*--------------------------------------------------------------------
Validate the cargo data
return: True if the data has been validated
--------------------------------------------------------------------*/
bool DetachedWrap::validate() {
return m_reference && base::get().validate();
} //DetachedWrap::validate
@@ -0,0 +1,89 @@
#ifndef SPECKLE_SERIALISE_DETACHED_WRAP
#define SPECKLE_SERIALISE_DETACHED_WRAP
#include "Active/Serialise/Package/Package.h"
#include "Speckle/Database/Identity/RecordID.h"
namespace active::utility {
class BufferOut;
}
namespace speckle::serialise {
/*!
Lightweight interface wrapper for a detached object
The wrapper generates a new reference ID for the object during serialisation, embedding it in the output
*/
class DetachedWrap : public active::serialise::Package, public std::reference_wrapper<active::serialise::Package> {
public:
// MARK: - Types
///Item reference base
using base = std::reference_wrapper<active::serialise::Package>;
// MARK: - Constructors
/*!
Constructor
@param source The source package to wrap
@param bufferOut The serialisation output buffer
*/
DetachedWrap(active::serialise::Package& source, active::utility::BufferOut& bufferOut) : base(source), m_bufferOut{&bufferOut} {}
/*!
Constructor
@param source The source package to wrap
@param bufferOut The serialisation output buffer
*/
DetachedWrap(const active::serialise::Package& source, active::utility::BufferOut& bufferOut) :
DetachedWrap{const_cast<active::serialise::Package&>(source), bufferOut} {}
/*!
Copy constructor
@param source The object to copy
*/
DetachedWrap(const DetachedWrap& source) : base(source), m_reference{source.m_reference} {}
// MARK: - Functions (const)
/*!
Get the detached object reference
@return The detached object reference (nullopt if the reference has not been determined yet - call after (de)serialisation)
*/
std::optional<database::RecordID> getReference() const { return m_reference; }
/*!
Fill an inventory with the cargo items
@param inventory The inventory to receive the cargo items
@return True if items have been added to the inventory
*/
bool fillInventory(active::serialise::Inventory& inventory) const override;
/*!
Get the specified cargo
@param item The inventory item to retrieve
@return The requested cargo (nullptr on failure)
*/
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
// MARK: - Functions (mutating)
/*!
Set to the default package content
*/
void setDefault() override;
/*!
Validate the cargo data
@return True if the data has been validated
*/
bool validate() override;
private:
///The detached record reference
mutable std::optional<database::RecordID> m_reference;
///The serialisation output buffer
active::utility::BufferOut* m_bufferOut;
};
}
#endif //SPECKLE_SERIALISE_DETACHED_WRAP
@@ -0,0 +1,89 @@
#include "Speckle/Serialise/Detached/DetachmentManager.h"
#include "Active/Utility/BufferOut.h"
#include "Speckle/Serialise/Detached/DetachedWrap.h"
#include "Speckle/Serialise/Detached/Storage/DetachedObjectStore.h"
using namespace active::serialise;
using namespace speckle::database;
using namespace speckle::serialise;
using namespace speckle::utility;
/*--------------------------------------------------------------------
Default constructor
--------------------------------------------------------------------*/
DetachmentManager::DetachmentManager() {
} //DetachmentManager::DetachmentManager
/*--------------------------------------------------------------------
Destructor
--------------------------------------------------------------------*/
DetachmentManager::~DetachmentManager() {
} //DetachmentManager::~DetachmentManager
/*--------------------------------------------------------------------
Send cargo as a detached object
package: The package to become a detached object
identity: The package identity (name, optional namespace)
return: The ID of the sent detached object
--------------------------------------------------------------------*/
std::optional<RecordID> DetachmentManager::send(Package&& package, const Identity& identity) const {
auto transport = m_transport.lock();
if (!transport)
throw; //TODO: Throw meaningful exception type
//Prepare the detached object data
String serialisedData;
active::utility::BufferOut buffer{serialisedData};
//The wrapper will manage the object serialisation and generate a unique reference based on the output
DetachedWrap wrapper{package, buffer};
transport->send(std::forward<Cargo&&>(wrapper), identity, serialisedData);
auto detachedReference = wrapper.getReference();
//If a reference is obtained, file/cache the object as required
if (detachedReference) {
m_store->file(*detachedReference, serialisedData);
if (m_cache)
m_cache->file(*detachedReference, serialisedData);
}
return detachedReference;
} //DetachmentManager::send
/*--------------------------------------------------------------------
Receive cargo from a detached object
id: The ID of the detached object to receive
package: The package to receive the detached object data
identity: The package identity (name, optional namespace)
return: True if the detached object was found and received
--------------------------------------------------------------------*/
bool DetachmentManager::receive(const database::RecordID& id, Package&& package, const Identity& identity) const {
return false; //TODO: Implement when we start receiving in Archicad
} //DetachmentManager::receive
/*--------------------------------------------------------------------
Set the manager primary storage
store: the primary storage (this is the long-term storage, e.g. a remote/cloud database)
--------------------------------------------------------------------*/
void DetachmentManager::setStore(std::unique_ptr<DetachedObjectStore> store) {
m_store = std::move(store);
} //DetachmentManager::setStore
/*--------------------------------------------------------------------
Set the manager storage cache
cache: the storage cache (this is intended to provide faster access than the primary storage for repeated detached objects)
--------------------------------------------------------------------*/
void DetachmentManager::setCache(std::unique_ptr<DetachedObjectStore> cache) {
m_cache = std::move(cache);
} //DetachmentManager::setCache
@@ -0,0 +1,82 @@
#ifndef SPECKLE_SERIALISE_DETACHMENT_MANAGER
#define SPECKLE_SERIALISE_DETACHMENT_MANAGER
#include "Active/Serialise/Management/Manager.h"
#include "Active/Serialise/Transport.h"
#include "Speckle/Database/Identity/RecordID.h"
namespace active::serialise {
class Package;
}
namespace speckle::serialise {
class DetachedObjectStore;
/*!
Manager for detached (serialised) objects
Pass this manager to the target transport for (de)serialisation supporting detached objects. Note that the manager is expected to know how
to send/receive detached objects, e.g. to a JS portal, remote server or local database (or some combo)
*/
class DetachmentManager : public virtual active::serialise::Manager {
public:
// MARK: - Types
///Base class
using base = active::serialise::Manager;
/*!
Default constructor
*/
DetachmentManager();
DetachmentManager(const DetachmentManager&) = delete;
/*!
Destructor
*/
~DetachmentManager();
// MARK: - Functions (const)
/*!
Send cargo as a detached object
@param package The package to become a detached object
@param identity The package identity (name, optional namespace)
@return The ID of the sent detached object
*/
std::optional<database::RecordID> send(active::serialise::Package&& package, const active::serialise::Identity& identity) const;
/*!
Receive cargo from a detached object
@param id The ID of the detached object to receive
@param package The package to receive the detached object data
@param identity The package identity (name, optional namespace)
@return True if the detached object was found and received
*/
bool receive(const database::RecordID& id, active::serialise::Package&& package, const active::serialise::Identity& identity) const;
// MARK: - Functions (mutating)
/*!
Set the manager primary storage
@param store the primary storage (this is the long-term storage, e.g. a remote/cloud database)
*/
void setStore(std::unique_ptr<DetachedObjectStore> store);
/*!
Set the manager storage cache
@param cache the storage cache (this is intended to provide faster access than the primary storage for repeated detached objects)
*/
void setCache(std::unique_ptr<DetachedObjectStore> cache);
private:
///The manager serialisation transport (NB - this is expected to be a shared resource, so the manager does not own it)
std::weak_ptr<active::serialise::Transport> m_transport;
///The primary store for sending/retrieving detached objects
std::unique_ptr<DetachedObjectStore> m_store;
///A cache for detached objects - can be used as a local store to save
std::unique_ptr<DetachedObjectStore> m_cache;
};
}
#endif //SPECKLE_SERIALISE_DETACHMENT_MANAGER
@@ -0,0 +1,52 @@
#ifndef SPECKLE_SERIALISE_DETACHED_MEMORY_STORE
#define SPECKLE_SERIALISE_DETACHED_MEMORY_STORE
#include "Speckle/Serialise/Detached/Storage/DetachedObjectStore.h"
#include <unordered_map>
namespace speckle::serialise {
/*!
Memory-based storage for detached objects
Detached object serialised data is held in a simple unordered_map keying the data against the object reference.
This class primarily intended for collecting the JSON from detached objects and holding until they can be forwarded to the server. The data
will not persist beyond this usage.
*/
class DetachedMemoryStore : public DetachedObjectStore, public std::unordered_map<database::RecordID, utility::String> {
public:
// MARK: - Types
using base = std::unordered_map<database::RecordID, utility::String>;
// MARK: - Functions (const)
/*!
Retrieve a detached object from storage
@param reference The required object reference
@return The object data (nullopt if the object cannot be found in storage)
*/
utility::String::Option retrieve(const database::RecordID& reference) const override {
if (auto iter = base::find(reference); iter != base::end())
return iter->second;
return std::nullopt;
}
// MARK: - Functions (mutating)
/*!
File a detached object in storage
@param reference The object reference (typically a hash generated from the object data)
@param data The object data (currently expected to be serialised as JSON)
@return True if the object was filed (typically ignored if it duplicates an object already in the store)
*/
bool file(const database::RecordID& reference, const utility::String& data) override {
return base::insert(std::make_pair(reference, data)).second;
}
};
}
#endif //SPECKLE_SERIALISE_DETACHED_MEMORY_STORE
@@ -0,0 +1,46 @@
#ifndef SPECKLE_SERIALISE_DETACHED_OBJECT_STORE
#define SPECKLE_SERIALISE_DETACHED_OBJECT_STORE
#include "Speckle/Database/Identity/RecordID.h"
#include "Speckle/Utility/String.h"
namespace speckle::serialise {
/*!
Interface for objects that store/cache/send/receive detached objects
It is currently assumed that objects will be serialised and can be held in a string. This can be revisited in future if binary data is required.
*/
class DetachedObjectStore {
public:
// MARK: Constructors
/*!
Destructor
*/
virtual ~DetachedObjectStore() {}
// MARK: - Functions (const)
/*!
Retrieve a detached object from storage
@param reference The required object reference
@return The object data (nullopt if the object cannot be found in storage)
*/
virtual utility::String::Option retrieve(const database::RecordID& reference) const = 0;
// MARK: - Functions (mutating)
/*!
File a detached object in storage
@param reference The object reference (typically a hash generated from the object data)
@param data The object data (currently expected to be serialised as JSON)
@return True if the object was filed (typically rejected if it duplicates an object already in the store)
*/
virtual bool file(const database::RecordID& reference, const utility::String& data) = 0;
};
}
#endif //SPECKLE_SERIALISE_DETACHED_OBJECT_STORE
@@ -0,0 +1,55 @@
#include "Speckle/Serialise/Units/LengthUnit.h"
#include <algorithm>
#include <map>
using namespace active::measure;
using namespace active::utility;
using enum LengthType;
namespace {
//All recognised encoding types
std::map<LengthType, String> lengthNames = {
{ millimetre, "mm" },
{ centimetre, "cm" },
{ metre, "m" },
{ kilometre, "km" },
{ inch, "in" },
{ foot, "ft" },
{ yard, "yd" },
{ mile, "ml" },
};
} // namespace
/*--------------------------------------------------------------------
Convert a length unit name to a type
name: The length unit name
return: The length unit type (nullopt if no match found)
--------------------------------------------------------------------*/
std::optional<LengthType> speckle::serialise::lengthUnitFromName(const String& name) {
if (auto match = std::find_if(lengthNames.begin(), lengthNames.end(), [&](const auto& i){ return (i.second == name); });
match != lengthNames.end()) {
return match->first;
}
return std::nullopt;
} //encodingFromName
/*--------------------------------------------------------------------
Convert a length unit type to a name
lengthType: The length unit type
return: The name of the length unit type (nullopt if no match found)
--------------------------------------------------------------------*/
std::optional<String> speckle::serialise::nameFromLengthUnit(LengthType lengthType) {
if (auto match = lengthNames.find(lengthType); match != lengthNames.end()) {
return match->second;
}
return std::nullopt;
} //nameFromEncoding
@@ -0,0 +1,107 @@
#ifndef SPECKLE_SERIALISE_LENGTH_UNIT
#define SPECKLE_SERIALISE_LENGTH_UNIT
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
#include "Active/Serialise/Item/Wrapper/ValueOptionWrap.h"
#include "Active/Setting/Values/Measurement/Units/LengthUnit.h"
namespace speckle::serialise {
/*!
Convert a length unit name to a type
@param name The length unit name
@return The length unit type (nullopt if no match found)
*/
std::optional<active::measure::LengthType> lengthUnitFromName(const active::utility::String& name);
/*!
Convert a length unit type to a name
@param lengthType The length unit type
@return The name of the length unit type (nullopt if no match found)
*/
std::optional<active::utility::String> nameFromLengthUnit(active::measure::LengthType lengthType);
}
namespace active::serialise {
// MARK: - Specialisations for length types
/*!
Read a length type value from the specified string
@param source The string to read
@return True if the data was successfully read
*/
inline std::pair<active::measure::LengthType, bool> readLengthTypeRefValue(const utility::String& source) {
using enum active::measure::LengthType;
if (auto converted = speckle::serialise::lengthUnitFromName(source); converted)
return {*converted, true};
return {metre, false};
} //ValueWrap<active::measure::LengthType>::read
/*!
Import the object from the specified string (specialisation for length type)
@param source The string to read
@return True if the data was successfully read
*/
template<> inline
bool ValueWrap<active::measure::LengthType>::read(const utility::String& source) {
auto result = readLengthTypeRefValue(source);
if (result.second)
base::get() = result.first;
return result.second;
} //ValueWrap<active::measure::LengthType>::read
/*!
Import the object from the specified string (specialisation for length type)
@param source The string to read
@return True if the data was successfully read
*/
template<> inline
bool ValueOptionWrap<active::measure::LengthType>::read(const utility::String& source) {
auto result = readLengthTypeRefValue(source);
if (result.second)
base::get() = result.first;
return result.second;
} //ValueWrap<active::measure::LengthType>::read
/*!
Export the object to the specified string (specialisation for length type)
@param dest The string to write the data to
@return True if the data was successfully written
*/
template<> inline
bool ValueWrap<active::measure::LengthType>::write(utility::String& dest) const {
if (auto name = speckle::serialise::nameFromLengthUnit(base::get()); name) {
dest = *name;
return true;
}
return false;
} //ValueWrap<active::measure::LengthType>::write
/*!
Export the object to the specified string (specialisation for length type)
@param dest The string to write the data to
@return True if the data was successfully written
*/
template<> inline
bool ValueOptionWrap<active::measure::LengthType>::write(utility::String& dest) const {
if (!base::get())
return false;
if (auto name = speckle::serialise::nameFromLengthUnit(*base::get()); name) {
dest = *name;
return true;
}
return false;
} //ValueOptionWrap<active::measure::LengthType>::write
}
#endif //SPECKLE_SERIALISE_LENGTH_UNIT
+1
View File
@@ -14,6 +14,7 @@ enum SpeckleStringResource {
//Title strings (UI title/label for dialogs, controls, menu items etc)
enum SpeckleTitleString {
untitledProjectID = 1,
unknownElementTypeID,
};
+222 -4
View File
@@ -18,11 +18,41 @@
215F08552C99DA8D00CD343B /* Project.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 215F08512C99DA8D00CD343B /* Project.cpp */; };
215F08562C99DA8D00CD343B /* Project.h in Headers */ = {isa = PBXBuildFile; fileRef = 215F08542C99DA8D00CD343B /* Project.h */; };
215F08662C9B006800CD343B /* ProjectEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 215F08652C9B006700CD343B /* ProjectEvent.cpp */; };
215F087D2CA18E1400CD343B /* Element.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 215F08782CA18E1400CD343B /* Element.cpp */; };
215F087E2CA18E1400CD343B /* Element.h in Headers */ = {isa = PBXBuildFile; fileRef = 215F08792CA18E1400CD343B /* Element.h */; };
215F088B2CA195EC00CD343B /* ArchicadDBaseCore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 215F08872CA195EC00CD343B /* ArchicadDBaseCore.cpp */; };
215F088C2CA195EC00CD343B /* ArchicadDBaseCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 215F08882CA195EC00CD343B /* ArchicadDBaseCore.h */; };
215F088D2CA195EC00CD343B /* ArchicadElementDBaseEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 215F08892CA195EC00CD343B /* ArchicadElementDBaseEngine.h */; };
215F08952CA19AF800CD343B /* BIMElementDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 215F08932CA19AF800CD343B /* BIMElementDatabase.cpp */; };
215F08962CA19AF800CD343B /* BIMElementDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 215F08942CA19AF800CD343B /* BIMElementDatabase.h */; };
219245FE2CA2CC4300CF5703 /* BIMRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219245FA2CA2CC4300CF5703 /* BIMRecord.cpp */; };
219245FF2CA2CC4300CF5703 /* BIMRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 219245FD2CA2CC4300CF5703 /* BIMRecord.h */; };
219246032CA2CE2700CF5703 /* BIMLink.h in Headers */ = {isa = PBXBuildFile; fileRef = 219246012CA2CE2700CF5703 /* BIMLink.h */; };
219246042CA2CE2700CF5703 /* BIMLink.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219246022CA2CE2700CF5703 /* BIMLink.cpp */; };
219246082CA2ED2F00CF5703 /* ArchicadElementDBaseEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219246072CA2ED2F00CF5703 /* ArchicadElementDBaseEngine.cpp */; };
219246122CA34DCE00CF5703 /* Mesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2192460E2CA34DCE00CF5703 /* Mesh.cpp */; };
219246132CA34DCE00CF5703 /* Mesh.h in Headers */ = {isa = PBXBuildFile; fileRef = 2192460F2CA34DCE00CF5703 /* Mesh.h */; };
2193517B2C624FC100E5A69C /* MenuSubscriber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219351782C624FC100E5A69C /* MenuSubscriber.cpp */; };
2193519B2C6278D900E5A69C /* SelectionSubscriber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219351992C6278D900E5A69C /* SelectionSubscriber.cpp */; };
219351B12C62CC1A00E5A69C /* Guid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219351AC2C62CC1A00E5A69C /* Guid.cpp */; };
219351B32C62CC1A00E5A69C /* String.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 219351AE2C62CC1A00E5A69C /* String.cpp */; };
2196F2E32CB05BAF00450DFC /* LengthUnit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2196F2E22CB05BAF00450DFC /* LengthUnit.cpp */; };
2196F2EB2CB4816B00450DFC /* ArchicadAttributeDBaseEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2196F2E82CB4816B00450DFC /* ArchicadAttributeDBaseEngine.cpp */; };
2196F2EC2CB4816B00450DFC /* ArchicadAttributeDBaseEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 2196F2E92CB4816B00450DFC /* ArchicadAttributeDBaseEngine.h */; };
2196F2F02CB4823C00450DFC /* Attribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2196F2ED2CB4823C00450DFC /* Attribute.cpp */; };
2196F2F12CB4823C00450DFC /* Attribute.h in Headers */ = {isa = PBXBuildFile; fileRef = 2196F2EE2CB4823C00450DFC /* Attribute.h */; };
2196F2F42CB483D600450DFC /* Finish.h in Headers */ = {isa = PBXBuildFile; fileRef = 2196F2F22CB483D600450DFC /* Finish.h */; };
2196F2F52CB483D600450DFC /* Finish.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2196F2F32CB483D600450DFC /* Finish.cpp */; };
2196F2F82CB51ED400450DFC /* BIMAttributeDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2196F2F62CB51ED400450DFC /* BIMAttributeDatabase.cpp */; };
2196F2F92CB51ED400450DFC /* BIMAttributeDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 2196F2F72CB51ED400450DFC /* BIMAttributeDatabase.h */; };
2196F3042CB57E8000450DFC /* Storey.h in Headers */ = {isa = PBXBuildFile; fileRef = 2196F3022CB57E7F00450DFC /* Storey.h */; };
2196F3052CB57E8000450DFC /* Storey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2196F3032CB57E7F00450DFC /* Storey.cpp */; };
2199881E2BD833830035E5EA /* libArchicad27.a in CopyFiles */ = {isa = PBXBuildFile; fileRef = 21379E082AE47A6400A1584C /* libArchicad27.a */; };
21A0FBA42CB880690023F24E /* FinishCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = 21A0FB9F2CB880690023F24E /* FinishCollector.h */; };
21AEF9BA2CA606B5000B8681 /* DetachedReference.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9B92CA606B4000B8681 /* DetachedReference.cpp */; };
21AEF9BC2CA6DF84000B8681 /* DetachmentManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9BB2CA6DF84000B8681 /* DetachmentManager.cpp */; };
21AEF9BE2CA6FDA4000B8681 /* DetachedWrap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21AEF9BD2CA6FDA4000B8681 /* DetachedWrap.cpp */; };
21AEF9DD2CAAA4EA000B8681 /* DetachedObjectStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 21AEF9DB2CAAA4EA000B8681 /* DetachedObjectStore.h */; };
21B67D002C7CE15100FD64FC /* Exception.h in Headers */ = {isa = PBXBuildFile; fileRef = 21B67CFE2C7CE15100FD64FC /* Exception.h */; };
21B67D0D2C7E0E8D00FD64FC /* ErrorReport.h in Headers */ = {isa = PBXBuildFile; fileRef = 21B67D092C7E0E8D00FD64FC /* ErrorReport.h */; };
21B67D0E2C7E0E8D00FD64FC /* ErrorReport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21B67D0C2C7E0E8D00FD64FC /* ErrorReport.cpp */; };
@@ -31,7 +61,6 @@
21D0BD2B2C86FC350077E104 /* Record.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD252C86FC350077E104 /* Record.cpp */; };
21D0BD2C2C86FC350077E104 /* Record.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BD262C86FC350077E104 /* Record.h */; };
21D0BD312C86FE090077E104 /* Index.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BD2D2C86FE090077E104 /* Index.h */; };
21D0BD322C86FE090077E104 /* Link.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD2E2C86FE090077E104 /* Link.cpp */; };
21D0BD332C86FE090077E104 /* Link.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BD2F2C86FE090077E104 /* Link.h */; };
21D0BD4D2C8901A00077E104 /* ServerInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 21D0BD4B2C8901A00077E104 /* ServerInfo.h */; };
21D0BD4E2C8901A00077E104 /* ServerInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 21D0BD4C2C8901A00077E104 /* ServerInfo.cpp */; };
@@ -114,10 +143,26 @@
215F085B2C9AE23200CD343B /* SpeckleResource.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SpeckleResource.h; sourceTree = "<group>"; };
215F08622C9AE3D200CD343B /* Speckle.grc */ = {isa = PBXFileReference; lastKnownFileType = text; path = Speckle.grc; sourceTree = "<group>"; };
215F08652C9B006700CD343B /* ProjectEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProjectEvent.cpp; sourceTree = "<group>"; };
215F08782CA18E1400CD343B /* Element.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Element.cpp; sourceTree = "<group>"; };
215F08792CA18E1400CD343B /* Element.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Element.h; sourceTree = "<group>"; };
215F08872CA195EC00CD343B /* ArchicadDBaseCore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArchicadDBaseCore.cpp; sourceTree = "<group>"; };
215F08882CA195EC00CD343B /* ArchicadDBaseCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArchicadDBaseCore.h; sourceTree = "<group>"; };
215F08892CA195EC00CD343B /* ArchicadElementDBaseEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArchicadElementDBaseEngine.h; sourceTree = "<group>"; };
215F08932CA19AF800CD343B /* BIMElementDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BIMElementDatabase.cpp; sourceTree = "<group>"; };
215F08942CA19AF800CD343B /* BIMElementDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BIMElementDatabase.h; sourceTree = "<group>"; };
2167E2782C4911E2000827D3 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
2167E2792C4911EB000827D3 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
2167E27C2C49121F000827D3 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
218953A32C0C9CB00078F182 /* Version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Version.h; sourceTree = "<group>"; };
219245FA2CA2CC4300CF5703 /* BIMRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BIMRecord.cpp; sourceTree = "<group>"; };
219245FD2CA2CC4300CF5703 /* BIMRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BIMRecord.h; sourceTree = "<group>"; };
219246002CA2CCD700CF5703 /* BIMRecordID.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BIMRecordID.h; sourceTree = "<group>"; };
219246012CA2CE2700CF5703 /* BIMLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BIMLink.h; sourceTree = "<group>"; };
219246022CA2CE2700CF5703 /* BIMLink.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BIMLink.cpp; sourceTree = "<group>"; };
219246052CA2CFF000CF5703 /* BIMIndex.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BIMIndex.h; sourceTree = "<group>"; };
219246072CA2ED2F00CF5703 /* ArchicadElementDBaseEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArchicadElementDBaseEngine.cpp; sourceTree = "<group>"; };
2192460E2CA34DCE00CF5703 /* Mesh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Mesh.cpp; sourceTree = "<group>"; };
2192460F2CA34DCE00CF5703 /* Mesh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Mesh.h; sourceTree = "<group>"; };
2193516A2C62318B00E5A69C /* ActiveLib.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = ActiveLib.xcodeproj; path = ../../ActiveLib/ActiveLib.xcodeproj; sourceTree = "<group>"; };
219351782C624FC100E5A69C /* MenuSubscriber.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MenuSubscriber.cpp; sourceTree = "<group>"; };
219351792C624FC100E5A69C /* MenuSubscriber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MenuSubscriber.h; sourceTree = "<group>"; };
@@ -129,7 +174,28 @@
219351AD2C62CC1A00E5A69C /* Guid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Guid.h; sourceTree = "<group>"; };
219351AE2C62CC1A00E5A69C /* String.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = String.cpp; sourceTree = "<group>"; };
219351AF2C62CC1A00E5A69C /* String.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = String.h; sourceTree = "<group>"; };
2196F2DE2CB0566500450DFC /* LengthUnit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LengthUnit.h; sourceTree = "<group>"; };
2196F2E22CB05BAF00450DFC /* LengthUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LengthUnit.cpp; sourceTree = "<group>"; };
2196F2E82CB4816B00450DFC /* ArchicadAttributeDBaseEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArchicadAttributeDBaseEngine.cpp; sourceTree = "<group>"; };
2196F2E92CB4816B00450DFC /* ArchicadAttributeDBaseEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArchicadAttributeDBaseEngine.h; sourceTree = "<group>"; };
2196F2ED2CB4823C00450DFC /* Attribute.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Attribute.cpp; sourceTree = "<group>"; };
2196F2EE2CB4823C00450DFC /* Attribute.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Attribute.h; sourceTree = "<group>"; };
2196F2F22CB483D600450DFC /* Finish.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Finish.h; sourceTree = "<group>"; };
2196F2F32CB483D600450DFC /* Finish.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Finish.cpp; sourceTree = "<group>"; };
2196F2F62CB51ED400450DFC /* BIMAttributeDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BIMAttributeDatabase.cpp; sourceTree = "<group>"; };
2196F2F72CB51ED400450DFC /* BIMAttributeDatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BIMAttributeDatabase.h; sourceTree = "<group>"; };
2196F3022CB57E7F00450DFC /* Storey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Storey.h; sourceTree = "<group>"; };
2196F3032CB57E7F00450DFC /* Storey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Storey.cpp; sourceTree = "<group>"; };
219712682BE7E2D500D9EF7E /* Serialisation.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = Serialisation.md; sourceTree = "<group>"; };
21A0FB9F2CB880690023F24E /* FinishCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FinishCollector.h; sourceTree = "<group>"; };
21AEF9B32CA5F7CF000B8681 /* DetachedWrap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachedWrap.h; sourceTree = "<group>"; };
21AEF9B52CA5FA02000B8681 /* DetachedReference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachedReference.h; sourceTree = "<group>"; };
21AEF9B72CA5FCB6000B8681 /* DetachmentManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachmentManager.h; sourceTree = "<group>"; };
21AEF9B92CA606B4000B8681 /* DetachedReference.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DetachedReference.cpp; sourceTree = "<group>"; };
21AEF9BB2CA6DF84000B8681 /* DetachmentManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DetachmentManager.cpp; sourceTree = "<group>"; };
21AEF9BD2CA6FDA4000B8681 /* DetachedWrap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DetachedWrap.cpp; sourceTree = "<group>"; };
21AEF9DB2CAAA4EA000B8681 /* DetachedObjectStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachedObjectStore.h; sourceTree = "<group>"; };
21AEF9DF2CAAC2AF000B8681 /* DetachedMemoryStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetachedMemoryStore.h; sourceTree = "<group>"; };
21B67CFE2C7CE15100FD64FC /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = "<group>"; };
21B67D092C7E0E8D00FD64FC /* ErrorReport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErrorReport.h; sourceTree = "<group>"; };
21B67D0C2C7E0E8D00FD64FC /* ErrorReport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErrorReport.cpp; sourceTree = "<group>"; };
@@ -138,7 +204,6 @@
21D0BD252C86FC350077E104 /* Record.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Record.cpp; sourceTree = "<group>"; };
21D0BD262C86FC350077E104 /* Record.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Record.h; sourceTree = "<group>"; };
21D0BD2D2C86FE090077E104 /* Index.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Index.h; sourceTree = "<group>"; };
21D0BD2E2C86FE090077E104 /* Link.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Link.cpp; sourceTree = "<group>"; };
21D0BD2F2C86FE090077E104 /* Link.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Link.h; sourceTree = "<group>"; };
21D0BD4B2C8901A00077E104 /* ServerInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServerInfo.h; sourceTree = "<group>"; };
21D0BD4C2C8901A00077E104 /* ServerInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ServerInfo.cpp; sourceTree = "<group>"; };
@@ -213,6 +278,7 @@
21F93AE82B2F406D009A2C5B /* Environment */,
21F93ACC2B2B67FC009A2C5B /* Event */,
21F69F1B2C6A0FE2008B6A06 /* Interface */,
219246112CA34DCE00CF5703 /* Primitive */,
21F69F952C71087A008B6A06 /* Record */,
212A834E2AE47AD9001EAFE7 /* Serialise */,
215F085B2C9AE23200CD343B /* SpeckleResource.h */,
@@ -226,7 +292,10 @@
isa = PBXGroup;
children = (
2167E27C2C49121F000827D3 /* CMakeLists.txt */,
21A0FBA02CB880690023F24E /* Collection */,
21AEF9C72CA818EA000B8681 /* Detached */,
21F69F3A2C6B880B008B6A06 /* JSBase */,
2196F2DF2CB0566500450DFC /* Units */,
219712682BE7E2D500D9EF7E /* Serialisation.md */,
);
path = Serialise;
@@ -263,6 +332,26 @@
path = RINT;
sourceTree = SOURCE_ROOT;
};
215F087A2CA18E1400CD343B /* Element */ = {
isa = PBXGroup;
children = (
215F08782CA18E1400CD343B /* Element.cpp */,
215F08792CA18E1400CD343B /* Element.h */,
);
path = Element;
sourceTree = "<group>";
};
215F088A2CA195EC00CD343B /* ArchicadDBase */ = {
isa = PBXGroup;
children = (
215F08872CA195EC00CD343B /* ArchicadDBaseCore.cpp */,
215F08882CA195EC00CD343B /* ArchicadDBaseCore.h */,
2196F2EA2CB4816B00450DFC /* Attribute */,
219246062CA2D22D00CF5703 /* Element */,
);
path = ArchicadDBase;
sourceTree = "<group>";
};
218953A92C0F29FB0078F182 /* EventTests */ = {
isa = PBXGroup;
children = (
@@ -270,6 +359,32 @@
name = EventTests;
sourceTree = "<group>";
};
219246062CA2D22D00CF5703 /* Element */ = {
isa = PBXGroup;
children = (
219246072CA2ED2F00CF5703 /* ArchicadElementDBaseEngine.cpp */,
215F08892CA195EC00CD343B /* ArchicadElementDBaseEngine.h */,
);
path = Element;
sourceTree = "<group>";
};
219246102CA34DCE00CF5703 /* Mesh */ = {
isa = PBXGroup;
children = (
2192460E2CA34DCE00CF5703 /* Mesh.cpp */,
2192460F2CA34DCE00CF5703 /* Mesh.h */,
);
path = Mesh;
sourceTree = "<group>";
};
219246112CA34DCE00CF5703 /* Primitive */ = {
isa = PBXGroup;
children = (
219246102CA34DCE00CF5703 /* Mesh */,
);
path = Primitive;
sourceTree = "<group>";
};
2193516B2C62318B00E5A69C /* Products */ = {
isa = PBXGroup;
children = (
@@ -320,6 +435,37 @@
path = Utility;
sourceTree = "<group>";
};
2196F2DF2CB0566500450DFC /* Units */ = {
isa = PBXGroup;
children = (
2196F2E22CB05BAF00450DFC /* LengthUnit.cpp */,
2196F2DE2CB0566500450DFC /* LengthUnit.h */,
);
path = Units;
sourceTree = "<group>";
};
2196F2EA2CB4816B00450DFC /* Attribute */ = {
isa = PBXGroup;
children = (
2196F2E82CB4816B00450DFC /* ArchicadAttributeDBaseEngine.cpp */,
2196F2E92CB4816B00450DFC /* ArchicadAttributeDBaseEngine.h */,
);
path = Attribute;
sourceTree = "<group>";
};
2196F2EF2CB4823C00450DFC /* Attribute */ = {
isa = PBXGroup;
children = (
2196F2ED2CB4823C00450DFC /* Attribute.cpp */,
2196F2EE2CB4823C00450DFC /* Attribute.h */,
2196F2F32CB483D600450DFC /* Finish.cpp */,
2196F2F22CB483D600450DFC /* Finish.h */,
2196F3032CB57E7F00450DFC /* Storey.cpp */,
2196F3022CB57E7F00450DFC /* Storey.h */,
);
path = Attribute;
sourceTree = "<group>";
};
219987FA2BD708BC0035E5EA /* SpeckleLibDoctest */ = {
isa = PBXGroup;
children = (
@@ -329,11 +475,46 @@
path = SpeckleLibDoctest;
sourceTree = "<group>";
};
21A0FBA02CB880690023F24E /* Collection */ = {
isa = PBXGroup;
children = (
21A0FB9F2CB880690023F24E /* FinishCollector.h */,
);
path = Collection;
sourceTree = "<group>";
};
21AEF9C72CA818EA000B8681 /* Detached */ = {
isa = PBXGroup;
children = (
21AEF9B92CA606B4000B8681 /* DetachedReference.cpp */,
21AEF9B52CA5FA02000B8681 /* DetachedReference.h */,
21AEF9BD2CA6FDA4000B8681 /* DetachedWrap.cpp */,
21AEF9B32CA5F7CF000B8681 /* DetachedWrap.h */,
21AEF9BB2CA6DF84000B8681 /* DetachmentManager.cpp */,
21AEF9B72CA5FCB6000B8681 /* DetachmentManager.h */,
21AEF9DE2CAAA78A000B8681 /* Storage */,
);
path = Detached;
sourceTree = "<group>";
};
21AEF9DE2CAAA78A000B8681 /* Storage */ = {
isa = PBXGroup;
children = (
21AEF9DB2CAAA4EA000B8681 /* DetachedObjectStore.h */,
21AEF9DF2CAAC2AF000B8681 /* DetachedMemoryStore.h */,
);
path = Storage;
sourceTree = "<group>";
};
21D0BD1F2C86F0280077E104 /* Database */ = {
isa = PBXGroup;
children = (
21D0BD1D2C86F0280077E104 /* AccountDatabase.cpp */,
21D0BD1E2C86F0280077E104 /* AccountDatabase.h */,
2196F2F62CB51ED400450DFC /* BIMAttributeDatabase.cpp */,
2196F2F72CB51ED400450DFC /* BIMAttributeDatabase.h */,
215F08932CA19AF800CD343B /* BIMElementDatabase.cpp */,
215F08942CA19AF800CD343B /* BIMElementDatabase.h */,
21D0BD272C86FC350077E104 /* Content */,
21D0BD302C86FE090077E104 /* Identity */,
21D0BDB02C8F8AB60077E104 /* Storage */,
@@ -344,6 +525,8 @@
21D0BD272C86FC350077E104 /* Content */ = {
isa = PBXGroup;
children = (
219245FA2CA2CC4300CF5703 /* BIMRecord.cpp */,
219245FD2CA2CC4300CF5703 /* BIMRecord.h */,
21D0BD252C86FC350077E104 /* Record.cpp */,
21D0BD262C86FC350077E104 /* Record.h */,
);
@@ -353,8 +536,11 @@
21D0BD302C86FE090077E104 /* Identity */ = {
isa = PBXGroup;
children = (
219246052CA2CFF000CF5703 /* BIMIndex.h */,
219246022CA2CE2700CF5703 /* BIMLink.cpp */,
219246012CA2CE2700CF5703 /* BIMLink.h */,
219246002CA2CCD700CF5703 /* BIMRecordID.h */,
21D0BD2D2C86FE090077E104 /* Index.h */,
21D0BD2E2C86FE090077E104 /* Link.cpp */,
21D0BD2F2C86FE090077E104 /* Link.h */,
21D0BDE42C943D3F0077E104 /* RecordID.h */,
);
@@ -374,6 +560,7 @@
21D0BDB02C8F8AB60077E104 /* Storage */ = {
isa = PBXGroup;
children = (
215F088A2CA195EC00CD343B /* ArchicadDBase */,
21D0BDAF2C8F8AB60077E104 /* DocumentStore */,
);
path = Storage;
@@ -462,6 +649,8 @@
21F69F952C71087A008B6A06 /* Record */ = {
isa = PBXGroup;
children = (
2196F2EF2CB4823C00450DFC /* Attribute */,
215F087A2CA18E1400CD343B /* Element */,
21F69F942C71087A008B6A06 /* Credentials */,
);
path = Record;
@@ -500,23 +689,37 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
215F088C2CA195EC00CD343B /* ArchicadDBaseCore.h in Headers */,
21D0BDE72C943D3F0077E104 /* RecordID.h in Headers */,
21D0BD212C86F0280077E104 /* AccountDatabase.h in Headers */,
210CC86F2C7E879700610F58 /* ArgumentBase.h in Headers */,
210CC8A02C81E34400610F58 /* Platform.h in Headers */,
219246132CA34DCE00CF5703 /* Mesh.h in Headers */,
219246032CA2CE2700CF5703 /* BIMLink.h in Headers */,
21B67D0D2C7E0E8D00FD64FC /* ErrorReport.h in Headers */,
215F08962CA19AF800CD343B /* BIMElementDatabase.h in Headers */,
2196F2F12CB4823C00450DFC /* Attribute.h in Headers */,
21D0BD332C86FE090077E104 /* Link.h in Headers */,
21D0BD5A2C8910400077E104 /* UserInfo.h in Headers */,
21D0BD562C890B1C0077E104 /* ServerMigration.h in Headers */,
210CC88F2C81A98500610F58 /* Guid64.h in Headers */,
21AEF9DD2CAAA4EA000B8681 /* DetachedObjectStore.h in Headers */,
21A0FBA42CB880690023F24E /* FinishCollector.h in Headers */,
215F088D2CA195EC00CD343B /* ArchicadElementDBaseEngine.h in Headers */,
2196F2F42CB483D600450DFC /* Finish.h in Headers */,
21B67D002C7CE15100FD64FC /* Exception.h in Headers */,
21D0BD2C2C86FC350077E104 /* Record.h in Headers */,
21D0BDB42C8F8AB60077E104 /* DocumentStoreCore.h in Headers */,
215F087E2CA18E1400CD343B /* Element.h in Headers */,
2196F2F92CB51ED400450DFC /* BIMAttributeDatabase.h in Headers */,
215F08562C99DA8D00CD343B /* Project.h in Headers */,
219245FF2CA2CC4300CF5703 /* BIMRecord.h in Headers */,
210CC8802C80CD2A00610F58 /* BridgeChild.h in Headers */,
21D0BD4D2C8901A00077E104 /* ServerInfo.h in Headers */,
2196F3042CB57E8000450DFC /* Storey.h in Headers */,
21D0BDB52C8F8AB60077E104 /* DocumentStoreEngine.h in Headers */,
21D0BDC52C9241940077E104 /* ProjectSubscriber.h in Headers */,
2196F2EC2CB4816B00450DFC /* ArchicadAttributeDBaseEngine.h in Headers */,
21D0BD312C86FE090077E104 /* Index.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -646,29 +849,44 @@
21F69FA62C733EDA008B6A06 /* BridgeArgument.cpp in Sources */,
21F69F682C6DFB01008B6A06 /* RunMethod.cpp in Sources */,
21F69F812C6FF3B0008B6A06 /* BridgeArgumentWrap.cpp in Sources */,
215F088B2CA195EC00CD343B /* ArchicadDBaseCore.cpp in Sources */,
2193517B2C624FC100E5A69C /* MenuSubscriber.cpp in Sources */,
2196F2F02CB4823C00450DFC /* Attribute.cpp in Sources */,
21F69F612C6D0286008B6A06 /* GetBindingsMethodNames.cpp in Sources */,
215F08662C9B006800CD343B /* ProjectEvent.cpp in Sources */,
21D0BDBD2C90F2830077E104 /* DocStoreSubscriber.cpp in Sources */,
21D0BDB32C8F8AB60077E104 /* DocumentStoreCore.cpp in Sources */,
219246082CA2ED2F00CF5703 /* ArchicadElementDBaseEngine.cpp in Sources */,
2196F2E32CB05BAF00450DFC /* LengthUnit.cpp in Sources */,
21F93AEC2B2F406E009A2C5B /* Addon.cpp in Sources */,
215F087D2CA18E1400CD343B /* Element.cpp in Sources */,
2196F2F82CB51ED400450DFC /* BIMAttributeDatabase.cpp in Sources */,
21D0BD4E2C8901A00077E104 /* ServerInfo.cpp in Sources */,
21B67D0E2C7E0E8D00FD64FC /* ErrorReport.cpp in Sources */,
21F69F7E2C6FD9FC008B6A06 /* GetCallResult.cpp in Sources */,
2196F3052CB57E8000450DFC /* Storey.cpp in Sources */,
219245FE2CA2CC4300CF5703 /* BIMRecord.cpp in Sources */,
21AEF9BE2CA6FDA4000B8681 /* DetachedWrap.cpp in Sources */,
2196F2F52CB483D600450DFC /* Finish.cpp in Sources */,
2193519B2C6278D900E5A69C /* SelectionSubscriber.cpp in Sources */,
21D0BD2B2C86FC350077E104 /* Record.cpp in Sources */,
219246042CA2CE2700CF5703 /* BIMLink.cpp in Sources */,
215F08952CA19AF800CD343B /* BIMElementDatabase.cpp in Sources */,
219246122CA34DCE00CF5703 /* Mesh.cpp in Sources */,
21D0BD592C8910400077E104 /* UserInfo.cpp in Sources */,
210CC8902C81A98500610F58 /* Guid64.cpp in Sources */,
21D0BDC42C9241940077E104 /* ProjectSubscriber.cpp in Sources */,
21D0BD322C86FE090077E104 /* Link.cpp in Sources */,
219351B32C62CC1A00E5A69C /* String.cpp in Sources */,
219351B12C62CC1A00E5A69C /* Guid.cpp in Sources */,
21F69F512C6CCC25008B6A06 /* BrowserBridge.cpp in Sources */,
21AEF9BC2CA6DF84000B8681 /* DetachmentManager.cpp in Sources */,
215F08552C99DA8D00CD343B /* Project.cpp in Sources */,
21F69F3B2C6B880C008B6A06 /* JSBaseTransport.cpp in Sources */,
2196F2EB2CB4816B00450DFC /* ArchicadAttributeDBaseEngine.cpp in Sources */,
210CC89F2C81E34400610F58 /* Platform.cpp in Sources */,
21D0BD202C86F0280077E104 /* AccountDatabase.cpp in Sources */,
21F69F962C71087A008B6A06 /* Account.cpp in Sources */,
21AEF9BA2CA606B5000B8681 /* DetachedReference.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
+36 -1
View File
@@ -20,9 +20,18 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="Speckle\Database\AccountDatabase.h" />
<ClInclude Include="Speckle\Database\BIMAttributeDatabase.h" />
<ClInclude Include="Speckle\Database\BIMElementDatabase.h" />
<ClInclude Include="Speckle\Database\Content\BIMRecord.h" />
<ClInclude Include="Speckle\Database\Content\Record.h" />
<ClInclude Include="Speckle\Database\Identity\BIMIndex.h" />
<ClInclude Include="Speckle\Database\Identity\BIMLink.h" />
<ClInclude Include="Speckle\Database\Identity\BIMRecordID.h" />
<ClInclude Include="Speckle\Database\Identity\Index.h" />
<ClInclude Include="Speckle\Database\Identity\Link.h" />
<ClInclude Include="Speckle\Database\Storage\ArchicadDBase\ArchicadDBaseCore.h" />
<ClInclude Include="Speckle\Database\Storage\ArchicadDBase\Attribute\ArchicadAttributeDBaseEngine.h" />
<ClInclude Include="Speckle\Database\Storage\ArchicadDBase\Element\ArchicadElementDBaseEngine.h" />
<ClInclude Include="Speckle\Database\Storage\DocumentStore\DocumentStoreCore.h" />
<ClInclude Include="Speckle\Database\Storage\DocumentStore\DocumentStoreEngine.h" />
<ClInclude Include="Speckle\Environment\Addon.h" />
@@ -54,11 +63,22 @@
<ClInclude Include="Speckle\Interface\Browser\JSPortal.h" />
<ClInclude Include="Speckle\Interface\Browser\NamedFunction.h" />
<ClInclude Include="Speckle\Interface\Browser\PlatformBinding.h" />
<ClInclude Include="Speckle\Primitive\Mesh\Mesh.h" />
<ClInclude Include="Speckle\Record\Attribute\Attribute.h" />
<ClInclude Include="Speckle\Record\Attribute\Finish.h" />
<ClInclude Include="Speckle\Record\Attribute\Storey.h" />
<ClInclude Include="Speckle\Record\Credentials\Account.h" />
<ClInclude Include="Speckle\Record\Credentials\ServerInfo.h" />
<ClInclude Include="Speckle\Record\Credentials\ServerMigration.h" />
<ClInclude Include="Speckle\Record\Credentials\UserInfo.h" />
<ClInclude Include="Speckle\Record\Element\Element.h" />
<ClInclude Include="Speckle\Serialise\Detached\DetachedReference.h" />
<ClInclude Include="Speckle\Serialise\Detached\DetachedWrap.h" />
<ClInclude Include="Speckle\Serialise\Detached\DetachmentManager.h" />
<ClInclude Include="Speckle\Serialise\Detached\Storage\DetachedMemoryStore.h" />
<ClInclude Include="Speckle\Serialise\Detached\Storage\DetachedObjectStore.h" />
<ClInclude Include="Speckle\Serialise\JSBase\JSBaseTransport.h" />
<ClInclude Include="Speckle\Serialise\Units\LengthUnit.h" />
<ClInclude Include="Speckle\SpeckleResource.h" />
<ClInclude Include="Speckle\Utility\Exception.h" />
<ClInclude Include="Speckle\Utility\Guid.h" />
@@ -68,8 +88,14 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="Speckle\Database\AccountDatabase.cpp" />
<ClCompile Include="Speckle\Database\BIMAttributeDatabase.cpp" />
<ClCompile Include="Speckle\Database\BIMElementDatabase.cpp" />
<ClCompile Include="Speckle\Database\Content\BIMRecord.cpp" />
<ClCompile Include="Speckle\Database\Content\Record.cpp" />
<ClCompile Include="Speckle\Database\Identity\Link.cpp" />
<ClCompile Include="Speckle\Database\Identity\BIMLink.cpp" />
<ClCompile Include="Speckle\Database\Storage\ArchicadDBase\ArchicadDBaseCore.cpp" />
<ClCompile Include="Speckle\Database\Storage\ArchicadDBase\Attribute\ArchicadAttributeDBaseEngine.cpp" />
<ClCompile Include="Speckle\Database\Storage\ArchicadDBase\Element\ArchicadElementDBaseEngine.cpp" />
<ClCompile Include="Speckle\Database\Storage\DocumentStore\DocumentStoreCore.cpp" />
<ClCompile Include="Speckle\Environment\Addon.cpp" />
<ClCompile Include="Speckle\Environment\Platform.cpp" />
@@ -86,11 +112,20 @@
<ClCompile Include="Speckle\Interface\Browser\Bridge\Functions\GetBindingsMethodNames.cpp" />
<ClCompile Include="Speckle\Interface\Browser\Bridge\Functions\GetCallResult.cpp" />
<ClCompile Include="Speckle\Interface\Browser\Bridge\Functions\RunMethod.cpp" />
<ClCompile Include="Speckle\Primitive\Mesh\Mesh.cpp" />
<ClCompile Include="Speckle\Record\Attribute\Attribute.cpp" />
<ClCompile Include="Speckle\Record\Attribute\Finish.cpp" />
<ClCompile Include="Speckle\Record\Attribute\Storey.cpp" />
<ClCompile Include="Speckle\Record\Credentials\Account.cpp" />
<ClCompile Include="Speckle\Record\Credentials\ServerInfo.cpp" />
<ClCompile Include="Speckle\Record\Credentials\ServerMigration.cpp" />
<ClCompile Include="Speckle\Record\Credentials\UserInfo.cpp" />
<ClCompile Include="Speckle\Record\Element\Element.cpp" />
<ClCompile Include="Speckle\Serialise\Detached\DetachedReference.cpp" />
<ClCompile Include="Speckle\Serialise\Detached\DetachedWrap.cpp" />
<ClCompile Include="Speckle\Serialise\Detached\DetachmentManager.cpp" />
<ClCompile Include="Speckle\Serialise\JSBase\JSBaseTransport.cpp" />
<ClCompile Include="Speckle\Serialise\Units\LengthUnit.cpp" />
<ClCompile Include="Speckle\Utility\Guid.cpp" />
<ClCompile Include="Speckle\Utility\Guid64.cpp" />
<ClCompile Include="Speckle\Utility\String.cpp" />
+138 -3
View File
@@ -62,6 +62,36 @@
<Filter Include="Speckle\Database\Storage\DocumentStore">
<UniqueIdentifier>{c4146af8-d1a1-44cc-9810-cc8da1a705a8}</UniqueIdentifier>
</Filter>
<Filter Include="Speckle\Record\Element">
<UniqueIdentifier>{728f7e85-53d8-4fe0-9994-394010324eb8}</UniqueIdentifier>
</Filter>
<Filter Include="Speckle\Primitive">
<UniqueIdentifier>{896361f5-4195-4662-be29-9e8241cab17c}</UniqueIdentifier>
</Filter>
<Filter Include="Speckle\Primitive\Mesh">
<UniqueIdentifier>{87719e02-08cb-466e-a01b-66fdbb278efe}</UniqueIdentifier>
</Filter>
<Filter Include="Speckle\Database\Storage\ArchicadDBase">
<UniqueIdentifier>{c99c6ba7-cdb5-4182-9df9-debe5559b460}</UniqueIdentifier>
</Filter>
<Filter Include="Speckle\Database\Storage\ArchicadDBase\Element">
<UniqueIdentifier>{93db2ed5-fd21-4ed1-86ee-f549682f66a5}</UniqueIdentifier>
</Filter>
<Filter Include="Speckle\Serialise\Detached">
<UniqueIdentifier>{e9aec552-0aa8-4193-867d-69febdf93139}</UniqueIdentifier>
</Filter>
<Filter Include="Speckle\Serialise\Detached\Storage">
<UniqueIdentifier>{cb77e795-e8d8-4e31-9773-dd32beb694d3}</UniqueIdentifier>
</Filter>
<Filter Include="Speckle\Serialise\Units">
<UniqueIdentifier>{7d5ec9ba-bc7e-412c-9b14-16c37b183409}</UniqueIdentifier>
</Filter>
<Filter Include="Speckle\Database\Storage\ArchicadDBase\Attribute">
<UniqueIdentifier>{490a65bd-28e3-4282-bb33-67823e81e825}</UniqueIdentifier>
</Filter>
<Filter Include="Speckle\Record\Attribute">
<UniqueIdentifier>{525b6bd6-96e4-48c8-91e9-9710e1e54389}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Speckle\Environment\Addon.h">
@@ -202,6 +232,66 @@
<ClInclude Include="Speckle\Version.h">
<Filter>Speckle</Filter>
</ClInclude>
<ClInclude Include="Speckle\Record\Element\Element.h">
<Filter>Speckle\Record\Element</Filter>
</ClInclude>
<ClInclude Include="Speckle\Primitive\Mesh\Mesh.h">
<Filter>Speckle\Primitive\Mesh</Filter>
</ClInclude>
<ClInclude Include="Speckle\Database\Storage\ArchicadDBase\ArchicadDBaseCore.h">
<Filter>Speckle\Database\Storage\ArchicadDBase</Filter>
</ClInclude>
<ClInclude Include="Speckle\Database\Storage\ArchicadDBase\Element\ArchicadElementDBaseEngine.h">
<Filter>Speckle\Database\Storage\ArchicadDBase\Element</Filter>
</ClInclude>
<ClInclude Include="Speckle\Database\BIMElementDatabase.h">
<Filter>Speckle\Database</Filter>
</ClInclude>
<ClInclude Include="Speckle\Database\Content\BIMRecord.h">
<Filter>Speckle\Database\Content</Filter>
</ClInclude>
<ClInclude Include="Speckle\Database\Identity\BIMIndex.h">
<Filter>Speckle\Database\Identity</Filter>
</ClInclude>
<ClInclude Include="Speckle\Database\Identity\BIMLink.h">
<Filter>Speckle\Database\Identity</Filter>
</ClInclude>
<ClInclude Include="Speckle\Database\Identity\BIMRecordID.h">
<Filter>Speckle\Database\Identity</Filter>
</ClInclude>
<ClInclude Include="Speckle\Serialise\Detached\DetachedReference.h">
<Filter>Speckle\Serialise\Detached</Filter>
</ClInclude>
<ClInclude Include="Speckle\Serialise\Detached\DetachedWrap.h">
<Filter>Speckle\Serialise\Detached</Filter>
</ClInclude>
<ClInclude Include="Speckle\Serialise\Detached\DetachmentManager.h">
<Filter>Speckle\Serialise\Detached</Filter>
</ClInclude>
<ClInclude Include="Speckle\Serialise\Detached\Storage\DetachedMemoryStore.h">
<Filter>Speckle\Serialise\Detached\Storage</Filter>
</ClInclude>
<ClInclude Include="Speckle\Serialise\Detached\Storage\DetachedObjectStore.h">
<Filter>Speckle\Serialise\Detached\Storage</Filter>
</ClInclude>
<ClInclude Include="Speckle\Serialise\Units\LengthUnit.h">
<Filter>Speckle\Serialise\Units</Filter>
</ClInclude>
<ClInclude Include="Speckle\Database\BIMAttributeDatabase.h">
<Filter>Speckle\Database</Filter>
</ClInclude>
<ClInclude Include="Speckle\Database\Storage\ArchicadDBase\Attribute\ArchicadAttributeDBaseEngine.h">
<Filter>Speckle\Database\Storage\ArchicadDBase\Attribute</Filter>
</ClInclude>
<ClInclude Include="Speckle\Record\Attribute\Attribute.h">
<Filter>Speckle\Record\Attribute</Filter>
</ClInclude>
<ClInclude Include="Speckle\Record\Attribute\Finish.h">
<Filter>Speckle\Record\Attribute</Filter>
</ClInclude>
<ClInclude Include="Speckle\Record\Attribute\Storey.h">
<Filter>Speckle\Record\Attribute</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Speckle\Environment\Addon.cpp">
@@ -252,9 +342,6 @@
<ClCompile Include="Speckle\Utility\Guid64.cpp">
<Filter>Speckle\Utility</Filter>
</ClCompile>
<ClCompile Include="Speckle\Database\Identity\Link.cpp">
<Filter>Speckle\Database\Identity</Filter>
</ClCompile>
<ClCompile Include="Speckle\Database\AccountDatabase.cpp">
<Filter>Speckle\Database</Filter>
</ClCompile>
@@ -285,6 +372,54 @@
<ClCompile Include="Speckle\Event\Type\ProjectEvent.cpp">
<Filter>Speckle\Event\Type</Filter>
</ClCompile>
<ClCompile Include="Speckle\Record\Element\Element.cpp">
<Filter>Speckle\Record\Element</Filter>
</ClCompile>
<ClCompile Include="Speckle\Primitive\Mesh\Mesh.cpp">
<Filter>Speckle\Primitive\Mesh</Filter>
</ClCompile>
<ClCompile Include="Speckle\Database\Storage\ArchicadDBase\ArchicadDBaseCore.cpp">
<Filter>Speckle\Database\Storage\ArchicadDBase</Filter>
</ClCompile>
<ClCompile Include="Speckle\Database\Storage\ArchicadDBase\Element\ArchicadElementDBaseEngine.cpp">
<Filter>Speckle\Database\Storage\ArchicadDBase\Element</Filter>
</ClCompile>
<ClCompile Include="Speckle\Database\BIMElementDatabase.cpp">
<Filter>Speckle\Database</Filter>
</ClCompile>
<ClCompile Include="Speckle\Database\Content\BIMRecord.cpp">
<Filter>Speckle\Database\Content</Filter>
</ClCompile>
<ClCompile Include="Speckle\Database\Identity\BIMLink.cpp">
<Filter>Speckle\Database\Identity</Filter>
</ClCompile>
<ClCompile Include="Speckle\Serialise\Detached\DetachedReference.cpp">
<Filter>Speckle\Serialise\Detached</Filter>
</ClCompile>
<ClCompile Include="Speckle\Serialise\Detached\DetachedWrap.cpp">
<Filter>Speckle\Serialise\Detached</Filter>
</ClCompile>
<ClCompile Include="Speckle\Serialise\Detached\DetachmentManager.cpp">
<Filter>Speckle\Serialise\Detached</Filter>
</ClCompile>
<ClCompile Include="Speckle\Serialise\Units\LengthUnit.cpp">
<Filter>Speckle\Serialise\Units</Filter>
</ClCompile>
<ClCompile Include="Speckle\Database\BIMAttributeDatabase.cpp">
<Filter>Speckle\Database</Filter>
</ClCompile>
<ClCompile Include="Speckle\Database\Storage\ArchicadDBase\Attribute\ArchicadAttributeDBaseEngine.cpp">
<Filter>Speckle\Database\Storage\ArchicadDBase\Attribute</Filter>
</ClCompile>
<ClCompile Include="Speckle\Record\Attribute\Attribute.cpp">
<Filter>Speckle\Record\Attribute</Filter>
</ClCompile>
<ClCompile Include="Speckle\Record\Attribute\Finish.cpp">
<Filter>Speckle\Record\Attribute</Filter>
</ClCompile>
<ClCompile Include="Speckle\Record\Attribute\Storey.cpp">
<Filter>Speckle\Record\Attribute</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Text Include="Speckle\CMakeLists.txt">