mirror of
https://github.com/microsoft/Microsoft-3D-Movie-Maker.git
synced 2024-12-02 16:07:28 +00:00
461 lines
11 KiB
C++
461 lines
11 KiB
C++
/* Copyright (c) Microsoft Corporation.
|
|
Licensed under the MIT License. */
|
|
|
|
/***************************************************************************
|
|
|
|
splot.cpp: Splot machine class
|
|
|
|
Primary Author: ******
|
|
Review Status: Reviewed
|
|
|
|
***************************************************************************/
|
|
#include "studio.h"
|
|
ASSERTNAME
|
|
|
|
RTCLASS(SPLOT)
|
|
|
|
BEGIN_CMD_MAP(SPLOT, GOK)
|
|
ON_CID_GEN(cidSplotInit, FCmdInit, pvNil)
|
|
ON_CID_GEN(cidSplotDo, FCmdSplot, pvNil)
|
|
ON_CID_GEN(cidSplotUpdate, FCmdUpdate, pvNil)
|
|
ON_CID_GEN(cidSplotOk, FCmdDismiss, pvNil)
|
|
ON_CID_GEN(cidSplotCancel, FCmdDismiss, pvNil)
|
|
END_CMD_MAP_NIL()
|
|
|
|
|
|
/******************************************************************************
|
|
PsplotNew
|
|
Creates a new SPLOT instance.
|
|
|
|
Returns: pvNil on failure, pointer to SPLOT on success
|
|
|
|
************************************************************ PETED ***********/
|
|
PSPLOT SPLOT::PsplotNew(long hidPar, long hid, PRCA prca)
|
|
{
|
|
PSPLOT psplot = pvNil;
|
|
PGL pglclr = pvNil;
|
|
PGOB pgobPar;
|
|
RC rcRel;
|
|
GCB gcb;
|
|
CLOK clok(CMH::HidUnique());
|
|
|
|
if ((pgobPar = vapp.Pkwa()->PgobFromHid(hidPar)) == pvNil)
|
|
{
|
|
Bug("Couldn't find background GOB");
|
|
goto LFail;
|
|
}
|
|
|
|
pglclr = GPT::PglclrGetPalette();
|
|
if (pglclr == pvNil)
|
|
goto LFail;
|
|
|
|
rcRel.Set(krelZero, krelZero, krelOne, krelOne);
|
|
gcb.Set(hid, pgobPar, fgobNil, kginDefault, pvNil, &rcRel);
|
|
|
|
if ((psplot = NewObj SPLOT(&gcb)) == pvNil)
|
|
goto LFail;
|
|
|
|
if (!psplot->_FInit(vpapp->Pkwa(), hid, prca))
|
|
{
|
|
ReleasePpo(&psplot);
|
|
goto LFail;
|
|
}
|
|
if (!psplot->_FEnterState(ksnoInit))
|
|
{
|
|
Warn("GOK immediately destroyed!");
|
|
goto LFail;
|
|
}
|
|
|
|
/* Copy random number generator and palette */
|
|
psplot->_pglclrSav = pglclr;
|
|
psplot->_pglclrSav->AddRef();
|
|
|
|
LFail:
|
|
ReleasePpo(&pglclr);
|
|
return psplot;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
FCmdInit
|
|
Initializes the splot machine; right now, just sets up the movie
|
|
and MVU for the splot machine, inside the given GOK parent. In the
|
|
future, perhaps the content data structures can be inited here, and
|
|
only updated if we fail loading something (which would indicate that
|
|
the user removed a CD or something during the splot machine).
|
|
|
|
Arguments:
|
|
PCMD pcmd
|
|
rglw[0] -- the kid of the parent frame to show the movie in
|
|
|
|
Returns: fTrue, always handles the cid
|
|
|
|
************************************************************ PETED ***********/
|
|
bool SPLOT::FCmdInit(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
Assert(_pmvie == pvNil, "Already Inited the Splot Machine");
|
|
|
|
PMCC pmcc = pvNil;
|
|
PGOB pgobParent;
|
|
RC rcRel;
|
|
GCB gcb;
|
|
|
|
if ((pgobParent = vpapp->Pkwa()->PgobFromHid(pcmd->rglw[0])) == pvNil)
|
|
{
|
|
Bug("Parent GOB for view doesn't exist");
|
|
goto LFail;
|
|
}
|
|
|
|
pmcc = NewObj MCC(kdxpWorkspace, kdypWorkspace, kcbStudioCache);
|
|
if (pmcc == pvNil)
|
|
goto LFail;
|
|
|
|
if ((_pmvie = MVIE::PmvieNew(vpapp->FSlowCPU(), pmcc)) == pvNil)
|
|
goto LFail;
|
|
|
|
_pmvie->SetFSoundsEnabled(fTrue);
|
|
rcRel.Set(krelZero, krelZero, krelOne, krelOne);
|
|
gcb.Set(khidDdg, pgobParent, fgobNil, kginDefault, pvNil, &rcRel);
|
|
if (_pmvie->PddgNew(&gcb) == pvNil)
|
|
{
|
|
ReleasePpo(&_pmvie);
|
|
goto LFail;
|
|
}
|
|
_pmvie->InvalViews();
|
|
|
|
LFail:
|
|
ReleasePpo(&pmcc);
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
FCmdSplot
|
|
Actually generates some random content for the splot machine. Grab
|
|
content here, since sometimes we'll have to retrieve content here
|
|
anyway, so it's cleaner to just always do it here.
|
|
|
|
Arguments:
|
|
PCMD pcmd
|
|
rglw[0] -- 1 if the background should be randomized
|
|
rglw[1] -- 1 if the camera should be
|
|
rglw[2] -- 1 if the actors/props should be
|
|
rglw[3] -- 1 if the music should be
|
|
|
|
Returns: fTrue, always handles the cid
|
|
|
|
************************************************************ PETED ***********/
|
|
bool SPLOT::FCmdSplot(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
|
|
bool fDirty = fFalse;
|
|
CKI cki;
|
|
THD thd;
|
|
|
|
vapp.BeginLongOp();
|
|
|
|
/* On failure, pretend that we didn't change anything */
|
|
_fDirty = fFalse;
|
|
|
|
/* Background. New background implies new camera view */
|
|
if (_pbclBkgd == pvNil)
|
|
{
|
|
cki.ctg = kctgBkth;
|
|
cki.cno = cnoNil;
|
|
_pbclBkgd = BCL::PbclNew(pvNil, &cki, ctgNil, pvNil, fTrue);
|
|
if (_pbclBkgd == pvNil || _pbclBkgd->IthdMac() == 0)
|
|
{
|
|
ReleasePpo(&_pbclBkgd);
|
|
goto LFail;
|
|
}
|
|
pcmd->rglw[0] = 1;
|
|
}
|
|
if (pcmd->rglw[0] != 0)
|
|
{
|
|
long ithdBkgd;
|
|
|
|
ithdBkgd = _sflBkgd.LwNext(_pbclBkgd->IthdMac());
|
|
if (ithdBkgd != _ithdBkgd)
|
|
ReleasePpo(&_pbclCam);
|
|
_ithdBkgd = ithdBkgd;
|
|
pcmd->rglw[1] = 1;
|
|
fDirty = fTrue;
|
|
}
|
|
|
|
/* Camera */
|
|
if (_pbclCam == pvNil)
|
|
{
|
|
_pbclBkgd->GetThd(_ithdBkgd, &thd);
|
|
cki.ctg = kctgBkth;
|
|
cki.cno = thd.tag.cno;
|
|
_pbclCam = BCL::PbclNew(pvNil, &cki, kctgCath, pvNil, fTrue);
|
|
if (_pbclCam == pvNil || _pbclCam->IthdMac() == 0)
|
|
{
|
|
ReleasePpo(&_pbclCam);
|
|
goto LFail;
|
|
}
|
|
|
|
pcmd->rglw[1] = 1;
|
|
}
|
|
if (pcmd->rglw[1] != 0)
|
|
{
|
|
_ithdCam = _sflCam.LwNext(_pbclCam->IthdMac());
|
|
fDirty = fTrue;
|
|
}
|
|
|
|
/* Actor & Props */
|
|
if (_pbclActr == pvNil)
|
|
{
|
|
cki.ctg = kctgTmth;
|
|
cki.cno = cnoNil;
|
|
_pbclActr = BCL::PbclNew(pvNil, &cki, ctgNil, pvNil, fTrue);
|
|
if (_pbclActr == pvNil || _pbclActr->IthdMac() == 0)
|
|
{
|
|
ReleasePpo(&_pbclActr);
|
|
goto LFail;
|
|
}
|
|
pcmd->rglw[2] = 1;
|
|
}
|
|
if (_pbclProp == pvNil)
|
|
{
|
|
cki.ctg = kctgPrth;
|
|
cki.cno = cnoNil;
|
|
_pbclProp = BCL::PbclNew(pvNil, &cki, ctgNil, pvNil, fTrue);
|
|
if (_pbclProp == pvNil || _pbclProp->IthdMac() == 0)
|
|
{
|
|
ReleasePpo(&_pbclProp);
|
|
goto LFail;
|
|
}
|
|
pcmd->rglw[2] = 1;
|
|
}
|
|
if (pcmd->rglw[2] != 0)
|
|
{
|
|
_ithdActr = _sflActr.LwNext(_pbclActr->IthdMac());
|
|
_ithdProp = _sflProp.LwNext(_pbclProp->IthdMac());
|
|
fDirty = fTrue;
|
|
}
|
|
|
|
/* Background music */
|
|
if (_pbclSound == pvNil)
|
|
{
|
|
cki.ctg = kctgSmth;
|
|
cki.cno = cnoNil;
|
|
_pbclSound = BCL::PbclNew(pvNil, &cki, ctgNil, pvNil, fTrue);
|
|
if (_pbclSound == pvNil || _pbclSound->IthdMac() == 0)
|
|
{
|
|
ReleasePpo(&_pbclSound);
|
|
goto LFail;
|
|
}
|
|
pcmd->rglw[3] = 1;
|
|
}
|
|
if (pcmd->rglw[3] != 0)
|
|
{
|
|
_ithdSound = _sflSound.LwNext(_pbclSound->IthdMac());
|
|
fDirty = fTrue;
|
|
}
|
|
|
|
Assert(fDirty, "Why bother calling this with no random elements?");
|
|
_fDirty = fDirty;
|
|
LFail:
|
|
vapp.EndLongOp();
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
FCmdUpdate
|
|
Show the new movie on the screen.
|
|
|
|
Arguments:
|
|
PCMD pcmd -- no additional parameters
|
|
|
|
Returns: fTrue, always handles the cid
|
|
|
|
************************************************************ PETED ***********/
|
|
bool SPLOT::FCmdUpdate(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
|
|
if (_fDirty)
|
|
{
|
|
THD thd;
|
|
TAG tagCam, tagBkgd;
|
|
|
|
vapp.BeginLongOp();
|
|
|
|
if (_pmvie->Cscen() > 0 && !_pmvie->FRemScen(0))
|
|
goto LFail;
|
|
|
|
_pmvie->Pmsq()->SndOff();
|
|
|
|
#ifdef BUG1907
|
|
// We will run out of disk space eventually if the HD cache is not
|
|
// periodically cleared. We don't want to do it on every pull of the
|
|
// lever, because there's a significant time hit (especially if you're
|
|
// only pulling a "small lever", which only has to cache one new thing
|
|
// unless you clear the cache). Ideally, this algorithm would only
|
|
// purge the cache if disk space is getting low on the volume that
|
|
// tagman is caching to, but there's currently no way to do that, so
|
|
// just purge every five pulls.
|
|
static long _cactPullTilClearCache = 5;
|
|
|
|
_pmvie->Pmsq()->StopAll(); // Make sure no sounds are streaming from HD cache
|
|
if (--_cactPullTilClearCache == 0)
|
|
{
|
|
vptagm->ClearCache(sidNil, ftagmFile); // Clear content out of HD cache
|
|
_cactPullTilClearCache = 5;
|
|
}
|
|
#endif //BUG1907
|
|
|
|
/* No tags need to be opened, because all are from installed content */
|
|
/* Still need to ensure on HD though */
|
|
_pbclBkgd->GetThd(_ithdBkgd, &thd);
|
|
Assert(thd.tag.sid != ksidUseCrf, "Need to open tag before using it");
|
|
if (!BKGD::FCacheToHD(&thd.tag))
|
|
goto LFail;
|
|
if (!_pmvie->FAddScen(&thd.tag))
|
|
goto LFail;
|
|
tagBkgd = thd.tag;
|
|
AssertPo(_pmvie->Pscen(), 0);
|
|
|
|
_pmvie->Pmsq()->SndOnLong();
|
|
|
|
_pbclCam->GetThd(_ithdCam, &thd);
|
|
if (!vptagm->FBuildChildTag(&tagBkgd, thd.chid, kctgCam, &tagCam))
|
|
goto LFail;
|
|
if (!vptagm->FCacheTagToHD(&tagCam))
|
|
goto LFail;
|
|
if (!_pmvie->Pscen()->FChangeCam(thd.chid))
|
|
goto LFail;
|
|
|
|
_pbclActr->GetThd(_ithdActr, &thd);
|
|
Assert(thd.tag.sid != ksidUseCrf, "Need to open tag before using it");
|
|
if (!vptagm->FCacheTagToHD(&thd.tag))
|
|
goto LFail;
|
|
if (!_pmvie->FInsActr(&thd.tag))
|
|
goto LFail;
|
|
|
|
_pbclProp->GetThd(_ithdProp, &thd);
|
|
Assert(thd.tag.sid != ksidUseCrf, "Need to open tag before using it");
|
|
if (!vptagm->FCacheTagToHD(&thd.tag))
|
|
goto LFail;
|
|
if (!_pmvie->FInsActr(&thd.tag))
|
|
goto LFail;
|
|
|
|
_pmvie->Pscen()->SelectActr(pvNil);
|
|
_pmvie->PmvuCur()->SetTool(toolDefault);
|
|
|
|
_pbclSound->GetThd(_ithdSound, &thd);
|
|
Assert(thd.tag.sid != ksidUseCrf, "Need to open tag before using it");
|
|
if (!vptagm->FCacheTagToHD(&thd.tag))
|
|
goto LFail;
|
|
if (!_pmvie->FAddBkgdSnd(&thd.tag, fTrue, fFalse))
|
|
goto LFail;
|
|
|
|
_pmvie->Pmsq()->PlayMsq();
|
|
|
|
vapp.EndLongOp();
|
|
}
|
|
|
|
LFail:
|
|
return fTrue;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
FCmdDismiss
|
|
Okays or Cancels the Splot Machine.
|
|
|
|
Arguments:
|
|
PCMD pcmd -- no additional parameters
|
|
|
|
Returns: fTrue, always handles the cid
|
|
|
|
************************************************************ PETED ***********/
|
|
bool SPLOT::FCmdDismiss(PCMD pcmd)
|
|
{
|
|
AssertThis(0);
|
|
|
|
if (pcmd->cid == cidSplotOk)
|
|
{
|
|
/* Attempt to release the current scene so that we'll force a palette
|
|
update when we come back into the studio. Don't sweat a failure */
|
|
_pmvie->FSwitchScen(ivNil);
|
|
_pmvie->ClearUndo();
|
|
vapp.HandoffMovie(_pmvie);
|
|
}
|
|
#ifdef BUG1907
|
|
else
|
|
{
|
|
_pmvie->Pmsq()->StopAll(); // Make sure no sounds are streaming from HD cache
|
|
vptagm->ClearCache(sidNil, ftagmFile); // Clear content out of HD cache
|
|
// Note: could clear out the RAM cache too, but I'm keeping this change
|
|
// as small as possible.
|
|
}
|
|
#endif //BUG1907
|
|
|
|
Release();
|
|
|
|
return fTrue;
|
|
}
|
|
|
|
SPLOT::~SPLOT(void)
|
|
{
|
|
if (_pmvie != pvNil)
|
|
{
|
|
/* This should be freed when its parent, the Splot Machine View gob, is
|
|
freed */
|
|
Assert(_pmvie->PddgGet(0) == pvNil, "MVU wasn't freed");
|
|
|
|
_pmvie->Pmsq()->StopAll();
|
|
_pmvie->Pmsq()->SndOnShort();
|
|
}
|
|
|
|
if (_pglclrSav != pvNil)
|
|
{
|
|
vapp.UpdateMarked();
|
|
GPT::SetActiveColors(_pglclrSav, fpalIdentity);
|
|
ReleasePpo(&_pglclrSav);
|
|
}
|
|
|
|
ReleasePpo(&_pmvie);
|
|
ReleasePpo(&_pbclBkgd);
|
|
ReleasePpo(&_pbclCam);
|
|
ReleasePpo(&_pbclActr);
|
|
ReleasePpo(&_pbclProp);
|
|
ReleasePpo(&_pbclSound);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
void SPLOT::AssertValid(ulong grf)
|
|
{
|
|
SPLOT_PAR::AssertValid(grf);
|
|
AssertPo(_pglclrSav, 0);
|
|
|
|
AssertNilOrPo(_pmvie, 0);
|
|
AssertNilOrPo(_pbclBkgd, 0);
|
|
AssertNilOrPo(_pbclCam, 0);
|
|
AssertNilOrPo(_pbclActr, 0);
|
|
AssertNilOrPo(_pbclProp, 0);
|
|
AssertNilOrPo(_pbclSound, 0);
|
|
}
|
|
|
|
void SPLOT::MarkMem(void)
|
|
{
|
|
SPLOT_PAR::MarkMem();
|
|
MarkMemObj(_pglclrSav);
|
|
MarkMemObj(_pmvie);
|
|
MarkMemObj(_pbclBkgd);
|
|
MarkMemObj(_pbclCam);
|
|
MarkMemObj(_pbclActr);
|
|
MarkMemObj(_pbclProp);
|
|
MarkMemObj(_pbclSound);
|
|
_sflBkgd.MarkMem();
|
|
_sflCam.MarkMem();
|
|
_sflActr.MarkMem();
|
|
_sflProp.MarkMem();
|
|
_sflSound.MarkMem();
|
|
}
|
|
#endif // DEBUG
|