// Copyright Epic Games, Inc. All Rights Reserved. #include "TechSoftUtils.h" #include "TUniqueTechSoftObj.h" #include "CADOptions.h" #include "GenericPlatform/GenericPlatformMisc.h" #include "Math/Color.h" #ifndef CADKERNEL_DEV #include "Serialization/JsonSerializer.h" #include "Serialization/JsonWriter.h" #include "TechSoftInterfaceUtils.inl" #endif #include namespace CADLibrary { namespace TechSoftUtils { #ifdef USE_TECHSOFT_SDK TSharedPtr GetJsonObject(A3DAsmProductOccurrence* ProductOcccurence); void RestoreMaterials(const TSharedPtr& DefaultValues, CADLibrary::FBodyMesh& BodyMesh); void SaveModelFileToPrcFile(void* ModelFile, const FString& Filename); A3DUns32 CreateRGBColor(FColor& Color); void SetRootOccurenceAttributes(A3DEntity* Entity); #endif bool GetBodyFromPcrFile(const FString& Filename, const FImportParameters& ImportParameters, FBodyMesh& BodyMesh) { #if defined USE_TECHSOFT_SDK && !defined CADKERNEL_DEV A3DRWParamsPrcReadHelper* ReadHelper = nullptr; FUniqueTechSoftModelFile ModelFile = TechSoftInterface::LoadModelFileFromPrcFile(TCHAR_TO_UTF8(*Filename), &ReadHelper); if (!ModelFile.IsValid()) { return false; } if(ImportParameters.GetStitchingTechnique() != CADLibrary::EStitchingTechnique::StitchingNone) { CADLibrary::TUniqueTSObj SewData; SewData->m_bComputePreferredOpenShellOrientation = false; TechSoftInterface::SewModel(ModelFile.Get(), CADLibrary::FImportParameters::GStitchingTolerance, SewData.GetPtr()); } TUniqueTSObj ModelFileData(ModelFile.Get()); if (!ModelFileData.IsValid() || ModelFileData->m_uiPOccurrencesSize == 0) { return false; } TUniqueTSObj OccurenceData(ModelFileData->m_ppPOccurrences[0]); if (!OccurenceData.IsValid() || !OccurenceData->m_pPart) { return false; } TUniqueTSObj PartDefinitionData(OccurenceData->m_pPart); if (!PartDefinitionData.IsValid() || PartDefinitionData->m_uiRepItemsSize == 0) { return false; } TSharedPtr JsonObject = GetJsonObject(ModelFileData->m_ppPOccurrences[0]); if (JsonObject.IsValid()) { double BodyUnit = 1.0; JsonObject->TryGetNumberField(JSON_ENTRY_BODY_UNIT, BodyUnit); for (A3DUns32 Index = 0; Index < PartDefinitionData->m_uiRepItemsSize; ++Index) { if (!FillBodyMesh(PartDefinitionData->m_ppRepItems[Index], ImportParameters, BodyUnit, BodyMesh)) { return false; } } RestoreMaterials(JsonObject, BodyMesh); return true; } #endif return false; } FUniqueTechSoftModelFile SaveBodiesToPrcFile(void** Bodies, uint32 BodyCount, const FString& Filename, const FString& JsonString) { #if defined USE_TECHSOFT_SDK && !defined CADKERNEL_DEV if (!Bodies) { return FUniqueTechSoftModelFile(); } // Create PartDefinition A3DRiRepresentationItem** RepresentationItems = (A3DRiRepresentationItem**)Bodies; TUniqueTSObj PartDefinitionData; PartDefinitionData->m_uiRepItemsSize = BodyCount; PartDefinitionData->m_ppRepItems = RepresentationItems; A3DAsmPartDefinition* PartDefinition = TechSoftInterface::CreateAsmPartDefinition(*PartDefinitionData); TUniqueTSObj ProductOccurrenceData; ProductOccurrenceData->m_pPart = PartDefinition; A3DAsmProductOccurrence* ProductOccurrence = TechSoftInterface::CreateAsmProductOccurrence(*ProductOccurrenceData); // Add MaterialTable as attribute to ProductOccurrence std::string StringAnsi(TCHAR_TO_UTF8(*JsonString)); TUniqueTSObj SingleAttributeData; SingleAttributeData->m_eType = kA3DModellerAttributeTypeString; SingleAttributeData->m_pcTitle = (char*)"MaterialTable"; SingleAttributeData->m_pcData = (char*)StringAnsi.c_str(); TUniqueTSObj AttributesData; AttributesData->m_pcTitle = SingleAttributeData->m_pcTitle; AttributesData->m_asSingleAttributesData = SingleAttributeData.GetPtr(); AttributesData->m_uiSize = 1; A3DMiscAttribute* Attributes = TechSoftInterface::CreateMiscAttribute(*AttributesData); TUniqueTSObj RootBaseData; RootBaseData->m_pcName = SingleAttributeData->m_pcTitle; RootBaseData->m_ppAttributes = &Attributes; RootBaseData->m_uiSize = 1; TechSoftInterface::SetRootBase(ProductOccurrence, *RootBaseData); // Create ModelFile TUniqueTSObj ModelFileData; ModelFileData->m_uiPOccurrencesSize = 1; ModelFileData->m_dUnit = 1.0; ModelFileData->m_ppPOccurrences = &ProductOccurrence; FUniqueTechSoftModelFile ModelFile = TechSoftInterface::CreateAsmModelFile(*ModelFileData); // Save ModelFile to Pcr file SaveModelFileToPrcFile(ModelFile.Get(), Filename); // #ueent_techsoft: Deleting the model seems to delete the entire content. To be double-checked TechSoftInterface::DeleteEntity(Attributes); return ModelFile; #else return FUniqueTechSoftModelFile(); #endif } bool FillBodyMesh(void* BodyPtr, const FImportParameters& ImportParameters, double BodyUnit, FBodyMesh& BodyMesh) { #if defined USE_TECHSOFT_SDK && !defined CADKERNEL_DEV A3DRiRepresentationItem* RepresentationItemPtr = (A3DRiRepresentationItem*)BodyPtr; A3DEEntityType Type; A3DEntityGetType(RepresentationItemPtr, &Type); if (Type == kA3DTypeRiPolyBrepModel) { TechSoftInterfaceUtils::FTechSoftTessellationExtractor Extractor(RepresentationItemPtr, BodyUnit); return Extractor.FillBodyMesh(BodyMesh); } // TUniqueTechSoftObj does not work in this case TUniqueTSObj TessellationParameters; TessellationParameters->m_eTessellationLevelOfDetail = kA3DTessLODUserDefined; // Enum to specify predefined values for some following members. TessellationParameters->m_bUseHeightInsteadOfRatio = A3D_TRUE; TessellationParameters->m_dMaxChordHeight = ImportParameters.GetChordTolerance(); if (!FMath::IsNearlyZero(BodyUnit)) { TessellationParameters->m_dMaxChordHeight /= BodyUnit; } TessellationParameters->m_dAngleToleranceDeg = ImportParameters.GetMaxNormalAngle(); TessellationParameters->m_dMaximalTriangleEdgeLength = 0; //ImportParameters.MaxEdgeLength; TessellationParameters->m_bAccurateTessellation = A3D_FALSE; // A3D_FALSE' indicates the tessellation is set for visualization TessellationParameters->m_bAccurateTessellationWithGrid = A3D_FALSE; // Enable accurate tessellation with faces inner points on a grid. TessellationParameters->m_dAccurateTessellationWithGridMaximumStitchLength = 0; // Maximal grid stitch length. Disabled if value is 0. Be careful, a too small value can generate a huge tessellation. TessellationParameters->m_bKeepUVPoints = A3D_TRUE; // Keep parametric points as texture points. // Get the tessellation A3DStatus Status = A3DRiRepresentationItemComputeTessellation(RepresentationItemPtr, TessellationParameters.GetPtr()); TUniqueTSObj RepresentationItemData(RepresentationItemPtr); if (!RepresentationItemData.IsValid()) { return false; } { A3DEntityGetType(RepresentationItemData->m_pTessBase, &Type); if (Type != kA3DTypeTess3D) { return false; } } TechSoftInterfaceUtils::FTechSoftTessellationExtractor Extractor(RepresentationItemPtr, BodyUnit); return Extractor.FillBodyMesh(BodyMesh); #else return false; #endif } #if defined USE_TECHSOFT_SDK && !defined CADKERNEL_DEV TSharedPtr GetJsonObject(A3DAsmProductOccurrence* ProductOcccurence) { TUniqueTSObj RootBaseData(ProductOcccurence); if (RootBaseData.IsValid() && RootBaseData->m_uiSize > 0) { TUniqueTSObj AttributeData(RootBaseData->m_ppAttributes[0]); if (AttributeData->m_uiSize > 0 && AttributeData->m_asSingleAttributesData[0].m_eType == kA3DModellerAttributeTypeString) { FString JsonString = UTF8_TO_TCHAR(AttributeData->m_asSingleAttributesData[0].m_pcData); TSharedRef> JsonReader = TJsonReaderFactory<>::Create(JsonString); TSharedPtr JsonObject; if (FJsonSerializer::Deserialize(JsonReader, JsonObject)) { return JsonObject; } } } return {}; } // Replicate logic in FTechSoftFileParser::FindOrAddMaterial and the methods it calls void BuildCADMaterial(uint32 MaterialIndex, const A3DGraphStyleData& GraphStyleData, FCADMaterial& Material) { if (TechSoftInterface::IsMaterialTexture(MaterialIndex)) { TUniqueTSObjFromIndex TextureData(MaterialIndex); if (TextureData.IsValid()) { MaterialIndex = TextureData->m_uiMaterialIndex; } } TUniqueTSObjFromIndex MaterialData(MaterialIndex); if (MaterialData.IsValid()) { Material.Diffuse = GetColorAt(MaterialData->m_uiDiffuse); Material.Ambient = GetColorAt(MaterialData->m_uiAmbient); Material.Specular = GetColorAt(MaterialData->m_uiSpecular); Material.Shininess = MaterialData->m_dShininess; if (GraphStyleData.m_bIsTransparencyDefined) { Material.Transparency = 1. - GraphStyleData.m_ucTransparency / 255.; } // todo: find how to convert Emissive color into ? reflexion coef... // Material.Emissive = GetColor(MaterialData->m_uiEmissive); // Material.Reflexion; } } #endif // Replicates the logic in FTechSoftFileParser::ExtractGraphStyleProperties void GetMaterialValues(uint32 StyleIndex, FMaterialUId& OutColorName, FMaterialUId& OutMaterialName) { #if defined USE_TECHSOFT_SDK && !defined CADKERNEL_DEV TUniqueTSObjFromIndex GraphStyleData(StyleIndex); if (GraphStyleData.IsValid()) { if (GraphStyleData->m_bMaterial) { FCADMaterial Material; BuildCADMaterial(GraphStyleData->m_uiRgbColorIndex, *GraphStyleData, Material); OutMaterialName = BuildMaterialUId(Material); } else { TUniqueTSObjFromIndex ColorData(GraphStyleData->m_uiRgbColorIndex); if (ColorData.IsValid()) { // Alpha == Opacity == (255 - Transparency) const uint8 Alpha = GraphStyleData->m_bIsTransparencyDefined ? (255 - GraphStyleData->m_ucTransparency) : 255; const FColor ColorValue((uint8)(ColorData->m_dRed * 255), (uint8)(ColorData->m_dGreen * 255), (uint8)(ColorData->m_dBlue * 255), Alpha); OutColorName = BuildColorUId(ColorValue); } } } #endif } void RestoreMaterials(const TSharedPtr& DefaultValues, FBodyMesh& BodyMesh) { FMaterialUId DefaultColorName = 0; FMaterialUId DefaultMaterialName = 0; #ifndef CADKERNEL_DEV DefaultValues->TryGetNumberField(JSON_ENTRY_COLOR_NAME, DefaultColorName); DefaultValues->TryGetNumberField(JSON_ENTRY_MATERIAL_NAME, DefaultMaterialName); #endif BodyMesh.MaterialSet.Empty(); BodyMesh.ColorSet.Empty(); for (FTessellationData& Tessellation : BodyMesh.Faces) { // Extract proper color or material based on style index uint32 CachedStyleIndex = Tessellation.MaterialUId; Tessellation.MaterialUId = 0; FMaterialUId ColorUId = DefaultColorName; FMaterialUId MaterialUId = DefaultMaterialName; GetMaterialValues(CachedStyleIndex, ColorUId, MaterialUId); if (ColorUId) { Tessellation.ColorUId = ColorUId; BodyMesh.ColorSet.Add(ColorUId); } if (MaterialUId) { Tessellation.MaterialUId = MaterialUId; BodyMesh.MaterialSet.Add(MaterialUId); } } } FColor GetColorAt(uint32 ColorIndex) { #if defined USE_TECHSOFT_SDK && !defined CADKERNEL_DEV TUniqueTSObjFromIndex ColorData(ColorIndex); if (ColorData.IsValid()) { return FColor((uint8)(ColorData->m_dRed * 255) , (uint8)(ColorData->m_dGreen * 255) , (uint8)(ColorData->m_dBlue * 255)); } #endif return FColor(200, 200, 200); } void SaveModelFileToPrcFile(void* ModelFile, const FString& Filename) { #if defined USE_TECHSOFT_SDK && !defined CADKERNEL_DEV TUniqueTSObj ParamsExportData; ParamsExportData->m_bCompressBrep = false; ParamsExportData->m_bCompressTessellation = false; #if PLATFORM_WINDOWS A3DUTF8Char HsfFileName[MAX_PATH]; FCStringAnsi::Strncpy(HsfFileName, TCHAR_TO_UTF8(*Filename), MAX_PATH); #elif PLATFORM_LINUX A3DUTF8Char HsfFileName[PATH_MAX]; FCStringAnsi::Strncpy(HsfFileName, TCHAR_TO_UTF8(*Filename), PATH_MAX); #else #error Platform not supported #endif // PLATFORM_WINDOWS TechSoftInterface::ExportModelFileToPrcFile(ModelFile, ParamsExportData.GetPtr(), HsfFileName, nullptr); #endif } #if defined USE_TECHSOFT_SDK && !defined CADKERNEL_DEV A3DUns32 CreateRGBColor(FColor& Color) { TUniqueTSObjFromIndex RgbColor; RgbColor->m_dRed = Color.R / 255.; RgbColor->m_dGreen = Color.G / 255.; RgbColor->m_dBlue = Color.B / 255.; return TechSoftInterface::InsertGraphRgbColor(*RgbColor); } int32 SetEntityGraphicsColor(A3DEntity* InEntity, FColor Color) { TUniqueTSObj BaseWithGraphicsData(InEntity); //Create a style color A3DUns32 ColorIndex = CreateRGBColor(Color); A3DUns32 StyleIndex = 0; TUniqueTSObjFromIndex StyleData; StyleData->m_bMaterial = false; StyleData->m_bVPicture = false; StyleData->m_dWidth = 0.1; // default A3DUns8 Alpha = Color.A; if (Alpha < 255) { StyleData->m_bIsTransparencyDefined = true; StyleData->m_ucTransparency = 255 - Alpha; } else { StyleData->m_bIsTransparencyDefined = false; StyleData->m_ucTransparency = 0; } StyleData->m_bSpecialCulling = false; StyleData->m_bBackCulling = false; StyleData->m_uiRgbColorIndex = ColorIndex; StyleIndex = TechSoftInterface::InsertGraphStyle(*StyleData); TUniqueTSObj GraphicsData; GraphicsData->m_uiStyleIndex = StyleIndex; GraphicsData->m_usBehaviour = kA3DGraphicsShow; GraphicsData->m_usBehaviour |= kA3DGraphicsSonHeritColor; BaseWithGraphicsData->m_pGraphics = TechSoftInterface::CreateGraphics(*GraphicsData); if (BaseWithGraphicsData->m_pGraphics == nullptr) { return A3DStatus::A3D_ERROR; } return TechSoftInterface::SetRootBaseWithGraphics(*BaseWithGraphicsData, InEntity); } void SetRootOccurenceAttributes(A3DEntity* Entity) { A3DMiscAttribute* Attributes[3]; TUniqueTSObj Single; Single->m_eType = kA3DModellerAttributeTypeString; TUniqueTSObj AttributeData; AttributeData->m_asSingleAttributesData = Single.GetPtr(); AttributeData->m_uiSize = 1; Single->m_pcTitle = (char*)"Title"; Single->m_pcData = (char*)"Body model"; AttributeData->m_pcTitle = Single->m_pcTitle; Attributes[0] = TechSoftInterface::CreateMiscAttribute(*AttributeData); Single->m_pcTitle = (char*)"Author"; Single->m_pcData = (char*)"Unreal Engine"; AttributeData->m_pcTitle = Single->m_pcTitle; Attributes[1] = TechSoftInterface::CreateMiscAttribute(*AttributeData); Single->m_pcTitle = (char*)"Company"; Single->m_pcData = (char*)"Epic Games"; AttributeData->m_pcTitle = Single->m_pcTitle; Attributes[2] = TechSoftInterface::CreateMiscAttribute(*AttributeData); TUniqueTSObj RootData; RootData->m_pcName = (char*)"Body model"; RootData->m_ppAttributes = Attributes; RootData->m_uiSize = 3; TechSoftInterface::SetRootBase(Entity, *RootData); for (A3DUns32 i = 0; i < RootData->m_uiSize; ++i) { TechSoftInterface::DeleteEntity(Attributes[i]); } } A3DAsmModelFile* CreateModelFile(A3DAsmProductOccurrence* Occurrence) { if (Occurrence != NULL) { return nullptr; } CADLibrary::TUniqueTSObj ModelFileData; // In this model there will be only one product occurrence ModelFileData->m_uiPOccurrencesSize = 1; ModelFileData->m_dUnit = 1.0; ModelFileData->m_ppPOccurrences = &Occurrence; return TechSoftInterface::CreateModelFile(*ModelFileData); } A3DAsmProductOccurrence* CreateOccurrence(A3DAsmPartDefinition* Part) { if (Part == nullptr) { return nullptr; } TUniqueTSObj ProductOccurrenceData; ProductOccurrenceData->m_pPart = Part; A3DAsmProductOccurrence* ProductOccurrencePtr = TechSoftInterface::CreateAsmProductOccurrence(*ProductOccurrenceData); if (ProductOccurrencePtr != nullptr) { SetRootOccurenceAttributes(ProductOccurrencePtr); } return ProductOccurrencePtr; } A3DAsmPartDefinition* CreatePart(TArray& RepresentationItems) { if (RepresentationItems.IsEmpty()) { return nullptr; } TUniqueTSObj PartDefinitionData; PartDefinitionData->m_uiRepItemsSize = RepresentationItems.Num(); PartDefinitionData->m_ppRepItems = RepresentationItems.GetData(); return TechSoftInterface::CreateAsmPartDefinition(*PartDefinitionData); } A3DRiRepresentationItem* CreateRIBRep(A3DTopoShell* TopoShellPtr) { if (TopoShellPtr == nullptr) { return nullptr; } A3DTopoConnex* TopoConnexPtr = nullptr; { CADLibrary::TUniqueTSObj TopoConnexData; TopoConnexData->m_ppShells = &TopoShellPtr; TopoConnexData->m_uiShellSize = 1; TopoConnexPtr = TechSoftInterface::CreateTopoConnex(*TopoConnexData); if (TopoConnexPtr == nullptr) { return nullptr; } } A3DTopoBrepData* TopoBRepPtr = nullptr; { CADLibrary::TUniqueTSObj TopoBRepData; TopoBRepData->m_uiConnexSize = 1; TopoBRepData->m_ppConnexes = &TopoConnexPtr; TopoBRepPtr = TechSoftInterface::CreateTopoBRep(*TopoBRepData); if (TopoBRepPtr == nullptr) { return nullptr; } } CADLibrary::TUniqueTSObj RiBRepModelData; RiBRepModelData->m_pBrepData = TopoBRepPtr; RiBRepModelData->m_bSolid = false; return TechSoftInterface::CreateRiBRepModel(*RiBRepModelData); } A3DTopoEdge* CreateTopoEdge() { CADLibrary::TUniqueTSObj EdgeData; return TechSoftInterface::CreateTopoEdge(*EdgeData); } A3DTopoFace* CreateTopoFaceWithNaturalLoop(A3DSurfBase* CarrierSurface) { CADLibrary::TUniqueTSObj Face; Face->m_pSurface = CarrierSurface; Face->m_bHasTrimDomain = false; Face->m_ppLoops = nullptr; Face->m_uiLoopSize = 0; Face->m_uiOuterLoopIndex = 0; Face->m_dTolerance = 0.01; //mm return CADLibrary::TechSoftInterface::CreateTopoFace(*Face); } A3DCrvNurbs* CreateTrimNurbsCurve(A3DCrvNurbs* CurveNurbsPtr, double UMin, double UMax, bool bIs2D) { if (CurveNurbsPtr == nullptr) { return nullptr; } TUniqueTSObj TransformCurveData; TransformCurveData->m_bIs2D = bIs2D; TransformCurveData->m_sParam.m_sInterval.m_dMin = UMin; TransformCurveData->m_sParam.m_sInterval.m_dMax = UMax; TransformCurveData->m_sParam.m_dCoeffA = 1.; TransformCurveData->m_sParam.m_dCoeffB = 0.; TransformCurveData->m_pBasisCrv = CurveNurbsPtr; TransformCurveData->m_pTransfo = nullptr; TransformCurveData->m_sTrsf.m_sXVector.m_dX = 1.; TransformCurveData->m_sTrsf.m_sYVector.m_dY = 1.; TransformCurveData->m_sTrsf.m_sScale.m_dX = 1.; TransformCurveData->m_sTrsf.m_sScale.m_dY = 1.; TransformCurveData->m_sTrsf.m_sScale.m_dZ = 1.; A3DCrvTransform* CurveTransformPtr = CADLibrary::TechSoftInterface::CreateCurveTransform(*TransformCurveData); if (CurveTransformPtr == nullptr) { return nullptr; } TUniqueTSObj TransformedNurbsData; if (CADLibrary::TechSoftInterface::GetCurveAsNurbs(CurveTransformPtr, &*TransformedNurbsData, 0.01 /*mm*/, /*bUseSameParameterization*/ true) != A3DStatus::A3D_SUCCESS) { return nullptr; } return CADLibrary::TechSoftInterface::CreateCurveNurbs(*TransformedNurbsData); } #endif #ifdef USE_TECHSOFT_SDK void ExtractAttribute(const A3DMiscAttributeData& AttributeData, TMap& OutMetaData) { FString AttributeName; if (AttributeData.m_bTitleIsInt) { A3DUns32 UnsignedValue = 0; memcpy(&UnsignedValue, AttributeData.m_pcTitle, sizeof(A3DUns32)); AttributeName = FString::Printf(TEXT("%u"), UnsignedValue); } else if (AttributeData.m_pcTitle && AttributeData.m_pcTitle[0] != '\0') { AttributeName = UTF8_TO_TCHAR(AttributeData.m_pcTitle); } for (A3DUns32 Index = 0; Index < AttributeData.m_uiSize; ++Index) { FString AttributeValue; switch (AttributeData.m_asSingleAttributesData[Index].m_eType) { case kA3DModellerAttributeTypeTime: case kA3DModellerAttributeTypeInt: { A3DInt32 Value = *reinterpret_cast(AttributeData.m_asSingleAttributesData[Index].m_pcData); AttributeValue = FString::Printf(TEXT("%d"), Value); break; } case kA3DModellerAttributeTypeReal: { A3DDouble Value = *reinterpret_cast(AttributeData.m_asSingleAttributesData[Index].m_pcData); AttributeValue = FString::Printf(TEXT("%f"), Value); break; } case kA3DModellerAttributeTypeString: { if (AttributeData.m_asSingleAttributesData[Index].m_pcData && AttributeData.m_asSingleAttributesData[Index].m_pcData[0] != '\0') { AttributeValue = UTF8_TO_TCHAR(AttributeData.m_asSingleAttributesData[Index].m_pcData); } break; } default: break; } if (AttributeName.Len()) { if (Index) { OutMetaData.Emplace(FString::Printf(TEXT("%s_%u"), *AttributeName, (int32)Index), AttributeValue); } else { OutMetaData.Emplace(AttributeName, AttributeValue); } } } } #endif FString CleanLabel(const FString& Name) { int32 Index; if (Name.FindLastChar(TEXT('['), Index)) { return Name.Left(Index); } return Name; } FString CleanCatiaInstanceLabel(const FString& Name) { int32 Index; if (Name.FindChar(TEXT('('), Index)) { FString NewName = Name.RightChop(Index + 1); if (NewName.FindLastChar(TEXT(')'), Index)) { NewName = NewName.Left(Index); } return NewName; } return Name; } FString Clean3dxmlInstanceLabel(const FString& Name) { FString NewName = CleanCatiaInstanceLabel(Name); int32 Index = NewName.Find(TEXT("_InstanceRep")); if (Index != INDEX_NONE) { NewName = NewName.Left(Index); } return NewName; } FString Clean3dxmlReferenceLabel(const FString& Name) { int32 Index; if (Name.FindChar(TEXT('('), Index)) { FString NewName = Name.Left(Index); return NewName; } Index = Name.Find(TEXT("_InstanceRep")); if (Index != INDEX_NONE) { FString NewName = Name.Left(Index); return NewName; } return Name; } FString CleanSwInstanceLabel(const FString& Name) { int32 Position; if (Name.FindLastChar(TEXT('-'), Position)) { FString NewName = Name.Left(Position) + TEXT("<") + Name.RightChop(Position + 1) + TEXT(">"); return NewName; } return Name; } FString CleanSwReferenceLabel(const FString& Name) { int32 Position; if (Name.FindLastChar(TEXT('-'), Position)) { FString NewName = Name.Left(Position); return NewName; } return Name; } FString CleanCatiaReferenceLabel(const FString& Name) { int32 Position; if (Name.FindLastChar(TEXT('.'), Position)) { FString Indice = Name.RightChop(Position + 1); if (Indice.IsNumeric()) { FString NewName = Name.Left(Position); return NewName; } } return Name; } FString CleanCreoLabel(const FString& Name) { int32 Position; if (Name.FindLastChar(TEXT('.'), Position)) { FString Extension = Name.RightChop(Position); if (Extension.Equals(TEXT("prt"), ESearchCase::IgnoreCase)) { FString NewName = Name.Left(Position); return NewName; } } return Name; } } // NS TechSoftUtils } // NS CADLibrary