mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-05-25 08:41:26 +00:00
213 lines
5.9 KiB
C++
213 lines
5.9 KiB
C++
#include "CCharacterEditor.h"
|
|
#include "ui_CCharacterEditor.h"
|
|
#include "Editor/UICommon.h"
|
|
#include <Math/MathUtil.h>
|
|
#include <QFileDialog>
|
|
|
|
CCharacterEditor::CCharacterEditor(QWidget *parent)
|
|
: QMainWindow(parent)
|
|
, ui(new Ui::CCharacterEditor)
|
|
, mpScene(new CScene())
|
|
, mpCharNode(new CCharacterNode(mpScene, -1))
|
|
, mPlayAnim(true)
|
|
, mLoopAnim(true)
|
|
, mPlaybackSpeed(1.f)
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
ui->Viewport->SetNode(mpCharNode);
|
|
|
|
CCamera& rCamera = ui->Viewport->Camera();
|
|
rCamera.Snap(CVector3f(0, 3, 1));
|
|
rCamera.SetOrbit(CVector3f(0, 0, 1), 3.f);
|
|
rCamera.SetMoveSpeed(0.5f);
|
|
|
|
// Init UI
|
|
ui->ToolBar->addSeparator();
|
|
|
|
mpCharComboBox = new QComboBox(this);
|
|
mpCharComboBox->setMinimumWidth(175);
|
|
ui->ToolBar->addWidget(mpCharComboBox);
|
|
|
|
mpAnimComboBox = new QComboBox(this);
|
|
mpAnimComboBox->setMinimumWidth(175);
|
|
ui->ToolBar->addWidget(mpAnimComboBox);
|
|
|
|
connect(&mRefreshTimer, SIGNAL(timeout()), this, SLOT(RefreshViewport()));
|
|
mRefreshTimer.start(0);
|
|
|
|
connect(ui->Viewport, SIGNAL(HoverBoneChanged(u32)), this, SLOT(HoverBoneChanged(u32)));
|
|
connect(ui->ActionOpen, SIGNAL(triggered()), this, SLOT(Open()));
|
|
connect(mpCharComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(SetActiveCharacterIndex(int)));
|
|
connect(mpAnimComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(SetActiveAnimation(int)));
|
|
|
|
connect(ui->AnimSlider, SIGNAL(valueChanged(int)), this, SLOT(SetAnimTime(int)));
|
|
connect(ui->PlayPauseButton, SIGNAL(pressed()), this, SLOT(PlayPauseButtonPressed()));
|
|
connect(ui->LoopButton, SIGNAL(toggled(bool)), this, SLOT(LoopButtonToggled(bool)));
|
|
connect(ui->AnimSpeedSpinBox, SIGNAL(valueChanged(double)), this, SLOT(AnimSpeedSpinBoxChanged(double)));
|
|
}
|
|
|
|
CCharacterEditor::~CCharacterEditor()
|
|
{
|
|
delete ui;
|
|
}
|
|
|
|
void CCharacterEditor::UpdateAnimTime()
|
|
{
|
|
double Time = CTimer::GlobalTime();
|
|
double DeltaTime = Time - mLastAnimUpdate;
|
|
mLastAnimUpdate = Time;
|
|
|
|
if (mPlayAnim && !ui->AnimSlider->isSliderDown())
|
|
{
|
|
mAnimTime += DeltaTime * mPlaybackSpeed;
|
|
|
|
CAnimation *pAnim = CurrentAnimation();
|
|
float AnimLength = (pAnim ? pAnim->Duration() : 0.f);
|
|
|
|
if (mAnimTime > AnimLength)
|
|
{
|
|
if (mLoopAnim)
|
|
mAnimTime = fmodf(mAnimTime, AnimLength);
|
|
else
|
|
mAnimTime = AnimLength;
|
|
}
|
|
|
|
if (mAnimTime < 0.f)
|
|
{
|
|
if (mLoopAnim)
|
|
mAnimTime = AnimLength + fmodf(mAnimTime, AnimLength);
|
|
else
|
|
mAnimTime = 0.f;
|
|
}
|
|
|
|
SetAnimTime(mAnimTime);
|
|
}
|
|
}
|
|
|
|
CAnimation* CCharacterEditor::CurrentAnimation() const
|
|
{
|
|
if (mpSet)
|
|
return mpSet->Animation(mCurrentAnim);
|
|
else
|
|
return nullptr;
|
|
}
|
|
|
|
// ************ PUBLIC SLOTS ************
|
|
void CCharacterEditor::Open()
|
|
{
|
|
QString CharFilename = QFileDialog::getOpenFileName(this, "Open Character", "", "Animation Character Set (*.ANCS)");
|
|
if (CharFilename.isEmpty()) return;
|
|
|
|
mpSet = gResCache.GetResource(CharFilename.toStdString());
|
|
|
|
if (mpSet)
|
|
{
|
|
mpCharNode->SetCharSet(mpSet);
|
|
setWindowTitle("Prime World Editor - Character Editor: " + TO_QSTRING(mpSet->Source()));
|
|
|
|
// Set up character combo box
|
|
mpCharComboBox->blockSignals(true);
|
|
mpCharComboBox->clear();
|
|
|
|
for (u32 iChar = 0; iChar < mpSet->NumNodes(); iChar++)
|
|
mpCharComboBox->addItem( TO_QSTRING(mpSet->NodeName(iChar)) );
|
|
|
|
SetActiveCharacterIndex(0);
|
|
mpCharComboBox->blockSignals(false);
|
|
|
|
// Set up anim combo box
|
|
mpAnimComboBox->blockSignals(true);
|
|
mpAnimComboBox->clear();
|
|
|
|
for (u32 iAnim = 0; iAnim < mpSet->NumAnims(); iAnim++)
|
|
mpAnimComboBox->addItem( TO_QSTRING(mpSet->AnimName(iAnim)) );
|
|
|
|
SetActiveAnimation(0);
|
|
mpAnimComboBox->blockSignals(false);
|
|
}
|
|
|
|
gResCache.Clean();
|
|
}
|
|
|
|
void CCharacterEditor::RefreshViewport()
|
|
{
|
|
UpdateAnimTime();
|
|
ui->Viewport->ProcessInput();
|
|
ui->Viewport->Render();
|
|
}
|
|
|
|
void CCharacterEditor::HoverBoneChanged(u32 BoneID)
|
|
{
|
|
if (BoneID == 0xFFFFFFFF)
|
|
ui->StatusBar->clearMessage();
|
|
else
|
|
ui->StatusBar->showMessage(QString("Bone %1: %2").arg(BoneID).arg( TO_QSTRING(mpSet->NodeSkeleton(mCurrentChar)->BoneByID(BoneID)->Name()) ));
|
|
}
|
|
|
|
void CCharacterEditor::SetActiveCharacterIndex(int CharIndex)
|
|
{
|
|
mCurrentChar = CharIndex;
|
|
mpCharNode->SetActiveChar((u32) CharIndex);
|
|
}
|
|
|
|
void CCharacterEditor::SetActiveAnimation(int AnimIndex)
|
|
{
|
|
mCurrentAnim = AnimIndex;
|
|
mpCharNode->SetActiveAnim((u32) AnimIndex);
|
|
mLastAnimUpdate = CTimer::GlobalTime();
|
|
|
|
ui->AnimSlider->blockSignals(true);
|
|
ui->AnimSlider->setMaximum((int) (mpSet->Animation(AnimIndex)->Duration() * 1000));
|
|
ui->AnimSlider->blockSignals(false);
|
|
|
|
SetAnimTime(0.f);
|
|
}
|
|
|
|
void CCharacterEditor::SetAnimTime(int Time)
|
|
{
|
|
float FloatTime = Time / 1000.f;
|
|
SetAnimTime(FloatTime);
|
|
}
|
|
|
|
void CCharacterEditor::SetAnimTime(float Time)
|
|
{
|
|
mAnimTime = Time;
|
|
|
|
if (ui->AnimSlider != sender())
|
|
{
|
|
int IntTime = (int) (Time * 1000);
|
|
ui->AnimSlider->setValue(IntTime);
|
|
}
|
|
|
|
mpCharNode->SetAnimTime(Time);
|
|
|
|
CAnimation *pAnim = (mpSet ? mpSet->Animation(mCurrentAnim) : nullptr);
|
|
u32 NumKeys = 1, CurKey = 0;
|
|
|
|
if (pAnim)
|
|
{
|
|
NumKeys = pAnim->NumKeys();
|
|
CurKey = Math::Min<u32>((u32) (Time / pAnim->TickInterval()) + 1, NumKeys - 1);
|
|
}
|
|
|
|
ui->FrameLabel->setText(QString("Frame %1 / %2").arg(CurKey).arg(NumKeys - 1));
|
|
}
|
|
|
|
void CCharacterEditor::PlayPauseButtonPressed()
|
|
{
|
|
mPlayAnim = !mPlayAnim;
|
|
QString NewText = (mPlayAnim ? "Pause" : "Play");
|
|
ui->PlayPauseButton->setText(NewText);
|
|
}
|
|
|
|
void CCharacterEditor::LoopButtonToggled(bool Checked)
|
|
{
|
|
mLoopAnim = Checked;
|
|
}
|
|
|
|
void CCharacterEditor::AnimSpeedSpinBoxChanged(double NewVal)
|
|
{
|
|
mPlaybackSpeed = (float) NewVal;
|
|
}
|