diff options
Diffstat (limited to 'tools')
9 files changed, 513 insertions, 17 deletions
diff --git a/tools/qgltf/qgltf.cpp b/tools/qgltf/qgltf.cpp index 788f3cef5..e5f49bdc6 100644 --- a/tools/qgltf/qgltf.cpp +++ b/tools/qgltf/qgltf.cpp @@ -1016,7 +1016,7 @@ void AssimpImporter::parseCameras() c.aspectRatio = qFuzzyIsNull(cam->mAspect) ? 1.5f : cam->mAspect; c.yfov = cam->mHorizontalFOV; if (c.yfov < (M_PI / 10.0)) // this can't be right (probably orthographic source camera) - c.yfov = M_PI / 4.0; + c.yfov = float(M_PI / 4.0); c.znear = cam->mClipPlaneNear; c.zfar = cam->mClipPlaneFar; @@ -1964,13 +1964,13 @@ void GltfExporter::exportTechniques(QJsonObject &obj, const QString &basename) if (newName.isEmpty()) newName = newShaderName(); QString key = basename + QStringLiteral("_") + newName + QStringLiteral("_v"); - QString fn = QString(QStringLiteral("%1.%2")).arg(key).arg("vert"); + QString fn = QString(QStringLiteral("%1.vert")).arg(key); vertexShader["uri"] = fn; writeShader(prog->vertShader, fn, m_subst_es2); if (opts.genCore) { QJsonObject coreVertexShader; QString coreKey = QString(QStringLiteral("%1_core").arg(key)); - fn = QString(QStringLiteral("%1.%2")).arg(coreKey).arg("vert"); + fn = QString(QStringLiteral("%1.vert")).arg(coreKey); coreVertexShader["type"] = 35633; coreVertexShader["uri"] = fn; writeShader(prog->vertShader, fn, m_subst_core); @@ -1986,13 +1986,13 @@ void GltfExporter::exportTechniques(QJsonObject &obj, const QString &basename) if (newName.isEmpty()) newName = newShaderName(); QString key = basename + QStringLiteral("_") + newName + QStringLiteral("_f"); - QString fn = QString(QStringLiteral("%1.%2")).arg(key).arg("frag"); + QString fn = QString(QStringLiteral("%1.frag")).arg(key); fragmentShader["uri"] = fn; writeShader(prog->fragShader, fn, m_subst_es2); if (opts.genCore) { QJsonObject coreFragmentShader; QString coreKey = QString(QStringLiteral("%1_core").arg(key)); - fn = QString(QStringLiteral("%1.%2")).arg(coreKey).arg("frag"); + fn = QString(QStringLiteral("%1.frag")).arg(coreKey); coreFragmentShader["type"] = 35632; coreFragmentShader["uri"] = fn; writeShader(prog->fragShader, fn, m_subst_core); diff --git a/tools/tools.pro b/tools/tools.pro index 9c384630e..8e973aecb 100644 --- a/tools/tools.pro +++ b/tools/tools.pro @@ -1,2 +1,4 @@ TEMPLATE = subdirs -!android:SUBDIRS += qgltf +QT_FOR_CONFIG += 3dcore-private +!android:qtConfig(assimp):qtConfig(commandlineparser): \ + SUBDIRS += qgltf diff --git a/tools/utils/exporters/blender/qt3d_animation_export.py b/tools/utils/exporters/blender/qt3d_animation_export.py new file mode 100644 index 000000000..2d6575198 --- /dev/null +++ b/tools/utils/exporters/blender/qt3d_animation_export.py @@ -0,0 +1,433 @@ +############################################################################# +## +## Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the Qt3D module of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:LGPL$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU Lesser General Public License Usage +## Alternatively, this file may be used under the terms of the GNU Lesser +## General Public License version 3 as published by the Free Software +## Foundation and appearing in the file LICENSE.LGPL3 included in the +## packaging of this file. Please review the following information to +## ensure the GNU Lesser General Public License version 3 requirements +## will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 2.0 or (at your option) the GNU General +## Public license version 3 or any later version approved by the KDE Free +## Qt Foundation. The licenses are as published by the Free Software +## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-2.0.html and +## https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +# Required Blender information. +bl_info = { + "name": "Qt3D Animation Exporter", + "author": "Sean Harmer <sean.harmer@kdab.com>, Paul Lemire <paul.lemire@kdab.com>", + "version": (0, 4), + "blender": (2, 72, 0), + "location": "File > Export > Qt3D Animation (.json)", + "description": "Export animations to json to use with Qt3D", + "warning": "", + "wiki_url": "", + "tracker_url": "", + "category": "Import-Export" + } + +import bpy +import os +import struct +import mathutils +import math +import json +from array import array +from bpy_extras.io_utils import ExportHelper +from bpy.props import ( + BoolProperty, + FloatProperty, + StringProperty, + EnumProperty, + ) +from collections import defaultdict + +def frameToTime(frame): + # Get the fps to convert from frame number to time in seconds for x values + fps = bpy.context.scene.render.fps + + # Calculate time, remembering that blender uses 1-based frame numbers + return (frame - 1) / fps; + +def findResolvingObject(rootId): + if rootId == "OBJECT": + return bpy.data.objects[0] + elif rootId == "MATERIAL": + return bpy.data.materials[0] + return None + +# Note that we swap the Y and Z components because blender uses Z-up +# whereas Qt 3D tends to use Y-Up convention. +def arrayIndexFromTypeAndIndex(dataPath, index): + if dataPath.startswith("rotation"): + # Swap Y and Z components of rotations + if index == 2: + return 3 + elif index == 3: + return 2 + elif dataPath.startswith("location"): + # Swap Y and Z components of locations + if index == 1: + return 2 + elif index == 2: + return 1 + + # Otherwise keep the original index + return index + +def componentSuffix(typeName, componentIndex): + vectorComponents = ["X", "Y", "Z", "W"] + quaternionComponents = ["W", "X", "Y", "Z"] + colorComponents = ["R", "G", "B"] + + if typeName == "Vector": + return vectorComponents[componentIndex] + elif typeName == "Quaternion": + return quaternionComponents[componentIndex] + elif typeName == "Color": + return colorComponents[componentIndex] + return "Unknown" + +def resolveDataType(object, dataPath): + value = object.path_resolve(dataPath) + if isinstance(value, mathutils.Vector): + return "Vector" + elif isinstance(value, mathutils.Quaternion): + return "Quaternion" + elif isinstance(value, mathutils.Euler): + return "Euler" + value.order + elif isinstance(value, mathutils.Color): + return "Color" + return "Unknown type" + +class PropertyData: + m_action = None + m_name = "" + m_resolverObject = None + m_dataPath = "" + m_fcurveIndices = [] + m_componentIndices = [] + m_dataType = "" + m_outputDataType = "" + m_outputChannelCount = 0 + m_outputChannelSuffixes = [] + + def __init__(self): + self.m_action = None + self.m_resolverObject = None + self.m_dataPath = "" + self.m_fcurveIndices = [] + self.m_componentIndices = [] + self.m_dataType = "" + self.m_outputDataType = "" + self.m_outputChannelCount = 0 + self.m_outputChannelSuffixes = [] + + def setDataPath(self, dataPath): + self.m_dataPath = dataPath + if dataPath.startswith("rotation"): + self.m_name = "Rotation" + else: + self.m_name = dataPath.title() + self.m_name = self.m_name.replace("_", " ") + + def print(self): + print("Action = " + self.m_action.name \ + + "DataPath = " + self.m_dataPath \ + + "Name = " + self.m_name) + # + "fcurve indices =" + self.m_componentIndices + + def generateKeyframesData(self, outputComponentIndex): + outputKeyframes = [] + + # Lookup fcurve index for this component + fcurveIndex = self.m_fcurveIndices[outputComponentIndex] + + # Invert the sign of the 2nd component of quaternions for rotations + # We already swap the Y and Z components in the componentSuffix function + axisOrientationfactor = 1.0 + if self.m_name == "Rotation" and outputComponentIndex == 2: + axisOrientationfactor = -1.0 + + if self.m_dataType == self.m_outputDataType: + # We can take easy route if no data type conversion is needed + # Iterate over keyframes + fcurve = self.m_action.fcurves[fcurveIndex] + for keyframe in fcurve.keyframe_points: + outputKeyframe = { \ + "coords": [frameToTime(keyframe.co.x), axisOrientationfactor * keyframe.co.y], \ + "leftHandle": [frameToTime(keyframe.handle_left.x), axisOrientationfactor * keyframe.handle_left.y], \ + "rightHandle": [frameToTime(keyframe.handle_right.x), axisOrientationfactor * keyframe.handle_right.y] } + outputKeyframes.append(outputKeyframe) + else: + # Iterate over keyframes - we assume that all channels were keyed at the same times + # This is usually the case as blender doesn't support keying individual components + # but a user could have tweaked the individual channels + fcurve = self.m_action.fcurves[self.m_fcurveIndices[0]] + for keyframeIndex, keyframe in enumerate(fcurve.keyframe_points): + # Get data for this property + if not self.m_dataType.startswith("Euler"): + print("Unhandled data type conversion") + return None + + # Convert the control point to a quaternion + eulerOrder = self.m_dataType[-3:] + time_co = frameToTime(self.m_action.fcurves[self.m_fcurveIndices[0]].keyframe_points[keyframeIndex].co.x) + rotX = self.m_action.fcurves[self.m_fcurveIndices[0]].keyframe_points[keyframeIndex].co.y + rotY = self.m_action.fcurves[self.m_fcurveIndices[1]].keyframe_points[keyframeIndex].co.y + rotZ = self.m_action.fcurves[self.m_fcurveIndices[2]].keyframe_points[keyframeIndex].co.y + euler = mathutils.Euler((rotX, rotY, rotZ), eulerOrder) + q_co = euler.to_quaternion() + + # Convert the left handle to a quaternion + time_hl = frameToTime(self.m_action.fcurves[self.m_fcurveIndices[0]].keyframe_points[keyframeIndex].handle_left.x) + rotX = self.m_action.fcurves[self.m_fcurveIndices[0]].keyframe_points[keyframeIndex].handle_left.y + rotY = self.m_action.fcurves[self.m_fcurveIndices[1]].keyframe_points[keyframeIndex].handle_left.y + rotZ = self.m_action.fcurves[self.m_fcurveIndices[2]].keyframe_points[keyframeIndex].handle_left.y + euler = mathutils.Euler((rotX, rotY, rotZ), eulerOrder) + q_hl = euler.to_quaternion() + + # Convert the right handle to a quaternion + time_hr = frameToTime(self.m_action.fcurves[self.m_fcurveIndices[0]].keyframe_points[keyframeIndex].handle_left.x) + rotX = self.m_action.fcurves[self.m_fcurveIndices[0]].keyframe_points[keyframeIndex].handle_left.y + rotY = self.m_action.fcurves[self.m_fcurveIndices[1]].keyframe_points[keyframeIndex].handle_left.y + rotZ = self.m_action.fcurves[self.m_fcurveIndices[2]].keyframe_points[keyframeIndex].handle_left.y + euler = mathutils.Euler((rotX, rotY, rotZ), eulerOrder) + q_hr = euler.to_quaternion() + + # Extract the corresponding component + co = [] + handle_left = [] + handle_right = [] + if outputComponentIndex == 0: + co = [time_co, axisOrientationfactor * q_co.w] + handle_left = [time_hl, axisOrientationfactor * q_hl.w] + handle_right = [time_hr, axisOrientationfactor * q_hr.w] + elif outputComponentIndex == 1: + co = [time_co, axisOrientationfactor * q_co.x] + handle_left = [time_hl, axisOrientationfactor * q_hl.x] + handle_right = [time_hr, axisOrientationfactor * q_hr.x] + elif outputComponentIndex == 2: + co = [time_co, axisOrientationfactor * q_co.y] + handle_left = [time_hl, axisOrientationfactor * q_hl.y] + handle_right = [time_hr, axisOrientationfactor * q_hr.y] + elif outputComponentIndex == 3: + co = [time_co, axisOrientationfactor * q_co.z] + handle_left = [time_hl, axisOrientationfactor * q_hl.z] + handle_right = [time_hr, axisOrientationfactor * q_hr.z] + + outputKeyframe = { \ + "coords": co, \ + "leftHandle": handle_left, \ + "rightHandle": handle_right } + outputKeyframes.append(outputKeyframe) + return outputKeyframes + + def generateChannelComponentsData(self): + # First find the data type stored in the blender file + self.m_dataType = resolveDataType(self.m_resolverObject, self.m_dataPath) + + # Convert this to an output data type - we force rotations as quaternions + if self.m_dataType.startswith("Euler"): + self.m_outputDataType = "Quaternion" + self.m_outputChannelCount = 4 + for i in range(0, 4): + index = arrayIndexFromTypeAndIndex(self.m_dataPath, i) + suffix = componentSuffix(self.m_outputDataType, index) + self.m_outputChannelSuffixes.append(suffix) + else: + self.m_outputDataType = self.m_dataType + self.m_outputChannelCount = len(self.m_componentIndices) + for i in self.m_componentIndices: + index = arrayIndexFromTypeAndIndex(self.m_dataPath, i) + suffix = componentSuffix(self.m_outputDataType, index) + self.m_outputChannelSuffixes.append(suffix) + + outputChannels = [] + for i in range(0, self.m_outputChannelCount): + outputChannel = { "channelComponentName": self.m_name + " " + self.m_outputChannelSuffixes[i], "keyFrames": [] } + keyframes = self.generateKeyframesData(i) + outputChannel["keyFrames"] = keyframes + outputChannels.append(outputChannel) + + return outputChannels + + +class Qt3DAnimationConverter: + def animationsToJson(self): + propertyDataMap = defaultdict(list) + + # Pass 1 - collect data we need to produce the output in pass 2 + for action in bpy.data.actions: + groupCount = len(action.groups) + #print(" " + action.name + " for type " + action.id_root) + + # We need a datablock of the right type to be able to resolve an fcurve data path to a value. + # We need the value to be able to determine the type and eventually the correct name for the + # exported fcurve. + resolverObject = findResolvingObject(action.id_root) + + fcurveCount = len(action.fcurves) + #print(" " + action.name + " has " + str(fcurveCount) + " fcurves") + + if fcurveCount == 0: + break + + lastTitle = "" + property = PropertyData() + for fcurveIndex,fcurve in enumerate(action.fcurves): + title = fcurve.data_path.title() + + # For debugging + groupName = "<NoGroup>" + if fcurve.group != None: + groupName = fcurve.group.name + dataPath = fcurve.data_path + type = resolveDataType(resolverObject, dataPath) + labelSuffix = componentSuffix("Vector", fcurve.array_index) + print(" " + str(fcurveIndex) + ": Group: " + groupName \ + + ", Title = " + title \ + + ", Component:" + str(fcurve.array_index) \ + + ", Data Path: " + dataPath \ + + ", Data Type: " + type \ + + ", Label: " + labelSuffix) + + # Create a new PropertyData if this fcurve is for a new property + if title != lastTitle: + property = PropertyData() + property.m_action = action + property.setDataPath(fcurve.data_path) + property.m_resolverObject = resolverObject + arrayIndex = arrayIndexFromTypeAndIndex(fcurve.data_path, fcurve.array_index) + property.m_componentIndices.append(arrayIndex) + #property.m_componentIndices.append(fcurve.array_index) + property.m_fcurveIndices.append(fcurveIndex) + propertyDataMap[action.name].append(property) + else: + property.m_componentIndices.append(fcurve.array_index) + property.m_fcurveIndices.append(fcurveIndex) + + lastTitle = title + print("") + + # For debugging + print("Pass 1 - Collected data for " + str(len(propertyDataMap)) + " actions") + actionIndex = 0 + for key in propertyDataMap: + print(str(actionIndex) + ": " + key + " has " + str(len(propertyDataMap[key])) + " properties") + for propertyIndex, property in enumerate(propertyDataMap[key]): + print(" " + str(propertyIndex) + ": " + property.m_name) + actionIndex = actionIndex + 1 + + # Pass 2 + + # The data structure that will be exported + output = {"animations": []} + + actionIndex = 0 + for key in propertyDataMap: + #print(str(actionIndex) + ": " + key) + + # Create an output action + outputAction = { "animationName": key, "channels": []} + for propertyIndex, property in enumerate(propertyDataMap[key]): + #print(" " + str(propertyIndex) + ": " + property.m_name) + + # Create an output group and append it to the output action + outputGroup = { "channelComponents": [], "channelName": property.m_name } + + # Populate the channels list from the property object + outputChannels = property.generateChannelComponentsData() + outputGroup["channelComponents"] = outputChannels + + outputAction["channels"].append(outputGroup) + + output["animations"].append(outputAction) + actionIndex = actionIndex + 1 + + jsonData = json.dumps(output, indent=2, sort_keys=True, separators=(',', ': ')) + return jsonData + + +class Qt3DExporter(bpy.types.Operator, ExportHelper): + """Qt3D Exporter""" + bl_idname = "export_scene.qt3d_exporter"; + bl_label = "Qt3DExporter"; + bl_options = {'PRESET'}; + + filename_ext = "" + use_filter_folder = True + + # TO DO: Handle properly + use_mesh_modifiers = BoolProperty( + name="Apply Modifiers", + description="Apply modifiers (preview resolution)", + default=True, + ) + + # TO DO: Handle properly + use_selection_only = BoolProperty( + name="Selection Only", + description="Only export select objects", + default=False, + ) + + def __init__(self): + pass + + def execute(self, context): + print("In Execute" + bpy.context.scene.name) + + self.userpath = self.properties.filepath + + # unselect all + bpy.ops.object.select_all(action='DESELECT') + + converter = Qt3DAnimationConverter() + fileContent = converter.animationsToJson() + with open(self.userpath + ".json", '+w') as f: + f.write(fileContent) + + return {'FINISHED'} + +def createBlenderMenu(self, context): + self.layout.operator(Qt3DExporter.bl_idname, text="Qt3D Animation(.json)") + +# Register against Blender +def register(): + bpy.utils.register_class(Qt3DExporter) + bpy.types.INFO_MT_file_export.append(createBlenderMenu) + +def unregister(): + bpy.utils.unregister_class(Qt3DExporter) + bpy.types.INFO_MT_file_export.remove(createBlenderMenu) + +# Handle running the script from Blender's text editor. +if (__name__ == "__main__"): + register(); + bpy.ops.export_scene.qt3d_exporter(); diff --git a/tools/utils/qtcreator/templates/wizards/classes/qt3d/backendnode.cpp b/tools/utils/qtcreator/templates/wizards/classes/qt3d/backendnode.cpp new file mode 100644 index 000000000..46f711849 --- /dev/null +++ b/tools/utils/qtcreator/templates/wizards/classes/qt3d/backendnode.cpp @@ -0,0 +1,20 @@ +%{Cpp:LicenseTemplate}\ +#include "%{PrivateHdrFileName}" + +QT_BEGIN_NAMESPACE +%{JS: Cpp.openNamespaces('%{Class}')} +%{CN}::%{CN}() +{ +} + +void %{CN}::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) +{ +} + +void %{CN}::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) +{ +} + +%{JS: Cpp.closeNamespaces('%{Class}')}\ + +QT_END_NAMESPACE diff --git a/tools/utils/qtcreator/templates/wizards/classes/qt3d/backendnode_p.h b/tools/utils/qtcreator/templates/wizards/classes/qt3d/backendnode_p.h new file mode 100644 index 000000000..12ee68155 --- /dev/null +++ b/tools/utils/qtcreator/templates/wizards/classes/qt3d/backendnode_p.h @@ -0,0 +1,35 @@ +%{Cpp:LicenseTemplate}\ + +#ifndef %{GUARD} +#define %{GUARD} + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <Qt3DCore/qbackendnode.h> + +QT_BEGIN_NAMESPACE +%{JS: Cpp.openNamespaces('%{Class}')} +class %{CN} : public Qt3DCore::%{Base} +{ +public: + %{CN}(); + + void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) Q_DECL_OVERRIDE; + +private: + void initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) Q_DECL_FINAL; +}; +%{JS: Cpp.closeNamespaces('%{Class}')} + +QT_END_NAMESPACE + +#endif // %{GUARD}\ diff --git a/tools/utils/qtcreator/templates/wizards/classes/qt3d/file.cpp b/tools/utils/qtcreator/templates/wizards/classes/qt3d/file.cpp index 4200859a9..5106a9e74 100644 --- a/tools/utils/qtcreator/templates/wizards/classes/qt3d/file.cpp +++ b/tools/utils/qtcreator/templates/wizards/classes/qt3d/file.cpp @@ -4,7 +4,6 @@ QT_BEGIN_NAMESPACE %{JS: Cpp.openNamespaces('%{Class}')} -@if '%{Base}' === 'QNode' || '%{Base}' === 'QComponent' || '%{Base}' === 'QEntity' %{CN}Private::%{CN}Private() : Qt3DCore::%{Base}Private() { @@ -23,11 +22,7 @@ QT_BEGIN_NAMESPACE %{CN}::~%{CN}() { } -@else -// TODO: Implement QBackendNode template -@endif -@if '%{Base}' === 'QNode' || '%{Base}' === 'QComponent' || '%{Base}' === 'QEntity' Qt3DCore::QNodeCreatedChangeBasePtr %{CN}::createNodeCreationChange() const { auto creationChange = Qt3DCore::QNodeCreatedChangePtr<%{CN}Data>::create(this); @@ -36,7 +31,6 @@ Qt3DCore::QNodeCreatedChangeBasePtr %{CN}::createNodeCreationChange() const // TODO: Send data members in creation change return creationChange; } -@endif %{JS: Cpp.closeNamespaces('%{Class}')}\ QT_END_NAMESPACE diff --git a/tools/utils/qtcreator/templates/wizards/classes/qt3d/file.h b/tools/utils/qtcreator/templates/wizards/classes/qt3d/file.h index 9060461eb..c4162d647 100644 --- a/tools/utils/qtcreator/templates/wizards/classes/qt3d/file.h +++ b/tools/utils/qtcreator/templates/wizards/classes/qt3d/file.h @@ -9,8 +9,6 @@ #include <Qt3DCore/qcomponent.h> @elsif '%{Base}' === 'QEntity' #include <Qt3DCore/qentity.h> -@elsif '%{Base}' === 'QBackendNode' -#include <Qt3DCore/qbackendnode.h> @endif QT_BEGIN_NAMESPACE diff --git a/tools/utils/qtcreator/templates/wizards/classes/qt3d/file_p.h b/tools/utils/qtcreator/templates/wizards/classes/qt3d/file_p.h index 9de21e805..d1acea35e 100644 --- a/tools/utils/qtcreator/templates/wizards/classes/qt3d/file_p.h +++ b/tools/utils/qtcreator/templates/wizards/classes/qt3d/file_p.h @@ -20,8 +20,6 @@ #include <Qt3DCore/private/qcomponent_p.h> @elsif '%{Base}' === 'QEntity' #include <Qt3DCore/private/qentity_p.h> -@elsif '%{Base}' === 'QBackendNode' -#include <Qt3DCore/private/qbackendnode_p.h> @endif QT_BEGIN_NAMESPACE diff --git a/tools/utils/qtcreator/templates/wizards/classes/qt3d/wizard.json b/tools/utils/qtcreator/templates/wizards/classes/qt3d/wizard.json index c9fe63685..8079aa4b4 100644 --- a/tools/utils/qtcreator/templates/wizards/classes/qt3d/wizard.json +++ b/tools/utils/qtcreator/templates/wizards/classes/qt3d/wizard.json @@ -73,7 +73,8 @@ "name": "HdrFileName", "type": "LineEdit", "trDisplayName": "Header file:", - "mandatory": true, + "mandatory": false, + "enabled": "%{JS: '%{BaseCB}' !== 'QBackendNode'}", "data": { "trText": "%{JS: Cpp.classToFileName('%{Class}', '%{JS: Util.preferredSuffix('text/x-c++hdr')}')}" } }, { @@ -120,16 +121,31 @@ { "source": "file.h", "target": "%{HdrPath}", + "condition": "%{JS: '%{Base}' !== 'QBackendNode'}", "openInEditor": true }, { "source": "file_p.h", "target": "%{PrivateHdrPath}", + "condition": "%{JS: '%{Base}' !== 'QBackendNode'}", "openInEditor": true }, { "source": "file.cpp", "target": "%{SrcPath}", + "condition": "%{JS: '%{Base}' !== 'QBackendNode'}", + "openInEditor": true + }, + { + "source": "backendnode.cpp", + "target": "%{SrcPath}", + "condition": "%{JS: '%{Base}' === 'QBackendNode'}", + "openInEditor": true + }, + { + "source": "backendnode_p.h", + "target": "%{PrivateHdrPath}", + "condition": "%{JS: '%{Base}' === 'QBackendNode'}", "openInEditor": true } ] |