Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "ofMain.h"
- /**
- * This is the base class for all ui elements.
- * It can have children, so you can have nested elements.
- * A UI is often represented as a tree - you have the root
- * which is like the window that holds everything, then all the controls
- * or sub-panels etc are children of that.
- *
- * It inherits from ofRectangle becasue it's almost always
- * useful for a UI control to have a position, width and height.
- *
- * The methods propagate***() are to send events to every child
- * of this UI element if it has any.
- */
- class UIElement: public ofRectangle {
- public:
- // whether the touch is down on this element
- bool isDown = false;
- // This is what you implement to draw your UI element.
- virtual void draw() {}
- // this gets called when you receive a touch down event
- // you need to decide whether to act upon it - if you
- // do then return true, otherwise return false if the
- // touch is irrelevant to you.
- virtual bool touchDown(int x, int y) {}
- virtual void touchMoved(int x, int y) {}
- virtual void touchUp(int x, int y) {}
- /////////////////////////////////////////////////////////////////////
- void addChild(shared_ptr<UIElement> child) {
- children.push_back(child);
- }
- // EVENT PROPAGATION
- // The draw call positions children relative to themselves
- void propagateDraw() {
- draw();
- ofPushMatrix();
- ofTranslate(x, y);
- for(auto &c : children) {
- c->propagateDraw();
- }
- ofPopMatrix();
- }
- bool propagateTouchDown(int x, int y) {
- for(auto it = children.rbegin(); it != children.rend(); it++) {
- if((*it)->propagateTouchDown(x - this->x, y - this->y)) {
- return true;
- }
- }
- if(inside(x, y)) {
- isDown = true;
- return touchDown(x, y);
- }
- return false;
- }
- void propagateTouchMoved(int x, int y) {
- for(auto it = children.rbegin(); it != children.rend(); it++) {
- (*it)->propagateTouchMoved(x - this->x, y - this->y);
- }
- if(isDown) {
- touchMoved(x, y);
- }
- }
- void propagateTouchUp(int x, int y) {
- for(auto it = children.rbegin(); it != children.rend(); it++) {
- (*it)->propagateTouchUp(x - this->x, y - this->y);
- }
- if(isDown) {
- touchUp(x, y);
- }
- isDown = false;
- }
- protected:
- vector<shared_ptr<UIElement>> children;
- };
- //--------------------------------------------------------------
- /**
- * Here's an example of how a button would work
- */
- class Button : public UIElement {
- public:
- string label;
- // this is what happens when you press the button
- function<void()> action;
- Button(string label) {
- this->label = label;
- width = 100;
- height = 40;
- }
- void draw() {
- // if the button is down, draw it dark
- // otherwise draw it light.
- ofSetHexColor(isDown?0x555555:0xCCCCCC);
- ofDrawRectRounded(*this, 5);
- ofSetHexColor(isDown?0xCCCCCC:0x555555);
- // draw string roughly in the centre
- ofDrawBitmapString(label, x + width / 2 - label.size() * 4, y + height / 2 + 6);
- }
- // buttons generally only react on touch up events
- void touchUp(int x, int y) {
- if(isDown && inside(x, y) && action) {
- action();
- }
- isDown = false;
- }
- };
- //--------------------------------------------------------------
- class Menu : public UIElement {
- public:
- bool isShowing = false;
- Menu() {
- // make the menu as tall as the screen
- height = ofGetHeight();
- width = 200;
- // put it offscreen for now
- x = -width;
- }
- void draw() {
- // this animates the menu in and out
- if(isShowing) {
- x *= 0.9;
- } else {
- x = x * 0.9 - width * 0.1;
- }
- // just draw a dark background
- ofSetHexColor(0x333333);
- ofDrawRectangle(*this);
- }
- };
- //--------------------------------------------------------------
- /**
- * A basic slider
- */
- class Slider : public UIElement {
- public:
- string label;
- float *val;
- // Takes a reference to the variable
- // you want to change and saves it
- // as a pointer. Works on the basis that
- // your number goes from 0 to 1.
- Slider(string label, float &val) {
- this->label = label;
- this->val = &val;
- width = 160;
- height = 20;
- }
- void draw() {
- ofSetHexColor(0xCCCCCC);
- // slider label
- ofDrawBitmapString(label, x, y-5);
- // slider background
- ofDrawRectRounded(*this, 5);
- // draw the slider value
- ofSetHexColor(0x666666);
- ofRectangle r = *this;
- r.width *= *val;
- ofDrawRectRounded(r, 5);
- }
- // set the value from the position of the mouse
- // relative to the sliders x and width
- bool touchDown(int x, int y) {
- *val = ofMap(x, this->x, this->getRight(), 0, 1, true);
- }
- // does the same as touchDown, so just call touch down.
- void touchMoved(int x, int y) {
- touchDown(x, y);
- }
- void touchUp(int x, int y) {
- }
- };
- // This is the root of the UI
- shared_ptr<UIElement> root;
- // menu show/hide button
- shared_ptr<Button> menuButton;
- // the menu - it's a container
- // for menu items.
- shared_ptr<Menu> menu;
- int PADDING = 10;
- glm::vec3 color;
- //--------------------------------------------------------------
- class ofApp : public ofBaseApp {
- void setup(){
- root = make_shared<UIElement>();
- // create a menu button that will toggle the menu's isShowing variable when pressed
- menuButton = make_shared<Button>("SHOW");
- // position it
- menuButton->x = menuButton->y = PADDING;
- // this is what happens when you press the menu button
- menuButton->action = []() {
- // toggle showing menu when menu button is pressed.
- menu->isShowing = !menu->isShowing;
- // change the text of the menu button depending
- // on whether the menu is showing or not.
- if(menu->isShowing) {
- menuButton->label = "HIDE";
- } else {
- menuButton->label = "SHOW";
- }
- };
- menu = make_shared<Menu>();
- // make some buttons for the menu
- auto someButton = make_shared<Button>("SOMETHING");
- auto someOtherButton = make_shared<Button>("OTHER THING");
- // a few sliders
- auto redSlider = make_shared<Slider>("Red", color.r);
- auto greenSlider = make_shared<Slider>("Green", color.g);
- auto blueSlider = make_shared<Slider>("Blue", color.b);
- // position everything
- someButton->x = someOtherButton->x = redSlider->x = greenSlider->x = blueSlider->x = PADDING;
- someButton->y = menuButton->getBottom() + PADDING;
- someOtherButton->y = someButton->getBottom() + PADDING;
- redSlider->y = someOtherButton->getBottom() + PADDING*6;
- greenSlider->y = redSlider->getBottom() + PADDING*6;
- blueSlider->y = greenSlider->getBottom() + PADDING*6;
- // add everything to the menu
- menu->addChild(someButton);
- menu->addChild(someOtherButton);
- menu->addChild(redSlider);
- menu->addChild(greenSlider);
- menu->addChild(blueSlider);
- // add the menu and the menu button to the root
- root->addChild(menu);
- root->addChild(menuButton);
- }
- //--------------------------------------------------------------
- void draw(){
- ofSetBackgroundColor(color.r * 255.f, color.g * 255.f, color.b * 255.f);
- root->propagateDraw();
- }
- //--------------------------------------------------------------
- void mousePressed(int x, int y, int button){
- root->propagateTouchDown(x, y);
- }
- //--------------------------------------------------------------
- void mouseDragged(int x, int y, int button){
- root->propagateTouchMoved(x, y);
- }
- //--------------------------------------------------------------
- void mouseReleased(int x, int y, int button){
- root->propagateTouchUp(x, y);
- }
- };
- //========================================================================
- int main( ){
- ofSetupOpenGL(1024,768,OF_WINDOW); // <-------- setup the GL context
- // this kicks off the running of my app
- // can be OF_WINDOW or OF_FULLSCREEN
- // pass in width and height too:
- ofRunApp(new ofApp());
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement