/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a license // agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// // ODA Platform #include "OdaCommon.h" #include "RxDynamicModule.h" #include "RxObject.h" #include "StaticRxObject.h" #include "TvFactory.h" #include "TvGeomCollector.h" #include "TvFilerTimer.h" #include "TvModuleNames.h" #include "TvDatabaseCleaner.h" #include "TvDatabaseUtils.h" #include "Sw2Visualize.h" #include "TSwModuleNames.h" #include "RxInit.h" #include "RxVariantValue.h" #include "SwDb/SwGsManager.h" #include "ColorMapping.h" //SEA #include "DynamicLinker.h" #include "TvFactory.h" #include "ExVisualizeDeviceExtensions.h" #include "ThreadsCounter.h" #include "RxModelTreeBaseNode.h" #include "RxModelHierarchyTreeBase.h" #include #include //*************************************************************************************// // Implementation of the methods of the inheritants of 'OdTvVisualizeSwFilerDbSource' //*************************************************************************************// class OdTvVisualizeSwFilerSourceFromDb : public OdTvVisualizeSwFilerDbSource { OdDbBaseDatabase *mDatabase; public: OdTvVisualizeSwFilerSourceFromDb(OdDbBaseDatabase *pDatabase) : mDatabase(pDatabase) {}; virtual OdRxSwDatabasePtr getDb() { return mDatabase; }; virtual bool odWasInitialized() const { return false; } virtual OdString getFullFileName() { return OdString(); } virtual OdString getFilename() { OdRxSwDatabasePtr pDb = mDatabase; if (!pDb.isNull()) { OdString fileName = pDb->getFilename(); if (!fileName.isEmpty()) return fileName; } return OD_T("NoNameDgnDatabase"); } }; class OdTvVisualizeSwFilerSourceFromFile : public OdTvVisualizeSwFilerDbSource { OdStaticRxObject svcs; OdString mFilePath; protected: double m_initTime; public: OdTvVisualizeSwFilerSourceFromFile(const OdString& filePath, OdTvFilerTimeProfiling* pProfileRes, const SW2Visualize::OdTvVisualizeSwFilerPropertiesPtr pProperties) { initialize(filePath, pProfileRes, pProperties); }; virtual OdRxSwDatabasePtr getDb() { OdRxSwModulePtr pModule = odrxDynamicLinker()->loadModule(SwModuleName, false); OdRxSwDatabasePtr pDb = pModule->readSwFile(mFilePath, Oda::kShareDenyWrite, true); return pDb; }; virtual double getInitTime() const { return m_initTime; } virtual OdString getFilename() { //generate name for the stream file return OdTvDatabaseUtils::getFileNameFromPath(mFilePath); }; virtual OdString getFullFileName() { return mFilePath; } protected: OdTvVisualizeSwFilerSourceFromFile() {}; void initialize(const OdString& filePath, OdTvFilerTimeProfiling* pProfileRes, const SW2Visualize::OdTvVisualizeSwFilerPropertiesPtr pProperties) { mFilePath = filePath; OdTvFilerTimer timing(needTimer(pProfileRes)); timing.startTotal(); timing.endTotal(); m_initTime = timing.getTotalTime(); }; }; //***************************************************************************// // 'OdTvVisualizeSwFilerProperties' methods implementation //***************************************************************************// using namespace SW2Visualize; OdTvVisualizeSwFilerProperties::OdTvVisualizeSwFilerProperties() : m_flags(kClearEmptyObjects | kUseIsolinesFor3DObjects), m_pCallback(0) { m_importRect.xmax = 1; m_importRect.xmin = 0; m_importRect.ymax = 0; m_importRect.ymin = 1; m_defaultUnits = OdTv::kMillimeters; } OdRxDictionaryPtr OdTvVisualizeSwFilerProperties::createObject() { return OdRxObjectImpl::createObject(); } OdTvVisualizeSwFilerProperties::~OdTvVisualizeSwFilerProperties() { } namespace SW2Visualize { ODRX_DECLARE_PROPERTY(Palette) ODRX_DECLARE_PROPERTY(DCRect) ODRX_DECLARE_PROPERTY(ObjectNaming) ODRX_DECLARE_PROPERTY(StoreSourceObjects) ODRX_DECLARE_PROPERTY(FeedbackForChooseCallback) ODRX_DECLARE_PROPERTY(ClearEmptyObjects) ODRX_DECLARE_PROPERTY(UseIsolinesFor3DObjects) ODRX_DECLARE_PROPERTY(AppendTransform) ODRX_DECLARE_PROPERTY(NeedCDATree) ODRX_DECLARE_PROPERTY(NeedCollectPropertiesInCDA) ODRX_DECLARE_PROPERTY(DefaultUnits) ODRX_BEGIN_DYNAMIC_PROPERTY_MAP(OdTvVisualizeSwFilerProperties); ODRX_GENERATE_PROPERTY(Palette) ODRX_GENERATE_PROPERTY(DCRect) ODRX_GENERATE_PROPERTY(ObjectNaming) ODRX_GENERATE_PROPERTY(StoreSourceObjects) ODRX_GENERATE_PROPERTY(FeedbackForChooseCallback) ODRX_GENERATE_PROPERTY(ClearEmptyObjects) ODRX_GENERATE_PROPERTY(UseIsolinesFor3DObjects) ODRX_GENERATE_PROPERTY(AppendTransform) ODRX_GENERATE_PROPERTY(NeedCDATree) ODRX_GENERATE_PROPERTY(NeedCollectPropertiesInCDA) ODRX_GENERATE_PROPERTY(DefaultUnits) ODRX_END_DYNAMIC_PROPERTY_MAP(OdTvVisualizeSwFilerProperties); ODRX_DEFINE_PROPERTY_METHODS(Palette, OdTvVisualizeSwFilerProperties, getPalette, setPalette, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(DCRect, OdTvVisualizeSwFilerProperties, getDCRect, setDCRect, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(ObjectNaming, OdTvVisualizeSwFilerProperties, getObjectNaming, setObjectNaming, getBool); ODRX_DEFINE_PROPERTY_METHODS(StoreSourceObjects, OdTvVisualizeSwFilerProperties, getStoreSourceObjects, setStoreSourceObjects, getBool); ODRX_DEFINE_PROPERTY_METHODS(FeedbackForChooseCallback, OdTvVisualizeSwFilerProperties, getFeedbackForChooseCallback, setFeedbackForChooseCallback, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(ClearEmptyObjects, OdTvVisualizeSwFilerProperties, getClearEmptyObjects, setClearEmptyObjects, getBool); ODRX_DEFINE_PROPERTY_METHODS(UseIsolinesFor3DObjects, OdTvVisualizeSwFilerProperties, getUseIsolinesFor3DObjects, setUseIsolinesFor3DObjects, getBool); ODRX_DEFINE_PROPERTY_METHODS(AppendTransform, OdTvVisualizeSwFilerProperties, getAppendTransform, setAppendTransform, getIntPtr); ODRX_DEFINE_PROPERTY_METHODS(NeedCDATree, OdTvVisualizeSwFilerProperties, getNeedCDATree, setNeedCDATree, getBool); ODRX_DEFINE_PROPERTY_METHODS(NeedCollectPropertiesInCDA, OdTvVisualizeSwFilerProperties, getNeedCollectPropertiesInCDA, setNeedCollectPropertiesInCDA, getBool); ODRX_DEFINE_PROPERTY_METHODS(DefaultUnits, OdTvVisualizeSwFilerProperties, getDefaultUnits, setDefaultUnits, getIntPtr); } void OdTvVisualizeSwFilerProperties::setPalette(OdIntPtr palette) { const ODCOLORREF* pPalette = (const ODCOLORREF*)(palette); m_pPalette = pPalette; } OdIntPtr OdTvVisualizeSwFilerProperties::getPalette() const { return (OdIntPtr)(m_pPalette); } void OdTvVisualizeSwFilerProperties::setDCRect(OdIntPtr rect) { OdTvDCRect* pRect = (OdTvDCRect*)(rect); if (!pRect) { ODA_ASSERT(false); } m_importRect = *pRect; } OdIntPtr OdTvVisualizeSwFilerProperties::getDCRect() const { return (OdIntPtr)(&m_importRect); } void OdTvVisualizeSwFilerProperties::setFeedbackForChooseCallback(OdIntPtr pCallback) { m_pCallback = (OdTvFeedbackForChooseCallback)pCallback; } OdIntPtr OdTvVisualizeSwFilerProperties::getFeedbackForChooseCallback() const { return (OdIntPtr)m_pCallback; } void OdTvVisualizeSwFilerProperties::setAppendTransform(OdIntPtr pTransform) { const OdTvMatrix* pAppendTransform = (const OdTvMatrix*)(pTransform); if (pAppendTransform) { m_appendTransform = *pAppendTransform; } else { m_appendTransform = OdTvMatrix::kIdentity; } } OdIntPtr OdTvVisualizeSwFilerProperties::getAppendTransform() const { return (OdIntPtr)(&m_appendTransform); } //***************************************************************************// // 'OdTvVisualizeDgnFiler' methods implementation //***************************************************************************// OdTvVisualizeSwFiler::OdTvVisualizeSwFiler() : m_properties(OdTvVisualizeSwFilerProperties::createObject()), m_pDl(NULL) { } OdTvVisualizeSwFiler::~OdTvVisualizeSwFiler() { if (m_pDl) m_pDl = NULL; } OdTvDatabaseId OdTvVisualizeSwFiler::loadFrom(OdDbBaseDatabase *pDatabase, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvVisualizeSwFilerSourceFromDb dl(pDatabase); return loadFrom(&dl, pProfileRes, rc); } OdTvDatabaseId OdTvVisualizeSwFiler::loadFrom(OdStreamBuf* pBuffer, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { if (rc) *rc = tvNotSupported; return OdTvDatabaseId(); } OdTvDatabaseId OdTvVisualizeSwFiler::loadFrom(const OdString& filePath, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvVisualizeSwFilerSourceFromFile dl(filePath, pProfileRes, m_properties); return loadFrom(&dl, pProfileRes, rc); } OdTvDatabaseId OdTvVisualizeSwFiler::generate(OdTvFilerTimeProfiling* pProfileRes) const { return OdTvDatabaseId(); } OdTvModelId OdTvVisualizeSwFiler::appendFrom(const OdTvDatabaseId& databaseId, OdDbBaseDatabase *pDatabase, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvVisualizeSwFilerSourceFromDb dl(pDatabase); return appendFrom(databaseId, &dl, pProfileRes, rc); } OdTvModelId OdTvVisualizeSwFiler::appendFrom(const OdTvDatabaseId& databaseId, OdStreamBuf *pBuffer, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { if (rc) *rc = tvNotSupported; return OdTvModelId(); } OdTvModelId OdTvVisualizeSwFiler::appendFrom(const OdTvDatabaseId& databaseId, const OdString &filePath, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvVisualizeSwFilerSourceFromFile dl(filePath, pProfileRes, m_properties); return appendFrom(databaseId, &dl, pProfileRes, rc); } OdTvResult OdTvVisualizeSwFiler::startActionsWithNativeProperties(const OdString& sFilePath, bool bPartial) { OdTvResult rc = tvOk; return rc; } bool OdTvVisualizeSwFiler::isActionsWithNativePropertiesStarted(const OdString& sFilePath) { return false; } OdTvResult OdTvVisualizeSwFiler::endActionsWithNativeProperties() { return tvOk; } OdRxMemberIteratorPtr OdTvVisualizeSwFiler::getNativePropertiesIterator(OdUInt64 dbHandle, OdTvResult* rc) { OdRxMemberIteratorPtr pIter; return pIter; } OdRxValue OdTvVisualizeSwFiler::getNativePropertyValue(OdUInt64 dbHandle, const OdRxPropertyPtr& pProperty, bool* bReadOnly, OdTvResult* rc) { OdRxObjectPtr pElement; return pElement; } OdRxValueIteratorPtr OdTvVisualizeSwFiler::getNativeCollectionPropertyIterator(OdUInt64 dbHandle, const OdRxCollectionPropertyPtr& pCollectionProperty, bool* bReadOnly, OdTvResult* rc) { OdRxValueIteratorPtr pValIter; return pValIter; } OdTvResult OdTvVisualizeSwFiler::setNativePropertyValue(OdUInt64 dbHandle, OdRxPropertyPtr& pProperty, const OdRxValue& value) { OdRxObjectPtr pElement; return tvOk; } OdDbBaseDatabase* OdTvVisualizeSwFiler::getNativeDatabase(OdTvResult* rc) const { return NULL; } OdTvDatabaseId OdTvVisualizeSwFiler::loadFrom(OdTvVisualizeSwFilerDbSource* pSwDatabaseSource, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvDatabaseId tvDbId; if (rc) *rc = tvOk; //check that time profiling is need bool bUseTimeProfiling = needTimer(pProfileRes); double internalTiming = 0.; double externalTiming = 0.; //prepare timing object OdTvFilerTimer timing(bUseTimeProfiling); timing.startTotal(); double dbReadingTime = 0.; //store visualize device module name OdString moduleName; try { OdRxSwDatabasePtr pDb = pSwDatabaseSource->getDb(); // reading SW file here if (!pDb.isNull()) { timing.endTotal(); dbReadingTime = timing.getTotalTime() /*+ pSwDatabaseSource->getInitTime()*/; OdTvFilerFeedbackForChooseObject filerFeedbackForChooseObject(OD_T("Choose views for import")); bool bCanceled = false; OdTvFilerFeedbackItemForChooseArray* pFilerFeedbackForChooseArray = filerFeedbackForChooseObject.getFilerFeedbackItemForChooseArrayPtr(); OdString strIndex; strIndex.format(OD_T("%d"), 0); OdTvFilerFeedbackItemForChoose filerFeedbackForChoose(strIndex); pFilerFeedbackForChooseArray->append(filerFeedbackForChoose); if (bCanceled) { if (rc) *rc = tvFilerEmptyInternalDatabase; pDb = NULL; //unload Sw modules (try to emulate the OdUninitialized for SW) //here we will unload all including Visualize device odrxDynamicLinker()->unloadUnreferenced(); return tvDbId; } timing.startTotal(); timing.startVectorizing(); OdGsModulePtr pGs = ::odrxDynamicLinker()->loadModule(OdTvVisualizeDeviceModuleName, false); if (pGs.isNull()) { if (rc) *rc = tvMissingVisualizeDeviceModule; return tvDbId; } //get the palette from the database const ODCOLORREF* refColors = (ODCOLORREF*)(ODRGB(195, 200, 210)); //For the each 'OdSwView' will be created a separate device with a separate model. //More of it, for each view it will used a new Visualize device. At the same time the //TV database will be the same. That's why we will create the tv database outside of the //visualize device. //create empty tv database. OdTvFactoryId tvFactoryId = odTvGetFactory(); tvDbId = tvFactoryId.createDatabase(); OdTvDatabasePtr pTvDb = tvDbId.openObject(OdTv::kForWrite); // save filename to database user data OdTvDatabaseUtils::writeFileNameToTvDatabase(tvDbId, pSwDatabaseSource->getFilename()); //Also there are some objects like material which should be the same for all models. For this //purpose we will use special Visualize device cache //initialize cache and switch it to the "write only" mode ExGsVisualizeDeviceCache deviceCache; deviceCache.m_bApplyCacheData = false; OdSwViewPtr pCurView = pDb->getActiveView(); OdGsDeviceForSwModelPtr pCachedDevice; //get the background color from the model OdSwIModelDocPtr pModel = pDb->get_IActiveDoc(); ODCOLORREF background = (ODCOLORREF)(ODRGB(195, 200, 210)); //create device OdGsDevicePtr pDevice = pGs->createDevice(); OdGiContextForSwDatabasePtr pSwContext = OdGiContextForSwDatabaseToPlotStyleSupport::createObject(); pSwContext->setDatabase(pDb); pSwContext->setView(pCurView); pSwContext->enableGsModel(true); pSwContext->setPaletteBackground(background); OdRxDictionaryPtr pProperties = pDevice->properties(); if (pProperties.get()) { if (pProperties->has(OD_T("DisplayViaGLES2"))) pProperties->putAt(OD_T("DisplayViaGLES2"), OdRxVariantValue(false)); if (pProperties->has(OD_T("AllowNonPersistentObjects"))) pProperties->putAt(OD_T("AllowNonPersistentObjects"), OdRxVariantValue(false)); #if !defined(__APPLE__) if (pProperties->has(OD_T("EnableTiming"))) pProperties->putAt(OD_T("EnableTiming"), OdRxVariantValue(bUseTimeProfiling)); #endif if (pProperties->has(OD_T("TvDatabaseID"))) pProperties->putAt(OD_T("TvDatabaseID"), OdRxVariantValue((OdIntPtr)(&tvDbId))); if (pProperties->has(OD_T("WriteUserData"))) pProperties->putAt(OD_T("WriteUserData"), OdRxVariantValue(m_properties->getStoreSourceObjects())); if (pProperties->has(OD_T("GenerateEntityNames"))) pProperties->putAt(OD_T("GenerateEntityNames"), OdRxVariantValue(m_properties->getObjectNaming())); if (pProperties->has(OD_T("DeviceCache"))) pProperties->putAt(OD_T("DeviceCache"), OdRxVariantValue((OdIntPtr)(&deviceCache))); if (pProperties->has(OD_T("CompareUnnamedImages"))) pProperties->putAt(OD_T("CompareUnnamedImages"), OdRxVariantValue(true)); if (pProperties->has(OD_T("EnableViewDependentEntities"))) pProperties->putAt(OD_T("EnableViewDependentEntities"), OdRxVariantValue(true)); if (pProperties->has(OD_T("ModelName"))) { OdString strModelName; pProperties->putAt(OD_T("ModelName"), OdRxVariantValue(strModelName)); } //Write font file path as user data if (pProperties->has(OD_T("WriteFontFilePath"))) pProperties->putAt(OD_T("WriteFontFilePath"), OdRxVariantValue(true)); //Do not transform layer lineweight if (pProperties->has(OD_T("DisableNonEntityLineweightTransformation"))) pProperties->putAt(OD_T("DisableNonEntityLineweightTransformation"), OdRxVariantValue(true)); } //set the palette and background to the device const ODCOLORREF* palette = (const ODCOLORREF*)m_properties->getPalette(); palette = odcmAcadPalette(background); // black background //set the palette and background to the device OdArray > pPalCpy; pPalCpy.insert(pPalCpy.begin(), palette, palette + 256); pPalCpy[7] = ODRGB(149, 155, 176); // model color pDevice->setLogicalPalette(pPalCpy.asArrayPtr(), 256); pDevice->setBackgroundColor(background); // setup the device and views OdGsDeviceForSwModelPtr pDeviceForSw = OdGsDeviceForSwModel::setupModelView(pModel.get(), pCurView.get(), pDevice, pSwContext); if (pCachedDevice.isNull()) { pCachedDevice = pDeviceForSw; } //call onsize OdTvDCRect* pRect = (OdTvDCRect*)m_properties->getDCRect(); if (pRect && (pRect->xmax > 0 || pRect->xmin > 0 || pRect->ymax > 0 || pRect->ymin > 0)) { OdGsDCRect gsRect(pRect->xmin, pRect->xmax, pRect->ymin, pRect->ymax); pDevice->onSize(gsRect); } //call draw to the Visualize database pDeviceForSw->update(); if (bUseTimeProfiling) { #if !defined(__APPLE__) if (pProperties->has(OD_T("TvElapsedTime"))) { internalTiming += OdRxVariantValue(pProperties->getAt(OD_T("TvElapsedTime")).get())->getDouble(); } #endif } //we should update the state of the device cache marked it to use the cached data during next vectorizing if (pProperties->has(OD_T("DeviceCache"))) { deviceCache.m_bApplyCacheData = true; OdIntPtr ptr = OdRxVariantValue(pProperties->getAt(OD_T("DeviceCache")).get())->getIntPtr(); } externalTiming += timing.getMiscTime(); timing.startMisc(); if (tvDbId.isValid() && m_properties->getClearEmptyObjects()) OdTvDatabaseCleaner::cleanTvDatabase(tvDbId); timing.endMisc(); externalTiming += timing.getMiscTime(); timing.endVectorizing(); } else { if (rc) *rc = tvFilerEmptyInternalDatabase; } } catch (...) { if (rc) *rc = tvInternal; timing.endVectorizing(); } //unload Sw modules (try to emulate the OdUninitialized for SW) //here we will unload all including Visualize device odrxDynamicLinker()->unloadUnreferenced(); timing.endTotal(); if (pProfileRes) { pProfileRes->setImportTime(OdInt64(dbReadingTime * 1000.)); pProfileRes->setVectorizingTime(OdInt64(timing.getVectorizingTime() * 1000.)); #if !defined(__APPLE__) pProfileRes->setTvTime(OdInt64((internalTiming + externalTiming) * 1000.)); #endif } return tvDbId; } OdTvModelId OdTvVisualizeSwFiler::appendFrom(const OdTvDatabaseId& databaseId, OdTvVisualizeSwFilerDbSource *pDgnDatabaseSource, OdTvFilerTimeProfiling* pProfileRes, OdTvResult* rc) const { OdTvModelId tvModelId; return tvModelId; } OdTvGsDeviceId OdTvVisualizeSwFiler::getActiveTvDevice(OdTvDatabaseId& tvDbId, int idDevice) const { return OdTvGsDeviceId(); } OdTvGsViewId OdTvVisualizeSwFiler::getActiveTvView(OdTvGsDeviceId& tvDeviceId, int iActViewViewInd) const { return OdTvGsViewId(); } void OdTvVisualizeSwFiler::createCommonDataAccessTree(OdTvDatabasePtr pTvDb, OdDbBaseDatabase *pDatabase, const OdString& strTreeName) const { } //***************************************************************************// // 'OdTvVisualizeSwFilerModule' methods implementation //***************************************************************************// ODRX_DEFINE_DYNAMIC_MODULE(OdTvVisualizeSwFilerModule); void OdTvVisualizeSwFilerModule::initApp() { // initialize the Visualize odTvInitialize(); } void OdTvVisualizeSwFilerModule::uninitApp() { // Uninitialize the Visualize odTvUninitialize(); } OdTvVisualizeFilerPtr OdTvVisualizeSwFilerModule::getVisualizeFiler() const { OdTvVisualizeFilerPtr pAcisFiler = new OdTvVisualizeSwFiler(); return pAcisFiler; }