Jump to content

JHangstoerfer

Member
  • Posts

    12
  • Joined

  • Last visited

Everything posted by JHangstoerfer

  1. I thought of manually creating the script object but there are way too many edge cases that I would want to deal with. Like "Saved Views" palette name being a localized text, or when someone renamed "Saved Views", or it already exists as a different object, doesn't exist yet at all and more. There's probably even more that happens in the background that I don't know of so I'd rather use the script function to do all of this for me. Be careful with VWViewObj, because it deletes the view that it creates/duplicates in its dtor. That's why I mentioned that it's really only used for temporary views. VWViewObj::VWViewObj() { fhViewObj = gSDK->ViewCreateCurrent(); } VWViewObj::VWViewObj(const VWViewObj& src) { fhViewObj = gSDK->ViewDuplicate( src.fhViewObj ); } VWViewObj::VWViewObj(MCObjectHandle hView) { VWFC_ASSERT(VWViewObj::IsViewObject(hView)); if (!VWViewObj::IsViewObject(hView)) THROW_VWFC_EXCEPTION(VWBadObjectTypeException, 0, "bad handle type when creating"); fhViewObj = gSDK->DuplicateObject( hView ); fhObject = fhViewObj; VWFC_ASSERT(fhObject != nil); } VWViewObj::~VWViewObj() { gSDK->ViewDelete( fhViewObj ); fhViewObj = NULL; fhObject= NULL; }
  2. VWViewObj only is for temporary saved views like when you want to change camera, layers and then restore to how it was previously afterwards. For creating a saved view that shows up in the navigation palette there is ISDK::CreateSavedViewWithUI or the python/vss SaveSheet. To modify a saved view you also need to use the ISDK calls directly as VWViewObj operates on a duplicate. I know it's not hard but I would have rather used a type safe way instead of converting everything to string myself. Alright, if CallUserProcedure doesn't do what I expected then I guess I will be using the ExecuteScript method.
  3. I have a (hopefully) simple question about the usage of VectorWorks::Scripting::IPythonScriptEngine and or IVectorScriptEngine. I want to call a procedure that is not available in the SDK but is available in both python and vss. I want to call SaveSheet, which saves the current view, layer settings and more in a saved view (saved views used to be called sheets). The closest equivalent in the SDK that I could find was ISDK::CreateSavedViewWithUI, which does the same but instead opens up the dialogue that you would see when you manually create a saved view via the UI. Basically, I want to create a saved view without the UI. An obvious starting point to achieve what I want seems to be VectorWorks::Scripting::IPythonScriptEngine and VectorWorks::Scripting::IVectorScriptEngine and I also got it to work quite fast: VCOMPtr<VectorWorks::Scripting::IPythonScriptEngine> pythonScriptEngine{ VectorWorks::Scripting::IID_PythonScriptEngine }; VCOMError err = pythonScriptEngine->ExecuteScript("vs.SaveSheet(\"Test\", True, True, True)"); This might be easy to use but I don't like the fact that I have to concatenate a string if I want to change any of the parameters. For this case, both of the ScriptEngines seem to offer a function called CallUserProcedure. I think it does what I want but in a more type safe manner Now finally for my questions. Can CallUserProcedure be used to call SaveSheet? Is this even the correct function that I'm trying to use or does this something completely different? I'm also struggling to find out what the first parameter "procedureRef" has to be to achieve this call. This is what I think it would look like with CallUserProcedure but it's missing the procedureRef VCOMPtr<VectorWorks::Scripting::IPythonScriptEngine> pythonScriptEngine{ VectorWorks::Scripting::IID_PythonScriptEngine }; PluginLibraryArgTable argTable { .args = { { .argType = kStringArgType, .strValue = "Test" }, { .argType = kBooleanArgType, .boolValue = true }, { .argType = kBooleanArgType, .boolValue = true }, { .argType = kBooleanArgType, .boolValue = true } }}; void* procedureRef = nullptr; // ??? VCOMError err = pythonScriptEngine->CallUserProcedure(procedureRef, &argTable, 4);
  4. kNotifyDocPreSaved seems to have the information you want // Manual kNotifyDocPreSaved C:\Users\Work\AppData\Local\Temp\Untitled 1-VWTMP.swap kNotifyDocPostSaved C:\tmp\Untitled 1.vwx // Backup kNotifyDocPreSaved C:\tmp\VW Backup\Untitled 1-Backup-20220603201902.vwx kNotifyDocPostSaved C:\tmp\Untitled 1.vwx Note that I used gSDK->GetOpenFilesList to read the filepath of the doc during the event, I don't know whether gSDK->GetActiveDocument provides the same information
  5. gSDK->ViewStore is the call that we needed. The problem was that we used the VWViewObj utility class. In its constructor, it creates a duplicate of the original saved view so VWViewObj::StoreView doesn't actually commit those changes to the correct object. Here is a working sample, although this might required a RestoreView beforehand, otherwise ViewStore commits changes other than the ViewMatrix. At least I think that's how it works. auto viewParentHandle = VWFC::VWObject::GetNamedObject("Saved View Name"); auto viewHandle = gSDK->FindAuxObject(viewParentHandle, saveViewNode); auto activeLayer = gSDK->GetActiveLayer(); gSDK->SetViewMatrix(activeLayer, viewMatrix); gSDK->ViewStore(viewHandle);
  6. There is some tagged data below saveViewNode but nothing looks like the information that we want.
  7. I don't see a way to read or write the fields from my screenshot directly. It might be possible they are additionally saved in tagged user data but I don't have the dataTags and dataIndex to read those values without brute forcing to find them.
  8. We want to update the matrix of a saved view of perspective type. In the UI this is handled via "Redefine..." in the Navigation palette and also allows you to change some restore options but those are not relevant for us. I don't see any methods in the SDK that would allows us to do this. There is gSDK->EditSavedViewWithUI but that opens the Edit dialog, which does not update the matrix, only the other options and the name. A way to trigger to open up the Redefine UI would also be fine for us. "Redefine..." seems update the matrix on the saveViewNode. Would it be possible to directly modify these fields with our new matrix?
  9. I've only used GetImageStream from ICompressedImage. You don't get a file path to the image because the file content of the images is embedded in the Vectorworks project. You either use the file content bytes directly or you have to write them to the filesystem if you really want a Filepath. I think the compress image api can also write the files using the Save() call. VectorWorks::Imaging::ICompressedImagePtr imageApi(VectorWorks::Imaging::IID_CompressedImage); auto err = imageApi->CreateFromObject(imageHandle); // check err // Contains jpg or png data VectorWorks::Imaging::ImageStream imageStream{}; err = imageApi->GetImageStream(imageStream); // check err // Use imageStream.bufferPtr as std::byte[] with size imageStream.bufferSizeInBytes // Never used this but it looks like meta information about the image VectorWorks::Imaging::CompressedImageDesc desc{}; err = imageApi->GetCompressedImageDesc(desc); // check err I don't know where you would fine extra info like brightness, uv and rotation but it sounds like this would be either in the material or in the geometry. ICompressedImage is just for the raw image file content.
  10. Field id is not the prototype value, but you don't really have to know the field id anyway. You need an additional step to read the transparency value, in case you have a plain transparency shader. Shaders are divided into families and families are divided into prototypes. See the difference in the texture edit dialog: You can use VWFC::VWTextureShaderBase::GetShaderRecordFamilyAndPrototype or each of the prototype helpers like VWTextureShaderTransparencyPlain::IsShaderRecordObject to determine what prototype it is. After figuring out what prototype it is you can use the helpers to read the values: auto recordHandle = gSDK->GetShaderRecord(hMaterial, kShaderFamily_Transparency); // option 1 if (VWFC::VWTextureShaderTransparencyPlain::IsShaderRecordObject(recordHandle)) { VWFC::VWTextureShaderTransparencyPlain shader{ recordHandle }; auto opacity = shader.GetOpacity(); } // option 2 auto family = kShaderFamily_Undefined; auto prototype = 0; if (!VWFC::VWTextureShaderBase::GetShaderRecordFamilyAndPrototype(recordHandle, family, prototype)) { // "None" Transparency Shader return; } if (prototype == kShaderPrototypeTransparency_Image) { VWFC::VWTextureShaderTransparencyImage shader{ recordHandle }; // read image file content with VectorWorks::Imaging::ICompressedImage auto imageHandle = shader.GetImage(); auto refraction = shader.GetRefraction(); auto bluriness = shader.GetTransparencyBlurriness(); // ... } GetOpacity uses the field Id to get the value from the record. In this case it's 4, which is a constant that is only specific to plain transparency. You can see those field values when you look at the record handles in the debug menu, or if you look at the .cpp files of the prototype helpers. But as I said before, if you use the helper you don't have to know the field id is.
  11. GetMesh only works for kMeshNode objects. It doesn't work for solids. Where are you having troubles with VGS? I think it's the easiest of any of these methods. You get meshes for all objects including solids via VGS and their materials in easy to use formats. I can answer any questions you got about VGS.
  12. @Cachino KingVectorworks Graphics Sync is what you want for a true live sync, assuming that you use VW2020 or higher. Look at Interfaces\VectorWorks\IVGS.h, you will need an extra header file for ::VGS::Operation because it's not included in the normal SDK. You'd have to contact VW and ask for access to the API. VGS is relatively straightforward, you get tessellated geometry, camera position, rudimentary materials (full materials with some more work), object instances and proper update events for all of it. Alternatively there is the Tesselator that you can use to get geometry from objects and their children. If you throw a layer handle into this tesselator it will export everything on that layer. The STessTraingle contains information about what is being tessellated and the object, material, triangles for it. Extra information like a transformation you can get from the object. This is more of a one-time export and you would need to detect any changes in the document yourself and then tessellate those parts again, which I'm not sure how to do. GS_TessellateIteratorProcPtr tesselationCallback = [](ETessProcReason reason, STessTraingle triangle, CallBackPtr cbp, void* pEnv) { YourExportContext* context = static_cast<YourExportContext*>(pEnv); switch (reason) { // collect data into context } }; YourExportContext context{}; TTesselator tesselator = gSDK->CreateTessellator(true); VectorWorks::STesselateOptions tesselationOptions{}; MCObjectHandle handleToRecursivelyTesselate; gSDK->TesselateObjectN(tesselator, tesselationOptions, handleToRecursivelyTesselate, tesselationCallback, &context); gSDK->DeleteTessellator(tesselator);
×
×
  • Create New...