ComplexTools/ActionScriptMgr.py

ComplexTools/ActionScriptMgr.py
1 # Copyright 2009 Autodesk, Inc. All rights reserved.
2 # Use of this software is subject to the terms of the Autodesk license agreement
3 # provided at the time of installation or download, or which otherwise accompanies
4 # this software in either electronic or hard copy form.
5 #
6 # Script description:
7 # Allow edition of MoBu ActionScript.txt that maps a Python action to a script. To change
8 # the shortcut that is mapped to an action use the KeyboardMapper.py script (or edit
9 # a keyboard file).
10 #
11 # Topic: FBConfigFile, FBSpread, FBConfigFile
12 #
13 
14 from pyfbsdk import *
15 from pyfbsdk_additions import *
16 
17 import os
18 import os.path
19 import mbutils
20 
21 TOOL_NAME = "Action Script Manager"
22 ACTION_SCRIPT_PATH = os.path.join(mbutils.GetConfigPath(), "Scripts")
23 ACTION_SCRIPT_FILE = os.path.join(ACTION_SCRIPT_PATH, "ActionScript.txt")
24 
25 class ActionScriptMgr(FBTool):
26  def RowClicked(self,control,event):
27  # Populate path edit box
28  if self.path_spread.GetRow(event.Row).RowSelected:
29  self.current_row = event.Row
30  else:
31  self.current_row = -1
32  path = self.path_spread.GetCellValue(event.Row, 0)
33 
34  # Do not update the path edit if the selected row has no path. It makes
35  # path manipulation easier
36  if path:
37  self.path_edit.Text = path
38 
39  def Browse(self,control,event):
40  filepopup = pyfbsdk.FBFilePopup()
41  filepopup.Caption = "Select a script"
42  filepopup.Style = pyfbsdk.FBFilePopupStyle.kFBFilePopupOpen
43  filepopup.Filter = "*.py"
44  result = filepopup.Execute()
45  if result:
46  self.path_edit.Text = os.path.join(filepopup.Path,filepopup.FileName)
47  del filepopup
48 
49  def Add(self,control,event):
50  if self.current_row == -1:
51  return
52  self.path_spread.SetCellValue(self.current_row,0,self.path_edit.Text)
53  self.UpdateScript(self.current_row)
54 
55  def Remove(self,control,event):
56  # Unbind the selected row's path
57  if self.current_row == -1:
58  return
59  self.path_spread.SetCellValue(self.current_row,0,"")
60  self.UpdateScript(self.current_row)
61 
62  def UpdateScript(self,row):
63  config = FBConfigFile("ActionScript.txt",ACTION_SCRIPT_PATH)
64 
65  spread_row = self.path_spread.GetRow(row)
66  key = spread_row.Caption
67  value = self.path_spread.GetCellValue(row,0)
68  if value:
69  # Convert it to relative path as it is more portable if
70  # the script is inside MotionBuilder tree
71  value = os.path.relpath(value,ACTION_SCRIPT_PATH)
72  config.Set("ScriptFiles",key,value)
73 
74  def CellChanged(self,control,event):
75  # User has edited a path by modifying the cell himself: update the relevant binding
76  self.UpdateScript(event.Row)
77 
78  def Populate(self):
79  # All relative paths inside ActionScript.txt are relative to ActionScrip.txt path
80  # so set the current working dir as ACTION_SCRIPT_PATH
81  old_cwd = os.getcwd()
82  os.chdir(ACTION_SCRIPT_PATH)
83 
84  self.current_row = -1
85  self.nb_row = 0
86  config = FBConfigFile("ActionScript.txt",ACTION_SCRIPT_PATH)
87  for i in range(12):
88  key = "Script%d" % (i + 1)
89  value = config.Get("ScriptFiles",key)
90  self.path_spread.RowAdd(key,self.nb_row)
91  if value:
92  self.path_spread.SetCellValue(self.nb_row,0,os.path.abspath(value))
93  self.nb_row += 1
94  os.chdir(old_cwd)
95 
96  def __init__(self):
97  # init base class
98  FBTool.__init__(self,TOOL_NAME)
99 
100  FBAddTool(self)
101 
102  x = FBAddRegionParam(0,FBAttachType.kFBAttachLeft,"")
103  y = FBAddRegionParam(0,FBAttachType.kFBAttachTop,"")
104  w = FBAddRegionParam(0,FBAttachType.kFBAttachRight,"")
105  h = FBAddRegionParam(0,FBAttachType.kFBAttachBottom,"")
106  self.AddRegion("main","main", x, y, w, h)
107 
108  vbox = FBVBoxLayout()
109  self.SetControl("main",vbox)
110 
111  widget_height = 30
112  button_width = 60
113 
114  l = FBLabel()
115  l.Caption = "Action Scripts"
116  vbox.Add(l, widget_height)
117 
118  self.path_spread = FBSpread()
119  self.path_spread.Caption = "Actions"
120  self.path_spread.ColumnAdd("Path")
121  self.path_spread.GetColumn(0).Width = 550
122  self.path_spread.OnRowClick.Add(self.RowClicked)
123  self.path_spread.OnCellChange.Add(self.CellChanged)
124  vbox.AddRelative(self.path_spread,1.0)
125 
126  hbox = FBHBoxLayout()
127 
128  self.path_edit = FBEdit()
129  hbox.AddRelative(self.path_edit,1.0)
130 
131  b = FBButton()
132  b.Caption = "Browse..."
133  b.OnClick.Add(self.Browse)
134  hbox.Add(b, button_width)
135 
136  vbox.Add(hbox,widget_height)
137 
138  hbox = FBHBoxLayout()
139  b = FBButton()
140  b.Caption = "Set"
141  b.OnClick.Add(self.Add)
142  hbox.Add(b, button_width)
143 
144  b = FBButton()
145  b.Caption = "Remove"
146  b.OnClick.Add(self.Remove)
147  hbox.Add(b, button_width)
148 
149  # Notify user that motionbuiler reads the ActionScript.txt file on startup only.
150  l = FBLabel()
151  l.Caption = "You will need to restart MotionBuilder for changes to takes place!"
152  l.Style = FBTextStyle.kFBTextStyleBold
153  hbox.Add(l, 400)
154 
155  vbox.Add(hbox,widget_height)
156 
157  self.StartSizeX = 800
158  self.StartSizeY = 425
159 
160  # Populate Datas
161  self.Populate()
162 
163 # This call is only useful in Development to ensure a recreation of the tool each time
164 #FBDestroyToolByName(TOOL_NAME)
165 
166 # this snippet of code ensure our tool will only be created once,
167 # even if this script is "imported" from other scripts.
168 if TOOL_NAME in FBToolList:
169  tool = FBToolList[TOOL_NAME]
170  ShowTool(tool)
171 else:
172  tool=ActionScriptMgr()
173  ShowTool(tool)
174  # This call is only useful in Development to ensure we show the tool when created
175  #ShowTool(tool)
176 
177 
178