fork download
  1. #include <includes.h>
  2.  
  3. //AARRGGBB
  4. struct button_color
  5. {
  6. DWORD button;
  7. DWORD border;
  8. DWORD text;
  9. button_color(){}
  10. ~button_color(){}
  11. button_color(DWORD color_button,DWORD color_border,DWORD color_text)
  12. : button(color_button),border(color_border),text(color_text)
  13. {}
  14. };
  15.  
  16. class menu;
  17. class button
  18. {
  19. public:
  20. std::map<std::string,std::shared_ptr<menu>> Submenu;
  21.  
  22. std::string selected_submenu_item;
  23. std::string text_;
  24. button_color appearance_;
  25. button_color highlighted_;
  26. button_color mousedown_;
  27. bool clickable_;
  28. bool highlight_;
  29. unsigned short vkkey_;
  30. bool holding_;
  31. int fontid_;
  32.  
  33. button()
  34. {
  35. SetOnClickCode([]{});
  36. SetOnRMBHoldCode([]{});
  37. SetOnRMBHoldReleasedCode([]{});
  38. SetOnRMBReleasedCode([]{});
  39. holding_=false;
  40. }
  41. ~button()
  42. {
  43. Submenu.clear();
  44. }
  45. button(std::string button_text,button_color &appearance, button_color &highlighted, button_color &mousedown, bool clickable, bool highlight, int fontid = 1, unsigned short vkkey = VK_LBUTTON)
  46. : text_(button_text), appearance_(appearance), highlighted_(highlighted), clickable_(clickable), highlight_(highlight), mousedown_(mousedown), vkkey_(vkkey), fontid_(fontid)
  47. {
  48. SetOnClickCode([]{});
  49. SetOnRMBHoldCode([]{});
  50. SetOnRMBHoldReleasedCode([]{});
  51. SetOnRMBReleasedCode([]{});
  52. holding_=false;
  53. }
  54.  
  55. std::function<void(void)> OnClick;
  56. template<class Functor> void SetOnClickCode(Functor&& f)
  57. {
  58. OnClick = std::forward<Functor>(f);
  59. }
  60. std::function<void(void)> OnRMBHold;
  61. template<class Functor> void SetOnRMBHoldCode(Functor&& f)
  62. {
  63. OnRMBHold = std::forward<Functor>(f);
  64. }
  65. std::function<void(void)> OnRMBHoldReleased;
  66. template<class Functor> void SetOnRMBHoldReleasedCode(Functor&& f)
  67. {
  68. OnRMBHoldReleased = std::forward<Functor>(f);
  69. }
  70. std::function<void(void)> OnRMBReleased;
  71. template<class Functor> void SetOnRMBReleasedCode(Functor&& f)
  72. {
  73. OnRMBReleased = std::forward<Functor>(f);
  74. }
  75. void SetInfo(std::string button_text,button_color &appearance, button_color &highlighted, button_color &mousedown, bool clickable, bool highlight, int fontid = 1, unsigned short vkkey = VK_LBUTTON)
  76. {
  77. text_.assign(button_text);
  78. appearance_ = appearance;
  79. highlighted_ = highlighted;
  80. clickable_ = clickable;
  81. highlight_ = highlight;
  82. mousedown_ = mousedown;
  83. vkkey_ = vkkey;
  84. fontid_ = fontid;
  85. }
  86. void SetSelected()
  87. {
  88. appearance_ = selected_appearance;
  89. highlighted_ = selected_highlighted;
  90. mousedown_ = selected_mousedown;
  91. }
  92. void SetUnselected()
  93. {
  94. appearance_ = default_appearance;
  95. highlighted_ = default_highlighted;
  96. mousedown_ = default_mousedown;
  97. }
  98. float GetLenght()
  99. {
  100. return DirectXFont::Access(fontid_)->DrawLength(text_.c_str());
  101. }
  102. float GetHeight()
  103. {
  104. return DirectXFont::Access(fontid_)->DrawHeight();
  105. }
  106. void Display(float btn_x, float btn_y, float btn_w, float btn_h)
  107. {
  108. if(!Submenu.empty())
  109. {
  110. if(holding_)
  111. {
  112. if(Keys(VK_RBUTTON).Down)
  113. {
  114. OnRMBHold();//dunno, diplay submenu
  115. }else
  116. if(Keys(VK_RBUTTON).Released)
  117. {
  118. OnRMBHoldReleased();//select submenu item here
  119. holding_ = false;
  120. }
  121. }
  122. }
  123. if(!IsPointInArea(cursorPos.x,cursorPos.y,btn_x,btn_y,btn_w,btn_h))
  124. {
  125. render->D3DBoxBorder(btn_x,btn_y,btn_w,btn_h,appearance_.border,appearance_.button);
  126. DirectXFont::Access(fontid_)->Print(btn_x+((btn_w-GetLenght())/2.0f),btn_y+((btn_h-GetHeight())/2.0f),appearance_.text,text_.c_str(),true);
  127. return;
  128. }
  129. else
  130. {
  131. if(!Submenu.empty())
  132. {
  133. if(Keys(VK_RBUTTON).Pressed)
  134. {
  135. holding_ = true;
  136. }
  137. }
  138. if(Keys(VK_RBUTTON).Released)
  139. {
  140. OnRMBReleased();
  141. }
  142. }
  143. if(!clickable_)
  144. {
  145. render->D3DBoxBorder(btn_x,btn_y,btn_w,btn_h,(highlight_)? highlighted_.border : appearance_.border,(highlight_)? highlighted_.button : appearance_.button);
  146. DirectXFont::Access(fontid_)->Print(btn_x+((btn_w-GetLenght())/2.0f),btn_y+((btn_h-GetHeight())/2.0f),(highlight_)? highlighted_.text : appearance_.text,text_.c_str(),true);
  147. return;
  148. }
  149. if(!OldKeys(vkkey_).Down)
  150. {
  151. render->D3DBoxBorder(btn_x,btn_y,btn_w,btn_h,(highlight_)? highlighted_.border : appearance_.border,(highlight_)? highlighted_.button : appearance_.button);
  152. DirectXFont::Access(fontid_)->Print(btn_x+((btn_w-GetLenght())/2.0f),btn_y+((btn_h-GetHeight())/2.0f),(highlight_)? highlighted_.text : appearance_.text,text_.c_str(),true);
  153. return;
  154. }
  155. if(!Keys(vkkey_).Released)
  156. {
  157. render->D3DBoxBorder(btn_x,btn_y,btn_w,btn_h, mousedown_.border,mousedown_.button);
  158. DirectXFont::Access(fontid_)->Print(btn_x+((btn_w-GetLenght())/2.0f),btn_y+((btn_h-GetHeight())/2.0f), mousedown_.text,text_.c_str(),true);
  159. return;
  160. }
  161. OnClick();
  162. return;
  163. }
  164. void DisplayEx(float btn_x, float btn_y, float btn_w, float btn_h)
  165. {
  166. Display(btn_x, btn_y,GetLenght()+btn_w, GetHeight()+btn_h);
  167. }
  168. };
  169.  
  170. template<class T = int> struct slider_point
  171. {
  172. slider_point(){}
  173. slider_point(T x, T y): X(x), Y(y){}
  174. ~slider_point(){}
  175. T X;
  176. T Y;
  177. };
  178.  
  179. template<class T = int> struct slider_values
  180. {
  181. slider_values(){}
  182. slider_values(slider_point<T> min_values, slider_point<T> max_values, slider_point<T> default_values)
  183. :minimum(min_values),maximum(max_values),default(default_values),current(default_values)
  184. {}
  185. ~slider_values(){}
  186. slider_point<T> minimum;
  187. slider_point<T> maximum;
  188. slider_point<T> default;
  189. slider_point<T> current;
  190. };
  191.  
  192. struct slider_box
  193. {
  194. slider_box(){}
  195. ~slider_box(){}
  196. slider_box(slider_point<float> position, slider_point<float> size, DWORD color_inner, DWORD color_outline):
  197. pos(position), size(size), color_inner(color_inner), color_outline(color_outline)
  198. {}
  199. slider_point<float> pos;
  200. slider_point<float> size;
  201. DWORD color_inner;
  202. DWORD color_outline;
  203. void draw()
  204. {
  205. return render->D3DBoxBorder(pos.X,pos.Y,size.X,size.Y,color_outline,color_inner);
  206. }
  207. };
  208.  
  209. struct slider_button
  210. {
  211. slider_button(){}
  212. slider_button(slider_point<float> size, slider_point<float> pos, button_color _appearance = default_appearance, button_color _highlight = default_highlighted, button_color _mousedown = default_mousedown)
  213. : size(size), pos(pos), appearance(_appearance), highlight(_highlight), mousedown(_mousedown)
  214. {}
  215. ~slider_button(){}
  216. button_color appearance;
  217. button_color highlight;
  218. button_color mousedown;
  219. slider_point<float> size;
  220. slider_point<float> pos;
  221. bool IsPointOnThis(slider_point<float> point)
  222. {
  223. return IsPointInArea(point.X,point.Y,pos.X,pos.Y,size.X,size.Y);
  224. }
  225. bool IsMouseOnThis()
  226. {
  227. return IsPointOnThis(slider_point<float>((float)cursorPos.x,(float)cursorPos.y));
  228. }
  229. void SetPos(slider_point<float> point)
  230. {
  231. pos = point;
  232. }
  233. void SetCenter(slider_point<float> point)
  234. {
  235. pos.X = (point.X - (size.X/2.0f));
  236. pos.Y = (point.Y - (size.Y/2.0f));
  237. }
  238. void SetTopLeft(slider_point<float> point)
  239. {
  240. pos = point;
  241. }
  242. void SetTopRight(slider_point<float> point)
  243. {
  244. pos.Y = point.Y;
  245. pos.X = point.X-size.X;
  246. }
  247. void SetBottomLeft(slider_point<float> point)
  248. {
  249. pos.X = point.X;
  250. pos.Y = point.Y-size.Y;
  251. }
  252. void SetBottomRight(slider_point<float> point)
  253. {
  254. pos.X = point.X-size.X;
  255. pos.Y = point.Y-size.Y;
  256. }
  257. float GetLeft()
  258. {
  259. return pos.X;
  260. }
  261. float GetRight()
  262. {
  263. return pos.X+size.X;
  264. }
  265. float GetTop()
  266. {
  267. return pos.Y;
  268. }
  269. float GetBottom()
  270. {
  271. return pos.Y+size.Y;
  272. }
  273. slider_point<float> GetCenter()
  274. {
  275. return slider_point<float>(pos.X+(size.X/2.0f),pos.Y+(size.Y/2.0f));
  276. }
  277. void draw()
  278. {
  279. if(!IsPointInArea(cursorPos.x,cursorPos.y,pos.X,pos.Y,size.X,size.Y))
  280. return render->D3DBoxBorder(pos.X,pos.Y,size.X,size.Y,appearance.border,appearance.button);
  281. if(Keys(VK_LBUTTON).Down)
  282. return render->D3DBoxBorder(pos.X,pos.Y,size.X,size.Y,mousedown.border,mousedown.button);
  283. return render->D3DBoxBorder(pos.X,pos.Y,size.X,size.Y,highlight.border,highlight.button);
  284. }
  285. };
  286.  
  287. //not only left/right or up/down, but also both at once!
  288. template<class T = int> class slider
  289. {
  290. private:
  291. slider_values<T> data;
  292. bool Dragging;
  293. slider_point<float> DragMouseStart;
  294. slider_point<float> DragSliderStart;
  295. public:
  296. bool Show;
  297. bool LockXMovement;
  298. bool LockYMovement;
  299. slider_box box;
  300. slider_button sliding;
  301. slider(){Show = true;Dragging=false;}
  302. slider(slider_point<float> pos, slider_point<float> size, slider_point<T> minimum, slider_point<T> maximum, slider_point<T> default, slider_point<float> slider_size, DWORD _color_inner, DWORD _color_outline, bool LockX = false, bool LockY = false, button_color _appearance = default_appearance, button_color _highlighted = default_highlighted, button_color _mousedown = default_mousedown)
  303. : data(minimum,maximum,default),LockXMovement(LockX),LockYMovement(LockY),box(pos,size,_color_inner,_color_outline), sliding(slider_size,pos,_appearance,_highlighted,_mousedown)
  304. {
  305. Dragging = false;
  306. if(sliding.size.Y > box.size.Y)
  307. {
  308. sliding.size.Y = box.size.Y;
  309. LockYMovement = true;
  310. }
  311. if(sliding.size.X > box.size.X)
  312. {
  313. sliding.size.X = box.size.X;
  314. LockXMovement = true;
  315. }
  316.  
  317.  
  318. sliding.SetCenter( slider_point<float>( pos.X+( (float)(((float)(default.X-minimum.X))/((float)(maximum.X-minimum.X))) *size.X), pos.Y+( (float)(((float)(default.Y-minimum.Y))/((float)(maximum.Y-minimum.Y))) *size.Y)));
  319. if(sliding.pos.X < box.pos.X)
  320. sliding.pos = slider_point<float>( box.pos.X , sliding.pos.Y );
  321. if(sliding.GetRight() > (box.pos.X + box.size.X))
  322. sliding.SetTopRight(slider_point<float>( box.pos.X+box.size.X , sliding.pos.Y ));
  323. if(sliding.pos.Y < box.pos.Y)
  324. sliding.pos = slider_point<float>( sliding.pos.X , box.pos.Y );
  325. if(sliding.GetBottom() > (box.pos.Y+box.size.Y))
  326. sliding.SetBottomLeft(slider_point<float>( sliding.pos.X , box.pos.Y+box.size.Y ));
  327. Show = true;
  328. }
  329. slider_values<T> GetValue()
  330. {
  331. return data.current;
  332. }
  333. void SetPosByValue(slider_point<T> value)
  334. {
  335. sliding.pos.X = (box.pos.X + ((box.size.X-sliding.size.X)*(((float)(value.X-data.minimum.X))/((float)(data.maximum.X-data.minimum.X)))));
  336. sliding.pos.Y = (box.pos.Y + ((box.size.Y-sliding.size.Y)*(((float)(value.Y-data.minimum.Y))/((float)(data.maximum.Y-data.minimum.Y)))));
  337. }
  338. void SetPosByValueX(T value)
  339. {
  340. sliding.pos.X = (box.pos.X + ((box.size.X-sliding.size.X)*(((float)(value-data.minimum.X))/((float)(data.maximum.X-data.minimum.X)))));
  341. }
  342. void SetPosByValueY(T value)
  343. {
  344. sliding.pos.Y = (box.pos.Y + ((box.size.Y-sliding.size.Y)*(((float)(value-data.minimum.Y))/((float)(data.maximum.Y-data.minimum.Y)))));
  345. }
  346. void Process()
  347. {
  348. if(Dragging)
  349. {
  350. if(Keys(VK_LBUTTON).Up)
  351. {
  352. Dragging = false;
  353. }
  354. if(!LockXMovement)
  355. {
  356. float mousepos = (float)cursorPos.x;
  357. sliding.pos = slider_point<float>( DragSliderStart.X+(mousepos-DragMouseStart.X) , sliding.pos.Y );
  358. if(sliding.pos.X < box.pos.X)
  359. sliding.pos = slider_point<float>( box.pos.X , sliding.pos.Y );
  360. if(sliding.GetRight() > (box.pos.X+box.size.X))
  361. sliding.SetTopRight(slider_point<float>( box.pos.X+box.size.X , sliding.pos.Y ));
  362. data.current.X = data.minimum.X + (T)((float)(data.maximum.X-data.minimum.X) * ((sliding.pos.X-box.pos.X)/(box.size.X-sliding.size.X)));
  363. }
  364. if(!LockYMovement)
  365. {
  366. float mousepos = (float)cursorPos.y;
  367. sliding.pos = slider_point<float>( sliding.pos.X , DragSliderStart.Y+(mousepos-DragMouseStart.Y) );
  368. if(sliding.pos.Y < box.pos.Y)
  369. sliding.pos = slider_point<float>( sliding.pos.X , box.pos.Y );
  370. if(sliding.GetBottom() > (box.pos.Y+box.size.Y))
  371. sliding.SetBottomLeft(slider_point<float>( sliding.pos.X , box.pos.Y+box.size.Y ));
  372. data.current.Y = data.minimum.Y + (T)((float)(data.maximum.Y-data.minimum.Y) * ((sliding.pos.Y-box.pos.Y)/(box.size.Y-sliding.size.Y)));
  373. }
  374. DirectXFont::Access(4)->Print(0.0f,50.0f,0xFF00FF00,string_format("[%04d,%04d]",(int)data.current.X,(int)data.current.Y).c_str());
  375. }else
  376. if(Keys(VK_LBUTTON).Pressed)
  377. {
  378. if(sliding.IsMouseOnThis())
  379. {
  380. Dragging = true;
  381. DragMouseStart.X = (float)cursorPos.x;
  382. DragMouseStart.Y = (float)cursorPos.y;
  383. DragSliderStart = sliding.pos;
  384. }
  385. }
  386. box.draw();
  387. sliding.draw();
  388. }
  389. ~slider()
  390. {
  391.  
  392. }
  393. };
  394.  
  395. class menu
  396. {
  397. public:
  398. typedef boost::variant<std::shared_ptr<slider<int>>,std::shared_ptr<slider<float>>,std::shared_ptr<slider<double>>,std::shared_ptr<slider<char>>> slider_type;
  399. std::map<std::string,slider_type> Sliders;
  400. std::map<std::string,std::shared_ptr<button>> Buttons;
  401. float pos_top_;
  402. float pos_left_;
  403. float spacing_;
  404. float width_;
  405. float height_;
  406. DWORD BoxColor;
  407. DWORD BorderColor;
  408. bool horizontal_;
  409. bool central_;
  410. bool manual_draw_;
  411.  
  412. std::string name_;
  413. menu()
  414. {
  415. pos_top_ = 0.0f;
  416. pos_left_ = 0.0f;
  417. spacing_ = 5.0f;
  418. width_ = 0.0f;
  419. height_ = 0.0f;
  420. BoxColor = 0xFF330088;
  421. BorderColor = 0xFF338800;
  422. manual_draw_ = false;
  423. horizontal_ = true;
  424. central_ = false;
  425. SetOnProcessExtraCode([]{});
  426. }
  427. ~menu()
  428. {
  429. Buttons.clear();
  430. Sliders.clear();
  431. }
  432. void SetProcessParameters(bool horizontal, bool central, bool manual_draw = false)
  433. {
  434. horizontal_ = horizontal;
  435. central_ = central;
  436. manual_draw_ = manual_draw;
  437. }
  438. std::function<void(void)> OnProcessExtra;
  439. template<class Functor> void SetOnProcessExtraCode(Functor&& f)
  440. {
  441. OnProcessExtra = std::forward<Functor>(f);
  442. }
  443. void SetupWidth()
  444. {
  445. width_ = 0.0f;
  446. height_ = 0.0f;
  447. for(auto i = Buttons.begin(); i != Buttons.end(); ++i)
  448. {
  449. if(width_ < i->second->GetLenght())
  450. {
  451. width_ = i->second->GetLenght();
  452. }
  453. if(height_ < i->second->GetHeight())
  454. {
  455. height_ = i->second->GetHeight();
  456. }
  457. }
  458. }
  459. std::shared_ptr<button>& AddButton(std::string name,std::shared_ptr<button> button)
  460. {
  461. Buttons.emplace(name,button);
  462. SetupWidth();
  463. return Buttons[name];
  464. }
  465. void RemoveButton(std::shared_ptr<button> button)
  466. {
  467. for(auto i = Buttons.begin(); i != Buttons.end(); ++i)
  468. {
  469. if(i->second == button)
  470. {
  471. Buttons.erase(i);
  472. break;
  473. }
  474. }
  475. SetupWidth();
  476. }
  477. void RemoveButton(std::string name)
  478. {
  479. for(auto i = Buttons.begin(); i != Buttons.end(); ++i)
  480. {
  481. if(i->first == name)
  482. {
  483. Buttons.erase(i);
  484. break;
  485. }
  486. }
  487. SetupWidth();
  488. }
  489. float GetWidth()
  490. {
  491. if(!horizontal_)
  492. return (width_ + (spacing_ * 4.0f));
  493. if(Buttons.empty())
  494. return spacing_;
  495. return spacing_ + ((width_ + (3.0f * spacing_)) * ((float)Buttons.size()));
  496. }
  497. float GetHeight()
  498. {
  499. if(horizontal_)
  500. return (3.0f * spacing_) + height_;
  501. if(Buttons.empty())
  502. return spacing_;
  503. return spacing_ + (((float)Buttons.size())*spacing_)+((spacing_ + height_)*((float)Buttons.size()));
  504. }
  505. void Process()
  506. {
  507. OnProcessExtra();
  508. if(!Sliders.empty())
  509. {
  510. for(auto i = Sliders.begin(); i != Sliders.end(); ++i)
  511. {
  512. switch(i->second.which())
  513. {
  514. case 0://slider<int>
  515. {
  516. boost::get<std::shared_ptr<slider<int>>>(i->second)->Process();
  517. break;
  518. }
  519. case 1://slider<float>
  520. {
  521. boost::get<std::shared_ptr<slider<float>>>(i->second)->Process();
  522. break;
  523. }
  524. case 2://slider<double>
  525. {
  526. boost::get<std::shared_ptr<slider<double>>>(i->second)->Process();
  527. break;
  528. }
  529. case 3://slider<char>
  530. {
  531. boost::get<std::shared_ptr<slider<char>>>(i->second)->Process();
  532. break;
  533. }
  534. }
  535. }
  536. }
  537. if(!manual_draw_)
  538. {
  539. if(!Buttons.empty())
  540. {
  541. if(central_)
  542. {
  543. Pos((((float)ScreenX)/2.0f)-(GetWidth()/2.0f),(((float)ScreenY)/2.0f)-(GetHeight()/2.0f));
  544. }
  545. if(!horizontal_)
  546. {
  547. render->D3DBoxBorder(pos_left_,pos_top_,(width_ + (spacing_ * 4.0f)),spacing_ + (((float)Buttons.size())*spacing_)+((spacing_ + height_)*((float)Buttons.size())), BorderColor,BoxColor);
  548. int x = 0;
  549. for(auto i = Buttons.begin(); i != Buttons.end(); ++i)
  550. {
  551. i->second->Display(pos_left_ + spacing_,pos_top_ + spacing_ + spacing_*((float)x) + ((spacing_ + height_)*(float)x),(width_ + (2.0f * spacing_)),height_+spacing_);
  552. ++x;
  553. }
  554. }
  555. else
  556. {
  557. render->D3DBoxBorder(pos_left_,pos_top_,spacing_ + ((width_ + (3.0f * spacing_)) * ((float)Buttons.size())),(3.0f * spacing_) + height_, BorderColor,BoxColor);
  558. int x = 0;
  559. for(auto i = Buttons.begin(); i != Buttons.end(); ++i)
  560. {
  561. i->second->Display(pos_left_ + spacing_ + ((width_ + (3.0f * spacing_)) * ((float)x)),pos_top_ + spacing_ ,(width_ + (2.0f * spacing_)),height_+spacing_);
  562. ++x;
  563. }
  564. }
  565. }
  566. }
  567. }
  568. void Pos(float x, float y)
  569. {
  570. pos_left_ = x;
  571. pos_top_ = y;
  572. }
  573. void Colors(DWORD border,DWORD background)
  574. {
  575. BorderColor = border;
  576. BoxColor = background;
  577. }
  578. };
  579.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty