v01
This commit is contained in:
660
thirdparty/Pangolin/src/display/display.cpp
vendored
Normal file
660
thirdparty/Pangolin/src/display/display.cpp
vendored
Normal file
@@ -0,0 +1,660 @@
|
||||
/* This file is part of the Pangolin Project.
|
||||
* http://github.com/stevenlovegrove/Pangolin
|
||||
*
|
||||
* Copyright (c) 2011 Steven Lovegrove, Richard Newcombe
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <pangolin/platform.h>
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
#include <pangolin/python/pyinterpreter.h>
|
||||
#include <pangolin/console/ConsoleView.h>
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <pangolin/factory/factory_registry.h>
|
||||
#include <pangolin/window_frameworks.h>
|
||||
#include <pangolin/gl/glinclude.h>
|
||||
#include <pangolin/gl/gldraw.h>
|
||||
#include <pangolin/display/display.h>
|
||||
#include <pangolin/display/display_internal.h>
|
||||
#include <pangolin/handler/handler.h>
|
||||
#include <pangolin/utils/simple_math.h>
|
||||
#include <pangolin/utils/timer.h>
|
||||
#include <pangolin/utils/type_convert.h>
|
||||
#include <pangolin/image/image_io.h>
|
||||
|
||||
#ifdef BUILD_PANGOLIN_VARS
|
||||
#include <pangolin/var/var.h>
|
||||
#endif
|
||||
|
||||
namespace pangolin
|
||||
{
|
||||
|
||||
#ifdef BUILD_PANGOLIN_VIDEO
|
||||
// Forward declaration.
|
||||
void SaveFramebuffer(VideoOutput& video, const Viewport& v);
|
||||
#endif // BUILD_PANGOLIN_VIDEO
|
||||
|
||||
const char* PARAM_DISPLAYNAME = "DISPLAYNAME";
|
||||
const char* PARAM_DOUBLEBUFFER = "DOUBLEBUFFER";
|
||||
const char* PARAM_SAMPLE_BUFFERS = "SAMPLE_BUFFERS";
|
||||
const char* PARAM_SAMPLES = "SAMPLES";
|
||||
const char* PARAM_HIGHRES = "HIGHRES";
|
||||
|
||||
|
||||
typedef std::map<std::string,std::shared_ptr<PangolinGl> > ContextMap;
|
||||
|
||||
// Map of active contexts
|
||||
ContextMap contexts;
|
||||
std::recursive_mutex contexts_mutex;
|
||||
bool one_time_window_frameworks_init = false;
|
||||
|
||||
// Context active for current thread
|
||||
__thread PangolinGl* context = 0;
|
||||
|
||||
PangolinGl::PangolinGl()
|
||||
: user_app(0), is_high_res(false), quit(false), mouse_state(0),activeDisplay(0)
|
||||
#ifdef BUILD_PANGOLIN_VIDEO
|
||||
, record_view(0)
|
||||
#endif
|
||||
#ifdef HAVE_PYTHON
|
||||
, console_view(0)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
PangolinGl::~PangolinGl()
|
||||
{
|
||||
// Free displays owned by named_managed_views
|
||||
for(ViewMap::iterator iv = named_managed_views.begin(); iv != named_managed_views.end(); ++iv) {
|
||||
delete iv->second;
|
||||
}
|
||||
named_managed_views.clear();
|
||||
}
|
||||
|
||||
PangolinGl* GetCurrentContext()
|
||||
{
|
||||
return context;
|
||||
}
|
||||
|
||||
PangolinGl *FindContext(const std::string& name)
|
||||
{
|
||||
contexts_mutex.lock();
|
||||
ContextMap::iterator ic = contexts.find(name);
|
||||
PangolinGl* context = (ic == contexts.end()) ? 0 : ic->second.get();
|
||||
contexts_mutex.unlock();
|
||||
return context;
|
||||
}
|
||||
|
||||
WindowInterface& CreateWindowAndBind(std::string window_title, int w, int h, const Params& params)
|
||||
{
|
||||
std::unique_lock<std::recursive_mutex> l(contexts_mutex);
|
||||
|
||||
if(!one_time_window_frameworks_init) {
|
||||
one_time_window_frameworks_init = LoadBuiltInWindowFrameworks();
|
||||
}
|
||||
|
||||
pangolin::Uri win_uri;
|
||||
|
||||
if(const char* extra_params = std::getenv("PANGOLIN_WINDOW_URI"))
|
||||
{
|
||||
// Take any defaults from the environment
|
||||
win_uri = pangolin::ParseUri(extra_params);
|
||||
}else{
|
||||
// Otherwise revert to 'default' scheme.
|
||||
win_uri.scheme = "default";
|
||||
}
|
||||
|
||||
// Allow params to override
|
||||
win_uri.scheme = params.Get("scheme", win_uri.scheme);
|
||||
|
||||
// Override with anything the program specified
|
||||
win_uri.params.insert(std::end(win_uri.params), std::begin(params.params), std::end(params.params));
|
||||
win_uri.Set("w", w);
|
||||
win_uri.Set("h", h);
|
||||
win_uri.Set("window_title", window_title);
|
||||
|
||||
std::unique_ptr<WindowInterface> window = FactoryRegistry<WindowInterface>::I().Open(win_uri);
|
||||
|
||||
// We're expecting not only a WindowInterface, but a PangolinGl.
|
||||
if(!window || !dynamic_cast<PangolinGl*>(window.get())) {
|
||||
throw WindowExceptionNoKnownHandler(win_uri.scheme);
|
||||
}
|
||||
|
||||
std::shared_ptr<PangolinGl> context(dynamic_cast<PangolinGl*>(window.release()));
|
||||
RegisterNewContext(window_title, context );
|
||||
// is_high_res will alter default font size and a few other gui elements.
|
||||
context->is_high_res = win_uri.Get(PARAM_HIGHRES,false);
|
||||
context->MakeCurrent();
|
||||
context->ProcessEvents();
|
||||
glewInit();
|
||||
|
||||
return *context;
|
||||
}
|
||||
|
||||
// Assumption: unique lock is held on contexts_mutex for multi-threaded operation
|
||||
void RegisterNewContext(const std::string& name, std::shared_ptr<PangolinGl> newcontext)
|
||||
{
|
||||
// Set defaults
|
||||
newcontext->base.left = 0.0;
|
||||
newcontext->base.bottom = 0.0;
|
||||
newcontext->base.top = 1.0;
|
||||
newcontext->base.right = 1.0;
|
||||
newcontext->base.aspect = 0;
|
||||
newcontext->base.handler = &StaticHandler;
|
||||
newcontext->is_fullscreen = false;
|
||||
|
||||
// Create and add
|
||||
if( contexts.find(name) != contexts.end() ) {
|
||||
throw std::runtime_error("Context already exists.");
|
||||
}
|
||||
contexts[name] = newcontext;
|
||||
|
||||
// Process the following as if this context is now current.
|
||||
PangolinGl *oldContext = context;
|
||||
context = newcontext.get();
|
||||
process::Resize(
|
||||
newcontext->windowed_size[0],
|
||||
newcontext->windowed_size[1]
|
||||
);
|
||||
|
||||
// Default key bindings can be overridden
|
||||
RegisterKeyPressCallback(PANGO_KEY_ESCAPE, Quit );
|
||||
RegisterKeyPressCallback('\t', ToggleFullscreen );
|
||||
RegisterKeyPressCallback('`', ToggleConsole );
|
||||
|
||||
context = oldContext;
|
||||
}
|
||||
|
||||
WindowInterface* GetBoundWindow()
|
||||
{
|
||||
return context;
|
||||
}
|
||||
|
||||
void DestroyWindow(const std::string& name)
|
||||
{
|
||||
contexts_mutex.lock();
|
||||
ContextMap::iterator ic = contexts.find(name);
|
||||
PangolinGl *context_to_destroy = (ic == contexts.end()) ? 0 : ic->second.get();
|
||||
if (context_to_destroy == context) {
|
||||
context = nullptr;
|
||||
}
|
||||
size_t erased = contexts.erase(name);
|
||||
if(erased == 0) {
|
||||
pango_print_warn("Context '%s' doesn't exist for deletion.\n", name.c_str());
|
||||
}
|
||||
contexts_mutex.unlock();
|
||||
}
|
||||
|
||||
WindowInterface& BindToContext(std::string name)
|
||||
{
|
||||
std::unique_lock<std::recursive_mutex> l(contexts_mutex);
|
||||
|
||||
// N.B. context is modified prior to invoking MakeCurrent so that
|
||||
// state management callbacks (such as Resize()) can be correctly
|
||||
// processed.
|
||||
PangolinGl *context_to_bind = FindContext(name);
|
||||
if( !context_to_bind )
|
||||
{
|
||||
std::shared_ptr<PangolinGl> newcontext(new PangolinGl());
|
||||
RegisterNewContext(name, newcontext);
|
||||
return *(newcontext.get());
|
||||
}else{
|
||||
context_to_bind->MakeCurrent();
|
||||
return *context_to_bind;
|
||||
}
|
||||
}
|
||||
|
||||
void Quit()
|
||||
{
|
||||
context->quit = true;
|
||||
}
|
||||
|
||||
void QuitAll()
|
||||
{
|
||||
for(auto nc : contexts) {
|
||||
nc.second->quit = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool ShouldQuit()
|
||||
{
|
||||
return !context || context->quit;
|
||||
}
|
||||
|
||||
bool HadInput()
|
||||
{
|
||||
if( context->had_input > 0 )
|
||||
{
|
||||
--context->had_input;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HasResized()
|
||||
{
|
||||
if( context->has_resized > 0 )
|
||||
{
|
||||
--context->has_resized;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void StartFullScreen() {
|
||||
if(!context->is_fullscreen) {
|
||||
context->ToggleFullscreen();
|
||||
context->is_fullscreen = true;
|
||||
}
|
||||
}
|
||||
|
||||
void StopFullScreen() {
|
||||
if(context->is_fullscreen) {
|
||||
context->ToggleFullscreen();
|
||||
context->is_fullscreen = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SetFullscreen(bool fullscreen)
|
||||
{
|
||||
if(fullscreen) {
|
||||
StartFullScreen();
|
||||
}else{
|
||||
StopFullScreen();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderViews()
|
||||
{
|
||||
Viewport::DisableScissor();
|
||||
DisplayBase().Render();
|
||||
}
|
||||
|
||||
void RenderRecordGraphic(const Viewport& v)
|
||||
{
|
||||
const float r = 7;
|
||||
v.ActivatePixelOrthographic();
|
||||
glRecordGraphic(v.w-2*r, v.h-2*r, r);
|
||||
}
|
||||
|
||||
void PostRender()
|
||||
{
|
||||
while(context->screen_capture.size()) {
|
||||
std::pair<std::string,Viewport> fv = context->screen_capture.front();
|
||||
context->screen_capture.pop();
|
||||
SaveFramebuffer(fv.first, fv.second);
|
||||
}
|
||||
|
||||
#ifdef BUILD_PANGOLIN_VIDEO
|
||||
if(context->recorder.IsOpen()) {
|
||||
SaveFramebuffer(context->recorder, context->record_view->GetBounds() );
|
||||
RenderRecordGraphic(context->record_view->GetBounds());
|
||||
}
|
||||
#endif // BUILD_PANGOLIN_VIDEO
|
||||
|
||||
// Disable scissor each frame
|
||||
Viewport::DisableScissor();
|
||||
}
|
||||
|
||||
void FinishFrame()
|
||||
{
|
||||
RenderViews();
|
||||
PostRender();
|
||||
context->SwapBuffers();
|
||||
context->ProcessEvents();
|
||||
}
|
||||
|
||||
View& DisplayBase()
|
||||
{
|
||||
return context->base;
|
||||
}
|
||||
|
||||
View& CreateDisplay()
|
||||
{
|
||||
int iguid = rand();
|
||||
std::stringstream ssguid;
|
||||
ssguid << iguid;
|
||||
return Display(ssguid.str());
|
||||
}
|
||||
|
||||
void ToggleConsole()
|
||||
{
|
||||
#ifdef HAVE_PYTHON
|
||||
if( !context->console_view) {
|
||||
// Create console and let the pangolin context take ownership
|
||||
context->console_view = new ConsoleView(new PyInterpreter());
|
||||
context->named_managed_views["pangolin_console"] = context->console_view;
|
||||
context->console_view->SetFocus();
|
||||
context->console_view->zorder = std::numeric_limits<int>::max();
|
||||
DisplayBase().AddDisplay(*context->console_view);
|
||||
}else{
|
||||
context->console_view->ToggleShow();
|
||||
if(context->console_view->IsShown()) {
|
||||
context->console_view->SetFocus();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ToggleFullscreen()
|
||||
{
|
||||
SetFullscreen(!context->is_fullscreen);
|
||||
}
|
||||
|
||||
View& Display(const std::string& name)
|
||||
{
|
||||
// Get / Create View
|
||||
ViewMap::iterator vi = context->named_managed_views.find(name);
|
||||
if( vi != context->named_managed_views.end() )
|
||||
{
|
||||
return *(vi->second);
|
||||
}else{
|
||||
View * v = new View();
|
||||
context->named_managed_views[name] = v;
|
||||
v->handler = &StaticHandler;
|
||||
context->base.views.push_back(v);
|
||||
return *v;
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterKeyPressCallback(int key, std::function<void(void)> func)
|
||||
{
|
||||
context->keypress_hooks[key] = func;
|
||||
}
|
||||
|
||||
void SaveWindowOnRender(std::string prefix)
|
||||
{
|
||||
context->screen_capture.push(std::pair<std::string,Viewport>(prefix, context->base.v) );
|
||||
}
|
||||
|
||||
void SaveFramebuffer(std::string prefix, const Viewport& v)
|
||||
{
|
||||
PANGOLIN_UNUSED(prefix);
|
||||
PANGOLIN_UNUSED(v);
|
||||
|
||||
#ifndef HAVE_GLES
|
||||
|
||||
#ifdef HAVE_PNG
|
||||
PixelFormat fmt = PixelFormatFromString("RGBA32");
|
||||
TypedImage buffer(v.w, v.h, fmt );
|
||||
glReadBuffer(GL_BACK);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1); // TODO: Avoid this?
|
||||
glReadPixels(v.l, v.b, v.w, v.h, GL_RGBA, GL_UNSIGNED_BYTE, buffer.ptr );
|
||||
SaveImage(buffer, fmt, prefix + ".png", false);
|
||||
#endif // HAVE_PNG
|
||||
|
||||
#endif // HAVE_GLES
|
||||
}
|
||||
|
||||
#ifdef BUILD_PANGOLIN_VIDEO
|
||||
void SaveFramebuffer(VideoOutput& video, const Viewport& v)
|
||||
{
|
||||
#ifndef HAVE_GLES
|
||||
const StreamInfo& si = video.Streams()[0];
|
||||
if(video.Streams().size()==0 || (int)si.Width() != v.w || (int)si.Height() != v.h) {
|
||||
video.Close();
|
||||
return;
|
||||
}
|
||||
|
||||
static basetime last_time = TimeNow();
|
||||
const basetime time_now = TimeNow();
|
||||
last_time = time_now;
|
||||
|
||||
static std::vector<unsigned char> img;
|
||||
img.resize(v.w*v.h*4);
|
||||
|
||||
glReadBuffer(GL_BACK);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1); // TODO: Avoid this?
|
||||
glReadPixels(v.l, v.b, v.w, v.h, GL_RGB, GL_UNSIGNED_BYTE, &img[0] );
|
||||
video.WriteStreams(&img[0]);
|
||||
#endif // HAVE_GLES
|
||||
}
|
||||
#endif // BUILD_PANGOLIN_VIDEO
|
||||
|
||||
|
||||
namespace process
|
||||
{
|
||||
float last_x = 0;
|
||||
float last_y = 0;
|
||||
|
||||
void Keyboard( unsigned char key, int x, int y)
|
||||
{
|
||||
// Force coords to match OpenGl Window Coords
|
||||
y = context->base.v.h - y;
|
||||
|
||||
#ifdef HAVE_APPLE_OPENGL_FRAMEWORK
|
||||
// Switch backspace and delete for OSX!
|
||||
if(key== '\b') {
|
||||
key = 127;
|
||||
}else if(key == 127) {
|
||||
key = '\b';
|
||||
}
|
||||
#endif
|
||||
|
||||
context->had_input = context->is_double_buffered ? 2 : 1;
|
||||
|
||||
// Check if global key hook exists
|
||||
const KeyhookMap::iterator hook = context->keypress_hooks.find(key);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
// Console receives all input when it is open
|
||||
if( context->console_view && context->console_view->IsShown() ) {
|
||||
context->console_view->Keyboard(*(context->console_view),key,x,y,true);
|
||||
}else
|
||||
#endif
|
||||
if(hook != context->keypress_hooks.end() ) {
|
||||
hook->second();
|
||||
} else if(context->activeDisplay && context->activeDisplay->handler) {
|
||||
context->activeDisplay->handler->Keyboard(*(context->activeDisplay),key,x,y,true);
|
||||
}
|
||||
}
|
||||
|
||||
void KeyboardUp(unsigned char key, int x, int y)
|
||||
{
|
||||
// Force coords to match OpenGl Window Coords
|
||||
y = context->base.v.h - y;
|
||||
|
||||
if(context->activeDisplay && context->activeDisplay->handler)
|
||||
{
|
||||
context->activeDisplay->handler->Keyboard(*(context->activeDisplay),key,x,y,false);
|
||||
}
|
||||
}
|
||||
|
||||
void SpecialFunc(int key, int x, int y)
|
||||
{
|
||||
Keyboard(key+128,x,y);
|
||||
}
|
||||
|
||||
void SpecialFuncUp(int key, int x, int y)
|
||||
{
|
||||
KeyboardUp(key+128,x,y);
|
||||
}
|
||||
|
||||
|
||||
void Mouse( int button_raw, int state, int x, int y)
|
||||
{
|
||||
// Force coords to match OpenGl Window Coords
|
||||
y = context->base.v.h - y;
|
||||
|
||||
last_x = (float)x;
|
||||
last_y = (float)y;
|
||||
|
||||
const MouseButton button = (MouseButton)(1 << (button_raw & 0xf) );
|
||||
const bool pressed = (state == 0);
|
||||
|
||||
context->had_input = context->is_double_buffered ? 2 : 1;
|
||||
|
||||
const bool fresh_input = ( (context->mouse_state & 7) == 0);
|
||||
|
||||
if( pressed ) {
|
||||
context->mouse_state |= (button&7);
|
||||
}else{
|
||||
context->mouse_state &= ~(button&7);
|
||||
}
|
||||
|
||||
#if defined(_WIN_)
|
||||
context->mouse_state &= 0x0000ffff;
|
||||
context->mouse_state |= (button_raw >> 4) << 16;
|
||||
#endif
|
||||
|
||||
if(fresh_input) {
|
||||
context->base.handler->Mouse(context->base,button,x,y,pressed,context->mouse_state);
|
||||
}else if(context->activeDisplay && context->activeDisplay->handler) {
|
||||
context->activeDisplay->handler->Mouse(*(context->activeDisplay),button,x,y,pressed,context->mouse_state);
|
||||
}
|
||||
}
|
||||
|
||||
void MouseMotion( int x, int y)
|
||||
{
|
||||
// Force coords to match OpenGl Window Coords
|
||||
y = context->base.v.h - y;
|
||||
|
||||
last_x = (float)x;
|
||||
last_y = (float)y;
|
||||
|
||||
context->had_input = context->is_double_buffered ? 2 : 1;
|
||||
|
||||
if( context->activeDisplay)
|
||||
{
|
||||
if( context->activeDisplay->handler )
|
||||
context->activeDisplay->handler->MouseMotion(*(context->activeDisplay),x,y,context->mouse_state);
|
||||
}else{
|
||||
context->base.handler->MouseMotion(context->base,x,y,context->mouse_state);
|
||||
}
|
||||
}
|
||||
|
||||
void PassiveMouseMotion(int x, int y)
|
||||
{
|
||||
// Force coords to match OpenGl Window Coords
|
||||
y = context->base.v.h - y;
|
||||
|
||||
context->base.handler->PassiveMouseMotion(context->base,x,y,context->mouse_state);
|
||||
|
||||
last_x = (float)x;
|
||||
last_y = (float)y;
|
||||
}
|
||||
|
||||
void Display()
|
||||
{
|
||||
// No implementation
|
||||
}
|
||||
|
||||
void Resize( int width, int height )
|
||||
{
|
||||
if( !context->is_fullscreen )
|
||||
{
|
||||
context->windowed_size[0] = width;
|
||||
context->windowed_size[1] = height;
|
||||
}
|
||||
// TODO: Fancy display managers seem to cause this to mess up?
|
||||
context->had_input = 20; //context->is_double_buffered ? 2 : 1;
|
||||
context->has_resized = 20; //context->is_double_buffered ? 2 : 1;
|
||||
Viewport win(0,0,width,height);
|
||||
context->base.Resize(win);
|
||||
}
|
||||
|
||||
void SpecialInput(InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4)
|
||||
{
|
||||
// Assume coords already match OpenGl Window Coords
|
||||
|
||||
context->had_input = context->is_double_buffered ? 2 : 1;
|
||||
|
||||
const bool fresh_input = (context->mouse_state == 0);
|
||||
|
||||
if(fresh_input) {
|
||||
context->base.handler->Special(context->base,inType,x,y,p1,p2,p3,p4,context->mouse_state);
|
||||
}else if(context->activeDisplay && context->activeDisplay->handler) {
|
||||
context->activeDisplay->handler->Special(*(context->activeDisplay),inType,x,y,p1,p2,p3,p4,context->mouse_state);
|
||||
}
|
||||
}
|
||||
|
||||
void Scroll(float x, float y)
|
||||
{
|
||||
SpecialInput(InputSpecialScroll, last_x, last_y, x, y, 0, 0);
|
||||
}
|
||||
|
||||
void Zoom(float m)
|
||||
{
|
||||
SpecialInput(InputSpecialZoom, last_x, last_y, m, 0, 0, 0);
|
||||
}
|
||||
|
||||
void Rotate(float r)
|
||||
{
|
||||
SpecialInput(InputSpecialRotate, last_x, last_y, r, 0, 0, 0);
|
||||
}
|
||||
|
||||
void SubpixMotion(float x, float y, float pressure, float rotation, float tiltx, float tilty)
|
||||
{
|
||||
// Force coords to match OpenGl Window Coords
|
||||
y = context->base.v.h - y;
|
||||
SpecialInput(InputSpecialTablet, x, y, pressure, rotation, tiltx, tilty);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawTextureToViewport(GLuint texid)
|
||||
{
|
||||
OpenGlRenderState::ApplyIdentity();
|
||||
glBindTexture(GL_TEXTURE_2D, texid);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
GLfloat sq_vert[] = { -1,-1, 1,-1, 1, 1, -1, 1 };
|
||||
glVertexPointer(2, GL_FLOAT, 0, sq_vert);
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
GLfloat sq_tex[] = { 0,0, 1,0, 1,1, 0,1 };
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, sq_tex);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
ToggleViewFunctor::ToggleViewFunctor(View& view)
|
||||
: view(view)
|
||||
{
|
||||
}
|
||||
|
||||
ToggleViewFunctor::ToggleViewFunctor(const std::string& name)
|
||||
: view(Display(name))
|
||||
{
|
||||
}
|
||||
|
||||
void ToggleViewFunctor::operator()()
|
||||
{
|
||||
view.ToggleShow();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user