Created
April 2, 2018 08:08
-
-
Save SeijiEmery/0225e21af95f0c3fa09f4d6262ec088f to your computer and use it in GitHub Desktop.
Game engine window management snippet
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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