int CModel::AnimEnumInUse(LPCSTR psAnimEnum) { int iCount = 0; if (strlen(psAnimEnum)) // added for G2 models, which don't necessarily use enums yet { CSequence *curSequence = GetFirstSequence(); while (curSequence) { if (!strcmp(psAnimEnum,curSequence->GetEnum())) { iCount++;// return true; } // new bit, ask the additional sequences as well... // for (int i=0; i<MAX_ADDITIONAL_SEQUENCES; i++) { if (!strcmp(psAnimEnum,curSequence->AdditionalSeqs[i]->GetEnum())) { iCount++;// return true; } } curSequence = curSequence->GetNext(); } } return iCount;//false; }
void CSequence::Write(CTxtFile* file, bool bPreQuat) { CComment* curComment = m_comments; while(curComment != NULL) { curComment->Write(file); curComment = curComment->GetNext(); } file->Write("$", CAssimilateDoc::GetKeyword(IsGLA()?TK_AS_GRAB_GLA:TK_AS_GRAB, TABLE_QDT), " "); CString path = m_path; int loc = path.Find("/base"); if (loc > -1) { path = path.Right(path.GetLength() - loc - 5); loc = path.Find("/"); path = path.Right(path.GetLength() - loc - 1); } if (!path.GetLength()) // check that some dopey artist hasn't use the name "base" on the right hand side { path = m_path; } Filename_AccountForLOD(path, giLODLevelOverride); file->Write(path); /* if (m_frameCount > -1) { file->Space(); file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_FRAMES, TABLE_GRAB), " "); file->Write(m_startFrame); file->Space(); file->Write(m_targetFrame); file->Space(); file->Write(m_frameCount); } */ // if (strstr(path,"death16")) // { // int z=1; // } if (!IsGLA()) { if (m_fill > -1) { file->Space(); file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_FILL, TABLE_GRAB), " "); // file->Space(); file->Write(m_fill); } if (m_loopFrame != 0) { file->Space(); file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_LOOP, TABLE_GRAB), " "); // file->Space(); file->Write(m_loopFrame); } // if (m_enum && (strcmp(m_name, m_enum) != 0)) if (m_enum.GetLength() && (strcmp(m_name, m_enum) != 0)) { file->Space(); file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_ENUM, TABLE_GRAB), " "); // file->Space(); file->Write(m_enum); } if (m_sound != NULL) { file->Space(); file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_SOUND, TABLE_GRAB), " "); // file->Space(); file->Write(m_sound); } if (m_action != NULL) { file->Space(); file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_ACTION, TABLE_GRAB), " "); // file->Space(); file->Write(m_action); } if (m_bGenLoopFrame) { file->Space(); file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_GENLOOPFRAME, TABLE_GRAB), " "); } if (m_frameSpeed != m_iFrameSpeedFromHeader || GetValidAdditionalSequences() || bPreQuat ) { // write out start marker (and stop-marker at bottom) so qdata can skip this more easily... // file->Space(); file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_QDSKIPSTART, TABLE_GRAB)); if (m_frameSpeed != m_iFrameSpeedFromHeader) { file->Space(); file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_FRAMESPEED, TABLE_GRAB), " "); file->Write(m_frameSpeed); } for (int i=0; i<MAX_ADDITIONAL_SEQUENCES; i++) { CSequence* additionalSeq = AdditionalSeqs[i]; if (additionalSeq->AdditionalSequenceIsValid()) { file->Space(); file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_ADDITIONAL, TABLE_GRAB), " "); file->Write(additionalSeq->GetStartFrame()); file->Space(); file->Write(additionalSeq->GetFrameCount()); file->Space(); file->Write(additionalSeq->GetLoopFrame()); file->Space(); file->Write(additionalSeq->GetFrameSpeed()); file->Space(); file->Write(additionalSeq->GetEnum()); } } // this is an unpleasant abuse, but needed to retro-hack into old versions of carcass... // if (bPreQuat) { file->Space(); file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_PREQUAT, TABLE_GRAB)); } // any other stuff in future (sound events etc)... // // ... // write end marker (so QData knows to start reading again)... // file->Space(); file->Write("-", CAssimilateDoc::GetKeyword(TK_AS_QDSKIPSTOP, TABLE_GRAB)); } } file->Writeln(); }
void CModel::Resequence(bool bReScanASEFiles /* = false */) { CWaitCursor wait; CRect Rect; CProgressCtrl *pProgress = NULL; if (bReScanASEFiles && ((CAssimilateApp*)AfxGetApp())->m_pMainWnd) { pProgress = new CProgressCtrl; bool bOK = !!pProgress->Create( WS_CHILD|WS_VISIBLE|PBS_SMOOTH, // DWORD dwStyle, CRect(100,100,200,200), // const RECT& rect, ((CAssimilateApp*)AfxGetApp())->m_pMainWnd, // CWnd* pParentWnd, 1 // UINT nID ); if (!bOK) { delete pProgress; pProgress = NULL; } } int iTotMasterSequences = GetTotMasterSequences(); if (pProgress) { pProgress->SetRange(0,iTotMasterSequences); } int iSequenceNumber=0; int curFrame = 0; CSequence* curSequence = m_sequences; while(curSequence != NULL) { if (pProgress) { pProgress->SetPos(iSequenceNumber++); wait.Restore(); } // mark current enums as valid or not... curSequence->SetValidEnum(((CAssimilateApp*)AfxGetApp())->ValidEnum(curSequence->GetEnum())); for (int _i=0; _i<MAX_ADDITIONAL_SEQUENCES; _i++) { CSequence *additionalSeq = curSequence->AdditionalSeqs[_i]; additionalSeq->SetValidEnum(((CAssimilateApp*)AfxGetApp())->ValidEnum(additionalSeq->GetEnum())); } if ( bReScanASEFiles ) { // new code, first of all check for changed framecounts (ie updated ASE file), and update sequence if nec... CString nameASE = ((CAssimilateApp*)AfxGetApp())->GetQuakeDir(); nameASE+= curSequence->GetPath(); if (!FileExists(nameASE)) { if (gbCarWash_DoingScan) { strCarWashErrors += va("Model file missing: \"%s\"\n",nameASE); } else { if ( gbReportMissingASEs ) { gbReportMissingASEs = GetYesNo(va("Model file missing: \"%s\"\n\nContinue recieving this message?",nameASE)); } } } else { int iStartFrame, iFrameCount, iFrameSpeed; iFrameCount = curSequence->GetFrameCount(); // default it in case we skip an XSI read iFrameSpeed = curSequence->GetFrameSpeed(); // default it in case we cache this file curSequence->ReadASEHeader( nameASE, iStartFrame, iFrameCount, iFrameSpeed, true); // true = can skip XSI read if ( iFrameCount != curSequence->GetFrameCount() ) { if (gbCarWash_DoingScan) { strCarWashErrors += va("file: \"%s\" has a framecount of %d, but .CAR file says %d\n",nameASE,iFrameCount,curSequence->GetFrameCount()); } else { // don't mention it if the current count is zero, it's probably a new anim we've just added... if ( curSequence->GetFrameCount() ) { if (giFixUpdatedASEFrameCounts == YES || giFixUpdatedASEFrameCounts == NO) { CYesNoYesAllNoAll query( va("Model file: \"%s\"",nameASE), "", va("... has a framecount of %d instead of %d as the QDT/CAR file says",iFrameCount, curSequence->GetFrameCount()), "", "", "Do you want me to fix this?" ); giFixUpdatedASEFrameCounts = query.DoModal(); } } // update the sequence?... if (giFixUpdatedASEFrameCounts == YES || giFixUpdatedASEFrameCounts == YES_ALL || !curSequence->GetFrameCount() // update: I think this should be here? ) { curSequence->SetFrameCount( iFrameCount ); } } } } // findmeste: this no longer seems to do anything under JK2, presumablt EF1-only? #if 0 // now try to do any auto-associate between the ASE filename base and the existing enums, // so if we find (eg) /...../...../CROUCH.ASE and we have BOTH_CROUCH then auto-set the enum to BOTH_CROUCH CString stringASEName = nameASE; Filename_BaseOnly(stringASEName); // now = (eg) "falldeath" or "injured" etc for (int i=0; ; i++) { LPCSTR p = ((CAssimilateApp*)AfxGetApp())->GetEnumEntry(i); if (!p) // EOS? break; CString stringEnum = p; // note, I could check stuff like "IsEnumSeperator(LPCSTR lpString)" on <p>, but you'd never // have one of those enums assigned to a sequence anyway. char *psEnumPosAfterUnderScore = strchr(stringEnum,'_'); if (psEnumPosAfterUnderScore++) // check it, and skip to next char { // does this enum match the ASE name? if ( !stricmp( psEnumPosAfterUnderScore, stringASEName ) ) { // ok, we've found a good candidate, so set it... (no need for query-prev code, but I wanted to) if ( strcmp( curSequence->GetEnum(), stringEnum)) { curSequence->SetEnum(stringEnum); } } } else { // this should never happen... if (gbCarWash_DoingScan) { strCarWashErrors += va("found an anim enum with no underscore: \"%s\"\n",stringEnum); } else { ASSERT(0); ErrorBox(va("Error! Somehow I found an anim enum with no underscore: \"%s\"",stringEnum)); } } } #endif } // More bollox for Gummelt... :-) // now do the other freaky trick (you'd better be grateful for all this Mike!!! <g>), which is: // If you find the substring DEATH in this (master) sequence's enum, then ensure that the first *additional* // sequence of it is set to be the corresponding DEAD enum, but using the last frame only (and non-looping) // // (... or something...) { // keep scope local for neatness if ( strstr (curSequence->GetEnum(), "DEATH") ) { // scan this sequence's additional sequences for a DEAD of the same basic type... CString stringEnumDEAD = curSequence->GetEnum(); ASSERT(!IsEnumSeperator(stringEnumDEAD)); stringEnumDEAD.Replace("DEATH","DEAD"); // 1st, is there even a corresponding DEAD enum in the global enum table that we can look for... CString stringEnum; bool bEnumFound = false; for (int iEnumEntry=0; !bEnumFound; iEnumEntry++) { LPCSTR p = ((CAssimilateApp*)AfxGetApp())->GetEnumEntry(iEnumEntry); if (!p) // EOS? break; stringEnum = p; // note, I could check stuff like "IsEnumSeperator(LPCSTR lpString)" on <p>, but you'd never // have one of those enums assigned to a sequence anyway. // does this enum match the one we've built? if ( !_stricmp( stringEnum, stringEnumDEAD ) ) { bEnumFound = true; } } if ( bEnumFound ) { // ok, there *is* one of these, so let's scan this sequence's additional sequences to see if we've // got it... CSequence *additionalSeq; // outside FOR scope for (int i=0; i<MAX_ADDITIONAL_SEQUENCES; i++) { additionalSeq = curSequence->AdditionalSeqs[i]; if (additionalSeq->AdditionalSequenceIsValid()) { if (!strcmp(additionalSeq->GetEnum(),stringEnum)) { break; // we've found one! } } } // if we didn't find one, NULL the ptr if (int i=MAX_ADDITIONAL_SEQUENCES) { additionalSeq = NULL; } // did we find one? (or did it have the wrong info in?) if ( additionalSeq == NULL // didn't find one || additionalSeq->GetFrameCount()!=1 || additionalSeq->GetLoopFrame() !=-1 || additionalSeq->GetStartFrame()!= curSequence->GetFrameCount()-1 || additionalSeq->GetFrameSpeed()!= curSequence->GetFrameSpeed() ) { // find a slot to add this new sequence to, or use the faulty one... if (additionalSeq == NULL) { for (int i=0; i<MAX_ADDITIONAL_SEQUENCES; i++) { additionalSeq = curSequence->AdditionalSeqs[i]; if (!additionalSeq->AdditionalSequenceIsValid()) { break; // found an unused slot } } } // so have we got a slot to work with? if ( additionalSeq == NULL ) { if (gbCarWash_DoingScan) { strCarWashErrors += va( "F**k!!!: I need an 'additional sequence' slot free in the entry: \"%s\" to generate a DEAD seq, but there isn't one spare. Edit this yourself later.\n",curSequence->GetPath()); } else { ErrorBox( va( "F**k!!!\n\nI need an 'additional sequence' slot free in the ASE:\n\n\"%s\"\n\n... to generate a DEAD seq, but there isn't one spare. Edit this yourself later.",curSequence->GetPath())); } } else { additionalSeq->SetStartFrame( curSequence->GetFrameCount()-1 ); additionalSeq->SetFrameCount( 1 ); additionalSeq->SetLoopFrame (-1 ); additionalSeq->SetFrameSpeed( curSequence->GetFrameSpeed() ); additionalSeq->SetEnum ( stringEnumDEAD ); } } } } } curSequence->SetTargetFrame(curFrame + curSequence->GetStartFrame()); // slightly more legal than just (curFrame) // update: now set any additional sequences within it... for (int i=0; i<MAX_ADDITIONAL_SEQUENCES; i++) { curSequence->AdditionalSeqs[i]->SetTargetFrame(curFrame + curSequence->AdditionalSeqs[i]->GetStartFrame()); } curFrame += curSequence->GetFrameCount(); curFrame += curSequence->GetGenLoopFrame()?1:0; // findme: is this right? I hate this system curSequence = curSequence->GetNext(); } m_totFrames = curFrame; ghAssimilateView->GetDocument()->SetModifiedFlag(); if (pProgress) { delete pProgress; pProgress = 0; } }