diff --git a/inc/hgl/type/Gradient.h b/inc/hgl/type/Gradient.h new file mode 100644 index 0000000..00cf6f2 --- /dev/null +++ b/inc/hgl/type/Gradient.h @@ -0,0 +1,144 @@ +#pragma once + +#include +#include +#include + +namespace hgl +{ + template struct GradientStop + { + P pos; + T data; + }; + + /** + * ½¥±äÀà + */ + template class Gradient + { + using GS=GradientStop; + + List stop_list; + + bool dirty; + + protected: + + void Sort() + { + if(!dirty||stop_list.GetCount()<2) + return; + + Comparator comp; + + hgl::Sort(stop_list,&comp); + + dirty=false; + } + + public: + + Gradient() + { + dirty=true; + } + + void Add(const P &pos,const T &data) + { + GS gs; + + gs.pos=pos; + gs.data=data; + + stop_list.Add(gs); + dirty=true; + } + + void Clear() + { + stop_list.Clear(); + dirty=true; + } + + const bool GetLowest(P &pos)const + { + GS gs; + + if(stop_list.First(gs)) + { + pos=gs.pos; + return(true); + } + + return false; + } + + const bool GetHighest(P &pos)const + { + GS gs; + + if(stop_list.Last(gs)) + { + pos=gs.pos; + return(true); + } + + return false; + } + + virtual void Get(T &reuslt,const T &start,const T &end,const float &pos) + { + result=start+(end-start)*pos; + } + + const void Get(T &result,const P &pos) + { + const uint count=stop_list.GetCount(); + + if(count<=0) + return; + + Sort(); + + GS *cp=stop_list.GetData(); + GS *pp; + + if(count<2||pos<=cp->pos) + { + result=cp->data; + return; + } + + if(pos>=cp[count-1].pos) + { + result=cp[count-1].data; + return; + } + + pp=cp; + ++cp; + for(uint i=1;ipos) + { + Get(result,pp->data,cp->data,float(pos-pp->pos)/float(cp->pos-pp->pos)); + return; + } + + ++pp; + ++cp; + } + } + };//class Gradient + + #define HGL_GRADIENT_DEFINE(name,P,T) using name=Gradient; \ + using name##Stop=GradientStop; \ + \ + int Comparator::compare(const name##Stop &a,const name##Stop &b)const \ + { \ + return a.pos-b.pos; \ + } \ + \ + template<> void name::Get(T &result,const T &start,const T &end,const float &pos) +}//namespace hgl \ No newline at end of file