X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fbindable.h;h=b2634ea92bd4b1b43bb1f88b502af230f1e3c4bd;hp=f534d7afd8e9788e412dd0d2ddd876eee0091c8e;hb=4b4d2a48048268d2ad48bafbce8647af8088573f;hpb=f33a98b1a044c8ac7b12778cbca6c4a124875e4a diff --git a/source/bindable.h b/source/bindable.h index f534d7af..b2634ea9 100644 --- a/source/bindable.h +++ b/source/bindable.h @@ -15,6 +15,7 @@ protected: static const T *cur_obj; Bindable() { } + ~Bindable() { if(cur_obj==this) T::unbind(); } static bool set_current(const T *obj) { @@ -39,8 +40,11 @@ A helper class for Bindables that revert to a default object on unbind. template class BindableWithDefault: protected Bindable { + friend class Bindable; + protected: BindableWithDefault() { } + ~BindableWithDefault() { if(this==&default_object()) Bindable::set_current(0); } public: static const T *current() @@ -52,7 +56,8 @@ public: static void unbind() { - default_object().bind(); + if(Bindable::cur_obj) + default_object().bind(); } static const T &default_object() @@ -71,8 +76,9 @@ does nothing upon destruction. class Bind { private: - typedef void CleanupFunc(); + typedef void CleanupFunc(int); + int slot; CleanupFunc *cleanup; public: @@ -85,25 +91,50 @@ public: template Bind(const T &o) { init(&o); } + template + Bind(T *o, S s) { init(o, s); } + + template + Bind(const T *o, S s) { init(o, s); } + + template + Bind(const T &o, S s) { init(&o, s); } + private: template void init(const T *o) { - cleanup = (o ? &unbind : 0); + cleanup = (o ? static_cast(&unbind) : 0); + slot = 0; if(o) o->bind(); else T::unbind(); } + template + void init(const T *o, S s) + { + cleanup = (o ? static_cast(&unbind_from) : 0); + slot = s; + if(o) + o->bind_to(s); + else + T::unbind_from(s); + } + public: ~Bind() - { if(cleanup) cleanup(); } + { if(cleanup) cleanup(slot); } private: template - static void unbind() + static void unbind(int) { T::unbind(); } + + template + static void unbind_from(int s) + { T::unbind_from(static_cast(s)); } }; @@ -113,9 +144,10 @@ Similar to Bind, but restores previous binding upon destruction. class BindRestore { private: - typedef void CleanupFunc(const void *); + typedef void CleanupFunc(const void *, int); const void *old; + int slot; CleanupFunc *cleanup; public: @@ -128,31 +160,63 @@ public: template BindRestore(const T &o) { init(&o); } + template + BindRestore(T *o, S s) { init(o, s); } + + template + BindRestore(const T *o, S s) { init(o, s); } + + template + BindRestore(const T &o, S s) { init(&o, s); } + private: template void init(T *o) { old = T::current(); - cleanup = (o!=old ? &restore : 0); + slot = 0; + cleanup = (o!=old ? static_cast(&restore) : 0); if(o) o->bind(); else if(old) T::unbind(); } + template + void init(T *o, S s) + { + old = T::current(s); + slot = s; + cleanup = (o!=old ? static_cast(&restore_to) : 0); + if(o) + o->bind_to(s); + else if(old) + T::unbind_from(s); + } + public: ~BindRestore() - { if(cleanup) cleanup(old); } + { if(cleanup) cleanup(old, slot); } private: template - static void restore(const void *o) + static void restore(const void *o, int) { if(o) reinterpret_cast(o)->bind(); else T::unbind(); } + + template + static void restore_to(const void *o, int si) + { + S s = static_cast(si); + if(o) + reinterpret_cast(o)->bind_to(s); + else + T::unbind_from(s); + } }; } // namespace GL