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.

176 lines
5.0KB

  1. /* ---------------------------------------------------------------------------|
  2. *
  3. * Distributed under the CC0 public domain license.
  4. * By Alison G. Watson. Attribution is encouraged, though not required.
  5. * See licenses/cc0.txt for more information.
  6. *
  7. * ---------------------------------------------------------------------------|
  8. *
  9. * GUI scroll bars.
  10. *
  11. * ---------------------------------------------------------------------------|
  12. */
  13. #include "common.h"
  14. #include "p_player.h"
  15. /* This function is excessively commented in case I need to change it.
  16. * Reading this function will cause a 5x1d20 hit to your SAN stat. Beware!
  17. */
  18. void G_ScrBeg_Imp(struct gui_state *g, u32 id, struct gui_arg_scr const *a) {
  19. struct gui_pre_scr const *pre = a->preset ? a->preset : &gui_p.scrdef;
  20. struct gui_scr *scr = a->st;
  21. /* sizes */
  22. i32 const blockh = pre->scrlh; /* height of graphical block */
  23. i32 const blocks = a->h / blockh - 1; /* height in graphical blocks -caps */
  24. i32 const caph = blockh / 2; /* size of cap */
  25. i32 const caps = blocks * 2; /* height in caps, -caps */
  26. i32 const h = blocks * blockh; /* height in pixels -caps */
  27. i32 const realh = h + caph * 2; /* height in pixels +caps */
  28. /* positions */
  29. i32 x = a->x + pre->scrlw; /* base x to draw from */
  30. i32 y = a->y; /* base y to draw from */
  31. /* check collision - height is minus caps, and y is offset by the top cap */
  32. G_Auto(g, id, x - pre->scrlw, y + caph, pre->scrlw, h);
  33. /* add offset */
  34. x += g->ox;
  35. y += g->oy;
  36. /* get height of scroller */
  37. i32 notches; /* height of scroller in caps */
  38. if(a->contenth > realh) notches = a->h / (k64)a->contenth * caps;
  39. else notches = caps;
  40. i32 const scrlh = notches * caph; /* height in pixels of scroller */
  41. k64 const maxy = (h - scrlh) / (k64)h; /* normalized maximum y value */
  42. /* decrement the sound timer */
  43. if(scr->nextsnd) scr->nextsnd--;
  44. /* move scroller */
  45. __with(k64 supposedy = scr->y * h;)
  46. {
  47. if(g->active == id)
  48. {
  49. k64 const cy = g->cy - y - caph;
  50. /* if it isn't grabbed and the cursor is over the scroller, */
  51. /* set the grab position to where the cursor is relative to it */
  52. if(!scr->grabbed && cy > supposedy && cy < supposedy + scrlh)
  53. {
  54. scr->grabbed = true;
  55. scr->grabpos = cy - supposedy;
  56. }
  57. /* if the scroller is grabbed we set the position relative to where */
  58. /* we grabbed it from, otherwise we just use the middle of it */
  59. if(scr->grabbed) supposedy = cy - scr->grabpos;
  60. else supposedy = cy - scrlh / 2;
  61. if(g->cy != g->old.cy && scr->nextsnd == 0)
  62. {
  63. ACS_LocalAmbientSound(ss_player_cbi_scroll, 127);
  64. scr->nextsnd = 7;
  65. }
  66. }
  67. else if(scr->grabbed)
  68. {
  69. ACS_LocalAmbientSound(ss_player_cbi_scrollend, 127);
  70. scr->grabbed = false;
  71. scr->nextsnd = 0;
  72. }
  73. /* finally, normalize and clamp */
  74. scr->y = supposedy / (k64)h;
  75. scr->y = minmax(scr->y, 0, maxy);
  76. }
  77. /* get offset of scroller */
  78. __with(i32 vofs = 0;) /* offset in pixels of the content */
  79. {
  80. if(a->contenth > realh)
  81. vofs = roundlk((a->contenth - realh) * (scr->y / maxy), 10);
  82. /* set the scrollbar's offset */
  83. scr->ox = a->x + pre->scrlw; /* offset by scrollbar width */
  84. scr->oy = a->y - vofs; /* offset by scroller pos */
  85. /* set the top and bottom for occlusion */
  86. scr->occludeS = vofs;
  87. scr->occludeE = vofs + realh;
  88. }
  89. /* draw top cap */
  90. __with(char cap[64];)
  91. {
  92. G_Prefix(g, cap, pre, capS);
  93. PrintSprite(l_strdup(cap), x,2, y,1);
  94. }
  95. y += caph;
  96. /* draw middle of bar */
  97. __with(char scrl[64];)
  98. {
  99. G_Prefix(g, scrl, pre, scrl);
  100. str scrls = l_strdup(scrl);
  101. for(i32 i = 0; i < blocks; i++)
  102. {
  103. PrintSprite(scrls, x,2, y,1);
  104. y += blockh;
  105. }
  106. }
  107. /* draw bottom cap */
  108. __with(char cap[64];)
  109. {
  110. G_Prefix(g, cap, pre, capE);
  111. if(cap[0]) PrintSprite(l_strdup(cap), x,2, y,1);
  112. }
  113. /* get base Y */
  114. i32 const ory = a->y + g->oy;
  115. /* draw scroller */
  116. __with(char gfx[64];)
  117. {
  118. if(g->hot == id || g->active == id) G_Prefix(g, gfx, pre, notchhot);
  119. else G_Prefix(g, gfx, pre, notchgfx);
  120. str gfxs = l_strdup(gfx);
  121. for(i32 i = 0; i < notches; i++)
  122. {
  123. i32 const npos = roundlk(caph + h * scr->y + caph * i, 10);
  124. PrintSprite(gfxs, x,2, ory + npos,1);
  125. }
  126. }
  127. /* setup offsets */
  128. g->ox += scr->ox;
  129. g->oy += scr->oy;
  130. /* setup clip */
  131. G_Clip(g, x, ory, a->w, realh, a->ww);
  132. }
  133. void G_ScrEnd(struct gui_state *g, struct gui_scr *scr)
  134. {
  135. /* reset offsets */
  136. g->ox -= scr->ox;
  137. g->oy -= scr->oy;
  138. /* reset clip */
  139. G_ClipRelease(g);
  140. }
  141. bool G_ScrOcc(struct gui_state *g, struct gui_scr const *scr, i32 y, i32 h)
  142. {
  143. return y > scr->occludeE || (h && (y + h) - scr->occludeS < 0);
  144. }
  145. /* EOF */