Compare commits
No commits in common. "master" and "gh-pages" have entirely different histories.
1
.gitattributes
vendored
|
|
@ -1 +0,0 @@
|
|||
* text=auto
|
||||
55
.gitignore
vendored
|
|
@ -1,55 +0,0 @@
|
|||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
bin/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
.tox/
|
||||
.coverage
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
|
||||
# Mr Developer
|
||||
.mr.developer.cfg
|
||||
.project
|
||||
.pydevproject
|
||||
|
||||
# Rope
|
||||
.ropeproject
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
*.pot
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# gltools build
|
||||
MANIFEST
|
||||
0
.nojekyll
Normal file
368
LICENSE.txt
|
|
@ -1,368 +0,0 @@
|
|||
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.
|
||||
10
MANIFEST.in
|
|
@ -1,10 +0,0 @@
|
|||
include Makefile
|
||||
include setup_build.py
|
||||
include setup_docs.py
|
||||
include version.py
|
||||
include MANIFEST.in
|
||||
include README.rst
|
||||
include LICENSE.txt
|
||||
recursive-include gltools *.py *.pyx *.pxi *.pxd *.rst
|
||||
recursive-include gltools *.cpp *.c *.h
|
||||
prune gltools/@arch
|
||||
38
Makefile
|
|
@ -1,38 +0,0 @@
|
|||
#
|
||||
# File: Makefile (for library)
|
||||
#
|
||||
# The variables 'PYTHON' and 'PYVER' can be modified by
|
||||
# passing parameters to make: make PYTHON=python PYVER=2.6
|
||||
#
|
||||
PYTHON=python2
|
||||
PYVER=2.7
|
||||
|
||||
.PHONY: all docs test install clean
|
||||
|
||||
all:
|
||||
@echo lib Makefile - building python extension
|
||||
$(PYTHON) setup_build.py build_ext --inplace
|
||||
|
||||
docs: all
|
||||
@echo lib Makefile - building documentation
|
||||
@cd gltools/@docs ; $(PYTHON) ../../setup_docs.py build_sphinx
|
||||
@cp -rf gltools/@docs/build/sphinx/html/* gltools/@docs/html/
|
||||
|
||||
install: all
|
||||
@cp gltools.so ~/.local/lib/python$(PYVER)/site-packages/
|
||||
@cp gltools/gltools.pxd ~/.local/lib/python$(PYVER)/site-packages/
|
||||
|
||||
sdist: clean
|
||||
@echo lib Makefile - creating source distribution
|
||||
$(PYTHON) setup_build.py sdist --formats=gztar,zip
|
||||
|
||||
clean:
|
||||
-rm -rf build dist
|
||||
-rm -rf gltools/@docs/build
|
||||
-rm gltools/@src/Config.pxi
|
||||
-rm gltools/gltools.cpp gltools.so gltools/gltools.so MANIFEST
|
||||
-find gltools -iname '*.so' -exec rm {} \;
|
||||
-find gltools -iname '*.dll' -exec rm {} \;
|
||||
-find gltools -iname '*.pyc' -exec rm {} \;
|
||||
-find gltools -iname '*.pyo' -exec rm {} \;
|
||||
-find gltools -iname '*.pyd' -exec rm {} \;
|
||||
49
README.rst
|
|
@ -1,49 +0,0 @@
|
|||
Introduction
|
||||
============
|
||||
|
||||
gltools is library for quickly creating OpenGL based
|
||||
application in Python/Cython with support for:
|
||||
|
||||
* Access to vertex buffers and GLSL shaders
|
||||
* Access to truetype fonts
|
||||
* Windows handling through GLFW
|
||||
* Saving framebuffer content to PNG file.
|
||||
* 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.7/3.x and Cython 0.17 or later.
|
||||
* The geotools_ library.
|
||||
* GLFW_ v3.0
|
||||
* OpenGL headers
|
||||
|
||||
For Linux build scripts are available for ArchLinux in the AUR_
|
||||
repository. These could be adapted to other Linux distros.
|
||||
|
||||
History
|
||||
=======
|
||||
|
||||
* v0.2.1 : Updated to released version of GLFW3
|
||||
* v0.1.1 : Added missing files and fix building against GLFW3 trunk.
|
||||
|
||||
Documentation
|
||||
=============
|
||||
|
||||
See online Sphinx docs_
|
||||
|
||||
.. _docs: http://tenko.github.com/gltools/index.html
|
||||
|
||||
.. _geotools: http://github.com/tenko/geotools
|
||||
|
||||
.. _GLFW: http://github.com/elmindreda/glfw
|
||||
|
||||
.. _pypi: http://pypi.python.org/pypi/gltools
|
||||
|
||||
.. _AUR: https://aur.archlinux.org/packages/?O=0&K=gltools
|
||||
BIN
_static/ajax-loader.gif
Normal file
|
After Width: | Height: | Size: 673 B |
540
_static/basic.css
Normal file
|
|
@ -0,0 +1,540 @@
|
|||
/*
|
||||
* basic.css
|
||||
* ~~~~~~~~~
|
||||
*
|
||||
* Sphinx stylesheet -- basic theme.
|
||||
*
|
||||
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
/* -- main layout ----------------------------------------------------------- */
|
||||
|
||||
div.clearer {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* -- relbar ---------------------------------------------------------------- */
|
||||
|
||||
div.related {
|
||||
width: 100%;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
div.related h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.related ul {
|
||||
margin: 0;
|
||||
padding: 0 0 0 10px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
div.related li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.related li.right {
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
/* -- sidebar --------------------------------------------------------------- */
|
||||
|
||||
div.sphinxsidebarwrapper {
|
||||
padding: 10px 5px 0 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
float: left;
|
||||
width: 230px;
|
||||
margin-left: -100%;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul ul,
|
||||
div.sphinxsidebar ul.want-points {
|
||||
margin-left: 20px;
|
||||
list-style: square;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar form {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #98dbcc;
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar #searchbox input[type="text"] {
|
||||
width: 170px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar #searchbox input[type="submit"] {
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/* -- search page ----------------------------------------------------------- */
|
||||
|
||||
ul.search {
|
||||
margin: 10px 0 0 20px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul.search li {
|
||||
padding: 5px 0 5px 20px;
|
||||
background-image: url(file.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0 7px;
|
||||
}
|
||||
|
||||
ul.search li a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
ul.search li div.context {
|
||||
color: #888;
|
||||
margin: 2px 0 0 30px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
ul.keywordmatches li.goodmatch a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* -- index page ------------------------------------------------------------ */
|
||||
|
||||
table.contentstable {
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
table.contentstable p.biglink {
|
||||
line-height: 150%;
|
||||
}
|
||||
|
||||
a.biglink {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
span.linkdescr {
|
||||
font-style: italic;
|
||||
padding-top: 5px;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
/* -- general index --------------------------------------------------------- */
|
||||
|
||||
table.indextable {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table.indextable td {
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table.indextable dl, table.indextable dd {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
table.indextable tr.pcap {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
table.indextable tr.cap {
|
||||
margin-top: 10px;
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
img.toggler {
|
||||
margin-right: 3px;
|
||||
margin-top: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.modindex-jumpbox {
|
||||
border-top: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin: 1em 0 1em 0;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
div.genindex-jumpbox {
|
||||
border-top: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin: 1em 0 1em 0;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
/* -- general body styles --------------------------------------------------- */
|
||||
|
||||
a.headerlink {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
h1:hover > a.headerlink,
|
||||
h2:hover > a.headerlink,
|
||||
h3:hover > a.headerlink,
|
||||
h4:hover > a.headerlink,
|
||||
h5:hover > a.headerlink,
|
||||
h6:hover > a.headerlink,
|
||||
dt:hover > a.headerlink {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
div.body p.caption {
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
div.body td {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.field-list ul {
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.first {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
p.rubric {
|
||||
margin-top: 30px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
img.align-left, .figure.align-left, object.align-left {
|
||||
clear: left;
|
||||
float: left;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
img.align-right, .figure.align-right, object.align-right {
|
||||
clear: right;
|
||||
float: right;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
img.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* -- sidebars -------------------------------------------------------------- */
|
||||
|
||||
div.sidebar {
|
||||
margin: 0 0 0.5em 1em;
|
||||
border: 1px solid #ddb;
|
||||
padding: 7px 7px 0 7px;
|
||||
background-color: #ffe;
|
||||
width: 40%;
|
||||
float: right;
|
||||
}
|
||||
|
||||
p.sidebar-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* -- topics ---------------------------------------------------------------- */
|
||||
|
||||
div.topic {
|
||||
border: 1px solid #ccc;
|
||||
padding: 7px 7px 0 7px;
|
||||
margin: 10px 0 10px 0;
|
||||
}
|
||||
|
||||
p.topic-title {
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* -- admonitions ----------------------------------------------------------- */
|
||||
|
||||
div.admonition {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
padding: 7px;
|
||||
}
|
||||
|
||||
div.admonition dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.admonition dl {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
margin: 0px 10px 5px 0px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.body p.centered {
|
||||
text-align: center;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
/* -- tables ---------------------------------------------------------------- */
|
||||
|
||||
table.docutils {
|
||||
border: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table.docutils td, table.docutils th {
|
||||
padding: 1px 8px 1px 5px;
|
||||
border-top: 0;
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
|
||||
table.field-list td, table.field-list th {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
table.footnote td, table.footnote th {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
table.citation {
|
||||
border-left: solid 1px gray;
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
table.citation td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/* -- other body styles ----------------------------------------------------- */
|
||||
|
||||
ol.arabic {
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
ol.loweralpha {
|
||||
list-style: lower-alpha;
|
||||
}
|
||||
|
||||
ol.upperalpha {
|
||||
list-style: upper-alpha;
|
||||
}
|
||||
|
||||
ol.lowerroman {
|
||||
list-style: lower-roman;
|
||||
}
|
||||
|
||||
ol.upperroman {
|
||||
list-style: upper-roman;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
dd p {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
dd ul, dd table {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
dt:target, .highlighted {
|
||||
background-color: #fbe54e;
|
||||
}
|
||||
|
||||
dl.glossary dt {
|
||||
font-weight: bold;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.field-list ul {
|
||||
margin: 0;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.field-list p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.refcount {
|
||||
color: #060;
|
||||
}
|
||||
|
||||
.optional {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.versionmodified {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.system-message {
|
||||
background-color: #fda;
|
||||
padding: 5px;
|
||||
border: 3px solid red;
|
||||
}
|
||||
|
||||
.footnote:target {
|
||||
background-color: #ffa;
|
||||
}
|
||||
|
||||
.line-block {
|
||||
display: block;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.line-block .line-block {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
margin-left: 1.5em;
|
||||
}
|
||||
|
||||
.guilabel, .menuselection {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.accelerator {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.classifier {
|
||||
font-style: oblique;
|
||||
}
|
||||
|
||||
abbr, acronym {
|
||||
border-bottom: dotted 1px;
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
/* -- code displays --------------------------------------------------------- */
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
overflow-y: hidden; /* fixes display issues on Chrome browsers */
|
||||
}
|
||||
|
||||
td.linenos pre {
|
||||
padding: 5px 0px;
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
table.highlighttable {
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
table.highlighttable td {
|
||||
padding: 0 0.5em 0 0.5em;
|
||||
}
|
||||
|
||||
tt.descname {
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
tt.descclassname {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
tt.xref, a tt {
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.viewcode-link {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.viewcode-back {
|
||||
float: right;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
div.viewcode-block:target {
|
||||
margin: -1px -10px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
/* -- math display ---------------------------------------------------------- */
|
||||
|
||||
img.math {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
div.body div.math p {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
span.eqno {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* -- printout stylesheet --------------------------------------------------- */
|
||||
|
||||
@media print {
|
||||
div.document,
|
||||
div.documentwrapper,
|
||||
div.bodywrapper {
|
||||
margin: 0 !important;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.sphinxsidebar,
|
||||
div.related,
|
||||
div.footer,
|
||||
#top-link {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
BIN
_static/comment-bright.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
_static/comment-close.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
_static/comment.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
256
_static/default.css
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
* default.css_t
|
||||
* ~~~~~~~~~~~~~
|
||||
*
|
||||
* Sphinx stylesheet -- default theme.
|
||||
*
|
||||
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
@import url("basic.css");
|
||||
|
||||
/* -- page layout ----------------------------------------------------------- */
|
||||
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
font-size: 100%;
|
||||
background-color: #11303d;
|
||||
color: #000;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.document {
|
||||
background-color: #1c4e63;
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0 0 0 230px;
|
||||
}
|
||||
|
||||
div.body {
|
||||
background-color: #ffffff;
|
||||
color: #000000;
|
||||
padding: 0 20px 30px 20px;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
color: #ffffff;
|
||||
width: 100%;
|
||||
padding: 9px 0 9px 0;
|
||||
text-align: center;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
div.footer a {
|
||||
color: #ffffff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div.related {
|
||||
background-color: #133f52;
|
||||
line-height: 30px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
div.related a {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 {
|
||||
font-family: 'Trebuchet MS', sans-serif;
|
||||
color: #ffffff;
|
||||
font-size: 1.4em;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 a {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h4 {
|
||||
font-family: 'Trebuchet MS', sans-serif;
|
||||
color: #ffffff;
|
||||
font-size: 1.3em;
|
||||
font-weight: normal;
|
||||
margin: 5px 0 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p.topless {
|
||||
margin: 5px 10px 10px 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
margin: 10px;
|
||||
padding: 0;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a {
|
||||
color: #98dbcc;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #98dbcc;
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -- hyperlink styles ------------------------------------------------------ */
|
||||
|
||||
a {
|
||||
color: #355f7c;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #355f7c;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -- body styles ----------------------------------------------------------- */
|
||||
|
||||
div.body h1,
|
||||
div.body h2,
|
||||
div.body h3,
|
||||
div.body h4,
|
||||
div.body h5,
|
||||
div.body h6 {
|
||||
font-family: 'Trebuchet MS', sans-serif;
|
||||
background-color: #f2f2f2;
|
||||
font-weight: normal;
|
||||
color: #20435c;
|
||||
border-bottom: 1px solid #ccc;
|
||||
margin: 20px -20px 10px -20px;
|
||||
padding: 3px 0 3px 10px;
|
||||
}
|
||||
|
||||
div.body h1 { margin-top: 0; font-size: 200%; }
|
||||
div.body h2 { font-size: 160%; }
|
||||
div.body h3 { font-size: 140%; }
|
||||
div.body h4 { font-size: 120%; }
|
||||
div.body h5 { font-size: 110%; }
|
||||
div.body h6 { font-size: 100%; }
|
||||
|
||||
a.headerlink {
|
||||
color: #c60f0f;
|
||||
font-size: 0.8em;
|
||||
padding: 0 4px 0 4px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.headerlink:hover {
|
||||
background-color: #c60f0f;
|
||||
color: white;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li {
|
||||
text-align: justify;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
div.admonition p.admonition-title + p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.admonition p {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
div.admonition pre {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
div.admonition ul, div.admonition ol {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
div.note {
|
||||
background-color: #eee;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.seealso {
|
||||
background-color: #ffc;
|
||||
border: 1px solid #ff6;
|
||||
}
|
||||
|
||||
div.topic {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
div.warning {
|
||||
background-color: #ffe4e4;
|
||||
border: 1px solid #f66;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
p.admonition-title:after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 5px;
|
||||
background-color: #eeffcc;
|
||||
color: #333333;
|
||||
line-height: 120%;
|
||||
border: 1px solid #ac9;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
tt {
|
||||
background-color: #ecf0f3;
|
||||
padding: 0 1px 0 1px;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #ede;
|
||||
}
|
||||
|
||||
.warning tt {
|
||||
background: #efc2c2;
|
||||
}
|
||||
|
||||
.note tt {
|
||||
background: #d6d6d6;
|
||||
}
|
||||
|
||||
.viewcode-back {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
div.viewcode-block:target {
|
||||
background-color: #f4debf;
|
||||
border-top: 1px solid #ac9;
|
||||
border-bottom: 1px solid #ac9;
|
||||
}
|
||||
247
_static/doctools.js
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
* doctools.js
|
||||
* ~~~~~~~~~~~
|
||||
*
|
||||
* Sphinx JavaScript utilities for all documentation.
|
||||
*
|
||||
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* select a different prefix for underscore
|
||||
*/
|
||||
$u = _.noConflict();
|
||||
|
||||
/**
|
||||
* make the code below compatible with browsers without
|
||||
* an installed firebug like debugger
|
||||
if (!window.console || !console.firebug) {
|
||||
var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
|
||||
"dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
|
||||
"profile", "profileEnd"];
|
||||
window.console = {};
|
||||
for (var i = 0; i < names.length; ++i)
|
||||
window.console[names[i]] = function() {};
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* small helper function to urldecode strings
|
||||
*/
|
||||
jQuery.urldecode = function(x) {
|
||||
return decodeURIComponent(x).replace(/\+/g, ' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* small helper function to urlencode strings
|
||||
*/
|
||||
jQuery.urlencode = encodeURIComponent;
|
||||
|
||||
/**
|
||||
* This function returns the parsed url parameters of the
|
||||
* current request. Multiple values per key are supported,
|
||||
* it will always return arrays of strings for the value parts.
|
||||
*/
|
||||
jQuery.getQueryParameters = function(s) {
|
||||
if (typeof s == 'undefined')
|
||||
s = document.location.search;
|
||||
var parts = s.substr(s.indexOf('?') + 1).split('&');
|
||||
var result = {};
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
var tmp = parts[i].split('=', 2);
|
||||
var key = jQuery.urldecode(tmp[0]);
|
||||
var value = jQuery.urldecode(tmp[1]);
|
||||
if (key in result)
|
||||
result[key].push(value);
|
||||
else
|
||||
result[key] = [value];
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* small function to check if an array contains
|
||||
* a given item.
|
||||
*/
|
||||
jQuery.contains = function(arr, item) {
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (arr[i] == item)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* highlight a given string on a jquery object by wrapping it in
|
||||
* span elements with the given class name.
|
||||
*/
|
||||
jQuery.fn.highlightText = function(text, className) {
|
||||
function highlight(node) {
|
||||
if (node.nodeType == 3) {
|
||||
var val = node.nodeValue;
|
||||
var pos = val.toLowerCase().indexOf(text);
|
||||
if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) {
|
||||
var span = document.createElement("span");
|
||||
span.className = className;
|
||||
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
|
||||
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
|
||||
document.createTextNode(val.substr(pos + text.length)),
|
||||
node.nextSibling));
|
||||
node.nodeValue = val.substr(0, pos);
|
||||
}
|
||||
}
|
||||
else if (!jQuery(node).is("button, select, textarea")) {
|
||||
jQuery.each(node.childNodes, function() {
|
||||
highlight(this);
|
||||
});
|
||||
}
|
||||
}
|
||||
return this.each(function() {
|
||||
highlight(this);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Small JavaScript module for the documentation.
|
||||
*/
|
||||
var Documentation = {
|
||||
|
||||
init : function() {
|
||||
this.fixFirefoxAnchorBug();
|
||||
this.highlightSearchWords();
|
||||
this.initIndexTable();
|
||||
},
|
||||
|
||||
/**
|
||||
* i18n support
|
||||
*/
|
||||
TRANSLATIONS : {},
|
||||
PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; },
|
||||
LOCALE : 'unknown',
|
||||
|
||||
// gettext and ngettext don't access this so that the functions
|
||||
// can safely bound to a different name (_ = Documentation.gettext)
|
||||
gettext : function(string) {
|
||||
var translated = Documentation.TRANSLATIONS[string];
|
||||
if (typeof translated == 'undefined')
|
||||
return string;
|
||||
return (typeof translated == 'string') ? translated : translated[0];
|
||||
},
|
||||
|
||||
ngettext : function(singular, plural, n) {
|
||||
var translated = Documentation.TRANSLATIONS[singular];
|
||||
if (typeof translated == 'undefined')
|
||||
return (n == 1) ? singular : plural;
|
||||
return translated[Documentation.PLURALEXPR(n)];
|
||||
},
|
||||
|
||||
addTranslations : function(catalog) {
|
||||
for (var key in catalog.messages)
|
||||
this.TRANSLATIONS[key] = catalog.messages[key];
|
||||
this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
|
||||
this.LOCALE = catalog.locale;
|
||||
},
|
||||
|
||||
/**
|
||||
* add context elements like header anchor links
|
||||
*/
|
||||
addContextElements : function() {
|
||||
$('div[id] > :header:first').each(function() {
|
||||
$('<a class="headerlink">\u00B6</a>').
|
||||
attr('href', '#' + this.id).
|
||||
attr('title', _('Permalink to this headline')).
|
||||
appendTo(this);
|
||||
});
|
||||
$('dt[id]').each(function() {
|
||||
$('<a class="headerlink">\u00B6</a>').
|
||||
attr('href', '#' + this.id).
|
||||
attr('title', _('Permalink to this definition')).
|
||||
appendTo(this);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* workaround a firefox stupidity
|
||||
*/
|
||||
fixFirefoxAnchorBug : function() {
|
||||
if (document.location.hash && $.browser.mozilla)
|
||||
window.setTimeout(function() {
|
||||
document.location.href += '';
|
||||
}, 10);
|
||||
},
|
||||
|
||||
/**
|
||||
* highlight the search words provided in the url in the text
|
||||
*/
|
||||
highlightSearchWords : function() {
|
||||
var params = $.getQueryParameters();
|
||||
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
|
||||
if (terms.length) {
|
||||
var body = $('div.body');
|
||||
window.setTimeout(function() {
|
||||
$.each(terms, function() {
|
||||
body.highlightText(this.toLowerCase(), 'highlighted');
|
||||
});
|
||||
}, 10);
|
||||
$('<p class="highlight-link"><a href="javascript:Documentation.' +
|
||||
'hideSearchWords()">' + _('Hide Search Matches') + '</a></p>')
|
||||
.appendTo($('#searchbox'));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* init the domain index toggle buttons
|
||||
*/
|
||||
initIndexTable : function() {
|
||||
var togglers = $('img.toggler').click(function() {
|
||||
var src = $(this).attr('src');
|
||||
var idnum = $(this).attr('id').substr(7);
|
||||
$('tr.cg-' + idnum).toggle();
|
||||
if (src.substr(-9) == 'minus.png')
|
||||
$(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
|
||||
else
|
||||
$(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
|
||||
}).css('display', '');
|
||||
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
|
||||
togglers.click();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* helper function to hide the search marks again
|
||||
*/
|
||||
hideSearchWords : function() {
|
||||
$('#searchbox .highlight-link').fadeOut(300);
|
||||
$('span.highlighted').removeClass('highlighted');
|
||||
},
|
||||
|
||||
/**
|
||||
* make the url absolute
|
||||
*/
|
||||
makeURL : function(relativeURL) {
|
||||
return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
|
||||
},
|
||||
|
||||
/**
|
||||
* get the current relative url
|
||||
*/
|
||||
getCurrentURL : function() {
|
||||
var path = document.location.pathname;
|
||||
var parts = path.split(/\//);
|
||||
$.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
|
||||
if (this == '..')
|
||||
parts.pop();
|
||||
});
|
||||
var url = parts.join('/');
|
||||
return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
|
||||
}
|
||||
};
|
||||
|
||||
// quick alias for translations
|
||||
_ = Documentation.gettext;
|
||||
|
||||
$(document).ready(function() {
|
||||
Documentation.init();
|
||||
});
|
||||
BIN
_static/down-pressed.png
Normal file
|
After Width: | Height: | Size: 368 B |
BIN
_static/down.png
Normal file
|
After Width: | Height: | Size: 363 B |
BIN
_static/file.png
Normal file
|
After Width: | Height: | Size: 392 B |
154
_static/jquery.js
vendored
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
/*!
|
||||
* jQuery JavaScript Library v1.4.2
|
||||
* http://jquery.com/
|
||||
*
|
||||
* Copyright 2010, John Resig
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* Includes Sizzle.js
|
||||
* http://sizzlejs.com/
|
||||
* Copyright 2010, The Dojo Foundation
|
||||
* Released under the MIT, BSD, and GPL Licenses.
|
||||
*
|
||||
* Date: Sat Feb 13 22:33:48 2010 -0500
|
||||
*/
|
||||
(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
|
||||
e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
|
||||
j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
|
||||
"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
|
||||
true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
|
||||
Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
|
||||
(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
|
||||
a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
|
||||
"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
|
||||
function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
|
||||
c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
|
||||
L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
|
||||
"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
|
||||
a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
|
||||
d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
|
||||
a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
|
||||
!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
|
||||
true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
|
||||
var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
|
||||
parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
|
||||
false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
|
||||
s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
|
||||
applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
|
||||
else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
|
||||
a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
|
||||
w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
|
||||
cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
|
||||
i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
|
||||
" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
|
||||
this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
|
||||
e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
|
||||
c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
|
||||
a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
|
||||
function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
|
||||
k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
|
||||
C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
|
||||
null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
|
||||
e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
|
||||
f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
|
||||
if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
|
||||
fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
|
||||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
|
||||
"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
|
||||
a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
|
||||
isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
|
||||
{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
|
||||
if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
|
||||
e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
|
||||
"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
|
||||
d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
|
||||
!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
|
||||
toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
|
||||
u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
|
||||
function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
|
||||
if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
|
||||
e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
|
||||
t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
|
||||
g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
|
||||
for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
|
||||
1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
|
||||
CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
|
||||
relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
|
||||
l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
|
||||
h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
|
||||
CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
|
||||
g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
|
||||
text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
|
||||
setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
|
||||
h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
|
||||
m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
|
||||
"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
|
||||
h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
|
||||
!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
|
||||
h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
|
||||
q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
|
||||
if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
|
||||
(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
|
||||
function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
|
||||
gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
|
||||
c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
|
||||
{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
|
||||
"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
|
||||
d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
|
||||
a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
|
||||
1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
|
||||
a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
|
||||
c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
|
||||
wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
|
||||
prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
|
||||
this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
|
||||
return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
|
||||
""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
|
||||
this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
|
||||
u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
|
||||
1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
|
||||
return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
|
||||
""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
|
||||
c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
|
||||
c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
|
||||
function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
|
||||
Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
|
||||
"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
|
||||
a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
|
||||
a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
|
||||
"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
|
||||
serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
|
||||
function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
|
||||
global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
|
||||
e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
|
||||
"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
|
||||
false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
|
||||
false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
|
||||
c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
|
||||
d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
|
||||
g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
|
||||
1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
|
||||
"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
|
||||
if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
|
||||
this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
|
||||
"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
|
||||
animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
|
||||
j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
|
||||
this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
|
||||
"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
|
||||
c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
|
||||
this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
|
||||
this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
|
||||
e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
|
||||
c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
|
||||
function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
|
||||
this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
|
||||
k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
|
||||
f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
|
||||
a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
|
||||
c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
|
||||
d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
|
||||
f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
|
||||
"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
|
||||
e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
|
||||
BIN
_static/minus.png
Normal file
|
After Width: | Height: | Size: 199 B |
BIN
_static/plus.png
Normal file
|
After Width: | Height: | Size: 199 B |
62
_static/pygments.css
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
.highlight .hll { background-color: #ffffcc }
|
||||
.highlight { background: #eeffcc; }
|
||||
.highlight .c { color: #408090; font-style: italic } /* Comment */
|
||||
.highlight .err { border: 1px solid #FF0000 } /* Error */
|
||||
.highlight .k { color: #007020; font-weight: bold } /* Keyword */
|
||||
.highlight .o { color: #666666 } /* Operator */
|
||||
.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */
|
||||
.highlight .cp { color: #007020 } /* Comment.Preproc */
|
||||
.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */
|
||||
.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
|
||||
.highlight .gd { color: #A00000 } /* Generic.Deleted */
|
||||
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||
.highlight .gr { color: #FF0000 } /* Generic.Error */
|
||||
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
.highlight .gi { color: #00A000 } /* Generic.Inserted */
|
||||
.highlight .go { color: #303030 } /* Generic.Output */
|
||||
.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
|
||||
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
.highlight .gt { color: #0040D0 } /* Generic.Traceback */
|
||||
.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
|
||||
.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
|
||||
.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
|
||||
.highlight .kp { color: #007020 } /* Keyword.Pseudo */
|
||||
.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #902000 } /* Keyword.Type */
|
||||
.highlight .m { color: #208050 } /* Literal.Number */
|
||||
.highlight .s { color: #4070a0 } /* Literal.String */
|
||||
.highlight .na { color: #4070a0 } /* Name.Attribute */
|
||||
.highlight .nb { color: #007020 } /* Name.Builtin */
|
||||
.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
|
||||
.highlight .no { color: #60add5 } /* Name.Constant */
|
||||
.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
|
||||
.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
|
||||
.highlight .ne { color: #007020 } /* Name.Exception */
|
||||
.highlight .nf { color: #06287e } /* Name.Function */
|
||||
.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
|
||||
.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
|
||||
.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
|
||||
.highlight .nv { color: #bb60d5 } /* Name.Variable */
|
||||
.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
|
||||
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
.highlight .mf { color: #208050 } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #208050 } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #208050 } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #208050 } /* Literal.Number.Oct */
|
||||
.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #4070a0 } /* Literal.String.Char */
|
||||
.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
|
||||
.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #c65d09 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #235388 } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #517918 } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
|
||||
.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
|
||||
.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
|
||||
560
_static/searchtools.js
Normal file
|
|
@ -0,0 +1,560 @@
|
|||
/*
|
||||
* searchtools.js_t
|
||||
* ~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* Sphinx JavaScript utilties for the full-text search.
|
||||
*
|
||||
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* helper function to return a node containing the
|
||||
* search summary for a given text. keywords is a list
|
||||
* of stemmed words, hlwords is the list of normal, unstemmed
|
||||
* words. the first one is used to find the occurance, the
|
||||
* latter for highlighting it.
|
||||
*/
|
||||
|
||||
jQuery.makeSearchSummary = function(text, keywords, hlwords) {
|
||||
var textLower = text.toLowerCase();
|
||||
var start = 0;
|
||||
$.each(keywords, function() {
|
||||
var i = textLower.indexOf(this.toLowerCase());
|
||||
if (i > -1)
|
||||
start = i;
|
||||
});
|
||||
start = Math.max(start - 120, 0);
|
||||
var excerpt = ((start > 0) ? '...' : '') +
|
||||
$.trim(text.substr(start, 240)) +
|
||||
((start + 240 - text.length) ? '...' : '');
|
||||
var rv = $('<div class="context"></div>').text(excerpt);
|
||||
$.each(hlwords, function() {
|
||||
rv = rv.highlightText(this, 'highlighted');
|
||||
});
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Porter Stemmer
|
||||
*/
|
||||
var Stemmer = function() {
|
||||
|
||||
var step2list = {
|
||||
ational: 'ate',
|
||||
tional: 'tion',
|
||||
enci: 'ence',
|
||||
anci: 'ance',
|
||||
izer: 'ize',
|
||||
bli: 'ble',
|
||||
alli: 'al',
|
||||
entli: 'ent',
|
||||
eli: 'e',
|
||||
ousli: 'ous',
|
||||
ization: 'ize',
|
||||
ation: 'ate',
|
||||
ator: 'ate',
|
||||
alism: 'al',
|
||||
iveness: 'ive',
|
||||
fulness: 'ful',
|
||||
ousness: 'ous',
|
||||
aliti: 'al',
|
||||
iviti: 'ive',
|
||||
biliti: 'ble',
|
||||
logi: 'log'
|
||||
};
|
||||
|
||||
var step3list = {
|
||||
icate: 'ic',
|
||||
ative: '',
|
||||
alize: 'al',
|
||||
iciti: 'ic',
|
||||
ical: 'ic',
|
||||
ful: '',
|
||||
ness: ''
|
||||
};
|
||||
|
||||
var c = "[^aeiou]"; // consonant
|
||||
var v = "[aeiouy]"; // vowel
|
||||
var C = c + "[^aeiouy]*"; // consonant sequence
|
||||
var V = v + "[aeiou]*"; // vowel sequence
|
||||
|
||||
var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
|
||||
var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
|
||||
var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
|
||||
var s_v = "^(" + C + ")?" + v; // vowel in stem
|
||||
|
||||
this.stemWord = function (w) {
|
||||
var stem;
|
||||
var suffix;
|
||||
var firstch;
|
||||
var origword = w;
|
||||
|
||||
if (w.length < 3)
|
||||
return w;
|
||||
|
||||
var re;
|
||||
var re2;
|
||||
var re3;
|
||||
var re4;
|
||||
|
||||
firstch = w.substr(0,1);
|
||||
if (firstch == "y")
|
||||
w = firstch.toUpperCase() + w.substr(1);
|
||||
|
||||
// Step 1a
|
||||
re = /^(.+?)(ss|i)es$/;
|
||||
re2 = /^(.+?)([^s])s$/;
|
||||
|
||||
if (re.test(w))
|
||||
w = w.replace(re,"$1$2");
|
||||
else if (re2.test(w))
|
||||
w = w.replace(re2,"$1$2");
|
||||
|
||||
// Step 1b
|
||||
re = /^(.+?)eed$/;
|
||||
re2 = /^(.+?)(ed|ing)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
re = new RegExp(mgr0);
|
||||
if (re.test(fp[1])) {
|
||||
re = /.$/;
|
||||
w = w.replace(re,"");
|
||||
}
|
||||
}
|
||||
else if (re2.test(w)) {
|
||||
var fp = re2.exec(w);
|
||||
stem = fp[1];
|
||||
re2 = new RegExp(s_v);
|
||||
if (re2.test(stem)) {
|
||||
w = stem;
|
||||
re2 = /(at|bl|iz)$/;
|
||||
re3 = new RegExp("([^aeiouylsz])\\1$");
|
||||
re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
|
||||
if (re2.test(w))
|
||||
w = w + "e";
|
||||
else if (re3.test(w)) {
|
||||
re = /.$/;
|
||||
w = w.replace(re,"");
|
||||
}
|
||||
else if (re4.test(w))
|
||||
w = w + "e";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 1c
|
||||
re = /^(.+?)y$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
re = new RegExp(s_v);
|
||||
if (re.test(stem))
|
||||
w = stem + "i";
|
||||
}
|
||||
|
||||
// Step 2
|
||||
re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
suffix = fp[2];
|
||||
re = new RegExp(mgr0);
|
||||
if (re.test(stem))
|
||||
w = stem + step2list[suffix];
|
||||
}
|
||||
|
||||
// Step 3
|
||||
re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
suffix = fp[2];
|
||||
re = new RegExp(mgr0);
|
||||
if (re.test(stem))
|
||||
w = stem + step3list[suffix];
|
||||
}
|
||||
|
||||
// Step 4
|
||||
re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
|
||||
re2 = /^(.+?)(s|t)(ion)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
re = new RegExp(mgr1);
|
||||
if (re.test(stem))
|
||||
w = stem;
|
||||
}
|
||||
else if (re2.test(w)) {
|
||||
var fp = re2.exec(w);
|
||||
stem = fp[1] + fp[2];
|
||||
re2 = new RegExp(mgr1);
|
||||
if (re2.test(stem))
|
||||
w = stem;
|
||||
}
|
||||
|
||||
// Step 5
|
||||
re = /^(.+?)e$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
re = new RegExp(mgr1);
|
||||
re2 = new RegExp(meq1);
|
||||
re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
|
||||
if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
|
||||
w = stem;
|
||||
}
|
||||
re = /ll$/;
|
||||
re2 = new RegExp(mgr1);
|
||||
if (re.test(w) && re2.test(w)) {
|
||||
re = /.$/;
|
||||
w = w.replace(re,"");
|
||||
}
|
||||
|
||||
// and turn initial Y back to y
|
||||
if (firstch == "y")
|
||||
w = firstch.toLowerCase() + w.substr(1);
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Search Module
|
||||
*/
|
||||
var Search = {
|
||||
|
||||
_index : null,
|
||||
_queued_query : null,
|
||||
_pulse_status : -1,
|
||||
|
||||
init : function() {
|
||||
var params = $.getQueryParameters();
|
||||
if (params.q) {
|
||||
var query = params.q[0];
|
||||
$('input[name="q"]')[0].value = query;
|
||||
this.performSearch(query);
|
||||
}
|
||||
},
|
||||
|
||||
loadIndex : function(url) {
|
||||
$.ajax({type: "GET", url: url, data: null, success: null,
|
||||
dataType: "script", cache: true});
|
||||
},
|
||||
|
||||
setIndex : function(index) {
|
||||
var q;
|
||||
this._index = index;
|
||||
if ((q = this._queued_query) !== null) {
|
||||
this._queued_query = null;
|
||||
Search.query(q);
|
||||
}
|
||||
},
|
||||
|
||||
hasIndex : function() {
|
||||
return this._index !== null;
|
||||
},
|
||||
|
||||
deferQuery : function(query) {
|
||||
this._queued_query = query;
|
||||
},
|
||||
|
||||
stopPulse : function() {
|
||||
this._pulse_status = 0;
|
||||
},
|
||||
|
||||
startPulse : function() {
|
||||
if (this._pulse_status >= 0)
|
||||
return;
|
||||
function pulse() {
|
||||
Search._pulse_status = (Search._pulse_status + 1) % 4;
|
||||
var dotString = '';
|
||||
for (var i = 0; i < Search._pulse_status; i++)
|
||||
dotString += '.';
|
||||
Search.dots.text(dotString);
|
||||
if (Search._pulse_status > -1)
|
||||
window.setTimeout(pulse, 500);
|
||||
};
|
||||
pulse();
|
||||
},
|
||||
|
||||
/**
|
||||
* perform a search for something
|
||||
*/
|
||||
performSearch : function(query) {
|
||||
// create the required interface elements
|
||||
this.out = $('#search-results');
|
||||
this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out);
|
||||
this.dots = $('<span></span>').appendTo(this.title);
|
||||
this.status = $('<p style="display: none"></p>').appendTo(this.out);
|
||||
this.output = $('<ul class="search"/>').appendTo(this.out);
|
||||
|
||||
$('#search-progress').text(_('Preparing search...'));
|
||||
this.startPulse();
|
||||
|
||||
// index already loaded, the browser was quick!
|
||||
if (this.hasIndex())
|
||||
this.query(query);
|
||||
else
|
||||
this.deferQuery(query);
|
||||
},
|
||||
|
||||
query : function(query) {
|
||||
var stopwords = ["and","then","into","it","as","are","in","if","for","no","there","their","was","is","be","to","that","but","they","not","such","with","by","a","on","these","of","will","this","near","the","or","at"];
|
||||
|
||||
// Stem the searchterms and add them to the correct list
|
||||
var stemmer = new Stemmer();
|
||||
var searchterms = [];
|
||||
var excluded = [];
|
||||
var hlterms = [];
|
||||
var tmp = query.split(/\s+/);
|
||||
var objectterms = [];
|
||||
for (var i = 0; i < tmp.length; i++) {
|
||||
if (tmp[i] != "") {
|
||||
objectterms.push(tmp[i].toLowerCase());
|
||||
}
|
||||
|
||||
if ($u.indexOf(stopwords, tmp[i]) != -1 || tmp[i].match(/^\d+$/) ||
|
||||
tmp[i] == "") {
|
||||
// skip this "word"
|
||||
continue;
|
||||
}
|
||||
// stem the word
|
||||
var word = stemmer.stemWord(tmp[i]).toLowerCase();
|
||||
// select the correct list
|
||||
if (word[0] == '-') {
|
||||
var toAppend = excluded;
|
||||
word = word.substr(1);
|
||||
}
|
||||
else {
|
||||
var toAppend = searchterms;
|
||||
hlterms.push(tmp[i].toLowerCase());
|
||||
}
|
||||
// only add if not already in the list
|
||||
if (!$.contains(toAppend, word))
|
||||
toAppend.push(word);
|
||||
};
|
||||
var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
|
||||
|
||||
// console.debug('SEARCH: searching for:');
|
||||
// console.info('required: ', searchterms);
|
||||
// console.info('excluded: ', excluded);
|
||||
|
||||
// prepare search
|
||||
var filenames = this._index.filenames;
|
||||
var titles = this._index.titles;
|
||||
var terms = this._index.terms;
|
||||
var fileMap = {};
|
||||
var files = null;
|
||||
// different result priorities
|
||||
var importantResults = [];
|
||||
var objectResults = [];
|
||||
var regularResults = [];
|
||||
var unimportantResults = [];
|
||||
$('#search-progress').empty();
|
||||
|
||||
// lookup as object
|
||||
for (var i = 0; i < objectterms.length; i++) {
|
||||
var others = [].concat(objectterms.slice(0,i),
|
||||
objectterms.slice(i+1, objectterms.length))
|
||||
var results = this.performObjectSearch(objectterms[i], others);
|
||||
// Assume first word is most likely to be the object,
|
||||
// other words more likely to be in description.
|
||||
// Therefore put matches for earlier words first.
|
||||
// (Results are eventually used in reverse order).
|
||||
objectResults = results[0].concat(objectResults);
|
||||
importantResults = results[1].concat(importantResults);
|
||||
unimportantResults = results[2].concat(unimportantResults);
|
||||
}
|
||||
|
||||
// perform the search on the required terms
|
||||
for (var i = 0; i < searchterms.length; i++) {
|
||||
var word = searchterms[i];
|
||||
// no match but word was a required one
|
||||
if ((files = terms[word]) == null)
|
||||
break;
|
||||
if (files.length == undefined) {
|
||||
files = [files];
|
||||
}
|
||||
// create the mapping
|
||||
for (var j = 0; j < files.length; j++) {
|
||||
var file = files[j];
|
||||
if (file in fileMap)
|
||||
fileMap[file].push(word);
|
||||
else
|
||||
fileMap[file] = [word];
|
||||
}
|
||||
}
|
||||
|
||||
// now check if the files don't contain excluded terms
|
||||
for (var file in fileMap) {
|
||||
var valid = true;
|
||||
|
||||
// check if all requirements are matched
|
||||
if (fileMap[file].length != searchterms.length)
|
||||
continue;
|
||||
|
||||
// ensure that none of the excluded terms is in the
|
||||
// search result.
|
||||
for (var i = 0; i < excluded.length; i++) {
|
||||
if (terms[excluded[i]] == file ||
|
||||
$.contains(terms[excluded[i]] || [], file)) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if we have still a valid result we can add it
|
||||
// to the result list
|
||||
if (valid)
|
||||
regularResults.push([filenames[file], titles[file], '', null]);
|
||||
}
|
||||
|
||||
// delete unused variables in order to not waste
|
||||
// memory until list is retrieved completely
|
||||
delete filenames, titles, terms;
|
||||
|
||||
// now sort the regular results descending by title
|
||||
regularResults.sort(function(a, b) {
|
||||
var left = a[1].toLowerCase();
|
||||
var right = b[1].toLowerCase();
|
||||
return (left > right) ? -1 : ((left < right) ? 1 : 0);
|
||||
});
|
||||
|
||||
// combine all results
|
||||
var results = unimportantResults.concat(regularResults)
|
||||
.concat(objectResults).concat(importantResults);
|
||||
|
||||
// print the results
|
||||
var resultCount = results.length;
|
||||
function displayNextItem() {
|
||||
// results left, load the summary and display it
|
||||
if (results.length) {
|
||||
var item = results.pop();
|
||||
var listItem = $('<li style="display:none"></li>');
|
||||
if (DOCUMENTATION_OPTIONS.FILE_SUFFIX == '') {
|
||||
// dirhtml builder
|
||||
var dirname = item[0] + '/';
|
||||
if (dirname.match(/\/index\/$/)) {
|
||||
dirname = dirname.substring(0, dirname.length-6);
|
||||
} else if (dirname == 'index/') {
|
||||
dirname = '';
|
||||
}
|
||||
listItem.append($('<a/>').attr('href',
|
||||
DOCUMENTATION_OPTIONS.URL_ROOT + dirname +
|
||||
highlightstring + item[2]).html(item[1]));
|
||||
} else {
|
||||
// normal html builders
|
||||
listItem.append($('<a/>').attr('href',
|
||||
item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX +
|
||||
highlightstring + item[2]).html(item[1]));
|
||||
}
|
||||
if (item[3]) {
|
||||
listItem.append($('<span> (' + item[3] + ')</span>'));
|
||||
Search.output.append(listItem);
|
||||
listItem.slideDown(5, function() {
|
||||
displayNextItem();
|
||||
});
|
||||
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
|
||||
$.get(DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' +
|
||||
item[0] + '.txt', function(data) {
|
||||
if (data != '') {
|
||||
listItem.append($.makeSearchSummary(data, searchterms, hlterms));
|
||||
Search.output.append(listItem);
|
||||
}
|
||||
listItem.slideDown(5, function() {
|
||||
displayNextItem();
|
||||
});
|
||||
}, "text");
|
||||
} else {
|
||||
// no source available, just display title
|
||||
Search.output.append(listItem);
|
||||
listItem.slideDown(5, function() {
|
||||
displayNextItem();
|
||||
});
|
||||
}
|
||||
}
|
||||
// search finished, update title and status message
|
||||
else {
|
||||
Search.stopPulse();
|
||||
Search.title.text(_('Search Results'));
|
||||
if (!resultCount)
|
||||
Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
|
||||
else
|
||||
Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
|
||||
Search.status.fadeIn(500);
|
||||
}
|
||||
}
|
||||
displayNextItem();
|
||||
},
|
||||
|
||||
performObjectSearch : function(object, otherterms) {
|
||||
var filenames = this._index.filenames;
|
||||
var objects = this._index.objects;
|
||||
var objnames = this._index.objnames;
|
||||
var titles = this._index.titles;
|
||||
|
||||
var importantResults = [];
|
||||
var objectResults = [];
|
||||
var unimportantResults = [];
|
||||
|
||||
for (var prefix in objects) {
|
||||
for (var name in objects[prefix]) {
|
||||
var fullname = (prefix ? prefix + '.' : '') + name;
|
||||
if (fullname.toLowerCase().indexOf(object) > -1) {
|
||||
var match = objects[prefix][name];
|
||||
var objname = objnames[match[1]][2];
|
||||
var title = titles[match[0]];
|
||||
// If more than one term searched for, we require other words to be
|
||||
// found in the name/title/description
|
||||
if (otherterms.length > 0) {
|
||||
var haystack = (prefix + ' ' + name + ' ' +
|
||||
objname + ' ' + title).toLowerCase();
|
||||
var allfound = true;
|
||||
for (var i = 0; i < otherterms.length; i++) {
|
||||
if (haystack.indexOf(otherterms[i]) == -1) {
|
||||
allfound = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!allfound) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
var descr = objname + _(', in ') + title;
|
||||
anchor = match[3];
|
||||
if (anchor == '')
|
||||
anchor = fullname;
|
||||
else if (anchor == '-')
|
||||
anchor = objnames[match[1]][1] + '-' + fullname;
|
||||
result = [filenames[match[0]], fullname, '#'+anchor, descr];
|
||||
switch (match[2]) {
|
||||
case 1: objectResults.push(result); break;
|
||||
case 0: importantResults.push(result); break;
|
||||
case 2: unimportantResults.push(result); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sort results descending
|
||||
objectResults.sort(function(a, b) {
|
||||
return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
|
||||
});
|
||||
|
||||
importantResults.sort(function(a, b) {
|
||||
return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
|
||||
});
|
||||
|
||||
unimportantResults.sort(function(a, b) {
|
||||
return (a[1] > b[1]) ? -1 : ((a[1] < b[1]) ? 1 : 0);
|
||||
});
|
||||
|
||||
return [importantResults, objectResults, unimportantResults]
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
Search.init();
|
||||
});
|
||||
151
_static/sidebar.js
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* sidebar.js
|
||||
* ~~~~~~~~~~
|
||||
*
|
||||
* This script makes the Sphinx sidebar collapsible.
|
||||
*
|
||||
* .sphinxsidebar contains .sphinxsidebarwrapper. This script adds
|
||||
* in .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton
|
||||
* used to collapse and expand the sidebar.
|
||||
*
|
||||
* When the sidebar is collapsed the .sphinxsidebarwrapper is hidden
|
||||
* and the width of the sidebar and the margin-left of the document
|
||||
* are decreased. When the sidebar is expanded the opposite happens.
|
||||
* This script saves a per-browser/per-session cookie used to
|
||||
* remember the position of the sidebar among the pages.
|
||||
* Once the browser is closed the cookie is deleted and the position
|
||||
* reset to the default (expanded).
|
||||
*
|
||||
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
$(function() {
|
||||
// global elements used by the functions.
|
||||
// the 'sidebarbutton' element is defined as global after its
|
||||
// creation, in the add_sidebar_button function
|
||||
var bodywrapper = $('.bodywrapper');
|
||||
var sidebar = $('.sphinxsidebar');
|
||||
var sidebarwrapper = $('.sphinxsidebarwrapper');
|
||||
|
||||
// for some reason, the document has no sidebar; do not run into errors
|
||||
if (!sidebar.length) return;
|
||||
|
||||
// original margin-left of the bodywrapper and width of the sidebar
|
||||
// with the sidebar expanded
|
||||
var bw_margin_expanded = bodywrapper.css('margin-left');
|
||||
var ssb_width_expanded = sidebar.width();
|
||||
|
||||
// margin-left of the bodywrapper and width of the sidebar
|
||||
// with the sidebar collapsed
|
||||
var bw_margin_collapsed = '.8em';
|
||||
var ssb_width_collapsed = '.8em';
|
||||
|
||||
// colors used by the current theme
|
||||
var dark_color = $('.related').css('background-color');
|
||||
var light_color = $('.document').css('background-color');
|
||||
|
||||
function sidebar_is_collapsed() {
|
||||
return sidebarwrapper.is(':not(:visible)');
|
||||
}
|
||||
|
||||
function toggle_sidebar() {
|
||||
if (sidebar_is_collapsed())
|
||||
expand_sidebar();
|
||||
else
|
||||
collapse_sidebar();
|
||||
}
|
||||
|
||||
function collapse_sidebar() {
|
||||
sidebarwrapper.hide();
|
||||
sidebar.css('width', ssb_width_collapsed);
|
||||
bodywrapper.css('margin-left', bw_margin_collapsed);
|
||||
sidebarbutton.css({
|
||||
'margin-left': '0',
|
||||
'height': bodywrapper.height()
|
||||
});
|
||||
sidebarbutton.find('span').text('»');
|
||||
sidebarbutton.attr('title', _('Expand sidebar'));
|
||||
document.cookie = 'sidebar=collapsed';
|
||||
}
|
||||
|
||||
function expand_sidebar() {
|
||||
bodywrapper.css('margin-left', bw_margin_expanded);
|
||||
sidebar.css('width', ssb_width_expanded);
|
||||
sidebarwrapper.show();
|
||||
sidebarbutton.css({
|
||||
'margin-left': ssb_width_expanded-12,
|
||||
'height': bodywrapper.height()
|
||||
});
|
||||
sidebarbutton.find('span').text('«');
|
||||
sidebarbutton.attr('title', _('Collapse sidebar'));
|
||||
document.cookie = 'sidebar=expanded';
|
||||
}
|
||||
|
||||
function add_sidebar_button() {
|
||||
sidebarwrapper.css({
|
||||
'float': 'left',
|
||||
'margin-right': '0',
|
||||
'width': ssb_width_expanded - 28
|
||||
});
|
||||
// create the button
|
||||
sidebar.append(
|
||||
'<div id="sidebarbutton"><span>«</span></div>'
|
||||
);
|
||||
var sidebarbutton = $('#sidebarbutton');
|
||||
light_color = sidebarbutton.css('background-color');
|
||||
// find the height of the viewport to center the '<<' in the page
|
||||
var viewport_height;
|
||||
if (window.innerHeight)
|
||||
viewport_height = window.innerHeight;
|
||||
else
|
||||
viewport_height = $(window).height();
|
||||
sidebarbutton.find('span').css({
|
||||
'display': 'block',
|
||||
'margin-top': (viewport_height - sidebar.position().top - 20) / 2
|
||||
});
|
||||
|
||||
sidebarbutton.click(toggle_sidebar);
|
||||
sidebarbutton.attr('title', _('Collapse sidebar'));
|
||||
sidebarbutton.css({
|
||||
'color': '#FFFFFF',
|
||||
'border-left': '1px solid ' + dark_color,
|
||||
'font-size': '1.2em',
|
||||
'cursor': 'pointer',
|
||||
'height': bodywrapper.height(),
|
||||
'padding-top': '1px',
|
||||
'margin-left': ssb_width_expanded - 12
|
||||
});
|
||||
|
||||
sidebarbutton.hover(
|
||||
function () {
|
||||
$(this).css('background-color', dark_color);
|
||||
},
|
||||
function () {
|
||||
$(this).css('background-color', light_color);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function set_position_from_cookie() {
|
||||
if (!document.cookie)
|
||||
return;
|
||||
var items = document.cookie.split(';');
|
||||
for(var k=0; k<items.length; k++) {
|
||||
var key_val = items[k].split('=');
|
||||
var key = key_val[0];
|
||||
if (key == 'sidebar') {
|
||||
var value = key_val[1];
|
||||
if ((value == 'collapsed') && (!sidebar_is_collapsed()))
|
||||
collapse_sidebar();
|
||||
else if ((value == 'expanded') && (sidebar_is_collapsed()))
|
||||
expand_sidebar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
add_sidebar_button();
|
||||
var sidebarbutton = $('#sidebarbutton');
|
||||
set_position_from_cookie();
|
||||
});
|
||||
23
_static/underscore.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Underscore.js 0.5.5
|
||||
// (c) 2009 Jeremy Ashkenas, DocumentCloud Inc.
|
||||
// Underscore is freely distributable under the terms of the MIT license.
|
||||
// Portions of Underscore are inspired by or borrowed from Prototype.js,
|
||||
// Oliver Steele's Functional, and John Resig's Micro-Templating.
|
||||
// For all details and documentation:
|
||||
// http://documentcloud.github.com/underscore/
|
||||
(function(){var j=this,n=j._,i=function(a){this._wrapped=a},m=typeof StopIteration!=="undefined"?StopIteration:"__break__",b=j._=function(a){return new i(a)};if(typeof exports!=="undefined")exports._=b;var k=Array.prototype.slice,o=Array.prototype.unshift,p=Object.prototype.toString,q=Object.prototype.hasOwnProperty,r=Object.prototype.propertyIsEnumerable;b.VERSION="0.5.5";b.each=function(a,c,d){try{if(a.forEach)a.forEach(c,d);else if(b.isArray(a)||b.isArguments(a))for(var e=0,f=a.length;e<f;e++)c.call(d,
|
||||
a[e],e,a);else{var g=b.keys(a);f=g.length;for(e=0;e<f;e++)c.call(d,a[g[e]],g[e],a)}}catch(h){if(h!=m)throw h;}return a};b.map=function(a,c,d){if(a&&b.isFunction(a.map))return a.map(c,d);var e=[];b.each(a,function(f,g,h){e.push(c.call(d,f,g,h))});return e};b.reduce=function(a,c,d,e){if(a&&b.isFunction(a.reduce))return a.reduce(b.bind(d,e),c);b.each(a,function(f,g,h){c=d.call(e,c,f,g,h)});return c};b.reduceRight=function(a,c,d,e){if(a&&b.isFunction(a.reduceRight))return a.reduceRight(b.bind(d,e),c);
|
||||
var f=b.clone(b.toArray(a)).reverse();b.each(f,function(g,h){c=d.call(e,c,g,h,a)});return c};b.detect=function(a,c,d){var e;b.each(a,function(f,g,h){if(c.call(d,f,g,h)){e=f;b.breakLoop()}});return e};b.select=function(a,c,d){if(a&&b.isFunction(a.filter))return a.filter(c,d);var e=[];b.each(a,function(f,g,h){c.call(d,f,g,h)&&e.push(f)});return e};b.reject=function(a,c,d){var e=[];b.each(a,function(f,g,h){!c.call(d,f,g,h)&&e.push(f)});return e};b.all=function(a,c,d){c=c||b.identity;if(a&&b.isFunction(a.every))return a.every(c,
|
||||
d);var e=true;b.each(a,function(f,g,h){(e=e&&c.call(d,f,g,h))||b.breakLoop()});return e};b.any=function(a,c,d){c=c||b.identity;if(a&&b.isFunction(a.some))return a.some(c,d);var e=false;b.each(a,function(f,g,h){if(e=c.call(d,f,g,h))b.breakLoop()});return e};b.include=function(a,c){if(b.isArray(a))return b.indexOf(a,c)!=-1;var d=false;b.each(a,function(e){if(d=e===c)b.breakLoop()});return d};b.invoke=function(a,c){var d=b.rest(arguments,2);return b.map(a,function(e){return(c?e[c]:e).apply(e,d)})};b.pluck=
|
||||
function(a,c){return b.map(a,function(d){return d[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);var e={computed:-Infinity};b.each(a,function(f,g,h){g=c?c.call(d,f,g,h):f;g>=e.computed&&(e={value:f,computed:g})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);var e={computed:Infinity};b.each(a,function(f,g,h){g=c?c.call(d,f,g,h):f;g<e.computed&&(e={value:f,computed:g})});return e.value};b.sortBy=function(a,c,d){return b.pluck(b.map(a,
|
||||
function(e,f,g){return{value:e,criteria:c.call(d,e,f,g)}}).sort(function(e,f){e=e.criteria;f=f.criteria;return e<f?-1:e>f?1:0}),"value")};b.sortedIndex=function(a,c,d){d=d||b.identity;for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(c)?(e=g+1):(f=g)}return e};b.toArray=function(a){if(!a)return[];if(a.toArray)return a.toArray();if(b.isArray(a))return a;if(b.isArguments(a))return k.call(a);return b.values(a)};b.size=function(a){return b.toArray(a).length};b.first=function(a,c,d){return c&&!d?k.call(a,
|
||||
0,c):a[0]};b.rest=function(a,c,d){return k.call(a,b.isUndefined(c)||d?1:c)};b.last=function(a){return a[a.length-1]};b.compact=function(a){return b.select(a,function(c){return!!c})};b.flatten=function(a){return b.reduce(a,[],function(c,d){if(b.isArray(d))return c.concat(b.flatten(d));c.push(d);return c})};b.without=function(a){var c=b.rest(arguments);return b.select(a,function(d){return!b.include(c,d)})};b.uniq=function(a,c){return b.reduce(a,[],function(d,e,f){if(0==f||(c===true?b.last(d)!=e:!b.include(d,
|
||||
e)))d.push(e);return d})};b.intersect=function(a){var c=b.rest(arguments);return b.select(b.uniq(a),function(d){return b.all(c,function(e){return b.indexOf(e,d)>=0})})};b.zip=function(){for(var a=b.toArray(arguments),c=b.max(b.pluck(a,"length")),d=new Array(c),e=0;e<c;e++)d[e]=b.pluck(a,String(e));return d};b.indexOf=function(a,c){if(a.indexOf)return a.indexOf(c);for(var d=0,e=a.length;d<e;d++)if(a[d]===c)return d;return-1};b.lastIndexOf=function(a,c){if(a.lastIndexOf)return a.lastIndexOf(c);for(var d=
|
||||
a.length;d--;)if(a[d]===c)return d;return-1};b.range=function(a,c,d){var e=b.toArray(arguments),f=e.length<=1;a=f?0:e[0];c=f?e[0]:e[1];d=e[2]||1;e=Math.ceil((c-a)/d);if(e<=0)return[];e=new Array(e);f=a;for(var g=0;1;f+=d){if((d>0?f-c:c-f)>=0)return e;e[g++]=f}};b.bind=function(a,c){var d=b.rest(arguments,2);return function(){return a.apply(c||j,d.concat(b.toArray(arguments)))}};b.bindAll=function(a){var c=b.rest(arguments);if(c.length==0)c=b.functions(a);b.each(c,function(d){a[d]=b.bind(a[d],a)});
|
||||
return a};b.delay=function(a,c){var d=b.rest(arguments,2);return setTimeout(function(){return a.apply(a,d)},c)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(b.rest(arguments)))};b.wrap=function(a,c){return function(){var d=[a].concat(b.toArray(arguments));return c.apply(c,d)}};b.compose=function(){var a=b.toArray(arguments);return function(){for(var c=b.toArray(arguments),d=a.length-1;d>=0;d--)c=[a[d].apply(this,c)];return c[0]}};b.keys=function(a){if(b.isArray(a))return b.range(0,a.length);
|
||||
var c=[];for(var d in a)q.call(a,d)&&c.push(d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=function(a){return b.select(b.keys(a),function(c){return b.isFunction(a[c])}).sort()};b.extend=function(a,c){for(var d in c)a[d]=c[d];return a};b.clone=function(a){if(b.isArray(a))return a.slice(0);return b.extend({},a)};b.tap=function(a,c){c(a);return a};b.isEqual=function(a,c){if(a===c)return true;var d=typeof a;if(d!=typeof c)return false;if(a==c)return true;if(!a&&c||a&&!c)return false;
|
||||
if(a.isEqual)return a.isEqual(c);if(b.isDate(a)&&b.isDate(c))return a.getTime()===c.getTime();if(b.isNaN(a)&&b.isNaN(c))return true;if(b.isRegExp(a)&&b.isRegExp(c))return a.source===c.source&&a.global===c.global&&a.ignoreCase===c.ignoreCase&&a.multiline===c.multiline;if(d!=="object")return false;if(a.length&&a.length!==c.length)return false;d=b.keys(a);var e=b.keys(c);if(d.length!=e.length)return false;for(var f in a)if(!b.isEqual(a[f],c[f]))return false;return true};b.isEmpty=function(a){return b.keys(a).length==
|
||||
0};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=function(a){return!!(a&&a.concat&&a.unshift)};b.isArguments=function(a){return a&&b.isNumber(a.length)&&!b.isArray(a)&&!r.call(a,"length")};b.isFunction=function(a){return!!(a&&a.constructor&&a.call&&a.apply)};b.isString=function(a){return!!(a===""||a&&a.charCodeAt&&a.substr)};b.isNumber=function(a){return p.call(a)==="[object Number]"};b.isDate=function(a){return!!(a&&a.getTimezoneOffset&&a.setUTCFullYear)};b.isRegExp=function(a){return!!(a&&
|
||||
a.test&&a.exec&&(a.ignoreCase||a.ignoreCase===false))};b.isNaN=function(a){return b.isNumber(a)&&isNaN(a)};b.isNull=function(a){return a===null};b.isUndefined=function(a){return typeof a=="undefined"};b.noConflict=function(){j._=n;return this};b.identity=function(a){return a};b.breakLoop=function(){throw m;};var s=0;b.uniqueId=function(a){var c=s++;return a?a+c:c};b.template=function(a,c){a=new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+a.replace(/[\r\t\n]/g,
|
||||
" ").replace(/'(?=[^%]*%>)/g,"\t").split("'").join("\\'").split("\t").join("'").replace(/<%=(.+?)%>/g,"',$1,'").split("<%").join("');").split("%>").join("p.push('")+"');}return p.join('');");return c?a(c):a};b.forEach=b.each;b.foldl=b.inject=b.reduce;b.foldr=b.reduceRight;b.filter=b.select;b.every=b.all;b.some=b.any;b.head=b.first;b.tail=b.rest;b.methods=b.functions;var l=function(a,c){return c?b(a).chain():a};b.each(b.functions(b),function(a){var c=b[a];i.prototype[a]=function(){var d=b.toArray(arguments);
|
||||
o.call(d,this._wrapped);return l(c.apply(b,d),this._chain)}});b.each(["pop","push","reverse","shift","sort","splice","unshift"],function(a){var c=Array.prototype[a];i.prototype[a]=function(){c.apply(this._wrapped,arguments);return l(this._wrapped,this._chain)}});b.each(["concat","join","slice"],function(a){var c=Array.prototype[a];i.prototype[a]=function(){return l(c.apply(this._wrapped,arguments),this._chain)}});i.prototype.chain=function(){this._chain=true;return this};i.prototype.value=function(){return this._wrapped}})();
|
||||
BIN
_static/up-pressed.png
Normal file
|
After Width: | Height: | Size: 372 B |
BIN
_static/up.png
Normal file
|
After Width: | Height: | Size: 363 B |
808
_static/websupport.js
Normal file
|
|
@ -0,0 +1,808 @@
|
|||
/*
|
||||
* websupport.js
|
||||
* ~~~~~~~~~~~~~
|
||||
*
|
||||
* sphinx.websupport utilties for all documentation.
|
||||
*
|
||||
* :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
$.fn.autogrow = function() {
|
||||
return this.each(function() {
|
||||
var textarea = this;
|
||||
|
||||
$.fn.autogrow.resize(textarea);
|
||||
|
||||
$(textarea)
|
||||
.focus(function() {
|
||||
textarea.interval = setInterval(function() {
|
||||
$.fn.autogrow.resize(textarea);
|
||||
}, 500);
|
||||
})
|
||||
.blur(function() {
|
||||
clearInterval(textarea.interval);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$.fn.autogrow.resize = function(textarea) {
|
||||
var lineHeight = parseInt($(textarea).css('line-height'), 10);
|
||||
var lines = textarea.value.split('\n');
|
||||
var columns = textarea.cols;
|
||||
var lineCount = 0;
|
||||
$.each(lines, function() {
|
||||
lineCount += Math.ceil(this.length / columns) || 1;
|
||||
});
|
||||
var height = lineHeight * (lineCount + 1);
|
||||
$(textarea).css('height', height);
|
||||
};
|
||||
})(jQuery);
|
||||
|
||||
(function($) {
|
||||
var comp, by;
|
||||
|
||||
function init() {
|
||||
initEvents();
|
||||
initComparator();
|
||||
}
|
||||
|
||||
function initEvents() {
|
||||
$('a.comment-close').live("click", function(event) {
|
||||
event.preventDefault();
|
||||
hide($(this).attr('id').substring(2));
|
||||
});
|
||||
$('a.vote').live("click", function(event) {
|
||||
event.preventDefault();
|
||||
handleVote($(this));
|
||||
});
|
||||
$('a.reply').live("click", function(event) {
|
||||
event.preventDefault();
|
||||
openReply($(this).attr('id').substring(2));
|
||||
});
|
||||
$('a.close-reply').live("click", function(event) {
|
||||
event.preventDefault();
|
||||
closeReply($(this).attr('id').substring(2));
|
||||
});
|
||||
$('a.sort-option').live("click", function(event) {
|
||||
event.preventDefault();
|
||||
handleReSort($(this));
|
||||
});
|
||||
$('a.show-proposal').live("click", function(event) {
|
||||
event.preventDefault();
|
||||
showProposal($(this).attr('id').substring(2));
|
||||
});
|
||||
$('a.hide-proposal').live("click", function(event) {
|
||||
event.preventDefault();
|
||||
hideProposal($(this).attr('id').substring(2));
|
||||
});
|
||||
$('a.show-propose-change').live("click", function(event) {
|
||||
event.preventDefault();
|
||||
showProposeChange($(this).attr('id').substring(2));
|
||||
});
|
||||
$('a.hide-propose-change').live("click", function(event) {
|
||||
event.preventDefault();
|
||||
hideProposeChange($(this).attr('id').substring(2));
|
||||
});
|
||||
$('a.accept-comment').live("click", function(event) {
|
||||
event.preventDefault();
|
||||
acceptComment($(this).attr('id').substring(2));
|
||||
});
|
||||
$('a.delete-comment').live("click", function(event) {
|
||||
event.preventDefault();
|
||||
deleteComment($(this).attr('id').substring(2));
|
||||
});
|
||||
$('a.comment-markup').live("click", function(event) {
|
||||
event.preventDefault();
|
||||
toggleCommentMarkupBox($(this).attr('id').substring(2));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set comp, which is a comparator function used for sorting and
|
||||
* inserting comments into the list.
|
||||
*/
|
||||
function setComparator() {
|
||||
// If the first three letters are "asc", sort in ascending order
|
||||
// and remove the prefix.
|
||||
if (by.substring(0,3) == 'asc') {
|
||||
var i = by.substring(3);
|
||||
comp = function(a, b) { return a[i] - b[i]; };
|
||||
} else {
|
||||
// Otherwise sort in descending order.
|
||||
comp = function(a, b) { return b[by] - a[by]; };
|
||||
}
|
||||
|
||||
// Reset link styles and format the selected sort option.
|
||||
$('a.sel').attr('href', '#').removeClass('sel');
|
||||
$('a.by' + by).removeAttr('href').addClass('sel');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a comp function. If the user has preferences stored in
|
||||
* the sortBy cookie, use those, otherwise use the default.
|
||||
*/
|
||||
function initComparator() {
|
||||
by = 'rating'; // Default to sort by rating.
|
||||
// If the sortBy cookie is set, use that instead.
|
||||
if (document.cookie.length > 0) {
|
||||
var start = document.cookie.indexOf('sortBy=');
|
||||
if (start != -1) {
|
||||
start = start + 7;
|
||||
var end = document.cookie.indexOf(";", start);
|
||||
if (end == -1) {
|
||||
end = document.cookie.length;
|
||||
by = unescape(document.cookie.substring(start, end));
|
||||
}
|
||||
}
|
||||
}
|
||||
setComparator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a comment div.
|
||||
*/
|
||||
function show(id) {
|
||||
$('#ao' + id).hide();
|
||||
$('#ah' + id).show();
|
||||
var context = $.extend({id: id}, opts);
|
||||
var popup = $(renderTemplate(popupTemplate, context)).hide();
|
||||
popup.find('textarea[name="proposal"]').hide();
|
||||
popup.find('a.by' + by).addClass('sel');
|
||||
var form = popup.find('#cf' + id);
|
||||
form.submit(function(event) {
|
||||
event.preventDefault();
|
||||
addComment(form);
|
||||
});
|
||||
$('#s' + id).after(popup);
|
||||
popup.slideDown('fast', function() {
|
||||
getComments(id);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide a comment div.
|
||||
*/
|
||||
function hide(id) {
|
||||
$('#ah' + id).hide();
|
||||
$('#ao' + id).show();
|
||||
var div = $('#sc' + id);
|
||||
div.slideUp('fast', function() {
|
||||
div.remove();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an ajax request to get comments for a node
|
||||
* and insert the comments into the comments tree.
|
||||
*/
|
||||
function getComments(id) {
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: opts.getCommentsURL,
|
||||
data: {node: id},
|
||||
success: function(data, textStatus, request) {
|
||||
var ul = $('#cl' + id);
|
||||
var speed = 100;
|
||||
$('#cf' + id)
|
||||
.find('textarea[name="proposal"]')
|
||||
.data('source', data.source);
|
||||
|
||||
if (data.comments.length === 0) {
|
||||
ul.html('<li>No comments yet.</li>');
|
||||
ul.data('empty', true);
|
||||
} else {
|
||||
// If there are comments, sort them and put them in the list.
|
||||
var comments = sortComments(data.comments);
|
||||
speed = data.comments.length * 100;
|
||||
appendComments(comments, ul);
|
||||
ul.data('empty', false);
|
||||
}
|
||||
$('#cn' + id).slideUp(speed + 200);
|
||||
ul.slideDown(speed);
|
||||
},
|
||||
error: function(request, textStatus, error) {
|
||||
showError('Oops, there was a problem retrieving the comments.');
|
||||
},
|
||||
dataType: 'json'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a comment via ajax and insert the comment into the comment tree.
|
||||
*/
|
||||
function addComment(form) {
|
||||
var node_id = form.find('input[name="node"]').val();
|
||||
var parent_id = form.find('input[name="parent"]').val();
|
||||
var text = form.find('textarea[name="comment"]').val();
|
||||
var proposal = form.find('textarea[name="proposal"]').val();
|
||||
|
||||
if (text == '') {
|
||||
showError('Please enter a comment.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable the form that is being submitted.
|
||||
form.find('textarea,input').attr('disabled', 'disabled');
|
||||
|
||||
// Send the comment to the server.
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: opts.addCommentURL,
|
||||
dataType: 'json',
|
||||
data: {
|
||||
node: node_id,
|
||||
parent: parent_id,
|
||||
text: text,
|
||||
proposal: proposal
|
||||
},
|
||||
success: function(data, textStatus, error) {
|
||||
// Reset the form.
|
||||
if (node_id) {
|
||||
hideProposeChange(node_id);
|
||||
}
|
||||
form.find('textarea')
|
||||
.val('')
|
||||
.add(form.find('input'))
|
||||
.removeAttr('disabled');
|
||||
var ul = $('#cl' + (node_id || parent_id));
|
||||
if (ul.data('empty')) {
|
||||
$(ul).empty();
|
||||
ul.data('empty', false);
|
||||
}
|
||||
insertComment(data.comment);
|
||||
var ao = $('#ao' + node_id);
|
||||
ao.find('img').attr({'src': opts.commentBrightImage});
|
||||
if (node_id) {
|
||||
// if this was a "root" comment, remove the commenting box
|
||||
// (the user can get it back by reopening the comment popup)
|
||||
$('#ca' + node_id).slideUp();
|
||||
}
|
||||
},
|
||||
error: function(request, textStatus, error) {
|
||||
form.find('textarea,input').removeAttr('disabled');
|
||||
showError('Oops, there was a problem adding the comment.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively append comments to the main comment list and children
|
||||
* lists, creating the comment tree.
|
||||
*/
|
||||
function appendComments(comments, ul) {
|
||||
$.each(comments, function() {
|
||||
var div = createCommentDiv(this);
|
||||
ul.append($(document.createElement('li')).html(div));
|
||||
appendComments(this.children, div.find('ul.comment-children'));
|
||||
// To avoid stagnating data, don't store the comments children in data.
|
||||
this.children = null;
|
||||
div.data('comment', this);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* After adding a new comment, it must be inserted in the correct
|
||||
* location in the comment tree.
|
||||
*/
|
||||
function insertComment(comment) {
|
||||
var div = createCommentDiv(comment);
|
||||
|
||||
// To avoid stagnating data, don't store the comments children in data.
|
||||
comment.children = null;
|
||||
div.data('comment', comment);
|
||||
|
||||
var ul = $('#cl' + (comment.node || comment.parent));
|
||||
var siblings = getChildren(ul);
|
||||
|
||||
var li = $(document.createElement('li'));
|
||||
li.hide();
|
||||
|
||||
// Determine where in the parents children list to insert this comment.
|
||||
for(i=0; i < siblings.length; i++) {
|
||||
if (comp(comment, siblings[i]) <= 0) {
|
||||
$('#cd' + siblings[i].id)
|
||||
.parent()
|
||||
.before(li.html(div));
|
||||
li.slideDown('fast');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, this comment rates lower than all the others,
|
||||
// or it is the only comment in the list.
|
||||
ul.append(li.html(div));
|
||||
li.slideDown('fast');
|
||||
}
|
||||
|
||||
function acceptComment(id) {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: opts.acceptCommentURL,
|
||||
data: {id: id},
|
||||
success: function(data, textStatus, request) {
|
||||
$('#cm' + id).fadeOut('fast');
|
||||
$('#cd' + id).removeClass('moderate');
|
||||
},
|
||||
error: function(request, textStatus, error) {
|
||||
showError('Oops, there was a problem accepting the comment.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function deleteComment(id) {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: opts.deleteCommentURL,
|
||||
data: {id: id},
|
||||
success: function(data, textStatus, request) {
|
||||
var div = $('#cd' + id);
|
||||
if (data == 'delete') {
|
||||
// Moderator mode: remove the comment and all children immediately
|
||||
div.slideUp('fast', function() {
|
||||
div.remove();
|
||||
});
|
||||
return;
|
||||
}
|
||||
// User mode: only mark the comment as deleted
|
||||
div
|
||||
.find('span.user-id:first')
|
||||
.text('[deleted]').end()
|
||||
.find('div.comment-text:first')
|
||||
.text('[deleted]').end()
|
||||
.find('#cm' + id + ', #dc' + id + ', #ac' + id + ', #rc' + id +
|
||||
', #sp' + id + ', #hp' + id + ', #cr' + id + ', #rl' + id)
|
||||
.remove();
|
||||
var comment = div.data('comment');
|
||||
comment.username = '[deleted]';
|
||||
comment.text = '[deleted]';
|
||||
div.data('comment', comment);
|
||||
},
|
||||
error: function(request, textStatus, error) {
|
||||
showError('Oops, there was a problem deleting the comment.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function showProposal(id) {
|
||||
$('#sp' + id).hide();
|
||||
$('#hp' + id).show();
|
||||
$('#pr' + id).slideDown('fast');
|
||||
}
|
||||
|
||||
function hideProposal(id) {
|
||||
$('#hp' + id).hide();
|
||||
$('#sp' + id).show();
|
||||
$('#pr' + id).slideUp('fast');
|
||||
}
|
||||
|
||||
function showProposeChange(id) {
|
||||
$('#pc' + id).hide();
|
||||
$('#hc' + id).show();
|
||||
var textarea = $('#pt' + id);
|
||||
textarea.val(textarea.data('source'));
|
||||
$.fn.autogrow.resize(textarea[0]);
|
||||
textarea.slideDown('fast');
|
||||
}
|
||||
|
||||
function hideProposeChange(id) {
|
||||
$('#hc' + id).hide();
|
||||
$('#pc' + id).show();
|
||||
var textarea = $('#pt' + id);
|
||||
textarea.val('').removeAttr('disabled');
|
||||
textarea.slideUp('fast');
|
||||
}
|
||||
|
||||
function toggleCommentMarkupBox(id) {
|
||||
$('#mb' + id).toggle();
|
||||
}
|
||||
|
||||
/** Handle when the user clicks on a sort by link. */
|
||||
function handleReSort(link) {
|
||||
var classes = link.attr('class').split(/\s+/);
|
||||
for (var i=0; i<classes.length; i++) {
|
||||
if (classes[i] != 'sort-option') {
|
||||
by = classes[i].substring(2);
|
||||
}
|
||||
}
|
||||
setComparator();
|
||||
// Save/update the sortBy cookie.
|
||||
var expiration = new Date();
|
||||
expiration.setDate(expiration.getDate() + 365);
|
||||
document.cookie= 'sortBy=' + escape(by) +
|
||||
';expires=' + expiration.toUTCString();
|
||||
$('ul.comment-ul').each(function(index, ul) {
|
||||
var comments = getChildren($(ul), true);
|
||||
comments = sortComments(comments);
|
||||
appendComments(comments, $(ul).empty());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to process a vote when a user clicks an arrow.
|
||||
*/
|
||||
function handleVote(link) {
|
||||
if (!opts.voting) {
|
||||
showError("You'll need to login to vote.");
|
||||
return;
|
||||
}
|
||||
|
||||
var id = link.attr('id');
|
||||
if (!id) {
|
||||
// Didn't click on one of the voting arrows.
|
||||
return;
|
||||
}
|
||||
// If it is an unvote, the new vote value is 0,
|
||||
// Otherwise it's 1 for an upvote, or -1 for a downvote.
|
||||
var value = 0;
|
||||
if (id.charAt(1) != 'u') {
|
||||
value = id.charAt(0) == 'u' ? 1 : -1;
|
||||
}
|
||||
// The data to be sent to the server.
|
||||
var d = {
|
||||
comment_id: id.substring(2),
|
||||
value: value
|
||||
};
|
||||
|
||||
// Swap the vote and unvote links.
|
||||
link.hide();
|
||||
$('#' + id.charAt(0) + (id.charAt(1) == 'u' ? 'v' : 'u') + d.comment_id)
|
||||
.show();
|
||||
|
||||
// The div the comment is displayed in.
|
||||
var div = $('div#cd' + d.comment_id);
|
||||
var data = div.data('comment');
|
||||
|
||||
// If this is not an unvote, and the other vote arrow has
|
||||
// already been pressed, unpress it.
|
||||
if ((d.value !== 0) && (data.vote === d.value * -1)) {
|
||||
$('#' + (d.value == 1 ? 'd' : 'u') + 'u' + d.comment_id).hide();
|
||||
$('#' + (d.value == 1 ? 'd' : 'u') + 'v' + d.comment_id).show();
|
||||
}
|
||||
|
||||
// Update the comments rating in the local data.
|
||||
data.rating += (data.vote === 0) ? d.value : (d.value - data.vote);
|
||||
data.vote = d.value;
|
||||
div.data('comment', data);
|
||||
|
||||
// Change the rating text.
|
||||
div.find('.rating:first')
|
||||
.text(data.rating + ' point' + (data.rating == 1 ? '' : 's'));
|
||||
|
||||
// Send the vote information to the server.
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: opts.processVoteURL,
|
||||
data: d,
|
||||
error: function(request, textStatus, error) {
|
||||
showError('Oops, there was a problem casting that vote.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a reply form used to reply to an existing comment.
|
||||
*/
|
||||
function openReply(id) {
|
||||
// Swap out the reply link for the hide link
|
||||
$('#rl' + id).hide();
|
||||
$('#cr' + id).show();
|
||||
|
||||
// Add the reply li to the children ul.
|
||||
var div = $(renderTemplate(replyTemplate, {id: id})).hide();
|
||||
$('#cl' + id)
|
||||
.prepend(div)
|
||||
// Setup the submit handler for the reply form.
|
||||
.find('#rf' + id)
|
||||
.submit(function(event) {
|
||||
event.preventDefault();
|
||||
addComment($('#rf' + id));
|
||||
closeReply(id);
|
||||
})
|
||||
.find('input[type=button]')
|
||||
.click(function() {
|
||||
closeReply(id);
|
||||
});
|
||||
div.slideDown('fast', function() {
|
||||
$('#rf' + id).find('textarea').focus();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the reply form opened with openReply.
|
||||
*/
|
||||
function closeReply(id) {
|
||||
// Remove the reply div from the DOM.
|
||||
$('#rd' + id).slideUp('fast', function() {
|
||||
$(this).remove();
|
||||
});
|
||||
|
||||
// Swap out the hide link for the reply link
|
||||
$('#cr' + id).hide();
|
||||
$('#rl' + id).show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively sort a tree of comments using the comp comparator.
|
||||
*/
|
||||
function sortComments(comments) {
|
||||
comments.sort(comp);
|
||||
$.each(comments, function() {
|
||||
this.children = sortComments(this.children);
|
||||
});
|
||||
return comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the children comments from a ul. If recursive is true,
|
||||
* recursively include childrens' children.
|
||||
*/
|
||||
function getChildren(ul, recursive) {
|
||||
var children = [];
|
||||
ul.children().children("[id^='cd']")
|
||||
.each(function() {
|
||||
var comment = $(this).data('comment');
|
||||
if (recursive)
|
||||
comment.children = getChildren($(this).find('#cl' + comment.id), true);
|
||||
children.push(comment);
|
||||
});
|
||||
return children;
|
||||
}
|
||||
|
||||
/** Create a div to display a comment in. */
|
||||
function createCommentDiv(comment) {
|
||||
if (!comment.displayed && !opts.moderator) {
|
||||
return $('<div class="moderate">Thank you! Your comment will show up '
|
||||
+ 'once it is has been approved by a moderator.</div>');
|
||||
}
|
||||
// Prettify the comment rating.
|
||||
comment.pretty_rating = comment.rating + ' point' +
|
||||
(comment.rating == 1 ? '' : 's');
|
||||
// Make a class (for displaying not yet moderated comments differently)
|
||||
comment.css_class = comment.displayed ? '' : ' moderate';
|
||||
// Create a div for this comment.
|
||||
var context = $.extend({}, opts, comment);
|
||||
var div = $(renderTemplate(commentTemplate, context));
|
||||
|
||||
// If the user has voted on this comment, highlight the correct arrow.
|
||||
if (comment.vote) {
|
||||
var direction = (comment.vote == 1) ? 'u' : 'd';
|
||||
div.find('#' + direction + 'v' + comment.id).hide();
|
||||
div.find('#' + direction + 'u' + comment.id).show();
|
||||
}
|
||||
|
||||
if (opts.moderator || comment.text != '[deleted]') {
|
||||
div.find('a.reply').show();
|
||||
if (comment.proposal_diff)
|
||||
div.find('#sp' + comment.id).show();
|
||||
if (opts.moderator && !comment.displayed)
|
||||
div.find('#cm' + comment.id).show();
|
||||
if (opts.moderator || (opts.username == comment.username))
|
||||
div.find('#dc' + comment.id).show();
|
||||
}
|
||||
return div;
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple template renderer. Placeholders such as <%id%> are replaced
|
||||
* by context['id'] with items being escaped. Placeholders such as <#id#>
|
||||
* are not escaped.
|
||||
*/
|
||||
function renderTemplate(template, context) {
|
||||
var esc = $(document.createElement('div'));
|
||||
|
||||
function handle(ph, escape) {
|
||||
var cur = context;
|
||||
$.each(ph.split('.'), function() {
|
||||
cur = cur[this];
|
||||
});
|
||||
return escape ? esc.text(cur || "").html() : cur;
|
||||
}
|
||||
|
||||
return template.replace(/<([%#])([\w\.]*)\1>/g, function() {
|
||||
return handle(arguments[2], arguments[1] == '%' ? true : false);
|
||||
});
|
||||
}
|
||||
|
||||
/** Flash an error message briefly. */
|
||||
function showError(message) {
|
||||
$(document.createElement('div')).attr({'class': 'popup-error'})
|
||||
.append($(document.createElement('div'))
|
||||
.attr({'class': 'error-message'}).text(message))
|
||||
.appendTo('body')
|
||||
.fadeIn("slow")
|
||||
.delay(2000)
|
||||
.fadeOut("slow");
|
||||
}
|
||||
|
||||
/** Add a link the user uses to open the comments popup. */
|
||||
$.fn.comment = function() {
|
||||
return this.each(function() {
|
||||
var id = $(this).attr('id').substring(1);
|
||||
var count = COMMENT_METADATA[id];
|
||||
var title = count + ' comment' + (count == 1 ? '' : 's');
|
||||
var image = count > 0 ? opts.commentBrightImage : opts.commentImage;
|
||||
var addcls = count == 0 ? ' nocomment' : '';
|
||||
$(this)
|
||||
.append(
|
||||
$(document.createElement('a')).attr({
|
||||
href: '#',
|
||||
'class': 'sphinx-comment-open' + addcls,
|
||||
id: 'ao' + id
|
||||
})
|
||||
.append($(document.createElement('img')).attr({
|
||||
src: image,
|
||||
alt: 'comment',
|
||||
title: title
|
||||
}))
|
||||
.click(function(event) {
|
||||
event.preventDefault();
|
||||
show($(this).attr('id').substring(2));
|
||||
})
|
||||
)
|
||||
.append(
|
||||
$(document.createElement('a')).attr({
|
||||
href: '#',
|
||||
'class': 'sphinx-comment-close hidden',
|
||||
id: 'ah' + id
|
||||
})
|
||||
.append($(document.createElement('img')).attr({
|
||||
src: opts.closeCommentImage,
|
||||
alt: 'close',
|
||||
title: 'close'
|
||||
}))
|
||||
.click(function(event) {
|
||||
event.preventDefault();
|
||||
hide($(this).attr('id').substring(2));
|
||||
})
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
var opts = {
|
||||
processVoteURL: '/_process_vote',
|
||||
addCommentURL: '/_add_comment',
|
||||
getCommentsURL: '/_get_comments',
|
||||
acceptCommentURL: '/_accept_comment',
|
||||
deleteCommentURL: '/_delete_comment',
|
||||
commentImage: '/static/_static/comment.png',
|
||||
closeCommentImage: '/static/_static/comment-close.png',
|
||||
loadingImage: '/static/_static/ajax-loader.gif',
|
||||
commentBrightImage: '/static/_static/comment-bright.png',
|
||||
upArrow: '/static/_static/up.png',
|
||||
downArrow: '/static/_static/down.png',
|
||||
upArrowPressed: '/static/_static/up-pressed.png',
|
||||
downArrowPressed: '/static/_static/down-pressed.png',
|
||||
voting: false,
|
||||
moderator: false
|
||||
};
|
||||
|
||||
if (typeof COMMENT_OPTIONS != "undefined") {
|
||||
opts = jQuery.extend(opts, COMMENT_OPTIONS);
|
||||
}
|
||||
|
||||
var popupTemplate = '\
|
||||
<div class="sphinx-comments" id="sc<%id%>">\
|
||||
<p class="sort-options">\
|
||||
Sort by:\
|
||||
<a href="#" class="sort-option byrating">best rated</a>\
|
||||
<a href="#" class="sort-option byascage">newest</a>\
|
||||
<a href="#" class="sort-option byage">oldest</a>\
|
||||
</p>\
|
||||
<div class="comment-header">Comments</div>\
|
||||
<div class="comment-loading" id="cn<%id%>">\
|
||||
loading comments... <img src="<%loadingImage%>" alt="" /></div>\
|
||||
<ul id="cl<%id%>" class="comment-ul"></ul>\
|
||||
<div id="ca<%id%>">\
|
||||
<p class="add-a-comment">Add a comment\
|
||||
(<a href="#" class="comment-markup" id="ab<%id%>">markup</a>):</p>\
|
||||
<div class="comment-markup-box" id="mb<%id%>">\
|
||||
reStructured text markup: <i>*emph*</i>, <b>**strong**</b>, \
|
||||
<tt>``code``</tt>, \
|
||||
code blocks: <tt>::</tt> and an indented block after blank line</div>\
|
||||
<form method="post" id="cf<%id%>" class="comment-form" action="">\
|
||||
<textarea name="comment" cols="80"></textarea>\
|
||||
<p class="propose-button">\
|
||||
<a href="#" id="pc<%id%>" class="show-propose-change">\
|
||||
Propose a change ▹\
|
||||
</a>\
|
||||
<a href="#" id="hc<%id%>" class="hide-propose-change">\
|
||||
Propose a change ▿\
|
||||
</a>\
|
||||
</p>\
|
||||
<textarea name="proposal" id="pt<%id%>" cols="80"\
|
||||
spellcheck="false"></textarea>\
|
||||
<input type="submit" value="Add comment" />\
|
||||
<input type="hidden" name="node" value="<%id%>" />\
|
||||
<input type="hidden" name="parent" value="" />\
|
||||
</form>\
|
||||
</div>\
|
||||
</div>';
|
||||
|
||||
var commentTemplate = '\
|
||||
<div id="cd<%id%>" class="sphinx-comment<%css_class%>">\
|
||||
<div class="vote">\
|
||||
<div class="arrow">\
|
||||
<a href="#" id="uv<%id%>" class="vote" title="vote up">\
|
||||
<img src="<%upArrow%>" />\
|
||||
</a>\
|
||||
<a href="#" id="uu<%id%>" class="un vote" title="vote up">\
|
||||
<img src="<%upArrowPressed%>" />\
|
||||
</a>\
|
||||
</div>\
|
||||
<div class="arrow">\
|
||||
<a href="#" id="dv<%id%>" class="vote" title="vote down">\
|
||||
<img src="<%downArrow%>" id="da<%id%>" />\
|
||||
</a>\
|
||||
<a href="#" id="du<%id%>" class="un vote" title="vote down">\
|
||||
<img src="<%downArrowPressed%>" />\
|
||||
</a>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class="comment-content">\
|
||||
<p class="tagline comment">\
|
||||
<span class="user-id"><%username%></span>\
|
||||
<span class="rating"><%pretty_rating%></span>\
|
||||
<span class="delta"><%time.delta%></span>\
|
||||
</p>\
|
||||
<div class="comment-text comment"><#text#></div>\
|
||||
<p class="comment-opts comment">\
|
||||
<a href="#" class="reply hidden" id="rl<%id%>">reply ▹</a>\
|
||||
<a href="#" class="close-reply" id="cr<%id%>">reply ▿</a>\
|
||||
<a href="#" id="sp<%id%>" class="show-proposal">proposal ▹</a>\
|
||||
<a href="#" id="hp<%id%>" class="hide-proposal">proposal ▿</a>\
|
||||
<a href="#" id="dc<%id%>" class="delete-comment hidden">delete</a>\
|
||||
<span id="cm<%id%>" class="moderation hidden">\
|
||||
<a href="#" id="ac<%id%>" class="accept-comment">accept</a>\
|
||||
</span>\
|
||||
</p>\
|
||||
<pre class="proposal" id="pr<%id%>">\
|
||||
<#proposal_diff#>\
|
||||
</pre>\
|
||||
<ul class="comment-children" id="cl<%id%>"></ul>\
|
||||
</div>\
|
||||
<div class="clearleft"></div>\
|
||||
</div>\
|
||||
</div>';
|
||||
|
||||
var replyTemplate = '\
|
||||
<li>\
|
||||
<div class="reply-div" id="rd<%id%>">\
|
||||
<form id="rf<%id%>">\
|
||||
<textarea name="comment" cols="80"></textarea>\
|
||||
<input type="submit" value="Add reply" />\
|
||||
<input type="button" value="Cancel" />\
|
||||
<input type="hidden" name="parent" value="<%id%>" />\
|
||||
<input type="hidden" name="node" value="" />\
|
||||
</form>\
|
||||
</div>\
|
||||
</li>';
|
||||
|
||||
$(document).ready(function() {
|
||||
init();
|
||||
});
|
||||
})(jQuery);
|
||||
|
||||
$(document).ready(function() {
|
||||
// add comment anchors for all paragraphs that are commentable
|
||||
$('.sphinx-has-comment').comment();
|
||||
|
||||
// highlight search words in search results
|
||||
$("div.context").each(function() {
|
||||
var params = $.getQueryParameters();
|
||||
var terms = (params.q) ? params.q[0].split(/\s+/) : [];
|
||||
var result = $(this);
|
||||
$.each(terms, function() {
|
||||
result.highlightText(this.toLowerCase(), 'highlighted');
|
||||
});
|
||||
});
|
||||
|
||||
// directly open comment window if requested
|
||||
var anchor = document.location.hash;
|
||||
if (anchor.substring(0, 9) == '#comment-') {
|
||||
$('#ao' + anchor.substring(9)).click();
|
||||
document.location.hash = '#s' + anchor.substring(9);
|
||||
}
|
||||
});
|
||||
2296
content.html
Normal file
1629
genindex.html
Normal file
|
|
@ -1,514 +0,0 @@
|
|||
//
|
||||
// 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>
|
||||
|
||||
#if _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#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);
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
//
|
||||
// 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
|
||||
|
|
@ -1,768 +0,0 @@
|
|||
//
|
||||
// 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 _MSC_VER
|
||||
#include <stdarg.h>
|
||||
|
||||
#define snprintf c99_snprintf
|
||||
|
||||
inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap)
|
||||
{
|
||||
int count = -1;
|
||||
|
||||
if (size != 0)
|
||||
count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
|
||||
if (count == -1)
|
||||
count = _vscprintf(format, ap);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
inline int c99_snprintf(char* str, size_t size, const char* format, ...)
|
||||
{
|
||||
int count;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
count = c99_vsnprintf(str, size, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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));
|
||||
|
||||
addGfxCmdScissor(x+SCROLL_AREA_PADDING, y+SCROLL_AREA_PADDING, w-SCROLL_AREA_PADDING*4, h-AREA_HEADER-SCROLL_AREA_PADDING);
|
||||
|
||||
return g_insideScrollArea;
|
||||
}
|
||||
|
||||
void imguiEndScrollArea()
|
||||
{
|
||||
// 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 (barHeight < 1)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
g_state.insideCurrentScroll = false;
|
||||
}
|
||||
|
||||
bool imguiBeginArea(const char* name, int x, int y, int w, int h)
|
||||
{
|
||||
g_state.areaId++;
|
||||
g_state.widgetId = 0;
|
||||
g_scrollId = (g_state.areaId<<16) | g_state.widgetId;
|
||||
|
||||
g_state.widgetX = x + DEFAULT_SPACING;
|
||||
g_state.widgetY = y + h - AREA_HEADER;
|
||||
g_state.widgetW = w - DEFAULT_SPACING;
|
||||
|
||||
g_scrollTop = y + h - AREA_HEADER;
|
||||
g_scrollBottom = y+DEFAULT_SPACING;
|
||||
g_scrollRight = x+w - 2*DEFAULT_SPACING;
|
||||
|
||||
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));
|
||||
|
||||
addGfxCmdScissor(x, y, w, h-AREA_HEADER);
|
||||
addGfxCmdScissor(x+DEFAULT_SPACING, y+DEFAULT_SPACING, w-2*DEFAULT_SPACING, h-AREA_HEADER-DEFAULT_SPACING);
|
||||
|
||||
return g_insideScrollArea;
|
||||
}
|
||||
|
||||
void imguiEndArea()
|
||||
{
|
||||
// Disable scissoring.
|
||||
addGfxCmdScissor(-1,-1,-1,-1);
|
||||
g_state.insideCurrentScroll = false;
|
||||
}
|
||||
|
||||
bool imguiButton(const char* text, bool enabled, int x, int y, int w, int h)
|
||||
{
|
||||
g_state.widgetId++;
|
||||
unsigned int id = (g_state.areaId<<16) | g_state.widgetId;
|
||||
|
||||
bool floating = false;
|
||||
if (x == -1) {
|
||||
x = g_state.widgetX;
|
||||
} else {
|
||||
x += g_state.widgetX;
|
||||
}
|
||||
|
||||
if (y == -1) {
|
||||
y = g_state.widgetY - BUTTON_HEIGHT;
|
||||
} else {
|
||||
floating = true;
|
||||
y = g_scrollTop - y;
|
||||
}
|
||||
|
||||
if (w == -1)
|
||||
w = g_state.widgetW;
|
||||
|
||||
if (h == -1)
|
||||
h = BUTTON_HEIGHT;
|
||||
|
||||
if (!floating)
|
||||
g_state.widgetY -= h + 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+h/2, y+h/2-TEXT_HEIGHT/2, IMGUI_ALIGN_LEFT, text, isHot(id) ? imguiRGBA(255,196,0,255) : imguiRGBA(255,255,255,200));
|
||||
else
|
||||
addGfxCmdText(x+h/2, y+h/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);
|
||||
}
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
//
|
||||
// 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 imguiBeginArea(const char* name, int x, int y, int w, int h);
|
||||
void imguiEndArea();
|
||||
|
||||
bool imguiButton(const char* text, bool enabled, int x = -1, int y = -1,
|
||||
int w = -1, int h = -1);
|
||||
|
||||
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
|
||||
|
|
@ -1,375 +0,0 @@
|
|||
//
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
//
|
||||
// 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
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include "stb_image_write.h"
|
||||
|
|
@ -1,511 +0,0 @@
|
|||
/* stbiw-0.92 - public domain - http://nothings.org/stb/stb_image_write.h
|
||||
writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010
|
||||
no warranty implied; use at your own risk
|
||||
|
||||
|
||||
Before including,
|
||||
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
|
||||
in the file that you want to have the implementation.
|
||||
|
||||
|
||||
ABOUT:
|
||||
|
||||
This header file is a library for writing images to C stdio. It could be
|
||||
adapted to write to memory or a general streaming interface; let me know.
|
||||
|
||||
The PNG output is not optimal; it is 20-50% larger than the file
|
||||
written by a decent optimizing implementation. This library is designed
|
||||
for source code compactness and simplicitly, not optimal image file size
|
||||
or run-time performance.
|
||||
|
||||
USAGE:
|
||||
|
||||
There are three functions, one for each image file format:
|
||||
|
||||
int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
|
||||
int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
|
||||
int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
|
||||
|
||||
Each function returns 0 on failure and non-0 on success.
|
||||
|
||||
The functions create an image file defined by the parameters. The image
|
||||
is a rectangle of pixels stored from left-to-right, top-to-bottom.
|
||||
Each pixel contains 'comp' channels of data stored interleaved with 8-bits
|
||||
per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is
|
||||
monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall.
|
||||
The *data pointer points to the first byte of the top-left-most pixel.
|
||||
For PNG, "stride_in_bytes" is the distance in bytes from the first byte of
|
||||
a row of pixels to the first byte of the next row of pixels.
|
||||
|
||||
PNG creates output files with the same number of components as the input.
|
||||
The BMP and TGA formats expand Y to RGB in the file format. BMP does not
|
||||
output alpha.
|
||||
|
||||
PNG supports writing rectangles of data even when the bytes storing rows of
|
||||
data are not consecutive in memory (e.g. sub-rectangles of a larger image),
|
||||
by supplying the stride between the beginning of adjacent rows. The other
|
||||
formats do not. (Thus you cannot write a native-format BMP through the BMP
|
||||
writer, both because it is in BGR order and because it may have padding
|
||||
at the end of the line.)
|
||||
*/
|
||||
|
||||
#ifndef INCLUDE_STB_IMAGE_WRITE_H
|
||||
#define INCLUDE_STB_IMAGE_WRITE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
|
||||
extern int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
|
||||
extern int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif//INCLUDE_STB_IMAGE_WRITE_H
|
||||
|
||||
#ifdef STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
typedef unsigned int stbiw_uint32;
|
||||
typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
|
||||
|
||||
static void writefv(FILE *f, const char *fmt, va_list v)
|
||||
{
|
||||
while (*fmt) {
|
||||
switch (*fmt++) {
|
||||
case ' ': break;
|
||||
case '1': { unsigned char x = (unsigned char) va_arg(v, int); fputc(x,f); break; }
|
||||
case '2': { int x = va_arg(v,int); unsigned char b[2];
|
||||
b[0] = (unsigned char) x; b[1] = (unsigned char) (x>>8);
|
||||
fwrite(b,2,1,f); break; }
|
||||
case '4': { stbiw_uint32 x = va_arg(v,int); unsigned char b[4];
|
||||
b[0]=(unsigned char)x; b[1]=(unsigned char)(x>>8);
|
||||
b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24);
|
||||
fwrite(b,4,1,f); break; }
|
||||
default:
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void write3(FILE *f, unsigned char a, unsigned char b, unsigned char c)
|
||||
{
|
||||
unsigned char arr[3];
|
||||
arr[0] = a, arr[1] = b, arr[2] = c;
|
||||
fwrite(arr, 3, 1, f);
|
||||
}
|
||||
|
||||
static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad)
|
||||
{
|
||||
unsigned char bg[3] = { 255, 0, 255}, px[3];
|
||||
stbiw_uint32 zero = 0;
|
||||
int i,j,k, j_end;
|
||||
|
||||
if (y <= 0)
|
||||
return;
|
||||
|
||||
if (vdir < 0)
|
||||
j_end = -1, j = y-1;
|
||||
else
|
||||
j_end = y, j = 0;
|
||||
|
||||
for (; j != j_end; j += vdir) {
|
||||
for (i=0; i < x; ++i) {
|
||||
unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
|
||||
if (write_alpha < 0)
|
||||
fwrite(&d[comp-1], 1, 1, f);
|
||||
switch (comp) {
|
||||
case 1:
|
||||
case 2: write3(f, d[0],d[0],d[0]);
|
||||
break;
|
||||
case 4:
|
||||
if (!write_alpha) {
|
||||
// composite against pink background
|
||||
for (k=0; k < 3; ++k)
|
||||
px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255;
|
||||
write3(f, px[1-rgb_dir],px[1],px[1+rgb_dir]);
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case 3:
|
||||
write3(f, d[1-rgb_dir],d[1],d[1+rgb_dir]);
|
||||
break;
|
||||
}
|
||||
if (write_alpha > 0)
|
||||
fwrite(&d[comp-1], 1, 1, f);
|
||||
}
|
||||
fwrite(&zero,scanline_pad,1,f);
|
||||
}
|
||||
}
|
||||
|
||||
static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, void *data, int alpha, int pad, const char *fmt, ...)
|
||||
{
|
||||
FILE *f;
|
||||
if (y < 0 || x < 0) return 0;
|
||||
f = fopen(filename, "wb");
|
||||
if (f) {
|
||||
va_list v;
|
||||
va_start(v, fmt);
|
||||
writefv(f, fmt, v);
|
||||
va_end(v);
|
||||
write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad);
|
||||
fclose(f);
|
||||
}
|
||||
return f != NULL;
|
||||
}
|
||||
|
||||
int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
|
||||
{
|
||||
int pad = (-x*3) & 3;
|
||||
return outfile(filename,-1,-1,x,y,comp,(void *) data,0,pad,
|
||||
"11 4 22 4" "4 44 22 444444",
|
||||
'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
|
||||
40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
|
||||
}
|
||||
|
||||
int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
|
||||
{
|
||||
int has_alpha = !(comp & 1);
|
||||
return outfile(filename, -1,-1, x, y, comp, (void *) data, has_alpha, 0,
|
||||
"111 221 2222 11", 0,0,2, 0,0,0, 0,0,x,y, 24+8*has_alpha, 8*has_alpha);
|
||||
}
|
||||
|
||||
// stretchy buffer; stbi__sbpush() == vector<>::push_back() -- stbi__sbcount() == vector<>::size()
|
||||
#define stbi__sbraw(a) ((int *) (a) - 2)
|
||||
#define stbi__sbm(a) stbi__sbraw(a)[0]
|
||||
#define stbi__sbn(a) stbi__sbraw(a)[1]
|
||||
|
||||
#define stbi__sbneedgrow(a,n) ((a)==0 || stbi__sbn(a)+n >= stbi__sbm(a))
|
||||
#define stbi__sbmaybegrow(a,n) (stbi__sbneedgrow(a,(n)) ? stbi__sbgrow(a,n) : 0)
|
||||
#define stbi__sbgrow(a,n) stbi__sbgrowf((void **) &(a), (n), sizeof(*(a)))
|
||||
|
||||
#define stbi__sbpush(a, v) (stbi__sbmaybegrow(a,1), (a)[stbi__sbn(a)++] = (v))
|
||||
#define stbi__sbcount(a) ((a) ? stbi__sbn(a) : 0)
|
||||
#define stbi__sbfree(a) ((a) ? free(stbi__sbraw(a)),0 : 0)
|
||||
|
||||
static void *stbi__sbgrowf(void **arr, int increment, int itemsize)
|
||||
{
|
||||
int m = *arr ? 2*stbi__sbm(*arr)+increment : increment+1;
|
||||
void *p = realloc(*arr ? stbi__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2);
|
||||
assert(p);
|
||||
if (p) {
|
||||
if (!*arr) ((int *) p)[1] = 0;
|
||||
*arr = (void *) ((int *) p + 2);
|
||||
stbi__sbm(*arr) = m;
|
||||
}
|
||||
return *arr;
|
||||
}
|
||||
|
||||
static unsigned char *stbi__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
|
||||
{
|
||||
while (*bitcount >= 8) {
|
||||
stbi__sbpush(data, (unsigned char) *bitbuffer);
|
||||
*bitbuffer >>= 8;
|
||||
*bitcount -= 8;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
static int stbi__zlib_bitrev(int code, int codebits)
|
||||
{
|
||||
int res=0;
|
||||
while (codebits--) {
|
||||
res = (res << 1) | (code & 1);
|
||||
code >>= 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static unsigned int stbi__zlib_countm(unsigned char *a, unsigned char *b, int limit)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < limit && i < 258; ++i)
|
||||
if (a[i] != b[i]) break;
|
||||
return i;
|
||||
}
|
||||
|
||||
static unsigned int stbi__zhash(unsigned char *data)
|
||||
{
|
||||
stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
|
||||
hash ^= hash << 3;
|
||||
hash += hash >> 5;
|
||||
hash ^= hash << 4;
|
||||
hash += hash >> 17;
|
||||
hash ^= hash << 25;
|
||||
hash += hash >> 6;
|
||||
return hash;
|
||||
}
|
||||
|
||||
#define stbi__zlib_flush() (out = stbi__zlib_flushf(out, &bitbuf, &bitcount))
|
||||
#define stbi__zlib_add(code,codebits) \
|
||||
(bitbuf |= (code) << bitcount, bitcount += (codebits), stbi__zlib_flush())
|
||||
#define stbi__zlib_huffa(b,c) stbi__zlib_add(stbi__zlib_bitrev(b,c),c)
|
||||
// default huffman tables
|
||||
#define stbi__zlib_huff1(n) stbi__zlib_huffa(0x30 + (n), 8)
|
||||
#define stbi__zlib_huff2(n) stbi__zlib_huffa(0x190 + (n)-144, 9)
|
||||
#define stbi__zlib_huff3(n) stbi__zlib_huffa(0 + (n)-256,7)
|
||||
#define stbi__zlib_huff4(n) stbi__zlib_huffa(0xc0 + (n)-280,8)
|
||||
#define stbi__zlib_huff(n) ((n) <= 143 ? stbi__zlib_huff1(n) : (n) <= 255 ? stbi__zlib_huff2(n) : (n) <= 279 ? stbi__zlib_huff3(n) : stbi__zlib_huff4(n))
|
||||
#define stbi__zlib_huffb(n) ((n) <= 143 ? stbi__zlib_huff1(n) : stbi__zlib_huff2(n))
|
||||
|
||||
#define stbi__ZHASH 16384
|
||||
|
||||
unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
|
||||
{
|
||||
static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 };
|
||||
static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 };
|
||||
static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 };
|
||||
static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 };
|
||||
unsigned int bitbuf=0;
|
||||
int i,j, bitcount=0;
|
||||
unsigned char *out = NULL;
|
||||
unsigned char **hash_table[stbi__ZHASH]; // 64KB on the stack!
|
||||
if (quality < 5) quality = 5;
|
||||
|
||||
stbi__sbpush(out, 0x78); // DEFLATE 32K window
|
||||
stbi__sbpush(out, 0x5e); // FLEVEL = 1
|
||||
stbi__zlib_add(1,1); // BFINAL = 1
|
||||
stbi__zlib_add(1,2); // BTYPE = 1 -- fixed huffman
|
||||
|
||||
for (i=0; i < stbi__ZHASH; ++i)
|
||||
hash_table[i] = NULL;
|
||||
|
||||
i=0;
|
||||
while (i < data_len-3) {
|
||||
// hash next 3 bytes of data to be compressed
|
||||
int h = stbi__zhash(data+i)&(stbi__ZHASH-1), best=3;
|
||||
unsigned char *bestloc = 0;
|
||||
unsigned char **hlist = hash_table[h];
|
||||
int n = stbi__sbcount(hlist);
|
||||
for (j=0; j < n; ++j) {
|
||||
if (hlist[j]-data > i-32768) { // if entry lies within window
|
||||
int d = stbi__zlib_countm(hlist[j], data+i, data_len-i);
|
||||
if (d >= best) best=d,bestloc=hlist[j];
|
||||
}
|
||||
}
|
||||
// when hash table entry is too long, delete half the entries
|
||||
if (hash_table[h] && stbi__sbn(hash_table[h]) == 2*quality) {
|
||||
memcpy(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
|
||||
stbi__sbn(hash_table[h]) = quality;
|
||||
}
|
||||
stbi__sbpush(hash_table[h],data+i);
|
||||
|
||||
if (bestloc) {
|
||||
// "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal
|
||||
h = stbi__zhash(data+i+1)&(stbi__ZHASH-1);
|
||||
hlist = hash_table[h];
|
||||
n = stbi__sbcount(hlist);
|
||||
for (j=0; j < n; ++j) {
|
||||
if (hlist[j]-data > i-32767) {
|
||||
int e = stbi__zlib_countm(hlist[j], data+i+1, data_len-i-1);
|
||||
if (e > best) { // if next match is better, bail on current match
|
||||
bestloc = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestloc) {
|
||||
int d = data+i - bestloc; // distance back
|
||||
assert(d <= 32767 && best <= 258);
|
||||
for (j=0; best > lengthc[j+1]-1; ++j);
|
||||
stbi__zlib_huff(j+257);
|
||||
if (lengtheb[j]) stbi__zlib_add(best - lengthc[j], lengtheb[j]);
|
||||
for (j=0; d > distc[j+1]-1; ++j);
|
||||
stbi__zlib_add(stbi__zlib_bitrev(j,5),5);
|
||||
if (disteb[j]) stbi__zlib_add(d - distc[j], disteb[j]);
|
||||
i += best;
|
||||
} else {
|
||||
stbi__zlib_huffb(data[i]);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
// write out final bytes
|
||||
for (;i < data_len; ++i)
|
||||
stbi__zlib_huffb(data[i]);
|
||||
stbi__zlib_huff(256); // end of block
|
||||
// pad with 0 bits to byte boundary
|
||||
while (bitcount)
|
||||
stbi__zlib_add(0,1);
|
||||
|
||||
for (i=0; i < stbi__ZHASH; ++i)
|
||||
(void) stbi__sbfree(hash_table[i]);
|
||||
|
||||
{
|
||||
// compute adler32 on input
|
||||
unsigned int i=0, s1=1, s2=0, blocklen = data_len % 5552;
|
||||
int j=0;
|
||||
while (j < data_len) {
|
||||
for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
|
||||
s1 %= 65521, s2 %= 65521;
|
||||
j += blocklen;
|
||||
blocklen = 5552;
|
||||
}
|
||||
stbi__sbpush(out, (unsigned char) (s2 >> 8));
|
||||
stbi__sbpush(out, (unsigned char) s2);
|
||||
stbi__sbpush(out, (unsigned char) (s1 >> 8));
|
||||
stbi__sbpush(out, (unsigned char) s1);
|
||||
}
|
||||
*out_len = stbi__sbn(out);
|
||||
// make returned pointer freeable
|
||||
memmove(stbi__sbraw(out), out, *out_len);
|
||||
return (unsigned char *) stbi__sbraw(out);
|
||||
}
|
||||
|
||||
unsigned int stbi__crc32(unsigned char *buffer, int len)
|
||||
{
|
||||
static unsigned int crc_table[256];
|
||||
unsigned int crc = ~0u;
|
||||
int i,j;
|
||||
if (crc_table[1] == 0)
|
||||
for(i=0; i < 256; i++)
|
||||
for (crc_table[i]=i, j=0; j < 8; ++j)
|
||||
crc_table[i] = (crc_table[i] >> 1) ^ (crc_table[i] & 1 ? 0xedb88320 : 0);
|
||||
for (i=0; i < len; ++i)
|
||||
crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
#define stbi__wpng4(o,a,b,c,d) ((o)[0]=(unsigned char)(a),(o)[1]=(unsigned char)(b),(o)[2]=(unsigned char)(c),(o)[3]=(unsigned char)(d),(o)+=4)
|
||||
#define stbi__wp32(data,v) stbi__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
|
||||
#define stbi__wptag(data,s) stbi__wpng4(data, s[0],s[1],s[2],s[3])
|
||||
|
||||
static void stbi__wpcrc(unsigned char **data, int len)
|
||||
{
|
||||
unsigned int crc = stbi__crc32(*data - len - 4, len+4);
|
||||
stbi__wp32(*data, crc);
|
||||
}
|
||||
|
||||
static unsigned char stbi__paeth(int a, int b, int c)
|
||||
{
|
||||
int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
|
||||
if (pa <= pb && pa <= pc) return (unsigned char) a;
|
||||
if (pb <= pc) return (unsigned char) b;
|
||||
return (unsigned char) c;
|
||||
}
|
||||
|
||||
unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
|
||||
{
|
||||
int ctype[5] = { -1, 0, 4, 2, 6 };
|
||||
unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
|
||||
unsigned char *out,*o, *filt, *zlib;
|
||||
signed char *line_buffer;
|
||||
int i,j,k,p,zlen;
|
||||
|
||||
if (stride_bytes == 0)
|
||||
stride_bytes = x * n;
|
||||
|
||||
filt = (unsigned char *) malloc((x*n+1) * y); if (!filt) return 0;
|
||||
line_buffer = (signed char *) malloc(x * n); if (!line_buffer) { free(filt); return 0; }
|
||||
for (j=0; j < y; ++j) {
|
||||
static int mapping[] = { 0,1,2,3,4 };
|
||||
static int firstmap[] = { 0,1,0,5,6 };
|
||||
int *mymap = j ? mapping : firstmap;
|
||||
int best = 0, bestval = 0x7fffffff;
|
||||
for (p=0; p < 2; ++p) {
|
||||
for (k= p?best:0; k < 5; ++k) {
|
||||
int type = mymap[k],est=0;
|
||||
unsigned char *z = pixels + stride_bytes*j;
|
||||
for (i=0; i < n; ++i)
|
||||
switch (type) {
|
||||
case 0: line_buffer[i] = z[i]; break;
|
||||
case 1: line_buffer[i] = z[i]; break;
|
||||
case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
|
||||
case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break;
|
||||
case 4: line_buffer[i] = (signed char) (z[i] - stbi__paeth(0,z[i-stride_bytes],0)); break;
|
||||
case 5: line_buffer[i] = z[i]; break;
|
||||
case 6: line_buffer[i] = z[i]; break;
|
||||
}
|
||||
for (i=n; i < x*n; ++i) {
|
||||
switch (type) {
|
||||
case 0: line_buffer[i] = z[i]; break;
|
||||
case 1: line_buffer[i] = z[i] - z[i-n]; break;
|
||||
case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
|
||||
case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break;
|
||||
case 4: line_buffer[i] = z[i] - stbi__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break;
|
||||
case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break;
|
||||
case 6: line_buffer[i] = z[i] - stbi__paeth(z[i-n], 0,0); break;
|
||||
}
|
||||
}
|
||||
if (p) break;
|
||||
for (i=0; i < x*n; ++i)
|
||||
est += abs((signed char) line_buffer[i]);
|
||||
if (est < bestval) { bestval = est; best = k; }
|
||||
}
|
||||
}
|
||||
// when we get here, best contains the filter type, and line_buffer contains the data
|
||||
filt[j*(x*n+1)] = (unsigned char) best;
|
||||
memcpy(filt+j*(x*n+1)+1, line_buffer, x*n);
|
||||
}
|
||||
free(line_buffer);
|
||||
zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory
|
||||
free(filt);
|
||||
if (!zlib) return 0;
|
||||
|
||||
// each tag requires 12 bytes of overhead
|
||||
out = (unsigned char *) malloc(8 + 12+13 + 12+zlen + 12);
|
||||
if (!out) return 0;
|
||||
*out_len = 8 + 12+13 + 12+zlen + 12;
|
||||
|
||||
o=out;
|
||||
memcpy(o,sig,8); o+= 8;
|
||||
stbi__wp32(o, 13); // header length
|
||||
stbi__wptag(o, "IHDR");
|
||||
stbi__wp32(o, x);
|
||||
stbi__wp32(o, y);
|
||||
*o++ = 8;
|
||||
*o++ = (unsigned char) ctype[n];
|
||||
*o++ = 0;
|
||||
*o++ = 0;
|
||||
*o++ = 0;
|
||||
stbi__wpcrc(&o,13);
|
||||
|
||||
stbi__wp32(o, zlen);
|
||||
stbi__wptag(o, "IDAT");
|
||||
memcpy(o, zlib, zlen); o += zlen; free(zlib);
|
||||
stbi__wpcrc(&o, zlen);
|
||||
|
||||
stbi__wp32(o,0);
|
||||
stbi__wptag(o, "IEND");
|
||||
stbi__wpcrc(&o,0);
|
||||
|
||||
assert(o == out + *out_len);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
|
||||
{
|
||||
FILE *f;
|
||||
int len;
|
||||
unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
|
||||
if (!png) return 0;
|
||||
f = fopen(filename, "wb");
|
||||
if (!f) { free(png); return 0; }
|
||||
fwrite(png, 1, len, f);
|
||||
fclose(f);
|
||||
free(png);
|
||||
return 1;
|
||||
}
|
||||
#endif // STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
|
||||
/* Revision history
|
||||
|
||||
0.92 (2010-08-01)
|
||||
casts to unsigned char to fix warnings
|
||||
0.91 (2010-07-17)
|
||||
first public release
|
||||
0.90 first internal release
|
||||
*/
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
source_suffix = '.rst'
|
||||
master_doc = 'index'
|
||||
project = 'gltools'
|
||||
copyright = '2012, Runar Tenfjord'
|
||||
|
||||
extensions = ['sphinx.ext.autodoc']
|
||||
autodoc_docstring_signature = True
|
||||
autodoc_member_order = 'groupwise'
|
||||
|
||||
html_style = 'default.css'
|
||||
htmlhelp_basename = 'gltoolsdoc'
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
// 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 <GLFW/glfw3.h>
|
||||
#include <GL/glext.h>
|
||||
|
||||
#define GLEXTPROCSIZE 27
|
||||
#define VERTEXBUFFERATTRIBSIZE 8
|
||||
|
||||
extern char errorMessage[256];
|
||||
void setErrorMessage(const char *err);
|
||||
|
||||
// opengl error check
|
||||
int glCheck();
|
||||
|
||||
// opengl font
|
||||
extern struct sth_stash *_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 PFNGLACTIVETEXTUREPROC pglActiveTexture = NULL;
|
||||
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);
|
||||
|
||||
class TextureRect2D {
|
||||
public:
|
||||
GLuint m_id;
|
||||
GLuint m_width;
|
||||
GLuint m_height;
|
||||
GLuint m_depth;
|
||||
TextureRect2D(int width, int height, int depth, void *data);
|
||||
~TextureRect2D();
|
||||
void blit(float x, float y);
|
||||
void copy(GLenum mode);
|
||||
};
|
||||
|
||||
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
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
# -*- 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 glCheck()
|
||||
|
||||
int stbi_write_png(char *filename, int w, int h, int comp, void *data, int stride_in_bytes)
|
||||
|
||||
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_TextureRect2D "TextureRect2D":
|
||||
GLuint m_width
|
||||
GLuint m_height
|
||||
GLuint m_depth
|
||||
c_TextureRect2D(int width, int height, int depth, void *data)
|
||||
void blit(float x, float y)
|
||||
void copy(GLenum mode)
|
||||
|
||||
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)
|
||||
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
cdef extern from "stb_image_write.h":
|
||||
int stbi_write_png(char *filename, int w, int h, int comp, void *data, int stride_in_bytes)
|
||||
|
|
@ -1,285 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
cdef extern from "GLFW/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 glDepthFunc(GLenum func)
|
||||
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 glGetIntegerv(GLenum pname, GLint *params)
|
||||
void glHint(GLenum target, GLenum mode)
|
||||
void glPointSize(GLfloat size)
|
||||
void glLineWidth(GLfloat width)
|
||||
void glLightf(GLenum light, GLenum pname, GLfloat param)
|
||||
void glLightfv(GLenum light, GLenum pname, GLfloat *params )
|
||||
void glLightModeli(GLenum pname, GLint param)
|
||||
void glLightModelfv(GLenum pname, GLfloat *params)
|
||||
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 glPixelStorei(GLenum pname, GLint param)
|
||||
void glPolygonMode(GLenum face, GLenum mode)
|
||||
void glPolygonOffset(GLfloat factor, GLfloat units)
|
||||
void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels)
|
||||
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
|
||||
|
||||
# Hints
|
||||
GL_PERSPECTIVE_CORRECTION_HINT
|
||||
GL_POINT_SMOOTH_HINT
|
||||
GL_LINE_SMOOTH_HINT
|
||||
GL_POLYGON_SMOOTH_HINT
|
||||
GL_FOG_HINT
|
||||
GL_DONT_CARE
|
||||
GL_FASTEST
|
||||
GL_NICEST
|
||||
|
||||
# Ligthing & Material
|
||||
GL_AMBIENT
|
||||
GL_DIFFUSE
|
||||
GL_SPECULAR
|
||||
GL_SHININESS
|
||||
GL_EMISSION
|
||||
GL_POSITION
|
||||
GL_SPOT_DIRECTION
|
||||
GL_SPOT_EXPONENT
|
||||
GL_SPOT_CUTOFF
|
||||
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
|
||||
GL_POLYGON_OFFSET_LINE
|
||||
GL_POLYGON_OFFSET_FILL
|
||||
|
||||
# ShadingModel
|
||||
GL_FLAT
|
||||
GL_SMOOTH
|
||||
|
||||
# Images
|
||||
GL_RGB
|
||||
GL_RGBA
|
||||
GL_PACK_ALIGNMENT
|
||||
|
||||
# Texture mapping
|
||||
GL_TEXTURE_1D
|
||||
GL_TEXTURE_2D
|
||||
|
||||
# glext.h
|
||||
GL_MULTISAMPLE
|
||||
GL_STATIC_DRAW
|
||||
|
||||
GL_ARRAY_BUFFER
|
||||
GL_ELEMENT_ARRAY_BUFFER
|
||||
|
||||
|
|
@ -1,397 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
cdef extern from "GLFW/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
|
||||
|
||||
# Modifiers
|
||||
GLFW_MOD_SHIFT
|
||||
GLFW_MOD_CONTROL
|
||||
GLFW_MOD_ALT
|
||||
GLFW_MOD_SUPER
|
||||
|
||||
# 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
|
||||
|
||||
# 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_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)()
|
||||
|
||||
# Monitor handle type
|
||||
cdef struct GLFWmonitor:
|
||||
pass
|
||||
|
||||
# Window handle type
|
||||
cdef struct GLFWwindow:
|
||||
pass
|
||||
|
||||
# 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 *,double,double)
|
||||
ctypedef void (* GLFWcursorenterfun)(GLFWwindow *,int)
|
||||
ctypedef void (* GLFWscrollfun)(GLFWwindow *,double,double)
|
||||
ctypedef void (* GLFWkeyfun)(GLFWwindow *,int,int,int,int)
|
||||
ctypedef void (* GLFWcharfun)(GLFWwindow *,int)
|
||||
ctypedef void (* GLFWmonitorfun)(c_GLFWmonitor,int)
|
||||
|
||||
# The video mode structure used by glfwGetVideoModes
|
||||
cdef struct _GLFWvidmode:
|
||||
int width
|
||||
int height
|
||||
int redBits
|
||||
int blueBits
|
||||
int greenBits
|
||||
int refreshRate
|
||||
|
||||
ctypedef _GLFWvidmode GLFWvidmode
|
||||
|
||||
# Gamma ramp
|
||||
cdef struct _GLFWgammaramp:
|
||||
unsigned short* red
|
||||
unsigned short* green
|
||||
unsigned short* blue
|
||||
unsigned int 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)
|
||||
|
||||
# Monitor handling
|
||||
GLFWmonitor *glfwGetMonitors(int* count)
|
||||
GLFWmonitor *glfwGetPrimaryMonitor()
|
||||
void glfwGetMonitorPos(GLFWmonitor *monitor, int* xpos, int* ypos)
|
||||
void glfwGetMonitorPhysicalSize(GLFWmonitor *monitor, int* width, int* height)
|
||||
char* glfwGetMonitorName(GLFWmonitor *monitor)
|
||||
GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun)
|
||||
|
||||
# Video mode functions
|
||||
GLFWvidmode* glfwGetVideoModes(int* count)
|
||||
const GLFWvidmode* glfwGetVideoMode(GLFWmonitor *monitor)
|
||||
|
||||
# Gamma ramp functions
|
||||
void glfwSetGamma(GLFWmonitor *monitor, float gamma)
|
||||
GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor *monitor)
|
||||
void glfwSetGammaRamp(GLFWmonitor *monitor, GLFWgammaramp* ramp)
|
||||
|
||||
# Window handling
|
||||
void glfwDefaultWindowHints()
|
||||
void glfwWindowHint(int target, int hint)
|
||||
GLFWwindow * glfwCreateWindow(int width, int height, char* title, GLFWmonitor *monitor, GLFWwindow * share)
|
||||
int glfwWindowShouldClose(GLFWwindow * window)
|
||||
void glfwSetWindowShouldClose(GLFWwindow * window, int value)
|
||||
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)
|
||||
GLFWmonitor *glfwGetWindowMonitor(GLFWwindow * window)
|
||||
int glfwGetWindowParam(GLFWwindow * window, int param)
|
||||
void glfwSetWindowUserPointer(GLFWwindow * window, void* pointer)
|
||||
void* glfwGetWindowUserPointer(GLFWwindow * window)
|
||||
void glfwSetWindowSizeCallback(GLFWwindow * window, GLFWwindowsizefun cbfun)
|
||||
void glfwSetWindowCloseCallback(GLFWwindow * window, GLFWwindowclosefun cbfun)
|
||||
void glfwSetWindowRefreshCallback(GLFWwindow * window, GLFWwindowrefreshfun cbfun)
|
||||
void glfwSetWindowFocusCallback(GLFWwindow * window, GLFWwindowfocusfun cbfun)
|
||||
void glfwSetWindowIconifyCallback(GLFWwindow * window, 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, double* xpos, double* ypos)
|
||||
void glfwSetCursorPos(GLFWwindow * window, double xpos, double ypos)
|
||||
void glfwGetScrollOffset(GLFWwindow * window, double* xoffset, double* yoffset)
|
||||
void glfwSetKeyCallback(GLFWwindow * window, GLFWkeyfun cbfun)
|
||||
void glfwSetCharCallback(GLFWwindow * window, GLFWcharfun cbfun)
|
||||
void glfwSetMouseButtonCallback(GLFWwindow * window, GLFWmousebuttonfun cbfun)
|
||||
void glfwSetCursorPosCallback(GLFWwindow * window, GLFWcursorposfun cbfun)
|
||||
void glfwSetCursorEnterCallback(GLFWwindow * window, GLFWcursorenterfun cbfun)
|
||||
void glfwSetScrollCallback(GLFWwindow * window, 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)
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
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()
|
||||
|
||||
bint imguiBeginArea(char* name, int x, int y, int w, int h)
|
||||
void imguiEndArea()
|
||||
|
||||
void imguiIndent()
|
||||
void imguiUnindent()
|
||||
void imguiSeparator()
|
||||
void imguiSeparatorLine()
|
||||
|
||||
bint imguiButton(char* text, bint enabled, int x, int y, int w, int h)
|
||||
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)
|
||||
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of gltools - See LICENSE.txt
|
||||
#
|
||||
|
||||
cdef class ClientBuffer:
|
||||
'''
|
||||
Abstraction of OpenGL vertex buffer
|
||||
|
||||
The class initialize a single buffer object.
|
||||
The target argument is either gl.ARRAY_BUFFER
|
||||
or gl.ELEMENT_ARRAY_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)
|
||||
|
||||
if not glCheck():
|
||||
raise GLError(errorMessage)
|
||||
|
||||
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):
|
||||
'''
|
||||
Bind the buffer object and possible set the attribute pointers
|
||||
ig the target is gl.ARRAY_BUFFER and the datatype is defined
|
||||
'''
|
||||
cdef c_ClientBuffer *buf = <c_ClientBuffer *>self.thisptr
|
||||
buf.bind()
|
||||
|
||||
cpdef unBind(self):
|
||||
'''
|
||||
Unbind the buffer object
|
||||
'''
|
||||
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. Only makes sense when
|
||||
target is gl.ARRAY_BUFFER.
|
||||
|
||||
:type: gl.VERTEX_ARRAY, gl.NORMAL_ARRAY or gl.COLOR_ARRAY.
|
||||
:dataType: gl.FLOAT, gl.INT etc.
|
||||
:dataTypeSize: size of datatype.
|
||||
:stride: stride between data
|
||||
:pointer: pointer into buffer object (offser from index 0)
|
||||
|
||||
example::
|
||||
buffer.setDataType(gl.VERTEX_ARRAY, gl.FLOAT, 3, 0, 0)
|
||||
'''
|
||||
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.
|
||||
|
||||
:data: None, or any python python object with buffer interface
|
||||
:size: size of data to upload.
|
||||
:offset: offset into buffer object
|
||||
'''
|
||||
if data is None:
|
||||
self.cloadData(NULL, size, offset, usage)
|
||||
else:
|
||||
self.cloadData(getVoidPtr(data), size, offset, usage)
|
||||
|
|
@ -1,246 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of gltools - See LICENSE.txt
|
||||
#
|
||||
cdef class ColorRGBA:
|
||||
'''
|
||||
RGBA color with components stored as unsigned
|
||||
bytes.
|
||||
'''
|
||||
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):
|
||||
'''
|
||||
Scale color components and 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):
|
||||
'''
|
||||
Create copy with optional changes.
|
||||
'''
|
||||
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):
|
||||
'''
|
||||
Pack color to a single unsigned int
|
||||
'''
|
||||
return self.alpha << 24 | self.blue << 16 | self.green << 8 | self.red
|
||||
|
||||
cpdef fromInt(self, unsigned int value):
|
||||
'''
|
||||
Unpack color from unsigned int
|
||||
'''
|
||||
self.red = value & 0x000000FF
|
||||
self.green = (value & 0x0000FF00) >> 8
|
||||
self.blue = (value & 0x00FF0000) >> 16
|
||||
self.alpha = (value & 0xFF000000) >> 24
|
||||
|
||||
cpdef tuple toFloatVector(self):
|
||||
'''
|
||||
Return color as float normalized [0.0 - 1.0]
|
||||
'''
|
||||
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:
|
||||
'''
|
||||
Abstraction 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):
|
||||
'''
|
||||
Set OpenGL material state
|
||||
'''
|
||||
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)
|
||||
|
||||
cpdef AmbientLight(ColorRGBA col):
|
||||
'''
|
||||
Set global ambient light color.
|
||||
'''
|
||||
cdef float c_col[4]
|
||||
col.setFloatVector(c_col)
|
||||
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, c_col)
|
||||
|
||||
cdef class Light:
|
||||
'''
|
||||
Abstraction of OpenGL light
|
||||
'''
|
||||
def __init__(self, int index = 0, Material material = None,
|
||||
Point position = None, directional = True,
|
||||
Vector direction = None):
|
||||
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
|
||||
self.direction = direction
|
||||
|
||||
def __str__(self):
|
||||
return "Light%s" % repr(self)
|
||||
|
||||
def __repr__(self):
|
||||
return "()"
|
||||
|
||||
cpdef enable(self):
|
||||
'''
|
||||
Enable light and set OpenGL state
|
||||
'''
|
||||
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 self.directional:
|
||||
mat[3] = 0.
|
||||
else:
|
||||
mat[3] = 1.
|
||||
|
||||
if not self.direction is None:
|
||||
mat[0], mat[1], mat[2] = self.direction
|
||||
else:
|
||||
mat[0], mat[1], mat[2] = 0., 0., -1.
|
||||
|
||||
glLightfv(self.index, GL_SPOT_DIRECTION, mat)
|
||||
|
||||
if not self.position is None:
|
||||
mat[0], mat[1], mat[2] = self.position
|
||||
else:
|
||||
mat[0], mat[1], mat[2] = 0., 0., 0.
|
||||
|
||||
glLightfv(self.index, GL_POSITION, mat)
|
||||
|
||||
glLightf(self.index, GL_SPOT_CUTOFF, 180.)
|
||||
glLightf(self.index, GL_SPOT_EXPONENT, 0.)
|
||||
|
||||
cpdef disable(self):
|
||||
'''
|
||||
Disable light
|
||||
'''
|
||||
glDisable(self.index)
|
||||
|
|
@ -1,262 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
class ACTION:
|
||||
RELEASE = GLFW_RELEASE
|
||||
PRESS = GLFW_PRESS
|
||||
|
||||
class KEY:
|
||||
SPACE = GLFW_KEY_SPACE
|
||||
APOSTROPHE = GLFW_KEY_APOSTROPHE
|
||||
COMMA = GLFW_KEY_COMMA
|
||||
MINUS = GLFW_KEY_MINUS
|
||||
PERIOD = GLFW_KEY_PERIOD
|
||||
SLASH = GLFW_KEY_SLASH
|
||||
ZERO = GLFW_KEY_0
|
||||
ONE = GLFW_KEY_1
|
||||
TWO = GLFW_KEY_2
|
||||
THREE = GLFW_KEY_3
|
||||
FOUR = GLFW_KEY_4
|
||||
FIVE = GLFW_KEY_5
|
||||
SIX = GLFW_KEY_6
|
||||
SEVEN = GLFW_KEY_7
|
||||
EIGHT = GLFW_KEY_8
|
||||
NINE = GLFW_KEY_9
|
||||
SEMICOLON = GLFW_KEY_SEMICOLON
|
||||
EQUAL = GLFW_KEY_EQUAL
|
||||
A = GLFW_KEY_A
|
||||
B = GLFW_KEY_B
|
||||
C = GLFW_KEY_C
|
||||
D = GLFW_KEY_D
|
||||
E = GLFW_KEY_E
|
||||
F = GLFW_KEY_F
|
||||
G = GLFW_KEY_G
|
||||
H = GLFW_KEY_H
|
||||
I = GLFW_KEY_I
|
||||
J = GLFW_KEY_J
|
||||
K = GLFW_KEY_K
|
||||
L = GLFW_KEY_L
|
||||
M = GLFW_KEY_M
|
||||
N = GLFW_KEY_N
|
||||
O = GLFW_KEY_O
|
||||
P = GLFW_KEY_P
|
||||
Q = GLFW_KEY_Q
|
||||
R = GLFW_KEY_R
|
||||
S = GLFW_KEY_S
|
||||
T = GLFW_KEY_T
|
||||
U = GLFW_KEY_U
|
||||
V = GLFW_KEY_V
|
||||
W = GLFW_KEY_W
|
||||
X = GLFW_KEY_X
|
||||
Y = GLFW_KEY_Y
|
||||
Z = GLFW_KEY_Z
|
||||
LEFT_BRACKET = GLFW_KEY_LEFT_BRACKET
|
||||
BACKSLASH = GLFW_KEY_BACKSLASH
|
||||
RIGHT_BRACKET = GLFW_KEY_RIGHT_BRACKET
|
||||
SPACE = GLFW_KEY_SPACE
|
||||
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
|
||||
LEFT_SHIFT = GLFW_KEY_LEFT_SHIFT
|
||||
LEFT_CONTROL = GLFW_KEY_LEFT_CONTROL
|
||||
LEFT_ALT = GLFW_KEY_LEFT_ALT
|
||||
RIGHT_SHIFT = GLFW_KEY_RIGHT_SHIFT
|
||||
RIGHT_CONTROL = GLFW_KEY_RIGHT_CONTROL
|
||||
RIGHT_ALT = GLFW_KEY_RIGHT_ALT
|
||||
|
||||
class MOD:
|
||||
SHIFT = GLFW_MOD_SHIFT
|
||||
CONTROL = GLFW_MOD_CONTROL
|
||||
ALT = GLFW_MOD_ALT
|
||||
SUPER = GLFW_MOD_SUPER
|
||||
|
||||
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
|
||||
POLYGON_OFFSET_LINE = GL_POLYGON_OFFSET_LINE
|
||||
POLYGON_OFFSET_FILL = GL_POLYGON_OFFSET_FILL
|
||||
|
||||
# ShadingModel
|
||||
FLAT = GL_FLAT
|
||||
SMOOTH = GL_SMOOTH
|
||||
|
||||
# Hints
|
||||
PERSPECTIVE_CORRECTION_HINT = GL_PERSPECTIVE_CORRECTION_HINT
|
||||
POINT_SMOOTH_HINT = GL_POINT_SMOOTH_HINT
|
||||
LINE_SMOOTH_HINT = GL_LINE_SMOOTH_HINT
|
||||
POLYGON_SMOOTH_HINT = GL_POLYGON_SMOOTH_HINT
|
||||
FOG_HINT = GL_FOG_HINT
|
||||
DONT_CARE = GL_DONT_CARE
|
||||
FASTEST = GL_FASTEST
|
||||
NICEST = GL_NICEST
|
||||
|
||||
# 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
|
||||
|
||||
# Images
|
||||
RGB = GL_RGB
|
||||
RGBA = GL_RGBA
|
||||
|
||||
# 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
|
||||
|
|
@ -1,260 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of gltools - See LICENSE.txt
|
||||
#
|
||||
|
||||
from glLib cimport *
|
||||
|
||||
# init OpenGL function pointers
|
||||
cpdef InitGLExt():
|
||||
'''
|
||||
Initialize OpenGL 2.1 extension
|
||||
|
||||
Raise GLError if extensions not found
|
||||
'''
|
||||
if not c_initGLExt():
|
||||
raise GLError(errorMessage)
|
||||
|
||||
cpdef int Check():
|
||||
'''
|
||||
Check for OpenGL errors.
|
||||
|
||||
Raises GLError.
|
||||
'''
|
||||
if not glCheck():
|
||||
raise GLError(errorMessage)
|
||||
|
||||
cpdef BlendFunc(unsigned int sfactor, unsigned int dfactor):
|
||||
'''
|
||||
Specify pixel arithmetic
|
||||
|
||||
:sfactor: Specifies how the red, green, blue, and alpha source blending
|
||||
factors are computed. The initial value is GL_ONE.
|
||||
|
||||
:dfactor: Specifies how the red, green, blue, and alpha destination
|
||||
blending factors are computed. gl.ONE_MINUS_SRC_COLOR etc.
|
||||
'''
|
||||
glBlendFunc(sfactor, dfactor)
|
||||
|
||||
cpdef Clear(unsigned int mask):
|
||||
'''
|
||||
Clear selected buffers to preset values.
|
||||
|
||||
:mask: bit flags are gl.COLOR_BUFFER_BIT, gl.DEPTH_BUFFER_BIT, and
|
||||
gl.STENCIL_BUFFER_BIT
|
||||
'''
|
||||
glClear(mask)
|
||||
|
||||
cpdef ClearColor(ColorRGBA col):
|
||||
'''
|
||||
Specify clear values for the color buffers
|
||||
'''
|
||||
glClearColor(col.red / 255., col.green / 255., col.blue / 255., col.alpha / 255.)
|
||||
|
||||
cpdef ClearDepth(double depth):
|
||||
'''
|
||||
Specify the clear value for the depth buffer
|
||||
'''
|
||||
glClearDepth(depth)
|
||||
|
||||
cpdef DepthFunc(int func):
|
||||
'''
|
||||
Specify the value used for depth buffer comparisons
|
||||
'''
|
||||
glDepthFunc(func)
|
||||
|
||||
cpdef Color(ColorRGBA col):
|
||||
'''
|
||||
Sets the current color.
|
||||
'''
|
||||
glColor4ub(col.red, col.green, col.blue, col.alpha )
|
||||
|
||||
cpdef Disable(unsigned int cap):
|
||||
'''
|
||||
Disable server-side GL capabilities
|
||||
'''
|
||||
glDisable(cap)
|
||||
|
||||
cpdef DrawArrays(unsigned int mode, int first, int count):
|
||||
'''
|
||||
Render primitives from array data
|
||||
|
||||
:mode: Primitive type gl.POINTS, gl.LINE_STRIP, etc.
|
||||
:first: Specifies the starting index in the enabled arrays.
|
||||
:count: Specifies the number of indices to be rendered.
|
||||
'''
|
||||
glDrawArrays(mode, first, count)
|
||||
|
||||
cpdef DrawElements(unsigned int mode, int count, int type, indices):
|
||||
'''
|
||||
Render primitives from array data with indices.
|
||||
|
||||
:mode: Primitive type gl.POINTS, gl.LINE_STRIP, etc.
|
||||
:count: Specifies the number of indices to be rendered.
|
||||
:type: Indices data type. One of gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT, or
|
||||
gl.UNSIGNED_INT
|
||||
:indices: Either a python object with valid buffer interface or and
|
||||
integer as a pointer into a already bound ClientBuffer of
|
||||
element array type.
|
||||
'''
|
||||
cdef int offset
|
||||
try:
|
||||
offset = indices
|
||||
glDrawElements(mode, count, type, <void *>offset)
|
||||
except TypeError:
|
||||
glDrawElements(mode, count, type, getVoidPtr(indices))
|
||||
|
||||
cpdef Enable(unsigned int cap):
|
||||
'''
|
||||
Enable server-side GL capabilities
|
||||
'''
|
||||
glEnable(cap)
|
||||
|
||||
cpdef Hint(int target, int mode):
|
||||
'''
|
||||
specify implementation-specific hints
|
||||
'''
|
||||
glHint(target, mode)
|
||||
|
||||
cpdef PointSize(float width):
|
||||
'''
|
||||
Specify the diameter of rasterized points
|
||||
'''
|
||||
glPointSize(width)
|
||||
|
||||
cpdef LineWidth(float width):
|
||||
'''
|
||||
Specify the width of rasterized lines
|
||||
'''
|
||||
glLineWidth(width)
|
||||
|
||||
cpdef LightModeli(int pname, int param):
|
||||
'''
|
||||
Sets lighting model parameters.
|
||||
|
||||
Example::
|
||||
gl.LightModeli(gl.LIGHT_MODEL_TWO_SIDE, gl.TRUE)
|
||||
'''
|
||||
glLightModeli(pname, param)
|
||||
|
||||
cpdef LoadIdentity():
|
||||
'''
|
||||
Replace the current matrix with the identity matrix
|
||||
'''
|
||||
glLoadIdentity()
|
||||
|
||||
cpdef LoadMatrixd(Transform tr):
|
||||
'''
|
||||
Replace the current matrix with given matrix.
|
||||
'''
|
||||
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):
|
||||
'''
|
||||
Specify which matrix is the current matrix
|
||||
|
||||
:mode: gl.MODELVIEW, gl.PROJECTION, or gl.TEXTURE
|
||||
'''
|
||||
glMatrixMode(mode)
|
||||
|
||||
cpdef Ortho(double left, double right, double bottom, double top, double zNear,
|
||||
double zFar):
|
||||
'''
|
||||
Multiply the current matrix with an orthographic matrix
|
||||
|
||||
:left: Specify the coordinates for the left vertical clipping plane.
|
||||
:right: Specify the coordinates for the vertical clipping plane.
|
||||
:bottom: Specify the coordinates for the bottom horizontal clipping plane.
|
||||
:top: Specify the coordinates for the top horizontal clipping plane.
|
||||
:zNear: Specify the distances to the nearer clipping plane.
|
||||
:zFar: Specify the distances to the farther depth clipping plane.
|
||||
'''
|
||||
glOrtho(left, right, bottom, top, zNear, zFar)
|
||||
|
||||
cpdef PolygonMode(unsigned int face, unsigned int mode):
|
||||
'''
|
||||
Select a polygon rasterization mode
|
||||
|
||||
Example::
|
||||
gl.PolygonMode(gl.FRONT_AND_BACK, gl.FILL)
|
||||
'''
|
||||
glPolygonMode(face, mode)
|
||||
|
||||
cpdef PolygonOffset(float factor, float units):
|
||||
'''
|
||||
Set the scale and units used to calculate depth values
|
||||
|
||||
:factor: Specifies a scale factor that is used to create a variable depth
|
||||
offset for each polygon.
|
||||
:units: Is multiplied by an implementation-specific value to create a
|
||||
constant depth offset.
|
||||
'''
|
||||
glPolygonOffset(factor, units)
|
||||
|
||||
cpdef ColorRGBA ReadPixel(int x, int y):
|
||||
'''
|
||||
Read a sigle pixel from the frame buffer.
|
||||
'''
|
||||
cdef unsigned char pixel[4]
|
||||
cdef ColorRGBA ret = ColorRGBA.__new__(ColorRGBA)
|
||||
|
||||
glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel)
|
||||
|
||||
ret.red = pixel[0]
|
||||
ret.green = pixel[1]
|
||||
ret.blue = pixel[2]
|
||||
ret.alpha = pixel[3]
|
||||
return ret
|
||||
|
||||
cpdef ReadPixels(int x, int y, Image img):
|
||||
'''
|
||||
Read a block of pixels from the frame buffer
|
||||
'''
|
||||
cdef GLenum format
|
||||
|
||||
if img.bytesPerPixel == 3:
|
||||
format = GL_RGB
|
||||
else:
|
||||
format = GL_RGBA
|
||||
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1)
|
||||
glReadPixels(x, y, img.width, img.height, format, GL_UNSIGNED_BYTE, img._buffer)
|
||||
|
||||
|
||||
cpdef Viewport(int x, int y, int width, int height):
|
||||
'''
|
||||
Set the viewport
|
||||
|
||||
:x: x coordiante of lower left corner.
|
||||
:y: y coordiante of lower left corner.
|
||||
:width: viewport width
|
||||
:height: viewport height
|
||||
'''
|
||||
glViewport(x, y, width, height)
|
||||
|
||||
|
|
@ -1,419 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from glfwLib cimport *
|
||||
|
||||
cpdef Init():
|
||||
'''
|
||||
Initialize GLFW.
|
||||
|
||||
Raise GLError on failure
|
||||
'''
|
||||
if not glfwInit():
|
||||
raise GLError('failed to initialize glfw')
|
||||
|
||||
cpdef Terminate():
|
||||
'''
|
||||
Terminate GLFW
|
||||
'''
|
||||
glfwTerminate()
|
||||
|
||||
# event handling
|
||||
cpdef PollEvents():
|
||||
'''
|
||||
Process pending events and return
|
||||
'''
|
||||
glfwPollEvents()
|
||||
|
||||
cpdef WaitEvents():
|
||||
'''
|
||||
Wait for events
|
||||
'''
|
||||
glfwWaitEvents()
|
||||
|
||||
# timer functions
|
||||
cpdef double GetTime():
|
||||
'''
|
||||
Get current time since call to Init as float value
|
||||
'''
|
||||
Init()
|
||||
return glfwGetTime()
|
||||
|
||||
cpdef SetTime(double time):
|
||||
'''
|
||||
Sets current time
|
||||
'''
|
||||
Init()
|
||||
glfwSetTime(time)
|
||||
|
||||
# gamma value
|
||||
cpdef SetGamma(Window window, float gamma):
|
||||
'''
|
||||
Set gamma value
|
||||
'''
|
||||
Init()
|
||||
glfwSetGamma(glfwGetWindowMonitor(<GLFWwindow *>window.thisptr), gamma)
|
||||
|
||||
# get desktop size
|
||||
cpdef tuple GetDesktopSize(Window window):
|
||||
'''
|
||||
Return desktop size
|
||||
'''
|
||||
cdef GLFWvidmode *vidmode
|
||||
|
||||
Init()
|
||||
vidmode = glfwGetVideoMode(glfwGetWindowMonitor(<GLFWwindow *>window.thisptr))
|
||||
return vidmode.width, vidmode.height
|
||||
|
||||
|
||||
cdef class Window:
|
||||
'''
|
||||
GLFW based window
|
||||
|
||||
If width and height are not set then the window is
|
||||
sized to the current desktop size
|
||||
'''
|
||||
def __init__(self, int width = -1, int height = -1, title = None,
|
||||
bint fullscreen = False):
|
||||
cdef GLFWvidmode *vidmode
|
||||
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)
|
||||
|
||||
# open window
|
||||
if width < 0 or height < 0:
|
||||
# default to desktop size
|
||||
vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor())
|
||||
width, height = vidmode.width, vidmode.height
|
||||
glfwWindowHint(GLFW_RED_BITS, vidmode.redBits)
|
||||
glfwWindowHint(GLFW_GREEN_BITS, vidmode.greenBits)
|
||||
glfwWindowHint(GLFW_BLUE_BITS, vidmode.blueBits)
|
||||
|
||||
# decode to UTF-8
|
||||
if title is None:
|
||||
title = ''
|
||||
bytetext = unicode(title).encode('UTF-8','ignore')
|
||||
c_title = bytetext
|
||||
|
||||
self.thisptr = glfwCreateWindow(width, height, c_title, glfwGetPrimaryMonitor(), 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(<GLFWwindow *>self.thisptr, cb_onSize)
|
||||
glfwSetWindowRefreshCallback(<GLFWwindow *>self.thisptr, cb_onRefresh)
|
||||
glfwSetCursorPosCallback(<GLFWwindow *>self.thisptr, cb_onCursorPos)
|
||||
glfwSetMouseButtonCallback(<GLFWwindow *>self.thisptr, cb_onMouseButton)
|
||||
glfwSetKeyCallback(<GLFWwindow *>self.thisptr, cb_onKey)
|
||||
glfwSetCharCallback(<GLFWwindow *>self.thisptr, cb_onChar)
|
||||
glfwSetWindowCloseCallback(<GLFWwindow *>self.thisptr, cb_onClose)
|
||||
glfwSetWindowFocusCallback(<GLFWwindow *>self.thisptr, cb_onFocus)
|
||||
glfwSetCursorEnterCallback(<GLFWwindow *>self.thisptr, cb_onEnter)
|
||||
glfwSetScrollCallback(<GLFWwindow *>self.thisptr, cb_onScroll)
|
||||
glfwSetWindowIconifyCallback(<GLFWwindow *>self.thisptr, 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):
|
||||
'''
|
||||
Set window 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):
|
||||
'''
|
||||
Get window size
|
||||
'''
|
||||
cdef int width, height
|
||||
glfwGetWindowSize(<GLFWwindow *>self.thisptr, &width, &height)
|
||||
return width, height
|
||||
|
||||
cpdef setSize(self, int width, int height):
|
||||
'''
|
||||
Set window size
|
||||
'''
|
||||
if width <= 0 or height <= 0:
|
||||
raise GLError('window size not valid')
|
||||
glfwSetWindowSize(<GLFWwindow *>self.thisptr, width, height)
|
||||
|
||||
cpdef setClipboard(self, content):
|
||||
'''
|
||||
Set clipboard text
|
||||
'''
|
||||
glfwSetClipboardString(<GLFWwindow *>self.thisptr, content)
|
||||
|
||||
cpdef getClipboard(self):
|
||||
'''
|
||||
Get clipboard text
|
||||
'''
|
||||
cdef const_char *content = glfwGetClipboardString(<GLFWwindow *>self.thisptr)
|
||||
return content
|
||||
|
||||
cpdef iconify(self):
|
||||
'''
|
||||
Iconify window
|
||||
'''
|
||||
glfwIconifyWindow(<GLFWwindow *>self.thisptr)
|
||||
|
||||
cpdef restore(self):
|
||||
'''
|
||||
Restore window from iconification
|
||||
'''
|
||||
glfwRestoreWindow(<GLFWwindow *>self.thisptr)
|
||||
|
||||
cpdef show(self):
|
||||
'''
|
||||
Show window
|
||||
'''
|
||||
glfwShowWindow(<GLFWwindow *>self.thisptr)
|
||||
|
||||
cpdef hide(self):
|
||||
'''
|
||||
Hide window
|
||||
'''
|
||||
glfwHideWindow(<GLFWwindow *>self.thisptr)
|
||||
|
||||
cpdef close(self):
|
||||
'''
|
||||
Stop main loop and close window
|
||||
'''
|
||||
self.running = False
|
||||
glfwDestroyWindow(<GLFWwindow *>self.thisptr)
|
||||
glfwTerminate()
|
||||
|
||||
cpdef makeContextCurrent(self):
|
||||
'''
|
||||
Make window openGL context current
|
||||
'''
|
||||
glfwMakeContextCurrent(<GLFWwindow *>self.thisptr)
|
||||
|
||||
cpdef swapBuffers(self):
|
||||
'''
|
||||
Swap front and back buffers
|
||||
'''
|
||||
glfwSwapBuffers(<GLFWwindow *>self.thisptr)
|
||||
|
||||
cpdef mainLoop(self):
|
||||
'''
|
||||
Run main loop.
|
||||
|
||||
The main loops waits for events. Mouse move events are special
|
||||
handled to avoid to quick update.
|
||||
'''
|
||||
# keep waiting for events until running is False
|
||||
cdef double x, y, lastX, lastY
|
||||
cdef double t
|
||||
|
||||
glfwSetCursorPosCallback(<GLFWwindow *>self.thisptr, NULL)
|
||||
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.error is None:
|
||||
error = self.error
|
||||
self.error = None
|
||||
raise error
|
||||
|
||||
if not self.running:
|
||||
break
|
||||
|
||||
cpdef onSize(self, int w, int h):
|
||||
'''
|
||||
Callback when size changes
|
||||
'''
|
||||
pass
|
||||
|
||||
cpdef onRefresh(self):
|
||||
'''
|
||||
Callback when refresh of content is requested
|
||||
'''
|
||||
pass
|
||||
|
||||
cpdef onCursorPos(self, double x, double y):
|
||||
'''
|
||||
Callback on change of mouse cursor position
|
||||
'''
|
||||
pass
|
||||
|
||||
cpdef onMouseButton(self, int button, int action):
|
||||
'''
|
||||
Callback on mouse button press or release
|
||||
'''
|
||||
pass
|
||||
|
||||
cpdef onKey(self, int key, int scancode, int action, int mods):
|
||||
'''
|
||||
Callback on key press or relase.
|
||||
'''
|
||||
pass
|
||||
|
||||
cpdef onChar(self, ch):
|
||||
'''
|
||||
Callback non-special key pressed
|
||||
'''
|
||||
pass
|
||||
|
||||
cpdef onFocus(self, int status):
|
||||
'''
|
||||
Callback on windows focus change
|
||||
'''
|
||||
pass
|
||||
|
||||
cpdef onEnter(self, int status):
|
||||
'''
|
||||
Callback on mouse pointer enter/leave event
|
||||
'''
|
||||
pass
|
||||
|
||||
cpdef onScroll(self, double dx, double dy):
|
||||
'''
|
||||
Callback on mouse scroll wheel
|
||||
'''
|
||||
pass
|
||||
|
||||
cpdef onIconify(self, int status):
|
||||
'''
|
||||
Callback on iconify status change
|
||||
'''
|
||||
pass
|
||||
|
||||
cpdef bint onClose(self):
|
||||
'''
|
||||
Callback on close request.
|
||||
'''
|
||||
return False
|
||||
|
||||
# callback functions
|
||||
cdef void cb_onSize(GLFWwindow *window, int w, int h):
|
||||
cdef Window self = <Window>glfwGetWindowUserPointer(window)
|
||||
|
||||
try:
|
||||
self.onSize(w, max(1, h))
|
||||
except Exception as err:
|
||||
self.error = err
|
||||
|
||||
cdef void cb_onRefresh(GLFWwindow *window):
|
||||
cdef Window self = <Window>glfwGetWindowUserPointer(window)
|
||||
try:
|
||||
self.onRefresh()
|
||||
except Exception as err:
|
||||
self.error = err
|
||||
|
||||
cdef void cb_onCursorPos(GLFWwindow *window, double x, double y):
|
||||
cdef Window self = <Window>glfwGetWindowUserPointer(window)
|
||||
|
||||
try:
|
||||
self.onCursorPos(x, y)
|
||||
except Exception as err:
|
||||
self.error = err
|
||||
|
||||
cdef void cb_onMouseButton(GLFWwindow *window, int button, int action):
|
||||
cdef Window self = <Window>glfwGetWindowUserPointer(window)
|
||||
|
||||
try:
|
||||
self.onMouseButton(button, action)
|
||||
except Exception as err:
|
||||
self.error = err
|
||||
|
||||
cdef void cb_onKey(GLFWwindow *window, int key, int scancode, int action, int mods):
|
||||
cdef Window self = <Window>glfwGetWindowUserPointer(window)
|
||||
|
||||
try:
|
||||
self.onKey(key, scancode, action, mods)
|
||||
except Exception as err:
|
||||
self.error = err
|
||||
|
||||
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
|
||||
|
||||
try:
|
||||
self.onChar(st.decode('UTF-8', 'ignore'))
|
||||
except Exception as err:
|
||||
self.error = err
|
||||
|
||||
cdef void cb_onFocus(GLFWwindow *window, int status):
|
||||
cdef Window self = <Window>glfwGetWindowUserPointer(window)
|
||||
|
||||
try:
|
||||
self.onFocus(status)
|
||||
except Exception as err:
|
||||
self.error = err
|
||||
|
||||
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)
|
||||
|
||||
try:
|
||||
self.onScroll(dx, dy)
|
||||
except Exception as err:
|
||||
self.error = err
|
||||
|
||||
cdef void cb_onIconify(GLFWwindow *window, int status):
|
||||
cdef Window self = <Window>glfwGetWindowUserPointer(window)
|
||||
|
||||
try:
|
||||
self.onIconify(status)
|
||||
except Exception as err:
|
||||
self.error = err
|
||||
|
||||
cdef int cb_onClose(GLFWwindow *window):
|
||||
cdef Window self = <Window>glfwGetWindowUserPointer(window)
|
||||
cdef int ret
|
||||
|
||||
try:
|
||||
ret = self.onClose()
|
||||
except Exception as err:
|
||||
self.error = err
|
||||
|
||||
if ret:
|
||||
self.running = False
|
||||
|
||||
return ret
|
||||
|
||||
|
|
@ -1,553 +0,0 @@
|
|||
#include "GLTools.h"
|
||||
#include "fontstash.h"
|
||||
#include <Python.h>
|
||||
|
||||
// error handling
|
||||
char errorMessage[256];
|
||||
|
||||
void setErrorMessage(const char *err) {
|
||||
strncpy(errorMessage, err, 255);
|
||||
}
|
||||
|
||||
int glCheck() {
|
||||
switch(glGetError()) {
|
||||
case GL_NO_ERROR:
|
||||
return 1;
|
||||
|
||||
case GL_INVALID_ENUM:
|
||||
setErrorMessage("GL_INVALID_ENUM");
|
||||
break;
|
||||
|
||||
case GL_INVALID_VALUE:
|
||||
setErrorMessage("GL_INVALID_VALUE");
|
||||
break;
|
||||
|
||||
case GL_INVALID_OPERATION:
|
||||
setErrorMessage("GL_INVALID_OPERATION");
|
||||
break;
|
||||
|
||||
case GL_INVALID_FRAMEBUFFER_OPERATION:
|
||||
setErrorMessage("GL_INVALID_FRAMEBUFFER_OPERATION");
|
||||
break;
|
||||
|
||||
case GL_OUT_OF_MEMORY:
|
||||
setErrorMessage("GL_OUT_OF_MEMORY");
|
||||
break;
|
||||
|
||||
default:
|
||||
setErrorMessage("GL_UNKNOWN");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// load font
|
||||
struct sth_stash *_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");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// opengl 2.1 extensions
|
||||
#define GLEXTPROCSIZE 28
|
||||
int isGLExtLoaded = 0;
|
||||
|
||||
int initGLExt(void)
|
||||
{
|
||||
// OpenGL 2.1 functions
|
||||
int status = 0;
|
||||
|
||||
pglActiveTexture = (PFNGLACTIVETEXTUREPROC) glfwGetProcAddress("glActiveTexture");
|
||||
if (pglActiveTexture) status++;
|
||||
|
||||
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 texture rectangle
|
||||
TextureRect2D::TextureRect2D(int width, int height, int depth, void *data = NULL) {
|
||||
GLint iformat, format;
|
||||
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
m_depth = depth;
|
||||
|
||||
if (depth == 4) {
|
||||
iformat = GL_RGBA8;
|
||||
format = GL_RGBA;
|
||||
} else {
|
||||
iformat = GL_RGB8;
|
||||
format = GL_RGB;
|
||||
}
|
||||
|
||||
glGenTextures(1, &m_id);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, m_id);
|
||||
|
||||
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
if (!data) {
|
||||
char *colorBits = new char[width * height * depth];
|
||||
memset(colorBits, 0, width * height * depth);
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, format, width, height, 0,
|
||||
format, GL_UNSIGNED_BYTE, colorBits);
|
||||
delete[] colorBits;
|
||||
} else {
|
||||
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, format, width, height, 0,
|
||||
format, GL_UNSIGNED_BYTE, data);
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, 0);
|
||||
}
|
||||
|
||||
TextureRect2D::~TextureRect2D() {
|
||||
glDeleteTextures(1, &m_id);
|
||||
}
|
||||
|
||||
void TextureRect2D::blit(float x, float y) {
|
||||
glEnable(GL_TEXTURE_RECTANGLE);
|
||||
pglActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, m_id);
|
||||
glColor3ub(255,255,255);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0, 0);
|
||||
glVertex3f(x, y, 0);
|
||||
glTexCoord2f(m_width, 0);
|
||||
glVertex3f(x + m_width, y, 0);
|
||||
glTexCoord2f(m_width, m_height);
|
||||
glVertex3f(x + m_width, y + m_height, 0);
|
||||
glTexCoord2f(0, m_height);
|
||||
glVertex3f(x, y + m_height, 0);
|
||||
glEnd();
|
||||
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, 0);
|
||||
glDisable(GL_TEXTURE_RECTANGLE);
|
||||
}
|
||||
|
||||
void TextureRect2D::copy(GLenum mode = GL_BACK) {
|
||||
glReadBuffer(mode);
|
||||
glEnable(GL_TEXTURE_RECTANGLE);
|
||||
pglActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, m_id);
|
||||
glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE,0,0,0,0,0,m_width, m_height);
|
||||
glBindTexture(GL_TEXTURE_RECTANGLE, 0);
|
||||
glDisable(GL_TEXTURE_RECTANGLE);
|
||||
}
|
||||
|
||||
// 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";
|
||||
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of gltools - See LICENSE.txt
|
||||
#
|
||||
from ImageLib cimport *
|
||||
|
||||
cdef class Image:
|
||||
'''
|
||||
Image buffer containing either an RGB/RGBA 8bit
|
||||
channel image.
|
||||
|
||||
:width: image width
|
||||
:height: image height
|
||||
:format: gl.RGB or gl.RGBA
|
||||
'''
|
||||
def __init__(self, int width, int height, int format):
|
||||
cdef int bytesPerPixel
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
|
||||
if format == GL_RGB:
|
||||
self.bytesPerPixel = 3
|
||||
elif format == GL_RGBA:
|
||||
self.bytesPerPixel = 4
|
||||
else:
|
||||
raise GLError('Image format not supported')
|
||||
|
||||
self._buffer = <unsigned char *>malloc(width * height * self.bytesPerPixel * sizeof(unsigned char))
|
||||
if self._buffer == NULL:
|
||||
raise MemoryError('Could not allocate memory')
|
||||
|
||||
def __dealloc__(self):
|
||||
if not self._buffer == NULL:
|
||||
free(self._buffer)
|
||||
|
||||
def __getbuffer__(self, Py_buffer* buffer, int flags):
|
||||
self.__shape[0] = self.width * self.height * self.bytesPerPixel
|
||||
self.__strides[0] = 1
|
||||
|
||||
buffer.buf = <void *>self._buffer
|
||||
buffer.obj = self
|
||||
buffer.len = self.width * self.height * self.bytesPerPixel
|
||||
buffer.readonly = 0
|
||||
buffer.format = <char*>"B"
|
||||
buffer.ndim = 1
|
||||
buffer.shape = <Py_ssize_t *>&self.__shape[0]
|
||||
buffer.strides = <Py_ssize_t *>&self.__strides[0]
|
||||
buffer.suboffsets = NULL
|
||||
buffer.itemsize = sizeof(unsigned char)
|
||||
buffer.internal = NULL
|
||||
|
||||
def __releasebuffer__(self, Py_buffer* buffer):
|
||||
pass
|
||||
|
||||
def __len__(self):
|
||||
return self.width * self.height * self.bytesPerPixel
|
||||
|
||||
cpdef flipY(self):
|
||||
'''
|
||||
Flip inplace the image in the vertical direction
|
||||
'''
|
||||
cdef unsigned char *pixels = self._buffer
|
||||
cdef int x, y, i, swapY, offset, swapOffset
|
||||
|
||||
for y in range(self.height/ 2):
|
||||
swapY = self.height - y - 1
|
||||
|
||||
for x in range(self.width):
|
||||
offset = self.bytesPerPixel * (x + y * self.width)
|
||||
swapOffset = self.bytesPerPixel * (x + swapY * self.width)
|
||||
|
||||
# Swap R, G and B or A of the 2 pixels
|
||||
for i in range(self.bytesPerPixel):
|
||||
pixels[swapOffset + i], pixels[offset + i] = pixels[offset + i], pixels[swapOffset + i]
|
||||
|
||||
cpdef writePNG(self, filename, int stride = 0):
|
||||
'''
|
||||
Write image to PNG file. Note that the file
|
||||
will be overwritten if not locked.
|
||||
|
||||
:filename: image file name
|
||||
:stride: stride into buffer
|
||||
|
||||
Raises GLError on failure.
|
||||
'''
|
||||
cdef char *c_filename
|
||||
bytetext = unicode(filename).encode('UTF-8','ignore')
|
||||
c_filename = bytetext
|
||||
|
||||
if not stbi_write_png(c_filename, self.width, self.height, self.bytesPerPixel,
|
||||
self._buffer, stride):
|
||||
raise GLError("failed to write to PNG '%s'" % filename)
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,381 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of gltools - See LICENSE.txt
|
||||
#
|
||||
cdef class ShaderProgram:
|
||||
'''
|
||||
Class to encapsulate compiled GLSL shaders
|
||||
'''
|
||||
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):
|
||||
'''
|
||||
Return status
|
||||
'''
|
||||
cdef c_ShaderProgram *prog = <c_ShaderProgram *>self.thisptr
|
||||
return prog.isValid()
|
||||
|
||||
cpdef begin(self):
|
||||
'''
|
||||
Set program as current
|
||||
'''
|
||||
cdef c_ShaderProgram *prog = <c_ShaderProgram *>self.thisptr
|
||||
prog.begin()
|
||||
|
||||
cpdef end(self):
|
||||
'''
|
||||
Unset program. This will enable the fixed openGL pipeline
|
||||
'''
|
||||
cdef c_ShaderProgram *prog = <c_ShaderProgram *>self.thisptr
|
||||
prog.end()
|
||||
|
||||
cpdef loadUniform1i(self, char *name, int value):
|
||||
'''
|
||||
Load named uniform integer 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):
|
||||
'''
|
||||
Load named uniform 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):
|
||||
'''
|
||||
Load named uniform float vector
|
||||
'''
|
||||
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):
|
||||
'''
|
||||
Load named uniform matrix value
|
||||
'''
|
||||
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):
|
||||
'''
|
||||
Compile program source. If no argument is given the
|
||||
default program simulating the fixed pipeline is
|
||||
loaded.
|
||||
|
||||
Raises GLError if failed.
|
||||
'''
|
||||
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:
|
||||
if not isinstance(vertex_src, bytes):
|
||||
vertex_src = vertex_src.encode('ascii')
|
||||
|
||||
if not isinstance(fragment_src, bytes):
|
||||
fragment_src = fragment_src.encode('ascii')
|
||||
|
||||
ret = prog.build(vertex_src, fragment_src)
|
||||
|
||||
if not ret:
|
||||
raise GLError(errorMessage)
|
||||
|
||||
@classmethod
|
||||
def flat(cls):
|
||||
cdef ShaderProgram ret = ShaderProgram()
|
||||
ret.build(GLSL_VERTEX_FLAT, GLSL_FRAG_FLAT)
|
||||
return ret
|
||||
|
||||
@classmethod
|
||||
def pongDiffuse(cls, int lights):
|
||||
cdef ShaderProgram ret = ShaderProgram()
|
||||
|
||||
if lights < 1 or lights > 8:
|
||||
raise GLError('lights must be between 1 and 8')
|
||||
|
||||
INIT = "#define MAX_LIGHTS %d" % lights
|
||||
FRAG_SRC = b"\n".join((INIT.encode('ascii'), GLSL_FRAG_PONG_COMMON, GLSL_FRAG_PONG_DIFFUSE))
|
||||
|
||||
ret.build(GLSL_VERTEX_PONG, FRAG_SRC)
|
||||
return ret
|
||||
|
||||
@classmethod
|
||||
def pongSpecular(cls, int lights):
|
||||
cdef ShaderProgram ret = ShaderProgram()
|
||||
|
||||
if lights < 1 or lights > 8:
|
||||
raise GLError('lights must be between 1 and 8')
|
||||
|
||||
INIT = "#define MAX_LIGHTS %d" % lights
|
||||
FRAG_SRC = b"\n".join((INIT.encode('ascii'), GLSL_FRAG_PONG_COMMON, GLSL_FRAG_PONG_SPECULAR))
|
||||
|
||||
ret.build(GLSL_VERTEX_PONG, FRAG_SRC)
|
||||
return ret
|
||||
|
||||
# simple flat shader for overlay & background
|
||||
cdef char *GLSL_VERTEX_FLAT = \
|
||||
"""
|
||||
varying vec4 col;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
col = gl_Color;
|
||||
gl_Position = ftransform();
|
||||
}
|
||||
"""
|
||||
|
||||
cdef char *GLSL_FRAG_FLAT = \
|
||||
"""
|
||||
varying vec4 col;
|
||||
|
||||
void main (void)
|
||||
{
|
||||
gl_FragColor = col;
|
||||
}
|
||||
"""
|
||||
|
||||
# two sided per-pixel phong shader
|
||||
# ref: http://www.gamedev.net/page/resources/_/technical/opengl/creating-a-glsl-library-r2428
|
||||
|
||||
cdef char *GLSL_VERTEX_PONG = \
|
||||
"""
|
||||
varying vec3 normal;
|
||||
varying vec3 vertex;
|
||||
|
||||
void main()
|
||||
{
|
||||
// Calculate the normal
|
||||
normal = normalize(gl_NormalMatrix * gl_Normal);
|
||||
|
||||
// Transform the vertex position to eye space
|
||||
vertex = vec3(gl_ModelViewMatrix * gl_Vertex);
|
||||
|
||||
gl_Position = ftransform();
|
||||
}
|
||||
"""
|
||||
|
||||
cdef char *GLSL_FRAG_PONG_COMMON = \
|
||||
"""
|
||||
varying vec3 normal;
|
||||
varying vec3 vertex;
|
||||
|
||||
float calculateAttenuation(in int i, in float dist)
|
||||
{
|
||||
return(1.0 / (gl_LightSource[i].constantAttenuation +
|
||||
gl_LightSource[i].linearAttenuation * dist +
|
||||
gl_LightSource[i].quadraticAttenuation * dist * dist));
|
||||
}
|
||||
|
||||
void directionalLight(in int i, in vec3 N, in float shininess,
|
||||
inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)
|
||||
{
|
||||
vec3 L = normalize(gl_LightSource[i].position.xyz);
|
||||
|
||||
float nDotL = dot(N, L);
|
||||
|
||||
if (nDotL > 0.0)
|
||||
{
|
||||
vec3 H = gl_LightSource[i].halfVector.xyz;
|
||||
|
||||
float pf = pow(max(dot(N,H), 0.0), shininess);
|
||||
|
||||
diffuse += gl_LightSource[i].diffuse * nDotL;
|
||||
specular += gl_LightSource[i].specular * pf;
|
||||
}
|
||||
|
||||
ambient += gl_LightSource[i].ambient;
|
||||
}
|
||||
|
||||
void pointLight(in int i, in vec3 N, in vec3 V, in float shininess,
|
||||
inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)
|
||||
{
|
||||
vec3 D = gl_LightSource[i].position.xyz - V;
|
||||
vec3 L = normalize(D);
|
||||
|
||||
float dist = length(D);
|
||||
float attenuation = calculateAttenuation(i, dist);
|
||||
|
||||
float nDotL = dot(N,L);
|
||||
|
||||
if (nDotL > 0.0)
|
||||
{
|
||||
vec3 E = normalize(-V);
|
||||
vec3 R = reflect(-L, N);
|
||||
|
||||
float pf = pow(max(dot(R,E), 0.0), shininess);
|
||||
|
||||
diffuse += gl_LightSource[i].diffuse * attenuation * nDotL;
|
||||
specular += gl_LightSource[i].specular * attenuation * pf;
|
||||
}
|
||||
|
||||
ambient += gl_LightSource[i].ambient * attenuation;
|
||||
}
|
||||
|
||||
void spotLight(in int i, in vec3 N, in vec3 V, in float shininess,
|
||||
inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)
|
||||
{
|
||||
vec3 D = gl_LightSource[i].position.xyz - V;
|
||||
vec3 L = normalize(D);
|
||||
|
||||
float dist = length(D);
|
||||
float attenuation = calculateAttenuation(i, dist);
|
||||
|
||||
float nDotL = dot(N,L);
|
||||
|
||||
if (nDotL > 0.0)
|
||||
{
|
||||
float spotEffect = dot(normalize(gl_LightSource[i].spotDirection), -L);
|
||||
|
||||
if (spotEffect > gl_LightSource[i].spotCosCutoff)
|
||||
{
|
||||
attenuation *= pow(spotEffect, gl_LightSource[i].spotExponent);
|
||||
|
||||
vec3 E = normalize(-V);
|
||||
vec3 R = reflect(-L, N);
|
||||
|
||||
float pf = pow(max(dot(R,E), 0.0), shininess);
|
||||
|
||||
diffuse += gl_LightSource[i].diffuse * attenuation * nDotL;
|
||||
specular += gl_LightSource[i].specular * attenuation * pf;
|
||||
}
|
||||
}
|
||||
|
||||
ambient += gl_LightSource[i].ambient * attenuation;
|
||||
}
|
||||
|
||||
void calculateLighting(in vec3 N, in vec3 V, in float shininess,
|
||||
inout vec4 ambient, inout vec4 diffuse, inout vec4 specular)
|
||||
{
|
||||
// Just loop through each light, and add
|
||||
// its contributions to the color of the pixel.
|
||||
for (int i = 0; i < MAX_LIGHTS - 1; i++)
|
||||
{
|
||||
if (gl_LightSource[i].position.w == 0.0)
|
||||
directionalLight(i, N, shininess, ambient, diffuse, specular);
|
||||
else if (gl_LightSource[i].spotCutoff == 180.0)
|
||||
pointLight(i, N, V, shininess, ambient, diffuse, specular);
|
||||
else
|
||||
spotLight(i, N, V, shininess, ambient, diffuse, specular);
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
cdef char *GLSL_FRAG_PONG_SPECULAR = \
|
||||
"""
|
||||
void main()
|
||||
{
|
||||
// Normalize the normal. A varying variable CANNOT
|
||||
// be modified by a fragment shader. So a new variable
|
||||
// needs to be created.
|
||||
vec3 n = normalize(normal);
|
||||
|
||||
vec4 ambient, diffuse, specular, color;
|
||||
|
||||
// Initialize the contributions.
|
||||
ambient = vec4(0.0);
|
||||
diffuse = vec4(0.0);
|
||||
specular = vec4(0.0);
|
||||
|
||||
// In this case the built in uniform gl_MaxLights is used
|
||||
// to denote the number of lights. A better option may be passing
|
||||
// in the number of lights as a uniform or replacing the current
|
||||
// value with a smaller value.
|
||||
calculateLighting(n, vertex, gl_FrontMaterial.shininess,
|
||||
ambient, diffuse, specular);
|
||||
|
||||
color = gl_FrontLightModelProduct.sceneColor +
|
||||
(ambient * gl_FrontMaterial.ambient) +
|
||||
(diffuse * gl_FrontMaterial.diffuse) +
|
||||
(specular * gl_FrontMaterial.specular);
|
||||
|
||||
// Re-initialize the contributions for the back
|
||||
// pass over the lights
|
||||
ambient = vec4(0.0);
|
||||
diffuse = vec4(0.0);
|
||||
specular = vec4(0.0);
|
||||
|
||||
// Now caculate the back contribution. All that needs to be
|
||||
// done is to flip the normal.
|
||||
calculateLighting(-n, vertex, gl_BackMaterial.shininess,
|
||||
ambient, diffuse, specular);
|
||||
|
||||
color += gl_BackLightModelProduct.sceneColor +
|
||||
(ambient * gl_BackMaterial.ambient) +
|
||||
(diffuse * gl_BackMaterial.diffuse) +
|
||||
(specular * gl_BackMaterial.specular);
|
||||
|
||||
color = clamp(color, 0.0, 1.0);
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
"""
|
||||
|
||||
cdef char *GLSL_FRAG_PONG_DIFFUSE = \
|
||||
"""
|
||||
void main()
|
||||
{
|
||||
// Normalize the normal. A varying variable CANNOT
|
||||
// be modified by a fragment shader. So a new variable
|
||||
// needs to be created.
|
||||
vec3 n = normalize(normal);
|
||||
|
||||
vec4 ambient, diffuse, specular, color;
|
||||
|
||||
// Initialize the contributions.
|
||||
ambient = vec4(0.0);
|
||||
diffuse = vec4(0.0);
|
||||
specular = vec4(0.0);
|
||||
|
||||
// In this case the built in uniform gl_MaxLights is used
|
||||
// to denote the number of lights. A better option may be passing
|
||||
// in the number of lights as a uniform or replacing the current
|
||||
// value with a smaller value.
|
||||
calculateLighting(n, vertex, gl_FrontMaterial.shininess,
|
||||
ambient, diffuse, specular);
|
||||
|
||||
color = gl_FrontLightModelProduct.sceneColor +
|
||||
(ambient * gl_FrontMaterial.ambient) +
|
||||
(diffuse * gl_FrontMaterial.diffuse);
|
||||
|
||||
// Re-initialize the contributions for the back
|
||||
// pass over the lights
|
||||
ambient = vec4(0.0);
|
||||
diffuse = vec4(0.0);
|
||||
specular = vec4(0.0);
|
||||
|
||||
// Now caculate the back contribution. All that needs to be
|
||||
// done is to flip the normal.
|
||||
calculateLighting(-n, vertex, gl_BackMaterial.shininess,
|
||||
ambient, diffuse, specular);
|
||||
|
||||
color += gl_BackLightModelProduct.sceneColor +
|
||||
(ambient * gl_BackMaterial.ambient) +
|
||||
(diffuse * gl_BackMaterial.diffuse);
|
||||
|
||||
color = clamp(color, 0.0, 1.0);
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
"""
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of gltools - See LICENSE.txt
|
||||
#
|
||||
cpdef BeginText():
|
||||
'''
|
||||
Start text drawing
|
||||
'''
|
||||
if not c_beginText():
|
||||
raise GLError(errorMessage)
|
||||
|
||||
cpdef float DrawText(size, float x, float y, text):
|
||||
'''
|
||||
Draw text
|
||||
|
||||
:size: font size
|
||||
:x: x coordinate
|
||||
:y: y coordinate
|
||||
:text: text (must encode to UTF-8)
|
||||
'''
|
||||
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():
|
||||
'''
|
||||
Finish text drawing. This will flush any pending text
|
||||
drawing operations.
|
||||
'''
|
||||
if not c_endText():
|
||||
raise GLError(errorMessage)
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of gltools - See LICENSE.txt
|
||||
#
|
||||
|
||||
cdef class TextureRect2D:
|
||||
'''
|
||||
Abstraction of OpenGL 2d rectangular texture used
|
||||
for keeping a buffer of the screen content.
|
||||
'''
|
||||
def __init__(self, int width, int height, int depth = 3):
|
||||
self.thisptr = new c_TextureRect2D(width, height, depth, NULL)
|
||||
if not glCheck():
|
||||
raise GLError(errorMessage)
|
||||
|
||||
def __dealloc__(self):
|
||||
cdef c_TextureRect2D *tmp
|
||||
|
||||
if self.thisptr != NULL:
|
||||
tmp = <c_TextureRect2D *>self.thisptr
|
||||
del tmp
|
||||
|
||||
def __str__(self):
|
||||
return "TextureRect2D%s" % repr(self)
|
||||
|
||||
def __repr__(self):
|
||||
cdef c_TextureRect2D *tex = <c_TextureRect2D *>self.thisptr
|
||||
args = tex.m_width, tex.m_height, tex.m_depth
|
||||
return "(width = %d, height = %d, depth = %d)" % args
|
||||
|
||||
cpdef blit(self, float x = 0., float y = 0.):
|
||||
'''
|
||||
Blit content of the texture to the back buffer.
|
||||
'''
|
||||
cdef c_TextureRect2D *tex = <c_TextureRect2D *>self.thisptr
|
||||
tex.blit(x, y)
|
||||
|
||||
cpdef copy(self, int mode = GL_BACK):
|
||||
'''
|
||||
Copy buffer content to texture.
|
||||
'''
|
||||
cdef c_TextureRect2D *tex = <c_TextureRect2D *>self.thisptr
|
||||
tex.copy(mode)
|
||||
|
||||
@classmethod
|
||||
def fromImage(cls, Image img):
|
||||
'''
|
||||
Create texture from existing image
|
||||
'''
|
||||
cpdef TextureRect2D ret = TextureRect2D.__new__(TextureRect2D)
|
||||
ret.thisptr = new c_TextureRect2D(img.width, img.height, img.bytesPerPixel, img._buffer)
|
||||
return ret
|
||||
|
|
@ -1,228 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from imguiLib cimport *
|
||||
|
||||
cdef class UI:
|
||||
'''
|
||||
Draw UI elements
|
||||
'''
|
||||
def __init__(self):
|
||||
self.scrollIdx = 0
|
||||
imguiRenderGLInit()
|
||||
|
||||
if not c_initText():
|
||||
raise GLError(errorMessage)
|
||||
|
||||
cpdef bint anyActive(self):
|
||||
'''
|
||||
Return true if any ui element is active
|
||||
'''
|
||||
return imguiAnyActive()
|
||||
|
||||
cpdef flush(self):
|
||||
'''
|
||||
Flush drawing pipeline
|
||||
'''
|
||||
self.scrollIdx = 0
|
||||
imguiRenderGLDraw()
|
||||
|
||||
cpdef beginFrame(self, int mx, int my, char mbut, int scroll):
|
||||
'''
|
||||
Start frame
|
||||
'''
|
||||
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):
|
||||
'''
|
||||
End frame
|
||||
'''
|
||||
imguiEndFrame()
|
||||
|
||||
cpdef bint beginScrollArea(self, name, int x, int y, int w, int h):
|
||||
'''
|
||||
Begin scroll area
|
||||
|
||||
Up to 10 scroll areas can be used, but not nested.
|
||||
'''
|
||||
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):
|
||||
'''
|
||||
End scroll area
|
||||
'''
|
||||
imguiEndScrollArea()
|
||||
|
||||
cpdef bint beginArea(self, name, int x, int y, int w, int h):
|
||||
'''
|
||||
Begin fixed area
|
||||
'''
|
||||
cdef char *c_name
|
||||
|
||||
bytetext = unicode(name).encode('UTF-8','ignore')
|
||||
c_name = bytetext
|
||||
|
||||
return imguiBeginArea(c_name, x, y, w, h)
|
||||
|
||||
cpdef endArea(self):
|
||||
'''
|
||||
End fixed area
|
||||
'''
|
||||
imguiEndArea()
|
||||
|
||||
cpdef indent(self):
|
||||
'''
|
||||
Indent current x position
|
||||
'''
|
||||
imguiIndent()
|
||||
|
||||
cpdef unindent(self):
|
||||
'''
|
||||
Unindent current x position
|
||||
'''
|
||||
imguiUnindent()
|
||||
|
||||
cpdef separator(self):
|
||||
'''
|
||||
Add horisontal separator space
|
||||
'''
|
||||
imguiSeparator()
|
||||
|
||||
cpdef separatorLine(self):
|
||||
'''
|
||||
Add horisontal separator line
|
||||
'''
|
||||
imguiSeparatorLine()
|
||||
|
||||
cpdef bint button(self, text, bint enabled, int x = -1, int y = -1,
|
||||
int w = -1, int h = -1):
|
||||
'''
|
||||
Button element
|
||||
'''
|
||||
cdef char *c_text
|
||||
|
||||
bytetext = unicode(text).encode('UTF-8','ignore')
|
||||
c_text = bytetext
|
||||
|
||||
return imguiButton(c_text, enabled, x, y, w, h)
|
||||
|
||||
cpdef bint item(self, text, bint enabled):
|
||||
'''
|
||||
Item element
|
||||
'''
|
||||
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):
|
||||
'''
|
||||
Check box element
|
||||
'''
|
||||
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, subtext, bint checked, bint enabled):
|
||||
'''
|
||||
Collapse element
|
||||
'''
|
||||
cdef char *c_text, *c_subtext
|
||||
|
||||
bytetext = unicode(text).encode('UTF-8','ignore')
|
||||
c_text = bytetext
|
||||
|
||||
bytetext = unicode(subtext).encode('UTF-8','ignore')
|
||||
c_subtext = bytetext
|
||||
|
||||
return imguiCollapse(c_text, c_subtext, checked, enabled)
|
||||
|
||||
cpdef label(self, text):
|
||||
'''
|
||||
Text label (left aligned)
|
||||
'''
|
||||
cdef char *c_text
|
||||
|
||||
bytetext = unicode(text).encode('UTF-8','ignore')
|
||||
c_text = bytetext
|
||||
|
||||
imguiLabel(c_text)
|
||||
|
||||
cpdef value(self, text):
|
||||
'''
|
||||
Text label (right aligned)
|
||||
'''
|
||||
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):
|
||||
'''
|
||||
Horisontal slider
|
||||
'''
|
||||
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):
|
||||
'''
|
||||
Draw text
|
||||
'''
|
||||
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):
|
||||
'''
|
||||
Draw single line
|
||||
'''
|
||||
imguiDrawLine(x0, y0, x1, y1, r, color.toInt())
|
||||
|
||||
|
||||
cpdef drawRoundedRect(self, float x, float y, float w, float h, float r, ColorRGBA color):
|
||||
'''
|
||||
Draw rounded rectangle
|
||||
'''
|
||||
imguiDrawRoundedRect(x, y, w, h, r, color.toInt())
|
||||
|
||||
cpdef drawRect(self, float x, float y, float w, float h, ColorRGBA color):
|
||||
'''
|
||||
Draw rectangle
|
||||
'''
|
||||
imguiDrawRect(x, y, w, h, color.toInt())
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of gltools - See LICENSE.txt
|
||||
#
|
||||
|
||||
# general imports
|
||||
IF UNAME_SYSNAME == "Windows":
|
||||
ctypedef unsigned int uintptr_t
|
||||
ELSE:
|
||||
from libc.stdint cimport uintptr_t
|
||||
|
||||
cdef extern from *:
|
||||
ctypedef char const_char "const char"
|
||||
|
||||
from libc.stdlib cimport malloc, free
|
||||
|
||||
from libc.math cimport fabs, copysign
|
||||
from libc.math cimport M_PI, sqrt, sin, cos, tan
|
||||
|
||||
cimport cpython.array
|
||||
|
||||
cdef inline double fmax(double a, double b):
|
||||
if a < b:
|
||||
return b
|
||||
return a
|
||||
|
||||
cdef inline double fmin(double a, double b):
|
||||
if a > b:
|
||||
return b
|
||||
return a
|
||||
|
||||
# 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')
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of gltools - See LICENSE.txt
|
||||
#
|
||||
from geotools cimport Point, Vector, Transform
|
||||
|
||||
cdef class ColorRGBA:
|
||||
cdef public unsigned char red
|
||||
cdef public unsigned char green
|
||||
cdef public unsigned char blue
|
||||
cdef public unsigned char alpha
|
||||
cpdef ColorRGBA copy(self, int red = ?, int green = ?, int blue = ?, alpha = ?)
|
||||
cpdef unsigned toInt(self)
|
||||
cpdef fromInt(self, unsigned int value)
|
||||
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)
|
||||
|
||||
cpdef AmbientLight(ColorRGBA col)
|
||||
|
||||
cdef class Light:
|
||||
cdef public Material material
|
||||
cdef public Point position
|
||||
cdef public bint directional
|
||||
cdef public Vector direction
|
||||
cdef readonly int index
|
||||
cpdef enable(self)
|
||||
cpdef disable(self)
|
||||
|
||||
cdef class TextureRect2D:
|
||||
cdef void *thisptr
|
||||
cpdef blit(self, float x = ?, float y = ?)
|
||||
cpdef copy(self, int mode = ?)
|
||||
|
||||
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 Terminate()
|
||||
cpdef double GetTime()
|
||||
cpdef SetTime(double time)
|
||||
cpdef SetGamma(Window window, float gamma)
|
||||
cpdef tuple GetDesktopSize(Window window)
|
||||
|
||||
cdef class Window:
|
||||
cdef void *thisptr
|
||||
cdef public bint running
|
||||
cdef object error
|
||||
cpdef setTitle(self, title)
|
||||
cpdef tuple getSize(self)
|
||||
cpdef setSize(self, int width, int height)
|
||||
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, double x, double y)
|
||||
cpdef onMouseButton(self, int button, int action)
|
||||
cpdef onKey(self, int key, int scancode, int action, int mods)
|
||||
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 bint beginArea(self, name, int x, int y, int w, int h)
|
||||
cpdef endArea(self)
|
||||
cpdef indent(self)
|
||||
cpdef unindent(self)
|
||||
cpdef separator(self)
|
||||
cpdef separatorLine(self)
|
||||
cpdef bint button(self, text, bint enabled, int x = ?, int y = ?,
|
||||
int w = ?, int h = ?)
|
||||
cpdef bint item(self, text, bint enabled)
|
||||
cpdef bint check(self, text, bint checked, bint enabled)
|
||||
cpdef bint collapse(self, text, 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)
|
||||
|
||||
cdef class Image:
|
||||
cdef unsigned char *_buffer
|
||||
cdef readonly int width
|
||||
cdef readonly int height
|
||||
cdef readonly int bytesPerPixel
|
||||
|
||||
# buffer interface
|
||||
cdef Py_ssize_t __shape[1]
|
||||
cdef Py_ssize_t __strides[1]
|
||||
cdef __cythonbufferdefaults__ = {"ndim": 1, "mode": "c"}
|
||||
|
||||
cpdef flipY(self)
|
||||
cpdef writePNG(self, filename, int stride = ?)
|
||||
|
||||
cpdef InitGLExt()
|
||||
cpdef int Check()
|
||||
cpdef BlendFunc(unsigned int sfactor, unsigned int dfactor)
|
||||
cpdef Clear(unsigned int mask)
|
||||
cpdef ClearColor(ColorRGBA col)
|
||||
cpdef ClearDepth(double depth)
|
||||
cpdef DepthFunc(int func)
|
||||
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 Hint(int target, int mode)
|
||||
cpdef PointSize(float width)
|
||||
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 PolygonOffset(float factor, float units)
|
||||
cpdef ColorRGBA ReadPixel(int x, int y)
|
||||
cpdef ReadPixels(int x, int y, Image img)
|
||||
cpdef Viewport(int x, int y, int width, int height)
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#cython: embedsignature=True
|
||||
#
|
||||
# This file is part of gltools - See LICENSE.txt
|
||||
#
|
||||
import sys
|
||||
|
||||
if sys.hexversion > 0x03000000:
|
||||
unicode = str
|
||||
|
||||
from geotools cimport *
|
||||
from GLToolsLib cimport *
|
||||
|
||||
class GLError(Exception):
|
||||
pass
|
||||
|
||||
include "Config.pxi"
|
||||
include "Utilities.pxi"
|
||||
include "Constants.pxi"
|
||||
include "GLFW.pxi"
|
||||
include "Color.pxi"
|
||||
include "Image.pxi"
|
||||
include "GL.pxi"
|
||||
include "ClientBuffer.pxi"
|
||||
include "ShaderProgram.pxi"
|
||||
include "Text.pxi"
|
||||
include "Texture.pxi"
|
||||
include "UI.pxi"
|
||||
341
gltools/test.py
|
|
@ -1,341 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import math
|
||||
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
|
||||
))
|
||||
|
||||
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.mouseCenter = geo.Point()
|
||||
self.uiScroll = 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.pongDiffuse(3)
|
||||
|
||||
# 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 <= 210:
|
||||
if y >= self.height - 260 and y <= self.height - 10:
|
||||
return True
|
||||
|
||||
if x >= 10 and x <= 210:
|
||||
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()
|
||||
|
||||
scroll = self.uiScroll
|
||||
if scroll:
|
||||
self.uiScroll = 0
|
||||
|
||||
ui.beginFrame(x,h - y,self.currentButton,scroll)
|
||||
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.beginArea("Fixed Area", 10, h - 260, 200, 250)
|
||||
ui.label('Message')
|
||||
if ui.button("OK", True, 5, 210, 40):
|
||||
print('Button OK pressed')
|
||||
|
||||
ui.endArea()
|
||||
|
||||
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)
|
||||
|
||||
update = False
|
||||
if not ui and self.currentButton == gl.MOUSE.LEFT:
|
||||
# rotate view
|
||||
dx = x - lastx
|
||||
dy = y - lasty
|
||||
cam.rotateDeltas(dx, dy, target = self.mouseCenter)
|
||||
update = True
|
||||
|
||||
elif not ui and self.currentButton == gl.MOUSE.RIGHT:
|
||||
# pan view
|
||||
cam.pan(lastx, lasty, x, y, target = self.mouseCenter)
|
||||
update = True
|
||||
|
||||
#print('onCursorPos ', x, y)
|
||||
self.lastPos = x, y
|
||||
|
||||
if ui or update:
|
||||
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}:
|
||||
# temporary rotation center to avoid exponential increase
|
||||
self.mouseCenter.set(self.cam.target)
|
||||
self.currentButton = button
|
||||
else:
|
||||
self.currentButton = -1
|
||||
|
||||
self.onRefresh()
|
||||
|
||||
def onKey(self, key, scancode, action, mods):
|
||||
#print('onKey ', key, action)
|
||||
if key == gl.KEY.ESCAPE:
|
||||
self.running = False
|
||||
elif key == gl.KEY.F:
|
||||
self.cam.zoomExtents(self.near, self.far)
|
||||
self.onRefresh()
|
||||
elif key == gl.KEY.F1:
|
||||
self.makeContextCurrent()
|
||||
img = gl.Image(self.width, self.height, gl.RGBA)
|
||||
gl.ReadPixels(0, 0, img)
|
||||
img.flipY()
|
||||
img.writePNG('screenshot01.png')
|
||||
|
||||
def onScroll(self, scx, scy):
|
||||
x, y = self.lastPos
|
||||
self.uiScroll = -int(scy)
|
||||
|
||||
if not self.insideUI(x, y):
|
||||
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()
|
||||
184
index.html
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
|
||||
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>Overview — gltools documentation</title>
|
||||
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '',
|
||||
COLLAPSE_INDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<link rel="top" title="gltools documentation" href="#" />
|
||||
<link rel="next" title="GLTools" href="content.html" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="content.html" title="GLTools"
|
||||
accesskey="N">next</a> |</li>
|
||||
<li><a href="#">gltools documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<div class="section" id="overview">
|
||||
<h1>Overview<a class="headerlink" href="#overview" title="Permalink to this headline">¶</a></h1>
|
||||
<p><strong>gltools</strong> is library for quickly creating OpenGL based
|
||||
application in Python/Cython with support for:</p>
|
||||
<blockquote>
|
||||
<div><ul class="simple">
|
||||
<li>Access to vertex buffers and GLSL shaders</li>
|
||||
<li>Access to truetype fonts</li>
|
||||
<li>Windows handling through GLFW</li>
|
||||
<li>Simple GUI controls</li>
|
||||
</ul>
|
||||
</div></blockquote>
|
||||
<p>OpenGL version 2.1 is targeted which should be available
|
||||
in most computers these days, even in a laptop’s integrated
|
||||
graphics.</p>
|
||||
<p>The license is GPL v2.</p>
|
||||
</div>
|
||||
<div class="section" id="building">
|
||||
<h1>Building<a class="headerlink" href="#building" title="Permalink to this headline">¶</a></h1>
|
||||
<blockquote>
|
||||
<div><ul class="simple">
|
||||
<li>Python 2.7/3.x and Cython 0.17 or later.</li>
|
||||
<li>The <a class="reference external" href="http://github.com/tenko/geotools">geotools</a> library.</li>
|
||||
<li><a class="reference external" href="http://github.com/elmindreda/glfw">GLFW</a> v3.0 (not released, must be build from GIT repo)</li>
|
||||
<li>OpenGL headers</li>
|
||||
</ul>
|
||||
</div></blockquote>
|
||||
<p>Prebuild installers are available on the <a class="reference external" href="http://pypi.python.org/pypi/gltools">pypi</a> site
|
||||
for the Windows platform.</p>
|
||||
<p>For Linux build scripts are available for ArchLinux in the <a class="reference external" href="https://aur.archlinux.org/packages/?O=0&K=gltools">AUR</a>
|
||||
repository. These could be adapted to other Linux distros.</p>
|
||||
<p>Note that currently I can not find a way to install the required
|
||||
Cython ‘pxd’ files with distutils and this file has to be copied
|
||||
manually.</p>
|
||||
</div>
|
||||
<div class="section" id="history">
|
||||
<h1>History<a class="headerlink" href="#history" title="Permalink to this headline">¶</a></h1>
|
||||
<blockquote>
|
||||
<div><ul class="simple">
|
||||
<li>v0.1.1 : Added missing files and fix building against GLFW3 trunk.</li>
|
||||
</ul>
|
||||
</div></blockquote>
|
||||
</div>
|
||||
<div class="section" id="api-docs">
|
||||
<h1>API Docs<a class="headerlink" href="#api-docs" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="toctree-wrapper compound">
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="content.html">GLTools</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="content.html#colorrgba">ColorRGBA</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="content.html#material">Material</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="content.html#light">Light</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="content.html#image">Image</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="content.html#texturerect2d">TextureRect2D</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="content.html#clientbuffer">ClientBuffer</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="content.html#shaderprogram">ShaderProgram</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="content.html#glfw">GLFW</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="content.html#window">Window</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="content.html#ui">UI</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="content.html#glfw-constants">GLFW Constants</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="content.html#opengl">OpenGL</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="content.html#opengl-constants">OpenGL Constants</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="indices-and-tables">
|
||||
<h1>Indices and tables<a class="headerlink" href="#indices-and-tables" title="Permalink to this headline">¶</a></h1>
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="genindex.html"><em>Index</em></a></li>
|
||||
<li><a class="reference internal" href="py-modindex.html"><em>Module Index</em></a></li>
|
||||
<li><a class="reference internal" href="search.html"><em>Search Page</em></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h3><a href="#">Table Of Contents</a></h3>
|
||||
<ul>
|
||||
<li><a class="reference internal" href="#">Overview</a></li>
|
||||
<li><a class="reference internal" href="#building">Building</a></li>
|
||||
<li><a class="reference internal" href="#history">History</a></li>
|
||||
<li><a class="reference internal" href="#api-docs">API Docs</a><ul>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#indices-and-tables">Indices and tables</a></li>
|
||||
</ul>
|
||||
|
||||
<h4>Next topic</h4>
|
||||
<p class="topless"><a href="content.html"
|
||||
title="next chapter">GLTools</a></p>
|
||||
<h3>This Page</h3>
|
||||
<ul class="this-page-menu">
|
||||
<li><a href="_sources/index.txt"
|
||||
rel="nofollow">Show Source</a></li>
|
||||
</ul>
|
||||
<div id="searchbox" style="display: none">
|
||||
<h3>Quick search</h3>
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" />
|
||||
<input type="submit" value="Go" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
<p class="searchtip" style="font-size: 90%">
|
||||
Enter search terms or a module, class or function name.
|
||||
</p>
|
||||
</div>
|
||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="content.html" title="GLTools"
|
||||
>next</a> |</li>
|
||||
<li><a href="#">gltools documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2012, Runar Tenfjord.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
objects.inv
Normal file
99
search.html
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
|
||||
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
|
||||
<title>Search — gltools documentation</title>
|
||||
|
||||
<link rel="stylesheet" href="_static/default.css" type="text/css" />
|
||||
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
|
||||
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '',
|
||||
VERSION: '',
|
||||
COLLAPSE_INDEX: false,
|
||||
FILE_SUFFIX: '.html',
|
||||
HAS_SOURCE: true
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="_static/jquery.js"></script>
|
||||
<script type="text/javascript" src="_static/underscore.js"></script>
|
||||
<script type="text/javascript" src="_static/doctools.js"></script>
|
||||
<script type="text/javascript" src="_static/searchtools.js"></script>
|
||||
<link rel="top" title="gltools documentation" href="index.html" />
|
||||
<script type="text/javascript">
|
||||
jQuery(function() { Search.loadIndex("searchindex.js"); });
|
||||
</script>
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li><a href="index.html">gltools documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body">
|
||||
|
||||
<h1 id="search-documentation">Search</h1>
|
||||
<div id="fallback" class="admonition warning">
|
||||
<script type="text/javascript">$('#fallback').hide();</script>
|
||||
<p>
|
||||
Please activate JavaScript to enable the search
|
||||
functionality.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
From here you can search these documents. Enter your search
|
||||
words into the box below and click "search". Note that the search
|
||||
function will automatically search for all of the words. Pages
|
||||
containing fewer words won't appear in the result list.
|
||||
</p>
|
||||
<form action="" method="get">
|
||||
<input type="text" name="q" value="" />
|
||||
<input type="submit" value="search" />
|
||||
<span id="search-progress" style="padding-left: 10px"></span>
|
||||
</form>
|
||||
|
||||
<div id="search-results">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li><a href="index.html">gltools documentation</a> »</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© Copyright 2012, Runar Tenfjord.
|
||||
Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
1
searchindex.js
Normal file
135
setup_build.py
|
|
@ -1,135 +0,0 @@
|
|||
#!/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
|
||||
|
||||
try:
|
||||
from Cython.Distutils import build_ext
|
||||
except ImportError:
|
||||
print >>sys.stderr, "Cython is required to build geotools"
|
||||
sys.exit(1)
|
||||
|
||||
#sys.argv.append('build_ext')
|
||||
#sys.argv.extend(['sdist','--formats=gztar,zip'])
|
||||
#sys.argv.append('bdist_wininst')
|
||||
|
||||
# create config file
|
||||
sys.dont_write_bytecode = True
|
||||
import version
|
||||
|
||||
CONFIG = 'gltools/@src/Config.pxi'
|
||||
if not os.path.exists(CONFIG) and 'sdist' not in sys.argv:
|
||||
with open(CONFIG, 'w') as fh:
|
||||
fh.write("__version__ = '%s'\n" % version.STRING)
|
||||
args = version.MAJOR, version.MINOR, version.BUILD
|
||||
fh.write("__version_info__ = (%d,%d,%d)\n" % args)
|
||||
|
||||
# platform specific settings
|
||||
OBJECTS, LIBS, LINK_ARGS, COMPILE_ARGS = [],[],[],[]
|
||||
if sys.platform == 'win32':
|
||||
LIBS.append('OPENGL32')
|
||||
LIBS.append('glfw3')
|
||||
LIBS.append('user32')
|
||||
LIBS.append('gdi32')
|
||||
OBJECTS.append('glfw3.lib')
|
||||
|
||||
elif sys.platform == 'msys':
|
||||
LIBS.append('OPENGL32')
|
||||
LIBS.append('glfw3dll')
|
||||
COMPILE_ARGS.append("-fpermissive")
|
||||
|
||||
elif sys.platform == 'darwin':
|
||||
LINK_ARGS.extend(['-framework', 'OpenGL', '-arch', 'x86_64'])
|
||||
COMPILE_ARGS.extend(['-arch', 'x86_64'])
|
||||
LIBS.append('glfw')
|
||||
else:
|
||||
LIBS.append('GL')
|
||||
LIBS.append('glfw')
|
||||
COMPILE_ARGS.append("-fpermissive")
|
||||
|
||||
classifiers = '''\
|
||||
Development Status :: 4 - Beta
|
||||
Environment :: MacOS X
|
||||
Environment :: Win32 (MS Windows)
|
||||
Environment :: X11 Applications
|
||||
Intended Audience :: Science/Research
|
||||
License :: OSI Approved :: GNU General Public License v2 (GPLv2)
|
||||
Operating System :: OS Independent
|
||||
Programming Language :: Cython
|
||||
Topic :: Scientific/Engineering :: Visualization
|
||||
'''
|
||||
|
||||
SRC = [
|
||||
"gltools/gltools.pyx",
|
||||
"gltools/@src/GLTools.cpp",
|
||||
"gltools/@contrib/fontstash.c",
|
||||
"gltools/@contrib/stb_image_write.c",
|
||||
"gltools/@contrib/imgui.cpp",
|
||||
"gltools/@contrib/imguiRenderGL.cpp"
|
||||
]
|
||||
|
||||
DEP = \
|
||||
["gltools/gltools.pxd",] + \
|
||||
glob.glob("gltools/@src/*.pxi") + \
|
||||
glob.glob("gltools/@src/*.cpp") + \
|
||||
glob.glob("gltools/@include/*.pxd") + \
|
||||
glob.glob("gltools/@include/*.h")
|
||||
|
||||
try:
|
||||
setup(
|
||||
name = 'gltools',
|
||||
version = version.STRING,
|
||||
description = 'Library to create OpenGL based applications',
|
||||
long_description = \
|
||||
'''**gltools** is library for quickly creating OpenGL based
|
||||
application in Python/Cython with support for:
|
||||
|
||||
* Access to vertex buffers and GLSL shaders
|
||||
* Access to truetype fonts
|
||||
* Windows handling through GLFW
|
||||
* Saving framebuffer content to PNG file.
|
||||
* Simple GUI controls
|
||||
|
||||
**History**
|
||||
|
||||
* v0.1.1 : Added missing files in source distribution
|
||||
''',
|
||||
classifiers = [value for value in classifiers.split("\n") if value],
|
||||
author='Runar Tenfjord',
|
||||
author_email = 'runar.tenfjord@gmail.com',
|
||||
license = 'GPLv2',
|
||||
download_url='http://pypi.python.org/pypi/gltools/',
|
||||
url = 'http://github.com/tenko/gltools',
|
||||
platforms = ['any'],
|
||||
requires = ['geotools'],
|
||||
|
||||
ext_modules=[
|
||||
Extension("gltools",
|
||||
sources = SRC,
|
||||
depends = DEP,
|
||||
include_dirs = ['gltools/@include','gltools/@src',
|
||||
'gltools/@contrib'],
|
||||
library_dirs = ['gltools'],
|
||||
libraries = LIBS,
|
||||
extra_link_args = LINK_ARGS,
|
||||
extra_compile_args = COMPILE_ARGS,
|
||||
extra_objects = OBJECTS,
|
||||
language="c++"
|
||||
),
|
||||
],
|
||||
|
||||
cmdclass = {'build_ext': build_ext},
|
||||
packages=[''],
|
||||
package_dir={'': 'gltools'},
|
||||
package_data={'': ['*.pxd']},
|
||||
)
|
||||
except:
|
||||
print('Traceback\n:%s\n' % str(sys.exc_info()[-2]))
|
||||
sys.exit(1)
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
#!/usr/bin/python2
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# This file is part of gltools - See LICENSE.txt
|
||||
#
|
||||
import sys
|
||||
import os
|
||||
|
||||
from distutils.core import setup
|
||||
from sphinx.setup_command import BuildDoc
|
||||
cmdclass = {'build_sphinx': BuildDoc}
|
||||
|
||||
name = 'gltools'
|
||||
version = '0.1'
|
||||
release = '0.1.0'
|
||||
|
||||
try:
|
||||
setup(
|
||||
name = name,
|
||||
author = 'Runar Tenfjord',
|
||||
version = release,
|
||||
cmdclass = cmdclass,
|
||||
command_options = {
|
||||
'build_sphinx': {
|
||||
'builder': ('setup_docs.py', 'html'),
|
||||
}
|
||||
},
|
||||
|
||||
)
|
||||
except:
|
||||
print('Traceback\n:%s\n' % str(sys.exc_info()[-2]))
|
||||
sys.exit(1)
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
MAJOR = 0
|
||||
MINOR = 2
|
||||
BUILD = 1
|
||||
STRING = "%d.%d.%d" % (MAJOR,MINOR,BUILD)
|
||||