// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_sg_back_area #define tools_sg_back_area #include "node" #include "atb_vertices" #include "rgba" #include "draw_style" #include "../mathf" #include "separator" #include "normal" namespace tools { namespace sg { class back_area : public node { TOOLS_NODE(back_area,tools::sg::back_area,node) public: static unsigned int corner_top_right() {return 1<<0;} static unsigned int corner_top_left() {return 1<<1;} static unsigned int corner_bottom_right() {return 1<<2;} static unsigned int corner_bottom_left() {return 1<<3;} static unsigned int corner_all() { return corner_top_right()|corner_top_left()|corner_bottom_right()|corner_bottom_left(); } public: sf width; sf height; sf_vec color; sf gradient; sf_vec color_top; sf border_visible; sf_vec border_color; sf border_line_width; sf shadow; //in percent of width. sf corner_radius; //percent of height. sf corner_steps; sf corner_mask; public: virtual const desc_fields& node_desc_fields() const { TOOLS_FIELD_DESC_NODE_CLASS(tools::sg::back_area) static const desc_fields s_v(parent::node_desc_fields(),12, //WARNING : take care of count. TOOLS_ARG_FIELD_DESC(width), TOOLS_ARG_FIELD_DESC(height), TOOLS_ARG_FIELD_DESC(color), TOOLS_ARG_FIELD_DESC(gradient), TOOLS_ARG_FIELD_DESC(color_top), TOOLS_ARG_FIELD_DESC(border_visible), TOOLS_ARG_FIELD_DESC(border_color), TOOLS_ARG_FIELD_DESC(border_line_width), TOOLS_ARG_FIELD_DESC(shadow), TOOLS_ARG_FIELD_DESC(corner_radius), TOOLS_ARG_FIELD_DESC(corner_steps), TOOLS_ARG_FIELD_DESC(corner_mask) ); return s_v; } private: void add_fields(){ add_field(&width); add_field(&height); add_field(&color); add_field(&gradient); add_field(&color_top); add_field(&border_visible); add_field(&border_color); add_field(&border_line_width); add_field(&shadow); add_field(&corner_radius); add_field(&corner_steps); add_field(&corner_mask); } public: virtual void render(render_action& a_action) { if(touched()) { update_sg(); reset_touched(); } m_back_sep.render(a_action); } virtual void search(search_action& a_action) { if(touched()) { update_sg(); reset_touched(); } parent::search(a_action); if(a_action.done()) return; m_back_sep.search(a_action); if(a_action.done()) return; } virtual void pick(pick_action& a_action) { if(touched()) { update_sg(); reset_touched(); } m_back_sep.pick(a_action); } public: back_area() :parent() ,width(1) ,height(1) ,color(colorf_white()) ,gradient(false) ,color_top(colorf_white()) ,border_visible(true) ,border_color(colorf_black()) ,border_line_width(1) ,shadow(0) ,corner_radius(0) //in percent of the height. ,corner_steps(12) ,corner_mask(corner_all()) { add_fields(); } virtual ~back_area(){} public: back_area(const back_area& a_from) :parent(a_from) ,width(a_from.width) ,height(a_from.height) ,color(a_from.color) ,gradient(a_from.gradient) ,color_top(a_from.color_top) ,border_visible(a_from.border_visible) ,border_color(a_from.border_color) ,border_line_width(a_from.border_line_width) ,shadow(a_from.shadow) ,corner_radius(a_from.corner_radius) ,corner_steps(a_from.corner_steps) ,corner_mask(a_from.corner_mask) { add_fields(); } back_area& operator=(const back_area& a_from){ parent::operator=(a_from); width = a_from.width; height = a_from.height; color = a_from.color; gradient = a_from.gradient; color_top = a_from.color_top; border_visible = a_from.border_visible; border_color = a_from.border_color; border_line_width = a_from.border_line_width; shadow = a_from.shadow; corner_radius = a_from.corner_radius; corner_steps = a_from.corner_steps; corner_mask = a_from.corner_mask; return *this; } protected: void update_sg() { m_back_sep.clear(); if(width.value()<=0) return; if(height.value()<=0) return; float xb = -width*0.5f; float xe = width*0.5f; float yb = -height*0.5f; float zshadow = -0.005f; //ok with gopaw and ROOT_default. float zback = 0; float zborder = 0.01f; if(shadow.value()) { float zz = zback+zshadow; float ye = height*0.5f; sg::rgba* mat = new sg::rgba(); mat->color = colorf_black(); m_back_sep.add(mat); normal* nm = new normal; //nm->vec.value(); //default is z. ok. m_back_sep.add(nm); vertices* vtxs = new vertices; vtxs->mode = gl::triangle_fan(); m_back_sep.add(vtxs); float dx = width*shadow; float dy = -dx; vtxs->add(xb+dx,yb+dy,zz); vtxs->add(xe+dx,yb+dy,zz); vtxs->add(xe+dx,ye+dy,zz); vtxs->add(xb+dx,ye+dy,zz); } {//background : normal* nm = new normal; //nm->vec.value(); //default is z. ok. m_back_sep.add(nm); if(gradient.value()) { //color gradient from (bottom,color) to (top,color_top) atb_vertices* vtxs = new atb_vertices; vtxs->mode = gl::triangle_strip(); m_back_sep.add(vtxs); float zz = zback; unsigned int ncol = 50; float dy = height/ncol; float ye = yb+dy; colorf col_beg = color.value(); colorf col_end = color_top.value(); float dr = (col_end.r()-col_beg.r())/ncol; float dg = (col_end.g()-col_beg.g())/ncol; float db = (col_end.b()-col_beg.b())/ncol; float da = (col_end.a()-col_beg.a())/ncol; vec4f dcol(dr,dg,db,da); colorf col = col_beg; vtxs->add(xb,yb,zz); vtxs->add_color(col); vtxs->add(xe,yb,zz); vtxs->add_color(col); for(unsigned int index=0;indexadd(xb,ye,zz); vtxs->add(xe,ye,zz); vtxs->add_color(col); vtxs->add_color(col); ye += dy; col += dcol; } } else { float zz = zback; float ye = height*0.5f; sg::rgba* mat = new sg::rgba(); mat->color = color; m_back_sep.add(mat); vertices* vtxs = new vertices; vtxs->mode = gl::triangle_fan(); m_back_sep.add(vtxs); float r = height*corner_radius; if((r>(0.5f*height.value()))||(r>(0.5f*width.value()))) r = 0; if((r>0) && corner_steps.value()) { float dangle = fhalf_pi()/float(corner_steps); unsigned int nslice = corner_steps; vtxs->add(0,0,zz); vtxs->add(xe,yb+r,zz); vtxs->add(xe,ye-r,zz); // top-right : float angle = dangle; if(corner_mask.value() & corner_top_right()) { float xc = xe-r; float yc = ye-r; for(unsigned int i=0;iadd(r*fcos(angle)+xc,r*fsin(angle)+yc,zz); } } else { angle += fhalf_pi(); vtxs->add(xe,ye,zz); vtxs->add(xe-r,ye,zz); } vtxs->add(xb+r,ye,zz); // top-left : if(corner_mask.value() & corner_top_left()) { float xc = xb+r; float yc = ye-r; for(unsigned int i=0;iadd(r*fcos(angle)+xc,r*fsin(angle)+yc,zz); } } else { angle += fhalf_pi(); vtxs->add(xb,ye,zz); vtxs->add(xb,ye-r,zz); } vtxs->add(xb,yb+r,zz); // bottom-left : if(corner_mask.value() & corner_bottom_left()) { float xc = xb+r; float yc = yb+r; for(unsigned int i=0;iadd(r*fcos(angle)+xc,r*fsin(angle)+yc,zz); } } else { angle += fhalf_pi(); vtxs->add(xb,yb,zz); vtxs->add(xb+r,yb,zz); } vtxs->add(xe-r,yb,zz); // bottom-right : if(corner_mask.value() & corner_bottom_right()) { float xc = xe-r; float yc = yb+r; for(unsigned int i=0;iadd(r*fcos(angle)+xc,r*fsin(angle)+yc,zz); } } else { angle += fhalf_pi(); vtxs->add(xe,yb,zz); vtxs->add(xe,yb+r,zz); } } else { vtxs->add(xb,yb,zz); vtxs->add(xe,yb,zz); vtxs->add(xe,ye,zz); vtxs->add(xb,ye,zz); } }} if(border_visible.value()){ float zz = zborder; float ye = height*0.5f; sg::rgba* mat = new sg::rgba(); mat->color = border_color; m_back_sep.add(mat); draw_style* ds = new draw_style; ds->style = draw_lines; ds->line_width = border_line_width; m_back_sep.add(ds); vertices* vtxs = new vertices; vtxs->mode = gl::line_strip(); m_back_sep.add(vtxs); float r = height*corner_radius; if((r>(0.5f*height.value()))||(r>(0.5f*width.value()))) r = 0; if((r>0) && corner_steps.value()) { float dangle = fhalf_pi()/float(corner_steps); unsigned int nslice = corner_steps; vtxs->add(xe,yb+r,zz); vtxs->add(xe,ye-r,zz); // top-right : float angle = dangle; if(corner_mask.value() & corner_top_right()) { float xc = xe-r; float yc = ye-r; for(unsigned int i=0;iadd(r*fcos(angle)+xc,r*fsin(angle)+yc,zz); } } else { angle += fhalf_pi(); vtxs->add(xe,ye,zz); vtxs->add(xe-r,ye,zz); } vtxs->add(xb+r,ye,zz); // top-left : if(corner_mask.value() & corner_top_left()) { float xc = xb+r; float yc = ye-r; for(unsigned int i=0;iadd(r*fcos(angle)+xc,r*fsin(angle)+yc,zz); } } else { angle += fhalf_pi(); vtxs->add(xb,ye,zz); vtxs->add(xb,ye-r,zz); } vtxs->add(xb,yb+r,zz); // bottom-left : if(corner_mask.value() & corner_bottom_left()) { float xc = xb+r; float yc = yb+r; for(unsigned int i=0;iadd(r*fcos(angle)+xc,r*fsin(angle)+yc,zz); } } else { angle += fhalf_pi(); vtxs->add(xb,yb,zz); vtxs->add(xb+r,yb,zz); } vtxs->add(xe-r,yb,zz); // bottom-right : if(corner_mask.value() & corner_bottom_right()) { float xc = xe-r; float yc = yb+r; for(unsigned int i=0;iadd(r*fcos(angle)+xc,r*fsin(angle)+yc,zz); } } else { angle += fhalf_pi(); vtxs->add(xe,yb,zz); vtxs->add(xe,yb+r,zz); } } else { vtxs->add(xb,yb,zz); vtxs->add(xe,yb,zz); vtxs->add(xe,ye,zz); vtxs->add(xb,ye,zz); vtxs->add(xb,yb,zz); } } } protected: separator m_back_sep; }; }} #endif