Skip to content

Instantly share code, notes, and snippets.

@SeijiEmery
Created April 2, 2018 08:08
Show Gist options
  • Save SeijiEmery/0225e21af95f0c3fa09f4d6262ec088f to your computer and use it in GitHub Desktop.
Save SeijiEmery/0225e21af95f0c3fa09f4d6262ec088f to your computer and use it in GitHub Desktop.
Game engine window management snippet
//
// Property declaration macros: makes semantics clearer (and saves typing)
//
#define DECL_PROP_GET(name,type) type name () const
#define DECL_PROP_SET(name,type) This& name (type)
#define DECL_PROP_GET_VIRTUAL(name,type) virtual DECL_PROP_GET(name,type) = 0;
#define DECL_PROP_SET_VIRTUAL(name,type) virtual DECL_PROP_SET(name,type) = 0;
#define DECL_PROP_VIRTUAL(name,type) \
DECL_PROP_GET_VIRTUAL(name,type) \
DECL_PROP_SET_VIRTUAL(name,type)
#define DECL_VPROP(name,type) DECL_PROP_VIRTUAL(name,type)
// Range abstraction used to eg. iterate over things
template <typename T>
class IRange {
public:
virtual operator bool () = 0;
virtual T operator* () = 0;
virtual IRange<T>& operator++ () = 0;
};
//
// Predeclarations + class hierarchy
//
class IObject;
class ISurface;
class IRenderSurface;
class IRenderSurface2d;
class IRenderSurface3d;
class IWindow;
class IDisplay;
class IWindowManager;
class IWidget;
class IGuiNode;
class ITextbox;
class IObjectView;
class IToolbox;
class IGraph2d;
class IGraph3d;
// Base object type
class IObject {
public:
typedef IObject This;
DECL_PROP_GET_VIRTUAL(id, uuid) // unique runtime id; used for serialization + lookups
DECL_PROP_VIRTUAL(name, const std::string&) // optional name assigned for debugging purposes
DECL_PROP_GET_VIRTUAL(tags, TagList&) // optional tag list / management
DECL_PROP_GET_VIRTUAL(type, const RTTI_ClassInfo&) // runtime type information for this specific class
virtual ~IObject () {}
// Cast this to a child type using dyanmic_cast.
// Casting to an incorrect type will crash / fail horribly, so guarded with enforce.
template <typename T>
T& as () {
ENFORCE(RuntimeTypecastException, is<T>(),
"Failed dynamic_cast: " << type() << " to " << rtti_typeof<T>());
return dynamic_cast<T&>(*this);
}
// Return true if this type derives T. checks using .type()
template <typename T>
bool is () { return type().inheiritedFrom<T>(); }
};
// Base "surface" class (ie. 2d rect w/ stuff in / drawn on it)
// Surfaces have a hierarchy, with:
// - one single parent object (except root objects, ie IWindowManager)
// - multiple child surfaces, with restrictions
class ISurface : public IObject {
public:
typedef ISurface This;
DECL_PROP_VIRTUAL(parent, ISurface&) // get / set parent surface; semantics vary depending on derived type...
DECL_PROP_GET_VIRTUAL(children, IRange<ISurface&>) // get range of child surface objects
DECL_PROP_GET_VIRTUAL(events, IRange<IEvent&>) // get range of events attached to / affecting this object
DECL_PROP_VIRTUAL(pos, vec2d) // object position, in pixels
DECL_PROP_VIRTUAL(size, vec2d) // object size, in pixels
DECL_PROP_VIRTUAL(pixelScaleFactor, double) // pixel scaling (generally only used for real "platform" windows)
DECL_PROP_VIRTUAL(pixelScaleMode, PixelScaleMode)
DECL_PROP_VIRTUAL(draggable, bool) // lets surface be moved by dragging within content rect
DECL_PROP_VIRTUAL(scrollbar, bool) // lets surface be scrolled by dragging scrollbar or scrolling within content rect
DECL_PROP_VIRTUAL(scrollPos, vec2d) // scroll position, normalized
DECL_PROP_VIRTUAL(contentScalable, bool) // lets surface content be transformed
DECL_PROP_GET_VIRTUAL(contentPixelSize, vec2d) // size of min bounding box of child content
DECL_PROP_VIRTUAL(contentSize, vec2d) // size of content view
DECL_PROP_VIRTUAL(contentZoom, vec2d) // zoom scale (100% = 1.0) of content
DECL_PROP_VIRTUAL(contentPos, vec2d) // content position offset. related to / interdependent on scroll position, but uses different units (sort of...?)
DECL_PROP_VIRTUAL(pausable, bool) // lets surface be paused / unpaused by setting .active
DECL_PROP_VIRTUAL(active, bool) // if disabled, surface is frozen: is not simulated + does not respond to events
DECL_PROP_VIRTUAL(visible, bool) // if disabled, surface is not rendered. may be disabled under several conditions, eg. minimized.
};
// Abstracts a monitor / virtual display into which a window can be placed
// Implements functionality for window layout, drag and drop, etc;
// uses .parent() and .child() to manage window positioning + relationships.
class IDisplay : public ISurface {
public:
typedef IDisplay This;
DECL_PROP_GET_VIRTUAL(windowedMaxResolution, vec2d) // max size of a window / widget
DECL_PROP_GET_VIRTUAL(fullscreenResolutions, IRange<vec2u>)
};
// Manages window layout, lifetimes, etc.
// - all owned windows must be children of this object
// - the windowManager owns displays, which represent eg. monitors
// - each display can be mapped / positioned in a virtual "display space"
// - each window must be owned by a display, or by the window manager itself
// (which is considered a display, albeit a non-visible, inactive one)
// - as such, one way to disable / deactivate a window is to set its parent to
// its window manager (effectively sets as an "empty" display)
// - to reactivate, set its parent back to an active display
// - generally has automatic behavior to eg. reparent windows when / if displays are removed
class IWindowManager : public IDisplay {
public:
typedef IWindowManager This;
DECL_PROP_GET_VIRTUAL(windows, IRange<IWindow&>) // get a list of all owned windows
DECL_PROP_GET_VIRTUAL(displays, IRange<IDisplay&>) // get a list of all active displays
DECL_PROP_GET_VIRTUAL(devices, IRange<IDevice&>) // get a list of all (input) devices
};
// Decorated "window" object with special functionality
// - can represent a "real" (ie. "platform") window under a real window manager, or a
// "virtual" (ie. gui) window under a virtual window manager higher up on the stack
//
// Should have behavior for:
// - hiding (minimizing), resizing / maximizing, entering fullscreen mode (uses
// up all available space of parent display as a borderless window), tiling
// (TBD, but should work like blender / unity), and probably for tabbing + switching
// between windows
//
class IWindow : public ISurface {
public:
typedef IWindow This;
DECL_PROP_GET(windowManager, IWindowManager&)
// DECL_PROP_VIRTUAL(display, IDisplay&) // parent
DECL_PROP_VIRTUAL(decorated, bool) // enable / disable title bar, scroll bar(s), etc
DECL_PROP_VIRTUAL(showTitle, bool) // enable / disable title text
DECL_PROP_VIRTUAL(titleText, const std::string&) // set title text
DECL_PROP_VIRTUAL(titleDraggable, bool) // enable / disable window repositioning by dragging titlebar
DECL_PROP_VIRTUAL(closable, bool) // enable / disable following behavior via gui controls
DECL_PROP_VIRTUAL(minimizable, bool) // enable / disable following behavior via gui controls
DECL_PROP_VIRTUAL(maximizable, bool) // enable / disable following behavior via gui controls
DECL_PROP_VIRTUAL(fullscreenable, bool) // enable / disable following behavior via gui controls
DECL_PROP_VIRTUAL(closed, bool)
DECL_PROP_VIRTUAL(minimized, bool)
DECL_PROP_VIRTUAL(maximized, bool)
DECL_PROP_VIRTUAL(fullscreen, bool)
};
// Typical setup:
// IWindowManager platform_window_manager <= platform::glfw::WindowManager
// IDisplay mainMonitor <= platform::glfw::Monitor
// IWindow mainWindow <= platform::glfw::Window
// IRenderSurface3d gl_surface <= graphicsbackend::opengl41::RenderSurface3d
// IRenderSurface2d canvas <= graphicsbackend::opengl41::RenderSurface2d
// IWindowManager windowMgr <= gui::WindowManager
// IWindow virtualWindow1 <= gui::Window
// ITextbox fpsText <= gui::Textbox
// IGraph2d perfGraph <= gui::Graph2d
// IObjectView view <= gui::ObjectView
// .model = platform_window_manager (recursive inspection...)
// IWindow virtualWindow2 <= gui::Window
// IWindow virtualWindow3 <= gui::Window
// IRenderSurface2d canvas <= gui::Canvas2d
// IWidget controllerGizmo <= gui::gizmos::transform3d
// IRenderSurface3d view <= gui::Canvas3d
// IScene3d scene <= scene3d::Scene
// IDisplay otherMonitor <= platform::glfw::Monitor
// IWindow secondWindow <= platform::glfw::Window
// (stuff being rendered on second monitor...)
// .active = true
// .visible = true
//
// IWindow offscreenWindow <= platform::glfw::Window
// (parent is the window manager itself, so nothing rendered...)
// .active = false
// .visible = false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment