]> git.tdb.fi Git - libs/gl.git/blobdiff - source/bindable.h
Make Animation::Iterator assignable
[libs/gl.git] / source / bindable.h
index f534d7afd8e9788e412dd0d2ddd876eee0091c8e..b2634ea92bd4b1b43bb1f88b502af230f1e3c4bd 100644 (file)
@@ -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<typename T>
 class BindableWithDefault: protected Bindable<T>
 {
+       friend class Bindable<T>;
+
 protected:
        BindableWithDefault() { }
+       ~BindableWithDefault() { if(this==&default_object()) Bindable<T>::set_current(0); }
 
 public:
        static const T *current()
@@ -52,7 +56,8 @@ public:
 
        static void unbind()
        {
-               default_object().bind();
+               if(Bindable<T>::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<typename T>
        Bind(const T &o) { init(&o); }
 
+       template<typename T, typename S>
+       Bind(T *o, S s) { init(o, s); }
+
+       template<typename T, typename S>
+       Bind(const T *o, S s) { init(o, s); }
+
+       template<typename T, typename S>
+       Bind(const T &o, S s) { init(&o, s); }
+
 private:
        template<typename T>
        void init(const T *o)
        {
-               cleanup = (o ? &unbind<T> : 0);
+               cleanup = (o ? static_cast<CleanupFunc *>(&unbind<T>) : 0);
+               slot = 0;
                if(o)
                        o->bind();
                else
                        T::unbind();
        }
 
+       template<typename T, typename S>
+       void init(const T *o, S s)
+       {
+               cleanup = (o ? static_cast<CleanupFunc *>(&unbind_from<T, S>) : 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<typename T>
-       static void unbind()
+       static void unbind(int)
        { T::unbind(); }
+
+       template<typename T, typename S>
+       static void unbind_from(int s)
+       { T::unbind_from(static_cast<S>(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<typename T>
        BindRestore(const T &o) { init(&o); }
 
+       template<typename T, typename S>
+       BindRestore(T *o, S s) { init(o, s); }
+
+       template<typename T, typename S>
+       BindRestore(const T *o, S s) { init(o, s); }
+
+       template<typename T, typename S>
+       BindRestore(const T &o, S s) { init(&o, s); }
+
 private:
        template<typename T>
        void init(T *o)
        {
                old = T::current();
-               cleanup = (o!=old ? &restore<T> : 0);
+               slot = 0;
+               cleanup = (o!=old ? static_cast<CleanupFunc *>(&restore<T>) : 0);
                if(o)
                        o->bind();
                else if(old)
                        T::unbind();
        }
 
+       template<typename T, typename S>
+       void init(T *o, S s)
+       {
+               old = T::current(s);
+               slot = s;
+               cleanup = (o!=old ? static_cast<CleanupFunc *>(&restore_to<T, S>) : 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<typename T>
-       static void restore(const void *o)
+       static void restore(const void *o, int)
        {
                if(o)
                        reinterpret_cast<const T *>(o)->bind();
                else
                        T::unbind();
        }
+
+       template<typename T, typename S>
+       static void restore_to(const void *o, int si)
+       {
+               S s = static_cast<S>(si);
+               if(o)
+                       reinterpret_cast<const T *>(o)->bind_to(s);
+               else
+                       T::unbind_from(s);
+       }
 };
 
 } // namespace GL