Advertisement
Guest User

Untitled

a guest
Feb 27th, 2020
172
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.81 KB | None | 0 0
  1. #include "ofMain.h"
  2.  
  3. /**
  4.  * This is the base class for all ui elements.
  5.  * It can have children, so you can have nested elements.
  6.  * A UI is often represented as a tree - you have the root
  7.  * which is like the window that holds everything, then all the controls
  8.  * or sub-panels etc are children of that.
  9.  *
  10.  * It inherits from ofRectangle becasue it's almost always
  11.  * useful for a UI control to have a position, width and height.
  12.  *
  13.  * The methods propagate***() are to send events to every child
  14.  * of this UI element if it has any.
  15.  */
  16. class UIElement: public ofRectangle {
  17. public:
  18.    
  19.     // whether the touch is down on this element
  20.     bool isDown = false;
  21.  
  22.     // This is what you implement to draw your UI element.
  23.     virtual void draw() {}
  24.    
  25.     // this gets called when you receive a touch down event
  26.     // you need to decide whether to act upon it - if you
  27.     // do then return true, otherwise return false if the
  28.     // touch is irrelevant to you.
  29.     virtual bool touchDown(int x, int y) {}
  30.     virtual void touchMoved(int x, int y) {}
  31.     virtual void touchUp(int x, int y) {}
  32.    
  33.     /////////////////////////////////////////////////////////////////////
  34.    
  35.    
  36.    
  37.    
  38.     void addChild(shared_ptr<UIElement> child) {
  39.         children.push_back(child);
  40.     }
  41.    
  42.  
  43.     // EVENT PROPAGATION
  44.    
  45.     // The draw call positions children relative to themselves
  46.     void propagateDraw() {
  47.        
  48.         draw();
  49.        
  50.         ofPushMatrix();
  51.         ofTranslate(x, y);
  52.         for(auto &c : children) {
  53.             c->propagateDraw();
  54.         }
  55.         ofPopMatrix();
  56.     }
  57.    
  58.     bool propagateTouchDown(int x, int y) {
  59.        
  60.         for(auto it = children.rbegin(); it != children.rend(); it++) {
  61.             if((*it)->propagateTouchDown(x - this->x, y - this->y)) {
  62.                 return true;
  63.             }
  64.         }
  65.  
  66.         if(inside(x, y)) {
  67.             isDown = true;
  68.             return touchDown(x, y);
  69.         }
  70.         return false;
  71.     }
  72.        
  73.    
  74.     void propagateTouchMoved(int x, int y) {
  75.         for(auto it = children.rbegin(); it != children.rend(); it++) {
  76.             (*it)->propagateTouchMoved(x - this->x, y - this->y);
  77.         }
  78.         if(isDown) {
  79.             touchMoved(x, y);
  80.         }
  81.     }
  82.    
  83.     void propagateTouchUp(int x, int y) {
  84.         for(auto it = children.rbegin(); it != children.rend(); it++) {
  85.             (*it)->propagateTouchUp(x - this->x, y - this->y);
  86.         }
  87.         if(isDown) {
  88.             touchUp(x, y);
  89.         }
  90.         isDown = false;
  91.     }
  92. protected:
  93.     vector<shared_ptr<UIElement>> children;
  94. };
  95.  
  96.  
  97.  
  98. //--------------------------------------------------------------
  99.  
  100.  
  101. /**
  102.  * Here's an example of how a button would work
  103.  */
  104. class Button : public UIElement {
  105. public:
  106.    
  107.    
  108.     string label;
  109.    
  110.     // this is what happens when you press the button
  111.     function<void()> action;
  112.    
  113.    
  114.     Button(string label) {
  115.         this->label = label;
  116.         width = 100;
  117.         height = 40;
  118.     }
  119.    
  120.    
  121.     void draw() {
  122.         // if the button is down, draw it dark
  123.         // otherwise draw it light.
  124.         ofSetHexColor(isDown?0x555555:0xCCCCCC);
  125.         ofDrawRectRounded(*this, 5);
  126.         ofSetHexColor(isDown?0xCCCCCC:0x555555);
  127.         // draw string roughly in the centre
  128.         ofDrawBitmapString(label, x + width / 2 - label.size() * 4, y + height / 2 + 6);
  129.     }
  130.    
  131.     // buttons generally only react on touch up events
  132.     void touchUp(int x, int y) {
  133.         if(isDown && inside(x, y) && action) {
  134.             action();
  135.         }
  136.         isDown = false;
  137.     }
  138. };
  139.  
  140. //--------------------------------------------------------------
  141.  
  142. class Menu : public UIElement {
  143. public:
  144.     bool isShowing = false;
  145.     Menu() {
  146.         // make the menu as tall as the screen
  147.         height = ofGetHeight();
  148.         width = 200;
  149.        
  150.         // put it offscreen for now
  151.         x = -width;
  152.     }
  153.    
  154.     void draw() {
  155.        
  156.         // this animates the menu in and out
  157.         if(isShowing) {
  158.             x *= 0.9;
  159.         } else {
  160.             x = x * 0.9 - width * 0.1;
  161.         }
  162.        
  163.         // just draw a dark background
  164.         ofSetHexColor(0x333333);
  165.         ofDrawRectangle(*this);
  166.     }
  167.    
  168. };
  169. //--------------------------------------------------------------
  170.  
  171. /**
  172.  * A basic slider
  173.  */
  174. class Slider : public UIElement {
  175. public:
  176.     string label;
  177.     float *val;
  178.    
  179.     // Takes a reference to the variable
  180.     // you want to change and saves it
  181.     // as a pointer. Works on the basis that
  182.     // your number goes from 0 to 1.
  183.     Slider(string label, float &val) {
  184.         this->label = label;
  185.         this->val = &val;
  186.         width = 160;
  187.         height = 20;
  188.     }
  189.    
  190.     void draw() {
  191.        
  192.         ofSetHexColor(0xCCCCCC);
  193.         // slider label
  194.         ofDrawBitmapString(label, x, y-5);
  195.         // slider background
  196.         ofDrawRectRounded(*this, 5);
  197.        
  198.         // draw the slider value
  199.         ofSetHexColor(0x666666);
  200.         ofRectangle r = *this;
  201.         r.width *= *val;
  202.         ofDrawRectRounded(r, 5);
  203.     }
  204.    
  205.     // set the value from the position of the mouse
  206.     // relative to the sliders x and width
  207.     bool touchDown(int x, int y) {
  208.         *val = ofMap(x, this->x, this->getRight(), 0, 1, true);
  209.     }
  210.    
  211.     // does the same as touchDown, so just call touch down.
  212.     void touchMoved(int x, int y) {
  213.         touchDown(x, y);
  214.     }
  215.     void touchUp(int x, int y) {
  216.     }
  217. };
  218.  
  219. // This is the root of the UI
  220. shared_ptr<UIElement> root;
  221.  
  222. // menu show/hide button
  223. shared_ptr<Button> menuButton;
  224.  
  225. // the menu - it's a container
  226. // for menu items.
  227. shared_ptr<Menu> menu;
  228.  
  229. int PADDING = 10;
  230.  
  231. glm::vec3 color;
  232.  
  233.  
  234.  
  235.  
  236. //--------------------------------------------------------------
  237. class ofApp : public ofBaseApp {
  238.     void setup(){
  239.         root = make_shared<UIElement>();
  240.        
  241.        
  242.         // create a menu button that will toggle the menu's isShowing variable when pressed
  243.        
  244.         menuButton = make_shared<Button>("SHOW");
  245.        
  246.         // position it
  247.         menuButton->x = menuButton->y = PADDING;
  248.        
  249.         // this is what happens when you press the menu button
  250.         menuButton->action = []() {
  251.             // toggle showing menu when menu button is pressed.
  252.             menu->isShowing = !menu->isShowing;
  253.            
  254.             // change the text of the menu button depending
  255.             // on whether the menu is showing or not.
  256.             if(menu->isShowing) {
  257.                 menuButton->label = "HIDE";
  258.             } else {
  259.                 menuButton->label = "SHOW";
  260.             }
  261.         };
  262.        
  263.        
  264.         menu = make_shared<Menu>();
  265.        
  266.         // make some buttons for the menu
  267.         auto someButton      = make_shared<Button>("SOMETHING");
  268.         auto someOtherButton = make_shared<Button>("OTHER THING");
  269.        
  270.         // a few sliders
  271.         auto redSlider       = make_shared<Slider>("Red", color.r);
  272.         auto greenSlider     = make_shared<Slider>("Green", color.g);
  273.         auto blueSlider      = make_shared<Slider>("Blue", color.b);
  274.        
  275.        
  276.         // position everything
  277.         someButton->x = someOtherButton->x = redSlider->x = greenSlider->x = blueSlider->x = PADDING;
  278.         someButton->y = menuButton->getBottom() + PADDING;
  279.         someOtherButton->y = someButton->getBottom() + PADDING;
  280.        
  281.         redSlider->y = someOtherButton->getBottom() + PADDING*6;
  282.         greenSlider->y = redSlider->getBottom() + PADDING*6;
  283.         blueSlider->y = greenSlider->getBottom() + PADDING*6;
  284.        
  285.         // add everything to the menu
  286.         menu->addChild(someButton);
  287.         menu->addChild(someOtherButton);
  288.         menu->addChild(redSlider);
  289.         menu->addChild(greenSlider);
  290.         menu->addChild(blueSlider);
  291.        
  292.        
  293.         // add the menu and the menu button to the root
  294.         root->addChild(menu);
  295.         root->addChild(menuButton);
  296.     }
  297.  
  298.     //--------------------------------------------------------------
  299.     void draw(){
  300.         ofSetBackgroundColor(color.r * 255.f, color.g * 255.f, color.b * 255.f);
  301.         root->propagateDraw();
  302.     }
  303.  
  304.     //--------------------------------------------------------------
  305.     void mousePressed(int x, int y, int button){
  306.         root->propagateTouchDown(x, y);
  307.     }
  308.  
  309.     //--------------------------------------------------------------
  310.     void mouseDragged(int x, int y, int button){
  311.         root->propagateTouchMoved(x, y);
  312.     }
  313.  
  314.  
  315.     //--------------------------------------------------------------
  316.     void mouseReleased(int x, int y, int button){
  317.         root->propagateTouchUp(x, y);
  318.     }
  319. };
  320.  
  321. //========================================================================
  322. int main( ){
  323.     ofSetupOpenGL(1024,768,OF_WINDOW);          // <-------- setup the GL context
  324.  
  325.     // this kicks off the running of my app
  326.     // can be OF_WINDOW or OF_FULLSCREEN
  327.     // pass in width and height too:
  328.     ofRunApp(new ofApp());
  329.  
  330. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement