1import os
2
3from pyfbsdk import *
4from pyfbsdk_additions import *
5
6try:
7 from PySide6 import QtCore, QtWidgets
8except:
9 from PySide2 import QtCore, QtWidgets
10from ReferencingSampleUI2 import Ui_ReferencingSample
11
12import NamespaceTableModel
13
14
17def PickRefName():
18 lFileRefName = ''
19 lBtnClicked, lFileRefName =
FBMessageBoxGetUserValue(
'File Reference',
'Enter your file reference name',
'', FBPopupInputType.kFBPopupString,
'OK',
'Cancel',
None, 1,
True )
20 if lBtnClicked == 2: return lBtnClicked, lFileRefName
21
22 lFileRefName = lFileRefName.replace(' ','')
23 while lFileRefName == '':
24 FBMessageBox(
'File Reference',
'Error, please enter a file reference name',
"OK")
25 lBtnClicked, lFileRefName = PickRefName()
26 if lBtnClicked == 2: break
27
28 return lBtnClicked, lFileRefName
29
30class MainForm( QtWidgets.QWidget, Ui_ReferencingSample ):
31 def __init__( self, parent ):
32 super().__init__(parent)
33
34 self.setupUi( self )
35
36 import inspect
37 self.mDefaultPath = inspect.currentframe().f_code.co_filename
38 self.mSingleSelection = False
39
42 self.mApp.OnFileNew.Add( self.OnFileNew )
43
44 self.mNSModel = NamespaceTableModel.NamespaceTableModel( self )
45 self.uiTableNamespace.setModel( self.mNSModel )
46
47 self.mTimer = QtCore.QTimer( self )
48
49 self.mIsInitialized = False
50 self.Init()
51
52 def Init( self ):
53 self.mNSModel.namespaceRenamed.connect( self.OnNamespaceRenamed )
54
55 lSelectionModel = self.uiTableNamespace.selectionModel()
56 QtCore.QObject.connect( lSelectionModel, QtCore.SIGNAL( 'selectionChanged(const QItemSelection&, const QItemSelection&)' ), self.OnTableNamespaceSelectionChanged )
57
58 QtCore.QObject.connect( self.mTimer, QtCore.SIGNAL( 'timeout()' ), self.OnTimer )
59 self.mTimer.start( 2000 )
60 self.UpdateUI()
61
62 self.mIsInitialized = True
63
64 def Fini( self ):
65
66 self.mTimer.stop()
67 QtCore.QObject.disconnect( self.mTimer, QtCore.SIGNAL( 'timeout()' ), self.OnTimer )
68
69
70 lSelectionModel = self.uiTableNamespace.selectionModel()
71 QtCore.QObject.disconnect( lSelectionModel, QtCore.SIGNAL( 'selectionChanged(const QItemSelection&, const QItemSelection&)' ), self.OnTableNamespaceSelectionChanged )
72
73 self.mNSModel.namespaceRenamed.disconnect( self.OnNamespaceRenamed )
74
75 self.mIsInitialized = False
76
77 def OnShow( self ):
78 if not self.mIsInitialized:
79 self.Init()
80 self.mNSModel.Connect()
81
82 def OnHide( self ):
83 if self.mIsInitialized:
84 self.Fini()
85 self.mNSModel.Disconnect()
86
87 def OnFileNew( self, pControl, pEvent ):
88 self.mNSModel.Fini()
89 self.mNSModel.Init()
90
91 def OnNamespaceRenamed( self, pOldName, pNewName ):
92 self.UpdateTreeNamespace()
93
94 def OnBtnBrowsePathClicked( self ):
95 lFileToLoad = QtWidgets.QFileDialog.getOpenFileName(self, "Pick FBX to reference", self.mDefaultPath, "*.fbx" )[0]
96 lQFileInfo = QtCore.QFileInfo( lFileToLoad )
97 if lQFileInfo.exists() and lQFileInfo.suffix() == 'fbx':
98 self.uiEditFilePath.setText( lFileToLoad )
99 self.mDefaultPath = lQFileInfo.filePath()
100 self.UpdateUI()
101
102 def OnBtnLoadClicked( self ):
103 print('Load as a file reference')
104
105 lLoadCount = self.uiSpinLoadTimes.value()
106 lBtnClicked, lName = PickRefName()
107 if lBtnClicked == 2: return
108
110 if lLoadCount == 1:
111 lNameList.Add( lName )
112 else:
113 for lCount in range( 0, lLoadCount ):
114 if self.mSys.Scene.NamespaceGet( lName +
str(lCount+1) ) !=
None:
115 lMsgBox = QtWidgets.QMessageBox( QtWidgets.QMessageBox.Information,
'Loading',
'Creation of file reference %s will be skipped as it is already there.' % ( lName +
str(lCount+1) ), QtWidgets.QMessageBox.Ok, self )
116 lMsgBox.exec_()
117 else:
118 lNameList.Add( lName +
str(lCount+1) )
119
120 self.mSys.Scene.NamespaceImportToMultiple( lNameList,
str(self.uiEditFilePath.text()),
True )
121 self.mNSModel.Refresh()
122 self.UpdateUI()
123
124 def OnBtnUnloadClicked( self ):
125 lIndexes = self.uiTableNamespace.selectedIndexes()
126 for lIndex in lIndexes:
127 if lIndex.column() == 0:
128 lNSObj = self.mSys.Scene.Namespaces[lIndex.row()]
129 self.mNSModel.RemoveFileFromWatcher( lNSObj )
130 lNSObj.IsLoaded = False
131
132 self.mNSModel.Refresh( lIndex )
133 self.UpdateUI()
134 self.UpdateTreeNamespace()
135
136 def OnBtnReloadClicked( self ):
137 lIndexes = self.uiTableNamespace.selectedIndexes()
138 for lIndex in lIndexes:
139 if lIndex.column() == 0:
140 lNSObj = self.mSys.Scene.Namespaces[lIndex.row()]
141 lNSObj.IsLoaded = True
142 self.mNSModel.Refresh( lIndex )
143 self.UpdateUI()
144 self.UpdateTreeNamespace()
145
146 def OnBtnDeleteClicked( self ):
147 lIndexes = self.uiTableNamespace.selectedIndexes()
148 lNameList = []
149 for lIndex in lIndexes:
150 if lIndex.column() == 0:
151 lNSObj = self.mSys.Scene.Namespaces[lIndex.row()]
152 lNameList.append( lNSObj.LongName )
153 self.mNSModel.RemoveFileFromWatcher( lNSObj )
154
155 for lName in lNameList:
156 self.mSys.Scene.NamespaceDelete( lName )
157
158 self.mNSModel.Refresh()
159 self.UpdateUI()
160 self.UpdateTreeNamespace()
161
162 def OnBtnInstanceClicked( self ):
163 lIndexes = self.uiTableNamespace.selectedIndexes()
164 for lIndex in lIndexes:
165 if lIndex.column() == 0:
166 lNSObj = self.mSys.Scene.Namespaces[lIndex.row()]
167
168 lInstanceCount = self.uiSpinInstanceTimes.value()
169 lBtnClicked, lName = PickRefName()
170 if lBtnClicked == 2: return
171
173 if lInstanceCount == 1:
174 lNameList.Add( lName )
175 else:
176 for lCount in range( 0, lInstanceCount ):
177 lNameList.Add( lName +
str(lCount+1) )
178
179 lApplyRefEdits = False
180 if lNSObj.GetContentModified( FBPlugModificationFlag.kFBContentAllModifiedMask ):
181 lMsgBox = QtWidgets.QMessageBox( QtWidgets.QMessageBox.Question, 'Instancing', 'Do you want to apply reference edits after instancing?', QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, self )
182 if lMsgBox.exec_() == QtWidgets.QMessageBox.Yes:
183 lApplyRefEdits = True
184
185 lNSObj.DuplicateFileRef( lNameList, lApplyRefEdits )
186
187 self.mNSModel.Refresh()
188 self.UpdateUI()
189 self.UpdateTreeNamespace()
190
191 def OnBtnRestoreClicked( self ):
192 lIndexes = self.uiTableNamespace.selectedIndexes()
193 for lIndex in lIndexes:
194 if lIndex.column() == 0:
195 lNSObj = self.mSys.Scene.Namespaces[lIndex.row()]
196 lNSObj.RevertRefEdit()
197 self.mNSModel.Refresh( lIndex )
198 self.UpdateUI()
199
200 def OnBtnShowEditsClicked( self ):
201 lIndexes = self.uiTableNamespace.selectedIndexes()
202 for lIndex in lIndexes:
203 if lIndex.column() == 0:
204 lNSObj = self.mSys.Scene.Namespaces[lIndex.row()]
205 if lNSObj.GetContentModified( FBPlugModificationFlag.kFBContentAllModifiedMask ):
206 lMsgBox = QtWidgets.QMessageBox( self )
207 lMsgBox.setText( lNSObj.GetRefEdit() )
208 lMsgBox.exec_()
209
210 def OnTableNamespaceSelectionChanged( self, pSelected, pUnselected ):
211 self.UpdateUI()
212 self.UpdateTreeNamespace()
213
214 def UpdateTreeNamespace( self ):
215 self.uiTreeNamespace.clear()
216
217 if self.mSingleSelection:
218 lIndexes = self.uiTableNamespace.selectedIndexes()
219 lNSObj = self.mSys.Scene.Namespaces[lIndexes[0].row()]
220
221 lStrList = [lNSObj.LongName]
222 if lNSObj.ClassGroupName != '':
223 lStrList.append( lNSObj.ClassGroupName )
224
225 lItem = QtWidgets.QTreeWidgetItem( lStrList )
226 self.uiTreeNamespace.addTopLevelItem( lItem )
227 self.UpdateTreeNamespaceRecursively( lItem, lNSObj )
228 self.uiTreeNamespace.expandItem( lItem )
229
230 def UpdateTreeNamespaceRecursively( self, pParentItem, pNSObj ):
231 lList = FBComponentList()
232 pNSObj.GetContentList( lList, FBPlugModificationFlag.kFBPlugAllContent, False )
233 for lPlug in lList:
234 lStrList = [lPlug.LongName]
235 if lPlug.ClassGroupName != '':
236 lStrList.append( lPlug.ClassGroupName )
237
238 lItem = QtWidgets.QTreeWidgetItem( lStrList )
239 pParentItem.addChild( lItem )
240 self.uiTreeNamespace.expandItem( lItem )
241 if lPlug.TypeInfo == FBNamespace.TypeInfo:
242 self.UpdateTreeNamespaceRecursively( lItem, lPlug )
243
244
245
246
247
248
249
250
251
252
253
254 def UpdateUI( self ):
255 luiBtnBrowsePath = True
256 luiBtnLoad = False
257 luiSpinLoadTimes = False
258 luiBtnUnload = False
259 luiBtnReload = False
260 luiBtnDelete = False
261 luiBtnInstance = False
262 luiBtnRestore = False
263 luiBtnShowEdits = False
264 luiSpinInstanceTimes = False
265
266 if os.path.exists( self.uiEditFilePath.text() ):
267 luiBtnLoad = True
268 luiSpinLoadTimes = True
269
270
271
272
273 lIndexes = self.uiTableNamespace.selectedIndexes()
274
275 lRows = []
276 lHasSelection = False
277 if len( lIndexes ) > 0:
278 lHasSelection = True
279
280 lAllSelectionFileReference = True
281 lAllSelectionLoaded = True
282 lAllSelectionUnLoaded = True
283 lSelectionHasRefEdits = False
284 for lIndex in lIndexes:
285 if lIndex.column() == 0:
286 lRows.append( lIndex.row() )
287 lNSObj = self.mSys.Scene.Namespaces[lIndex.row()]
288 if lNSObj.TypeInfo == FBNamespace.TypeInfo:
289 lAllSelectionFileReference = False
290 else:
291 if lNSObj.IsLoaded:
292 if lNSObj.GetContentModified( FBPlugModificationFlag.kFBContentAllModifiedMask ):
293 lSelectionHasRefEdits = True
294 lAllSelectionUnLoaded = False
295 else:
296 lAllSelectionLoaded = False
297
298 self.mSingleSelection = False
299 if len( lRows ) == 1:
300 self.mSingleSelection = True
301
302 if lHasSelection:
303 luiBtnDelete = True
304
305 if lAllSelectionFileReference:
306 if lSelectionHasRefEdits:
307 luiBtnRestore = True
308
309 if self.mSingleSelection:
310 if lSelectionHasRefEdits:
311 luiBtnShowEdits = True
312 luiBtnInstance = True
313 luiSpinInstanceTimes = True
314
315 luiBtnUnload = True
316 luiBtnReload = True
317 if lAllSelectionLoaded:
318 luiBtnReload = False
319 if lAllSelectionUnLoaded:
320 luiBtnUnload = False
321
322 self.uiBtnBrowsePath.setEnabled( luiBtnBrowsePath )
323 self.uiBtnLoad.setEnabled( luiBtnLoad )
324 self.uiSpinLoadTimes.setEnabled( luiSpinLoadTimes )
325 self.uiBtnUnload.setEnabled( luiBtnUnload )
326 self.uiBtnReload.setEnabled( luiBtnReload )
327 self.uiBtnDelete.setEnabled( luiBtnDelete )
328 self.uiBtnInstance.setEnabled( luiBtnInstance )
329 self.uiBtnRestore.setEnabled( luiBtnRestore )
330 self.uiBtnShowEdits.setEnabled( luiBtnShowEdits )
331 self.uiSpinInstanceTimes.setEnabled( luiSpinInstanceTimes )
332
333 def OnTimer( self ):
334 for lFilePath, lReload in self.mNSModel.mRefFileReload.items():
335 if lReload:
336 FBMessageBox(
"External File Changed",
"The referenced file '%s' has been changed externally!" % ( lFilePath ),
"OK" )
337 if lFilePath in self.mNSModel.mRefFilePath:
338 for lFileRefName in self.mNSModel.mRefFilePath[lFilePath]:
340 lOption =
FBMessageBox(
"External File Changed",
"Please choose the following action for Reference: %s!" % ( lFileRefName ),
"Load",
"Merge",
"Ignore" )
341 if lOption != 3:
343 lUndo.Clear()
344 lFileRefObj.IsLoaded = False
345 lFileRefObj.IsLoaded = True
346
347 if lOption == 2:
348 if lFileRefObj.GetContentModified( FBPlugModificationFlag.kFBContentAllModifiedMask ):
349 lFileRefObj.ApplyRefEditPyScriptFromString( lFileRefObj.GetRefEdit() )
350
351 self.mNSModel.mRefFileReload[lFilePath] = False
352
353 self.mNSModel.UpdateFileWatcher()
FBApplication is used mainly to manage files.
Definition: pyfbsdk_generated.h:801
String list.
Definition: pyfbsdk_generated.h:18526
Provides access to the underlying system, and the MotionBuilder scene.
Definition: pyfbsdk_generated.h:18773
Access to global undo and redo functionality.
Definition: pyfbsdk_generated.h:20536
Python built-in string class.
Definition: pyfbsdk.h:77
tuple< int, str > FBMessageBoxGetUserValue(str pBoxTitle, str pMessage, object pValue, FBPopupInputType pValueType, str pButton1Str, str pButton2Str=None, str pButton3Str=None, int pDefaultButton=0)
Dialog popup box to get user input.
int FBMessageBox(str pBoxTitle, str pMessage, str pButton1Str, str pButton2Str=None, str pButton3Str=None, int pDefaultButton=0, int pScrolledMessage=0)
Dialog popup box.
FBComponent FBFindObjectByFullName(str pObjectFullName)
FBFindObjectByFullName.