Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

265 lines
9.4 KiB

  1. // CSweeper.cpp: implementation of the CSweeper class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "CSweeper.h"
  5. extern TextureBrush *g_paBrCleanBkg;
  6. extern Bitmap *g_paBmDirtyBkg;
  7. CSweeper::CSweeper()
  8. {
  9. ZeroMemory(&m_rDesktop,sizeof(m_rDesktop));
  10. ZeroMemory(&m_vLastPos,sizeof(m_vLastPos));
  11. m_flStepRadius=0.0f;
  12. m_flBroomWidth=0.0f;
  13. m_flSweepLength=0.0f;
  14. m_paBroomOn=NULL;
  15. m_paBroomOff=NULL;
  16. m_paBackground=NULL;
  17. m_bSweeping=false;
  18. m_flLastAngle=0.0f;
  19. m_flDist=0.0f;
  20. }
  21. CSweeper::~CSweeper()
  22. {
  23. Destroy();
  24. }
  25. void CSweeper::Destroy()
  26. {
  27. if (m_paBroomOn!=NULL) {
  28. delete m_paBroomOn;
  29. m_paBroomOn=NULL;
  30. }
  31. if (m_paBroomOff!=NULL) {
  32. delete m_paBroomOff;
  33. m_paBroomOff=NULL;
  34. }
  35. if (m_paBackground!=NULL) {
  36. delete m_paBackground;
  37. m_paBackground=NULL;
  38. }
  39. }
  40. BOOL CSweeper::Init(HWND hWnd)
  41. {
  42. int nRand;
  43. float flWidth;
  44. float flHeight;
  45. Destroy();
  46. // Get desktop dimensions (top/left can be negative on multimon)
  47. GetClientRect(hWnd,&m_rDesktop);
  48. flWidth=(float)m_rDesktop.right;
  49. flHeight=(float)m_rDesktop.bottom;
  50. m_rDesktop.top+=GetSystemMetrics(SM_YVIRTUALSCREEN);
  51. m_rDesktop.bottom+=GetSystemMetrics(SM_YVIRTUALSCREEN);
  52. m_rDesktop.left+=GetSystemMetrics(SM_XVIRTUALSCREEN);
  53. m_rDesktop.right+=GetSystemMetrics(SM_XVIRTUALSCREEN);
  54. m_flVelMax=((float)rand()/(float)RAND_MAX)*20.0f+20.0f;
  55. m_paBroomOn=LoadTGAResource(MAKEINTRESOURCE(IDR_BROOMON));
  56. m_paBroomOff=LoadTGAResource(MAKEINTRESOURCE(IDR_BROOMOFF));
  57. m_nSnapshotSize=(int)sqrt(m_paBroomOn->GetWidth()*m_paBroomOn->GetWidth()+(m_paBroomOn->GetHeight()+m_flVelMax*2.0f)*(m_paBroomOn->GetHeight()+m_flVelMax*2.0f));
  58. m_paBackground=new Bitmap(m_nSnapshotSize,m_nSnapshotSize,PixelFormat32bppPARGB);
  59. nRand=rand();
  60. if (nRand<RAND_MAX/4) { // Start walking from the left side of desktop
  61. m_vPos.X=(float)m_rDesktop.left;
  62. m_vPos.Y=((float)rand()/(float)RAND_MAX)*flHeight+m_rDesktop.top;
  63. m_vVel.X=((float)rand()/(float)RAND_MAX)*5.0f;
  64. m_vVel.Y=((float)rand()/(float)RAND_MAX)*10.0f-5.0f;
  65. }
  66. else if (nRand<2*RAND_MAX/4) { // Start walking from the right side of desktop
  67. m_vPos.X=(float)m_rDesktop.right;
  68. m_vPos.Y=((float)rand()/(float)RAND_MAX)*flHeight+m_rDesktop.top;
  69. m_vVel.X=((float)rand()/(float)RAND_MAX)*-5.0f;
  70. m_vVel.Y=((float)rand()/(float)RAND_MAX)*10.0f-5.0f;
  71. }
  72. else if (nRand<3*RAND_MAX/4) { // Start walking from the top side of desktop
  73. m_vPos.X=((float)rand()/(float)RAND_MAX)*flWidth+m_rDesktop.left;
  74. m_vPos.Y=(float)m_rDesktop.top;
  75. m_vVel.X=((float)rand()/(float)RAND_MAX)*10.0f-5.0f;
  76. m_vVel.Y=((float)rand()/(float)RAND_MAX)*5.0f;
  77. }
  78. else { // Start walking from the bottom side of desktop
  79. m_vPos.X=((float)rand()/(float)RAND_MAX)*flWidth+m_rDesktop.left;
  80. m_vPos.Y=(float)m_rDesktop.bottom;
  81. m_vVel.X=((float)rand()/(float)RAND_MAX)*10.0f-5.0f;
  82. m_vVel.Y=((float)rand()/(float)RAND_MAX)*-5.0f;
  83. }
  84. m_vAcc.X=((float)rand()/(float)RAND_MAX)*1.0f-0.5f;
  85. m_vAcc.Y=((float)rand()/(float)RAND_MAX)*1.0f-0.5f;
  86. m_flStepRadius=((float)rand()/(float)RAND_MAX)*10.0f+45.0f;
  87. m_flBroomWidth=m_paBroomOn->GetWidth()-6.0f;
  88. m_flSweepLength=((float)rand()/(float)RAND_MAX)*50.0f+200.0f;
  89. m_flStepRadius=m_flSweepLength;
  90. m_vVel=Normalize(m_vVel);
  91. m_vVel.X*=m_flVelMax;
  92. m_vVel.Y*=m_flVelMax;
  93. m_vLastPos=m_vPos;
  94. m_bSweeping=false;
  95. m_flDist=0.0f;
  96. m_flLastAngle=((float)atan2(m_vVel.Y,m_vVel.X)*180.0f/3.1415f);
  97. return true;
  98. }
  99. BOOL CSweeper::Move(Graphics *g)
  100. // Returns true if moved on screen, false if moved outside screen
  101. {
  102. float flAngle;
  103. float flAngleDist;
  104. if (m_bSweeping) {
  105. m_vPos=m_vPos+m_vVel;
  106. if ((m_vPos.X<(float)m_rDesktop.left-m_flSweepLength) ||
  107. (m_vPos.X>(float)m_rDesktop.right+m_flSweepLength) ||
  108. (m_vPos.Y<(float)m_rDesktop.top-m_flSweepLength) ||
  109. (m_vPos.Y>(float)m_rDesktop.bottom+m_flSweepLength)) {
  110. // If sweeper is outside desktop, erase it and remove it
  111. NoSweep(g);
  112. return false;
  113. }
  114. Sweep(g);
  115. }
  116. else {
  117. NoSweep(g);
  118. }
  119. if (!m_bSweeping && (m_flDist==0.0f)) {
  120. // If not sweeping and broom is back at distance 0, start next sweep
  121. m_bSweeping=true;
  122. m_flLastAngle=((float)atan2(m_vVel.Y,m_vVel.X)*180.0f/3.1415f);
  123. m_vPos.X=m_vPos.X-m_vVel.X*(m_flSweepLength/m_flVelMax*0.75f);
  124. m_vPos.Y=m_vPos.Y-m_vVel.Y*(m_flSweepLength/m_flVelMax*0.75f);
  125. m_vLastPos=m_vPos;
  126. flAngle=((float)atan2(m_vVel.Y,m_vVel.X)*180.0f/3.1415f);
  127. flAngleDist=((float)rand()/(float)RAND_MAX)*40.0f-20.0f;
  128. flAngle+=flAngleDist;
  129. m_vVel.X=(float)cos(flAngle*3.1415f/180.0f)*m_flVelMax;
  130. m_vVel.Y=(float)sin(flAngle*3.1415f/180.0f)*m_flVelMax;
  131. }
  132. return true;
  133. }
  134. void CSweeper::Sweep(Graphics *g)
  135. {
  136. Graphics *gBackground;
  137. RectF rect(0.0f,0.0f,m_flBroomWidth,m_flVelMax);
  138. RectF rect2(0.0f,0.0f,(float)m_paBroomOn->GetWidth(),(float)m_paBroomOn->GetHeight()+m_flVelMax);
  139. Matrix mat;
  140. GraphicsPath Path;
  141. Pen pen(Color(10,0,0,0),2);
  142. Graphics *gDirty;
  143. if (m_flDist!=0.0f) { // If broom has moved already, erase a rect on dirty background
  144. // Set up the brush transform (opposite from original transform)
  145. g_paBrCleanBkg->ResetTransform();
  146. mat.Reset();
  147. mat.Translate(0.0f,-m_flDist);
  148. mat.Translate(-(float)m_paBroomOn->GetWidth()/2.0f,-(float)m_paBroomOn->GetHeight()+20.0f);
  149. mat.Rotate(-m_flLastAngle-270.0f);
  150. mat.Translate(-m_vLastPos.X+m_rDesktop.left,-m_vLastPos.Y+m_rDesktop.top);
  151. g_paBrCleanBkg->SetTransform(&mat);
  152. // Set up original transform and erase from DirtyBkg a rectangle where the broom moved
  153. gDirty=new Graphics(g_paBmDirtyBkg);
  154. gDirty->TranslateTransform(m_vLastPos.X-m_rDesktop.left,m_vLastPos.Y-m_rDesktop.top);
  155. gDirty->RotateTransform(m_flLastAngle+270.0f);
  156. gDirty->TranslateTransform((float)m_paBroomOn->GetWidth()/2.0f,(float)m_paBroomOn->GetHeight()-20.0f);
  157. gDirty->TranslateTransform(0.0f,m_flDist);
  158. gDirty->FillRectangle(g_paBrCleanBkg,rect);
  159. // Draw dirty lines around the broom, to simulate dirty that fell beside the broom
  160. gDirty->DrawLine(&pen,0.0f,0.0f,0.0f,m_flVelMax+2);
  161. gDirty->DrawLine(&pen,0.0f,m_flVelMax+2,m_flBroomWidth,m_flVelMax+2);
  162. gDirty->DrawLine(&pen,m_flBroomWidth,m_flVelMax+2,m_flBroomWidth,0.0f);
  163. delete gDirty;
  164. }
  165. // Get the bounds of the broom after rotations
  166. Path.AddRectangle(rect2);
  167. mat.Reset();
  168. mat.Translate(m_vLastPos.X-m_rDesktop.left,m_vLastPos.Y-m_rDesktop.top);
  169. mat.Rotate(m_flLastAngle+270.0f);
  170. mat.Translate(m_flBroomWidth/2.0f,0.0);
  171. mat.Translate(0.0f,m_flDist);
  172. Path.GetBounds(&rect,&mat,&pen);
  173. // Draw on a temp surface whatever was on the dirty background where the broom is to be drawn
  174. gBackground=new Graphics(m_paBackground);
  175. gBackground->DrawImage(g_paBmDirtyBkg,0,0,(int)rect.X,(int)rect.Y,(int)rect.Width,(int)rect.Height,UnitPixel);
  176. // Draw broom on temp surface
  177. gBackground->ResetTransform();
  178. gBackground->TranslateTransform(rect.Width/2.0f,rect.Height/2.0f);
  179. gBackground->RotateTransform(m_flLastAngle+270.0f);
  180. gBackground->TranslateTransform(-(float)m_paBroomOn->GetWidth()/2.0f,-(float)m_paBroomOn->GetHeight()/2.0f+m_flVelMax/2.0f);
  181. gBackground->DrawImage(m_paBroomOn,0,0,0,0,m_paBroomOn->GetWidth(),m_paBroomOn->GetHeight(),UnitPixel);
  182. delete gBackground;
  183. // Draw temp surface to screen
  184. g->ResetTransform();
  185. g->DrawImage(m_paBackground,(int)rect.X,(int)rect.Y,0,0,(int)rect.Width,(int)rect.Height,UnitPixel);
  186. // Update distance, continue the sweep
  187. m_flDist+=m_flVelMax;
  188. if (m_flDist>m_flSweepLength) {
  189. // If sweep is at the end, start moving broom back
  190. m_flDist-=m_flVelMax;
  191. m_bSweeping=false;
  192. }
  193. }
  194. void CSweeper::NoSweep(Graphics *g)
  195. {
  196. Graphics *gBackground;
  197. RectF rect(0.0f,0.0f,m_flBroomWidth,m_flVelMax);
  198. RectF rect2(0.0f,0.0f,(float)m_paBroomOn->GetWidth(),(float)m_paBroomOn->GetHeight()+m_flVelMax);
  199. Matrix mat;
  200. GraphicsPath Path;
  201. Pen pen(Color(20,0,0,0),2);
  202. // Get the bounds of the broom after rotations
  203. Path.AddRectangle(rect2);
  204. mat.Reset();
  205. mat.Translate(m_vLastPos.X,m_vLastPos.Y);
  206. mat.Rotate(m_flLastAngle+270.0f);
  207. mat.Translate(m_flBroomWidth/2.0f,0.0f);
  208. mat.Translate(0.0f,m_flDist);
  209. Path.GetBounds(&rect,&mat,&pen);
  210. // Draw on a temp surface whatever was on the dirty background where the broom is to be drawn
  211. gBackground=new Graphics(m_paBackground);
  212. gBackground->DrawImage(g_paBmDirtyBkg,0,0,(int)rect.X-m_rDesktop.left,(int)rect.Y-m_rDesktop.top,(int)rect.Width,(int)rect.Height,UnitPixel);
  213. // Draw broom on temp surface
  214. gBackground->ResetTransform();
  215. gBackground->TranslateTransform(rect.Width/2.0f,rect.Height/2.0f);
  216. gBackground->RotateTransform(m_flLastAngle+270.0f);
  217. gBackground->TranslateTransform(-(float)m_paBroomOn->GetWidth()/2.0f,-(float)m_paBroomOn->GetHeight()/2.0f-m_flVelMax/2.0f);
  218. gBackground->DrawImage(m_paBroomOff,0,0,0,0,m_paBroomOn->GetWidth(),m_paBroomOn->GetHeight(),UnitPixel);
  219. delete gBackground;
  220. // Draw temp surface to screen
  221. g->ResetTransform();
  222. g->DrawImage(m_paBackground,(int)rect.X-m_rDesktop.left,(int)rect.Y-m_rDesktop.top,0,0,(int)rect.Width,(int)rect.Height,UnitPixel);
  223. // Update distance, continue moving back to start of sweep
  224. m_flDist-=m_flVelMax;
  225. if (m_flDist<=(m_flSweepLength/m_flVelMax*0.25f)*Magnitude(m_vVel)) {
  226. // If all the way back, erase last broom, and get ready for next sweep
  227. g->DrawImage(g_paBmDirtyBkg,(int)rect.X-m_rDesktop.left,(int)rect.Y-m_rDesktop.top,(int)rect.X-m_rDesktop.left,(int)rect.Y-m_rDesktop.top,(int)rect.Width,(int)rect.Height,UnitPixel);
  228. m_flDist=0.0f;
  229. }
  230. }