Initial commit

This commit is contained in:
Runar Tenfjord 2012-10-23 10:58:01 +02:00
parent c20520df41
commit 8e3cf419ab
31 changed files with 30719 additions and 4 deletions

368
LICENSE.txt Normal file
View file

@ -0,0 +1,368 @@
License for:
gltools
Truetype code:
stb_truetype.h - v0.6c - public domain
authored from 2009-2012 by Sean Barrett / RAD Game Tools
UTF-8 decoder:
http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
fontstash (with modifications marked in code)
recastnavigation - Mikko Mononen
http://digestingduck.blogspot.com/
License - MIT License
TTF font DroidSans:
http://www.droidfonts.com/
License - Apache License, Version 2.0
IMGUI (with modifications marked in code)
recastnavigation - Mikko Mononen
http://digestingduck.blogspot.com/
License - MIT License
Copyright (C) 2012 Runar Tenfjord, Tenko
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View file

@ -1,4 +0,0 @@
gltools
=======
Library for quickly creating OpenGL based application

30
README.rst Normal file
View file

@ -0,0 +1,30 @@
Introduction
============
gltools is library for quickly creating OpenGL based
application with support for:
* Access to vertex buffers and GLSL shaders
* Access to truetype fonts
* Windows handling through GLFW
* Simple GUI controls
OpenGL version 2.1 is targeted which should be available
in most computers these days, even in a laptop's integrated
graphics.
The license is GPL v2.
Building
========
* Python 2.6 or later and Cython 0.17.
* GLFW v3.0 (not released, must be build from repo)
* OpenGL headers
The extension have only been build on the Linux platform.
Documentation
=============
ToDo

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,510 @@
//
// Copyright (c) 2009 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <GL/gl.h>
// default font
#include "droidsans_ttf.h"
#define STB_TRUETYPE_IMPLEMENTATION
#define STBTT_malloc(x,u) malloc(x)
#define STBTT_free(x,u) free(x)
#include "stb_truetype.h"
#define HASH_LUT_SIZE 256
#define MAX_ROWS 128
#define MAX_FONTS 4
#define VERT_COUNT (6*128)
#define VERT_STRIDE (sizeof(float)*4)
static unsigned int hashint(unsigned int a)
{
a += ~(a<<15);
a ^= (a>>10);
a += (a<<3);
a ^= (a>>6);
a += ~(a<<11);
a ^= (a>>16);
return a;
}
struct sth_quad
{
float x0,y0,s0,t0;
float x1,y1,s1,t1;
};
struct sth_row
{
short x,y,h;
};
struct sth_glyph
{
unsigned int codepoint;
short size;
int x0,y0,x1,y1;
float xadv,xoff,yoff;
int next;
};
struct sth_font
{
stbtt_fontinfo font;
unsigned char* data;
int datasize;
int freedata; // rute : added flag
struct sth_glyph* glyphs;
int lut[HASH_LUT_SIZE];
int nglyphs;
float ascender;
float descender;
float lineh;
};
struct sth_stash
{
int tw,th;
float itw,ith;
GLuint tex;
struct sth_row rows[MAX_ROWS];
int nrows;
struct sth_font fonts[MAX_FONTS];
float verts[4*VERT_COUNT];
int nverts;
int drawing;
};
// Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
// See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
#define UTF8_ACCEPT 0
#define UTF8_REJECT 1
static const unsigned char utf8d[] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df
0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef
0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff
0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2
1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4
1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6
1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8
};
static unsigned int decutf8(unsigned int* state, unsigned int* codep, unsigned int byte)
{
unsigned int type = utf8d[byte];
*codep = (*state != UTF8_ACCEPT) ?
(byte & 0x3fu) | (*codep << 6) :
(0xff >> type) & (byte);
*state = utf8d[256 + *state*16 + type];
return *state;
}
struct sth_stash* sth_create(int cachew, int cacheh)
{
struct sth_stash* stash;
// Allocate memory for the font stash.
stash = (struct sth_stash*)malloc(sizeof(struct sth_stash));
if (stash == NULL) goto error;
memset(stash,0,sizeof(struct sth_stash));
// Create texture for the cache.
stash->tw = cachew;
stash->th = cacheh;
stash->itw = 1.0f/cachew;
stash->ith = 1.0f/cacheh;
glGenTextures(1, &stash->tex);
if (!stash->tex) goto error;
glBindTexture(GL_TEXTURE_2D, stash->tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, stash->tw,stash->th, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
return stash;
error:
if (stash != NULL)
free(stash);
return NULL;
}
int sth_add_font(struct sth_stash* stash, int idx, const char* path)
{
FILE* fp = 0;
int i, ascent, descent, fh, lineGap;
struct sth_font* fnt;
if (idx < 0 || idx >= MAX_FONTS) return 0;
fnt = &stash->fonts[idx];
if (fnt->data)
free(fnt->data);
if (fnt->glyphs)
free(fnt->glyphs);
memset(fnt,0,sizeof(struct sth_font));
// Init hash lookup.
for (i = 0; i < HASH_LUT_SIZE; ++i) fnt->lut[i] = -1;
if (path != NULL) {
// Read in the font data.
fp = fopen(path, "rb");
if (!fp) goto error;
fseek(fp,0,SEEK_END);
fnt->datasize = (int)ftell(fp);
fseek(fp,0,SEEK_SET);
fnt->data = (unsigned char*)malloc(fnt->datasize);
fnt->freedata = 1;
if (fnt->data == NULL) goto error;
fread(fnt->data, 1, fnt->datasize, fp);
fclose(fp);
fp = 0;
} else {
fnt->data = &droidsans_ttf[0];
fnt->freedata = 0;
}
// Init stb_truetype
if (!stbtt_InitFont(&fnt->font, fnt->data, 0)) goto error;
// Store normalized line height. The real line height is got
// by multiplying the lineh by font size.
stbtt_GetFontVMetrics(&fnt->font, &ascent, &descent, &lineGap);
fh = ascent - descent;
fnt->ascender = (float)ascent / (float)fh;
fnt->descender = (float)descent / (float)fh;
fnt->lineh = (float)(fh + lineGap) / (float)fh;
return 1;
error:
if (fnt->freedata && fnt->data) free(fnt->data);
if (fnt->glyphs) free(fnt->glyphs);
memset(fnt,0,sizeof(struct sth_font));
if (fp) fclose(fp);
return 0;
}
static struct sth_glyph* get_glyph(struct sth_stash* stash, struct sth_font* fnt, unsigned int codepoint, short isize)
{
int i,g,advance,lsb,x0,y0,x1,y1,gw,gh;
float scale;
struct sth_glyph* glyph;
unsigned char* bmp;
unsigned int h;
float size = isize/10.0f;
int rh;
struct sth_row* br;
// Find code point and size.
h = hashint(codepoint) & (HASH_LUT_SIZE-1);
i = fnt->lut[h];
while (i != -1)
{
if (fnt->glyphs[i].codepoint == codepoint && fnt->glyphs[i].size == isize)
return &fnt->glyphs[i];
i = fnt->glyphs[i].next;
}
// Could not find glyph, create it.
scale = stbtt_ScaleForPixelHeight(&fnt->font, size);
g = stbtt_FindGlyphIndex(&fnt->font, codepoint);
stbtt_GetGlyphHMetrics(&fnt->font, g, &advance, &lsb);
stbtt_GetGlyphBitmapBox(&fnt->font, g, scale,scale, &x0,&y0,&x1,&y1);
gw = x1-x0;
gh = y1-y0;
// Find row where the glyph can be fit.
br = NULL;
rh = (gh+7) & ~7;
for (i = 0; i < stash->nrows; ++i)
{
if (stash->rows[i].h == rh && stash->rows[i].x+gw+1 <= stash->tw)
br = &stash->rows[i];
}
// If no row found, add new.
if (br == NULL)
{
short py = 0;
// Check that there is enough space.
if (stash->nrows)
{
py = stash->rows[stash->nrows-1].y + stash->rows[stash->nrows-1].h+1;
if (py+rh > stash->th)
return 0;
}
// Init and add row
br = &stash->rows[stash->nrows];
br->x = 0;
br->y = py;
br->h = rh;
stash->nrows++;
}
// Alloc space for new glyph.
fnt->nglyphs++;
fnt->glyphs = realloc(fnt->glyphs, fnt->nglyphs*sizeof(struct sth_glyph));
if (!fnt->glyphs) return 0;
// Init glyph.
glyph = &fnt->glyphs[fnt->nglyphs-1];
memset(glyph, 0, sizeof(struct sth_glyph));
glyph->codepoint = codepoint;
glyph->size = isize;
glyph->x0 = br->x;
glyph->y0 = br->y;
glyph->x1 = glyph->x0+gw;
glyph->y1 = glyph->y0+gh;
glyph->xadv = scale * advance;
glyph->xoff = (float)x0;
glyph->yoff = (float)y0;
glyph->next = 0;
// Advance row location.
br->x += gw+1;
// Insert char to hash lookup.
glyph->next = fnt->lut[h];
fnt->lut[h] = fnt->nglyphs-1;
// Rasterize
bmp = (unsigned char*)malloc(gw*gh);
if (bmp)
{
stbtt_MakeGlyphBitmap(&fnt->font, bmp, gw,gh,gw, scale,scale, g);
// Update texture
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glTexSubImage2D(GL_TEXTURE_2D, 0, glyph->x0,glyph->y0, gw,gh, GL_ALPHA,GL_UNSIGNED_BYTE,bmp);
free(bmp);
}
return glyph;
}
static int get_quad(struct sth_stash* stash, struct sth_font* fnt, unsigned int codepoint, short isize, float* x, float* y, struct sth_quad* q)
{
int rx,ry;
struct sth_glyph* glyph = get_glyph(stash, fnt, codepoint, isize);
if (!glyph) return 0;
rx = floorf(*x + glyph->xoff);
ry = floorf(*y - glyph->yoff);
q->x0 = rx;
q->y0 = ry;
q->x1 = rx + glyph->x1 - glyph->x0;
q->y1 = ry - glyph->y1 + glyph->y0;
q->s0 = (glyph->x0) * stash->itw;
q->t0 = (glyph->y0) * stash->ith;
q->s1 = (glyph->x1) * stash->itw;
q->t1 = (glyph->y1) * stash->ith;
*x += glyph->xadv;
return 1;
}
static float* setv(float* v, float x, float y, float s, float t)
{
v[0] = x;
v[1] = y;
v[2] = s;
v[3] = t;
return v+4;
}
static void flush_draw(struct sth_stash* stash)
{
if (stash->nverts == 0)
return;
glBindTexture(GL_TEXTURE_2D, stash->tex);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, VERT_STRIDE, stash->verts);
glTexCoordPointer(2, GL_FLOAT, VERT_STRIDE, stash->verts+2);
glDrawArrays(GL_TRIANGLES, 0, stash->nverts);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
stash->nverts = 0;
}
void sth_begin_draw(struct sth_stash* stash)
{
if (stash == NULL) return;
if (stash->drawing)
flush_draw(stash);
stash->drawing = 1;
}
void sth_end_draw(struct sth_stash* stash)
{
if (stash == NULL) return;
if (!stash->drawing) return;
/*
// Debug dump.
if (stash->nverts+6 < VERT_COUNT)
{
float x = 500, y = 100;
float* v = &stash->verts[stash->nverts*4];
v = setv(v, x, y, 0, 0);
v = setv(v, x+stash->tw, y, 1, 0);
v = setv(v, x+stash->tw, y+stash->th, 1, 1);
v = setv(v, x, y, 0, 0);
v = setv(v, x+stash->tw, y+stash->th, 1, 1);
v = setv(v, x, y+stash->th, 0, 1);
stash->nverts += 6;
}
*/
flush_draw(stash);
stash->drawing = 0;
}
int sth_draw_text(struct sth_stash* stash,
int idx, float size,
float x, float y,
const char* s, float* dx)
{
unsigned int codepoint;
unsigned int state = 0;
struct sth_quad q;
short isize = (short)(size*10.0f);
float* v;
struct sth_font* fnt;
if (stash == NULL) return 0;
if (!stash->tex) return 0;
if (idx < 0 || idx >= MAX_FONTS) return 0;
fnt = &stash->fonts[idx];
if (!fnt->data) return 0;
for (; *s; ++s)
{
if (decutf8(&state, &codepoint, *(unsigned char*)s)) continue;
if (stash->nverts+6 >= VERT_COUNT)
flush_draw(stash);
if (!get_quad(stash, fnt, codepoint, isize, &x, &y, &q)) continue;
v = &stash->verts[stash->nverts*4];
v = setv(v, q.x0, q.y0, q.s0, q.t0);
v = setv(v, q.x1, q.y0, q.s1, q.t0);
v = setv(v, q.x1, q.y1, q.s1, q.t1);
v = setv(v, q.x0, q.y0, q.s0, q.t0);
v = setv(v, q.x1, q.y1, q.s1, q.t1);
v = setv(v, q.x0, q.y1, q.s0, q.t1);
stash->nverts += 6;
}
if (dx) *dx = x;
return 1;
}
void sth_dim_text(struct sth_stash* stash,
int idx, float size,
const char* s,
float* minx, float* miny, float* maxx, float* maxy)
{
unsigned int codepoint;
unsigned int state = 0;
struct sth_quad q;
short isize = (short)(size*10.0f);
struct sth_font* fnt;
float x = 0, y = 0;
if (stash == NULL) return;
if (!stash->tex) return;
if (idx < 0 || idx >= MAX_FONTS) return;
fnt = &stash->fonts[idx];
if (!fnt->data) return;
*minx = *maxx = x;
*miny = *maxy = y;
for (; *s; ++s)
{
if (decutf8(&state, &codepoint, *(unsigned char*)s)) continue;
if (!get_quad(stash, fnt, codepoint, isize, &x, &y, &q)) continue;
if (q.x0 < *minx) *minx = q.x0;
if (q.x1 > *maxx) *maxx = q.x1;
if (q.y1 < *miny) *miny = q.y1;
if (q.y0 > *maxy) *maxy = q.y0;
}
}
void sth_vmetrics(struct sth_stash* stash,
int idx, float size,
float* ascender, float* descender, float* lineh)
{
if (stash == NULL) return;
if (!stash->tex) return;
if (idx < 0 || idx >= MAX_FONTS) return;
if (!stash->fonts[idx].data) return;
if (ascender)
*ascender = stash->fonts[idx].ascender*size;
if (descender)
*descender = stash->fonts[idx].descender*size;
if (lineh)
*lineh = stash->fonts[idx].lineh*size;
}
void sth_delete(struct sth_stash* stash)
{
int i;
if (!stash) return;
if (stash->tex) glDeleteTextures(1,&stash->tex);
for (i = 0; i < MAX_FONTS; ++i)
{
if (stash->fonts[i].glyphs)
free(stash->fonts[i].glyphs);
if (stash->fonts[i].freedata && stash->fonts[i].data)
free(stash->fonts[i].data);
}
free(stash);
}

View file

@ -0,0 +1,50 @@
//
// Copyright (c) 2009 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef FONTSTASH_H
#define FONTSTASH_H
#ifdef __cplusplus
extern "C" {
#endif
struct sth_stash* sth_create(int cachew, int cacheh);
int sth_add_font(struct sth_stash*, int idx, const char* path);
void sth_begin_draw(struct sth_stash* stash);
void sth_end_draw(struct sth_stash* stash);
int sth_draw_text(struct sth_stash* stash,
int idx, float size,
float x, float y, const char* string, float* dx);
void sth_dim_text(struct sth_stash* stash, int idx, float size, const char* string,
float* minx, float* miny, float* maxx, float* maxy);
void sth_vmetrics(struct sth_stash* stash,
int idx, float size,
float* ascender, float* descender, float * lineh);
void sth_delete(struct sth_stash* stash);
#ifdef __cplusplus
}
#endif
#endif // FONTSTASH_H

693
gltools/@contrib/imgui.cpp Normal file
View file

@ -0,0 +1,693 @@
//
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
// Copyright (c) 2011 Mario 'rlyeh' Rodriguez
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#include <stdio.h>
#include <string.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "imgui.h"
#ifdef WIN32
# define snprintf _snprintf
#endif
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static const unsigned TEXT_POOL_SIZE = 8000;
static char g_textPool[TEXT_POOL_SIZE];
static unsigned g_textPoolSize = 0;
static const char* allocText(const char* text)
{
unsigned len = strlen(text)+1;
if (g_textPoolSize + len >= TEXT_POOL_SIZE)
return 0;
char* dst = &g_textPool[g_textPoolSize];
memcpy(dst, text, len);
g_textPoolSize += len;
return dst;
}
static const unsigned GFXCMD_QUEUE_SIZE = 5000;
static imguiGfxCmd g_gfxCmdQueue[GFXCMD_QUEUE_SIZE];
static unsigned g_gfxCmdQueueSize = 0;
static void resetGfxCmdQueue()
{
g_gfxCmdQueueSize = 0;
g_textPoolSize = 0;
}
static void addGfxCmdScissor(int x, int y, int w, int h)
{
if (g_gfxCmdQueueSize >= GFXCMD_QUEUE_SIZE)
return;
imguiGfxCmd& cmd = g_gfxCmdQueue[g_gfxCmdQueueSize++];
cmd.type = IMGUI_GFXCMD_SCISSOR;
cmd.flags = x < 0 ? 0 : 1; // on/off flag.
cmd.col = 0;
cmd.rect.x = (short)x;
cmd.rect.y = (short)y;
cmd.rect.w = (short)w;
cmd.rect.h = (short)h;
}
static void addGfxCmdRect(float x, float y, float w, float h, unsigned int color)
{
if (g_gfxCmdQueueSize >= GFXCMD_QUEUE_SIZE)
return;
imguiGfxCmd& cmd = g_gfxCmdQueue[g_gfxCmdQueueSize++];
cmd.type = IMGUI_GFXCMD_RECT;
cmd.flags = 0;
cmd.col = color;
cmd.rect.x = (short)(x*8.0f);
cmd.rect.y = (short)(y*8.0f);
cmd.rect.w = (short)(w*8.0f);
cmd.rect.h = (short)(h*8.0f);
cmd.rect.r = 0;
}
static void addGfxCmdLine(float x0, float y0, float x1, float y1, float r, unsigned int color)
{
if (g_gfxCmdQueueSize >= GFXCMD_QUEUE_SIZE)
return;
imguiGfxCmd& cmd = g_gfxCmdQueue[g_gfxCmdQueueSize++];
cmd.type = IMGUI_GFXCMD_LINE;
cmd.flags = 0;
cmd.col = color;
cmd.line.x0 = (short)(x0*8.0f);
cmd.line.y0 = (short)(y0*8.0f);
cmd.line.x1 = (short)(x1*8.0f);
cmd.line.y1 = (short)(y1*8.0f);
cmd.line.r = (short)(r*8.0f);
}
static void addGfxCmdRoundedRect(float x, float y, float w, float h, float r, unsigned int color)
{
if (g_gfxCmdQueueSize >= GFXCMD_QUEUE_SIZE)
return;
imguiGfxCmd& cmd = g_gfxCmdQueue[g_gfxCmdQueueSize++];
cmd.type = IMGUI_GFXCMD_RECT;
cmd.flags = 0;
cmd.col = color;
cmd.rect.x = (short)(x*8.0f);
cmd.rect.y = (short)(y*8.0f);
cmd.rect.w = (short)(w*8.0f);
cmd.rect.h = (short)(h*8.0f);
cmd.rect.r = (short)(r*8.0f);
}
static void addGfxCmdTriangle(int x, int y, int w, int h, int flags, unsigned int color)
{
if (g_gfxCmdQueueSize >= GFXCMD_QUEUE_SIZE)
return;
imguiGfxCmd& cmd = g_gfxCmdQueue[g_gfxCmdQueueSize++];
cmd.type = IMGUI_GFXCMD_TRIANGLE;
cmd.flags = (char)flags;
cmd.col = color;
cmd.rect.x = (short)(x*8.0f);
cmd.rect.y = (short)(y*8.0f);
cmd.rect.w = (short)(w*8.0f);
cmd.rect.h = (short)(h*8.0f);
}
static void addGfxCmdText(int x, int y, int align, const char* text, unsigned int color)
{
if (g_gfxCmdQueueSize >= GFXCMD_QUEUE_SIZE)
return;
imguiGfxCmd& cmd = g_gfxCmdQueue[g_gfxCmdQueueSize++];
cmd.type = IMGUI_GFXCMD_TEXT;
cmd.flags = 0;
cmd.col = color;
cmd.text.x = (short)x;
cmd.text.y = (short)y;
cmd.text.align = (short)align;
cmd.text.text = allocText(text);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct GuiState
{
GuiState() :
left(false), leftPressed(false), leftReleased(false),
mx(-1), my(-1), scroll(0),
active(0), hot(0), hotToBe(0), isHot(false), isActive(false), wentActive(false),
dragX(0), dragY(0), dragOrig(0), widgetX(0), widgetY(0), widgetW(100),
insideCurrentScroll(false), areaId(0), widgetId(0)
{
}
bool left;
bool leftPressed, leftReleased;
int mx,my;
int scroll;
unsigned int active;
unsigned int hot;
unsigned int hotToBe;
bool isHot;
bool isActive;
bool wentActive;
int dragX, dragY;
float dragOrig;
int widgetX, widgetY, widgetW;
bool insideCurrentScroll;
unsigned int areaId;
unsigned int widgetId;
};
static GuiState g_state;
inline bool anyActive()
{
return g_state.active != 0;
}
inline bool anyHot() // @rlyeh: new method
{
return g_state.hot != 0;
}
inline bool isActive(unsigned int id)
{
return g_state.active == id;
}
inline bool isHot(unsigned int id)
{
return g_state.hot == id;
}
inline bool inRect(int x, int y, int w, int h, bool checkScroll = true)
{
return (!checkScroll || g_state.insideCurrentScroll) && g_state.mx >= x && g_state.mx <= x+w && g_state.my >= y && g_state.my <= y+h;
}
inline void clearInput()
{
g_state.leftPressed = false;
g_state.leftReleased = false;
g_state.scroll = 0;
}
inline void clearActive()
{
g_state.active = 0;
// mark all UI for this frame as processed
clearInput();
}
inline void setActive(unsigned int id)
{
g_state.active = id;
g_state.wentActive = true;
}
inline void setHot(unsigned int id)
{
g_state.hotToBe = id;
}
static bool buttonLogic(unsigned int id, bool over)
{
bool res = false;
// process down
if (!anyActive())
{
if (over)
setHot(id);
if (isHot(id) && g_state.leftPressed)
setActive(id);
}
// if button is active, then react on left up
if (isActive(id))
{
g_state.isActive = true;
if (over)
setHot(id);
if (g_state.leftReleased)
{
if (isHot(id))
res = true;
clearActive();
}
}
if (isHot(id))
g_state.isHot = true;
return res;
}
static void updateInput(int mx, int my, unsigned char mbut, int scroll)
{
bool left = (mbut & IMGUI_MBUT_LEFT) != 0;
g_state.mx = mx;
g_state.my = my;
g_state.leftPressed = !g_state.left && left;
g_state.leftReleased = g_state.left && !left;
g_state.left = left;
g_state.scroll = scroll;
}
bool imguiAnyActive() // added by rute
{
return g_state.active != 0;
}
void imguiBeginFrame(int mx, int my, unsigned char mbut, int scroll)
{
updateInput(mx,my,mbut,scroll);
g_state.hot = g_state.hotToBe;
g_state.hotToBe = 0;
g_state.wentActive = false;
g_state.isActive = false;
g_state.isHot = false;
g_state.widgetX = 0;
g_state.widgetY = 0;
g_state.widgetW = 0;
g_state.areaId = 1;
g_state.widgetId = 1;
resetGfxCmdQueue();
}
void imguiEndFrame()
{
clearInput();
}
const imguiGfxCmd* imguiGetRenderQueue()
{
return g_gfxCmdQueue;
}
int imguiGetRenderQueueSize()
{
return g_gfxCmdQueueSize;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static const int BUTTON_HEIGHT = 20;
static const int SLIDER_HEIGHT = 20;
static const int SLIDER_MARKER_WIDTH = 10;
static const int CHECK_SIZE = 8;
static const int DEFAULT_SPACING = 4;
static const int TEXT_HEIGHT = 8;
static const int SCROLL_AREA_PADDING = 6;
static const int INDENT_SIZE = 16;
static const int AREA_HEADER = 28;
static int g_scrollTop = 0;
static int g_scrollBottom = 0;
static int g_scrollRight = 0;
static int g_scrollAreaTop = 0;
static int* g_scrollVal = 0;
static int g_focusTop = 0;
static int g_focusBottom = 0;
static unsigned int g_scrollId = 0;
static bool g_insideScrollArea = false;
bool imguiBeginScrollArea(const char* name, int x, int y, int w, int h, int* scroll)
{
g_state.areaId++;
g_state.widgetId = 0;
g_scrollId = (g_state.areaId<<16) | g_state.widgetId;
g_state.widgetX = x + SCROLL_AREA_PADDING;
g_state.widgetY = y+h-AREA_HEADER + (*scroll);
g_state.widgetW = w - SCROLL_AREA_PADDING*4;
g_scrollTop = y-AREA_HEADER+h;
g_scrollBottom = y+SCROLL_AREA_PADDING;
g_scrollRight = x+w - SCROLL_AREA_PADDING*3;
g_scrollVal = scroll;
g_scrollAreaTop = g_state.widgetY;
g_focusTop = y-AREA_HEADER;
g_focusBottom = y-AREA_HEADER+h;
g_insideScrollArea = inRect(x, y, w, h, false);
g_state.insideCurrentScroll = g_insideScrollArea;
addGfxCmdRoundedRect((float)x, (float)y, (float)w, (float)h, 6, imguiRGBA(0,0,0,192));
addGfxCmdText(x+AREA_HEADER/2, y+h-AREA_HEADER/2-TEXT_HEIGHT/2, IMGUI_ALIGN_LEFT, name, imguiRGBA(255,255,255,128));
if( g_scrollVal ) // @rlyeh: support for fixed areas
addGfxCmdScissor(
x < 0 ? 0 : x+SCROLL_AREA_PADDING, //@rlyeh: fix scissor clipping problem when scroll area is on left rect client
y+SCROLL_AREA_PADDING,
w-SCROLL_AREA_PADDING*4 + ( x < 0 ? x : 0 ), // @rlyeh: small optimization; @todo: on the right as well
h > (AREA_HEADER + SCROLL_AREA_PADDING ) ? h - (AREA_HEADER + SCROLL_AREA_PADDING) : h ); // @rlyeh: fix when collapsing areas ( h <= AREA_HEADER )
return g_insideScrollArea;
}
void imguiEndScrollArea()
{
if( g_scrollVal ) // @rlyeh: support for fixed areas
// Disable scissoring.
addGfxCmdScissor(-1,-1,-1,-1);
// Draw scroll bar
int x = g_scrollRight+SCROLL_AREA_PADDING/2;
int y = g_scrollBottom;
int w = SCROLL_AREA_PADDING*2;
int h = g_scrollTop - g_scrollBottom;
int stop = g_scrollAreaTop;
int sbot = g_state.widgetY;
int sh = stop - sbot; // The scrollable area height.
float barHeight = (float)h/(float)sh;
if (h > AREA_HEADER && barHeight < 1) // @rlyeh: fix when area size is too small
{
float barY = (float)(y - sbot)/(float)sh;
if (barY < 0) barY = 0;
if (barY > 1) barY = 1;
// Handle scroll bar logic.
unsigned int hid = g_scrollId;
int hx = x;
int hy = y + (int)(barY*h);
int hw = w;
int hh = (int)(barHeight*h);
const int range = h - (hh-1);
bool over = inRect(hx, hy, hw, hh);
buttonLogic(hid, over);
if (isActive(hid))
{
float u = (float)(hy-y) / (float)range;
if (g_state.wentActive)
{
g_state.dragY = g_state.my;
g_state.dragOrig = u;
}
if (g_state.dragY != g_state.my)
{
u = g_state.dragOrig + (g_state.my - g_state.dragY) / (float)range;
if (u < 0) u = 0;
if (u > 1) u = 1;
*g_scrollVal = (int)((1-u) * (sh - h));
}
}
// BG
addGfxCmdRoundedRect((float)x, (float)y, (float)w, (float)h, (float)w/2-1, imguiRGBA(0,0,0,196));
// Bar
if (isActive(hid))
addGfxCmdRoundedRect((float)hx, (float)hy, (float)hw, (float)hh, (float)w/2-1, imguiRGBA(255,196,0,196));
else
addGfxCmdRoundedRect((float)hx, (float)hy, (float)hw, (float)hh, (float)w/2-1, isHot(hid) ? imguiRGBA(255,196,0,96) : imguiRGBA(255,255,255,64));
// Handle mouse scrolling.
if (g_insideScrollArea) // && !anyActive())
{
if (g_state.scroll)
{
*g_scrollVal += 20*g_state.scroll;
if (*g_scrollVal < 0) *g_scrollVal = 0;
if (*g_scrollVal > (sh - h)) *g_scrollVal = (sh - h);
}
}
} else
*g_scrollVal = 0; // @rlyeh: fix for mismatching scroll when collapsing/uncollapsing content larger than container height
g_state.insideCurrentScroll = false;
}
bool imguiButton(const char* text, bool enabled)
{
g_state.widgetId++;
unsigned int id = (g_state.areaId<<16) | g_state.widgetId;
int x = g_state.widgetX;
int y = g_state.widgetY - BUTTON_HEIGHT;
int w = g_state.widgetW;
int h = BUTTON_HEIGHT;
g_state.widgetY -= BUTTON_HEIGHT + DEFAULT_SPACING;
bool over = enabled && inRect(x, y, w, h);
bool res = buttonLogic(id, over);
addGfxCmdRoundedRect((float)x, (float)y, (float)w, (float)h, (float)BUTTON_HEIGHT/2-1, imguiRGBA(128,128,128, isActive(id)?196:96));
if (enabled)
addGfxCmdText(x+BUTTON_HEIGHT/2, y+BUTTON_HEIGHT/2-TEXT_HEIGHT/2, IMGUI_ALIGN_LEFT, text, isHot(id) ? imguiRGBA(255,196,0,255) : imguiRGBA(255,255,255,200));
else
addGfxCmdText(x+BUTTON_HEIGHT/2, y+BUTTON_HEIGHT/2-TEXT_HEIGHT/2, IMGUI_ALIGN_LEFT, text, imguiRGBA(128,128,128,200));
return res;
}
bool imguiItem(const char* text, bool enabled)
{
g_state.widgetId++;
unsigned int id = (g_state.areaId<<16) | g_state.widgetId;
int x = g_state.widgetX;
int y = g_state.widgetY - BUTTON_HEIGHT;
int w = g_state.widgetW;
int h = BUTTON_HEIGHT;
g_state.widgetY -= BUTTON_HEIGHT + DEFAULT_SPACING;
bool over = enabled && inRect(x, y, w, h);
bool res = buttonLogic(id, over);
if (isHot(id))
addGfxCmdRoundedRect((float)x, (float)y, (float)w, (float)h, 2.0f, imguiRGBA(255,196,0,isActive(id)?196:96));
if (enabled)
addGfxCmdText(x+BUTTON_HEIGHT/2, y+BUTTON_HEIGHT/2-TEXT_HEIGHT/2, IMGUI_ALIGN_LEFT, text, imguiRGBA(255,255,255,200));
else
addGfxCmdText(x+BUTTON_HEIGHT/2, y+BUTTON_HEIGHT/2-TEXT_HEIGHT/2, IMGUI_ALIGN_LEFT, text, imguiRGBA(128,128,128,200));
return res;
}
bool imguiCheck(const char* text, bool checked, bool enabled)
{
g_state.widgetId++;
unsigned int id = (g_state.areaId<<16) | g_state.widgetId;
int x = g_state.widgetX;
int y = g_state.widgetY - BUTTON_HEIGHT;
int w = g_state.widgetW;
int h = BUTTON_HEIGHT;
g_state.widgetY -= BUTTON_HEIGHT + DEFAULT_SPACING;
bool over = enabled && inRect(x, y, w, h);
bool res = buttonLogic(id, over);
const int cx = x+BUTTON_HEIGHT/2-CHECK_SIZE/2;
const int cy = y+BUTTON_HEIGHT/2-CHECK_SIZE/2;
addGfxCmdRoundedRect((float)cx-3, (float)cy-3, (float)CHECK_SIZE+6, (float)CHECK_SIZE+6, 4, imguiRGBA(128,128,128, isActive(id)?196:96));
if (checked)
{
if (enabled)
addGfxCmdRoundedRect((float)cx, (float)cy, (float)CHECK_SIZE, (float)CHECK_SIZE, (float)CHECK_SIZE/2-1, imguiRGBA(255,255,255,isActive(id)?255:200));
else
addGfxCmdRoundedRect((float)cx, (float)cy, (float)CHECK_SIZE, (float)CHECK_SIZE, (float)CHECK_SIZE/2-1, imguiRGBA(128,128,128,200));
}
if (enabled)
addGfxCmdText(x+BUTTON_HEIGHT, y+BUTTON_HEIGHT/2-TEXT_HEIGHT/2, IMGUI_ALIGN_LEFT, text, isHot(id) ? imguiRGBA(255,196,0,255) : imguiRGBA(255,255,255,200));
else
addGfxCmdText(x+BUTTON_HEIGHT, y+BUTTON_HEIGHT/2-TEXT_HEIGHT/2, IMGUI_ALIGN_LEFT, text, imguiRGBA(128,128,128,200));
return res;
}
bool imguiCollapse(const char* text, const char* subtext, bool checked, bool enabled)
{
g_state.widgetId++;
unsigned int id = (g_state.areaId<<16) | g_state.widgetId;
int x = g_state.widgetX;
int y = g_state.widgetY - BUTTON_HEIGHT;
int w = g_state.widgetW;
int h = BUTTON_HEIGHT;
g_state.widgetY -= BUTTON_HEIGHT; // + DEFAULT_SPACING;
const int cx = x+BUTTON_HEIGHT/2-CHECK_SIZE/2;
const int cy = y+BUTTON_HEIGHT/2-CHECK_SIZE/2;
bool over = enabled && inRect(x, y, w, h);
bool res = buttonLogic(id, over);
if (checked)
addGfxCmdTriangle(cx, cy, CHECK_SIZE, CHECK_SIZE, 2, imguiRGBA(255,255,255,isActive(id)?255:200));
else
addGfxCmdTriangle(cx, cy, CHECK_SIZE, CHECK_SIZE, 1, imguiRGBA(255,255,255,isActive(id)?255:200));
if (enabled)
addGfxCmdText(x+BUTTON_HEIGHT, y+BUTTON_HEIGHT/2-TEXT_HEIGHT/2, IMGUI_ALIGN_LEFT, text, isHot(id) ? imguiRGBA(255,196,0,255) : imguiRGBA(255,255,255,200));
else
addGfxCmdText(x+BUTTON_HEIGHT, y+BUTTON_HEIGHT/2-TEXT_HEIGHT/2, IMGUI_ALIGN_LEFT, text, imguiRGBA(128,128,128,200));
if (subtext)
addGfxCmdText(x+w-BUTTON_HEIGHT/2, y+BUTTON_HEIGHT/2-TEXT_HEIGHT/2, IMGUI_ALIGN_RIGHT, subtext, imguiRGBA(255,255,255,128));
return res;
}
void imguiLabel(const char* text)
{
int x = g_state.widgetX;
int y = g_state.widgetY - BUTTON_HEIGHT;
g_state.widgetY -= BUTTON_HEIGHT;
addGfxCmdText(x, y+BUTTON_HEIGHT/2-TEXT_HEIGHT/2, IMGUI_ALIGN_LEFT, text, imguiRGBA(255,255,255,255));
}
void imguiValue(const char* text)
{
const int x = g_state.widgetX;
const int y = g_state.widgetY - BUTTON_HEIGHT;
const int w = g_state.widgetW;
g_state.widgetY -= BUTTON_HEIGHT;
addGfxCmdText(x+w-BUTTON_HEIGHT/2, y+BUTTON_HEIGHT/2-TEXT_HEIGHT/2, IMGUI_ALIGN_RIGHT, text, imguiRGBA(255,255,255,200));
}
bool imguiSlider(const char* text, float* val, float vmin, float vmax, float vinc, bool enabled)
{
g_state.widgetId++;
unsigned int id = (g_state.areaId<<16) | g_state.widgetId;
int x = g_state.widgetX;
int y = g_state.widgetY - BUTTON_HEIGHT;
int w = g_state.widgetW;
int h = SLIDER_HEIGHT;
g_state.widgetY -= SLIDER_HEIGHT + DEFAULT_SPACING;
addGfxCmdRoundedRect((float)x, (float)y, (float)w, (float)h, 4.0f, imguiRGBA(0,0,0,128));
const int range = w - SLIDER_MARKER_WIDTH;
float u = (*val - vmin) / (vmax-vmin);
if (u < 0) u = 0;
if (u > 1) u = 1;
int m = (int)(u * range);
bool over = enabled && inRect(x+m, y, SLIDER_MARKER_WIDTH, SLIDER_HEIGHT);
bool res = buttonLogic(id, over);
bool valChanged = false;
if (isActive(id))
{
if (g_state.wentActive)
{
g_state.dragX = g_state.mx;
g_state.dragOrig = u;
}
if (g_state.dragX != g_state.mx)
{
u = g_state.dragOrig + (float)(g_state.mx - g_state.dragX) / (float)range;
if (u < 0) u = 0;
if (u > 1) u = 1;
*val = vmin + u*(vmax-vmin);
*val = floorf(*val/vinc+0.5f)*vinc; // Snap to vinc
m = (int)(u * range);
valChanged = true;
}
}
if (isActive(id))
addGfxCmdRoundedRect((float)(x+m), (float)y, (float)SLIDER_MARKER_WIDTH, (float)SLIDER_HEIGHT, 4.0f, imguiRGBA(255,255,255,255));
else
addGfxCmdRoundedRect((float)(x+m), (float)y, (float)SLIDER_MARKER_WIDTH, (float)SLIDER_HEIGHT, 4.0f, isHot(id) ? imguiRGBA(255,196,0,128) : imguiRGBA(255,255,255,64));
// TODO: fix this, take a look at 'nicenum'.
int digits = (int)(ceilf(log10f(vinc)));
char fmt[16];
snprintf(fmt, 16, "%%.%df", digits >= 0 ? 0 : -digits);
char msg[128];
snprintf(msg, 128, fmt, *val);
if (enabled)
{
addGfxCmdText(x+SLIDER_HEIGHT/2, y+SLIDER_HEIGHT/2-TEXT_HEIGHT/2, IMGUI_ALIGN_LEFT, text, isHot(id) ? imguiRGBA(255,196,0,255) : imguiRGBA(255,255,255,200));
addGfxCmdText(x+w-SLIDER_HEIGHT/2, y+SLIDER_HEIGHT/2-TEXT_HEIGHT/2, IMGUI_ALIGN_RIGHT, msg, isHot(id) ? imguiRGBA(255,196,0,255) : imguiRGBA(255,255,255,200));
}
else
{
addGfxCmdText(x+SLIDER_HEIGHT/2, y+SLIDER_HEIGHT/2-TEXT_HEIGHT/2, IMGUI_ALIGN_LEFT, text, imguiRGBA(128,128,128,200));
addGfxCmdText(x+w-SLIDER_HEIGHT/2, y+SLIDER_HEIGHT/2-TEXT_HEIGHT/2, IMGUI_ALIGN_RIGHT, msg, imguiRGBA(128,128,128,200));
}
return res || valChanged;
}
void imguiIndent()
{
g_state.widgetX += INDENT_SIZE;
g_state.widgetW -= INDENT_SIZE;
}
void imguiUnindent()
{
g_state.widgetX -= INDENT_SIZE;
g_state.widgetW += INDENT_SIZE;
}
void imguiSeparator()
{
g_state.widgetY -= DEFAULT_SPACING*3;
}
void imguiSeparatorLine()
{
int x = g_state.widgetX;
int y = g_state.widgetY - DEFAULT_SPACING*2;
int w = g_state.widgetW;
int h = 1;
g_state.widgetY -= DEFAULT_SPACING*4;
addGfxCmdRect((float)x, (float)y, (float)w, (float)h, imguiRGBA(255,255,255,32));
}
void imguiDrawText(int x, int y, int align, const char* text, unsigned int color)
{
addGfxCmdText(x, y, align, text, color);
}
void imguiDrawLine(float x0, float y0, float x1, float y1, float r, unsigned int color)
{
addGfxCmdLine(x0, y0, x1, y1, r, color);
}
void imguiDrawRect(float x, float y, float w, float h, unsigned int color)
{
addGfxCmdRect(x, y, w, h, color);
}
void imguiDrawRoundedRect(float x, float y, float w, float h, float r, unsigned int color)
{
addGfxCmdRoundedRect(x, y, w, h, r, color);
}

110
gltools/@contrib/imgui.h Normal file
View file

@ -0,0 +1,110 @@
//
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef IMGUI_H
#define IMGUI_H
enum imguiMouseButton
{
IMGUI_MBUT_LEFT = 0x01,
IMGUI_MBUT_RIGHT = 0x02,
};
enum imguiTextAlign
{
IMGUI_ALIGN_LEFT,
IMGUI_ALIGN_CENTER,
IMGUI_ALIGN_RIGHT,
};
inline unsigned int imguiRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a=255)
{
return (r) | (g << 8) | (b << 16) | (a << 24);
}
bool imguiAnyActive();
void imguiBeginFrame(int mx, int my, unsigned char mbut, int scroll);
void imguiEndFrame();
bool imguiBeginScrollArea(const char* name, int x, int y, int w, int h, int* scroll);
void imguiEndScrollArea();
bool imguiButton(const char* text, bool enabled = true);
bool imguiItem(const char* text, bool enabled = true);
bool imguiCheck(const char* text, bool checked, bool enabled = true);
bool imguiCollapse(const char* text, const char* subtext, bool checked, bool enabled = true);
void imguiLabel(const char* text);
void imguiValue(const char* text);
bool imguiSlider(const char* text, float* val, float vmin, float vmax, float vinc, bool enabled = true);
void imguiIndent();
void imguiUnindent();
void imguiSeparator();
void imguiSeparatorLine();
void imguiDrawText(int x, int y, int align, const char* text, unsigned int color);
void imguiDrawLine(float x0, float y0, float x1, float y1, float r, unsigned int color);
void imguiDrawRoundedRect(float x, float y, float w, float h, float r, unsigned int color);
void imguiDrawRect(float x, float y, float w, float h, unsigned int color);
// Pull render interface.
enum imguiGfxCmdType
{
IMGUI_GFXCMD_RECT,
IMGUI_GFXCMD_TRIANGLE,
IMGUI_GFXCMD_LINE,
IMGUI_GFXCMD_TEXT,
IMGUI_GFXCMD_SCISSOR,
};
struct imguiGfxRect
{
short x,y,w,h,r;
};
struct imguiGfxText
{
short x,y,align;
const char* text;
};
struct imguiGfxLine
{
short x0,y0,x1,y1,r;
};
struct imguiGfxCmd
{
char type;
char flags;
char pad[2];
unsigned int col;
union
{
imguiGfxLine line;
imguiGfxRect rect;
imguiGfxText text;
};
};
const imguiGfxCmd* imguiGetRenderQueue();
int imguiGetRenderQueueSize();
#endif // IMGUI_H

View file

@ -0,0 +1,376 @@
//
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#define _USE_MATH_DEFINES
#include <stdio.h>
#include <math.h>
#include "imgui.h"
#include "fontstash.h"
#include "GLTools.h"
// Some math headers don't have PI defined.
static const float PI = 3.14159265f;
static const unsigned TEMP_COORD_COUNT = 100;
static float g_tempCoords[TEMP_COORD_COUNT*2];
static float g_tempNormals[TEMP_COORD_COUNT*2];
static const int CIRCLE_VERTS = 8*4;
static float g_circleVerts[CIRCLE_VERTS*2];
inline unsigned int RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{
return (r) | (g << 8) | (b << 16) | (a << 24);
}
static void drawPolygon(const float* coords, unsigned numCoords, float r, unsigned int col)
{
if (numCoords > TEMP_COORD_COUNT) numCoords = TEMP_COORD_COUNT;
for (unsigned i = 0, j = numCoords-1; i < numCoords; j=i++)
{
const float* v0 = &coords[j*2];
const float* v1 = &coords[i*2];
float dx = v1[0] - v0[0];
float dy = v1[1] - v0[1];
float d = sqrtf(dx*dx+dy*dy);
if (d > 0)
{
d = 1.0f/d;
dx *= d;
dy *= d;
}
g_tempNormals[j*2+0] = dy;
g_tempNormals[j*2+1] = -dx;
}
for (unsigned i = 0, j = numCoords-1; i < numCoords; j=i++)
{
float dlx0 = g_tempNormals[j*2+0];
float dly0 = g_tempNormals[j*2+1];
float dlx1 = g_tempNormals[i*2+0];
float dly1 = g_tempNormals[i*2+1];
float dmx = (dlx0 + dlx1) * 0.5f;
float dmy = (dly0 + dly1) * 0.5f;
float dmr2 = dmx*dmx + dmy*dmy;
if (dmr2 > 0.000001f)
{
float scale = 1.0f / dmr2;
if (scale > 10.0f) scale = 10.0f;
dmx *= scale;
dmy *= scale;
}
g_tempCoords[i*2+0] = coords[i*2+0]+dmx*r;
g_tempCoords[i*2+1] = coords[i*2+1]+dmy*r;
}
unsigned int colTrans = RGBA(col&0xff, (col>>8)&0xff, (col>>16)&0xff, 0);
glBegin(GL_TRIANGLES);
glColor4ubv((GLubyte*)&col);
for (unsigned i = 0, j = numCoords-1; i < numCoords; j=i++)
{
glVertex2fv(&coords[i*2]);
glVertex2fv(&coords[j*2]);
glColor4ubv((GLubyte*)&colTrans);
glVertex2fv(&g_tempCoords[j*2]);
glVertex2fv(&g_tempCoords[j*2]);
glVertex2fv(&g_tempCoords[i*2]);
glColor4ubv((GLubyte*)&col);
glVertex2fv(&coords[i*2]);
}
glColor4ubv((GLubyte*)&col);
for (unsigned i = 2; i < numCoords; ++i)
{
glVertex2fv(&coords[0]);
glVertex2fv(&coords[(i-1)*2]);
glVertex2fv(&coords[i*2]);
}
glEnd();
}
static void drawRect(float x, float y, float w, float h, float fth, unsigned int col)
{
float verts[4*2] =
{
x+0.5f, y+0.5f,
x+w-0.5f, y+0.5f,
x+w-0.5f, y+h-0.5f,
x+0.5f, y+h-0.5f,
};
drawPolygon(verts, 4, fth, col);
}
static void drawRoundedRect(float x, float y, float w, float h, float r, float fth, unsigned int col)
{
const unsigned n = CIRCLE_VERTS/4;
float verts[(n+1)*4*2];
const float* cverts = g_circleVerts;
float* v = verts;
for (unsigned i = 0; i <= n; ++i)
{
*v++ = x+w-r + cverts[i*2]*r;
*v++ = y+h-r + cverts[i*2+1]*r;
}
for (unsigned i = n; i <= n*2; ++i)
{
*v++ = x+r + cverts[i*2]*r;
*v++ = y+h-r + cverts[i*2+1]*r;
}
for (unsigned i = n*2; i <= n*3; ++i)
{
*v++ = x+r + cverts[i*2]*r;
*v++ = y+r + cverts[i*2+1]*r;
}
for (unsigned i = n*3; i < n*4; ++i)
{
*v++ = x+w-r + cverts[i*2]*r;
*v++ = y+r + cverts[i*2+1]*r;
}
*v++ = x+w-r + cverts[0]*r;
*v++ = y+r + cverts[1]*r;
drawPolygon(verts, (n+1)*4, fth, col);
}
static void drawLine(float x0, float y0, float x1, float y1, float r, float fth, unsigned int col)
{
float dx = x1-x0;
float dy = y1-y0;
float d = sqrtf(dx*dx+dy*dy);
if (d > 0.0001f)
{
d = 1.0f/d;
dx *= d;
dy *= d;
}
float nx = dy;
float ny = -dx;
float verts[4*2];
r -= fth;
r *= 0.5f;
if (r < 0.01f) r = 0.01f;
dx *= r;
dy *= r;
nx *= r;
ny *= r;
verts[0] = x0-dx-nx;
verts[1] = y0-dy-ny;
verts[2] = x0-dx+nx;
verts[3] = y0-dy+ny;
verts[4] = x1+dx+nx;
verts[5] = y1+dy+ny;
verts[6] = x1+dx-nx;
verts[7] = y1+dy-ny;
drawPolygon(verts, 4, fth, col);
}
void imguiRenderGLInit(void)
{
for (int i = 0; i < CIRCLE_VERTS; ++i)
{
float a = (float)i/(float)CIRCLE_VERTS * PI*2;
g_circleVerts[i*2+0] = cosf(a);
g_circleVerts[i*2+1] = sinf(a);
}
return true;
}
static void drawText(float x, float y, const char *text, int align, unsigned int col)
{
float minx, miny, maxx, maxy, dx, hsize;
if (!_fonts) return;
if (align != IMGUI_ALIGN_LEFT) {
// adjust for alignment
sth_dim_text(_fonts, 0, 15.0f, text, &minx, &miny, &maxx, &maxy);
hsize = maxx - minx;
if (align == IMGUI_ALIGN_CENTER)
x -= hsize/2;
else if (align == IMGUI_ALIGN_RIGHT)
x -= hsize;
}
glColor4ub(col&0xff, (col>>8)&0xff, (col>>16)&0xff, (col>>24)&0xff);
sth_begin_draw(_fonts);
sth_draw_text(_fonts, 0, 15.0f, x, y, text, &dx);
sth_end_draw(_fonts);
}
/*
static void drawText(float x, float y, const char *text, int align, unsigned int col)
{
if (!g_ftex) return;
if (!text) return;
if (align == IMGUI_ALIGN_CENTER)
x -= getTextLength(g_cdata, text)/2;
else if (align == IMGUI_ALIGN_RIGHT)
x -= getTextLength(g_cdata, text);
glColor4ub(col&0xff, (col>>8)&0xff, (col>>16)&0xff, (col>>24)&0xff);
glEnable(GL_TEXTURE_2D);
// assume orthographic projection with units = screen pixels, origin at top left
glBindTexture(GL_TEXTURE_2D, g_ftex);
glBegin(GL_TRIANGLES);
const float ox = x;
while (*text)
{
int c = (unsigned char)*text;
if (c == '\t')
{
for (int i = 0; i < 4; ++i)
{
if (x < g_tabStops[i]+ox)
{
x = g_tabStops[i]+ox;
break;
}
}
}
else if (c >= 32 && c < 128)
{
stbtt_aligned_quad q;
getBakedQuad(g_cdata, 512,512, c-32, &x,&y,&q);
glTexCoord2f(q.s0, q.t0);
glVertex2f(q.x0, q.y0);
glTexCoord2f(q.s1, q.t1);
glVertex2f(q.x1, q.y1);
glTexCoord2f(q.s1, q.t0);
glVertex2f(q.x1, q.y0);
glTexCoord2f(q.s0, q.t0);
glVertex2f(q.x0, q.y0);
glTexCoord2f(q.s0, q.t1);
glVertex2f(q.x0, q.y1);
glTexCoord2f(q.s1, q.t1);
glVertex2f(q.x1, q.y1);
}
++text;
}
glEnd();
glDisable(GL_TEXTURE_2D);
}
*/
void imguiRenderGLDraw()
{
const imguiGfxCmd* q = imguiGetRenderQueue();
int nq = imguiGetRenderQueueSize();
const float s = 1.0f/8.0f;
glDisable(GL_SCISSOR_TEST);
for (int i = 0; i < nq; ++i)
{
const imguiGfxCmd& cmd = q[i];
if (cmd.type == IMGUI_GFXCMD_RECT)
{
if (cmd.rect.r == 0)
{
drawRect((float)cmd.rect.x*s+0.5f, (float)cmd.rect.y*s+0.5f,
(float)cmd.rect.w*s-1, (float)cmd.rect.h*s-1,
1.0f, cmd.col);
}
else
{
drawRoundedRect((float)cmd.rect.x*s+0.5f, (float)cmd.rect.y*s+0.5f,
(float)cmd.rect.w*s-1, (float)cmd.rect.h*s-1,
(float)cmd.rect.r*s, 1.0f, cmd.col);
}
}
else if (cmd.type == IMGUI_GFXCMD_LINE)
{
drawLine(cmd.line.x0*s, cmd.line.y0*s, cmd.line.x1*s, cmd.line.y1*s, cmd.line.r*s, 1.0f, cmd.col);
}
else if (cmd.type == IMGUI_GFXCMD_TRIANGLE)
{
if (cmd.flags == 1)
{
const float verts[3*2] =
{
(float)cmd.rect.x*s+0.5f, (float)cmd.rect.y*s+0.5f,
(float)cmd.rect.x*s+0.5f+(float)cmd.rect.w*s-1, (float)cmd.rect.y*s+0.5f+(float)cmd.rect.h*s/2-0.5f,
(float)cmd.rect.x*s+0.5f, (float)cmd.rect.y*s+0.5f+(float)cmd.rect.h*s-1,
};
drawPolygon(verts, 3, 1.0f, cmd.col);
}
if (cmd.flags == 2)
{
const float verts[3*2] =
{
(float)cmd.rect.x*s+0.5f, (float)cmd.rect.y*s+0.5f+(float)cmd.rect.h*s-1,
(float)cmd.rect.x*s+0.5f+(float)cmd.rect.w*s/2-0.5f, (float)cmd.rect.y*s+0.5f,
(float)cmd.rect.x*s+0.5f+(float)cmd.rect.w*s-1, (float)cmd.rect.y*s+0.5f+(float)cmd.rect.h*s-1,
};
drawPolygon(verts, 3, 1.0f, cmd.col);
}
if (cmd.flags == 3) // @rlyeh new rotation: left
{
const float verts[3*2] =
{
(float)cmd.rect.x*s+0.5f+(float)cmd.rect.w*s-1, (float)cmd.rect.y*s+0.5f,
(float)cmd.rect.x*s+0.5f+(float)cmd.rect.w*s-1, (float)cmd.rect.y*s+0.5f+(float)cmd.rect.h*s-1,
(float)cmd.rect.x*s+0.5f, (float)cmd.rect.y*s+0.5f+(float)cmd.rect.h*s/2-0.5f,
};
drawPolygon(verts, 3, 1.0f, cmd.col);
}
}
else if (cmd.type == IMGUI_GFXCMD_TEXT)
{
drawText(cmd.text.x, cmd.text.y, cmd.text.text, cmd.text.align, cmd.col);
}
else if (cmd.type == IMGUI_GFXCMD_SCISSOR)
{
if (cmd.flags)
{
glEnable(GL_SCISSOR_TEST);
glScissor(cmd.rect.x, cmd.rect.y, cmd.rect.w, cmd.rect.h);
}
else
{
glDisable(GL_SCISSOR_TEST);
}
}
}
glDisable(GL_SCISSOR_TEST);
}

View file

@ -0,0 +1,25 @@
//
// Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef IMGUI_RENDER_GL_H
#define IMGUI_RENDER_GL_H
void imguiRenderGLInit();
void imguiRenderGLDraw();
#endif // IMGUI_RENDER_GL_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,61 @@
# -*- coding: utf-8 -*-
#
# This file is part of gltools - See LICENSE.txt
#
cdef class ClientBuffer:
'''
Abstraction of OpenGL vertex buffer
'''
def __init__(self, target = GL_ARRAY_BUFFER):
if not isGLExtLoaded:
raise GLError('OpenGL 2.1 function pointers not found')
self.thisptr = new c_ClientBuffer(target)
def __dealloc__(self):
cdef c_ClientBuffer *tmp
if self.thisptr != NULL:
tmp = <c_ClientBuffer *>self.thisptr
del tmp
def __str__(self):
return "ClientBuffer%s" % repr(self)
def __repr__(self):
return "()"
cpdef bind(self):
cdef c_ClientBuffer *buf = <c_ClientBuffer *>self.thisptr
buf.bind()
cpdef unBind(self):
cdef c_ClientBuffer *buf = <c_ClientBuffer *>self.thisptr
buf.unBind()
cpdef setDataType(self, int type, int dataType, int dataTypeSize,
int stride, size_t pointer):
'''
Set datatye for data in buffer. Pointer is an integer with an
offset into the buffer with optional stride.
'''
cdef c_ClientBuffer *buf = <c_ClientBuffer *>self.thisptr
if not buf.setDataType(type, dataType, dataTypeSize, stride, pointer):
raise GLError(errorMessage)
cdef cloadData(self, void *data, ssize_t size, ssize_t offset, int usage):
cdef c_ClientBuffer *buf = <c_ClientBuffer *>self.thisptr
if not buf.loadData(data, size, offset, usage):
raise GLError(errorMessage)
cpdef loadData(self, data, ssize_t size, ssize_t offset = 0, int usage = GL_STATIC_DRAW):
'''
Upload data to client side buffer. Passing None
for data will reserve capacity.
'''
if data is None:
self.cloadData(NULL, size, offset, usage)
else:
self.cloadData(getVoidPtr(data), size, offset, usage)

192
gltools/@src/Color.pxi Normal file
View file

@ -0,0 +1,192 @@
# -*- coding: utf-8 -*-
#
# This file is part of gltools - See LICENSE.txt
#
cdef class ColorRGBA:
'''RGBA color'''
def __init__(self, GLubyte red = 255, GLubyte green = 255, GLubyte blue = 255,
GLubyte alpha = 255):
self.red = red
self.green = green
self.blue = blue
self.alpha = alpha
def __str__(self):
return "ColorRGBA%s" % repr(self)
def __repr__(self):
args = self.red, self.green, self.blue, self.alpha
return "(red=%d, green=%d, blue=%d, alpha=%d)" % args
def __len__(self):
return 4
def __getitem__(self, int key):
if key == 0:
return self.red
elif key == 1:
return self.green
elif key == 2:
return self.blue
elif key == 3:
return self.alpha
raise IndexError('index out of range')
def __mul__(double factor, ColorRGBA rhs):
'''
Leaves alpha unchanged
'''
cdef ColorRGBA ret = ColorRGBA.__new__(ColorRGBA)
if factor < 0.:
raise GLError('factor < 0.')
ret.red = <unsigned char>fmin(255, factor*rhs.red)
ret.green = <unsigned char>fmin(255, factor*rhs.green)
ret.blue = <unsigned char>fmin(255, factor*rhs.blue)
ret.alpha = rhs.alpha
return ret
cpdef ColorRGBA copy(self, int red = -1, int green = -1, int blue = -1, alpha = -1):
cdef ColorRGBA ret = ColorRGBA.__new__(ColorRGBA)
ret.red = self.red
ret.green = self.green
ret.blue = self.blue
ret.alpha = self.alpha
if red >= 0 and red < 256:
ret.red = red
if green >= 0 and green < 256:
ret.green = green
if blue >= 0 and blue < 256:
ret.blue = blue
if alpha >= 0 and alpha < 256:
ret.alpha = alpha
return ret
cpdef unsigned toInt(self):
return self.alpha << 24 | self.blue << 16 | self.green << 8 | self.red
cpdef tuple toFloatVector(self):
return (self.red / 255., self.green / 255., self.blue / 255., self.alpha / 255.)
cdef setFloatVector(self, float *vec):
vec[0] = self.red / 255.
vec[1] = self.green / 255.
vec[2] = self.blue / 255.
vec[3] = self.alpha / 255.
WHITE = ColorRGBA(255,255,255,255)
BLACK = ColorRGBA(0,0,0,255)
cdef class Material:
'''
Abstrction of OpenGL material
'''
def __init__(self, int mode = GL_FRONT_AND_BACK, **kwargs):
self.mode = mode
self.shininess = -1.
for name, value in kwargs.iteritems():
if name in {'ambient','diffuse','specular','emissive','shininess'}:
setattr(self, name, value)
else:
raise GLError("attribute '%s' not known")
def __str__(self):
return "Material%s" % repr(self)
def __repr__(self):
return "()"
cpdef enable(self):
cdef float mat[4]
cdef int i
if not self.ambient is None:
self.ambient.setFloatVector(mat)
glMaterialfv(self.mode, GL_AMBIENT, mat)
if not self.diffuse is None:
self.diffuse.setFloatVector(mat)
glMaterialfv(self.mode, GL_DIFFUSE, mat)
if not self.specular is None:
self.specular.setFloatVector(mat)
glMaterialfv(self.mode, GL_SPECULAR, mat)
if not self.emissive is None:
self.emissive.setFloatVector(mat)
glMaterialfv(self.mode, GL_EMISSION, mat)
if self.shininess > 0:
mat[0] = fmin(fmax(0., self.shininess), 128)
glMaterialfv(self.mode, GL_SHININESS, mat)
cdef class Light:
'''
Abstraction of OpenGL light
'''
def __init__(self, int index = 0, Material material = None,
Point position = None, directional = True):
if index == 0:
self.index = GL_LIGHT0
elif index == 1:
self.index = GL_LIGHT1
elif index == 2:
self.index = GL_LIGHT2
elif index == 3:
self.index = GL_LIGHT3
elif index == 4:
self.index = GL_LIGHT4
elif index == 5:
self.index = GL_LIGHT5
elif index == 6:
self.index = GL_LIGHT6
elif index == 7:
self.index = GL_LIGHT7
else:
raise GLError('Light index out of range (0-7)')
self.material = material
self.position = position
self.directional = directional
def __str__(self):
return "Light%s" % repr(self)
def __repr__(self):
return "()"
cpdef enable(self):
cdef float mat[4]
glEnable(self.index)
if not self.material.ambient is None:
self.material.ambient.setFloatVector(mat)
glLightfv(self.index, GL_AMBIENT, mat)
if not self.material.diffuse is None:
self.material.diffuse.setFloatVector(mat)
glLightfv(self.index, GL_DIFFUSE, mat)
if not self.material.specular is None:
self.material.specular.setFloatVector(mat)
glLightfv(self.index, GL_SPECULAR, mat)
if not self.position is None:
mat[0], mat[1], mat[2] = self.position
if self.directional:
mat[3] = 0.
else:
mat[3] = 1.
glLightfv(self.index, GL_POSITION, mat)
cpdef disable(self):
glDisable(self.index)

186
gltools/@src/Constants.pxi Normal file
View file

@ -0,0 +1,186 @@
# -*- coding: utf-8 -*-
class ACTION:
RELEASE = GLFW_RELEASE
PRESS = GLFW_PRESS
class KEY:
ESCAPE = GLFW_KEY_ESCAPE
ENTER = GLFW_KEY_ENTER
TAB = GLFW_KEY_TAB
BACKSPACE = GLFW_KEY_BACKSPACE
INSERT = GLFW_KEY_INSERT
DELETE = GLFW_KEY_DELETE
RIGHT = GLFW_KEY_RIGHT
LEFT = GLFW_KEY_LEFT
DOWN = GLFW_KEY_DOWN
UP = GLFW_KEY_UP
PAGE_UP = GLFW_KEY_PAGE_UP
PAGE_DOWN = GLFW_KEY_PAGE_DOWN
HOME = GLFW_KEY_HOME
END = GLFW_KEY_END
CAPS_LOCK = GLFW_KEY_CAPS_LOCK
SCROLL_LOCK = GLFW_KEY_SCROLL_LOCK
NUM_LOCK = GLFW_KEY_NUM_LOCK
PRINT_SCREEN = GLFW_KEY_PRINT_SCREEN
PAUSE = GLFW_KEY_PAUSE
F1 = GLFW_KEY_F1
F2 = GLFW_KEY_F2
F3 = GLFW_KEY_F3
F4 = GLFW_KEY_F4
F5 = GLFW_KEY_F5
F6 = GLFW_KEY_F6
F7 = GLFW_KEY_F7
F8 = GLFW_KEY_F8
F9 = GLFW_KEY_F9
F10 = GLFW_KEY_F10
F11 = GLFW_KEY_F11
F12 = GLFW_KEY_F12
class MOUSE:
LEFT = GLFW_MOUSE_BUTTON_LEFT
RIGHT = GLFW_MOUSE_BUTTON_RIGHT
MIDDLE = GLFW_MOUSE_BUTTON_MIDDLE
# AlphaFunction
NEVER = GL_NEVER
LESS = GL_LESS
EQUAL = GL_EQUAL
LEQUAL = GL_LEQUAL
GREATER = GL_GREATER
NOTEQUAL = GL_NOTEQUAL
GEQUAL = GL_GEQUAL
ALWAYS = GL_ALWAYS
# AttribMask
CURRENT_BIT = GL_CURRENT_BIT
POINT_BIT = GL_POINT_BIT
LINE_BIT = GL_LINE_BIT
POLYGON_BIT = GL_POLYGON_BIT
POLYGON_STIPPLE_BIT = GL_POLYGON_STIPPLE_BIT
PIXEL_MODE_BIT = GL_PIXEL_MODE_BIT
LIGHTING_BIT = GL_LIGHTING_BIT
FOG_BIT = GL_FOG_BIT
DEPTH_BUFFER_BIT = GL_DEPTH_BUFFER_BIT
ACCUM_BUFFER_BIT = GL_ACCUM_BUFFER_BIT
STENCIL_BUFFER_BIT = GL_STENCIL_BUFFER_BIT
VIEWPORT_BIT = GL_VIEWPORT_BIT
TRANSFORM_BIT = GL_TRANSFORM_BIT
ENABLE_BIT = GL_ENABLE_BIT
COLOR_BUFFER_BIT = GL_COLOR_BUFFER_BIT
HINT_BIT = GL_HINT_BIT
EVAL_BIT = GL_EVAL_BIT
LIST_BIT = GL_LIST_BIT
TEXTURE_BIT = GL_TEXTURE_BIT
SCISSOR_BIT = GL_SCISSOR_BIT
ALL_ATTRIB_BITS = GL_ALL_ATTRIB_BITS
# BeginMode
POINTS = GL_POINTS
LINES = GL_LINES
LINE_LOOP = GL_LINE_LOOP
LINE_STRIP = GL_LINE_STRIP
TRIANGLES = GL_TRIANGLES
TRIANGLE_STRIP = GL_TRIANGLE_STRIP
TRIANGLE_FAN = GL_TRIANGLE_FAN
QUADS = GL_QUADS
QUAD_STRIP = GL_QUAD_STRIP
POLYGON = GL_POLYGON
# Vertex Arrays
VERTEX_ARRAY = GL_VERTEX_ARRAY
NORMAL_ARRAY = GL_NORMAL_ARRAY
COLOR_ARRAY = GL_COLOR_ARRAY
INDEX_ARRAY = GL_INDEX_ARRAY
TEXTURE_COORD_ARRAY = GL_TEXTURE_COORD_ARRAY
EDGE_FLAG_ARRAY = GL_EDGE_FLAG_ARRAY
# BlendingFactorDest
ZERO = GL_ZERO
ONE = GL_ONE
SRC_COLOR = GL_SRC_COLOR
ONE_MINUS_SRC_COLOR = GL_ONE_MINUS_SRC_COLOR
SRC_ALPHA = GL_SRC_ALPHA
ONE_MINUS_SRC_ALPHA = GL_ONE_MINUS_SRC_ALPHA
DST_ALPHA = GL_DST_ALPHA
ONE_MINUS_DST_ALPHA = GL_ONE_MINUS_DST_ALPHA
# BlendingFactorSrc
DST_COLOR = GL_DST_COLOR
ONE_MINUS_DST_COLOR = GL_ONE_MINUS_DST_COLOR
SRC_ALPHA_SATURATE = GL_SRC_ALPHA_SATURATE
# Boolean values
FALSE = GL_FALSE
TRUE = GL_TRUE
BYTE = GL_BYTE
UNSIGNED_BYTE = GL_UNSIGNED_BYTE
SHORT = GL_SHORT
UNSIGNED_SHORT = GL_UNSIGNED_SHORT
INT = GL_INT
UNSIGNED_INT = GL_UNSIGNED_INT
FLOAT = GL_FLOAT
DOUBLE = GL_DOUBLE
# DrawBufferMode
NONE = GL_NONE
FRONT_LEFT = GL_FRONT_LEFT
FRONT_RIGHT = GL_FRONT_RIGHT
BACK_LEFT = GL_BACK_LEFT
BACK_RIGHT = GL_BACK_RIGHT
FRONT = GL_FRONT
BACK = GL_BACK
LEFT = GL_LEFT
RIGHT = GL_RIGHT
FRONT_AND_BACK = GL_FRONT_AND_BACK
AUX0 = GL_AUX0
AUX1 = GL_AUX1
AUX2 = GL_AUX2
AUX3 = GL_AUX3
CW = GL_CW
CCW = GL_CCW
# GetTarget
DEPTH_TEST = GL_DEPTH_TEST
BLEND = GL_BLEND
DITHER = GL_DITHER
CULL_FACE = GL_CULL_FACE
# MatrixMode
MODELVIEW = GL_MODELVIEW
PROJECTION = GL_PROJECTION
TEXTURE = GL_TEXTURE
# Lines
LINE_SMOOTH = GL_LINE_SMOOTH
# PolygonMode
POINT = GL_POINT
LINE = GL_LINE
FILL = GL_FILL
# ShadingModel
FLAT = GL_FLAT
SMOOTH = GL_SMOOTH
# Lighting
LIGHTING = GL_LIGHTING
LIGHT0 = GL_LIGHT0
LIGHT1 = GL_LIGHT1
LIGHT2 = GL_LIGHT2
LIGHT3 = GL_LIGHT3
LIGHT4 = GL_LIGHT4
LIGHT5 = GL_LIGHT5
LIGHT6 = GL_LIGHT6
LIGHT7 = GL_LIGHT7
LIGHT_MODEL_TWO_SIDE = GL_LIGHT_MODEL_TWO_SIDE
# Texture
TEXTURE_2D = GL_TEXTURE_2D
# glext.h
MULTISAMPLE = GL_MULTISAMPLE
STATIC_DRAW = GL_STATIC_DRAW
ARRAY_BUFFER = GL_ARRAY_BUFFER
ELEMENT_ARRAY_BUFFER = GL_ELEMENT_ARRAY_BUFFER

95
gltools/@src/GL.pxi Normal file
View file

@ -0,0 +1,95 @@
# -*- coding: utf-8 -*-
#
# This file is part of gltools - See LICENSE.txt
#
from glLib cimport *
# init OpenGL function pointers
cpdef InitGLExt():
if not c_initGLExt():
raise GLError(errorMessage)
cpdef BlendFunc(unsigned int sfactor, unsigned int dfactor):
glBlendFunc(sfactor, dfactor)
cpdef Clear(unsigned int mask):
glClear(mask)
cpdef ClearColor(ColorRGBA col):
glClearColor(col.red / 255., col.green / 255., col.blue / 255., col.alpha / 255.)
cpdef ClearDepth(double depth):
glClearDepth(depth)
cpdef Color(ColorRGBA col):
glColor4ub(col.red, col.green, col.blue, col.alpha )
cpdef Disable(unsigned int cap):
glDisable(cap)
cpdef DrawArrays(unsigned int mode, int first, int count):
glDrawArrays(mode, first, count)
cpdef DrawElements(unsigned int mode, int count, int type, indices):
cdef size_t offset
if isinstance(indices, int):
offset = indices
glDrawElements(mode, count, type, <void *>offset)
else:
glDrawElements(mode, count, type, getVoidPtr(indices))
cpdef Enable(unsigned int cap):
glEnable(cap)
cpdef LineWidth(float width):
glLineWidth(width)
cpdef LightModeli(int pname, int param):
glLightModeli(pname, param)
cpdef LoadIdentity():
glLoadIdentity()
cpdef LoadMatrixd(Transform tr):
cdef double cm[16]
# col 1
cm[0] = tr.m[0][0]
cm[1] = tr.m[1][0]
cm[2] = tr.m[2][0]
cm[3] = tr.m[3][0]
# col 2
cm[4] = tr.m[0][1]
cm[5] = tr.m[1][1]
cm[6] = tr.m[2][1]
cm[7] = tr.m[3][1]
# col 3
cm[8] = tr.m[0][2]
cm[9] = tr.m[1][2]
cm[10] = tr.m[2][2]
cm[11] = tr.m[3][2]
# col 4
cm[12] = tr.m[0][3]
cm[13] = tr.m[1][3]
cm[14] = tr.m[2][3]
cm[15] = tr.m[3][3]
glLoadMatrixd(cm)
cpdef MatrixMode(unsigned int mode):
glMatrixMode(mode)
cpdef Ortho(double left, double right, double bottom, double top, double zNear,
double zFar):
glOrtho(left, right, bottom, top, zNear, zFar)
cpdef PolygonMode(unsigned int face, unsigned int mode):
glPolygonMode(face, mode)
cpdef Viewport(int x, int y, int width, int height):
glViewport(x, y, width, height)

266
gltools/@src/GLFW.pxi Normal file
View file

@ -0,0 +1,266 @@
# -*- coding: utf-8 -*-
from glfwLib cimport *
cpdef Init():
if not glfwInit():
raise GLError('failed to initialize glfw')
# timer functions
cpdef double getTime():
Init()
return glfwGetTime()
cpdef SetTime(double time):
Init()
glfwSetTime(time)
# gamma value
cpdef SetGamma(float gamma):
Init()
glfwSetGamma(gamma)
# get desktop size
cpdef tuple GetDesktopSize():
cdef GLFWvidmode vidmode
Init()
glfwGetDesktopMode(&vidmode)
return vidmode.width, vidmode.height
cdef class Window:
def __init__(self, int width = -1, int height = -1, title = None,
bint fullscreen = False):
cdef GLFWvidmode vidmode
cdef int mode = GLFW_WINDOWED
cdef char *c_title
# Initialise GLFW
if not glfwInit():
raise GLError('failed to initialize glfw')
# set window hints
glfwWindowHint(GLFW_RED_BITS, 8)
glfwWindowHint(GLFW_GREEN_BITS, 8)
glfwWindowHint(GLFW_BLUE_BITS, 8)
glfwWindowHint(GLFW_ALPHA_BITS, 8)
glfwWindowHint(GLFW_DEPTH_BITS, 24)
glfwWindowHint(GLFW_STENCIL_BITS, 8)
glfwWindowHint(GLFW_OPENGL_VERSION_MAJOR, 2)
glfwWindowHint(GLFW_OPENGL_VERSION_MINOR, 1)
# open window
if width < 0 or height < 0:
# default to desktop size
glfwGetDesktopMode(&vidmode)
width, height = vidmode.width, vidmode.height
glfwWindowHint(GLFW_RED_BITS, vidmode.redBits)
glfwWindowHint(GLFW_GREEN_BITS, vidmode.greenBits)
glfwWindowHint(GLFW_BLUE_BITS, vidmode.blueBits)
if fullscreen:
mode = GLFW_FULLSCREEN
# decode to UTF-8
if title is None:
title = ''
bytetext = unicode(title).encode('UTF-8','ignore')
c_title = bytetext
self.thisptr = glfwCreateWindow(width, height, mode, c_title, NULL)
if self.thisptr == NULL:
raise GLError('failed to open window')
# Set pointer back to this class for callbacks
glfwSetWindowUserPointer(<GLFWwindow>self.thisptr, <void *>self)
# Set callback functions
glfwSetWindowSizeCallback(cb_onSize)
glfwSetWindowRefreshCallback(cb_onRefresh)
glfwSetMouseButtonCallback(cb_onMouseButton)
glfwSetKeyCallback(cb_onKey)
glfwSetCharCallback(cb_onChar)
glfwSetWindowCloseCallback(cb_onClose)
glfwSetWindowFocusCallback(cb_onFocus)
glfwSetCursorEnterCallback(cb_onEnter)
glfwSetScrollCallback(cb_onScroll)
glfwSetWindowIconifyCallback(cb_onIconify)
# Get window size (may be different than the requested size)
glfwGetWindowSize(<GLFWwindow>self.thisptr, &width, &height);
self.onSize(width, max(1, height))
def __dealloc__(self):
glfwTerminate()
cpdef setTitle(self, title):
cdef char *c_title
# decode to UTF-8
bytetext = unicode(title).encode('UTF-8','ignore')
c_title = bytetext
glfwSetWindowTitle(<GLFWwindow>self.thisptr, c_title)
cpdef tuple getSize(self):
cdef int width, height
glfwGetWindowSize(<GLFWwindow>self.thisptr, &width, &height)
return width, height
cpdef setSize(self, int width, int height):
if width <= 0 or height <= 0:
raise GLError('window size not valid')
glfwSetWindowSize(<GLFWwindow>self.thisptr, width, height)
cpdef tuple getPos(self):
cdef int x, y
glfwGetWindowPos(<GLFWwindow>self.thisptr, &x, &y)
return x, y
cpdef setPos(self, int x, int y):
glfwSetWindowPos(<GLFWwindow>self.thisptr, x, y)
cpdef setClipboard(self, content):
glfwSetClipboardString(<GLFWwindow>self.thisptr, content)
cpdef getClipboard(self):
cdef char *content = glfwGetClipboardString(<GLFWwindow>self.thisptr)
return content
cpdef iconify(self):
glfwIconifyWindow(<GLFWwindow>self.thisptr)
cpdef restore(self):
glfwRestoreWindow(<GLFWwindow>self.thisptr)
cpdef show(self):
glfwShowWindow(<GLFWwindow>self.thisptr)
cpdef hide(self):
glfwHideWindow(<GLFWwindow>self.thisptr)
cpdef close(self):
self.running = False
glfwDestroyWindow(<GLFWwindow>self.thisptr)
glfwTerminate()
cpdef makeContextCurrent(self):
glfwMakeContextCurrent(<GLFWwindow>self.thisptr)
cpdef swapBuffers(self):
glfwSwapBuffers(<GLFWwindow>self.thisptr)
cpdef mainLoop(self):
# keep waiting for events until running is False
cdef int x, y, lastX, lastY
cdef double t
glfwGetCursorPos(<GLFWwindow>self.thisptr, &lastX, &lastY)
self.running = True
while True:
# Wait for new events
glfwWaitEvents()
# Avoid to quick update due to mouse move
glfwGetCursorPos(<GLFWwindow>self.thisptr, &x, &y)
if x != lastX or y != lastY:
# in mouse move
t = glfwGetTime()
while True and self.running:
glfwWaitEvents()
if glfwGetTime() - t > .025:
break
glfwGetCursorPos(<GLFWwindow>self.thisptr, &x, &y)
self.onCursorPos(x, y)
lastX, lastY = x, y
if not self.running:
break
cpdef onSize(self, int w, int h):
pass
cpdef onRefresh(self):
pass
cpdef onCursorPos(self, int x, int y):
pass
cpdef onMouseButton(self, int button, int action):
pass
cpdef onKey(self, int key, int action):
pass
cpdef onChar(self, ch):
pass
cpdef onFocus(self, int status):
pass
cpdef onEnter(self, int status):
pass
cpdef onScroll(self, double dx, double dy):
pass
cpdef onIconify(self, int status):
pass
cpdef bint onClose(self):
return False
# callback functions
cdef void cb_onSize(GLFWwindow window, int w, int h):
cdef Window self = <Window>glfwGetWindowUserPointer(window)
self.onSize(w, max(1, h))
cdef void cb_onRefresh(GLFWwindow window):
cdef Window self = <Window>glfwGetWindowUserPointer(window)
# avoid refresh when request closing
self.onRefresh()
cdef void cb_onMouseButton(GLFWwindow window, int button, int action):
cdef Window self = <Window>glfwGetWindowUserPointer(window)
self.onMouseButton(button, action)
cdef void cb_onKey(GLFWwindow window, int key, int action):
cdef Window self = <Window>glfwGetWindowUserPointer(window)
self.onKey(key, action)
cdef void cb_onChar(GLFWwindow window, int ch):
cdef Window self = <Window>glfwGetWindowUserPointer(window)
cdef char st[2]
st[0] = <char>(ch & 0xff)
st[1] = 0
self.onChar(st.decode('UTF-8', 'ignore'))
cdef void cb_onFocus(GLFWwindow window, int status):
cdef Window self = <Window>glfwGetWindowUserPointer(window)
self.onFocus(status)
cdef void cb_onEnter(GLFWwindow window, int status):
cdef Window self = <Window>glfwGetWindowUserPointer(window)
self.onEnter(status)
cdef void cb_onScroll(GLFWwindow window, double dx, double dy):
cdef Window self = <Window>glfwGetWindowUserPointer(window)
self.onScroll(dx, dy)
cdef void cb_onIconify(GLFWwindow window, int status):
cdef Window self = <Window>glfwGetWindowUserPointer(window)
self.onIconify(status)
cdef int cb_onClose(GLFWwindow window):
cdef Window self = <Window>glfwGetWindowUserPointer(window)
cdef int ret = self.onClose()
if ret:
self.running = False
return ret

441
gltools/@src/GLTools.cpp Normal file
View file

@ -0,0 +1,441 @@
#include "GLTools.h"
#include "fontstash.h"
// error handling
char errorMessage[256];
void setErrorMessage(const char *err) {
strncpy(errorMessage, err, 255);
}
// load font
void *_fonts;
void destroyFont(void)
{
sth_delete(_fonts);
_fonts = NULL;
}
int initFont(void)
{
_fonts = sth_create(512,512);
if (!_fonts) {
setErrorMessage("failed to initialize font structure");
printf("failed to initialize font structure\n");
return 0;
}
atexit(destroyFont);
if (!sth_add_font(_fonts, 0, NULL)) {
setErrorMessage("failed to initialize default font");
printf("failed to initialize default font\n");
return 0;
}
return 1;
}
int initText(void)
{
if (!_fonts) {
if (!initFont())
return 0;
}
return 1;
}
int beginText(void)
{
if (!_fonts) {
if (!initFont())
return 0;
}
sth_begin_draw(_fonts);
return 1;
}
int endText(void)
{
if (!_fonts) {
if (!initFont())
return 0;
}
sth_end_draw(_fonts);
return 1;
}
int drawText(int idx, float size, float x, float y, const char *text, float *dx)
{
if (!_fonts) {
if (!initFont())
return 0;
}
if (!sth_draw_text(_fonts, idx, size, x, y, text, dx)) {
setErrorMessage("failed to draw text string");
printf("failed to draw text string\n");
return 0;
}
return 1;
}
// opengl 2.1 extensions
#define GLEXTPROCSIZE 27
int isGLExtLoaded = 0;
int initGLExt(void)
{
// OpenGL 2.1 functions
int status = 0;
pglCreateShader = (PFNGLCREATESHADERPROC) glfwGetProcAddress("glCreateShader");
if (pglCreateShader) status++;
pglShaderSource = (PFNGLSHADERSOURCEPROC) glfwGetProcAddress("glShaderSource");
if (pglShaderSource) status++;
pglCompileShader = (PFNGLCOMPILESHADERPROC) glfwGetProcAddress("glCompileShader");
if (pglCompileShader) status++;
pglGetShaderiv = (PFNGLGETSHADERIVPROC) glfwGetProcAddress("glGetShaderiv");
if (pglGetShaderiv) status++;
pglGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) glfwGetProcAddress("glGetShaderInfoLog");
if (pglGetShaderInfoLog) status++;
pglDeleteShader = (PFNGLDELETESHADERPROC) glfwGetProcAddress("glDeleteShader");
if (pglDeleteShader) status++;
pglCreateProgram = (PFNGLCREATEPROGRAMPROC) glfwGetProcAddress("glCreateProgram");
if (pglCreateProgram) status++;
pglAttachShader = (PFNGLATTACHSHADERPROC) glfwGetProcAddress("glAttachShader");
if (pglAttachShader) status++;
pglLinkProgram = (PFNGLLINKPROGRAMPROC) glfwGetProcAddress("glLinkProgram");
if (pglLinkProgram) status++;
pglUseProgram = (PFNGLUSEPROGRAMPROC) glfwGetProcAddress("glUseProgram");
if (pglUseProgram) status++;
pglGetProgramiv = (PFNGLGETPROGRAMIVPROC) glfwGetProcAddress("glGetProgramiv");
if (pglGetProgramiv) status++;
pglGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) glfwGetProcAddress("glGetProgramInfoLog");
if (pglGetProgramInfoLog) status++;
pglDeleteProgram = (PFNGLDELETEPROGRAMPROC) glfwGetProcAddress("glDeleteProgram");
if (pglDeleteProgram) status++;
pglGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) glfwGetProcAddress("glGetUniformLocation");
if (pglGetUniformLocation) status++;
pglUniform1i = (PFNGLUNIFORM1IPROC) glfwGetProcAddress("glUniform1i");
if (pglUniform1i) status++;
pglUniform1f = (PFNGLUNIFORM1FPROC) glfwGetProcAddress("glUniform1f");
if (pglUniform1f) status++;
pglUniform4f = (PFNGLUNIFORM4FPROC) glfwGetProcAddress("glUniform4f");
if (pglUniform4f) status++;
pglUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) glfwGetProcAddress("glUniformMatrix4fv");
if (pglUniformMatrix4fv) status++;
pglGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) glfwGetProcAddress("glGetAttribLocation");
if (pglGetAttribLocation) status++;
pglGenBuffers = (PFNGLGENBUFFERSPROC) glfwGetProcAddress("glGenBuffers");
if (pglGenBuffers) status++;
pglDeleteBuffers = (PFNGLDELETEBUFFERSPROC) glfwGetProcAddress("glDeleteBuffers");
if (pglDeleteBuffers) status++;
pglBindBuffer = (PFNGLBINDBUFFERPROC) glfwGetProcAddress("glBindBuffer");
if (pglBindBuffer) status++;
pglBufferData = (PFNGLBUFFERDATAPROC) glfwGetProcAddress("glBufferData");
if (pglBufferData) status++;
pglBufferSubData = (PFNGLBUFFERSUBDATAPROC) glfwGetProcAddress("glBufferSubData");
if (pglBufferSubData) status++;
pglGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC) glfwGetProcAddress("glGetBufferParameteriv");
if (pglGetBufferParameteriv) status++;
pglEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) glfwGetProcAddress("glEnableVertexAttribArray");
if (pglEnableVertexAttribArray) status++;
pglVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) glfwGetProcAddress("glVertexAttribPointer");
if (pglVertexAttribPointer) status++;
if (status != GLEXTPROCSIZE) {
setErrorMessage("Failed to load OpenGL 2.1 function pointers");
return 0;
}
isGLExtLoaded = 1;
return 1;
}
// opengl buffer interface
ClientBuffer::ClientBuffer(GLenum target = GL_ARRAY_BUFFER) {
pglGenBuffers(1, &m_id);
m_target = target;
m_loaded = false;
for (unsigned i = 0; i < VERTEXBUFFERATTRIBSIZE; i++) {
m_attrib[i].enabled = 0;
}
}
ClientBuffer::~ClientBuffer() {
pglDeleteBuffers(1, &m_id);
}
void ClientBuffer::bind() {
pglBindBuffer(m_target, m_id);
if (m_target != GL_ARRAY_BUFFER)
return;
for (unsigned i = 0; i < VERTEXBUFFERATTRIBSIZE; i++) {
ClientBufferAttrib *attr = &m_attrib[i];
if(m_attrib[i].enabled) {
glEnableClientState(attr->type);
if (attr->type == GL_VERTEX_ARRAY) {
glVertexPointer(attr->dataTypeSize, attr->dataType,
attr->stride, attr->pointer);
} else if (attr->type == GL_NORMAL_ARRAY) {
glNormalPointer(attr->dataType, attr->stride, attr->pointer);
} else if (attr->type == GL_COLOR_ARRAY) {
glColorPointer(attr->dataTypeSize, attr->dataType,
attr->stride, attr->pointer);
}
}
}
}
void ClientBuffer::unBind() {
if (m_target == GL_ARRAY_BUFFER) {
for (unsigned i = 0; i < VERTEXBUFFERATTRIBSIZE; i++) {
if(m_attrib[i].enabled) {
glDisableClientState(m_attrib[i].type);
}
}
} else {
glDisableClientState(GL_INDEX_ARRAY);
}
pglBindBuffer(m_target, 0);
}
int ClientBuffer::setDataType(GLenum type, GLenum dataType, GLenum dataTypeSize,
GLsizei stride, const uintptr_t pointer) {
int idx;
switch (type)
{
case GL_VERTEX_ARRAY:
{
idx = 0;
break;
}
case GL_COLOR_ARRAY:
{
idx = 1;
break;
}
case GL_NORMAL_ARRAY:
{
idx = 2;
break;
}
default:
{
setErrorMessage("Failed to allocate memory for buffer");
return 0;
}
}
m_attrib[idx].enabled = 1;
m_attrib[idx].type = type;
m_attrib[idx].dataType = dataType;
m_attrib[idx].dataTypeSize = dataTypeSize;
m_attrib[idx].stride = stride;
m_attrib[idx].pointer = (void*)pointer;
return 1;
}
int ClientBuffer::loadData(const GLvoid *data, GLsizeiptr size,
GLintptr offset, GLenum usage) {
int bufferSize = 0;
if (!m_loaded) {
pglBindBuffer(m_target, m_id);
pglBufferData(m_target, size, data, usage);
pglGetBufferParameteriv(m_target, GL_BUFFER_SIZE_ARB, &bufferSize);
pglBindBuffer(m_target, 0);
if (bufferSize != size) {
setErrorMessage("Failed to allocate memory for buffer");
return 0;
}
m_loaded = true;
} else {
pglBindBuffer(m_target, m_id);
pglBufferSubData(m_target, offset, size, data);
pglBindBuffer(m_target, 0);
}
return 1;
}
// opengl shader program interface
ShaderProgram::ShaderProgram() {
m_id = 0u;
m_vertex_id = 0u;
m_fragment_id = 0u;
}
ShaderProgram::~ShaderProgram() {
if (m_vertex_id) pglDeleteShader(m_vertex_id);
if (m_fragment_id) pglDeleteShader(m_fragment_id);
if (m_id) pglDeleteProgram(m_id);
}
bool ShaderProgram::isValid() {
return (m_id != 0u && m_vertex_id != 0u && m_fragment_id != 0u);
}
void ShaderProgram::begin() {
pglUseProgram(m_id);
}
void ShaderProgram::end() {
pglUseProgram(0);
}
GLint ShaderProgram::attribLocation(const GLchar *name) {
GLint uloc = pglGetAttribLocation(m_id, name);
if (uloc == -1) {
setErrorMessage("Failed to find attrib variable");
return -1;
}
return uloc;
}
int ShaderProgram::loadUniform1i(const char *name, const GLint value) {
GLint uloc = pglGetUniformLocation(m_id, name);
if (uloc == -1) {
setErrorMessage("Failed to find uniform variable");
return 0;
}
pglUniform1i(uloc, value);
return 1;
}
int ShaderProgram::loadUniform1f(const char *name, const GLfloat value) {
GLint uloc = pglGetUniformLocation(m_id, name);
if (uloc == -1) {
setErrorMessage("Failed to find uniform variable");
return 0;
}
pglUniform1f(uloc, value);
return 1;
}
int ShaderProgram::loadUniform4f(const char *name, const GLfloat v0, const GLfloat v1,
const GLfloat v2, const GLfloat v3) {
GLint uloc = pglGetUniformLocation(m_id, name);
if (uloc == -1) {
setErrorMessage("Failed to find uniform variable");
return 0;
}
pglUniform4f(uloc, v0, v1, v2, v3);
return 1;
}
int ShaderProgram::loadUniformMatrix4vf(const char *name, const GLfloat *value,
GLsizei count) {
GLint uloc = pglGetUniformLocation(m_id, name);
if (uloc == -1) {
setErrorMessage("Failed to find uniform variable");
return 0;
}
pglUniformMatrix4fv(uloc, count, GL_FALSE, value);
return 1;
}
int ShaderProgram::build(const char* vertex_src,
const char* fragment_src) {
GLint status;
GLsizei log_length;
char info_log[256];
if (!vertex_src) vertex_src = default_vertex_shader;
if (!fragment_src) fragment_src = default_fragment_shader;
// build vertex shader
m_vertex_id = pglCreateShader(GL_VERTEX_SHADER);
if (m_vertex_id == 0u) {
setErrorMessage("Failed to create vertex shader");
return 0;
}
pglShaderSource(m_vertex_id, 1, (const GLchar**)&vertex_src, NULL);
pglCompileShader(m_vertex_id);
pglGetShaderiv(m_vertex_id, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE)
{
pglGetShaderInfoLog(m_vertex_id, sizeof(info_log), &log_length,info_log);
setErrorMessage(info_log);
return 0;
}
// build fragment shader
m_fragment_id = pglCreateShader(GL_FRAGMENT_SHADER);
if (m_fragment_id == 0u) {
setErrorMessage("Failed to create fragment shader");
return 0;
}
pglShaderSource(m_fragment_id, 1, (const GLchar**)&fragment_src, NULL);
pglCompileShader(m_fragment_id);
pglGetShaderiv(m_fragment_id, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE)
{
pglGetShaderInfoLog(m_fragment_id, sizeof(info_log), &log_length,info_log);
setErrorMessage(info_log);
return 0;
}
// create program and link shaders
m_id = pglCreateProgram();
if (m_id == 0u) {
setErrorMessage("Failed to create program");
return 0;
}
pglAttachShader(m_id, m_vertex_id);
pglAttachShader(m_id, m_fragment_id);
pglLinkProgram(m_id);
pglGetProgramiv(m_id, GL_LINK_STATUS, &status);
if (status != GL_TRUE)
{
pglGetShaderInfoLog(m_id, 8192, &log_length,info_log);
setErrorMessage(info_log);
return 0;
}
return 1;
}
const char* ShaderProgram::default_vertex_shader =
"#version 130\n"
"void main()\n"
"{\n"
" gl_FrontColor = gl_Color;\n"
" gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n"
"}\n";
const char* ShaderProgram::default_fragment_shader =
"#version 130\n"
"void main()\n"
"{\n"
" gl_FragColor = gl_Color;\n"
"}\n";

106
gltools/@src/GLTools.h Normal file
View file

@ -0,0 +1,106 @@
// Copyright 2012 by Runar Tenfjord, Tenko as.
// See LICENSE.txt for details on conditions.
#ifndef GLTOOLS_H
#define GLTOOLS_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <GL/glfw3.h>
#include <GL/glext.h>
#define GLEXTPROCSIZE 27
#define VERTEXBUFFERATTRIBSIZE 8
extern char errorMessage[256];
void setErrorMessage(const char *err);
// opengl font
extern void *_fonts;
int initText(void);
int beginText(void);
int endText(void);
int drawText(int idx, float size, float x, float y, const char *text, float *dx);
/* OpenGL 2.1 function pointers */
extern int isGLExtLoaded;
static PFNGLGENBUFFERSPROC pglGenBuffers = NULL;
static PFNGLDELETEBUFFERSPROC pglDeleteBuffers = NULL;
static PFNGLCREATESHADERPROC pglCreateShader = NULL;
static PFNGLSHADERSOURCEPROC pglShaderSource = NULL;
static PFNGLCOMPILESHADERPROC pglCompileShader = NULL;
static PFNGLGETSHADERIVPROC pglGetShaderiv = NULL;
static PFNGLGETSHADERINFOLOGPROC pglGetShaderInfoLog = NULL;
static PFNGLDELETESHADERPROC pglDeleteShader = NULL;
static PFNGLCREATEPROGRAMPROC pglCreateProgram = NULL;
static PFNGLATTACHSHADERPROC pglAttachShader = NULL;
static PFNGLLINKPROGRAMPROC pglLinkProgram = NULL;
static PFNGLUSEPROGRAMPROC pglUseProgram = NULL;
static PFNGLGETPROGRAMIVPROC pglGetProgramiv = NULL;
static PFNGLGETPROGRAMINFOLOGPROC pglGetProgramInfoLog = NULL;
static PFNGLDELETEPROGRAMPROC pglDeleteProgram = NULL;
static PFNGLGETUNIFORMLOCATIONPROC pglGetUniformLocation = NULL;
static PFNGLUNIFORM1IPROC pglUniform1i = NULL;
static PFNGLUNIFORM1FPROC pglUniform1f = NULL;
static PFNGLUNIFORM4FPROC pglUniform4f = NULL;
static PFNGLUNIFORMMATRIX4FVPROC pglUniformMatrix4fv = NULL;
static PFNGLGETATTRIBLOCATIONPROC pglGetAttribLocation = NULL;
static PFNGLBUFFERDATAPROC pglBufferData = NULL;
static PFNGLBINDBUFFERPROC pglBindBuffer = NULL;
static PFNGLBUFFERSUBDATAPROC pglBufferSubData = NULL;
static PFNGLGETBUFFERPARAMETERIVPROC pglGetBufferParameteriv = NULL;
static PFNGLENABLEVERTEXATTRIBARRAYPROC pglEnableVertexAttribArray = NULL;
static PFNGLVERTEXATTRIBPOINTERPROC pglVertexAttribPointer = NULL;
int initGLExt(void);
struct ClientBufferAttrib {
int enabled;
GLenum type;
GLenum dataType;
GLint dataTypeSize;
GLsizei stride;
const GLvoid *pointer;
};
class ClientBuffer {
public:
GLuint m_id;
GLenum m_target;
bool m_loaded;
ClientBufferAttrib m_attrib[VERTEXBUFFERATTRIBSIZE];
ClientBuffer(GLenum target);
~ClientBuffer();
void bind();
void unBind();
int setDataType(GLenum type, GLenum dataType, GLenum dataTypeSize,
GLsizei stride, const uintptr_t pointer);
int loadData(const GLvoid *data, GLsizeiptr size, GLintptr offset = 0,
GLenum usage = GL_STATIC_DRAW);
};
class ShaderProgram {
public:
GLuint m_id;
GLuint m_vertex_id;
GLuint m_fragment_id;
ShaderProgram();
~ShaderProgram();
bool isValid();
void begin();
void end();
GLint attribLocation(const GLchar *name);
int loadUniform1i(const char *name, const GLint value);
int loadUniform1f(const char *name, const GLfloat value);
int loadUniform4f(const char *name, const GLfloat v0, const GLfloat v1,
const GLfloat v2, const GLfloat v3);
int loadUniformMatrix4vf(const char *name, const GLfloat *value, GLsizei count = 1);
int build(const char* vertex_src = NULL, const char* fragment_src = NULL);
private:
static const char* default_vertex_shader;
static const char* default_fragment_shader;
};
#endif

View file

@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
cdef extern from "GLTools.h":
ctypedef unsigned int GLenum
ctypedef unsigned char GLboolean
ctypedef unsigned int GLbitfield
ctypedef signed char GLbyte
ctypedef short GLshort
ctypedef int GLint
ctypedef int GLsizei
ctypedef unsigned char GLubyte
ctypedef unsigned short GLushort
ctypedef unsigned int GLuint
ctypedef float GLfloat
ctypedef float GLclampf
ctypedef double GLdouble
ctypedef double GLclampd
ctypedef void GLvoid
ctypedef ssize_t GLintptr
ctypedef ssize_t GLsizeiptr
char errorMessage[256]
int c_initText "initText"()
int c_beginText "beginText"()
int c_endText "endText"()
int c_drawText "drawText"(int idx, float size, float x, float y, char *text, float *dx)
int isGLExtLoaded
int c_initGLExt "initGLExt"()
cdef cppclass c_ClientBuffer "ClientBuffer":
c_ClientBuffer(GLenum target)
void bind()
void unBind()
int setDataType(GLenum type, GLenum dataType, GLenum dataTypeSize,
GLsizei stride, size_t pointer)
int loadData(GLvoid *data, GLsizeiptr size, GLintptr offset, GLenum usage)
cdef cppclass c_ShaderProgram "ShaderProgram":
c_ShaderProgram()
bint isValid()
void begin()
void end()
GLint attribLocation(char *name)
int loadUniform1i(char *name, GLint value)
int loadUniform1f(char *name, GLfloat value)
int loadUniform4f(char *name, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
int loadUniformMatrix4vf(char *name, GLfloat *value, GLsizei count)
int build(char *vertex_src, char *fragment_src)

View file

@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
#
# This file is part of gltools - See LICENSE.txt
#
cdef class ShaderProgram:
def __init__(self):
if not isGLExtLoaded:
raise GLError('OpenGL 2.1 function pointers not found')
self.thisptr = new c_ShaderProgram()
def __dealloc__(self):
cdef c_ShaderProgram *tmp
if self.thisptr != NULL:
tmp = <c_ShaderProgram *>self.thisptr
del tmp
def __str__(self):
return "ShaderProgram%s" % repr(self)
def __repr__(self):
return "()"
cpdef bint isValid(self):
cdef c_ShaderProgram *prog = <c_ShaderProgram *>self.thisptr
return prog.isValid()
cpdef begin(self):
cdef c_ShaderProgram *prog = <c_ShaderProgram *>self.thisptr
prog.begin()
cpdef end(self):
cdef c_ShaderProgram *prog = <c_ShaderProgram *>self.thisptr
prog.end()
cpdef loadUniform1i(self, char *name, int value):
cdef c_ShaderProgram *prog = <c_ShaderProgram *>self.thisptr
if not prog.loadUniform1i(name, value):
raise GLError(errorMessage)
cpdef loadUniform1f(self, char *name, float value):
cdef c_ShaderProgram *prog = <c_ShaderProgram *>self.thisptr
if not prog.loadUniform1f(name, value):
raise GLError(errorMessage)
cpdef loadUniform4f(self, char *name, float v0, float v1, float v2, float v3):
print name, v0, v1, v2, v3
cdef c_ShaderProgram *prog = <c_ShaderProgram *>self.thisptr
if not prog.loadUniform4f(name, v0, v1, v2, v3):
raise GLError(errorMessage)
cpdef loadUniformMatrix4vf(self, char *name, float [::1] value, int count = 1):
cdef c_ShaderProgram *prog = <c_ShaderProgram *>self.thisptr
if not prog.loadUniformMatrix4vf(name, &value[0], count):
raise GLError(errorMessage)
cpdef build(self, vertex_src = None, fragment_src = None):
cdef c_ShaderProgram *prog = <c_ShaderProgram *>self.thisptr
cdef int ret
if vertex_src is None and fragment_src is None:
ret = prog.build(NULL,NULL)
else:
ret = prog.build(vertex_src, fragment_src)
if not ret:
raise GLError(errorMessage)

23
gltools/@src/Text.pxi Normal file
View file

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
#
# This file is part of gltools - See LICENSE.txt
#
cpdef BeginText():
if not c_beginText():
raise GLError(errorMessage)
cpdef float DrawText(size, float x, float y, text):
cdef float dx
cdef char *c_str
bytetext = unicode(text).encode('UTF-8','ignore')
c_str = bytetext
if not c_drawText(0, size, x, y, c_str, &dx):
raise GLError(errorMessage)
return dx
cpdef EndText():
if not c_endText():
raise GLError(errorMessage)

139
gltools/@src/UI.pxi Normal file
View file

@ -0,0 +1,139 @@
# -*- coding: utf-8 -*-
from imguiLib cimport *
cdef class UI:
def __init__(self):
self.scrollIdx = 0
imguiRenderGLInit()
if not c_initText():
raise GLError(errorMessage)
cpdef bint anyActive(self):
return imguiAnyActive()
cpdef flush(self):
self.scrollIdx = 0
imguiRenderGLDraw()
cpdef beginFrame(self, int mx, int my, char mbut, int scroll):
if mbut == GLFW_MOUSE_BUTTON_LEFT:
mbut = IMGUI_MBUT_LEFT
elif mbut == GLFW_MOUSE_BUTTON_RIGHT:
mbut = IMGUI_MBUT_RIGHT
elif mbut == -1:
mbut = 0
imguiBeginFrame(mx, my, mbut, scroll)
cpdef endFrame(self):
imguiEndFrame()
cpdef bint beginScrollArea(self, name, int x, int y, int w, int h):
cdef char *c_name
cdef bint ret
bytetext = unicode(name).encode('UTF-8','ignore')
c_name = bytetext
ret = imguiBeginScrollArea(c_name, x, y, w, h, &self.scroll[self.scrollIdx])
self.scrollIdx += 1
if self.scrollIdx >= 10:
raise GLError('Only 10 scrool areas supported')
return ret
cpdef endScrollArea(self):
imguiEndScrollArea()
cpdef indent(self):
imguiIndent()
cpdef unindent(self):
imguiUnindent()
cpdef separator(self):
imguiSeparator()
cpdef separatorLine(self):
imguiSeparatorLine()
cpdef bint button(self, text, bint enabled):
cdef char *c_text
bytetext = unicode(text).encode('UTF-8','ignore')
c_text = bytetext
return imguiButton(c_text, enabled)
cpdef bint item(self, text, bint enabled):
cdef char *c_text
bytetext = unicode(text).encode('UTF-8','ignore')
c_text = bytetext
return imguiItem(c_text, enabled)
cpdef bint check(self, text, bint checked, bint enabled):
cdef char *c_text
bytetext = unicode(text).encode('UTF-8','ignore')
c_text = bytetext
return imguiCheck(c_text, checked, enabled)
cpdef bint collapse(self, text, char* subtext, bint checked, bint enabled):
cdef char *c_text
bytetext = unicode(text).encode('UTF-8','ignore')
c_text = bytetext
return imguiCollapse(c_text, subtext, checked, enabled)
cpdef label(self, text):
cdef char *c_text
bytetext = unicode(text).encode('UTF-8','ignore')
c_text = bytetext
imguiLabel(c_text)
cpdef value(self, text):
cdef char *c_text
bytetext = unicode(text).encode('UTF-8','ignore')
c_text = bytetext
imguiValue(c_text)
cpdef float slider(self, text, float val, float vmin, float vmax,
float vinc, bint enabled):
cdef float c_val = val
cdef char *c_text
bytetext = unicode(text).encode('UTF-8','ignore')
c_text = bytetext
imguiSlider(c_text, &c_val, vmin, vmax, vinc, enabled)
return c_val
cpdef drawText(self, int x, int y, int align, text, ColorRGBA color):
cdef char *c_text
bytetext = unicode(text).encode('UTF-8','ignore')
c_text = bytetext
imguiDrawText(x, y, align, c_text, color.toInt())
cpdef drawLine(self, float x0, float y0, float x1, float y1, float r, ColorRGBA color):
imguiDrawLine(x0, y0, x1, y1, r, color.toInt())
cpdef drawRoundedRect(self, float x, float y, float w, float h, float r, ColorRGBA color):
imguiDrawRoundedRect(x, y, w, h, r, color.toInt())
cpdef drawRect(self, float x, float y, float w, float h, ColorRGBA color):
imguiDrawRect(x, y, w, h, color.toInt())

View file

@ -0,0 +1,82 @@
# -*- coding: utf-8 -*-
#
# This file is part of gltools - See LICENSE.txt
#
# general imports
from libc.stdint cimport uintptr_t
from libc.stdlib cimport malloc, free
from libc.math cimport fmin, fmax, fabs, copysign
from libc.math cimport M_PI, sqrt, sin, cos, tan
cimport cpython.array
# utility to get pointer from memoryview
cdef void *getVoidPtr(arr):
cdef double [::1] d_view
cdef float [::1] f_view
cdef long [::1] l_view
cdef int [::1] i_view
cdef unsigned int [::1] I_view
cdef char [::1] b_view
cdef unsigned char [::1] B_view
cdef void *ptr
try:
d_view = arr
except ValueError:
pass
else:
ptr = <void *>(&d_view[0])
return ptr
try:
f_view = arr
except ValueError:
pass
else:
ptr = <void *>(&f_view[0])
return ptr
try:
l_view = arr
except ValueError:
pass
else:
ptr = <void *>(&l_view[0])
return ptr
try:
i_view = arr
except ValueError:
pass
else:
ptr = <void *>(&i_view[0])
return ptr
try:
I_view = arr
except ValueError:
pass
else:
ptr = <void *>(&I_view[0])
return ptr
try:
b_view = arr
except ValueError:
pass
else:
ptr = <void *>(&b_view[0])
return ptr
try:
B_view = arr
except ValueError:
pass
else:
ptr = <void *>(&B_view[0])
return ptr
raise TypeError('no valid array type found')

257
gltools/@src/glLib.pxd Normal file
View file

@ -0,0 +1,257 @@
# -*- coding: utf-8 -*-
cdef extern from "GL/glfw3.h":
ctypedef unsigned int GLenum
ctypedef unsigned char GLboolean
ctypedef unsigned int GLbitfield
ctypedef signed char GLbyte
ctypedef short GLshort
ctypedef int GLint
ctypedef int GLsizei
ctypedef unsigned char GLubyte
ctypedef unsigned short GLushort
ctypedef unsigned int GLuint
ctypedef float GLfloat
ctypedef float GLclampf
ctypedef double GLdouble
ctypedef double GLclampd
ctypedef void GLvoid
void glBlendFunc(GLenum sfactor, GLenum dfactor)
void glClear(GLbitfield mask)
void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
void glClearDepth(GLclampd depth)
void glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha )
void glDisable(GLenum cap)
void glDrawArrays(GLenum mode, GLint first, GLsizei count)
void glDrawElements(GLenum mode, GLsizei count, GLenum type, GLvoid *indices)
void glEnable(GLenum cap)
void glLineWidth(GLfloat width)
void glLightfv(GLenum light, GLenum pname, GLfloat *params )
void glLightModeli(GLenum pname, GLint param)
void glLoadIdentity()
void glLoadMatrixd(GLdouble *m)
void glMaterialfv(GLenum face, GLenum pname, GLfloat *params)
void glMatrixMode(GLenum mode)
void glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar)
void glPolygonMode(GLenum face, GLenum mode)
void glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
cdef enum:
# Boolean values
GL_FALSE
GL_TRUE
# DataType
GL_BYTE
GL_UNSIGNED_BYTE
GL_SHORT
GL_UNSIGNED_SHORT
GL_INT
GL_UNSIGNED_INT
GL_FLOAT
GL_2_BYTES
GL_3_BYTES
GL_4_BYTES
GL_DOUBLE
# BeginMode
GL_POINTS
GL_LINES
GL_LINE_LOOP
GL_LINE_STRIP
GL_TRIANGLES
GL_TRIANGLE_STRIP
GL_TRIANGLE_FAN
GL_QUADS
GL_QUAD_STRIP
GL_POLYGON
# AlphaFunction
GL_NEVER
GL_LESS
GL_EQUAL
GL_LEQUAL
GL_GREATER
GL_NOTEQUAL
GL_GEQUAL
GL_ALWAYS
# AttribMask
GL_CURRENT_BIT
GL_POINT_BIT
GL_LINE_BIT
GL_POLYGON_BIT
GL_POLYGON_STIPPLE_BIT
GL_PIXEL_MODE_BIT
GL_LIGHTING_BIT
GL_FOG_BIT
GL_DEPTH_BUFFER_BIT
GL_ACCUM_BUFFER_BIT
GL_STENCIL_BUFFER_BIT
GL_VIEWPORT_BIT
GL_TRANSFORM_BIT
GL_ENABLE_BIT
GL_COLOR_BUFFER_BIT
GL_HINT_BIT
GL_EVAL_BIT
GL_LIST_BIT
GL_TEXTURE_BIT
GL_SCISSOR_BIT
GL_ALL_ATTRIB_BITS
# Vertex Arrays
GL_VERTEX_ARRAY
GL_NORMAL_ARRAY
GL_COLOR_ARRAY
GL_INDEX_ARRAY
GL_TEXTURE_COORD_ARRAY
GL_EDGE_FLAG_ARRAY
# BlendingFactorDest
GL_ZERO
GL_ONE
GL_SRC_COLOR
GL_ONE_MINUS_SRC_COLOR
GL_SRC_ALPHA
GL_ONE_MINUS_SRC_ALPHA
GL_DST_ALPHA
GL_ONE_MINUS_DST_ALPHA
# BlendingFactorSrc
GL_DST_COLOR
GL_ONE_MINUS_DST_COLOR
GL_SRC_ALPHA_SATURATE
# DrawBufferMode
GL_NONE
GL_FRONT_LEFT
GL_FRONT_RIGHT
GL_BACK_LEFT
GL_BACK_RIGHT
GL_FRONT
GL_BACK
GL_LEFT
GL_RIGHT
GL_FRONT_AND_BACK
GL_AUX0
GL_AUX1
GL_AUX2
GL_AUX3
GL_CW
GL_CCW
# ErrorCode
GL_NO_ERROR
GL_INVALID_ENUM
GL_INVALID_VALUE
GL_INVALID_OPERATION
GL_STACK_OVERFLOW
GL_STACK_UNDERFLOW
GL_OUT_OF_MEMORY
# GetTarget
GL_POLYGON_MODE
GL_POLYGON_SMOOTH
GL_POLYGON_STIPPLE
GL_FRONT_FACE
GL_SHADE_MODEL
GL_COLOR_MATERIAL_FACE
GL_COLOR_MATERIAL_PARAMETER
GL_COLOR_MATERIAL
GL_DEPTH_RANGE
GL_DEPTH_TEST
GL_DEPTH_WRITEMASK
GL_DEPTH_CLEAR_VALUE
GL_DEPTH_FUNC
GL_MATRIX_MODE
GL_NORMALIZE
GL_VIEWPORT
GL_MODELVIEW_MATRIX
GL_PROJECTION_MATRIX
GL_TEXTURE_MATRIX
GL_ALPHA_TEST
GL_ALPHA_TEST_FUNC
GL_ALPHA_TEST_REF
GL_DITHER
GL_BLEND_DST
GL_BLEND_SRC
GL_BLEND
GL_LOGIC_OP_MODE
GL_INDEX_LOGIC_OP
GL_COLOR_LOGIC_OP
GL_AUX_BUFFERS
GL_DRAW_BUFFER
GL_READ_BUFFER
GL_SCISSOR_BOX
GL_SCISSOR_TEST
GL_INDEX_CLEAR_VALUE
GL_INDEX_WRITEMASK
GL_COLOR_CLEAR_VALUE
GL_COLOR_WRITEMASK
GL_INDEX_MODE
GL_RGBA_MODE
GL_DOUBLEBUFFER
GL_STEREO
GL_RENDER_MODE
GL_SUBPIXEL_BITS
GL_INDEX_BITS
GL_RED_BITS
GL_GREEN_BITS
GL_BLUE_BITS
GL_ALPHA_BITS
GL_DEPTH_BITS
GL_STENCIL_BITS
GL_CULL_FACE
# Ligthing & Material
GL_AMBIENT
GL_DIFFUSE
GL_SPECULAR
GL_SHININESS
GL_EMISSION
GL_POSITION
GL_SPOT_DIRECTION
GL_AMBIENT_AND_DIFFUSE
GL_COLOR_INDEXES
GL_LIGHTING
GL_LIGHT0
GL_LIGHT1
GL_LIGHT2
GL_LIGHT3
GL_LIGHT4
GL_LIGHT5
GL_LIGHT6
GL_LIGHT7
GL_LIGHT_MODEL_TWO_SIDE
GL_LIGHT_MODEL_LOCAL_VIEWER
GL_LIGHT_MODEL_AMBIENT
# MatrixMode
GL_MODELVIEW
GL_PROJECTION
GL_TEXTURE
# Lines
GL_LINE_SMOOTH
# PolygonMode
GL_POINT
GL_LINE
GL_FILL
# ShadingModel
GL_FLAT
GL_SMOOTH
# Texture mapping
GL_TEXTURE_1D
GL_TEXTURE_2D
# glext.h
GL_MULTISAMPLE
GL_STATIC_DRAW
GL_ARRAY_BUFFER
GL_ELEMENT_ARRAY_BUFFER

378
gltools/@src/glfwLib.pxd Normal file
View file

@ -0,0 +1,378 @@
# -*- coding: utf-8 -*-
cdef extern from "GL/glfw3.h":
cdef enum:
GLFW_VERSION_MAJOR
GLFW_VERSION_MINOR
GLFW_VERSION_REVISION
# Key and button state/action definitions
GLFW_RELEASE
GLFW_PRESS
# Printable keys
GLFW_KEY_SPACE
GLFW_KEY_APOSTROPHE
GLFW_KEY_COMMA
GLFW_KEY_MINUS
GLFW_KEY_PERIOD
GLFW_KEY_SLASH
GLFW_KEY_0
GLFW_KEY_1
GLFW_KEY_2
GLFW_KEY_3
GLFW_KEY_4
GLFW_KEY_5
GLFW_KEY_6
GLFW_KEY_7
GLFW_KEY_8
GLFW_KEY_9
GLFW_KEY_SEMICOLON
GLFW_KEY_EQUAL
GLFW_KEY_A
GLFW_KEY_B
GLFW_KEY_C
GLFW_KEY_D
GLFW_KEY_E
GLFW_KEY_F
GLFW_KEY_G
GLFW_KEY_H
GLFW_KEY_I
GLFW_KEY_J
GLFW_KEY_K
GLFW_KEY_L
GLFW_KEY_M
GLFW_KEY_N
GLFW_KEY_O
GLFW_KEY_P
GLFW_KEY_Q
GLFW_KEY_R
GLFW_KEY_S
GLFW_KEY_T
GLFW_KEY_U
GLFW_KEY_V
GLFW_KEY_W
GLFW_KEY_X
GLFW_KEY_Y
GLFW_KEY_Z
GLFW_KEY_LEFT_BRACKET
GLFW_KEY_BACKSLASH
GLFW_KEY_RIGHT_BRACKET
GLFW_KEY_GRAVE_ACCENT
GLFW_KEY_WORLD_1
GLFW_KEY_WORLD_2
# Function keys
GLFW_KEY_ESCAPE
GLFW_KEY_ENTER
GLFW_KEY_TAB
GLFW_KEY_BACKSPACE
GLFW_KEY_INSERT
GLFW_KEY_DELETE
GLFW_KEY_RIGHT
GLFW_KEY_LEFT
GLFW_KEY_DOWN
GLFW_KEY_UP
GLFW_KEY_PAGE_UP
GLFW_KEY_PAGE_DOWN
GLFW_KEY_HOME
GLFW_KEY_END
GLFW_KEY_CAPS_LOCK
GLFW_KEY_SCROLL_LOCK
GLFW_KEY_NUM_LOCK
GLFW_KEY_PRINT_SCREEN
GLFW_KEY_PAUSE
GLFW_KEY_F1
GLFW_KEY_F2
GLFW_KEY_F3
GLFW_KEY_F4
GLFW_KEY_F5
GLFW_KEY_F6
GLFW_KEY_F7
GLFW_KEY_F8
GLFW_KEY_F9
GLFW_KEY_F10
GLFW_KEY_F11
GLFW_KEY_F12
GLFW_KEY_F13
GLFW_KEY_F14
GLFW_KEY_F15
GLFW_KEY_F16
GLFW_KEY_F17
GLFW_KEY_F18
GLFW_KEY_F19
GLFW_KEY_F20
GLFW_KEY_F21
GLFW_KEY_F22
GLFW_KEY_F23
GLFW_KEY_F24
GLFW_KEY_F25
GLFW_KEY_KP_0
GLFW_KEY_KP_1
GLFW_KEY_KP_2
GLFW_KEY_KP_3
GLFW_KEY_KP_4
GLFW_KEY_KP_5
GLFW_KEY_KP_6
GLFW_KEY_KP_7
GLFW_KEY_KP_8
GLFW_KEY_KP_9
GLFW_KEY_KP_DECIMAL
GLFW_KEY_KP_DIVIDE
GLFW_KEY_KP_MULTIPLY
GLFW_KEY_KP_SUBTRACT
GLFW_KEY_KP_ADD
GLFW_KEY_KP_ENTER
GLFW_KEY_KP_EQUAL
GLFW_KEY_LEFT_SHIFT
GLFW_KEY_LEFT_CONTROL
GLFW_KEY_LEFT_ALT
GLFW_KEY_LEFT_SUPER
GLFW_KEY_RIGHT_SHIFT
GLFW_KEY_RIGHT_CONTROL
GLFW_KEY_RIGHT_ALT
GLFW_KEY_RIGHT_SUPER
GLFW_KEY_MENU
GLFW_KEY_LAST
# Mouse button definitions
GLFW_MOUSE_BUTTON_1
GLFW_MOUSE_BUTTON_2
GLFW_MOUSE_BUTTON_3
GLFW_MOUSE_BUTTON_4
GLFW_MOUSE_BUTTON_5
GLFW_MOUSE_BUTTON_6
GLFW_MOUSE_BUTTON_7
GLFW_MOUSE_BUTTON_8
GLFW_MOUSE_BUTTON_LAST
# Mouse button aliases
GLFW_MOUSE_BUTTON_LEFT
GLFW_MOUSE_BUTTON_RIGHT
GLFW_MOUSE_BUTTON_MIDDLE
# Joystick identifiers
GLFW_JOYSTICK_1
GLFW_JOYSTICK_2
GLFW_JOYSTICK_3
GLFW_JOYSTICK_4
GLFW_JOYSTICK_5
GLFW_JOYSTICK_6
GLFW_JOYSTICK_7
GLFW_JOYSTICK_8
GLFW_JOYSTICK_9
GLFW_JOYSTICK_10
GLFW_JOYSTICK_11
GLFW_JOYSTICK_12
GLFW_JOYSTICK_13
GLFW_JOYSTICK_14
GLFW_JOYSTICK_15
GLFW_JOYSTICK_16
GLFW_JOYSTICK_LAST
# glfwCreateWindow modes
GLFW_WINDOWED
GLFW_FULLSCREEN
# glfwGetWindowParam tokens
GLFW_ACTIVE
GLFW_ICONIFIED
GLFW_CLOSE_REQUESTED
GLFW_OPENGL_REVISION
# glfwWindowHint tokens
GLFW_RED_BITS
GLFW_GREEN_BITS
GLFW_BLUE_BITS
GLFW_ALPHA_BITS
GLFW_DEPTH_BITS
GLFW_STENCIL_BITS
GLFW_REFRESH_RATE
GLFW_ACCUM_RED_BITS
GLFW_ACCUM_GREEN_BITS
GLFW_ACCUM_BLUE_BITS
GLFW_ACCUM_ALPHA_BITS
GLFW_AUX_BUFFERS
GLFW_STEREO
GLFW_FSAA_SAMPLES
# The following constants are used with both glfwGetWindowParam
# and glfwWindowHint
GLFW_CLIENT_API
GLFW_OPENGL_VERSION_MAJOR
GLFW_OPENGL_VERSION_MINOR
GLFW_OPENGL_FORWARD_COMPAT
GLFW_OPENGL_DEBUG_CONTEXT
GLFW_OPENGL_PROFILE
GLFW_OPENGL_ROBUSTNESS
GLFW_RESIZABLE
GLFW_VISIBLE
# GLFW_CLIENT_API tokens
GLFW_OPENGL_API
GLFW_OPENGL_ES_API
# GLFW_OPENGL_ROBUSTNESS mode tokens
GLFW_OPENGL_NO_ROBUSTNESS
GLFW_OPENGL_NO_RESET_NOTIFICATION
GLFW_OPENGL_LOSE_CONTEXT_ON_RESET
# GLFW_OPENGL_PROFILE bit tokens
GLFW_OPENGL_NO_PROFILE
GLFW_OPENGL_CORE_PROFILE
GLFW_OPENGL_COMPAT_PROFILE
# glfwGetInputMode/glfwSetInputMode tokens
GLFW_CURSOR_MODE
GLFW_STICKY_KEYS
GLFW_STICKY_MOUSE_BUTTONS
GLFW_SYSTEM_KEYS
GLFW_KEY_REPEAT
# GLFW_CURSOR_MODE values
GLFW_CURSOR_NORMAL
GLFW_CURSOR_HIDDEN
GLFW_CURSOR_CAPTURED
# glfwGetJoystickParam tokens
GLFW_PRESENT
GLFW_AXES
GLFW_BUTTONS
# glfwGetError/glfwErrorString tokens
GLFW_NO_ERROR
GLFW_NOT_INITIALIZED
GLFW_NO_CURRENT_CONTEXT
GLFW_INVALID_ENUM
GLFW_INVALID_VALUE
GLFW_OUT_OF_MEMORY
GLFW_OPENGL_UNAVAILABLE
GLFW_VERSION_UNAVAILABLE
GLFW_PLATFORM_ERROR
GLFW_WINDOW_NOT_ACTIVE
GLFW_FORMAT_UNAVAILABLE
# Gamma ramps
GLFW_GAMMA_RAMP_SIZE
# OpenGL function pointer type
ctypedef void (*GLFWglproc)()
# Window handle type
ctypedef void* GLFWwindow
# Function pointer types
ctypedef void (* GLFWerrorfun)(int,char*)
ctypedef void (* GLFWwindowsizefun)(GLFWwindow,int,int)
ctypedef int (* GLFWwindowclosefun)(GLFWwindow)
ctypedef void (* GLFWwindowrefreshfun)(GLFWwindow)
ctypedef void (* GLFWwindowfocusfun)(GLFWwindow,int)
ctypedef void (* GLFWwindowiconifyfun)(GLFWwindow,int)
ctypedef void (* GLFWmousebuttonfun)(GLFWwindow,int,int)
ctypedef void (* GLFWcursorposfun)(GLFWwindow,int,int)
ctypedef void (* GLFWcursorenterfun)(GLFWwindow,int)
ctypedef void (* GLFWscrollfun)(GLFWwindow,double,double)
ctypedef void (* GLFWkeyfun)(GLFWwindow,int,int)
ctypedef void (* GLFWcharfun)(GLFWwindow,int)
# The video mode structure used by glfwGetVideoModes
cdef struct _GLFWvidmode:
int width
int height
int redBits
int blueBits
int greenBits
ctypedef _GLFWvidmode GLFWvidmode
# Gamma ramp
cdef struct _GLFWgammaramp:
unsigned short red[GLFW_GAMMA_RAMP_SIZE]
unsigned short green[GLFW_GAMMA_RAMP_SIZE]
unsigned short blue[GLFW_GAMMA_RAMP_SIZE]
ctypedef _GLFWgammaramp GLFWgammaramp
# Initialization, termination and version querying
int glfwInit()
void glfwTerminate()
void glfwGetVersion(int* major, int* minor, int* rev)
char* glfwGetVersionString()
# Error handling
int glfwGetError()
char* glfwErrorString(int error)
void glfwSetErrorCallback(GLFWerrorfun cbfun)
# Video mode functions
GLFWvidmode* glfwGetVideoModes(int* count)
void glfwGetDesktopMode(GLFWvidmode* mode)
# Gamma ramp functions
void glfwSetGamma(float gamma)
void glfwGetGammaRamp(GLFWgammaramp* ramp)
void glfwSetGammaRamp(GLFWgammaramp* ramp)
# Window handling
void glfwWindowHint(int target, int hint)
GLFWwindow glfwCreateWindow(int width, int height, int mode, char* title, GLFWwindow share)
void glfwDestroyWindow(GLFWwindow window)
void glfwSetWindowTitle(GLFWwindow window, char* title)
void glfwGetWindowSize(GLFWwindow window, int* width, int* height)
void glfwSetWindowSize(GLFWwindow window, int width, int height)
void glfwGetWindowPos(GLFWwindow window, int* xpos, int* ypos)
void glfwSetWindowPos(GLFWwindow window, int xpos, int ypos)
void glfwIconifyWindow(GLFWwindow window)
void glfwRestoreWindow(GLFWwindow window)
void glfwShowWindow(GLFWwindow window)
void glfwHideWindow(GLFWwindow window)
int glfwGetWindowParam(GLFWwindow window, int param)
void glfwSetWindowUserPointer(GLFWwindow window, void* pointer)
void* glfwGetWindowUserPointer(GLFWwindow window)
void glfwSetWindowSizeCallback(GLFWwindowsizefun cbfun)
void glfwSetWindowCloseCallback(GLFWwindowclosefun cbfun)
void glfwSetWindowRefreshCallback(GLFWwindowrefreshfun cbfun)
void glfwSetWindowFocusCallback(GLFWwindowfocusfun cbfun)
void glfwSetWindowIconifyCallback(GLFWwindowiconifyfun cbfun)
# Event handling
void glfwPollEvents()
void glfwWaitEvents()
# Input handling
int glfwGetInputMode(GLFWwindow window, int mode)
void glfwSetInputMode(GLFWwindow window, int mode, int value)
int glfwGetKey(GLFWwindow window, int key)
int glfwGetMouseButton(GLFWwindow window, int button)
void glfwGetCursorPos(GLFWwindow window, int* xpos, int* ypos)
void glfwSetCursorPos(GLFWwindow window, int xpos, int ypos)
void glfwGetScrollOffset(GLFWwindow window, double* xoffset, double* yoffset)
void glfwSetKeyCallback(GLFWkeyfun cbfun)
void glfwSetCharCallback(GLFWcharfun cbfun)
void glfwSetMouseButtonCallback(GLFWmousebuttonfun cbfun)
void glfwSetCursorPosCallback(GLFWcursorposfun cbfun)
void glfwSetCursorEnterCallback(GLFWcursorenterfun cbfun)
void glfwSetScrollCallback(GLFWscrollfun cbfun)
# Joystick input
int glfwGetJoystickParam(int joy, int param)
int glfwGetJoystickAxes(int joy, float* axes, int numaxes)
int glfwGetJoystickButtons(int joy, unsigned char* buttons, int numbuttons)
# Clipboard
void glfwSetClipboardString(GLFWwindow window, char* string)
char* glfwGetClipboardString(GLFWwindow window)
# Time
double glfwGetTime()
void glfwSetTime(double time)
# OpenGL support
void glfwMakeContextCurrent(GLFWwindow window)
GLFWwindow glfwGetCurrentContext()
void glfwSwapBuffers(GLFWwindow window)
void glfwSwapInterval(int interval)
int glfwExtensionSupported(char* extension)
GLFWglproc glfwGetProcAddress(char* procname)
void glfwCopyContext(GLFWwindow src, GLFWwindow dst, unsigned long mask)

41
gltools/@src/imguiLib.pxd Normal file
View file

@ -0,0 +1,41 @@
cdef extern from "imguiRenderGL.h":
bint imguiRenderGLInit()
void imguiRenderGLDraw()
cdef extern from "imgui.h":
cdef enum imguiMouseButton:
IMGUI_MBUT_LEFT
IMGUI_MBUT_RIGHT
cdef enum imguiTextAlign:
IMGUI_ALIGN_LEFT
IMGUI_ALIGN_CENTER
IMGUI_ALIGN_RIGHT
unsigned int imguiRGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
bint imguiAnyActive()
void imguiBeginFrame(int mx, int my, unsigned char mbut, int scroll)
void imguiEndFrame()
bint imguiBeginScrollArea(char* name, int x, int y, int w, int h, int* scroll)
void imguiEndScrollArea()
void imguiIndent()
void imguiUnindent()
void imguiSeparator()
void imguiSeparatorLine()
bint imguiButton(char* text, bint enabled)
bint imguiItem(char* text, bint enabled)
bint imguiCheck(char* text, bint checked, bint enabled)
bint imguiCollapse(char* text, char* subtext, bint checked, bint enabled)
void imguiLabel(char* text)
void imguiValue(char* text)
bint imguiSlider(char* text, float* val, float vmin, float vmax, float vinc, bint enabled)
void imguiDrawText(int x, int y, int align, char* text, unsigned int color)
void imguiDrawLine(float x0, float y0, float x1, float y1, float r, unsigned int color)
void imguiDrawRoundedRect(float x, float y, float w, float h, float r, unsigned int color)
void imguiDrawRect(float x, float y, float w, float h, unsigned int color)

25
gltools/Makefile Normal file
View file

@ -0,0 +1,25 @@
#
# File: Makefile (for library)
#
PYTHON=python2
.PHONY: all docs test install clean
all:
@echo lib Makefile - building python extension
$(PYTHON) setup_build.py build_ext --inplace
-strip --strip-all gltools.so
docs: all
@echo lib Makefile - building documentation
@cd @docs ; $(PYTHON) ../setup_docs.py build_sphinx
@cp -rf @docs/build/sphinx/html/* @docs/html/
install: all
@cp gltools.so ~/.local/lib/python2.7/site-packages/
@cp gltools.pxd ~/.local/lib/python2.7/site-packages/
clean:
-rm -rf build
-rm gltools.cpp
-rm gltools.so

139
gltools/gltools.pxd Normal file
View file

@ -0,0 +1,139 @@
# -*- coding: utf-8 -*-
#
# This file is part of gltools - See LICENSE.txt
#
from geotools cimport Point, Transform
cdef class ColorRGBA:
cdef readonly unsigned char red
cdef readonly unsigned char green
cdef readonly unsigned char blue
cdef readonly unsigned char alpha
cpdef ColorRGBA copy(self, int red = ?, int green = ?, int blue = ?, alpha = ?)
cpdef unsigned toInt(self)
cpdef tuple toFloatVector(self)
cdef setFloatVector(self, float *vec)
cdef class Material:
cdef public ColorRGBA ambient
cdef public ColorRGBA diffuse
cdef public ColorRGBA specular
cdef public ColorRGBA emissive
cdef public float shininess
cdef readonly int mode
cpdef enable(self)
cdef class Light:
cdef public Material material
cdef public Point position
cdef public bint directional
cdef readonly int index
cpdef enable(self)
cpdef disable(self)
cdef class ClientBuffer:
cdef void *thisptr
cpdef bind(self)
cpdef unBind(self)
cpdef setDataType(self, int type, int dataType, int dataTypeSize,
int stride, size_t pointer)
cdef cloadData(self, void *data, ssize_t size, ssize_t offset, int usage)
cpdef loadData(self, data, ssize_t size, ssize_t offset = ?, int usage = ?)
cpdef Init()
cpdef double getTime()
cpdef SetTime(double time)
cpdef SetGamma(float gamma)
cpdef tuple GetDesktopSize()
cdef class Window:
cdef void *thisptr
cdef public bint running
cpdef setTitle(self, title)
cpdef tuple getSize(self)
cpdef setSize(self, int width, int height)
cpdef tuple getPos(self)
cpdef setPos(self, int x, int y)
cpdef setClipboard(self, content)
cpdef getClipboard(self)
cpdef iconify(self)
cpdef restore(self)
cpdef show(self)
cpdef hide(self)
cpdef close(self)
cpdef makeContextCurrent(self)
cpdef swapBuffers(self)
cpdef mainLoop(self)
cpdef onSize(self, int w, int h)
cpdef onRefresh(self)
cpdef onCursorPos(self, int x, int y)
cpdef onMouseButton(self, int button, int action)
cpdef onKey(self, int key, int action)
cpdef onChar(self, ch)
cpdef onFocus(self, int status)
cpdef onEnter(self, int status)
cpdef onScroll(self, double dx, double dy)
cpdef onIconify(self, int status)
cpdef bint onClose(self)
cdef class ShaderProgram:
cdef void *thisptr
cpdef bint isValid(self)
cpdef begin(self)
cpdef end(self)
cpdef loadUniform1i(self, char *name, int value)
cpdef loadUniform1f(self, char *name, float value)
cpdef loadUniform4f(self, char *name, float v0, float v1, float v2, float v3)
cpdef loadUniformMatrix4vf(self, char *name, float [::1] value, int count = ?)
cpdef build(self, vertex_src = ?, fragment_src = ?)
cpdef BeginText()
cpdef float DrawText(size, float x, float y, text)
cpdef EndText()
cdef class UI:
cdef int scroll[10]
cdef int scrollIdx
cpdef bint anyActive(self)
cpdef flush(self)
cpdef beginFrame(self, int mx, int my, char mbut, int scroll)
cpdef endFrame(self)
cpdef bint beginScrollArea(self, name, int x, int y, int w, int h)
cpdef endScrollArea(self)
cpdef indent(self)
cpdef unindent(self)
cpdef separator(self)
cpdef separatorLine(self)
cpdef bint button(self, text, bint enabled)
cpdef bint item(self, text, bint enabled)
cpdef bint check(self, text, bint checked, bint enabled)
cpdef bint collapse(self, text, char* subtext, bint checked, bint enabled)
cpdef label(self, text)
cpdef value(self, text)
cpdef float slider(self, text, float val, float vmin, float vmax,
float vinc, bint enabled)
cpdef drawText(self, int x, int y, int align, text, ColorRGBA color)
cpdef drawLine(self, float x0, float y0, float x1, float y1, float r, ColorRGBA color)
cpdef drawRoundedRect(self, float x, float y, float w, float h, float r, ColorRGBA color)
cpdef drawRect(self, float x, float y, float w, float h, ColorRGBA color)
cpdef InitGLExt()
cpdef BlendFunc(unsigned int sfactor, unsigned int dfactor)
cpdef Clear(unsigned int mask)
cpdef ClearColor(ColorRGBA col)
cpdef ClearDepth(double depth)
cpdef Color(ColorRGBA col)
cpdef Disable(unsigned int cap)
cpdef DrawArrays(unsigned int mode, int first, int count)
cpdef DrawElements(unsigned int mode, int count, int type, indices)
cpdef Enable(unsigned int cap)
cpdef LineWidth(float width)
cpdef LightModeli(int pname, int param)
cpdef LoadIdentity()
cpdef LoadMatrixd(Transform tr)
cpdef MatrixMode(unsigned int mode)
cpdef Ortho(double left, double right, double bottom, double top, double zNear,
double zFar)
cpdef PolygonMode(unsigned int face, unsigned int mode)
cpdef Viewport(int x, int y, int width, int height)

37
gltools/gltools.pyx Normal file
View file

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
#cython: embedsignature=True
#
# This file is part of gltools - See LICENSE.txt
#
from geotools cimport *
from GLToolsLib cimport *
class GLError(Exception):
pass
include "Utilities.pxi"
include "Constants.pxi"
include "GLFW.pxi"
include "Color.pxi"
include "GL.pxi"
include "ClientBuffer.pxi"
include "ShaderProgram.pxi"
include "Text.pxi"
include "UI.pxi"
def test2d(double [:, ::1] arr):
for row in range(4):
for col in range(4):
print row, col, arr[row][col]
print
print
def test1d(double [:] vec):
for col in range(4):
print col, vec[col]
print
def test1f(float [:] vec):
for col in range(4):
print col, vec[col]
print

36
gltools/setup_build.py Normal file
View file

@ -0,0 +1,36 @@
#!/usr/bin/python2
# -*- coding: utf-8 -*-
#
# This file is part of gltools - See LICENSE.txt
#
import sys
import os
import glob
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
try:
setup(
name = 'gltools',
ext_modules=[
Extension("gltools",
sources=["gltools.pyx", "@src/GLTools.cpp", "@contrib/fontstash.c",
"@contrib/imgui.cpp", "@contrib/imguiRenderGL.cpp"],
depends = ["gltools.pxd",] + glob.glob("@src/*.pxi") + \
glob.glob("@src/*.pxd") + glob.glob("@src/*.h"),
include_dirs = ['@src','@contrib'],
libraries = ["GL", "glfw"],
extra_compile_args = ["-fpermissive"],
language="c++"
),
],
cmdclass = {'build_ext': build_ext}
)
except:
print('Traceback\n:%s\n' % str(sys.exc_info()[-2]))
sys.exit(1)
else:
print('\n')

366
gltools/test.py Normal file
View file

@ -0,0 +1,366 @@
# -*- coding: utf-8 -*-
import sys
import array
import geotools as geo
import gltools as gl
# cube
# v6----- v5
# /| /|
# v1------v0|
# | | | |
# | |v7---|-|v4
# |/ |/
# v2------v3
vertices = array.array('f',(
1, 1, 1, -1, 1, 1, -1,-1, 1, 1,-1, 1, # v0,v1,v2,v3 (front)
1, 1, 1, 1,-1, 1, 1,-1,-1, 1, 1,-1, # v0,v3,v4,v5 (right)
1, 1, 1, 1, 1,-1, -1, 1,-1, -1, 1, 1, # v0,v5,v6,v1 (top)
-1, 1, 1, -1, 1,-1, -1,-1,-1, -1,-1, 1, # v1,v6,v7,v2 (left)
-1,-1,-1, 1,-1,-1, 1,-1, 1, -1,-1, 1, # v7,v4,v3,v2 (bottom)
1,-1,-1, -1,-1,-1, -1, 1,-1, 1, 1,-1, # v4,v7,v6,v5 (back)
))
normals = array.array('f',(
0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, # v0,v1,v2,v3 (front)
1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, # v0,v3,v4,v5 (right)
0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, # v0,v5,v6,v1 (top)
-1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, # v1,v6,v7,v2 (left)
0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, # v7,v4,v3,v2 (bottom)
0, 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, # v4,v7,v6,v5 (back)
))
colors = array.array('f',(
1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, # v0,v1,v2,v3 (front)
1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, # v0,v3,v4,v5 (right)
1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, # v0,v5,v6,v1 (top)
1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, # v1,v6,v7,v2 (left)
0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, # v7,v4,v3,v2 (bottom)
0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, # v4,v7,v6,v5 (back)
))
indices = array.array('B',(
0, 1, 2, 2, 3, 0, # front
4, 5, 6, 6, 7, 4, # right
8, 9,10, 10,11, 8, # top
12,13,14, 14,15,12, # left
16,17,18, 18,19,16, # bottom
20,21,22, 22,23,20, # back
))
GLSL_VERTEX = \
"""
varying vec3 vN;
varying vec3 v;
void main(void)
{
v = vec3(gl_ModelViewMatrix * gl_Vertex);
vN = normalize(gl_NormalMatrix * gl_Normal);
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
"""
GLSL_FRAG = \
"""
varying vec3 vN;
varying vec3 v;
#define MAX_LIGHTS 3
void main (void)
{
vec3 N = normalize(vN);
vec4 finalColor = vec4(0.0, 0.0, 0.0, 0.0);
for (int i=0;i<MAX_LIGHTS;i++)
{
vec3 L = normalize(gl_LightSource[i].position.xyz - v);
vec3 E = normalize(-v); // we are in Eye Coordinates, so EyePos is (0,0,0)
vec3 R = normalize(-reflect(L,N));
//calculate Ambient Term:
vec4 Iamb = gl_FrontLightProduct[i].ambient;
//calculate Diffuse Term:
vec4 Idiff = gl_FrontLightProduct[i].diffuse * max(dot(N,L), 0.0);
Idiff = clamp(Idiff, 0.0, 1.0);
// calculate Specular Term:
vec4 Ispec = gl_FrontLightProduct[i].specular
* pow(max(dot(R,E),0.0),0.3*gl_FrontMaterial.shininess);
Ispec = clamp(Ispec, 0.0, 1.0);
finalColor += Iamb + Idiff + Ispec;
}
// write Total Color:
gl_FragColor = gl_FrontLightModelProduct.sceneColor + finalColor;
}
"""
class MainWindow(gl.Window):
def __init__(self, width, height, title):
self.initialized = False
self.cam = geo.Camera()
self.near = geo.Point(-2.,-2.,-2.)
self.far = geo.Point(2.,2.,2.)
self.lastPos = 0,0
self.currentButton = -1
gl.Window.__init__(self, width, height, title)
self.projectionMatrix = geo.Transform()
self.modelviewMatrix = geo.Transform()
def onSetup(self):
self.ui = gl.UI()
gl.ClearColor(gl.ColorRGBA(38,38,102,255))
gl.ClearDepth(1.)
gl.InitGLExt()
# Material & lights
mat = self.mat = gl.Material(
ambient = gl.ColorRGBA(80,80,80,255),
diffuse = gl.ColorRGBA(45,45,45,255),
specular = gl.ColorRGBA(255,255,255,255),
shininess = 100.,
)
lightMat = gl.Material(
diffuse = gl.ColorRGBA(255,255,55,255),
ambient = gl.ColorRGBA(55,55,25,255),
specular = gl.ColorRGBA(255,255,255,255)
)
light0 = self.light0 = gl.Light(
0,
lightMat,
geo.Point(0.,50.,100.),
)
light1 = self.light1 = gl.Light(
1,
lightMat,
geo.Point(50.,0.,-100.),
)
light2 = self.light2 = gl.Light(
2,
lightMat,
geo.Point(0.,-50.,0.),
)
# GLSL
glsl = self.program = gl.ShaderProgram()
glsl.build(GLSL_VERTEX, GLSL_FRAG)
# mesh
fsize = vertices.itemsize
buffer = self.buffer = gl.ClientBuffer()
buffer.loadData(None, (len(vertices) + len(normals))*fsize)
offset = 0
size = len(vertices)*fsize
buffer.setDataType(gl.VERTEX_ARRAY, gl.FLOAT, 3, 0, 0)
buffer.loadData(vertices, size, offset) # copy vertices starting from 0 offest
offset += size
size = len(normals)*fsize
buffer.setDataType(gl.NORMAL_ARRAY, gl.FLOAT, 3, 0, offset)
buffer.loadData(normals, size, offset) # copy normals after vertices
offset += size
# index buffer
idxbuffer = self.idxbuffer = gl.ClientBuffer(gl.ELEMENT_ARRAY_BUFFER)
idxbuffer.loadData(indices, len(indices)*indices.itemsize)
def onSize(self, w, h):
#print 'onSize ', w, h
self.width, self.height = w - 1, h - 1
if self.width > 1 and self.height > 1:
# Adjust frustum to viewport aspect
frustum_aspect = float(self.width) / self.height
self.cam.setFrustumAspect(frustum_aspect)
self.cam.setViewportSize(self.width, self.height)
self.makeContextCurrent()
gl.Viewport(0, 0, self.width, self.height)
# initialize
if not self.initialized:
self.onSetup()
self.cam.zoomExtents(self.near, self.far)
self.initialized = True
def insideUI(self, x, y):
y = self.height - y
if x >= 10 and x <= 200:
if y >= 10 and y <= self.height - 300:
return True
return False
def onRefresh(self):
#print 'onRefresh'
if not self.running:
return
ui = self.ui
glsl = self.program
x, y = self.lastPos
w, h = self.width, self.height
self.makeContextCurrent()
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
gl.Enable(gl.DEPTH_TEST)
gl.Enable(gl.MULTISAMPLE)
gl.Enable(gl.DITHER)
gl.Disable(gl.BLEND)
gl.Disable(gl.CULL_FACE)
gl.PolygonMode(gl.FRONT_AND_BACK, gl.FILL)
gl.LightModeli(gl.LIGHT_MODEL_TWO_SIDE, gl.TRUE)
gl.MatrixMode(gl.PROJECTION)
self.projectionMatrix.cameraToClip(self.cam)
gl.LoadMatrixd(self.projectionMatrix)
gl.MatrixMode(gl.MODELVIEW)
self.modelviewMatrix.worldToCamera(self.cam)
gl.LoadMatrixd(self.modelviewMatrix)
gl.Enable(gl.LIGHTING)
self.light0.enable()
self.light1.enable()
self.light2.enable()
self.mat.enable()
glsl.begin()
self.buffer.bind()
self.idxbuffer.bind()
gl.DrawElements(gl.TRIANGLES, 36, gl.UNSIGNED_BYTE, 0)
self.buffer.unBind()
self.idxbuffer.unBind()
glsl.end()
# draw font overlay
gl.Disable(gl.DEPTH_TEST)
gl.Disable(gl.LIGHTING)
gl.Disable(gl.DITHER)
gl.Enable(gl.BLEND)
gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
gl.MatrixMode(gl.PROJECTION)
gl.LoadIdentity()
gl.Ortho(0,self.width,0,self.height,-1,1)
gl.MatrixMode(gl.MODELVIEW)
gl.LoadIdentity()
ui.beginFrame(x,h - y,self.currentButton,0)
ui.beginScrollArea("Scroll Area", 10, 10, 200, h-300)
ui.label('Label test')
ui.value(u'Value æøå')
ui.separatorLine()
ui.item('Item 1', True)
ui.indent()
ui.item('Item 2', False)
ui.separator()
ui.item('Item 3', True)
ui.unindent()
if ui.button("Button 1", True):
print 'Button 1 pressed'
ui.button("Button 2", False)
ui.separator()
ui.check("Check 1", True, True)
ui.check("Check 2", False, True)
ui.check("Check 3", False, False)
ui.separatorLine()
ui.slider('Slider 1', 5, 0, 10, 1, True)
ui.slider('Slider 2', 5, 0, 10, 1, False)
ui.separatorLine()
ui.collapse('Text line', 'Sub text line', True, True)
ui.collapse('Text line', 'Sub text line', False, True)
ui.endScrollArea()
ui.endFrame()
ui.flush()
gl.Enable(gl.DEPTH_TEST)
self.swapBuffers()
def onCursorPos(self, x, y):
width, height = self.width, self.height
lastx,lasty = self.lastPos
cam = self.cam
ui = self.insideUI(x, y)
if not ui and self.currentButton == gl.MOUSE.LEFT:
# rotate view
dx = x - lastx
dy = y - lasty
if dx != 0:
cam.rotateCamera(0.001*dx, geo.Vector(0.,0.,1.), cam.target)
if dy != 0:
cam.rotateCamera(0.001*dy, cam.X, cam.target)
elif not ui and self.currentButton == gl.MOUSE.RIGHT:
# pan view
d = geo.dot(geo.Vector(cam.Loc - cam.target), cam.Z)
dolly_vector = cam.getDollyCameraVector(lastx,lasty,x,y,d)
cam.Loc += dolly_vector
#print 'onCursorPos ', x, y
self.lastPos = x, y
self.onRefresh()
def onMouseButton(self, button, action):
#print 'onMouseButton ', button, action
if action == gl.ACTION.PRESS:
if button in {gl.MOUSE.LEFT, gl.MOUSE.RIGHT}:
self.currentButton = button
else:
self.currentButton = -1
self.onRefresh()
def onKey(self, key, action):
#print 'onKey ', key, action
if key == gl.KEY.ESCAPE:
self.running = False
def onChar(self, ch):
#print 'onChar ', ch
if ch == 'f':
self.cam.zoomExtents(self.near, self.far)
self.onRefresh()
def onScroll(self, scx, scy):
x, y = self.lastPos
if self.insideUI(x, y):
return
delta = 1e-4*scy
dx = delta*self.width
dy = delta*self.height
self.cam.zoomFactor(1. + max(dx,dy), (x, y))
self.onRefresh()
def onClose(self):
#print 'onClose'
return True
win = MainWindow(800, 600, title = u'title')
win.mainLoop()