Added skeleton hierarchy tree view to the character editor

This commit is contained in:
parax0 2016-05-01 20:00:35 -06:00
parent ce688fcb8e
commit ed16d05136
7 changed files with 273 additions and 107 deletions

View File

@ -82,10 +82,10 @@ void CCharacterNode::Draw(FRenderOptions Options, int ComponentIndex, const SVie
} }
} }
SRayIntersection CCharacterNode::RayNodeIntersectTest(const CRay& rkRay, u32 /*AssetID*/, const SViewInfo& /*rkViewInfo*/) SRayIntersection CCharacterNode::RayNodeIntersectTest(const CRay& rkRay, u32 /*AssetID*/, const SViewInfo& rkViewInfo)
{ {
// Check for bone under ray. Doesn't check for model intersections atm // Check for bone under ray. Doesn't check for model intersections atm
if (mpCharacter) if (mpCharacter && rkViewInfo.ShowFlags.HasFlag(eShowSkeletons))
{ {
CSkeleton *pSkel = mpCharacter->NodeSkeleton(mActiveCharSet); CSkeleton *pSkel = mpCharacter->NodeSkeleton(mActiveCharSet);

View File

@ -3,6 +3,7 @@
#include "Editor/UICommon.h" #include "Editor/UICommon.h"
#include <Math/MathUtil.h> #include <Math/MathUtil.h>
#include <QFileDialog> #include <QFileDialog>
#include <QTreeView>
CCharacterEditor::CCharacterEditor(QWidget *parent) CCharacterEditor::CCharacterEditor(QWidget *parent)
: QMainWindow(parent) : QMainWindow(parent)
@ -47,6 +48,12 @@ CCharacterEditor::CCharacterEditor(QWidget *parent)
connect(ui->PlayPauseButton, SIGNAL(pressed()), this, SLOT(TogglePlay())); connect(ui->PlayPauseButton, SIGNAL(pressed()), this, SLOT(TogglePlay()));
connect(ui->LoopButton, SIGNAL(toggled(bool)), this, SLOT(ToggleLoop(bool))); connect(ui->LoopButton, SIGNAL(toggled(bool)), this, SLOT(ToggleLoop(bool)));
connect(ui->AnimSpeedSpinBox, SIGNAL(valueChanged(double)), this, SLOT(AnimSpeedSpinBoxChanged(double))); connect(ui->AnimSpeedSpinBox, SIGNAL(valueChanged(double)), this, SLOT(AnimSpeedSpinBoxChanged(double)));
// Init skeleton tree view
ui->SkeletonHierarchyTreeView->setModel(&mSkeletonModel);
QList<int> SplitterSizes;
SplitterSizes << width() * 0.2 << width() * 0.8;
ui->splitter->setSizes(SplitterSizes);
} }
CCharacterEditor::~CCharacterEditor() CCharacterEditor::~CCharacterEditor()
@ -139,6 +146,12 @@ void CCharacterEditor::Open()
SetActiveAnimation(0); SetActiveAnimation(0);
mpAnimComboBox->blockSignals(false); mpAnimComboBox->blockSignals(false);
// Set up skeleton tree view
CSkeleton *pSkel = mpSet->NodeSkeleton(mCurrentChar);
mSkeletonModel.SetSkeleton(pSkel);
ui->SkeletonHierarchyTreeView->expandAll();
ui->SkeletonHierarchyTreeView->resizeColumnToContents(0);
} }
gResCache.Clean(); gResCache.Clean();

View File

@ -2,6 +2,7 @@
#define CCHARACTEREDITOR_H #define CCHARACTEREDITOR_H
#include "CCharacterEditorViewport.h" #include "CCharacterEditorViewport.h"
#include "CSkeletonHierarchyModel.h"
#include <Core/Scene/CScene.h> #include <Core/Scene/CScene.h>
#include <Core/Scene/CCharacterNode.h> #include <Core/Scene/CCharacterNode.h>
@ -21,6 +22,7 @@ class CCharacterEditor : public QMainWindow
CScene *mpScene; CScene *mpScene;
CCharacterNode *mpCharNode; CCharacterNode *mpCharNode;
CSkeletonHierarchyModel mSkeletonModel;
QComboBox *mpCharComboBox; QComboBox *mpCharComboBox;
QComboBox *mpAnimComboBox; QComboBox *mpAnimComboBox;
QTimer mRefreshTimer; QTimer mRefreshTimer;

View File

@ -14,113 +14,153 @@
<string>Prime World Editor - Character Editor</string> <string>Prime World Editor - Character Editor</string>
</property> </property>
<widget class="QWidget" name="CentralWidget"> <widget class="QWidget" name="CentralWidget">
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>
<widget class="CCharacterEditorViewport" name="Viewport" native="true"> <widget class="QSplitter" name="splitter">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="AnimSlider">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
</widget> <widget class="QTreeView" name="SkeletonHierarchyTreeView">
</item> <property name="editTriggers">
<item> <set>QAbstractItemView::NoEditTriggers</set>
<layout class="QHBoxLayout" name="horizontalLayout"> </property>
<item> <property name="showDropIndicator" stdset="0">
<widget class="QPushButton" name="LoopButton"> <bool>false</bool>
<property name="text"> </property>
<string>Loop</string> <property name="alternatingRowColors">
</property> <bool>true</bool>
<property name="checkable"> </property>
<bool>true</bool> <property name="selectionMode">
</property> <enum>QAbstractItemView::NoSelection</enum>
<property name="checked"> </property>
<bool>true</bool> <property name="verticalScrollMode">
</property> <enum>QAbstractItemView::ScrollPerPixel</enum>
</widget> </property>
</item> <property name="indentation">
<item> <number>15</number>
<widget class="QPushButton" name="PlayPauseButton"> </property>
<property name="text"> <property name="rootIsDecorated">
<string>Pause</string> <bool>true</bool>
</property> </property>
</widget> <property name="itemsExpandable">
</item> <bool>true</bool>
<item> </property>
<spacer name="horizontalSpacer"> <attribute name="headerVisible">
<property name="orientation"> <bool>false</bool>
<enum>Qt::Horizontal</enum> </attribute>
</property> </widget>
<property name="sizeHint" stdset="0"> <widget class="QWidget" name="">
<size> <layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0,0">
<width>40</width> <item>
<height>20</height> <widget class="CCharacterEditorViewport" name="Viewport" native="true">
</size> <property name="sizePolicy">
</property> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
</spacer> <horstretch>0</horstretch>
</item> <verstretch>1</verstretch>
<item> </sizepolicy>
<widget class="QLabel" name="AnimSpeedLabel"> </property>
<property name="text"> </widget>
<string>Speed:</string> </item>
</property> <item>
</widget> <widget class="QSlider" name="AnimSlider">
</item> <property name="orientation">
<item> <enum>Qt::Horizontal</enum>
<widget class="WDraggableSpinBox" name="AnimSpeedSpinBox"> </property>
<property name="suffix"> </widget>
<string>x</string> </item>
</property> <item>
<property name="decimals"> <layout class="QHBoxLayout" name="horizontalLayout">
<number>1</number> <item>
</property> <widget class="QPushButton" name="LoopButton">
<property name="minimum"> <property name="text">
<double>-10.000000000000000</double> <string>Loop</string>
</property> </property>
<property name="maximum"> <property name="checkable">
<double>10.000000000000000</double> <bool>true</bool>
</property> </property>
<property name="singleStep"> <property name="checked">
<double>0.100000000000000</double> <bool>true</bool>
</property> </property>
<property name="value"> </widget>
<double>1.000000000000000</double> </item>
</property> <item>
</widget> <widget class="QPushButton" name="PlayPauseButton">
</item> <property name="text">
</layout> <string>Pause</string>
</item> </property>
<item> </widget>
<widget class="QLabel" name="FrameLabel"> </item>
<property name="sizePolicy"> <item>
<sizepolicy hsizetype="Preferred" vsizetype="Minimum"> <spacer name="horizontalSpacer">
<horstretch>0</horstretch> <property name="orientation">
<verstretch>0</verstretch> <enum>Qt::Horizontal</enum>
</sizepolicy> </property>
</property> <property name="sizeHint" stdset="0">
<property name="maximumSize"> <size>
<size> <width>40</width>
<width>16777215</width> <height>20</height>
<height>21</height> </size>
</size> </property>
</property> </spacer>
<property name="text"> </item>
<string>Frame 0 / 0 (0.000s/0.000s)</string> <item>
</property> <widget class="QLabel" name="AnimSpeedLabel">
<property name="textFormat"> <property name="text">
<enum>Qt::PlainText</enum> <string>Speed:</string>
</property> </property>
<property name="alignment"> </widget>
<set>Qt::AlignCenter</set> </item>
</property> <item>
<widget class="WDraggableSpinBox" name="AnimSpeedSpinBox">
<property name="suffix">
<string>x</string>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="minimum">
<double>-10.000000000000000</double>
</property>
<property name="maximum">
<double>10.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="FrameLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>21</height>
</size>
</property>
<property name="text">
<string>Frame 0 / 0 (0.000s/0.000s)</string>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</widget> </widget>
</item> </item>
</layout> </layout>

View File

@ -0,0 +1,87 @@
#include "CSkeletonHierarchyModel.h"
#include "Editor/UICommon.h"
CSkeletonHierarchyModel::CSkeletonHierarchyModel(QObject *pParent /*= 0*/)
: QAbstractItemModel(pParent)
, mpSkeleton(nullptr)
{
}
QModelIndex CSkeletonHierarchyModel::index(int Row, int Column, const QModelIndex& rkParent) const
{
if (!hasIndex(Row, Column, rkParent))
return QModelIndex();
if (!rkParent.isValid())
{
if (mpSkeleton)
return createIndex(Row, Column, mpSkeleton->RootBone());
else
return QModelIndex();
}
CBone *pBone = (CBone*) rkParent.internalPointer();
if (Row < (int) pBone->NumChildren())
return createIndex(Row, Column, pBone->ChildByIndex(Row));
else
return QModelIndex();
}
QModelIndex CSkeletonHierarchyModel::parent(const QModelIndex& rkChild) const
{
CBone *pBone = (CBone*) rkChild.internalPointer();
if (pBone->Parent())
{
// Determine parent index
CBone *pParent = pBone->Parent();
if (pParent->Parent())
{
CBone *pGrandparent = pParent->Parent();
for (u32 iChild = 0; iChild < pGrandparent->NumChildren(); iChild++)
{
if (pGrandparent->ChildByIndex(iChild) == pParent)
return createIndex(iChild, 0, pParent);
}
}
else return createIndex(0, 0, pParent);
}
return QModelIndex();
}
int CSkeletonHierarchyModel::rowCount(const QModelIndex& rkParent) const
{
if (!mpSkeleton) return 0;
CBone *pBone = (CBone*) rkParent.internalPointer();
return (pBone ? pBone->NumChildren() : 1);
}
int CSkeletonHierarchyModel::columnCount(const QModelIndex& /*rkParent*/) const
{
return 1;
}
QVariant CSkeletonHierarchyModel::data(const QModelIndex& rkIndex, int Role) const
{
if (Role == Qt::DisplayRole || Role == Qt::ToolTipRole)
{
CBone *pBone = (CBone*) rkIndex.internalPointer();
return TO_QSTRING(pBone->Name());
}
return QVariant::Invalid;
}
void CSkeletonHierarchyModel::SetSkeleton(CSkeleton *pSkel)
{
if (mpSkeleton != pSkel)
{
beginResetModel();
mpSkeleton = pSkel;
endResetModel();
}
}

View File

@ -0,0 +1,22 @@
#ifndef CSKELETONHIERARCHYMODEL
#define CSKELETONHIERARCHYMODEL
#include <QAbstractItemModel>
#include <Core/Resource/CSkeleton.h>
class CSkeletonHierarchyModel : public QAbstractItemModel
{
CSkeleton *mpSkeleton;
public:
explicit CSkeletonHierarchyModel(QObject *pParent = 0);
QModelIndex index(int Row, int Column, const QModelIndex& rkParent) const;
QModelIndex parent(const QModelIndex& rkChild) const;
int rowCount(const QModelIndex& rkParent) const;
int columnCount(const QModelIndex& rkParent) const;
QVariant data(const QModelIndex& rkIndex, int Role) const;
void SetSkeleton(CSkeleton *pSkel);
};
#endif // CSKELETONHIERARCHYMODEL

View File

@ -159,7 +159,8 @@ HEADERS += \
CAboutDialog.h \ CAboutDialog.h \
CharacterEditor/CCharacterEditor.h \ CharacterEditor/CCharacterEditor.h \
CharacterEditor/CCharacterEditorViewport.h \ CharacterEditor/CCharacterEditorViewport.h \
CGridRenderable.h CGridRenderable.h \
CharacterEditor/CSkeletonHierarchyModel.h
# Source Files # Source Files
SOURCES += \ SOURCES += \
@ -218,7 +219,8 @@ SOURCES += \
WorldEditor/CRepackInfoDialog.cpp \ WorldEditor/CRepackInfoDialog.cpp \
CAboutDialog.cpp \ CAboutDialog.cpp \
CharacterEditor/CCharacterEditor.cpp \ CharacterEditor/CCharacterEditor.cpp \
CharacterEditor/CCharacterEditorViewport.cpp CharacterEditor/CCharacterEditorViewport.cpp \
CharacterEditor/CSkeletonHierarchyModel.cpp
# UI Files # UI Files
FORMS += \ FORMS += \