-/* $Id$
-
-This file is part of libmspgl
-Copyright © 2010 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
#ifndef MSP_GL_BINDABLE_H_
#define MSP_GL_BINDABLE_H_
namespace Msp {
namespace GL {
+/**
+A helper class for single-point binding. Provides tracking of the currently
+bound object.
+*/
template<typename T>
class Bindable
{
if(obj==cur_obj)
return false;
- cur_obj=obj;
+ cur_obj = obj;
return true;
}
public:
- const T *current() const { return cur_obj; }
+ static const T *current() { return cur_obj; }
};
template<typename T>
const T *Bindable<T>::cur_obj;
+/**
+A helper class for Bindables that revert to a default object on unbind.
+*/
+template<typename T>
+class BindableWithDefault: protected Bindable<T>
+{
+protected:
+ BindableWithDefault() { }
+
+public:
+ static const T *current()
+ {
+ if(!Bindable<T>::cur_obj)
+ Bindable<T>::cur_obj = &default_object();
+ return Bindable<T>::cur_obj;
+ }
+
+ static void unbind()
+ {
+ default_object().bind();
+ }
+
+ static const T &default_object()
+ {
+ static T obj;
+ return obj;
+ }
+};
+
+
/**
RAII class for binding things. Binds the thing upon construction and unbinds
it upon destruction. If a null pointer is given, unbinds upon construction and
-does nothing upon destruction.
+does nothing upon destruction. Optionally can restore the previous binding.
*/
class Bind
{
};
template<typename T>
- struct Binder: Base
+ struct Binder1: Base
{
- const T &obj;
+ const T *obj;
+
+ Binder1(const T *o):
+ obj(o)
+ {
+ if(obj)
+ obj->bind();
+ else
+ T::unbind();
+ }
+
+ ~Binder1()
+ {
+ if(obj)
+ obj->unbind();
+ }
+ };
- Binder(const T &o): obj(o) { obj.bind(); }
- ~Binder() { obj.unbind(); }
+ template<typename T, typename U>
+ struct Binder2: Base
+ {
+ const T *obj;
+ const U *old;
+
+ Binder2(const T *o, const U *l):
+ obj(o),
+ old(l)
+ {
+ if(obj)
+ obj->bind();
+ else
+ T::unbind();
+ }
+
+ ~Binder2()
+ {
+ if(old)
+ old->bind();
+ else if(obj)
+ obj->unbind();
+ }
};
Base *binder;
public:
template<typename T>
- Bind(const T &o): binder(new Binder<T>(o)) { }
+ Bind(const T &o, bool r = false):
+ binder(r ? create(&o, T::current()) : create(&o))
+ { }
+
+ template<typename T>
+ Bind(const T *o, bool r = false):
+ binder(r ? create(o, T::current()) : create(o))
+ { }
template<typename T>
- Bind(const T *o): binder(o ? new Binder<T>(*o) : 0) { if(!o) T::unbind(); }
+ Bind(T *o, bool r = false):
+ binder(r ? create(o, T::current()) : create(o))
+ { }
private:
Bind(const Bind &);
public:
~Bind() { delete binder; }
+
+private:
+ template<typename T>
+ Base *create(const T *o)
+ { return new Binder1<T>(o); }
+
+ template<typename T, typename U>
+ Base *create(const T *o, const U *l)
+ { return new Binder2<T, U>(o, l); }
};
} // namespace GL