SideFX Houdini customization package
git clone https://git.lucas.co/hou-control.git
python3.13libs/hc/hctab.py (5.9K)
1 import hou
2 import types
3 from .hccommands import command
4
5 class HCTab():
6 def __init__(self, hou_tab):
7 self.hou_tab = hou_tab
8
9 def initialize(self):
10 """Per-pane setup hook. Override in subclasses to apply pane-type
11 defaults, register hooks, set viewport prefs, etc. Called by factory
12 callers (e.g. HCLayout.launchFloating) after a pane tab is created."""
13 return
14
15 """ Status """
16
17 @command("Close Tab")
18 def close(self):
19 self.hou_tab.close()
20
21 @command("Close Other Tabs")
22 def closeOtherTabs(self):
23 for tab in self.pane().tabs():
24 if tab.hou_tab != self.hou_tab:
25 tab.close()
26
27 def name(self):
28 return self.hou_tab.name()
29
30 def pane(self):
31 from .hcpane import HCPane
32 return HCPane(self.hou_tab.pane())
33
34 def setCurrent(self):
35 self.hou_tab.setIsCurrentTab()
36
37 """ Type """
38
39 def type(self):
40 return self.__class__.__name__
41
42 def tab_type(self):
43 return 'HCTab'
44
45 def setTypeDetailsView(self):
46 self.setType(hou.paneTabType.DetailsView)
47
48 def setTypeNetworkEditor(self):
49 self.setType(hou.paneTabType.NetworkEditor)
50
51 def setTypeParm(self):
52 self.setType(hou.paneTabType.Parm)
53
54 def setTypePythonShell(self):
55 self.setType(hou.paneTabType.PythonShell)
56
57 def setTypeSceneViewer(self):
58 self.setType(hou.paneTabType.SceneViewer)
59
60 def paneTabTypes(self):
61 type_specs = (
62 ('Apex Editor', 'ApexEditor'),
63 ('Asset Browser', 'AssetBrowser'),
64 ('Bundle List', 'BundleList'),
65 ('Channel Editor', 'ChannelEditor'),
66 ('Channel List', 'ChannelList'),
67 ('Channel Viewer', 'ChannelViewer'),
68 ('Compositor Viewer', 'CompositorViewer'),
69 ('Context Viewer', 'ContextViewer'),
70 ('Data Tree', 'DataTree'),
71 ('Details View', 'DetailsView'),
72 ('Engine Session Sync', 'EngineSessionSync'),
73 ('Handle List', 'HandleList'),
74 ('Help Browser', 'HelpBrowser'),
75 ('IPR Viewer', 'IPRViewer'),
76 ('Light Linker', 'LightLinker'),
77 ('Material Palette', 'MaterialPalette'),
78 ('Network Editor', 'NetworkEditor'),
79 ('Output Viewer', 'OutputViewer'),
80 ('Parameter Editor', 'Parm'),
81 ('Parameter Spreadsheet', 'ParmSpreadsheet'),
82 ('Performance Monitor', 'PerformanceMonitor'),
83 ('Python Panel', 'PythonPanel'),
84 ('Python Shell', 'PythonShell'),
85 ('Render Gallery', 'RenderGallery'),
86 ('Scene Viewer', 'SceneViewer'),
87 ('Shader Viewer', 'ShaderViewer'),
88 ('Take List', 'TakeList'),
89 ('Textport', 'Textport'),
90 ('Tree View', 'TreeView'),
91 )
92
93 type_map = {}
94 for label, attr in type_specs:
95 tab_type = getattr(hou.paneTabType, attr, None)
96 if tab_type is not None:
97 type_map[label] = tab_type
98 return type_map
99
100 @command("Set Tab Type")
101 def changeTypeDialog(self):
102 from .hcwidgets import HCWidgets
103
104 type_map = self.paneTabTypes()
105 list_dict = {name: (lambda t=tab_type: self.setType(t)) for name, tab_type in type_map.items()}
106 anchor_geometry = self.pane().qtScreenGeometry()
107 dialog = HCWidgets.SelectionDialog('Set Tab Type', list_dict, anchor_geometry=anchor_geometry)
108 dialog.show()
109 dialog.raise_()
110 dialog.activateWindow()
111
112 def setType(self, tab_type):
113 if isinstance(tab_type, str):
114 tab_type_map = self.paneTabTypes()
115 compact_map = {label.replace(' ', ''): value for label, value in tab_type_map.items()}
116 compact_map['Parm'] = tab_type_map.get('Parameter Editor')
117 compact_map['DetailsView'] = tab_type_map.get('Details View')
118 tab_type = tab_type_map.get(tab_type) or compact_map.get(tab_type)
119 if tab_type is None:
120 hou.ui.setStatusMessage('Unknown pane tab type', hou.severityType.Error)
121 return None
122
123 new_tab = self.hou_tab.setType(tab_type)
124 if new_tab is None:
125 new_tab = self.hou_tab.pane().currentTab()
126
127 from .hcpane import HCPane
128 initialized = HCPane(new_tab.pane()).initializeObject(new_tab)
129 hou.ui.setStatusMessage('Changed tab type', hou.severityType.Message)
130 return initialized
131
132
133 """ Chrome """
134
135 # "Chrome" is whatever bars and controls a tab draws around its content.
136 # HCSession.toggleMenus and isVisibleMenus used to switch on tab.type()
137 # and call a different set of methods in each branch; each tab class now
138 # answers for itself and those two methods just iterate.
139 #
140 # The path bar ("network controls" to HOM) is the one piece of chrome
141 # every kind of tab may have -- network editors, viewers and parameter
142 # editors do, and so do the channel editor and the parameter spreadsheet,
143 # which wrap as plain HCTab -- while shells and browsers have none. So the
144 # Path toggle lives here and asks the tab, rather than living on a
145 # subclass or naming tab types.
146
147 def hasNetworkControls(self):
148 return self.hou_tab.hasNetworkControls()
149
150 def isShowingNetworkControls(self):
151 return self.hou_tab.isShowingNetworkControls()
152
153 def showNetworkControls(self, value):
154 self.hou_tab.showNetworkControls(value)
155
156 def isShowingPath(self):
157 return bool(self.hasNetworkControls() and self.isShowingNetworkControls())
158
159 @command("Path", state="isShowingPath", available="hasNetworkControls")
160 def toggleNetworkControls(self):
161 if self.hasNetworkControls():
162 self.showNetworkControls(not self.isShowingNetworkControls())
163
164 def isChromeVisible(self):
165 return bool(self.hasNetworkControls() and self.isShowingNetworkControls())
166
167 def showChrome(self, visible):
168 if self.hasNetworkControls():
169 self.showNetworkControls(visible)