frameimage.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. #include "pch.h"
  2. //////////////////////////////////////////////////////////////////////////////
  3. //
  4. // FrameImage
  5. //
  6. //////////////////////////////////////////////////////////////////////////////
  7. class FrameImage : public Image {
  8. private:
  9. TRef<Image> m_pimageBackground;
  10. TRef<Surface> m_psurface;
  11. TRef<IObject> m_pobjectMemory;
  12. int m_nFrame;
  13. int m_frameCurrent;
  14. DWORD* m_pdwOffsets;
  15. BYTE* m_prle;
  16. public:
  17. FrameImage(
  18. Image* pimageBackground,
  19. Number* pframe,
  20. int nFrames,
  21. DWORD* pdwOffsets,
  22. BYTE* prle,
  23. IObject* pobjectMemory
  24. ) :
  25. Image(pframe, pimageBackground),
  26. m_pimageBackground(pimageBackground),
  27. m_nFrame(nFrames),
  28. m_pdwOffsets(pdwOffsets),
  29. m_prle(prle),
  30. m_pobjectMemory(pobjectMemory)
  31. {
  32. TRef<Surface> psurfaceBackground = m_pimageBackground->GetSurface();
  33. m_psurface =
  34. psurfaceBackground->CreateCompatibleSurface(
  35. psurfaceBackground->GetSize(),
  36. SurfaceType2D()
  37. );
  38. m_psurface->BitBlt(WinPoint(0, 0), psurfaceBackground);
  39. m_frameCurrent = 0;
  40. m_bounds.SetRect(
  41. Rect(
  42. Point(0, 0),
  43. Point::Cast(m_psurface->GetSize())
  44. )
  45. );
  46. }
  47. ~FrameImage()
  48. {
  49. if (m_pobjectMemory == NULL) {
  50. delete[] m_pdwOffsets;
  51. delete[] m_prle;
  52. }
  53. }
  54. //////////////////////////////////////////////////////////////////////////////
  55. //
  56. // FrameImage methods
  57. //
  58. //////////////////////////////////////////////////////////////////////////////
  59. Number* GetFrameNumber() { return Number::Cast(GetChild(0)); }
  60. int GetFrame()
  61. {
  62. return
  63. bound(
  64. (int)(GetFrameNumber()->GetValue() * m_nFrame),
  65. 0,
  66. m_nFrame - 1
  67. );
  68. }
  69. void PlayRLE(BYTE* pd, BYTE* prle, BYTE* pend)
  70. {
  71. while (prle < pend) {
  72. WORD word = *(WORD*)prle;
  73. int length = word & RLELengthMask;
  74. prle += 2;
  75. switch (word & RLEMask) {
  76. case RLEMaskFill:
  77. {
  78. for (int index = length; index > 0; index --) {
  79. (*(BYTE*)pd) = (*(BYTE*)pd) ^ (*(BYTE*)prle);
  80. pd += 1;
  81. prle += 1;
  82. }
  83. }
  84. break;
  85. case RLEMaskBYTE:
  86. {
  87. BYTE byte = *(BYTE*)prle;
  88. prle += 1;
  89. for (int index = length; index > 0; index --) {
  90. (*(BYTE*)pd) = (*(BYTE*)pd) ^ byte;
  91. pd += 1;
  92. }
  93. }
  94. break;
  95. case RLEMaskWORD:
  96. {
  97. WORD word = *(WORD*)prle;
  98. prle += 2;
  99. for (int index = length; index > 0; index --) {
  100. (*(WORD*)pd) = (*(WORD*)pd) ^ word;
  101. pd += 2;
  102. }
  103. }
  104. break;
  105. case RLEMaskDWORD:
  106. {
  107. DWORD dword = *(DWORD*)prle;
  108. prle += 4;
  109. for (int index = length; index > 0; index --) {
  110. (*(DWORD*)pd) = (*(DWORD*)pd) ^ dword;
  111. pd += 4;
  112. }
  113. }
  114. break;
  115. }
  116. }
  117. }
  118. void UpdateFrame()
  119. {
  120. int newFrame = GetFrame();
  121. if (m_frameCurrent != newFrame) {
  122. BYTE* pd = m_psurface->GetWritablePointer();
  123. //
  124. // go forward
  125. //
  126. while (m_frameCurrent < newFrame) {
  127. PlayRLE(
  128. pd,
  129. m_prle + m_pdwOffsets[m_frameCurrent],
  130. m_prle + m_pdwOffsets[m_frameCurrent + 1]
  131. );
  132. m_frameCurrent++;
  133. }
  134. //
  135. // go backward
  136. //
  137. while (m_frameCurrent > newFrame) {
  138. m_frameCurrent--;
  139. PlayRLE(
  140. pd,
  141. m_prle + m_pdwOffsets[m_frameCurrent],
  142. m_prle + m_pdwOffsets[m_frameCurrent + 1]
  143. );
  144. }
  145. m_psurface->ReleasePointer();
  146. }
  147. }
  148. //////////////////////////////////////////////////////////////////////////////
  149. //
  150. // Image Methods
  151. //
  152. //////////////////////////////////////////////////////////////////////////////
  153. TRef<Surface> GetSurface()
  154. {
  155. UpdateFrame();
  156. return m_psurface;
  157. }
  158. void Render(Context* pcontext)
  159. {
  160. UpdateFrame();
  161. pcontext->DrawImage(m_psurface);
  162. }
  163. //////////////////////////////////////////////////////////////////////////////
  164. //
  165. // Value Methods
  166. //
  167. //////////////////////////////////////////////////////////////////////////////
  168. ZString GetFunctionName()
  169. {
  170. return "FrameImage";
  171. }
  172. void Write(IMDLBinaryFile* pmdlFile)
  173. {
  174. WriteChildren(pmdlFile);
  175. pmdlFile->WriteReference("FrameImage");
  176. TRef<ZFile> pfile = pmdlFile->WriteBinary();
  177. pfile->Write((void*)&m_nFrame, sizeof(m_nFrame) );
  178. pfile->Write((void*)m_pdwOffsets, sizeof(DWORD) * (m_nFrame));
  179. pfile->Write((void*)m_prle, m_pdwOffsets[m_nFrame - 1]);
  180. pfile->WritePad(m_pdwOffsets[m_nFrame - 1]);
  181. }
  182. };
  183. //////////////////////////////////////////////////////////////////////////////
  184. //
  185. // Factory
  186. //
  187. //////////////////////////////////////////////////////////////////////////////
  188. class FrameImageFactory : public IFunction {
  189. public:
  190. FrameImageFactory()
  191. {
  192. }
  193. TRef<IObject> Apply(ObjectStack& stack)
  194. {
  195. ZUnimplemented();
  196. return NULL;
  197. }
  198. TRef<IObject> Read(IBinaryReaderSite* psite, ObjectStack& stack)
  199. {
  200. Number* pframe = Number::Cast((IObject*)stack.Pop());
  201. Image* pimage = Image::Cast((Value*)(IObject*)stack.Pop());
  202. DWORD nFrame = psite->GetDWORD();
  203. DWORD* pdwOffsets = (DWORD*)psite->GetPointer();
  204. BYTE* prle = (BYTE*)(pdwOffsets + nFrame);
  205. psite->MovePointer(
  206. sizeof(DWORD) * nFrame
  207. + pdwOffsets[nFrame - 1]
  208. );
  209. return
  210. (Value*)new FrameImage(
  211. pimage,
  212. pframe,
  213. nFrame,
  214. pdwOffsets,
  215. prle,
  216. psite->GetMemoryObject()
  217. );
  218. }
  219. };
  220. TRef<IFunction> CreateFrameImageFactory()
  221. {
  222. return new FrameImageFactory();
  223. }
  224. //////////////////////////////////////////////////////////////////////////////
  225. //
  226. // Animation Compressor
  227. //
  228. //////////////////////////////////////////////////////////////////////////////
  229. class CompressAnimClass {
  230. private:
  231. BYTE* m_pdata;
  232. int m_sizeData;
  233. WinPoint m_sizeFrame;
  234. TRef<Surface> m_psurfaceFile;
  235. WinPoint m_sizeFile ;
  236. int m_xframes ;
  237. int m_yframes ;
  238. int m_nframes ;
  239. int m_xsize ;
  240. int m_ysize ;
  241. public:
  242. CompressAnimClass(
  243. Surface* psurfaceFile,
  244. int xframes,
  245. int yframes,
  246. TRef<Surface>& psurfaceBackground,
  247. DWORD*& pdwOffsets,
  248. BYTE*& prleStart
  249. ) {
  250. m_xframes = xframes;
  251. m_yframes = yframes;
  252. m_nframes = m_xframes * m_yframes;
  253. m_psurfaceFile = psurfaceFile;
  254. m_sizeFile = m_psurfaceFile->GetSize();
  255. m_xsize = m_sizeFile.X() / xframes;
  256. m_ysize = m_sizeFile.Y() / yframes;
  257. m_sizeFrame = WinPoint(m_xsize, m_ysize);
  258. psurfaceBackground = m_psurfaceFile->CreateCompatibleSurface(m_sizeFrame, SurfaceType2D());
  259. GetFrame(psurfaceBackground, 0);
  260. TRef<Surface> psurface0 = m_psurfaceFile->CreateCompatibleSurface(m_sizeFrame, SurfaceType2D());
  261. TRef<Surface> psurface1 = m_psurfaceFile->CreateCompatibleSurface(m_sizeFrame, SurfaceType2D());
  262. int length = psurface0->GetPitch() * m_ysize;
  263. int size = (length + 2) * m_nframes;
  264. prleStart = new BYTE[size];
  265. pdwOffsets = new DWORD[m_nframes];
  266. pdwOffsets[0] = 0;
  267. BYTE* pd = new BYTE[length];
  268. BYTE* prle = prleStart;
  269. for (int frame = 0; frame < m_nframes - 1; frame++) {
  270. GetFrame(psurface0, frame );
  271. GetFrame(psurface1, frame + 1);
  272. //
  273. // Xor the two frames
  274. //
  275. const BYTE* p0 = psurface0->GetPointer();
  276. const BYTE* p1 = psurface1->GetPointer();
  277. DoXOR(p0, p1, pd, length);
  278. //
  279. // Calculate the difference
  280. //
  281. DoRLE(pd, length, prle);
  282. pdwOffsets[frame + 1 ] = prle - prleStart;
  283. }
  284. ZAssert(prle - prleStart <= size);
  285. delete pd;
  286. }
  287. void GetFrame(Surface* psurface, int frame)
  288. {
  289. int x = (frame % m_xframes) * m_xsize;
  290. int y = (frame / m_xframes) * m_ysize;
  291. psurface->BitBlt(
  292. WinPoint(0, 0),
  293. m_psurfaceFile,
  294. WinRect(x, y, x + m_xsize, y + m_ysize)
  295. );
  296. }
  297. void DoXOR(const BYTE* p0, const BYTE* p1, BYTE* pd, int length)
  298. {
  299. for (int index = 0; index < length; index++) {
  300. pd[index] = p0[index] ^ p1[index];
  301. }
  302. }
  303. template<class Type>
  304. void DoStoreSpan(Type** ppd, BYTE*& prle, WORD code, WORD count)
  305. {
  306. *(WORD*)prle = code | count;
  307. *(Type*)(prle + 2) = (*ppd)[0];
  308. (*ppd) += count;
  309. prle += sizeof(Type) + 2;
  310. }
  311. template<class Type>
  312. WORD CouldStoreSpan(Type** ppd, Type* pend)
  313. {
  314. if ((*ppd) + 1 < pend) {
  315. Type value = (*ppd)[0];
  316. WORD count = 0;
  317. while (
  318. ((*ppd) + count + 1 < pend)
  319. && (*ppd)[count] == value
  320. ) {
  321. count++;
  322. }
  323. if (count * sizeof(Type) > 2 + sizeof(Type)) {
  324. return min(count, RLELengthMask);
  325. }
  326. }
  327. return 0;
  328. }
  329. void DoRawStoreSpan(BYTE* pstart, BYTE*& pd, BYTE*&prle)
  330. {
  331. WORD length = pd - pstart;
  332. if (length > 0) {
  333. *(WORD*)prle = RLEMaskFill | length;
  334. memcpy(prle + 2, pstart, length);
  335. prle += 2 + length;
  336. }
  337. }
  338. void DoRLE(BYTE* pd, int length, BYTE*& prle)
  339. {
  340. BYTE* pend = pd + length;
  341. BYTE* pstart = pd;
  342. while (pd < pend) {
  343. WORD count;
  344. if (count = CouldStoreSpan((DWORD**)&pd, (DWORD*)pend)) {
  345. DoRawStoreSpan(pstart, pd, prle);
  346. DoStoreSpan((DWORD**)&pd, prle, RLEMaskDWORD, count);
  347. pstart = pd;
  348. } else if (count = CouldStoreSpan((WORD**)&pd, (WORD*)pend)) {
  349. DoRawStoreSpan(pstart, pd, prle);
  350. DoStoreSpan((WORD**)&pd, prle, RLEMaskWORD, count);
  351. pstart = pd;
  352. } else if (count = CouldStoreSpan((BYTE**)&pd, (BYTE*)pend)) {
  353. DoRawStoreSpan(pstart, pd, prle);
  354. DoStoreSpan((BYTE**)&pd, prle, RLEMaskBYTE, count);
  355. pstart = pd;
  356. }
  357. pd++;
  358. }
  359. DoRawStoreSpan(pstart, pd, prle);
  360. }
  361. };
  362. //////////////////////////////////////////////////////////////////////////////
  363. //
  364. // Constructor
  365. //
  366. //////////////////////////////////////////////////////////////////////////////
  367. TRef<Image> CreateFrameImage(
  368. Number* pframe,
  369. Surface* psurface,
  370. int xframes,
  371. int yframes
  372. ) {
  373. //
  374. // compress the animation
  375. //
  376. TRef<Surface> psurfaceBackground;
  377. DWORD* pdwOffsets;
  378. BYTE* prle;
  379. CompressAnimClass foo(
  380. psurface,
  381. xframes,
  382. yframes,
  383. psurfaceBackground,
  384. pdwOffsets,
  385. prle
  386. );
  387. //
  388. // Create a frame image
  389. //
  390. return
  391. new FrameImage(
  392. new ConstantImage(psurfaceBackground, ZString()),
  393. pframe,
  394. xframes * yframes,
  395. pdwOffsets,
  396. prle,
  397. NULL
  398. );
  399. }
  400. //////////////////////////////////////////////////////////////////////////////
  401. //
  402. // FrameImageButtonPane
  403. //
  404. //////////////////////////////////////////////////////////////////////////////
  405. class FrameImageButtonPaneImpl :
  406. public FrameImageButtonPane,
  407. public Value
  408. {
  409. TRef<ModifiableNumber> m_pframe;
  410. TRef<Image> m_pimage;
  411. TRef<EventSourceImpl> m_peventSource;
  412. TRef<EventSourceImpl> m_peventMouseEnterSource;
  413. TRef<EventSourceImpl> m_peventMouseLeaveSource;
  414. bool m_bInside;
  415. float m_duration;
  416. float m_valueStart;
  417. float m_timeStart;
  418. float m_loop;
  419. float m_finish;
  420. public:
  421. FrameImageButtonPaneImpl(
  422. Number* ptime,
  423. Image* pimage,
  424. ModifiableNumber* pframe,
  425. float duration,
  426. bool loop,
  427. bool finish
  428. ) :
  429. Value(ptime),
  430. m_peventSource(new EventSourceImpl()),
  431. m_peventMouseEnterSource(new EventSourceImpl()),
  432. m_peventMouseLeaveSource(new EventSourceImpl()),
  433. m_pimage(pimage),
  434. m_pframe(pframe),
  435. m_duration(duration),
  436. m_loop(loop),
  437. m_finish(finish),
  438. m_bInside(false),
  439. m_valueStart(0),
  440. m_timeStart(ptime->GetValue())
  441. {
  442. InternalSetSize(
  443. WinPoint::Cast(m_pimage->GetBounds().GetRect().Size())
  444. );
  445. }
  446. Number* GetTime() { return Number::Cast(GetChild(0)); }
  447. //////////////////////////////////////////////////////////////////////////////
  448. //
  449. // FrameImageButtonPane methods
  450. //
  451. //////////////////////////////////////////////////////////////////////////////
  452. IEventSource* GetEventSource()
  453. {
  454. return m_peventSource;
  455. }
  456. IEventSource* GetMouseEnterEventSource()
  457. {
  458. return m_peventMouseEnterSource;
  459. }
  460. IEventSource* GetMouseLeaveEventSource()
  461. {
  462. return m_peventMouseLeaveSource;
  463. }
  464. //////////////////////////////////////////////////////////////////////////////
  465. //
  466. // Value Methods
  467. //
  468. //////////////////////////////////////////////////////////////////////////////
  469. void ChildChanged(Value* pvalue, Value* pvalueNew)
  470. {
  471. Value::ChildChanged(pvalue, pvalueNew);
  472. NeedPaint();
  473. }
  474. void Evaluate()
  475. {
  476. float time = GetTime()->GetValue();
  477. float value;
  478. float delta = (time - m_timeStart) / m_duration;
  479. if (m_bInside) {
  480. value = m_valueStart + delta;
  481. if (m_loop)
  482. {
  483. // wrap the value back around to the beginning
  484. value = float(value - (int)value);
  485. }
  486. } else {
  487. if (m_finish)
  488. {
  489. value = m_valueStart + delta;
  490. if (value > 1.0)
  491. value = 0.0;
  492. }
  493. else if (m_loop)
  494. {
  495. value = m_valueStart;
  496. }
  497. else
  498. {
  499. value = m_valueStart - delta;
  500. }
  501. }
  502. value = bound(value, 0.0f, 1.0f);
  503. if (value != m_pframe->GetValue()) {
  504. m_pframe->SetValue(value);
  505. NeedPaint();
  506. }
  507. }
  508. //////////////////////////////////////////////////////////////////////////////
  509. //
  510. // Pane Methods
  511. //
  512. //////////////////////////////////////////////////////////////////////////////
  513. void Paint(Surface* psurface)
  514. {
  515. Update();
  516. psurface->BitBlt(WinPoint(0, 0), m_pimage->GetSurface());
  517. }
  518. //////////////////////////////////////////////////////////////////////////////
  519. //
  520. // IMouseInput Methods
  521. //
  522. //////////////////////////////////////////////////////////////////////////////
  523. void MouseEnter(IInputProvider* pprovider, const Point& point)
  524. {
  525. m_bInside = true;
  526. m_valueStart = m_pframe->GetValue();
  527. m_timeStart = GetTime()->GetValue();
  528. m_peventMouseEnterSource->Trigger();
  529. }
  530. void MouseLeave(IInputProvider* pprovider)
  531. {
  532. m_bInside = false;
  533. m_valueStart = m_pframe->GetValue();
  534. m_timeStart = GetTime()->GetValue();
  535. m_peventMouseLeaveSource->Trigger();
  536. }
  537. MouseResult Button(IInputProvider* pprovider, const Point& point, int button, bool bCaptured, bool bInside, bool bDown)
  538. {
  539. if (button == 0) {
  540. if (bDown) {
  541. m_peventSource->Trigger();
  542. }
  543. }
  544. return MouseResult();
  545. }
  546. };
  547. TRef<FrameImageButtonPane> CreateFrameImageButtonPane(
  548. Number* ptime,
  549. Image* pimage,
  550. ModifiableNumber* pframe,
  551. float duration,
  552. bool loop,
  553. bool finish
  554. ) {
  555. return new FrameImageButtonPaneImpl(ptime, pimage, pframe, duration, loop, finish);
  556. }