Improvements to C++/Python tool gemplates

Signed-off-by: Chris Galvan <chgalvan@amazon.com>
monroegm-disable-blank-issue-2
Chris Galvan 4 years ago
parent a661189ea9
commit e56396a817

@ -832,7 +832,7 @@ QAction* LevelEditorMenuHandler::CreateViewPaneAction(const QtViewPane* view)
if (view->m_options.showOnToolsToolbar) if (view->m_options.showOnToolsToolbar)
{ {
action->setIcon(QIcon(view->m_options.toolbarIcon)); action->setIcon(QIcon(view->m_options.toolbarIcon.c_str()));
} }
m_actionManager->AddAction(view->m_id, action); m_actionManager->AddAction(view->m_id, action);

@ -40,7 +40,7 @@ namespace AzToolsFramework
bool isDisabledInSimMode = false; ///< set to true if the view pane should not be openable from level editor menu when editor is in simulation mode. bool isDisabledInSimMode = false; ///< set to true if the view pane should not be openable from level editor menu when editor is in simulation mode.
bool showOnToolsToolbar = false; ///< set to true if the view pane should create a button on the tools toolbar to open/close the pane bool showOnToolsToolbar = false; ///< set to true if the view pane should create a button on the tools toolbar to open/close the pane
QString toolbarIcon; ///< path to the icon to use for the toolbar button - only used if showOnToolsToolbar is set to true AZStd::string toolbarIcon; ///< path to the icon to use for the toolbar button - only used if showOnToolsToolbar is set to true
}; };
} // namespace AzToolsFramework } // namespace AzToolsFramework

@ -424,6 +424,8 @@ namespace AzToolsFramework
->Property("showInMenu", BehaviorValueProperty(&ViewPaneOptions::showInMenu)) ->Property("showInMenu", BehaviorValueProperty(&ViewPaneOptions::showInMenu))
->Property("canHaveMultipleInstances", BehaviorValueProperty(&ViewPaneOptions::canHaveMultipleInstances)) ->Property("canHaveMultipleInstances", BehaviorValueProperty(&ViewPaneOptions::canHaveMultipleInstances))
->Property("isPreview", BehaviorValueProperty(&ViewPaneOptions::isPreview)) ->Property("isPreview", BehaviorValueProperty(&ViewPaneOptions::isPreview))
->Property("showOnToolsToolbar", BehaviorValueProperty(&ViewPaneOptions::showOnToolsToolbar))
->Property("toolbarIcon", BehaviorValueProperty(&ViewPaneOptions::toolbarIcon))
; ;
behaviorContext->EBus<EditorRequestBus>("EditorRequestBus") behaviorContext->EBus<EditorRequestBus>("EditorRequestBus")

@ -27,7 +27,7 @@ def get_editor_main_window():
return editor_main_window return editor_main_window
# Helper method for registering a Python widget as a tool/view pane with the Editor # Helper method for registering a Python widget as a tool/view pane with the Editor
def register_view_pane(name, widget_type, options=editor.ViewPaneOptions()): def register_view_pane(name, widget_type, category="Tools", options=editor.ViewPaneOptions()):
global view_pane_handlers global view_pane_handlers
# The view pane names are unique in the Editor, so make sure one with the same name doesn't exist already # The view pane names are unique in the Editor, so make sure one with the same name doesn't exist already
@ -45,10 +45,10 @@ def register_view_pane(name, widget_type, options=editor.ViewPaneOptions()):
return new_widget.winId() return new_widget.winId()
def on_notify_register_views(parameters, my_name=name, my_options=options): def on_notify_register_views(parameters, my_name=name, my_category=category, my_options=options):
# Register our widget as an Editor view pane # Register our widget as an Editor view pane
print('Calling on_notify_register_views RegisterCustomViewPane') print('Calling on_notify_register_views RegisterCustomViewPane')
editor.EditorRequestBus(azlmbr.bus.Broadcast, 'RegisterCustomViewPane', my_name, 'Tools', my_options) editor.EditorRequestBus(azlmbr.bus.Broadcast, 'RegisterCustomViewPane', my_name, my_category, my_options)
# We keep a handler around in case a request for registering custom view panes comes later # We keep a handler around in case a request for registering custom view panes comes later
print('Initializing callback for RegisterCustomViewPane') print('Initializing callback for RegisterCustomViewPane')
@ -57,7 +57,7 @@ def register_view_pane(name, widget_type, options=editor.ViewPaneOptions()):
registration_handler.add_callback("NotifyRegisterViews", on_notify_register_views) registration_handler.add_callback("NotifyRegisterViews", on_notify_register_views)
global registration_handlers global registration_handlers
registration_handlers[name] = registration_handler registration_handlers[name] = registration_handler
editor.EditorRequestBus(azlmbr.bus.Broadcast, 'RegisterCustomViewPane', name, 'Tools', options) editor.EditorRequestBus(azlmbr.bus.Broadcast, 'RegisterCustomViewPane', name, category, options)
# Connect to the ViewPaneCallbackBus in order to respond to requests to create our widget # Connect to the ViewPaneCallbackBus in order to respond to requests to create our widget
# We also need to store our handler so it will exist for the life of the Editor # We also need to store our handler so it will exist for the life of the Editor

@ -71,8 +71,8 @@ namespace ${SanitizedCppName}
options.showOnToolsToolbar = true; options.showOnToolsToolbar = true;
options.toolbarIcon = ":/${Name}/toolbar_icon.svg"; options.toolbarIcon = ":/${Name}/toolbar_icon.svg";
// Register our custom widget as a dockable tool with the Editor // Register our custom widget as a dockable tool with the Editor under an Examples sub-menu
AzToolsFramework::RegisterViewPane<${SanitizedCppName}Widget>("${Name}", "Tools", options); AzToolsFramework::RegisterViewPane<${SanitizedCppName}Widget>("${Name}", "Examples", options);
} }
} // namespace ${SanitizedCppName} } // namespace ${SanitizedCppName}

@ -20,8 +20,6 @@ namespace ${SanitizedCppName}
${SanitizedCppName}Widget::${SanitizedCppName}Widget(QWidget* parent) ${SanitizedCppName}Widget::${SanitizedCppName}Widget(QWidget* parent)
: QWidget(parent) : QWidget(parent)
{ {
setWindowTitle(QObject::tr("${Name}"));
QVBoxLayout* mainLayout = new QVBoxLayout(this); QVBoxLayout* mainLayout = new QVBoxLayout(this);
QLabel* introLabel = new QLabel(QObject::tr("Put your cool stuff here!"), this); QLabel* introLabel = new QLabel(QObject::tr("Put your cool stuff here!"), this);

@ -11,4 +11,5 @@ set(FILES
Source/${Name}ModuleInterface.h Source/${Name}ModuleInterface.h
Source/${Name}EditorSystemComponent.cpp Source/${Name}EditorSystemComponent.cpp
Source/${Name}EditorSystemComponent.h Source/${Name}EditorSystemComponent.h
Source/${Name}.qrc
) )

@ -26,6 +26,7 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS)
ly_add_target( ly_add_target(
NAME ${Name}.Editor.Static STATIC NAME ${Name}.Editor.Static STATIC
NAMESPACE Gem NAMESPACE Gem
AUTORCC
FILES_CMAKE FILES_CMAKE
${NameLower}_editor_files.cmake ${NameLower}_editor_files.cmake
INCLUDE_DIRECTORIES INCLUDE_DIRECTORIES

@ -0,0 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/${Name}">
<file alias="toolbar_icon.svg">toolbar_icon.svg</file>
</qresource>
</RCC>

@ -11,6 +11,12 @@
#include <${Name}ModuleInterface.h> #include <${Name}ModuleInterface.h>
#include <${Name}EditorSystemComponent.h> #include <${Name}EditorSystemComponent.h>
void Init${SanitizedCppName}Resources()
{
// We must register our Qt resources (.qrc file) since this is being loaded from a separate module (gem)
Q_INIT_RESOURCE(${SanitizedCppName});
}
namespace ${SanitizedCppName} namespace ${SanitizedCppName}
{ {
class ${SanitizedCppName}EditorModule class ${SanitizedCppName}EditorModule
@ -22,6 +28,8 @@ namespace ${SanitizedCppName}
${SanitizedCppName}EditorModule() ${SanitizedCppName}EditorModule()
{ {
Init${SanitizedCppName}Resources();
// Push results of [MyComponent]::CreateDescriptor() into m_descriptors here. // Push results of [MyComponent]::CreateDescriptor() into m_descriptors here.
// Add ALL components descriptors associated with this gem to m_descriptors. // Add ALL components descriptors associated with this gem to m_descriptors.
// This will associate the AzTypeInfo information for the components with the the SerializeContext, BehaviorContext and EditContext. // This will associate the AzTypeInfo information for the components with the the SerializeContext, BehaviorContext and EditContext.

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#FFFFFF"><g><rect fill="none" height="24" width="24"/><path d="M19,3H5C3.89,3,3,3.9,3,5v14c0,1.1,0.89,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.11,3,19,3z M19,19H5V7h14V19z M13.5,13 c0,0.83-0.67,1.5-1.5,1.5s-1.5-0.67-1.5-1.5c0-0.83,0.67-1.5,1.5-1.5S13.5,12.17,13.5,13z M12,9c-2.73,0-5.06,1.66-6,4 c0.94,2.34,3.27,4,6,4s5.06-1.66,6-4C17.06,10.66,14.73,9,12,9z M12,15.5c-1.38,0-2.5-1.12-2.5-2.5c0-1.38,1.12-2.5,2.5-2.5 c1.38,0,2.5,1.12,2.5,2.5C14.5,14.38,13.38,15.5,12,15.5z"/></g></svg>

After

Width:  |  Height:  |  Size: 607 B

@ -6,24 +6,15 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
""" """
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
"""${SanitizedCppName}\\editor\\scripts\\${SanitizedCppName}_dialog.py """${SanitizedCppName}\\editor\\scripts\\${SanitizedCppName}_dialog.py
Generated from O3DE PythonGem Template""" Generated from O3DE PythonToolGem Template"""
import azlmbr from PySide2.QtCore import Qt
from shiboken2 import wrapInstance, getCppPointer from PySide2.QtWidgets import QDialog, QLabel, QVBoxLayout
from PySide2 import QtCore, QtWidgets, QtGui
from PySide2.QtCore import QEvent, Qt
from PySide2.QtWidgets import QVBoxLayout, QAction, QDialog, QHeaderView, QLabel, QLineEdit, QPushButton, QSplitter, QTreeWidget, QTreeWidgetItem, QWidget, QAbstractButton
# Once PySide2 has been bootstrapped, register our ${SanitizedCppName}Dialog with the Editor
class ${SanitizedCppName}Dialog(QDialog): class ${SanitizedCppName}Dialog(QDialog):
def __init__(self, parent=None): def __init__(self, parent=None):
super(${SanitizedCppName}Dialog, self).__init__(parent) super(${SanitizedCppName}Dialog, self).__init__(parent)
self.setObjectName("${SanitizedCppName}Dialog")
self.setWindowTitle("HelloWorld, ${SanitizedCppName} Dialog")
self.mainLayout = QVBoxLayout(self) self.mainLayout = QVBoxLayout(self)
self.introLabel = QLabel("Put your cool stuff here!") self.introLabel = QLabel("Put your cool stuff here!")
@ -42,5 +33,3 @@ class ${SanitizedCppName}Dialog(QDialog):
self.mainLayout.addWidget(self.helpLabel, 0, Qt.AlignCenter) self.mainLayout.addWidget(self.helpLabel, 0, Qt.AlignCenter)
self.setLayout(self.mainLayout) self.setLayout(self.mainLayout)
return

@ -6,112 +6,17 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
""" """
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
"""${SanitizedCppName}\\editor\\scripts\\boostrap.py """${SanitizedCppName}\\editor\\scripts\\boostrap.py
Generated from O3DE PythonGem Template""" Generated from O3DE PythonToolGem Template"""
import azlmbr
import az_qt_helpers import az_qt_helpers
from PySide2 import QtCore, QtWidgets, QtGui import azlmbr.editor as editor
from PySide2.QtCore import QEvent, Qt from ${NameLower}_dialog import ${SanitizedCppName}Dialog
from PySide2.QtWidgets import QMainWindow, QAction, QDialog, QHeaderView, QLabel, QLineEdit, QPushButton, QSplitter, QTreeWidget, QTreeWidgetItem, QWidget, QAbstractButton
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
class SampleUI(QtWidgets.QDialog):
"""Lightweight UI Test Class created a button"""
def __init__(self, parent, title='Not Set'):
super(SampleUI, self).__init__(parent)
self.setWindowTitle(title)
self.initUI()
def initUI(self):
mainLayout = QtWidgets.QHBoxLayout()
testBtn = QtWidgets.QPushButton("I am just a Button man!")
mainLayout.addWidget(testBtn)
self.setLayout(mainLayout)
# -------------------------------------------------------------------------
if __name__ == "__main__": if __name__ == "__main__":
print("${SanitizedCppName}.boostrap, Generated from O3DE PythonGem Template") print("${SanitizedCppName}.boostrap, Generated from O3DE PythonToolGem Template")
# ---------------------------------------------------------------------
# validate pyside before continuing
try:
azlmbr.qt.QtForPythonRequestBus(azlmbr.bus.Broadcast, 'IsActive')
params = azlmbr.qt.QtForPythonRequestBus(azlmbr.bus.Broadcast, 'GetQtBootstrapParameters')
params is not None and params.mainWindowId is not 0
from PySide2 import QtWidgets
except Exception as e:
_LOGGER.error(f'Pyside not available, exception: {e}')
raise e
# keep going, import the other PySide2 bits we will use
from PySide2 import QtGui
from PySide2.QtCore import Slot
from shiboken2 import wrapInstance, getCppPointer
# Get our Editor main window
_widget_main_window = None
try:
_widget_main_window = az_qt_helpers.get_editor_main_window()
except:
pass # may be booting in the AP?
# ---------------------------------------------------------------------
# ---------------------------------------------------------------------
if _widget_main_window:
# creat a custom menu
_tag_str = '${SanitizedCppName}'
# create our own menuBar
${SanitizedCppName}_menu = _widget_main_window.menuBar().addMenu(f"&{_tag_str}")
# nest a menu for util/tool launching
${SanitizedCppName}_launch_menu = ${SanitizedCppName}_menu.addMenu("examples")
else:
print('No O3DE MainWindow')
# ---------------------------------------------------------------------
# ---------------------------------------------------------------------
if _widget_main_window:
# (1) add the first SampleUI
action_launch_sample_ui = ${SanitizedCppName}_launch_menu.addAction("O3DE:SampleUI")
@Slot()
def clicked_sample_ui():
while 1: # simple PySide2 test, set to 0 to disable
ui = SampleUI(parent=_widget_main_window, title='O3DE:SampleUI')
ui.show()
break
return
# Add click event to menu bar
action_launch_sample_ui.triggered.connect(clicked_sample_ui)
# ---------------------------------------------------------------------
# ---------------------------------------------------------------------
if _widget_main_window:
# (1) and custom external module Qwidget
action_launch_${SanitizedCppName}_dialog = ${SanitizedCppName}_launch_menu.addAction("O3DE:${SanitizedCppName}_dialog")
@Slot()
def clicked_${SanitizedCppName}_dialog():
while 1: # simple PySide2 test, set to 0 to disable
try:
import az_qt_helpers
from ${NameLower}_dialog import ${SanitizedCppName}Dialog
az_qt_helpers.register_view_pane('${SanitizedCppName} Popup', ${SanitizedCppName}Dialog)
except Exception as e:
print(f'Error: {e}')
print('Skipping register our ${SanitizedCppName}Dialog with the Editor.')
${SanitizedCppName}_dialog = ${SanitizedCppName}Dialog(parent=_widget_main_window)
${SanitizedCppName}_dialog.show()
break
return
# Add click event to menu bar
action_launch_${SanitizedCppName}_dialog.triggered.connect(clicked_${SanitizedCppName}_dialog)
# ---------------------------------------------------------------------
# end # Register our custom widget as a dockable tool with the Editor under an Examples sub-menu
options = editor.ViewPaneOptions()
options.showOnToolsToolbar = True
options.toolbarIcon = ":/${Name}/toolbar_icon.svg"
az_qt_helpers.register_view_pane('${SanitizedCppName}', ${SanitizedCppName}Dialog, category="Examples", options=options)

@ -102,6 +102,12 @@
"isTemplated": true, "isTemplated": true,
"isOptional": false "isOptional": false
}, },
{
"file": "Code/Source/${Name}.qrc",
"origin": "Code/Source/${Name}.qrc",
"isTemplated": true,
"isOptional": false
},
{ {
"file": "Code/Source/${Name}EditorModule.cpp", "file": "Code/Source/${Name}EditorModule.cpp",
"origin": "Code/Source/${Name}EditorModule.cpp", "origin": "Code/Source/${Name}EditorModule.cpp",
@ -126,6 +132,12 @@
"isTemplated": true, "isTemplated": true,
"isOptional": false "isOptional": false
}, },
{
"file": "Code/Source/toolbar_icon.svg",
"origin": "Code/Source/toolbar_icon.svg",
"isTemplated": false,
"isOptional": false
},
{ {
"file": "Code/Tests/${Name}EditorTest.cpp", "file": "Code/Tests/${Name}EditorTest.cpp",
"origin": "Code/Tests/${Name}EditorTest.cpp", "origin": "Code/Tests/${Name}EditorTest.cpp",

Loading…
Cancel
Save