123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658 |
- #include "pch.h"
- //////////////////////////////////////////////////////////////////////////////
- //
- // FrameImage
- //
- //////////////////////////////////////////////////////////////////////////////
- class FrameImage : public Image {
- private:
- TRef<Image> m_pimageBackground;
- TRef<Surface> m_psurface;
- TRef<IObject> m_pobjectMemory;
- int m_nFrame;
- int m_frameCurrent;
- DWORD* m_pdwOffsets;
- BYTE* m_prle;
- public:
- FrameImage(
- Image* pimageBackground,
- Number* pframe,
- int nFrames,
- DWORD* pdwOffsets,
- BYTE* prle,
- IObject* pobjectMemory
- ) :
- Image(pframe, pimageBackground),
- m_pimageBackground(pimageBackground),
- m_nFrame(nFrames),
- m_pdwOffsets(pdwOffsets),
- m_prle(prle),
- m_pobjectMemory(pobjectMemory)
- {
- TRef<Surface> psurfaceBackground = m_pimageBackground->GetSurface();
- m_psurface =
- psurfaceBackground->CreateCompatibleSurface(
- psurfaceBackground->GetSize(),
- SurfaceType2D()
- );
- m_psurface->BitBlt(WinPoint(0, 0), psurfaceBackground);
- m_frameCurrent = 0;
- m_bounds.SetRect(
- Rect(
- Point(0, 0),
- Point::Cast(m_psurface->GetSize())
- )
- );
- }
- ~FrameImage()
- {
- if (m_pobjectMemory == NULL) {
- delete[] m_pdwOffsets;
- delete[] m_prle;
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // FrameImage methods
- //
- //////////////////////////////////////////////////////////////////////////////
- Number* GetFrameNumber() { return Number::Cast(GetChild(0)); }
- int GetFrame()
- {
- return
- bound(
- (int)(GetFrameNumber()->GetValue() * m_nFrame),
- 0,
- m_nFrame - 1
- );
- }
- void PlayRLE(BYTE* pd, BYTE* prle, BYTE* pend)
- {
- while (prle < pend) {
- WORD word = *(WORD*)prle;
- int length = word & RLELengthMask;
- prle += 2;
- switch (word & RLEMask) {
- case RLEMaskFill:
- {
- for (int index = length; index > 0; index --) {
- (*(BYTE*)pd) = (*(BYTE*)pd) ^ (*(BYTE*)prle);
- pd += 1;
- prle += 1;
- }
- }
- break;
- case RLEMaskBYTE:
- {
- BYTE byte = *(BYTE*)prle;
- prle += 1;
- for (int index = length; index > 0; index --) {
- (*(BYTE*)pd) = (*(BYTE*)pd) ^ byte;
- pd += 1;
- }
- }
- break;
- case RLEMaskWORD:
- {
- WORD word = *(WORD*)prle;
- prle += 2;
- for (int index = length; index > 0; index --) {
- (*(WORD*)pd) = (*(WORD*)pd) ^ word;
- pd += 2;
- }
- }
- break;
- case RLEMaskDWORD:
- {
- DWORD dword = *(DWORD*)prle;
- prle += 4;
- for (int index = length; index > 0; index --) {
- (*(DWORD*)pd) = (*(DWORD*)pd) ^ dword;
- pd += 4;
- }
- }
- break;
- }
- }
- }
- void UpdateFrame()
- {
- int newFrame = GetFrame();
- if (m_frameCurrent != newFrame) {
- BYTE* pd = m_psurface->GetWritablePointer();
- //
- // go forward
- //
- while (m_frameCurrent < newFrame) {
- PlayRLE(
- pd,
- m_prle + m_pdwOffsets[m_frameCurrent],
- m_prle + m_pdwOffsets[m_frameCurrent + 1]
- );
- m_frameCurrent++;
- }
- //
- // go backward
- //
- while (m_frameCurrent > newFrame) {
- m_frameCurrent--;
- PlayRLE(
- pd,
- m_prle + m_pdwOffsets[m_frameCurrent],
- m_prle + m_pdwOffsets[m_frameCurrent + 1]
- );
- }
- m_psurface->ReleasePointer();
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Image Methods
- //
- //////////////////////////////////////////////////////////////////////////////
- TRef<Surface> GetSurface()
- {
- UpdateFrame();
- return m_psurface;
- }
- void Render(Context* pcontext)
- {
- UpdateFrame();
- pcontext->DrawImage(m_psurface);
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Value Methods
- //
- //////////////////////////////////////////////////////////////////////////////
- ZString GetFunctionName()
- {
- return "FrameImage";
- }
- void Write(IMDLBinaryFile* pmdlFile)
- {
- WriteChildren(pmdlFile);
- pmdlFile->WriteReference("FrameImage");
- TRef<ZFile> pfile = pmdlFile->WriteBinary();
- pfile->Write((void*)&m_nFrame, sizeof(m_nFrame) );
- pfile->Write((void*)m_pdwOffsets, sizeof(DWORD) * (m_nFrame));
- pfile->Write((void*)m_prle, m_pdwOffsets[m_nFrame - 1]);
- pfile->WritePad(m_pdwOffsets[m_nFrame - 1]);
- }
- };
- //////////////////////////////////////////////////////////////////////////////
- //
- // Factory
- //
- //////////////////////////////////////////////////////////////////////////////
- class FrameImageFactory : public IFunction {
- public:
- FrameImageFactory()
- {
- }
- TRef<IObject> Apply(ObjectStack& stack)
- {
- ZUnimplemented();
- return NULL;
- }
- TRef<IObject> Read(IBinaryReaderSite* psite, ObjectStack& stack)
- {
- Number* pframe = Number::Cast((IObject*)stack.Pop());
- Image* pimage = Image::Cast((Value*)(IObject*)stack.Pop());
- DWORD nFrame = psite->GetDWORD();
- DWORD* pdwOffsets = (DWORD*)psite->GetPointer();
- BYTE* prle = (BYTE*)(pdwOffsets + nFrame);
- psite->MovePointer(
- sizeof(DWORD) * nFrame
- + pdwOffsets[nFrame - 1]
- );
- return
- (Value*)new FrameImage(
- pimage,
- pframe,
- nFrame,
- pdwOffsets,
- prle,
- psite->GetMemoryObject()
- );
- }
- };
- TRef<IFunction> CreateFrameImageFactory()
- {
- return new FrameImageFactory();
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Animation Compressor
- //
- //////////////////////////////////////////////////////////////////////////////
- class CompressAnimClass {
- private:
- BYTE* m_pdata;
- int m_sizeData;
- WinPoint m_sizeFrame;
- TRef<Surface> m_psurfaceFile;
- WinPoint m_sizeFile ;
- int m_xframes ;
- int m_yframes ;
- int m_nframes ;
- int m_xsize ;
- int m_ysize ;
- public:
- CompressAnimClass(
- Surface* psurfaceFile,
- int xframes,
- int yframes,
- TRef<Surface>& psurfaceBackground,
- DWORD*& pdwOffsets,
- BYTE*& prleStart
- ) {
- m_xframes = xframes;
- m_yframes = yframes;
- m_nframes = m_xframes * m_yframes;
- m_psurfaceFile = psurfaceFile;
- m_sizeFile = m_psurfaceFile->GetSize();
- m_xsize = m_sizeFile.X() / xframes;
- m_ysize = m_sizeFile.Y() / yframes;
- m_sizeFrame = WinPoint(m_xsize, m_ysize);
- psurfaceBackground = m_psurfaceFile->CreateCompatibleSurface(m_sizeFrame, SurfaceType2D());
- GetFrame(psurfaceBackground, 0);
- TRef<Surface> psurface0 = m_psurfaceFile->CreateCompatibleSurface(m_sizeFrame, SurfaceType2D());
- TRef<Surface> psurface1 = m_psurfaceFile->CreateCompatibleSurface(m_sizeFrame, SurfaceType2D());
- int length = psurface0->GetPitch() * m_ysize;
- int size = (length + 2) * m_nframes;
- prleStart = new BYTE[size];
- pdwOffsets = new DWORD[m_nframes];
- pdwOffsets[0] = 0;
- BYTE* pd = new BYTE[length];
- BYTE* prle = prleStart;
- for (int frame = 0; frame < m_nframes - 1; frame++) {
- GetFrame(psurface0, frame );
- GetFrame(psurface1, frame + 1);
- //
- // Xor the two frames
- //
- const BYTE* p0 = psurface0->GetPointer();
- const BYTE* p1 = psurface1->GetPointer();
- DoXOR(p0, p1, pd, length);
- //
- // Calculate the difference
- //
- DoRLE(pd, length, prle);
- pdwOffsets[frame + 1 ] = prle - prleStart;
- }
- ZAssert(prle - prleStart <= size);
- delete pd;
- }
- void GetFrame(Surface* psurface, int frame)
- {
- int x = (frame % m_xframes) * m_xsize;
- int y = (frame / m_xframes) * m_ysize;
- psurface->BitBlt(
- WinPoint(0, 0),
- m_psurfaceFile,
- WinRect(x, y, x + m_xsize, y + m_ysize)
- );
- }
- void DoXOR(const BYTE* p0, const BYTE* p1, BYTE* pd, int length)
- {
- for (int index = 0; index < length; index++) {
- pd[index] = p0[index] ^ p1[index];
- }
- }
- template<class Type>
- void DoStoreSpan(Type** ppd, BYTE*& prle, WORD code, WORD count)
- {
- *(WORD*)prle = code | count;
- *(Type*)(prle + 2) = (*ppd)[0];
- (*ppd) += count;
- prle += sizeof(Type) + 2;
- }
- template<class Type>
- WORD CouldStoreSpan(Type** ppd, Type* pend)
- {
- if ((*ppd) + 1 < pend) {
- Type value = (*ppd)[0];
- WORD count = 0;
-
- while (
- ((*ppd) + count + 1 < pend)
- && (*ppd)[count] == value
- ) {
- count++;
- }
- if (count * sizeof(Type) > 2 + sizeof(Type)) {
- return min(count, RLELengthMask);
- }
- }
- return 0;
- }
- void DoRawStoreSpan(BYTE* pstart, BYTE*& pd, BYTE*&prle)
- {
- WORD length = pd - pstart;
- if (length > 0) {
- *(WORD*)prle = RLEMaskFill | length;
- memcpy(prle + 2, pstart, length);
- prle += 2 + length;
- }
- }
- void DoRLE(BYTE* pd, int length, BYTE*& prle)
- {
- BYTE* pend = pd + length;
- BYTE* pstart = pd;
- while (pd < pend) {
- WORD count;
- if (count = CouldStoreSpan((DWORD**)&pd, (DWORD*)pend)) {
- DoRawStoreSpan(pstart, pd, prle);
- DoStoreSpan((DWORD**)&pd, prle, RLEMaskDWORD, count);
- pstart = pd;
- } else if (count = CouldStoreSpan((WORD**)&pd, (WORD*)pend)) {
- DoRawStoreSpan(pstart, pd, prle);
- DoStoreSpan((WORD**)&pd, prle, RLEMaskWORD, count);
- pstart = pd;
- } else if (count = CouldStoreSpan((BYTE**)&pd, (BYTE*)pend)) {
- DoRawStoreSpan(pstart, pd, prle);
- DoStoreSpan((BYTE**)&pd, prle, RLEMaskBYTE, count);
- pstart = pd;
- }
- pd++;
- }
- DoRawStoreSpan(pstart, pd, prle);
- }
- };
- //////////////////////////////////////////////////////////////////////////////
- //
- // Constructor
- //
- //////////////////////////////////////////////////////////////////////////////
- TRef<Image> CreateFrameImage(
- Number* pframe,
- Surface* psurface,
- int xframes,
- int yframes
- ) {
- //
- // compress the animation
- //
- TRef<Surface> psurfaceBackground;
- DWORD* pdwOffsets;
- BYTE* prle;
- CompressAnimClass foo(
- psurface,
- xframes,
- yframes,
- psurfaceBackground,
- pdwOffsets,
- prle
- );
- //
- // Create a frame image
- //
- return
- new FrameImage(
- new ConstantImage(psurfaceBackground, ZString()),
- pframe,
- xframes * yframes,
- pdwOffsets,
- prle,
- NULL
- );
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // FrameImageButtonPane
- //
- //////////////////////////////////////////////////////////////////////////////
- class FrameImageButtonPaneImpl :
- public FrameImageButtonPane,
- public Value
- {
- TRef<ModifiableNumber> m_pframe;
- TRef<Image> m_pimage;
- TRef<EventSourceImpl> m_peventSource;
- TRef<EventSourceImpl> m_peventMouseEnterSource;
- TRef<EventSourceImpl> m_peventMouseLeaveSource;
- bool m_bInside;
- float m_duration;
- float m_valueStart;
- float m_timeStart;
- float m_loop;
- float m_finish;
- public:
- FrameImageButtonPaneImpl(
- Number* ptime,
- Image* pimage,
- ModifiableNumber* pframe,
- float duration,
- bool loop,
- bool finish
- ) :
- Value(ptime),
- m_peventSource(new EventSourceImpl()),
- m_peventMouseEnterSource(new EventSourceImpl()),
- m_peventMouseLeaveSource(new EventSourceImpl()),
- m_pimage(pimage),
- m_pframe(pframe),
- m_duration(duration),
- m_loop(loop),
- m_finish(finish),
- m_bInside(false),
- m_valueStart(0),
- m_timeStart(ptime->GetValue())
- {
- InternalSetSize(
- WinPoint::Cast(m_pimage->GetBounds().GetRect().Size())
- );
- }
- Number* GetTime() { return Number::Cast(GetChild(0)); }
- //////////////////////////////////////////////////////////////////////////////
- //
- // FrameImageButtonPane methods
- //
- //////////////////////////////////////////////////////////////////////////////
- IEventSource* GetEventSource()
- {
- return m_peventSource;
- }
- IEventSource* GetMouseEnterEventSource()
- {
- return m_peventMouseEnterSource;
- }
- IEventSource* GetMouseLeaveEventSource()
- {
- return m_peventMouseLeaveSource;
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Value Methods
- //
- //////////////////////////////////////////////////////////////////////////////
- void ChildChanged(Value* pvalue, Value* pvalueNew)
- {
- Value::ChildChanged(pvalue, pvalueNew);
- NeedPaint();
- }
- void Evaluate()
- {
- float time = GetTime()->GetValue();
- float value;
- float delta = (time - m_timeStart) / m_duration;
- if (m_bInside) {
- value = m_valueStart + delta;
- if (m_loop)
- {
- // wrap the value back around to the beginning
- value = float(value - (int)value);
- }
- } else {
- if (m_finish)
- {
- value = m_valueStart + delta;
- if (value > 1.0)
- value = 0.0;
- }
- else if (m_loop)
- {
- value = m_valueStart;
- }
- else
- {
- value = m_valueStart - delta;
- }
- }
- value = bound(value, 0.0f, 1.0f);
- if (value != m_pframe->GetValue()) {
- m_pframe->SetValue(value);
- NeedPaint();
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // Pane Methods
- //
- //////////////////////////////////////////////////////////////////////////////
- void Paint(Surface* psurface)
- {
- Update();
- psurface->BitBlt(WinPoint(0, 0), m_pimage->GetSurface());
- }
- //////////////////////////////////////////////////////////////////////////////
- //
- // IMouseInput Methods
- //
- //////////////////////////////////////////////////////////////////////////////
- void MouseEnter(IInputProvider* pprovider, const Point& point)
- {
- m_bInside = true;
- m_valueStart = m_pframe->GetValue();
- m_timeStart = GetTime()->GetValue();
- m_peventMouseEnterSource->Trigger();
- }
- void MouseLeave(IInputProvider* pprovider)
- {
- m_bInside = false;
- m_valueStart = m_pframe->GetValue();
- m_timeStart = GetTime()->GetValue();
- m_peventMouseLeaveSource->Trigger();
- }
- MouseResult Button(IInputProvider* pprovider, const Point& point, int button, bool bCaptured, bool bInside, bool bDown)
- {
- if (button == 0) {
- if (bDown) {
- m_peventSource->Trigger();
- }
- }
- return MouseResult();
- }
- };
- TRef<FrameImageButtonPane> CreateFrameImageButtonPane(
- Number* ptime,
- Image* pimage,
- ModifiableNumber* pframe,
- float duration,
- bool loop,
- bool finish
- ) {
- return new FrameImageButtonPaneImpl(ptime, pimage, pframe, duration, loop, finish);
- }
|