From c3e065e50ba25597153eb701398e25dfd96a12fd Mon Sep 17 00:00:00 2001 From: hzqst <113660872@qq.com> Date: Tue, 13 Jul 2021 14:24:30 +0800 Subject: [PATCH] Add event-editing and sequence-editing support. --- src/c/hlmv_event.cpp | 164 ++++++++++++++++++++++++++++++++++------- src/c/hlmv_seq.cpp | 123 ++++++++++++++++++++++--------- src/m/studio_utils.cpp | 10 +-- src/v/hlmv.h | 2 + src/v/hlmv.ui | 122 ++++++++++++++++++++---------- 5 files changed, 316 insertions(+), 105 deletions(-) diff --git a/src/c/hlmv_event.cpp b/src/c/hlmv_event.cpp index 865f3bd..82dce3d 100644 --- a/src/c/hlmv_event.cpp +++ b/src/c/hlmv_event.cpp @@ -1,43 +1,156 @@ #include "hlmv.h" #include "ViewerSettings.h" #include "StudioModel.h" +#include +#include + +void QtGuiApplication1::editEvents() +{ + bool ok = false; + + studiohdr_t *hdr = g_studioModel.getStudioHeader(); + + if (!hdr) + { + return; + } + + int seq = ui.cEvent->currentData().toInt(&ok); + + if (!ok) + { + seq = ui.cSequence->currentRow(); + if (seq < 0 || seq >= hdr->numseq) + return; + } + + QString str; + + mstudioseqdesc_t *pseqdescs = (mstudioseqdesc_t *)(((byte *)hdr + hdr->seqindex)) + seq; + + for (int i = 0; i < pseqdescs->numevents; ++i) + { + mstudioevent_t *pevents = (mstudioevent_t *)((byte *)hdr + pseqdescs->eventindex) + i; + + str += QString("%1, %2, %3, %4\n") + .arg(pevents->frame) + .arg(pevents->event) + .arg(pevents->type) + .arg(pevents->event == 5004 ? QString(pevents->options) : ""); + } + + bool isOK = false; + QString text = QInputDialog::getMultiLineText( + this, + tr("Edit events"), + tr("Format: frame, event, type, options (string)"), + str, + &isOK); + + if (isOK) + { + std::vector evlist; + + QStringList lines = text.split("\n"); + + for (int i = 0; i < lines.size(); ++i) + { + QStringList evstr = lines[i].split(","); + if (evstr.size() == 4) + { + mstudioevent_t ev = {0}; + + ev.frame = evstr[0].trimmed().toInt(&isOK); + if (!isOK) + continue; + + ev.event = evstr[1].trimmed().toInt(&isOK); + if (!isOK) + continue; + + ev.type = evstr[2].trimmed().toInt(&isOK); + if (!isOK) + continue; + + if (ev.event == 5004) + { + auto optstr = evstr[3].trimmed().toLocal8Bit(); + memcpy(ev.options, optstr.data(), std::min(optstr.size(), 63) ); + } + evlist.emplace_back(ev); + } + } + + if (evlist.size() > 0) + { + if (pseqdescs->numevents < evlist.size()) + { + int original_length = hdr->texturedataindex; + auto original_texturedata = ((byte *)hdr + hdr->texturedataindex); + int texturedata_length = hdr->length - hdr->texturedataindex; + + int extend_length = sizeof(mstudioevent_t) * evlist.size(); + hdr->texturedataindex += extend_length; + hdr->length += extend_length; + + auto new_texturedata = ((byte *)hdr + hdr->texturedataindex); + memmove(new_texturedata, original_texturedata, texturedata_length); + + pseqdescs->eventindex = original_length; + + auto ptexture = (mstudiotexture_t *)((byte *)hdr + hdr->textureindex); + for (int i = 0; i < hdr->numtextures; i++) + { + ptexture->index += extend_length; + ptexture++; + } + } + + if (pseqdescs->eventindex) + { + mstudioevent_t *pevents_new = (mstudioevent_t *)((byte *)hdr + pseqdescs->eventindex); + memcpy(pevents_new, evlist.data(), sizeof(mstudioevent_t) * evlist.size()); + } + } + pseqdescs->numevents = evlist.size(); + } +} void QtGuiApplication1::setEventInfo(int index) { - char str[1024]; + QString str; - studiohdr_t *hdr = g_studioModel.getStudioHeader (); + studiohdr_t *hdr = g_studioModel.getStudioHeader(); if (!hdr) + { + ui.lEventInfo->setText(""); return; + } - mstudioseqdesc_t *pseqdescs = (mstudioseqdesc_t *) ((byte *)hdr + hdr->seqindex); + bool ok = false; + + int seq = ui.cEvent->currentData().toInt(&ok); - if(!ui.cEvent->count()) + if (!ok) { - ui.lEventInfo->setText (""); + ui.lEventInfo->setText(""); return; } - if (pseqdescs->numevents) + mstudioseqdesc_t *pseqdescs = (mstudioseqdesc_t *) (((byte *)hdr + hdr->seqindex)) + seq; + + if (index >= 0 && index < pseqdescs->numevents) { mstudioevent_t *pevents = (mstudioevent_t *) ((byte *)hdr + pseqdescs->eventindex) + index; - sprintf (str, - "Frame: %d " - "Event: %d " - "Type: %d\n" - "Options: %s", - pevents->frame, - pevents->event, - pevents->type, - pevents->options - ); - } - else - { - str[0] = '\0'; + str = QString("Frame: %1, Event: %2, Type: %3\nOptions: %4") + .arg(pevents->frame) + .arg(pevents->event) + .arg(pevents->type) + .arg(pevents->event == 5004 ? QString(pevents->options) : ""); } + ui.lEventInfo->setText (str); } @@ -50,16 +163,13 @@ void QtGuiApplication1::setEvent (int seq) if (!hdr) return; - mstudioseqdesc_t *pseqdescs = (mstudioseqdesc_t *) ((byte *)hdr + hdr->seqindex); //g_viewerSettings.sequence; + mstudioseqdesc_t *pseqdescs = (mstudioseqdesc_t *) ((byte *)hdr + hdr->seqindex); ui.cEvent->clear (); - if (0 < pseqdescs[seq].numevents) + for (int i = 0; i < pseqdescs[seq].numevents; i++) { - for (int i = 1; i <= pseqdescs[seq].numevents; i++) - { - sprintf (str, "Event %d", i); - ui.cEvent->addItem (str); - } + sprintf(str, "Event %d", i); + ui.cEvent->addItem(str, QVariant(seq)); } ui.cEvent->setCurrentIndex (0); setEventInfo(0); diff --git a/src/c/hlmv_seq.cpp b/src/c/hlmv_seq.cpp index 94f0f3f..f4af6b6 100644 --- a/src/c/hlmv_seq.cpp +++ b/src/c/hlmv_seq.cpp @@ -1,29 +1,78 @@ #include "hlmv.h" #include "ViewerSettings.h" #include "StudioModel.h" +#include -void QtGuiApplication1::initSequences () +void QtGuiApplication1::editSequence() { - studiohdr_t *hdr = g_studioModel.getStudioHeader (); - if (hdr) + studiohdr_t *hdr = g_studioModel.getStudioHeader(); + + if (!hdr) + return; + + if (g_viewerSettings.sequence >= hdr->numseq || g_viewerSettings.sequence < 0) + return; + + mstudioseqdesc_t *pseqdesc = (mstudioseqdesc_t *)((byte *)hdr + hdr->seqindex) + g_viewerSettings.sequence; + + bool isOK = false; + QString str = QString("%1, %2") + .arg(pseqdesc->flags) + .arg(pseqdesc->fps); + + QString text = QInputDialog::getMultiLineText( + this, + tr("Edit events"), + tr("Format: flags, fps"), + str, + &isOK); + + if (isOK) { - ui.cSequence->clear(); - ui.cWpSequence->clear (); - for (int i = 0; i < hdr->numseq; i++) + QStringList seqstr = text.split(","); + if (seqstr.size() == 2) { - mstudioseqdesc_t *pseqdescs = (mstudioseqdesc_t *) ((byte *) hdr + hdr->seqindex); - ui.cSequence->addItem (pseqdescs[i].label); - ui.cWpSequence->addItem (pseqdescs[i].label); + int flags = seqstr[0].trimmed().toInt(&isOK); + if (isOK) + pseqdesc->flags = flags; + float fps = seqstr[1].trimmed().toFloat(&isOK); + if (isOK) + pseqdesc->fps = fps; + + setSequenceInfo(); } + } +} - ui.cSequence->setCurrentRow (0); - ui.cWpSequence->setCurrentIndex (0); +void QtGuiApplication1::initSequences () +{ + studiohdr_t *hdr = g_studioModel.getStudioHeader(); + + if (!hdr) + return; + + ui.cSequence->clear(); + ui.cWpSequence->clear (); + + for (int i = 0; i < hdr->numseq; i++) + { + mstudioseqdesc_t *pseqdescs = (mstudioseqdesc_t *) ((byte *) hdr + hdr->seqindex); + ui.cSequence->addItem(pseqdescs[i].label); + ui.cWpSequence->addItem(pseqdescs[i].label); } + + ui.cSequence->setCurrentRow(0); + ui.cWpSequence->setCurrentIndex(0); } void QtGuiApplication1::setSequence(int index) { - if(index < 0) + studiohdr_t *hdr = g_studioModel.getStudioHeader(); + + if (!hdr) + return; + + if (index >= hdr->numseq || index < 0) return; ui.cSequence->setCurrentRow(index); @@ -31,41 +80,43 @@ void QtGuiApplication1::setSequence(int index) g_studioModel.SetSequence(index); g_viewerSettings.sequence = index; - setSequenceInfo (); + setSequenceInfo(); setEvent (index); } -void QtGuiApplication1::setSequenceInfo () +void QtGuiApplication1::setSequenceInfo() { - char str[1024]; - studiohdr_t *hdr = g_studioModel.getStudioHeader (); if (!hdr) return; + if (g_viewerSettings.sequence >= hdr->numseq || g_viewerSettings.sequence < 0) + return; + mstudioseqdesc_t *pseqdesc = (mstudioseqdesc_t *) ((byte *) hdr + hdr->seqindex) + g_viewerSettings.sequence; - sprintf (str, - "Sequence#: %d\n" - "Frames: %d\n" - "FPS: %d\n" - "Blends: %d\n" - "# of events: %d\n", - g_viewerSettings.sequence, - pseqdesc->numframes, - (int)pseqdesc->fps, - pseqdesc->numblends, - pseqdesc->numevents - ); - - ui.lSequenceInfo1->setText (str); - ui.lSequenceInfo2->setText (str); - - ui.slFrame->setRange(0, pseqdesc->numframes); - ui.leFrame->setRange(0, pseqdesc->numframes); - ui.slWeaponFrame->setRange(0, pseqdesc->numframes); - ui.leWeaponFrame->setRange(0, pseqdesc->numframes); + auto str = QString( + "Sequence: %1\n" + "Flags: %2\n" + "FPS: %3\n" + "NumofFrames: %4\n" + "NumofBlends: %5\n" + "NumofEvents: %6\n") + .arg(g_viewerSettings.sequence) + .arg(pseqdesc->flags) + .arg(pseqdesc->fps) + .arg(pseqdesc->numframes) + .arg(pseqdesc->numblends) + .arg(pseqdesc->numevents); + + ui.lSequenceInfo1->setText(str); + ui.lSequenceInfo2->setText(str); + + ui.slFrame->setRange(0, pseqdesc->numframes - 1); + ui.leFrame->setRange(0, pseqdesc->numframes - 1); + ui.slWeaponFrame->setRange(0, pseqdesc->numframes - 1); + ui.leWeaponFrame->setRange(0, pseqdesc->numframes - 1); ui.slWpSpeedFPS->setValue(pseqdesc->fps); ui.slWpSpeedFPS->setRange(0, pseqdesc->fps * 10); diff --git a/src/m/studio_utils.cpp b/src/m/studio_utils.cpp index 03370de..a7e885a 100644 --- a/src/m/studio_utils.cpp +++ b/src/m/studio_utils.cpp @@ -181,7 +181,7 @@ studiohdr_t *StudioModel::LoadModel( const char *modelname ) size = ftell( fp ); fseek( fp, 0, SEEK_SET ); - buffer = malloc( size ); + buffer = malloc( size + 0x1000 );//Pre-allocate 0x1000 more free space for new event usage if (!buffer) { fclose (fp); @@ -357,7 +357,7 @@ bool StudioModel::SaveModel ( const char *modelname ) return false; std::vector data_to_save(reinterpret_cast(m_pstudiohdr), reinterpret_cast(m_pstudiohdr) + m_pstudiohdr->length); - +#if 0 { studiohdr_t *phdr = reinterpret_cast(data_to_save.data()); mstudiotexture_t *ptexture = reinterpret_cast(data_to_save.data() + phdr->textureindex); @@ -368,7 +368,7 @@ bool StudioModel::SaveModel ( const char *modelname ) if(strncmp(ptexture[i].name, "*CSO* ", 5) != 0) continue; // TODO : convert and save external texture -#if 0 + auto old_size = data_to_save.size(); { data_to_save.resize(old_size + ptexture[i].width * ptexture[i].height * 3 + 256); @@ -379,7 +379,7 @@ bool StudioModel::SaveModel ( const char *modelname ) //glGetTexImage(GL_TEXTURE_2D, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data_to_save.data() + old_size); ptexture[i].index = old_size; -#endif + { char szName[64]; @@ -391,7 +391,7 @@ bool StudioModel::SaveModel ( const char *modelname ) } } } - +#endif fwrite (data_to_save.data(), sizeof (byte), data_to_save.size(), file); fclose (file); diff --git a/src/v/hlmv.h b/src/v/hlmv.h index dafd9f2..01833e7 100644 --- a/src/v/hlmv.h +++ b/src/v/hlmv.h @@ -18,6 +18,8 @@ public slots: void OnActionClear(); void OnActionAbout(); void OnTabChanged(int); + void editEvents(); + void editSequence(); void setSequence(int); void OnSetAnimationPlaying(bool); diff --git a/src/v/hlmv.ui b/src/v/hlmv.ui index ddecdee..0062e49 100644 --- a/src/v/hlmv.ui +++ b/src/v/hlmv.ui @@ -847,33 +847,40 @@ - - - - 0 - 0 - - - - - 100 - 0 - - - - Sequence: #0 -Frames: 0 -FPS: 0 -Blends: 0 -# of events: 0 - - - Qt::AutoText - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - + + + + + + 0 + 0 + + + + + 100 + 0 + + + + + + + Qt::AutoText + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + Edit Sequence + + + + @@ -895,6 +902,19 @@ Blends: 0 + + + + + 0 + 0 + + + + + + + @@ -905,16 +925,10 @@ Blends: 0 - - - - - 0 - 0 - - + + - TextLabel + Edit Events @@ -1352,7 +1366,7 @@ in your model's QC file. 0 0 600 - 22 + 23 @@ -1687,6 +1701,38 @@ in your model's QC file. + + pushButton_editEvent + clicked() + QtGuiApplication1Class + editEvents() + + + 294 + 238 + + + 299 + 199 + + + + + pushButton_editSeq + clicked() + QtGuiApplication1Class + editSequence() + + + 294 + 238 + + + 299 + 199 + + + cTextures currentIndexChanged(int) @@ -2272,6 +2318,8 @@ in your model's QC file. OnSetAnimationCurrentFrame(int) OnSetAnimationFPS(double) setEventInfo(int) + editEvents() + editSequence() setMesh(int) setTextureCurrent(int) updateTextureFlags()