32 KiB
TULayoutView Toolbar Integration in Toon Boom
This document explains how toolbars are created, managed, and displayed within TULayoutView instances in Toon Boom Harmony Premium and Storyboard Pro.
IDA Databases:
RE/HarmonyPremium.exe.i64- Main applicationRE/ToonBoomActionManager.dll.i64- AC_Toolbar and AC_Manager implementationsRE/ToonBoomLayout.dll.i64- TULayoutView and TULayoutFrame implementations
Overview
Toon Boom uses a two-tier toolbar system:
- Global Toolbars - Application-wide toolbars (FileToolbar, EditToolbar, DrawingToolToolbar, etc.)
- View-Specific Toolbars - Toolbars that appear when a specific view has focus (DrawingViewToolbar, TimelineViewToolbar, CameraViewToolbar, etc.)
Toolbar Buttons Disabled?
If your custom view’s toolbar shows but every button is disabled, the root cause is almost always validation / responder resolution, not the toolbar XML.
See docs/AC_Toolbar_ButtonEnablement.md:1 for the IDA-verified validation flow and why enabled="true" is ignored.
Important: raiseArea vs Toolbar Display
TULayoutManager::raiseArea() does NOT directly display toolbars.
raiseArea is used to bring a view/area to the foreground:
// Signature:
TULayoutView* raiseArea(const QString& areaName, TULayoutFrame* frame,
bool createNew, const QPoint& pos);
// Example usage (from HarmonyPremium.exe):
layoutManager->raiseArea("Colour", nullptr, true, QPoint(0,0)); // Shows Colour palette
layoutManager->raiseArea("Morphing", nullptr, true, QPoint(0,0)); // Shows Morphing view
Toolbar display is triggered separately through:
TULayoutFrame::setCurrentTab(...)(tab/view change)TULayoutFrame::showViewToolBar()(updates the view-toolbar for the new current view)view->toolbar()(returns toolbar definition as aQDomElement)
TULayoutManager::setCurrentLayoutFrame(frame) does not call showViewToolBar() directly (verified in ToonBoomLayout.dll 0x7ffa0be541d0).
If you call raiseArea and don't see toolbars, the likely causes are:
- Your view's
toolbar()override returns an emptyQDomElement - The toolbar XML hasn't been registered with
AC_Manager - The view isn't properly receiving focus after being raised
LAY_ToolbarInfo::m_isDefaultis still non-zero (the frame hides/resets the view-toolbar in this case)
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ TULayoutManager │
│ - Manages all frames, areas, and global toolbars │
│ - showToolbar() at vtable+416 creates/shows toolbars by name │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ TULayoutFrame │
│ - Contains TULayoutMainWindow for toolbar docking │
│ - showViewToolBar() displays view-specific toolbar │
│ - Stores LAY_ToolbarInfo per view for configuration │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ TULayoutViewHolder │
│ - Contains 1-2 TULayoutView instances │
│ - Notifies frame when active view changes │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ TULayoutView │
│ - Abstract base class for all views │
│ - toolbar() virtual method returns QDomElement │
│ - setToolbarInfo() receives LAY_ToolbarInfo │
└─────────────────────────────────────────────────────────────────┘
Toolbar Definition and Creation Flow
1. Toolbar XML Loading
During application startup, toolbars are loaded from toolbars.xml:
// From HarmonyPremium.exe session initialization (0x140034EB0)
// Loads toolbars.xml via AC_Manager::loadToolbars(path, outIds) (vtable+0x178)
UT_String toolbarsPath = RM_GetResourcePath("toolbars.xml");
QList<QString> toolbarIds;
actionManager->loadToolbars(toolbarsPath.ToQString(), toolbarIds);
The toolbars.xml file defines toolbar content using XML elements like:
<toolbar id="DrawingViewToolbar" trContext="Toolbars">
<item id="DrawingTool.Select" />
<separator />
<item id="DrawingTool.Brush" />
<!-- ... more items ... -->
</toolbar>
2. Global Toolbar Initialization
Global toolbars are shown during session initialization (sub_14002F840):
// Show global toolbars via TULayoutManager::showToolbar (vtable+416)
layoutManager->showToolbar("FileToolbar", true);
layoutManager->showToolbar("EditToolbar", true);
layoutManager->showToolbar("DrawingToolToolbar", true);
layoutManager->showToolbar("ArtLayerToolbar", true);
// Conditional toolbars based on features
if (WHO_Features::hasOnionSkinToolbar()) {
layoutManager->showToolbar("OnionSkinToolbar", false, true, nullptr);
}
Key Function Addresses (HarmonyPremium.exe):
- Session toolbar init:
0x14002F840 TULayoutManager::showToolbaris called via an import thunk in HarmonyPremium.exe (address is version-specific)
3. View-Specific Toolbar Definition
Each view class can override TULayoutView::toolbar() (ToonBoomLayout.dll vtable +0x58) to provide a QDomElement describing the view-toolbar content.
Implementation detail (MSVC x64 ABI): this return-by-value is implemented with a hidden return buffer pointer (passed in RDX for member functions), which is why decompiled code often looks like toolbar(this, out).
In Harmony Premium, many views inherit from TUWidgetLayoutView (via VL_ViewQt), so the TULayoutView* you get in toolbar() is an embedded subobject:
TUWidgetLayoutView::m_actionManageris stored at+0x30(in theTUWidgetLayoutViewobject)- the embedded
TULayoutViewbase is at+0x68 - therefore,
AC_Manager*is reachable from aTULayoutView*as*(AC_Manager**)((char*)this - 0x38)
Example: Drawing toolbar override
- Function:
VL_BaseDrawingViewQt__toolbar - Address:
0x1403B9880(HarmonyPremium.exe)
Behavior (from disassembly/decompilation):
- Read
AC_Manager*from[this-0x38] - Call
AC_Managervfunc at vtable+0x1A0to fill aQDomElementfor id"DrawingViewToolbar" - Return an empty
QDomElementifAC_Manageris null
Example: Reference View toolbar override
Toon Boom’s “Reference View” uses the ModelViewToolbar definition (see toolbars.xml), implemented in:
- Function:
VL_ModelViewQt__toolbar - Address:
0x1403C8A20(HarmonyPremium.exe)
Behavior: same as above, but requests "ModelViewToolbar".
Relevant TULayoutView virtuals (ToonBoomLayout.dll):
toolbar(...): vtable+0x58setToolbarInfo(const LAY_ToolbarInfo&): vtable+0x60
4. Toolbar Display Flow
When the current tab/view changes, Toon Boom updates the frame’s view-toolbar via TULayoutFrame::showViewToolBar() (ToonBoomLayout.dll 0x7ffa0be4bb70).
Confirmed call sites include:
TULayoutFrame::setCurrentTab(TULayoutViewHolder*)→showViewToolBar()TULayoutManager::showViewToolBars()→TULayoutFrame::showViewToolBar()
High-level behavior of showViewToolBar() (validated from disassembly):
currentView = m_layoutManager->findInstance(this, false)toolbarEl = currentView->toolbar()(calls the view’s override)info = currentView->getToolbarInfo()(copy ofTULayoutView::m_toolbarInfo)- Hide/reset cases:
- If
info.m_isDefault != 0: clear + hide the frame toolbar and return - If
toolbarElis null: clear + hide the frame toolbar and return
- If
- Ensure
m_viewToolbarexists (created once viacreateEmptyToolBar(info.m_name)if needed) - Populate the toolbar:
m_viewToolbar->setOwner(currentView->getWidget())m_viewToolbar->changeContent(toolbarEl, info.m_buttonConfig, info.m_buttonDefaultConfig)
- Dock and apply placement:
m_mainWindow->addToolBar(info.m_toolBarArea, m_viewToolbar->toQToolBar())Layout::Toolbar::loadToolbar(info, m_mainWindow)m_viewToolbar->setVisible(info.m_visible)
4.1 raiseArea Function Details
The raiseArea function is for bringing a view area to the foreground, not for toolbar display:
// Function signature (from ToonBoomLayout.dll)
TULayoutView* TULayoutManager::raiseArea(
const QString& areaName, // e.g., "Colour", "Morphing", "Timeline"
TULayoutFrame* frame, // Target frame, or nullptr for auto-selection
bool createNew, // true = create new instance if needed
const QPoint& pos // Position for floating windows
);
Example usages found in HarmonyPremium.exe:
// sub_14086E410: Opens the Colour palette view
void showColourView() {
TULayoutManager* mgr = getLayoutManager();
QString areaName("Colour");
QPoint pos(0, 0);
mgr->raiseArea(areaName, nullptr, true, pos);
}
// sub_1401579C0: Opens Morphing view on double-click
// (called from QAbstractItemView::mouseDoubleClickEvent handler)
void openMorphingOnDoubleClick() {
TULayoutFrame* frame = view->getLayoutFrame(widget);
TULayoutManager* mgr = frame->getLayoutManager();
QString areaName("Morphing");
QPoint pos(0, 0);
mgr->raiseArea(areaName, nullptr, true, pos);
}
Key points:
raiseAreareturns theTULayoutView*that was raised/created- The third parameter
createNewcontrols whether to create a new tab/instance - Pass
nullptrforframeto let the system choose the target frame - Toolbar display is a separate mechanism triggered by focus changes
4.2 Ensuring Toolbar Display After raiseArea
If you need to ensure toolbars appear after calling raiseArea:
// Method 1: Let the focus system handle it naturally
TULayoutView* view = layoutManager->raiseArea("MyArea", nullptr, true, QPoint(0,0));
if (view) {
QWidget* widget = view->getWidget();
if (widget) {
widget->setFocus(Qt::OtherFocusReason); // Triggers focus chain
}
}
// Method 2: Explicitly trigger the toolbar display
TULayoutView* view = layoutManager->raiseArea("MyArea", nullptr, true, QPoint(0,0));
if (view) {
TULayoutFrame* frame = view->getLayoutFrame(view->getWidget());
if (frame) {
// Direct refresh paths observed in ToonBoomLayout.dll:
// - TULayoutFrame::setCurrentTab(...) calls frame->showViewToolBar()
// - TULayoutManager::showViewToolBars() calls into the current frame(s)
frame->showViewToolBar();
layoutManager->showViewToolBars();
}
}
AC_Toolbar Integration
Toolbar definitions and instances involve three different components:
AC_Manager(ToonBoomActionManager.dll): loads<toolbar>definitions (e.g., fromtoolbars.xml) and can createAC_Toolbarinstances.TULayoutManager(ToonBoomLayout.dll / HarmonyPremium.exe): shows/hides global toolbars by name.TULayoutFrame(ToonBoomLayout.dll): owns the view toolbar instance (m_viewToolbar) and updates it on tab/view changes viashowViewToolBar().
How Toolbars Are Actually Registered
-
Toolbar Definitions are loaded from XML (
toolbars.xml):// During session init (sub_140034EB0 in HarmonyPremium.exe) AC_Manager* actionManager = AC_CreateActionManager(keywords); // Load toolbars via AC_Manager::loadToolbars(path, outIds) (vtable+0x178) QString path = RM_GetResourcePath("toolbars.xml").ToQString(); void** vtable = *reinterpret_cast<void***>(actionManager); using LoadToolbarsFromFileFn = void (__fastcall *)(AC_Manager* self, const QString* path, QList<QString>* outIds); auto loadToolbarsFromFile = reinterpret_cast<LoadToolbarsFromFileFn>(vtable[47]); // vtable+0x178 QList<QString> toolbarIds; loadToolbarsFromFile(actionManager, &path, &toolbarIds); -
Toolbars are shown/activated via TULayoutManager::showToolbar:
// During setupToolbars (0x14002f840) // This is vtable+416 on TULayoutManager, NOT AC_Manager layoutManager->showToolbar("FileToolbar", true); layoutManager->showToolbar("EditToolbar", true); -
View-specific toolbars are looked up via
AC_Manager::toolbarElement()(inside the view’stoolbar()override):// Common pattern in HarmonyPremium.exe view toolbar() overrides: // - AC_Manager* is reachable from a TUWidgetLayoutView-embedded TULayoutView* at [this-0x38] AC_Manager* manager = *(AC_Manager**)((char*)this - 0x38); if (!manager) { return QDomElement(); } return manager->toolbarElement(QString("DrawingViewToolbar"));
AC_Manager Methods Used
The AC_Manager provides these key toolbar methods:
| Method | Vtable Offset | Description |
|---|---|---|
toolbarElement(name) |
+0x1A0 |
Returns the <toolbar ...> QDomElement for name (member-function ABI uses a hidden return buffer in RDX) |
loadToolbars(element, outIds) |
+0x170 |
Loads toolbar definitions from a QDomElement (same structure as toolbars.xml) |
loadToolbars(path, outIds) |
+0x178 |
Loads toolbar definitions from an XML file (e.g., toolbars.xml) |
createToolbar(name, config, mainWindow, area, identity, owner) |
+0x180 |
Creates an AC_Toolbar instance from a stored toolbar id (implementation: AC_ToolbarImpl) |
createToolbar(element, config, mainWindow, area, identity, owner) |
+0x188 |
Creates an AC_Toolbar instance from a QDomElement (implementation: AC_ToolbarImpl) |
AC_Toolbar Creation / Reuse
TULayoutFrame::showViewToolBar() does not create a new AC_Toolbar every time focus changes.
Observed behavior (ToonBoomLayout.dll 0x7ffa0be4bb70):
- The frame keeps a single
AC_Toolbar*atTULayoutFrame + 0xC0(m_viewToolbar) - On each tab/view change, it:
- calls
m_viewToolbar->setOwner(currentView->getWidget()) - calls
m_viewToolbar->changeContent(toolbarEl, buttonConfig, buttonDefaultConfig) - docks
m_viewToolbar->toQToolBar()into the frame’sTULayoutMainWindow
- calls
The AC_Toolbar object itself is created lazily by TULayoutFrame::createEmptyToolBar(name):
- Builds an empty
<toolbar/>element - Calls
AC_Manager::createToolbar(emptyEl, nullptr, m_layoutManager, 4, nameLatin1, nullptr) - Stores the result as
m_viewToolbar
LAY_ToolbarInfo Configuration
Each view can have stored toolbar configuration via LAY_ToolbarInfo:
// Structure of LAY_ToolbarInfo (~104 bytes)
// Analyzed from ToonBoomLayout.dll constructors and getters
class LAY_ToolbarInfo {
int m_x; // +0x00 - X position (default: 0)
int m_y; // +0x04 - Y position (default: 0)
int m_index; // +0x08 - Toolbar index (default: -1)
int m_width; // +0x0C - Width (default: -1)
int m_height; // +0x10 - Height (default: -1)
bool m_newline; // +0x14 - Break to new line (default: false)
bool m_visible; // +0x15 - Visibility (default: true)
bool m_isDefault; // +0x16 - Default/unconfigured state (Layout hides view-toolbar when true)
// padding // +0x17
QString m_name; // +0x18 - Toolbar name (24 bytes with SSO)
Qt::Orientation m_orientation; // +0x30 - Orientation (default: Horizontal)
Qt::ToolBarArea m_toolBarArea; // +0x34 - Docking area (default: TopToolBarArea=4)
QList<QString> m_buttonConfig; // +0x38 - Current button order (24 bytes)
QList<QString> m_buttonDefaultConfig; // +0x50 - Default button order (24 bytes)
// Total size: ~104 bytes
};
Key LAY_ToolbarInfo Methods (ToonBoomLayout.dll):
| Method | Address | Description |
|---|---|---|
LAY_ToolbarInfo() |
0x7ffa0be6a3a0 |
Default constructor |
LAY_ToolbarInfo(QString, int, int, int, int, int, bool, bool) |
0x7ffa0be6a2c0 |
Initializes name,x,y,index,width,height,newline,visible (sets m_isDefault=1) |
getName() |
0x7ffa0be392b0 |
Returns toolbar name |
getHeight() |
0x7ffa0be39280 |
Returns height |
isVisible() |
0x7ffa0be39570 |
Returns visibility |
isDefault() |
0x7ffa0be39560 |
Returns m_isDefault (Layout treats non-zero as “hide/reset view-toolbar”) |
getButtonConfig() |
0x7ffa0be6a990 |
Returns nullptr when m_isDefault!=0, else &m_buttonConfig |
setButtonConfig() |
0x7ffa0be6a9a0 |
Copies config into m_buttonConfig and sets m_isDefault=0 |
setButtonDefaultConfig() |
0x7ffa0be6aaf0 |
Copies config into m_buttonDefaultConfig |
setName() |
0x7ffa0be39bd0 |
Sets toolbar name |
setVisible() |
0x7ffa0be39c10 |
Sets visibility |
fromXml() |
0x7ffa0be6a520 |
Loads from QDomElement |
toXml() |
0x7ffa0be6ab00 |
Saves to QDomElement |
Note: the m_buttonDefaultConfig accessor is ICF-folded with another trivial accessor and may show up in IDA as ?getChildren@TULayoutSplitter@@... at 0x7ffa0be5ac60; TULayoutFrame::showViewToolBar() uses that address as &m_buttonDefaultConfig.
How m_toolbarInfo Gets Initialized (Critical)
TULayoutFrame::showViewToolBar() will hide the view-toolbar when TULayoutView::m_toolbarInfo.m_isDefault != 0, so the question becomes: where does non-default toolbar info come from?
This happens when a view is added to a frame (e.g., via raiseArea() / layout activation):
TULayoutArea::add(ToonBoomLayout.dll0x7ffa0be41c10) first checks the frame’s cache (getToolbarInfoForView(viewKey)).- If no cached entry exists, it calls
view->toolbar()and readstoolbarEl.attribute("id")to get the toolbar identity string (e.g.,DrawingViewToolbar). - It then queries
TULayoutStorage::getViewToolbarConfig(viewKey, wantDefault)(ToonBoomLayout.dll0x7ffa0be5cff0) to fetch button config lists keyed byviewKey(typicallyview->getCaption(true)). - If configs exist, it builds a
LAY_ToolbarInfowith:m_name = toolbarIdm_buttonConfig+m_buttonDefaultConfigpopulated (which flipsm_isDefault -> 0)- applies it via
view->setToolbarInfo(info)and caches it in the frame.
Persisted customization updates the config lists via:
TULayoutFrame::toolbarWasCustomized(ToonBoomLayout.dll0x7ffa0be4be20) →TULayoutStorage::setViewToolbarConfig(viewKey, config, isDefault=false)+saveLayoutToolbar().
Implementing Custom View Toolbars
Step 1: Define Toolbar in XML
Create a toolbar definition that will be loaded by AC_Manager:
<toolbar id="MyCustomViewToolbar" trContext="MyToolbars">
<item id="MyResponder.Action1" />
<item id="MyResponder.Action2" />
<separator />
<placeholder id="CustomItems" />
</toolbar>
Step 2: Override toolbar() in Your View
class MyCustomView : public TULayoutView {
public:
QDomElement toolbar() override {
// Get AC_Manager - depends on your view's structure.
// In HarmonyPremium.exe views derived from TUWidgetLayoutView, AC_Manager* is reachable from the embedded
// TULayoutView* at [this-0x38]. For a custom TULayoutView subclass, store AC_Manager* yourself (or fetch
// it via PLUG_Services::getActionManager()).
AC_Manager* manager = getActionManager(); // your helper
if (!manager) {
return QDomElement();
}
return manager->toolbarElement(QString("MyCustomViewToolbar"));
}
};
Step 3: Register Toolbar XML
Ensure your toolbar XML is loaded during initialization:
// Option 1: Add to existing toolbars.xml (if modifying installation)
// Option 2: Load programmatically
AC_Manager* manager = PLUG_Services::getActionManager();
if (manager) {
// Use AC_Manager::loadToolbars(element, outIds) (vtable+0x170)
// Note: loadToolbars expects the same structure as toolbars.xml; easiest is to wrap your <toolbar> inside a <toolbars> root.
QDomDocument doc;
doc.setContent(myToolbarXml);
QDomElement element = doc.documentElement();
QList<QString> ids;
manager->loadToolbars(element, ids);
}
Step 4: Ensure LAY_ToolbarInfo Is Non-Default
TULayoutFrame::showViewToolBar() (ToonBoomLayout.dll 0x7ffa0be4bb70) will hide/reset the view-toolbar when TULayoutView::m_toolbarInfo.m_isDefault != 0.
For a custom view, you must ensure:
LAY_ToolbarInfo::m_nameis set to the toolbar element’s"id"(used as the toolbar instance identity whencreateEmptyToolBar(name)createsm_viewToolbar)LAY_ToolbarInfo::m_buttonConfig(and typicallym_buttonDefaultConfig) are populated, som_isDefaultflips to0
Built-in views typically get this via TULayoutArea::add() reading config from TULayoutStorage (see the section above). If your view has no stored config, the toolbar will remain hidden until you seed it.
Minimal pattern (conceptual):
LAY_ToolbarInfo info = this->getToolbarInfo();
info.setName(QString("MyCustomViewToolbar"));
QList<QString> buttons = {/* item ids in desired order */};
info.setButtonConfig(&buttons); // flips m_isDefault -> 0
info.setButtonDefaultConfig(&buttons); // used for reset/customize UI
this->setToolbarInfo(info);
Key Memory Offsets
TULayoutView (from TULayoutView*)
+0x00: vptr+0x08: QString m_internalName+0x20: LAY_ToolbarInfo m_toolbarInfo (104 bytes)+0x88: AC_Menu* m_menuByType[2]+0xA0: QString m_caption
TULayoutFrame (from TULayoutFrame*)
+0x28: TULayoutManager* m_layoutManager+0x48: TULayoutMainWindow* m_mainWindow (toolbar host)+0x90: AC_Toolbar* m_toolbar+0xC0: AC_Toolbar* m_viewToolbar
AC_ToolbarImpl (from QToolBar base)
+0x28: AC_ContainerImpl m_container (88 bytes)+0x80: AC_Toolbar vptr+0x98: QString m_responderIdentity+0xC8: bool m_isCustomizable+0xE0: QObject* m_owner
Database Reference
HarmonyPremium.exe
| Symbol | Address | Description |
|---|---|---|
| TULayoutManager__setupToolbars | 0x14002F840 |
Initializes/shows global toolbars by name |
| VL_BaseDrawingViewQt__toolbar | 0x1403B9880 |
Returns DrawingViewToolbar element |
| CV_CameraViewQt__toolbar | 0x1403BC450 |
Returns CameraViewToolbar element |
| VL_ModelViewQt__toolbar | 0x1403C8A20 |
Returns ModelViewToolbar element (Reference View) |
| TL_DockWindowQT__toolbar | 0x14011C5F0 |
Returns TimelineViewToolbar element |
ToonBoomActionManager.dll
| Symbol | Address | Description |
|---|---|---|
| AC_ManagerImpl__toolbarElement | 0x180016240 |
AC_Manager::toolbarElement(name) implementation (returns QDomElement by value) |
| AC_ToolbarImpl__changeContent_fromElement | 0x1800332F0 |
AC_Toolbar::changeContent(element, config, defaultConfig) |
| AC_ToolbarImpl::create | 0x180033910 |
Build toolbar from XML element |
| AC_ToolbarImpl::create (with config) | 0x180033D50 |
Build toolbar from XML element + config list |
ToonBoomLayout.dll (Toolbar Infrastructure)
| Symbol | Address | Description |
|---|---|---|
| TULayoutArea::add | 0x7ffa0be41c10 |
Initializes TULayoutView::m_toolbarInfo from view->toolbar().attribute(\"id\") + TULayoutStorage configs |
| TULayoutFrame::showViewToolBar | 0x7ffa0be4bb70 |
Core view-toolbar update flow (calls view->toolbar(), then changeContent + docking) |
| TULayoutFrame::createEmptyToolBar | 0x7ffa0be47730 |
Lazily creates/clears m_viewToolbar |
| TULayoutFrame::removeViewToolBar | 0x7ffa0be4a700 |
Hides m_viewToolbar |
| TULayoutFrame::getCurToolbarState | 0x7ffa0be48b20 |
Captures geometry/visibility from m_viewToolbar->toQToolBar() |
| TULayoutFrame::toolbarWasCustomized | 0x7ffa0be4be20 |
Persists button order into TULayoutStorage (flips m_isDefault -> 0) |
| TULayoutView::toolbar | 0x7ffa0be610d0 |
Base implementation (returns empty QDomElement) |
| TULayoutView::setToolbarInfo | 0x7ffa0be610c0 |
Stores LAY_ToolbarInfo into the view |
| TULayoutView::getToolbarInfo | 0x7ffa0be60e80 |
Returns pointer to embedded LAY_ToolbarInfo |
| TULayoutStorage::getViewToolbarConfig | 0x7ffa0be5cff0 |
Returns stored QList<QString> pointer for a view-toolbar config |
| TULayoutStorage::setViewToolbarConfig | 0x7ffa0be5fa20 |
Stores a view-toolbar config list (current or default) |
| LAY_ToolbarInfo::setButtonConfig | 0x7ffa0be6a9a0 |
Copies config + flips m_isDefault |
Toolbar Names Reference
Global Toolbars
FileToolbar- File operationsEditToolbar- Edit operationsDrawingToolToolbar- Drawing toolsArtLayerToolbar- Art layer selectionSceneplanningToolToolbar- Scene planning toolsOnionSkinToolbar- Onion skin controlsFlipToolbar- Flip/mirror toolsGameToolbar- Game export toolsAlignmentGuidesToolbar- Alignment guidesMarkDrawingToolBar- Mark drawing tools
View-Specific Toolbars
DrawingViewToolbar- Drawing viewCameraViewToolbar- Camera viewTimelineViewToolbar- Timeline viewXsheetViewToolbar- Xsheet viewNetworkViewToolbar- Network/Node viewFunctionViewToolbar- Function curve viewPlaybackViewToolbar- Playback viewModelViewToolbar- Model viewLibraryViewToolbar- Library viewModuleLibraryViewToolbar- Module library viewFreeViewToolbar- Free-form view
Troubleshooting
Toolbar Not Appearing After raiseArea
If you call TULayoutManager::raiseArea() and the view's toolbar doesn't appear:
-
raiseAreadoesn't trigger toolbars directlyraiseAreaonly brings a view to the foreground- Toolbar display is handled by
TULayoutFrame::showViewToolBar()(typically reached via tab/view changes orTULayoutManager::showViewToolBars())
-
Manual toolbar trigger
TULayoutView* view = layoutManager->raiseArea("MyArea", nullptr, true, QPoint(0,0)); if (view) { TULayoutFrame* frame = view->getLayoutFrame(view->getWidget()); if (frame) { // Direct refresh options: frame->showViewToolBar(); layoutManager->showViewToolBars(); } } -
Set focus to trigger natural flow
TULayoutView* view = layoutManager->raiseArea("MyArea", nullptr, true, QPoint(0,0)); if (view && view->getWidget()) { view->getWidget()->setFocus(Qt::OtherFocusReason); }
View toolbar() Returns Empty Element
If your custom view's toolbar() method doesn't work:
-
Check AC_Manager access
- For
TUWidgetLayoutViewsubclasses:AC_Manager* mgr = TULayoutView_getActionManager(this); - The manager must be non-null
- For
-
Verify toolbar is registered
- The toolbar XML must be loaded via
AC_Manager::loadToolbars(path, outIds)orloadToolbars(element, outIds) - Check that the toolbar
idattribute matches what you're requesting
- The toolbar XML must be loaded via
-
Debug the vtable call
QDomElement MyView::toolbar() { AC_Manager* manager = TULayoutView_getActionManager(this); if (!manager) { qDebug() << "No AC_Manager available"; return QDomElement(); } // NOTE: AC_Manager::toolbarElement(...) returns QDomElement by value. // MSVC x64 member-function ABI uses a hidden return buffer pointer (RDX), // so a raw vtable call must include an explicit QDomElement* out. void** vtable = *reinterpret_cast<void***>(manager); using ToolbarElementFn = QDomElement* (__fastcall *)(AC_Manager* self, QDomElement* out, const QString* name); auto toolbarElement = reinterpret_cast<ToolbarElementFn>(vtable[52]); QDomElement element; QString name("MyViewToolbar"); toolbarElement(manager, &element, &name); if (element.isNull()) { qDebug() << "Toolbar" << name << "not found in AC_Manager"; } return element; }
Focus/Frame Issues
-
Frame not set as current
- The system uses
setCurrentLayoutFrameto track which frame is active showViewToolBar()is triggered by tab/view changes orTULayoutManager::showViewToolBars(), not directly bysetCurrentLayoutFrame
- The system uses
-
View not in frame's current tab
- The raised view may be in a tab but not the current one
- Use
TULayoutFrame::setCurrentTab()if needed
See Database Reference for verified addresses used in this document.
Example: Complete Toolbar Integration
// 1. During initialization - register your toolbar XML
void MyPlugin::initialize(AC_Manager* manager) {
QString toolbarXml = R"(
<toolbar id="MyViewToolbar" trContext="MyPlugin">
<item id="MyResponder.DoSomething" />
<separator />
<item id="MyResponder.DoOther" />
</toolbar>
)";
QDomDocument doc;
doc.setContent(toolbarXml);
// Register with AC_Manager (loadToolbars(element, outIds))
QList<QString> ids;
manager->loadToolbars(doc.documentElement(), ids);
}
// 2. In your view class - override toolbar()
QDomElement MyView::toolbar() {
AC_Manager* manager = TULayoutView_getActionManager(this);
if (!manager) return QDomElement();
void** vtable = *reinterpret_cast<void***>(manager);
auto getToolbarElement = reinterpret_cast<void(*)(AC_Manager*, QDomElement*, const QString&)>(vtable[52]);
QDomElement element;
getToolbarElement(manager, &element, QString("MyViewToolbar"));
return element;
}
// 3. When raising your view and ensuring toolbar appears
void showMyView(TULayoutManager* layoutManager) {
TULayoutView* view = layoutManager->raiseArea("MyView", nullptr, true, QPoint(0,0));
if (view) {
// Ensure toolbar displays by triggering focus flow
if (QWidget* widget = view->getWidget()) {
widget->setFocus(Qt::OtherFocusReason);
}
// Or explicitly trigger a refresh
TULayoutFrame* frame = view->getLayoutFrame(view->getWidget());
if (frame) {
frame->showViewToolBar();
layoutManager->showViewToolBars();
}
}
}