0031501: Foundation Classes, Message_Printer - remove theToPutEndl argument -- use...
[occt.git] / src / RWMesh / RWMesh_MaterialMap.cxx
1 // Copyright (c) 2017-2019 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <RWMesh_MaterialMap.hxx>
15
16 #include <Message.hxx>
17 #include <Message_Messenger.hxx>
18 #include <OSD_Directory.hxx>
19 #include <OSD_File.hxx>
20 #include <OSD_Path.hxx>
21 #include <OSD_Protection.hxx>
22 #include <TDataStd_Name.hxx>
23 #include <TDF_Label.hxx>
24
25 // =======================================================================
26 // function : RWMesh_MaterialMap
27 // purpose  :
28 // =======================================================================
29 RWMesh_MaterialMap::RWMesh_MaterialMap (const TCollection_AsciiString& theFile)
30 : myFileName (theFile),
31   myKeyPrefix ("mat_"),
32   myNbMaterials (0),
33   myIsFailed (false),
34   myMatNameAsKey (true)
35 {
36   TCollection_AsciiString aFileName, aFileExt;
37   OSD_Path::FolderAndFileFromPath (theFile, myFolder, aFileName);
38   OSD_Path::FileNameAndExtension (aFileName, myShortFileNameBase, aFileExt);
39 }
40
41 // =======================================================================
42 // function : ~RWMesh_MaterialMap
43 // purpose  :
44 // =======================================================================
45 RWMesh_MaterialMap::~RWMesh_MaterialMap()
46 {
47   //
48 }
49
50 // =======================================================================
51 // function : AddMaterial
52 // purpose  :
53 // =======================================================================
54 TCollection_AsciiString RWMesh_MaterialMap::AddMaterial (const XCAFPrs_Style& theStyle)
55 {
56   if (myStyles.IsBound1 (theStyle))
57   {
58     return myStyles.Find1 (theStyle);
59   }
60
61   TCollection_AsciiString aMatKey, aMatName, aMatNameSuffix;
62   int  aCounter    = 0;
63   int* aCounterPtr = &myNbMaterials;
64   if (myMatNameAsKey)
65   {
66     if (!theStyle.Material().IsNull()
67      && !theStyle.Material()->IsEmpty())
68     {
69       aCounterPtr = &aCounter;
70       Handle(TDataStd_Name) aNodeName;
71       if (!theStyle.Material()->Label().IsNull()
72        &&  theStyle.Material()->Label().FindAttribute (TDataStd_Name::GetID(), aNodeName))
73       {
74         aMatName = aNodeName->Get();
75       }
76       else
77       {
78         aMatName = "mat";
79       }
80       aMatNameSuffix = aMatName;
81     }
82     else
83     {
84       ++myNbMaterials;
85       aMatNameSuffix = myKeyPrefix;
86       aMatName = aMatNameSuffix + myNbMaterials;
87     }
88     aMatKey = aMatName;
89   }
90   else
91   {
92     aMatKey        = myNbMaterials++; // starts from 0
93     aMatNameSuffix = myKeyPrefix;
94     aMatName       = aMatNameSuffix + aMatKey;
95   }
96
97   for (;; ++(*aCounterPtr))
98   {
99     if (myStyles.IsBound2 (aMatKey))
100     {
101       if (myMatNameAsKey)
102       {
103         aMatName = aMatNameSuffix + (*aCounterPtr);
104         aMatKey  = aMatName;
105       }
106       else
107       {
108         aMatKey  = *aCounterPtr;
109         aMatName = aMatNameSuffix + aMatKey;
110       }
111       continue;
112     }
113     break;
114   }
115
116   myStyles.Bind (theStyle, aMatKey);
117   DefineMaterial (theStyle, aMatKey, aMatName);
118   return aMatKey;
119 }
120
121 // =======================================================================
122 // function : copyFileTo
123 // purpose  :
124 // =======================================================================
125 bool RWMesh_MaterialMap::copyFileTo (const TCollection_AsciiString& theFileSrc,
126                                      const TCollection_AsciiString& theFileDst)
127 {
128   if (theFileSrc.IsEmpty()
129    || theFileDst.IsEmpty())
130   {
131     return false;
132   }
133   else if (theFileSrc == theFileDst)
134   {
135     return true;
136   }
137
138   try
139   {
140     OSD_Path aSrcPath (theFileSrc);
141     OSD_Path aDstPath (theFileDst);
142     OSD_File aFileSrc (aSrcPath);
143     if (!aFileSrc.Exists())
144     {
145       Message::SendFail (TCollection_AsciiString("Failed to copy file - source file '") + theFileSrc + "' does not exist");
146       return false;
147     }
148     aFileSrc.Copy (aDstPath);
149     return !aFileSrc.Failed();
150   }
151   catch (Standard_Failure const& theException)
152   {
153     Message::SendFail (TCollection_AsciiString("Failed to copy file\n") + theException.GetMessageString());
154     return false;
155   }
156 }
157
158 // =======================================================================
159 // function : CopyTexture
160 // purpose  :
161 // =======================================================================
162 bool RWMesh_MaterialMap::CopyTexture (TCollection_AsciiString& theResTexture,
163                                       const Handle(Image_Texture)& theTexture,
164                                       const TCollection_AsciiString& theKey)
165 {
166   CreateTextureFolder();
167
168   TCollection_AsciiString aTexFileName;
169   TCollection_AsciiString aTextureSrc = theTexture->FilePath();
170   if (!aTextureSrc.IsEmpty())
171   {
172     TCollection_AsciiString aSrcTexFolder;
173     OSD_Path::FolderAndFileFromPath (aTextureSrc, aSrcTexFolder, aTexFileName);
174     const TCollection_AsciiString aResTexFile = myTexFolder + aTexFileName;
175     theResTexture = myTexFolderShort + aTexFileName;
176     return copyFileTo (aTextureSrc, aResTexFile);
177   }
178
179   TCollection_AsciiString anExt = theTexture->ProbeImageFileFormat();
180   if (anExt.IsEmpty())
181   {
182     anExt = "bin";
183   }
184   aTexFileName = theKey + "." + anExt;
185
186   const TCollection_AsciiString aResTexFile = myTexFolder + aTexFileName;
187   theResTexture = myTexFolderShort + aTexFileName;
188   return theTexture->WriteImage (aResTexFile);
189 }
190
191 // =======================================================================
192 // function : CreateTextureFolder
193 // purpose  :
194 // =======================================================================
195 bool RWMesh_MaterialMap::CreateTextureFolder()
196 {
197   if (!myTexFolder.IsEmpty())
198   {
199     return true;
200   }
201
202   myTexFolderShort = myShortFileNameBase + "_textures/";
203   myTexFolder      = myFolder + "/" + myTexFolderShort;
204   OSD_Path aTexFolderPath (myTexFolder);
205   OSD_Directory aTexDir (aTexFolderPath);
206   if (aTexDir.Exists())
207   {
208     return true;
209   }
210
211   OSD_Path aResFolderPath (myFolder);
212   OSD_Directory aResDir (aResFolderPath);
213   if (!aResDir.Exists())
214   {
215     return false;
216   }
217   const OSD_Protection aParentProt = aResDir.Protection();
218   OSD_Protection aProt = aParentProt;
219   if (aProt.User() == OSD_None)
220   {
221     aProt.SetUser (OSD_RWXD);
222   }
223   if (aProt.System() == OSD_None)
224   {
225     aProt.SetSystem (OSD_RWXD);
226   }
227
228   aTexDir.Build (aProt);
229   if (aTexDir.Failed())
230   {
231     // fallback to the same folder as output model file
232     myTexFolder = myFolder;
233     myTexFolderShort.Clear();
234     return true;
235   }
236   return true;
237 }