├── .hgignore ├── DejaVuSans.ttf ├── LICENSE ├── LICENSE-DejaVuSans.ttf.txt ├── LICENSE-blender_icons.svg.txt ├── README.md ├── blender_icons.svg ├── blender_icons16.png ├── blendish.c ├── blendish.h ├── example.cpp ├── oui.h └── premake4.lua /.hgignore: -------------------------------------------------------------------------------- 1 | syntax: glob 2 | 3 | .sconsign.dblite 4 | .settings 5 | *.orig 6 | .project 7 | .pydevproject 8 | 9 | syntax: regexp 10 | 11 | ^build 12 | ^nanovg 13 | -------------------------------------------------------------------------------- /DejaVuSans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/oui-blendish/2fc6405883f8451944ed080547d073c8f9f31898/DejaVuSans.ttf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Blendish - Blender 2.5 UI based theming functions for NanoVG 2 | 3 | Copyright (c) 2014 Leonard Ritter 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE-DejaVuSans.ttf.txt: -------------------------------------------------------------------------------- 1 | Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. 2 | Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below) 3 | 4 | Bitstream Vera Fonts Copyright 5 | ------------------------------ 6 | 7 | Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is 8 | a trademark of Bitstream, Inc. 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of the fonts accompanying this license ("Fonts") and associated 12 | documentation files (the "Font Software"), to reproduce and distribute the 13 | Font Software, including without limitation the rights to use, copy, merge, 14 | publish, distribute, and/or sell copies of the Font Software, and to permit 15 | persons to whom the Font Software is furnished to do so, subject to the 16 | following conditions: 17 | 18 | The above copyright and trademark notices and this permission notice shall 19 | be included in all copies of one or more of the Font Software typefaces. 20 | 21 | The Font Software may be modified, altered, or added to, and in particular 22 | the designs of glyphs or characters in the Fonts may be modified and 23 | additional glyphs or characters may be added to the Fonts, only if the fonts 24 | are renamed to names not containing either the words "Bitstream" or the word 25 | "Vera". 26 | 27 | This License becomes null and void to the extent applicable to Fonts or Font 28 | Software that has been modified and is distributed under the "Bitstream 29 | Vera" names. 30 | 31 | The Font Software may be sold as part of a larger software package but no 32 | copy of one or more of the Font Software typefaces may be sold by itself. 33 | 34 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 35 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, 36 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, 37 | TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME 38 | FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING 39 | ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, 40 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 41 | THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE 42 | FONT SOFTWARE. 43 | 44 | Except as contained in this notice, the names of Gnome, the Gnome 45 | Foundation, and Bitstream Inc., shall not be used in advertising or 46 | otherwise to promote the sale, use or other dealings in this Font Software 47 | without prior written authorization from the Gnome Foundation or Bitstream 48 | Inc., respectively. For further information, contact: fonts at gnome dot 49 | org. 50 | 51 | Arev Fonts Copyright 52 | ------------------------------ 53 | 54 | Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. 55 | 56 | Permission is hereby granted, free of charge, to any person obtaining 57 | a copy of the fonts accompanying this license ("Fonts") and 58 | associated documentation files (the "Font Software"), to reproduce 59 | and distribute the modifications to the Bitstream Vera Font Software, 60 | including without limitation the rights to use, copy, merge, publish, 61 | distribute, and/or sell copies of the Font Software, and to permit 62 | persons to whom the Font Software is furnished to do so, subject to 63 | the following conditions: 64 | 65 | The above copyright and trademark notices and this permission notice 66 | shall be included in all copies of one or more of the Font Software 67 | typefaces. 68 | 69 | The Font Software may be modified, altered, or added to, and in 70 | particular the designs of glyphs or characters in the Fonts may be 71 | modified and additional glyphs or characters may be added to the 72 | Fonts, only if the fonts are renamed to names not containing either 73 | the words "Tavmjong Bah" or the word "Arev". 74 | 75 | This License becomes null and void to the extent applicable to Fonts 76 | or Font Software that has been modified and is distributed under the 77 | "Tavmjong Bah Arev" names. 78 | 79 | The Font Software may be sold as part of a larger software package but 80 | no copy of one or more of the Font Software typefaces may be sold by 81 | itself. 82 | 83 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 84 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 85 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 86 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL 87 | TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 88 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 89 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 90 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 91 | OTHER DEALINGS IN THE FONT SOFTWARE. 92 | 93 | Except as contained in this notice, the name of Tavmjong Bah shall not 94 | be used in advertising or otherwise to promote the sale, use or other 95 | dealings in this Font Software without prior written authorization 96 | from Tavmjong Bah. For further information, contact: tavmjong @ free 97 | . fr. 98 | 99 | $Id: LICENSE 2133 2007-11-28 02:46:28Z lechimp $ 100 | -------------------------------------------------------------------------------- /LICENSE-blender_icons.svg.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. 341 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **Blendish** is a small collection of drawing functions for [NanoVG](https://github.com/memononen/nanovg) in a single C header file, designed to replicate the look of the Blender 2.5+ User Interface. You can use these functions to theme your UI library. Some metric constants for faithful reproduction are also included. 2 | 3 | To render correctly, Blendish needs both [icon sheet](https://svn.blender.org/svnroot/bf-blender/trunk/blender/release/datafiles/blender_icons16.png) and [font](https://svn.blender.org/svnroot/bf-blender/trunk/blender/release/datafiles/fonts/) from the 4 | Blender repository. See source code for more information. 5 | 6 | ![oui_logo.png](https://bitbucket.org/repo/zAzpBG/images/4211571908-oui_logo.png) 7 | 8 | The repository also hosts **OUI** (short for "Open UI", spoken like the french "oui" for "yes"), a platform agnostic single-header C library for layouting GUI elements and 9 | handling related user input. Together with a set of widget drawing and logic routines it can be used to build complex user interfaces. 10 | 11 | Here's a screenshot of Blendish styling a set of layouted OUI items (also contained in example.cpp). 12 | 13 | ![oui_frozen.png](https://bitbucket.org/repo/zAzpBG/images/1655961333-oui_frozen.png) 14 | 15 | Here's a shot of all available Blendish theming functions: 16 | 17 | ![blendish2.png](https://bitbucket.org/repo/zAzpBG/images/1457969701-blendish2.png) 18 | -------------------------------------------------------------------------------- /blender_icons16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VCVRack/oui-blendish/2fc6405883f8451944ed080547d073c8f9f31898/blender_icons16.png -------------------------------------------------------------------------------- /blendish.c: -------------------------------------------------------------------------------- 1 | /* 2 | Blendish - Blender 2.5 UI based theming functions for NanoVG 3 | 4 | Copyright (c) 2014 Leonard Ritter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | */ 24 | 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #ifdef _MSC_VER 31 | #pragma warning (disable: 4996) // Switch off security warnings 32 | #pragma warning (disable: 4100) // Switch off unreferenced formal parameter warnings 33 | #pragma warning (disable: 4244) 34 | #pragma warning (disable: 4305) 35 | #ifdef __cplusplus 36 | #define BND_INLINE inline 37 | #else 38 | #define BND_INLINE 39 | #endif 40 | 41 | #include 42 | 43 | static float bnd_fminf ( float a, float b ) 44 | { 45 | return _isnan(a) ? b : ( _isnan(b) ? a : ((a < b) ? a : b)); 46 | } 47 | 48 | static float bnd_fmaxf ( float a, float b ) 49 | { 50 | return _isnan(a) ? b : ( _isnan(b) ? a : ((a > b) ? a : b)); 51 | } 52 | 53 | static double bnd_fmin ( double a, double b ) 54 | { 55 | return _isnan(a) ? b : ( _isnan(b) ? a : ((a < b) ? a : b)); 56 | } 57 | 58 | static double bnd_fmax ( double a, double b ) 59 | { 60 | return _isnan(a) ? b : ( _isnan(b) ? a : ((a > b) ? a : b)); 61 | } 62 | 63 | #else 64 | #define BND_INLINE inline 65 | #define bnd_fminf(a, b) fminf(a, b) 66 | #define bnd_fmaxf(a, b) fmaxf(a, b) 67 | #define bnd_fmin(a, b) fmin(a, b) 68 | #define bnd_fmax(a, b) fmax(a, b) 69 | #endif 70 | 71 | //////////////////////////////////////////////////////////////////////////////// 72 | 73 | BND_INLINE float bnd_clamp(float v, float mn, float mx) { 74 | return (v > mx)?mx:(v < mn)?mn:v; 75 | } 76 | 77 | //////////////////////////////////////////////////////////////////////////////// 78 | 79 | // the initial theme 80 | static BNDtheme bnd_theme = { 81 | // backgroundColor 82 | {{{ 0.447, 0.447, 0.447, 1.0 }}}, 83 | // regularTheme 84 | { 85 | {{{ 0.098,0.098,0.098,1 }}}, // color_outline 86 | {{{ 0.098,0.098,0.098,1 }}}, // color_item 87 | {{{ 0.6,0.6,0.6,1 }}}, // color_inner 88 | {{{ 0.392,0.392,0.392,1 }}}, // color_inner_selected 89 | BND_COLOR_TEXT, // color_text 90 | BND_COLOR_TEXT_SELECTED, // color_text_selected 91 | 0, // shade_top 92 | 0, // shade_down 93 | }, 94 | // toolTheme 95 | { 96 | {{{ 0.098,0.098,0.098,1 }}}, // color_outline 97 | {{{ 0.098,0.098,0.098,1 }}}, // color_item 98 | {{{ 0.6,0.6,0.6,1 }}}, // color_inner 99 | {{{ 0.392,0.392,0.392,1 }}}, // color_inner_selected 100 | BND_COLOR_TEXT, // color_text 101 | BND_COLOR_TEXT_SELECTED, // color_text_selected 102 | 15, // shade_top 103 | -15, // shade_down 104 | }, 105 | // radioTheme 106 | { 107 | {{{ 0,0,0,1 }}}, // color_outline 108 | {{{ 1,1,1,1 }}}, // color_item 109 | {{{ 0.275,0.275,0.275,1 }}}, // color_inner 110 | {{{ 0.337,0.502,0.761,1 }}}, // color_inner_selected 111 | BND_COLOR_TEXT_SELECTED, // color_text 112 | BND_COLOR_TEXT, // color_text_selected 113 | 15, // shade_top 114 | -15, // shade_down 115 | }, 116 | // textFieldTheme 117 | { 118 | {{{ 0.098,0.098,0.098,1 }}}, // color_outline 119 | {{{ 0.353, 0.353, 0.353,1 }}}, // color_item 120 | {{{ 0.6, 0.6, 0.6,1 }}}, // color_inner 121 | {{{ 0.6, 0.6, 0.6,1 }}}, // color_inner_selected 122 | BND_COLOR_TEXT, // color_text 123 | BND_COLOR_TEXT_SELECTED, // color_text_selected 124 | 0, // shade_top 125 | 25, // shade_down 126 | }, 127 | // optionTheme 128 | { 129 | {{{ 0,0,0,1 }}}, // color_outline 130 | {{{ 1,1,1,1 }}}, // color_item 131 | {{{ 0.275,0.275,0.275,1 }}}, // color_inner 132 | {{{ 0.275,0.275,0.275,1 }}}, // color_inner_selected 133 | BND_COLOR_TEXT, // color_text 134 | BND_COLOR_TEXT_SELECTED, // color_text_selected 135 | 15, // shade_top 136 | -15, // shade_down 137 | }, 138 | // choiceTheme 139 | { 140 | {{{ 0,0,0,1 }}}, // color_outline 141 | {{{ 1,1,1,1 }}}, // color_item 142 | {{{ 0.275,0.275,0.275,1 }}}, // color_inner 143 | {{{ 0.275,0.275,0.275,1 }}}, // color_inner_selected 144 | BND_COLOR_TEXT_SELECTED, // color_text 145 | {{{ 0.8,0.8,0.8,1 }}}, // color_text_selected 146 | 15, // shade_top 147 | -15, // shade_down 148 | }, 149 | // numberFieldTheme 150 | { 151 | {{{ 0.098,0.098,0.098,1 }}}, // color_outline 152 | {{{ 0.353, 0.353, 0.353,1 }}}, // color_item 153 | {{{ 0.706, 0.706, 0.706,1 }}}, // color_inner 154 | {{{ 0.6, 0.6, 0.6,1 }}}, // color_inner_selected 155 | BND_COLOR_TEXT, // color_text 156 | BND_COLOR_TEXT_SELECTED, // color_text_selected 157 | -20, // shade_top 158 | 0, // shade_down 159 | }, 160 | // sliderTheme 161 | { 162 | {{{ 0.098,0.098,0.098,1 }}}, // color_outline 163 | {{{ 0.502,0.502,0.502,1 }}}, // color_item 164 | {{{ 0.706, 0.706, 0.706,1 }}}, // color_inner 165 | {{{ 0.6, 0.6, 0.6,1 }}}, // color_inner_selected 166 | BND_COLOR_TEXT, // color_text 167 | BND_COLOR_TEXT_SELECTED, // color_text_selected 168 | -20, // shade_top 169 | 0, // shade_down 170 | }, 171 | // scrollBarTheme 172 | { 173 | {{{ 0.196,0.196,0.196,1 }}}, // color_outline 174 | {{{ 0.502,0.502,0.502,1 }}}, // color_item 175 | {{{ 0.314, 0.314, 0.314,0.706 }}}, // color_inner 176 | {{{ 0.392, 0.392, 0.392,0.706 }}}, // color_inner_selected 177 | BND_COLOR_TEXT, // color_text 178 | BND_COLOR_TEXT_SELECTED, // color_text_selected 179 | 5, // shade_top 180 | -5, // shade_down 181 | }, 182 | // tooltipTheme 183 | { 184 | {{{ 0,0,0,1 }}}, // color_outline 185 | {{{ 0.392,0.392,0.392,1 }}}, // color_item 186 | {{{ 0.098, 0.098, 0.098, 0.902 }}}, // color_inner 187 | {{{ 0.176, 0.176, 0.176, 0.902 }}}, // color_inner_selected 188 | {{{ 0.627, 0.627, 0.627, 1 }}}, // color_text 189 | BND_COLOR_TEXT_SELECTED, // color_text_selected 190 | 0, // shade_top 191 | 0, // shade_down 192 | }, 193 | // menuTheme 194 | { 195 | {{{ 0,0,0,1 }}}, // color_outline 196 | {{{ 0.392,0.392,0.392,1 }}}, // color_item 197 | {{{ 0.098, 0.098, 0.098, 0.902 }}}, // color_inner 198 | {{{ 0.176, 0.176, 0.176, 0.902 }}}, // color_inner_selected 199 | {{{ 0.627, 0.627, 0.627, 1 }}}, // color_text 200 | BND_COLOR_TEXT_SELECTED, // color_text_selected 201 | 0, // shade_top 202 | 0, // shade_down 203 | }, 204 | // menuItemTheme 205 | { 206 | {{{ 0,0,0,1 }}}, // color_outline 207 | {{{ 0.675,0.675,0.675,0.502 }}}, // color_item 208 | {{{ 0,0,0,0 }}}, // color_inner 209 | {{{ 0.337,0.502,0.761,1 }}}, // color_inner_selected 210 | BND_COLOR_TEXT_SELECTED, // color_text 211 | BND_COLOR_TEXT, // color_text_selected 212 | 38, // shade_top 213 | 0, // shade_down 214 | }, 215 | // nodeTheme 216 | { 217 | {{{ 0.945,0.345,0,1 }}}, // nodeSelectedColor 218 | {{{ 0,0,0,1 }}}, // wiresColor 219 | {{{ 0.498,0.439,0.439,1 }}}, // textSelectedColor 220 | {{{ 1,0.667,0.251,1 }}}, // activeNodeColor 221 | {{{ 1,1,1,1 }}}, // wireSelectColor 222 | {{{ 0.608,0.608,0.608,0.627 }}}, // nodeBackdropColor 223 | 5, // noodleCurving 224 | }, 225 | }; 226 | 227 | //////////////////////////////////////////////////////////////////////////////// 228 | 229 | void bndSetTheme(BNDtheme theme) { 230 | bnd_theme = theme; 231 | } 232 | 233 | const BNDtheme *bndGetTheme() { 234 | return &bnd_theme; 235 | } 236 | 237 | // the handle to the image containing the icon sheet 238 | static int bnd_icon_image = -1; 239 | 240 | void bndSetIconImage(int image) { 241 | bnd_icon_image = image; 242 | } 243 | 244 | // the handle to the UI font 245 | static int bnd_font = -1; 246 | 247 | void bndSetFont(int font) { 248 | bnd_font = font; 249 | } 250 | 251 | //////////////////////////////////////////////////////////////////////////////// 252 | 253 | void bndLabel(NVGcontext *ctx, 254 | float x, float y, float w, float h, int iconid, const char *label) { 255 | bndIconLabelValue(ctx,x,y,w,h,iconid, 256 | bnd_theme.regularTheme.textColor, BND_LEFT, 257 | BND_LABEL_FONT_SIZE, label, NULL); 258 | } 259 | 260 | void bndToolButton(NVGcontext *ctx, 261 | float x, float y, float w, float h, int flags, BNDwidgetState state, 262 | int iconid, const char *label) { 263 | float cr[4]; 264 | NVGcolor shade_top, shade_down; 265 | 266 | bndSelectCorners(cr, BND_TOOL_RADIUS, flags); 267 | bndBevelInset(ctx,x,y,w,h,cr[2],cr[3]); 268 | bndInnerColors(&shade_top, &shade_down, &bnd_theme.toolTheme, state, 1); 269 | bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down); 270 | bndOutlineBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], 271 | bndTransparent(bnd_theme.toolTheme.outlineColor)); 272 | bndIconLabelValue(ctx,x,y,w,h,iconid, 273 | bndTextColor(&bnd_theme.toolTheme, state), BND_CENTER, 274 | BND_LABEL_FONT_SIZE, label, NULL); 275 | } 276 | 277 | void bndRadioButton(NVGcontext *ctx, 278 | float x, float y, float w, float h, int flags, BNDwidgetState state, 279 | int iconid, const char *label) { 280 | float cr[4]; 281 | NVGcolor shade_top, shade_down; 282 | 283 | bndSelectCorners(cr, BND_OPTION_RADIUS, flags); 284 | bndBevelInset(ctx,x,y,w,h,cr[2],cr[3]); 285 | bndInnerColors(&shade_top, &shade_down, &bnd_theme.radioTheme, state, 1); 286 | bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down); 287 | bndOutlineBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], 288 | bndTransparent(bnd_theme.radioTheme.outlineColor)); 289 | bndIconLabelValue(ctx,x,y,w,h,iconid, 290 | bndTextColor(&bnd_theme.radioTheme, state), BND_CENTER, 291 | BND_LABEL_FONT_SIZE, label, NULL); 292 | } 293 | 294 | int bndTextFieldTextPosition(NVGcontext *ctx, float x, float y, float w, float h, 295 | int iconid, const char *text, int px, int py) { 296 | return bndIconLabelTextPosition(ctx, x, y, w, h, 297 | iconid, BND_LABEL_FONT_SIZE, text, px, py); 298 | } 299 | 300 | void bndTextField(NVGcontext *ctx, 301 | float x, float y, float w, float h, int flags, BNDwidgetState state, 302 | int iconid, const char *text, int cbegin, int cend) { 303 | float cr[4]; 304 | NVGcolor shade_top, shade_down; 305 | 306 | bndSelectCorners(cr, BND_TEXT_RADIUS, flags); 307 | bndBevelInset(ctx,x,y,w,h,cr[2],cr[3]); 308 | bndInnerColors(&shade_top, &shade_down, &bnd_theme.textFieldTheme, state, 0); 309 | bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down); 310 | bndOutlineBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], 311 | bndTransparent(bnd_theme.textFieldTheme.outlineColor)); 312 | if (state != BND_ACTIVE) { 313 | cend = -1; 314 | } 315 | bndIconLabelCaret(ctx,x,y,w,h,iconid, 316 | bndTextColor(&bnd_theme.textFieldTheme, state), BND_LABEL_FONT_SIZE, 317 | text, bnd_theme.textFieldTheme.itemColor, cbegin, cend); 318 | } 319 | 320 | void bndOptionButton(NVGcontext *ctx, 321 | float x, float y, float w, float h, BNDwidgetState state, 322 | const char *label) { 323 | float ox, oy; 324 | NVGcolor shade_top, shade_down; 325 | 326 | ox = x; 327 | oy = y+h-BND_OPTION_HEIGHT-3; 328 | 329 | bndBevelInset(ctx,ox,oy, 330 | BND_OPTION_WIDTH,BND_OPTION_HEIGHT, 331 | BND_OPTION_RADIUS,BND_OPTION_RADIUS); 332 | bndInnerColors(&shade_top, &shade_down, &bnd_theme.optionTheme, state, 1); 333 | bndInnerBox(ctx,ox,oy, 334 | BND_OPTION_WIDTH,BND_OPTION_HEIGHT, 335 | BND_OPTION_RADIUS,BND_OPTION_RADIUS,BND_OPTION_RADIUS,BND_OPTION_RADIUS, 336 | shade_top, shade_down); 337 | bndOutlineBox(ctx,ox,oy, 338 | BND_OPTION_WIDTH,BND_OPTION_HEIGHT, 339 | BND_OPTION_RADIUS,BND_OPTION_RADIUS,BND_OPTION_RADIUS,BND_OPTION_RADIUS, 340 | bndTransparent(bnd_theme.optionTheme.outlineColor)); 341 | if (state == BND_ACTIVE) { 342 | bndCheck(ctx,ox,oy, bndTransparent(bnd_theme.optionTheme.itemColor)); 343 | } 344 | bndIconLabelValue(ctx,x+12,y,w-12,h,-1, 345 | bndTextColor(&bnd_theme.optionTheme, state), BND_LEFT, 346 | BND_LABEL_FONT_SIZE, label, NULL); 347 | } 348 | 349 | void bndChoiceButton(NVGcontext *ctx, 350 | float x, float y, float w, float h, int flags, BNDwidgetState state, 351 | int iconid, const char *label) { 352 | float cr[4]; 353 | NVGcolor shade_top, shade_down; 354 | 355 | bndSelectCorners(cr, BND_OPTION_RADIUS, flags); 356 | bndBevelInset(ctx,x,y,w,h,cr[2],cr[3]); 357 | bndInnerColors(&shade_top, &shade_down, &bnd_theme.choiceTheme, state, 1); 358 | bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down); 359 | bndOutlineBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], 360 | bndTransparent(bnd_theme.choiceTheme.outlineColor)); 361 | bndIconLabelValue(ctx,x,y,w,h,iconid, 362 | bndTextColor(&bnd_theme.choiceTheme, state), BND_LEFT, 363 | BND_LABEL_FONT_SIZE, label, NULL); 364 | bndUpDownArrow(ctx,x+w-10,y+10,5, 365 | bndTransparent(bnd_theme.choiceTheme.itemColor)); 366 | } 367 | 368 | void bndColorButton(NVGcontext *ctx, 369 | float x, float y, float w, float h, int flags, NVGcolor color) { 370 | float cr[4]; 371 | bndSelectCorners(cr, BND_TOOL_RADIUS, flags); 372 | bndBevelInset(ctx,x,y,w,h,cr[2],cr[3]); 373 | bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], color, color); 374 | bndOutlineBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], 375 | bndTransparent(bnd_theme.toolTheme.outlineColor)); 376 | } 377 | 378 | void bndNumberField(NVGcontext *ctx, 379 | float x, float y, float w, float h, int flags, BNDwidgetState state, 380 | const char *label, const char *value) { 381 | float cr[4]; 382 | NVGcolor shade_top, shade_down; 383 | 384 | bndSelectCorners(cr, BND_NUMBER_RADIUS, flags); 385 | bndBevelInset(ctx,x,y,w,h,cr[2],cr[3]); 386 | bndInnerColors(&shade_top, &shade_down, &bnd_theme.numberFieldTheme, state, 0); 387 | bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down); 388 | bndOutlineBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], 389 | bndTransparent(bnd_theme.numberFieldTheme.outlineColor)); 390 | bndIconLabelValue(ctx,x,y,w,h,-1, 391 | bndTextColor(&bnd_theme.numberFieldTheme, state), BND_CENTER, 392 | BND_LABEL_FONT_SIZE, label, value); 393 | bndArrow(ctx,x+8,y+10,-BND_NUMBER_ARROW_SIZE, 394 | bndTransparent(bnd_theme.numberFieldTheme.itemColor)); 395 | bndArrow(ctx,x+w-8,y+10,BND_NUMBER_ARROW_SIZE, 396 | bndTransparent(bnd_theme.numberFieldTheme.itemColor)); 397 | } 398 | 399 | void bndSlider(NVGcontext *ctx, 400 | float x, float y, float w, float h, int flags, BNDwidgetState state, 401 | float progress, const char *label, const char *value) { 402 | float cr[4]; 403 | NVGcolor shade_top, shade_down; 404 | 405 | bndSelectCorners(cr, BND_NUMBER_RADIUS, flags); 406 | bndBevelInset(ctx,x,y,w,h,cr[2],cr[3]); 407 | bndInnerColors(&shade_top, &shade_down, &bnd_theme.sliderTheme, state, 0); 408 | bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down); 409 | 410 | if (state == BND_ACTIVE) { 411 | shade_top = bndOffsetColor( 412 | bnd_theme.sliderTheme.itemColor, bnd_theme.sliderTheme.shadeTop); 413 | shade_down = bndOffsetColor( 414 | bnd_theme.sliderTheme.itemColor, bnd_theme.sliderTheme.shadeDown); 415 | } else { 416 | shade_top = bndOffsetColor( 417 | bnd_theme.sliderTheme.itemColor, bnd_theme.sliderTheme.shadeDown); 418 | shade_down = bndOffsetColor( 419 | bnd_theme.sliderTheme.itemColor, bnd_theme.sliderTheme.shadeTop); 420 | } 421 | nvgScissor(ctx,x,y,8+(w-8)*bnd_clamp(progress,0,1),h); 422 | bndInnerBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down); 423 | nvgResetScissor(ctx); 424 | 425 | bndOutlineBox(ctx,x,y,w,h,cr[0],cr[1],cr[2],cr[3], 426 | bndTransparent(bnd_theme.sliderTheme.outlineColor)); 427 | bndIconLabelValue(ctx,x,y,w,h,-1, 428 | bndTextColor(&bnd_theme.sliderTheme, state), BND_CENTER, 429 | BND_LABEL_FONT_SIZE, label, value); 430 | } 431 | 432 | void bndScrollBar(NVGcontext *ctx, 433 | float x, float y, float w, float h, BNDwidgetState state, 434 | float offset, float size) { 435 | 436 | bndBevelInset(ctx,x,y,w,h, 437 | BND_SCROLLBAR_RADIUS, BND_SCROLLBAR_RADIUS); 438 | bndInnerBox(ctx,x,y,w,h, 439 | BND_SCROLLBAR_RADIUS,BND_SCROLLBAR_RADIUS, 440 | BND_SCROLLBAR_RADIUS,BND_SCROLLBAR_RADIUS, 441 | bndOffsetColor( 442 | bnd_theme.scrollBarTheme.innerColor, 3*bnd_theme.scrollBarTheme.shadeDown), 443 | bndOffsetColor( 444 | bnd_theme.scrollBarTheme.innerColor, 3*bnd_theme.scrollBarTheme.shadeTop)); 445 | bndOutlineBox(ctx,x,y,w,h, 446 | BND_SCROLLBAR_RADIUS,BND_SCROLLBAR_RADIUS, 447 | BND_SCROLLBAR_RADIUS,BND_SCROLLBAR_RADIUS, 448 | bndTransparent(bnd_theme.scrollBarTheme.outlineColor)); 449 | 450 | NVGcolor itemColor = bndOffsetColor( 451 | bnd_theme.scrollBarTheme.itemColor, 452 | (state == BND_ACTIVE)?BND_SCROLLBAR_ACTIVE_SHADE:0); 453 | 454 | bndScrollHandleRect(&x,&y,&w,&h,offset,size); 455 | 456 | bndInnerBox(ctx,x,y,w,h, 457 | BND_SCROLLBAR_RADIUS,BND_SCROLLBAR_RADIUS, 458 | BND_SCROLLBAR_RADIUS,BND_SCROLLBAR_RADIUS, 459 | bndOffsetColor( 460 | itemColor, 3*bnd_theme.scrollBarTheme.shadeTop), 461 | bndOffsetColor( 462 | itemColor, 3*bnd_theme.scrollBarTheme.shadeDown)); 463 | bndOutlineBox(ctx,x,y,w,h, 464 | BND_SCROLLBAR_RADIUS,BND_SCROLLBAR_RADIUS, 465 | BND_SCROLLBAR_RADIUS,BND_SCROLLBAR_RADIUS, 466 | bndTransparent(bnd_theme.scrollBarTheme.outlineColor)); 467 | } 468 | 469 | void bndMenuBackground(NVGcontext *ctx, 470 | float x, float y, float w, float h, int flags) { 471 | float cr[4]; 472 | NVGcolor shade_top, shade_down; 473 | 474 | bndSelectCorners(cr, BND_MENU_RADIUS, flags); 475 | bndInnerColors(&shade_top, &shade_down, &bnd_theme.menuTheme, 476 | BND_DEFAULT, 0); 477 | bndInnerBox(ctx,x,y,w,h+1,cr[0],cr[1],cr[2],cr[3], shade_top, shade_down); 478 | bndOutlineBox(ctx,x,y,w,h+1,cr[0],cr[1],cr[2],cr[3], 479 | bndTransparent(bnd_theme.menuTheme.outlineColor)); 480 | bndDropShadow(ctx,x,y,w,h,BND_MENU_RADIUS, 481 | BND_SHADOW_FEATHER,BND_SHADOW_ALPHA); 482 | } 483 | 484 | void bndTooltipBackground(NVGcontext *ctx, float x, float y, float w, float h) { 485 | NVGcolor shade_top, shade_down; 486 | 487 | bndInnerColors(&shade_top, &shade_down, &bnd_theme.tooltipTheme, 488 | BND_DEFAULT, 0); 489 | bndInnerBox(ctx,x,y,w,h+1, 490 | BND_MENU_RADIUS,BND_MENU_RADIUS,BND_MENU_RADIUS,BND_MENU_RADIUS, 491 | shade_top, shade_down); 492 | bndOutlineBox(ctx,x,y,w,h+1, 493 | BND_MENU_RADIUS,BND_MENU_RADIUS,BND_MENU_RADIUS,BND_MENU_RADIUS, 494 | bndTransparent(bnd_theme.tooltipTheme.outlineColor)); 495 | bndDropShadow(ctx,x,y,w,h,BND_MENU_RADIUS, 496 | BND_SHADOW_FEATHER,BND_SHADOW_ALPHA); 497 | } 498 | 499 | void bndMenuLabel(NVGcontext *ctx, 500 | float x, float y, float w, float h, int iconid, const char *label) { 501 | bndIconLabelValue(ctx,x,y,w,h,iconid, 502 | bnd_theme.menuTheme.textColor, BND_LEFT, 503 | BND_LABEL_FONT_SIZE, label, NULL); 504 | } 505 | 506 | void bndMenuItem(NVGcontext *ctx, 507 | float x, float y, float w, float h, BNDwidgetState state, 508 | int iconid, const char *label) { 509 | if (state != BND_DEFAULT) { 510 | bndInnerBox(ctx,x,y,w,h,0,0,0,0, 511 | bndOffsetColor(bnd_theme.menuItemTheme.innerSelectedColor, 512 | bnd_theme.menuItemTheme.shadeTop), 513 | bndOffsetColor(bnd_theme.menuItemTheme.innerSelectedColor, 514 | bnd_theme.menuItemTheme.shadeDown)); 515 | state = BND_ACTIVE; 516 | } 517 | bndIconLabelValue(ctx,x,y,w,h,iconid, 518 | bndTextColor(&bnd_theme.menuItemTheme, state), BND_LEFT, 519 | BND_LABEL_FONT_SIZE, label, NULL); 520 | } 521 | 522 | void bndNodePort(NVGcontext *ctx, float x, float y, BNDwidgetState state, 523 | NVGcolor color) { 524 | nvgBeginPath(ctx); 525 | nvgCircle(ctx, x, y, BND_NODE_PORT_RADIUS); 526 | nvgStrokeColor(ctx,bnd_theme.nodeTheme.wiresColor); 527 | nvgStrokeWidth(ctx,1.0f); 528 | nvgStroke(ctx); 529 | nvgFillColor(ctx,(state != BND_DEFAULT)? 530 | bndOffsetColor(color, BND_HOVER_SHADE):color); 531 | nvgFill(ctx); 532 | } 533 | 534 | void bndColoredNodeWire(NVGcontext *ctx, float x0, float y0, float x1, float y1, 535 | NVGcolor color0, NVGcolor color1) { 536 | float length = bnd_fmaxf(fabsf(x1 - x0),fabsf(y1 - y0)); 537 | float delta = length*(float)bnd_theme.nodeTheme.noodleCurving/10.0f; 538 | 539 | nvgBeginPath(ctx); 540 | nvgMoveTo(ctx, x0, y0); 541 | nvgBezierTo(ctx, 542 | x0 + delta, y0, 543 | x1 - delta, y1, 544 | x1, y1); 545 | NVGcolor colorw = bnd_theme.nodeTheme.wiresColor; 546 | colorw.a = (color0.a= 0) { 735 | w += BND_ICON_SHEET_RES; 736 | } 737 | if (label && (bnd_font >= 0)) { 738 | nvgFontFaceId(ctx, bnd_font); 739 | nvgFontSize(ctx, BND_LABEL_FONT_SIZE); 740 | float bounds[4]; 741 | nvgTextBoxBounds(ctx, 1, 1, INFINITY, label, NULL, bounds); 742 | w += bounds[2]; 743 | } 744 | return w; 745 | } 746 | 747 | float bndLabelHeight(NVGcontext *ctx, int iconid, const char *label, float width) { 748 | int h = BND_WIDGET_HEIGHT; 749 | width -= BND_TEXT_RADIUS*2; 750 | if (iconid >= 0) { 751 | width -= BND_ICON_SHEET_RES; 752 | } 753 | if (label && (bnd_font >= 0)) { 754 | nvgFontFaceId(ctx, bnd_font); 755 | nvgFontSize(ctx, BND_LABEL_FONT_SIZE); 756 | float bounds[4]; 757 | nvgTextBoxBounds(ctx, 1, 1, width, label, NULL, bounds); 758 | int bh = (int)(bounds[3] - bounds[1]) + BND_TEXT_PAD_DOWN; 759 | if (bh > h) 760 | h = bh; 761 | } 762 | return h; 763 | } 764 | 765 | //////////////////////////////////////////////////////////////////////////////// 766 | 767 | void bndRoundedBox(NVGcontext *ctx, float x, float y, float w, float h, 768 | float cr0, float cr1, float cr2, float cr3) { 769 | float d; 770 | 771 | w = bnd_fmaxf(0, w); 772 | h = bnd_fmaxf(0, h); 773 | d = bnd_fminf(w, h); 774 | 775 | nvgMoveTo(ctx, x,y+h*0.5f); 776 | nvgArcTo(ctx, x,y, x+w,y, bnd_fminf(cr0, d/2)); 777 | nvgArcTo(ctx, x+w,y, x+w,y+h, bnd_fminf(cr1, d/2)); 778 | nvgArcTo(ctx, x+w,y+h, x,y+h, bnd_fminf(cr2, d/2)); 779 | nvgArcTo(ctx, x,y+h, x,y, bnd_fminf(cr3, d/2)); 780 | nvgClosePath(ctx); 781 | } 782 | 783 | NVGcolor bndTransparent(NVGcolor color) { 784 | color.a *= BND_TRANSPARENT_ALPHA; 785 | return color; 786 | } 787 | 788 | NVGcolor bndOffsetColor(NVGcolor color, int delta) { 789 | float offset = (float)delta / 255.0f; 790 | return delta?( 791 | nvgRGBAf( 792 | bnd_clamp(color.r+offset,0,1), 793 | bnd_clamp(color.g+offset,0,1), 794 | bnd_clamp(color.b+offset,0,1), 795 | color.a) 796 | ):color; 797 | } 798 | 799 | void bndBevel(NVGcontext *ctx, float x, float y, float w, float h) { 800 | // Disable bevel 801 | return; 802 | nvgStrokeWidth(ctx, 1); 803 | 804 | x += 0.5f; 805 | y += 0.5f; 806 | w -= 1; 807 | h -= 1; 808 | 809 | nvgBeginPath(ctx); 810 | nvgMoveTo(ctx, x, y+h); 811 | nvgLineTo(ctx, x+w, y+h); 812 | nvgLineTo(ctx, x+w, y); 813 | nvgStrokeColor(ctx, bndTransparent( 814 | bndOffsetColor(bnd_theme.backgroundColor, -BND_BEVEL_SHADE))); 815 | nvgStroke(ctx); 816 | 817 | nvgBeginPath(ctx); 818 | nvgMoveTo(ctx, x, y+h); 819 | nvgLineTo(ctx, x, y); 820 | nvgLineTo(ctx, x+w, y); 821 | nvgStrokeColor(ctx, bndTransparent( 822 | bndOffsetColor(bnd_theme.backgroundColor, BND_BEVEL_SHADE))); 823 | nvgStroke(ctx); 824 | } 825 | 826 | void bndBevelInset(NVGcontext *ctx, float x, float y, float w, float h, 827 | float cr2, float cr3) { 828 | // Disable bevel 829 | return; 830 | float d; 831 | 832 | y -= 0.5f; 833 | d = bnd_fminf(w, h); 834 | cr2 = bnd_fminf(cr2, d/2); 835 | cr3 = bnd_fminf(cr3, d/2); 836 | 837 | nvgBeginPath(ctx); 838 | nvgMoveTo(ctx, x+w,y+h-cr2); 839 | nvgArcTo(ctx, x+w,y+h, x,y+h, cr2); 840 | nvgArcTo(ctx, x,y+h, x,y, cr3); 841 | 842 | NVGcolor bevelColor = bndOffsetColor(bnd_theme.backgroundColor, 843 | BND_INSET_BEVEL_SHADE); 844 | 845 | nvgStrokeWidth(ctx, 1); 846 | nvgStrokePaint(ctx, 847 | nvgLinearGradient(ctx, 848 | x,y+h-bnd_fmaxf(cr2,cr3)-1, 849 | x,y+h-1, 850 | nvgRGBAf(bevelColor.r, bevelColor.g, bevelColor.b, 0), 851 | bevelColor)); 852 | nvgStroke(ctx); 853 | } 854 | 855 | void bndBackground(NVGcontext *ctx, float x, float y, float w, float h) { 856 | nvgBeginPath(ctx); 857 | nvgRect(ctx, x, y, w, h); 858 | nvgFillColor(ctx, bnd_theme.backgroundColor); 859 | nvgFill(ctx); 860 | } 861 | 862 | void bndIcon(NVGcontext *ctx, float x, float y, int iconid) { 863 | int ix, iy, u, v; 864 | if (bnd_icon_image < 0) return; // no icons loaded 865 | 866 | ix = iconid & 0xff; 867 | iy = (iconid>>8) & 0xff; 868 | u = BND_ICON_SHEET_OFFSET_X + ix*BND_ICON_SHEET_GRID; 869 | v = BND_ICON_SHEET_OFFSET_Y + iy*BND_ICON_SHEET_GRID; 870 | 871 | nvgBeginPath(ctx); 872 | nvgRect(ctx,x,y,BND_ICON_SHEET_RES,BND_ICON_SHEET_RES); 873 | nvgFillPaint(ctx, 874 | nvgImagePattern(ctx,x-u,y-v, 875 | BND_ICON_SHEET_WIDTH, 876 | BND_ICON_SHEET_HEIGHT, 877 | 0,bnd_icon_image,1)); 878 | nvgFill(ctx); 879 | } 880 | 881 | void bndDropShadow(NVGcontext *ctx, float x, float y, float w, float h, 882 | float r, float feather, float alpha) { 883 | 884 | nvgBeginPath(ctx); 885 | y += feather; 886 | h -= feather; 887 | 888 | nvgMoveTo(ctx, x-feather, y-feather); 889 | nvgLineTo(ctx, x, y-feather); 890 | nvgLineTo(ctx, x, y+h-feather); 891 | nvgArcTo(ctx, x,y+h,x+r,y+h,r); 892 | nvgArcTo(ctx, x+w,y+h,x+w,y+h-r,r); 893 | nvgLineTo(ctx, x+w, y-feather); 894 | nvgLineTo(ctx, x+w+feather, y-feather); 895 | nvgLineTo(ctx, x+w+feather, y+h+feather); 896 | nvgLineTo(ctx, x-feather, y+h+feather); 897 | nvgClosePath(ctx); 898 | 899 | nvgFillPaint(ctx, nvgBoxGradient(ctx, 900 | x - feather*0.5f,y - feather*0.5f, 901 | w + feather,h+feather, 902 | r+feather*0.5f, 903 | feather, 904 | nvgRGBAf(0,0,0,alpha*alpha), 905 | nvgRGBAf(0,0,0,0))); 906 | nvgFill(ctx); 907 | } 908 | 909 | void bndInnerBox(NVGcontext *ctx, float x, float y, float w, float h, 910 | float cr0, float cr1, float cr2, float cr3, 911 | NVGcolor shade_top, NVGcolor shade_down) { 912 | nvgBeginPath(ctx); 913 | bndRoundedBox(ctx,x+1,y+1,w-2,h-3,bnd_fmaxf(0,cr0-1), 914 | bnd_fmaxf(0,cr1-1),bnd_fmaxf(0,cr2-1),bnd_fmaxf(0,cr3-1)); 915 | nvgFillPaint(ctx,((h-2)>w)? 916 | nvgLinearGradient(ctx,x,y,x+w,y,shade_top,shade_down): 917 | nvgLinearGradient(ctx,x,y,x,y+h,shade_top,shade_down)); 918 | nvgFill(ctx); 919 | } 920 | 921 | void bndOutlineBox(NVGcontext *ctx, float x, float y, float w, float h, 922 | float cr0, float cr1, float cr2, float cr3, NVGcolor color) { 923 | nvgBeginPath(ctx); 924 | bndRoundedBox(ctx,x+0.5f,y+0.5f,w-1,h-2,cr0,cr1,cr2,cr3); 925 | nvgStrokeColor(ctx,color); 926 | nvgStrokeWidth(ctx,1); 927 | nvgStroke(ctx); 928 | } 929 | 930 | void bndSelectCorners(float *radiuses, float r, int flags) { 931 | radiuses[0] = (flags & BND_CORNER_TOP_LEFT)?0:r; 932 | radiuses[1] = (flags & BND_CORNER_TOP_RIGHT)?0:r; 933 | radiuses[2] = (flags & BND_CORNER_DOWN_RIGHT)?0:r; 934 | radiuses[3] = (flags & BND_CORNER_DOWN_LEFT)?0:r; 935 | } 936 | 937 | void bndInnerColors( 938 | NVGcolor *shade_top, NVGcolor *shade_down, 939 | const BNDwidgetTheme *theme, BNDwidgetState state, int flipActive) { 940 | 941 | switch(state) { 942 | default: 943 | case BND_DEFAULT: { 944 | *shade_top = bndOffsetColor(theme->innerColor, theme->shadeTop); 945 | *shade_down = bndOffsetColor(theme->innerColor, theme->shadeDown); 946 | } break; 947 | case BND_HOVER: { 948 | NVGcolor color = bndOffsetColor(theme->innerColor, BND_HOVER_SHADE); 949 | *shade_top = bndOffsetColor(color, theme->shadeTop); 950 | *shade_down = bndOffsetColor(color, theme->shadeDown); 951 | } break; 952 | case BND_ACTIVE: { 953 | *shade_top = bndOffsetColor(theme->innerSelectedColor, 954 | flipActive?theme->shadeDown:theme->shadeTop); 955 | *shade_down = bndOffsetColor(theme->innerSelectedColor, 956 | flipActive?theme->shadeTop:theme->shadeDown); 957 | } break; 958 | } 959 | } 960 | 961 | NVGcolor bndTextColor(const BNDwidgetTheme *theme, BNDwidgetState state) { 962 | return (state == BND_ACTIVE)?theme->textSelectedColor:theme->textColor; 963 | } 964 | 965 | void bndIconLabelValue(NVGcontext *ctx, float x, float y, float w, float h, 966 | int iconid, NVGcolor color, int align, float fontsize, const char *label, 967 | const char *value) { 968 | float pleft = BND_PAD_LEFT; 969 | if (label) { 970 | if (iconid >= 0) { 971 | bndIcon(ctx,x+4,y+2,iconid); 972 | pleft += BND_ICON_SHEET_RES; 973 | } 974 | 975 | if (bnd_font < 0) return; 976 | nvgFontFaceId(ctx, bnd_font); 977 | nvgFontSize(ctx, fontsize); 978 | nvgBeginPath(ctx); 979 | nvgFillColor(ctx, color); 980 | if (value) { 981 | float label_width = nvgTextBounds(ctx, 1, 1, label, NULL, NULL); 982 | float sep_width = nvgTextBounds(ctx, 1, 1, 983 | BND_LABEL_SEPARATOR, NULL, NULL); 984 | 985 | nvgTextAlign(ctx, NVG_ALIGN_LEFT|NVG_ALIGN_BASELINE); 986 | x += pleft; 987 | if (align == BND_CENTER) { 988 | float width = label_width + sep_width 989 | + nvgTextBounds(ctx, 1, 1, value, NULL, NULL); 990 | x += ((w-BND_PAD_RIGHT-pleft)-width)*0.5f; 991 | } 992 | y += BND_WIDGET_HEIGHT-BND_TEXT_PAD_DOWN; 993 | nvgText(ctx, x, y, label, NULL); 994 | x += label_width; 995 | nvgText(ctx, x, y, BND_LABEL_SEPARATOR, NULL); 996 | x += sep_width; 997 | nvgText(ctx, x, y, value, NULL); 998 | } else { 999 | nvgTextAlign(ctx, 1000 | (align==BND_LEFT)?(NVG_ALIGN_LEFT|NVG_ALIGN_BASELINE): 1001 | (NVG_ALIGN_CENTER|NVG_ALIGN_BASELINE)); 1002 | nvgTextBox(ctx,x+pleft,y+BND_WIDGET_HEIGHT-BND_TEXT_PAD_DOWN, 1003 | w-BND_PAD_RIGHT-pleft,label, NULL); 1004 | } 1005 | } else if (iconid >= 0) { 1006 | bndIcon(ctx,x+2,y+2,iconid); 1007 | } 1008 | } 1009 | 1010 | void bndNodeIconLabel(NVGcontext *ctx, float x, float y, float w, float h, 1011 | int iconid, NVGcolor color, NVGcolor shadowColor, 1012 | int align, float fontsize, const char *label) { 1013 | if (label && (bnd_font >= 0)) { 1014 | nvgFontFaceId(ctx, bnd_font); 1015 | nvgFontSize(ctx, fontsize); 1016 | nvgBeginPath(ctx); 1017 | nvgTextAlign(ctx, NVG_ALIGN_LEFT|NVG_ALIGN_BASELINE); 1018 | nvgFillColor(ctx, shadowColor); 1019 | nvgFontBlur(ctx, BND_NODE_TITLE_FEATHER); 1020 | nvgTextBox(ctx,x+1,y+h+3-BND_TEXT_PAD_DOWN, 1021 | w,label, NULL); 1022 | nvgFillColor(ctx, color); 1023 | nvgFontBlur(ctx, 0); 1024 | nvgTextBox(ctx,x,y+h+2-BND_TEXT_PAD_DOWN, 1025 | w,label, NULL); 1026 | } 1027 | if (iconid >= 0) { 1028 | bndIcon(ctx,x+w-BND_ICON_SHEET_RES,y+3,iconid); 1029 | } 1030 | } 1031 | 1032 | int bndIconLabelTextPosition(NVGcontext *ctx, float x, float y, float w, float h, 1033 | int iconid, float fontsize, const char *label, int px, int py) { 1034 | float bounds[4]; 1035 | float pleft = BND_TEXT_RADIUS; 1036 | if (!label) return -1; 1037 | if (iconid >= 0) 1038 | pleft += BND_ICON_SHEET_RES; 1039 | 1040 | if (bnd_font < 0) return -1; 1041 | 1042 | x += pleft; 1043 | y += BND_WIDGET_HEIGHT - BND_TEXT_PAD_DOWN; 1044 | 1045 | nvgFontFaceId(ctx, bnd_font); 1046 | nvgFontSize(ctx, fontsize); 1047 | nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_BASELINE); 1048 | 1049 | w -= BND_TEXT_RADIUS + pleft; 1050 | 1051 | float asc, desc, lh; 1052 | static NVGtextRow rows[BND_MAX_ROWS]; 1053 | int nrows = nvgTextBreakLines( 1054 | ctx, label, NULL, w, rows, BND_MAX_ROWS); 1055 | if (nrows == 0) return 0; 1056 | nvgTextBoxBounds(ctx, x, y, w, label, NULL, bounds); 1057 | nvgTextMetrics(ctx, &asc, &desc, &lh); 1058 | 1059 | // calculate vertical position 1060 | int row = bnd_clamp((int)((float)(py - bounds[1]) / lh), 0, nrows - 1); 1061 | // search horizontal position 1062 | static NVGglyphPosition glyphs[BND_MAX_GLYPHS]; 1063 | int nglyphs = nvgTextGlyphPositions( 1064 | ctx, x, y, rows[row].start, rows[row].end + 1, glyphs, BND_MAX_GLYPHS); 1065 | int col, p = 0; 1066 | for (col = 0; col < nglyphs && glyphs[col].x < px; ++col) 1067 | p = glyphs[col].str - label; 1068 | // see if we should move one character further 1069 | if (col > 0 && col < nglyphs && glyphs[col].x - px < px - glyphs[col - 1].x) 1070 | p = glyphs[col].str - label; 1071 | return p; 1072 | } 1073 | 1074 | static void bndCaretPosition(NVGcontext *ctx, float x, float y, 1075 | float desc, float lineHeight, const char *caret, NVGtextRow *rows,int nrows, 1076 | int *cr, float *cx, float *cy) { 1077 | static NVGglyphPosition glyphs[BND_MAX_GLYPHS]; 1078 | int r,nglyphs; 1079 | for (r=0; r < nrows-1 && rows[r].end < caret; ++r); 1080 | *cr = r; 1081 | *cx = x; 1082 | *cy = y-lineHeight-desc + r*lineHeight; 1083 | if (nrows == 0) return; 1084 | *cx = rows[r].minx; 1085 | nglyphs = nvgTextGlyphPositions( 1086 | ctx, x, y, rows[r].start, rows[r].end+1, glyphs, BND_MAX_GLYPHS); 1087 | for (int i=0; i < nglyphs; ++i) { 1088 | *cx=glyphs[i].x; 1089 | if (glyphs[i].str == caret) break; 1090 | } 1091 | } 1092 | 1093 | void bndIconLabelCaret(NVGcontext *ctx, float x, float y, float w, float h, 1094 | int iconid, NVGcolor color, float fontsize, const char *label, 1095 | NVGcolor caretcolor, int cbegin, int cend) { 1096 | float pleft = BND_TEXT_RADIUS; 1097 | if (!label) return; 1098 | if (iconid >= 0) { 1099 | bndIcon(ctx,x+4,y+2,iconid); 1100 | pleft += BND_ICON_SHEET_RES; 1101 | } 1102 | 1103 | if (bnd_font < 0) return; 1104 | 1105 | x+=pleft; 1106 | y+=BND_WIDGET_HEIGHT-BND_TEXT_PAD_DOWN; 1107 | 1108 | nvgFontFaceId(ctx, bnd_font); 1109 | nvgFontSize(ctx, fontsize); 1110 | nvgTextAlign(ctx, NVG_ALIGN_LEFT|NVG_ALIGN_BASELINE); 1111 | 1112 | w -= BND_TEXT_RADIUS+pleft; 1113 | 1114 | if (cend >= cbegin) { 1115 | int c0r,c1r; 1116 | float c0x,c0y,c1x,c1y; 1117 | float desc,lh; 1118 | static NVGtextRow rows[BND_MAX_ROWS]; 1119 | int nrows = nvgTextBreakLines( 1120 | ctx, label, label+cend+1, w, rows, BND_MAX_ROWS); 1121 | nvgTextMetrics(ctx, NULL, &desc, &lh); 1122 | 1123 | bndCaretPosition(ctx, x, y, desc, lh, label+cbegin, 1124 | rows, nrows, &c0r, &c0x, &c0y); 1125 | bndCaretPosition(ctx, x, y, desc, lh, label+cend, 1126 | rows, nrows, &c1r, &c1x, &c1y); 1127 | 1128 | nvgBeginPath(ctx); 1129 | if (cbegin == cend) { 1130 | nvgFillColor(ctx, nvgRGBf(0.337,0.502,0.761)); 1131 | nvgRect(ctx, c0x-1, c0y, 2, lh+1); 1132 | } else { 1133 | nvgFillColor(ctx, caretcolor); 1134 | if (c0r == c1r) { 1135 | nvgRect(ctx, c0x-1, c0y, c1x-c0x+1, lh+1); 1136 | } else { 1137 | int blk=c1r-c0r-1; 1138 | nvgRect(ctx, c0x-1, c0y, x+w-c0x+1, lh+1); 1139 | nvgRect(ctx, x, c1y, c1x-x+1, lh+1); 1140 | 1141 | if (blk) 1142 | nvgRect(ctx, x, c0y+lh, w, blk*lh+1); 1143 | } 1144 | } 1145 | nvgFill(ctx); 1146 | } 1147 | 1148 | nvgBeginPath(ctx); 1149 | nvgFillColor(ctx, color); 1150 | nvgTextBox(ctx,x,y,w,label, NULL); 1151 | } 1152 | 1153 | void bndCheck(NVGcontext *ctx, float ox, float oy, NVGcolor color) { 1154 | nvgBeginPath(ctx); 1155 | nvgStrokeWidth(ctx,2); 1156 | nvgStrokeColor(ctx,color); 1157 | nvgLineCap(ctx,NVG_BUTT); 1158 | nvgLineJoin(ctx,NVG_MITER); 1159 | nvgMoveTo(ctx,ox+4,oy+5); 1160 | nvgLineTo(ctx,ox+7,oy+8); 1161 | nvgLineTo(ctx,ox+14,oy+1); 1162 | nvgStroke(ctx); 1163 | } 1164 | 1165 | void bndArrow(NVGcontext *ctx, float x, float y, float s, NVGcolor color) { 1166 | nvgBeginPath(ctx); 1167 | nvgMoveTo(ctx,x,y); 1168 | nvgLineTo(ctx,x-s,y+s); 1169 | nvgLineTo(ctx,x-s,y-s); 1170 | nvgClosePath(ctx); 1171 | nvgFillColor(ctx,color); 1172 | nvgFill(ctx); 1173 | } 1174 | 1175 | void bndUpDownArrow(NVGcontext *ctx, float x, float y, float s, NVGcolor color) { 1176 | float w; 1177 | 1178 | nvgBeginPath(ctx); 1179 | w = 1.1f*s; 1180 | nvgMoveTo(ctx,x,y-1); 1181 | nvgLineTo(ctx,x+0.5*w,y-s-1); 1182 | nvgLineTo(ctx,x+w,y-1); 1183 | nvgClosePath(ctx); 1184 | nvgMoveTo(ctx,x,y+1); 1185 | nvgLineTo(ctx,x+0.5*w,y+s+1); 1186 | nvgLineTo(ctx,x+w,y+1); 1187 | nvgClosePath(ctx); 1188 | nvgFillColor(ctx,color); 1189 | nvgFill(ctx); 1190 | } 1191 | 1192 | void bndNodeArrowDown(NVGcontext *ctx, float x, float y, float s, NVGcolor color) { 1193 | float w; 1194 | nvgBeginPath(ctx); 1195 | w = 1.0f*s; 1196 | nvgMoveTo(ctx,x,y); 1197 | nvgLineTo(ctx,x+0.5*w,y-s); 1198 | nvgLineTo(ctx,x-0.5*w,y-s); 1199 | nvgClosePath(ctx); 1200 | nvgFillColor(ctx,color); 1201 | nvgFill(ctx); 1202 | } 1203 | 1204 | void bndScrollHandleRect(float *x, float *y, float *w, float *h, 1205 | float offset, float size) { 1206 | size = bnd_clamp(size,0,1); 1207 | offset = bnd_clamp(offset,0,1); 1208 | if ((*h) > (*w)) { 1209 | float hs = bnd_fmaxf(size*(*h), (*w)+1); 1210 | *y = (*y) + ((*h)-hs)*offset; 1211 | *h = hs; 1212 | } else { 1213 | float ws = bnd_fmaxf(size*(*w), (*h)-1); 1214 | *x = (*x) + ((*w)-ws)*offset; 1215 | *w = ws; 1216 | } 1217 | } 1218 | 1219 | NVGcolor bndNodeWireColor(const BNDnodeTheme *theme, BNDwidgetState state) { 1220 | switch(state) { 1221 | default: 1222 | case BND_DEFAULT: return nvgRGBf(0.5f,0.5f,0.5f); 1223 | case BND_HOVER: return theme->wireSelectColor; 1224 | case BND_ACTIVE: return theme->activeNodeColor; 1225 | } 1226 | } 1227 | -------------------------------------------------------------------------------- /blendish.h: -------------------------------------------------------------------------------- 1 | /* 2 | Blendish - Blender 2.5 UI based theming functions for NanoVG 3 | 4 | Copyright (c) 2014 Leonard Ritter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | */ 24 | 25 | #ifndef BLENDISH_H 26 | #define BLENDISH_H 27 | 28 | #include 29 | #include 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | /* 36 | 37 | Revision 6 (2014-09-21) 38 | 39 | Summary 40 | ------- 41 | 42 | Blendish is a small collection of drawing functions for NanoVG, designed to 43 | replicate the look of the Blender 2.5+ User Interface. You can use these 44 | functions to theme your UI library. Several metric constants for faithful 45 | reproduction are also included. 46 | 47 | Blendish supports the original Blender icon sheet; As the licensing of Blenders 48 | icons is unclear, they are not included in Blendishes repository, but a SVG 49 | template, "icons_template.svg" is provided, which you can use to build your own 50 | icon sheet. 51 | 52 | To use icons, you must first load the icon sheet using one of the 53 | nvgCreateImage*() functions and then pass the image handle to bndSetIconImage(); 54 | otherwise, no icons will be drawn. See bndSetIconImage() for more information. 55 | 56 | Blendish will not render text until a suitable UI font has been passed to 57 | bndSetFont() has been called. See bndSetFont() for more information. 58 | 59 | 60 | Drawbacks 61 | --------- 62 | 63 | There is no support for varying dpi resolutions yet. The library is hardcoded 64 | to the equivalent of 72 dpi in the Blender system settings. 65 | 66 | Support for label truncation is missing. Text rendering breaks when widgets are 67 | too short to contain their labels. 68 | 69 | Usage 70 | ----- 71 | 72 | To use this header file in implementation mode, define BLENDISH_IMPLEMENTATION 73 | before including blendish.h, otherwise the file will be in header-only mode. 74 | 75 | */ 76 | 77 | // you can override this from the outside to pick 78 | // the export level you need 79 | #ifndef BND_EXPORT 80 | #define BND_EXPORT 81 | #endif 82 | 83 | // if that typedef is provided elsewhere, you may define 84 | // BLENDISH_NO_NVG_TYPEDEFS before including the header. 85 | #ifndef BLENDISH_NO_NVG_TYPEDEFS 86 | typedef struct NVGcontext NVGcontext; 87 | typedef struct NVGcolor NVGcolor; 88 | typedef struct NVGglyphPosition NVGglyphPosition; 89 | #endif 90 | 91 | // describes the theme used to draw a single widget or widget box; 92 | // these values correspond to the same values that can be retrieved from 93 | // the Theme panel in the Blender preferences 94 | typedef struct BNDwidgetTheme { 95 | // color of widget box outline 96 | NVGcolor outlineColor; 97 | // color of widget item (meaning changes depending on class) 98 | NVGcolor itemColor; 99 | // fill color of widget box 100 | NVGcolor innerColor; 101 | // fill color of widget box when active 102 | NVGcolor innerSelectedColor; 103 | // color of text label 104 | NVGcolor textColor; 105 | // color of text label when active 106 | NVGcolor textSelectedColor; 107 | // delta modifier for upper part of gradient (-100 to 100) 108 | int shadeTop; 109 | // delta modifier for lower part of gradient (-100 to 100) 110 | int shadeDown; 111 | } BNDwidgetTheme; 112 | 113 | // describes the theme used to draw nodes 114 | typedef struct BNDnodeTheme { 115 | // inner color of selected node (and downarrow) 116 | NVGcolor nodeSelectedColor; 117 | // outline of wires 118 | NVGcolor wiresColor; 119 | // color of text label when active 120 | NVGcolor textSelectedColor; 121 | 122 | // inner color of active node (and dragged wire) 123 | NVGcolor activeNodeColor; 124 | // color of selected wire 125 | NVGcolor wireSelectColor; 126 | // color of background of node 127 | NVGcolor nodeBackdropColor; 128 | 129 | // how much a noodle curves (0 to 10) 130 | int noodleCurving; 131 | } BNDnodeTheme; 132 | 133 | // describes the theme used to draw widgets 134 | typedef struct BNDtheme { 135 | // the background color of panels and windows 136 | NVGcolor backgroundColor; 137 | // theme for labels 138 | BNDwidgetTheme regularTheme; 139 | // theme for tool buttons 140 | BNDwidgetTheme toolTheme; 141 | // theme for radio buttons 142 | BNDwidgetTheme radioTheme; 143 | // theme for text fields 144 | BNDwidgetTheme textFieldTheme; 145 | // theme for option buttons (checkboxes) 146 | BNDwidgetTheme optionTheme; 147 | // theme for choice buttons (comboboxes) 148 | // Blender calls them "menu buttons" 149 | BNDwidgetTheme choiceTheme; 150 | // theme for number fields 151 | BNDwidgetTheme numberFieldTheme; 152 | // theme for slider controls 153 | BNDwidgetTheme sliderTheme; 154 | // theme for scrollbars 155 | BNDwidgetTheme scrollBarTheme; 156 | // theme for tooltips 157 | BNDwidgetTheme tooltipTheme; 158 | // theme for menu backgrounds 159 | BNDwidgetTheme menuTheme; 160 | // theme for menu items 161 | BNDwidgetTheme menuItemTheme; 162 | // theme for nodes 163 | BNDnodeTheme nodeTheme; 164 | } BNDtheme; 165 | 166 | // how text on a control is aligned 167 | typedef enum BNDtextAlignment { 168 | BND_LEFT = 0, 169 | BND_CENTER, 170 | } BNDtextAlignment; 171 | 172 | // states altering the styling of a widget 173 | typedef enum BNDwidgetState { 174 | // not interacting 175 | BND_DEFAULT = 0, 176 | // the mouse is hovering over the control 177 | BND_HOVER, 178 | // the widget is activated (pressed) or in an active state (toggled) 179 | BND_ACTIVE 180 | } BNDwidgetState; 181 | 182 | // flags indicating which corners are sharp (for grouping widgets) 183 | typedef enum BNDcornerFlags { 184 | // all corners are round 185 | BND_CORNER_NONE = 0, 186 | // sharp top left corner 187 | BND_CORNER_TOP_LEFT = 1, 188 | // sharp top right corner 189 | BND_CORNER_TOP_RIGHT = 2, 190 | // sharp bottom right corner 191 | BND_CORNER_DOWN_RIGHT = 4, 192 | // sharp bottom left corner 193 | BND_CORNER_DOWN_LEFT = 8, 194 | // all corners are sharp; 195 | // you can invert a set of flags using ^= BND_CORNER_ALL 196 | BND_CORNER_ALL = 0xF, 197 | // top border is sharp 198 | BND_CORNER_TOP = 3, 199 | // bottom border is sharp 200 | BND_CORNER_DOWN = 0xC, 201 | // left border is sharp 202 | BND_CORNER_LEFT = 9, 203 | // right border is sharp 204 | BND_CORNER_RIGHT = 6 205 | } BNDcornerFlags; 206 | 207 | // build an icon ID from two coordinates into the icon sheet, where 208 | // (0,0) designates the upper-leftmost icon, (1,0) the one right next to it, 209 | // and so on. 210 | #define BND_ICONID(x,y) ((x)|((y)<<8)) 211 | // alpha of disabled widget groups 212 | // can be used in conjunction with nvgGlobalAlpha() 213 | #define BND_DISABLED_ALPHA 0.5 214 | 215 | // default widget height 216 | #define BND_WIDGET_HEIGHT 21 217 | // default toolbutton width (if icon only) 218 | #define BND_TOOL_WIDTH 20 219 | 220 | // default radius of node ports 221 | #define BND_NODE_PORT_RADIUS 5 222 | // top margin of node content 223 | #define BND_NODE_MARGIN_TOP 25 224 | // bottom margin of node content 225 | #define BND_NODE_MARGIN_DOWN 5 226 | // left and right margin of node content 227 | #define BND_NODE_MARGIN_SIDE 10 228 | // height of node title bar 229 | #define BND_NODE_TITLE_HEIGHT 20 230 | // width of node title arrow click area 231 | #define BND_NODE_ARROW_AREA_WIDTH 20 232 | 233 | // size of splitter corner click area 234 | #define BND_SPLITTER_AREA_SIZE 12 235 | 236 | // width of vertical scrollbar 237 | #define BND_SCROLLBAR_WIDTH 13 238 | // height of horizontal scrollbar 239 | #define BND_SCROLLBAR_HEIGHT 14 240 | 241 | // default vertical spacing 242 | #define BND_VSPACING 1 243 | // default vertical spacing between groups 244 | #define BND_VSPACING_GROUP 8 245 | // default horizontal spacing 246 | #define BND_HSPACING 8 247 | 248 | // default text size 249 | #define BND_LABEL_FONT_SIZE 13 250 | 251 | // default text padding in inner box 252 | #define BND_PAD_LEFT 8 253 | #define BND_PAD_RIGHT 8 254 | 255 | // label: value separator string 256 | #define BND_LABEL_SEPARATOR ": " 257 | 258 | // alpha intensity of transparent items (0xa4) 259 | #define BND_TRANSPARENT_ALPHA 0.9 260 | 261 | // shade intensity of beveled panels 262 | #define BND_BEVEL_SHADE 30 263 | // shade intensity of beveled insets 264 | #define BND_INSET_BEVEL_SHADE 30 265 | // shade intensity of hovered inner boxes 266 | #define BND_HOVER_SHADE 15 267 | // shade intensity of splitter bevels 268 | #define BND_SPLITTER_SHADE 100 269 | 270 | // width of icon sheet 271 | #define BND_ICON_SHEET_WIDTH 602 272 | // height of icon sheet 273 | #define BND_ICON_SHEET_HEIGHT 640 274 | // gridsize of icon sheet in both dimensions 275 | #define BND_ICON_SHEET_GRID 21 276 | // offset of first icon tile relative to left border 277 | #define BND_ICON_SHEET_OFFSET_X 5 278 | // offset of first icon tile relative to top border 279 | #define BND_ICON_SHEET_OFFSET_Y 10 280 | // resolution of single icon 281 | #define BND_ICON_SHEET_RES 16 282 | 283 | // size of number field arrow 284 | #define BND_NUMBER_ARROW_SIZE 4 285 | 286 | // default text color 287 | #define BND_COLOR_TEXT {{{ 0,0,0,1 }}} 288 | // default highlighted text color 289 | #define BND_COLOR_TEXT_SELECTED {{{ 1,1,1,1 }}} 290 | 291 | // radius of tool button 292 | #define BND_TOOL_RADIUS 4 293 | 294 | // radius of option button 295 | #define BND_OPTION_RADIUS 4 296 | // width of option button checkbox 297 | #define BND_OPTION_WIDTH 14 298 | // height of option button checkbox 299 | #define BND_OPTION_HEIGHT 15 300 | 301 | // radius of text field 302 | #define BND_TEXT_RADIUS 4 303 | 304 | // radius of number button 305 | #define BND_NUMBER_RADIUS 10 306 | 307 | // radius of menu popup 308 | #define BND_MENU_RADIUS 3 309 | // feather of menu popup shadow 310 | #define BND_SHADOW_FEATHER 12 311 | // alpha of menu popup shadow 312 | #define BND_SHADOW_ALPHA 0.5 313 | 314 | // radius of scrollbar 315 | #define BND_SCROLLBAR_RADIUS 7 316 | // shade intensity of active scrollbar 317 | #define BND_SCROLLBAR_ACTIVE_SHADE 15 318 | 319 | // max glyphs for position testing 320 | #define BND_MAX_GLYPHS 1024 321 | 322 | // max rows for position testing 323 | #define BND_MAX_ROWS 32 324 | 325 | // text distance from bottom 326 | #define BND_TEXT_PAD_DOWN 7 327 | 328 | // stroke width of wire outline 329 | #define BND_NODE_WIRE_OUTLINE_WIDTH 4 330 | // stroke width of wire 331 | #define BND_NODE_WIRE_WIDTH 2 332 | // radius of node box 333 | #define BND_NODE_RADIUS 8 334 | // feather of node title text 335 | #define BND_NODE_TITLE_FEATHER 1 336 | // size of node title arrow 337 | #define BND_NODE_ARROW_SIZE 9 338 | 339 | typedef enum BNDicon { 340 | BND_ICON_NONE = BND_ICONID(0,29), 341 | BND_ICON_QUESTION = BND_ICONID(1,29), 342 | BND_ICON_ERROR = BND_ICONID(2,29), 343 | BND_ICON_CANCEL = BND_ICONID(3,29), 344 | BND_ICON_TRIA_RIGHT = BND_ICONID(4,29), 345 | BND_ICON_TRIA_DOWN = BND_ICONID(5,29), 346 | BND_ICON_TRIA_LEFT = BND_ICONID(6,29), 347 | BND_ICON_TRIA_UP = BND_ICONID(7,29), 348 | BND_ICON_ARROW_LEFTRIGHT = BND_ICONID(8,29), 349 | BND_ICON_PLUS = BND_ICONID(9,29), 350 | BND_ICON_DISCLOSURE_TRI_DOWN = BND_ICONID(10,29), 351 | BND_ICON_DISCLOSURE_TRI_RIGHT = BND_ICONID(11,29), 352 | BND_ICON_RADIOBUT_OFF = BND_ICONID(12,29), 353 | BND_ICON_RADIOBUT_ON = BND_ICONID(13,29), 354 | BND_ICON_MENU_PANEL = BND_ICONID(14,29), 355 | BND_ICON_BLENDER = BND_ICONID(15,29), 356 | BND_ICON_GRIP = BND_ICONID(16,29), 357 | BND_ICON_DOT = BND_ICONID(17,29), 358 | BND_ICON_COLLAPSEMENU = BND_ICONID(18,29), 359 | BND_ICON_X = BND_ICONID(19,29), 360 | BND_ICON_GO_LEFT = BND_ICONID(21,29), 361 | BND_ICON_PLUG = BND_ICONID(22,29), 362 | BND_ICON_UI = BND_ICONID(23,29), 363 | BND_ICON_NODE = BND_ICONID(24,29), 364 | BND_ICON_NODE_SEL = BND_ICONID(25,29), 365 | 366 | BND_ICON_FULLSCREEN = BND_ICONID(0,28), 367 | BND_ICON_SPLITSCREEN = BND_ICONID(1,28), 368 | BND_ICON_RIGHTARROW_THIN = BND_ICONID(2,28), 369 | BND_ICON_BORDERMOVE = BND_ICONID(3,28), 370 | BND_ICON_VIEWZOOM = BND_ICONID(4,28), 371 | BND_ICON_ZOOMIN = BND_ICONID(5,28), 372 | BND_ICON_ZOOMOUT = BND_ICONID(6,28), 373 | BND_ICON_PANEL_CLOSE = BND_ICONID(7,28), 374 | BND_ICON_COPY_ID = BND_ICONID(8,28), 375 | BND_ICON_EYEDROPPER = BND_ICONID(9,28), 376 | BND_ICON_LINK_AREA = BND_ICONID(10,28), 377 | BND_ICON_AUTO = BND_ICONID(11,28), 378 | BND_ICON_CHECKBOX_DEHLT = BND_ICONID(12,28), 379 | BND_ICON_CHECKBOX_HLT = BND_ICONID(13,28), 380 | BND_ICON_UNLOCKED = BND_ICONID(14,28), 381 | BND_ICON_LOCKED = BND_ICONID(15,28), 382 | BND_ICON_UNPINNED = BND_ICONID(16,28), 383 | BND_ICON_PINNED = BND_ICONID(17,28), 384 | BND_ICON_SCREEN_BACK = BND_ICONID(18,28), 385 | BND_ICON_RIGHTARROW = BND_ICONID(19,28), 386 | BND_ICON_DOWNARROW_HLT = BND_ICONID(20,28), 387 | BND_ICON_DOTSUP = BND_ICONID(21,28), 388 | BND_ICON_DOTSDOWN = BND_ICONID(22,28), 389 | BND_ICON_LINK = BND_ICONID(23,28), 390 | BND_ICON_INLINK = BND_ICONID(24,28), 391 | BND_ICON_PLUGIN = BND_ICONID(25,28), 392 | 393 | BND_ICON_HELP = BND_ICONID(0,27), 394 | BND_ICON_GHOST_ENABLED = BND_ICONID(1,27), 395 | BND_ICON_COLOR = BND_ICONID(2,27), 396 | BND_ICON_LINKED = BND_ICONID(3,27), 397 | BND_ICON_UNLINKED = BND_ICONID(4,27), 398 | BND_ICON_HAND = BND_ICONID(5,27), 399 | BND_ICON_ZOOM_ALL = BND_ICONID(6,27), 400 | BND_ICON_ZOOM_SELECTED = BND_ICONID(7,27), 401 | BND_ICON_ZOOM_PREVIOUS = BND_ICONID(8,27), 402 | BND_ICON_ZOOM_IN = BND_ICONID(9,27), 403 | BND_ICON_ZOOM_OUT = BND_ICONID(10,27), 404 | BND_ICON_RENDER_REGION = BND_ICONID(11,27), 405 | BND_ICON_BORDER_RECT = BND_ICONID(12,27), 406 | BND_ICON_BORDER_LASSO = BND_ICONID(13,27), 407 | BND_ICON_FREEZE = BND_ICONID(14,27), 408 | BND_ICON_STYLUS_PRESSURE = BND_ICONID(15,27), 409 | BND_ICON_GHOST_DISABLED = BND_ICONID(16,27), 410 | BND_ICON_NEW = BND_ICONID(17,27), 411 | BND_ICON_FILE_TICK = BND_ICONID(18,27), 412 | BND_ICON_QUIT = BND_ICONID(19,27), 413 | BND_ICON_URL = BND_ICONID(20,27), 414 | BND_ICON_RECOVER_LAST = BND_ICONID(21,27), 415 | BND_ICON_FULLSCREEN_ENTER = BND_ICONID(23,27), 416 | BND_ICON_FULLSCREEN_EXIT = BND_ICONID(24,27), 417 | BND_ICON_BLANK1 = BND_ICONID(25,27), 418 | 419 | BND_ICON_LAMP = BND_ICONID(0,26), 420 | BND_ICON_MATERIAL = BND_ICONID(1,26), 421 | BND_ICON_TEXTURE = BND_ICONID(2,26), 422 | BND_ICON_ANIM = BND_ICONID(3,26), 423 | BND_ICON_WORLD = BND_ICONID(4,26), 424 | BND_ICON_SCENE = BND_ICONID(5,26), 425 | BND_ICON_EDIT = BND_ICONID(6,26), 426 | BND_ICON_GAME = BND_ICONID(7,26), 427 | BND_ICON_RADIO = BND_ICONID(8,26), 428 | BND_ICON_SCRIPT = BND_ICONID(9,26), 429 | BND_ICON_PARTICLES = BND_ICONID(10,26), 430 | BND_ICON_PHYSICS = BND_ICONID(11,26), 431 | BND_ICON_SPEAKER = BND_ICONID(12,26), 432 | BND_ICON_TEXTURE_SHADED = BND_ICONID(13,26), 433 | 434 | BND_ICON_VIEW3D = BND_ICONID(0,25), 435 | BND_ICON_IPO = BND_ICONID(1,25), 436 | BND_ICON_OOPS = BND_ICONID(2,25), 437 | BND_ICON_BUTS = BND_ICONID(3,25), 438 | BND_ICON_FILESEL = BND_ICONID(4,25), 439 | BND_ICON_IMAGE_COL = BND_ICONID(5,25), 440 | BND_ICON_INFO = BND_ICONID(6,25), 441 | BND_ICON_SEQUENCE = BND_ICONID(7,25), 442 | BND_ICON_TEXT = BND_ICONID(8,25), 443 | BND_ICON_IMASEL = BND_ICONID(9,25), 444 | BND_ICON_SOUND = BND_ICONID(10,25), 445 | BND_ICON_ACTION = BND_ICONID(11,25), 446 | BND_ICON_NLA = BND_ICONID(12,25), 447 | BND_ICON_SCRIPTWIN = BND_ICONID(13,25), 448 | BND_ICON_TIME = BND_ICONID(14,25), 449 | BND_ICON_NODETREE = BND_ICONID(15,25), 450 | BND_ICON_LOGIC = BND_ICONID(16,25), 451 | BND_ICON_CONSOLE = BND_ICONID(17,25), 452 | BND_ICON_PREFERENCES = BND_ICONID(18,25), 453 | BND_ICON_CLIP = BND_ICONID(19,25), 454 | BND_ICON_ASSET_MANAGER = BND_ICONID(20,25), 455 | 456 | BND_ICON_OBJECT_DATAMODE = BND_ICONID(0,24), 457 | BND_ICON_EDITMODE_HLT = BND_ICONID(1,24), 458 | BND_ICON_FACESEL_HLT = BND_ICONID(2,24), 459 | BND_ICON_VPAINT_HLT = BND_ICONID(3,24), 460 | BND_ICON_TPAINT_HLT = BND_ICONID(4,24), 461 | BND_ICON_WPAINT_HLT = BND_ICONID(5,24), 462 | BND_ICON_SCULPTMODE_HLT = BND_ICONID(6,24), 463 | BND_ICON_POSE_HLT = BND_ICONID(7,24), 464 | BND_ICON_PARTICLEMODE = BND_ICONID(8,24), 465 | BND_ICON_LIGHTPAINT = BND_ICONID(9,24), 466 | 467 | BND_ICON_SCENE_DATA = BND_ICONID(0,23), 468 | BND_ICON_RENDERLAYERS = BND_ICONID(1,23), 469 | BND_ICON_WORLD_DATA = BND_ICONID(2,23), 470 | BND_ICON_OBJECT_DATA = BND_ICONID(3,23), 471 | BND_ICON_MESH_DATA = BND_ICONID(4,23), 472 | BND_ICON_CURVE_DATA = BND_ICONID(5,23), 473 | BND_ICON_META_DATA = BND_ICONID(6,23), 474 | BND_ICON_LATTICE_DATA = BND_ICONID(7,23), 475 | BND_ICON_LAMP_DATA = BND_ICONID(8,23), 476 | BND_ICON_MATERIAL_DATA = BND_ICONID(9,23), 477 | BND_ICON_TEXTURE_DATA = BND_ICONID(10,23), 478 | BND_ICON_ANIM_DATA = BND_ICONID(11,23), 479 | BND_ICON_CAMERA_DATA = BND_ICONID(12,23), 480 | BND_ICON_PARTICLE_DATA = BND_ICONID(13,23), 481 | BND_ICON_LIBRARY_DATA_DIRECT = BND_ICONID(14,23), 482 | BND_ICON_GROUP = BND_ICONID(15,23), 483 | BND_ICON_ARMATURE_DATA = BND_ICONID(16,23), 484 | BND_ICON_POSE_DATA = BND_ICONID(17,23), 485 | BND_ICON_BONE_DATA = BND_ICONID(18,23), 486 | BND_ICON_CONSTRAINT = BND_ICONID(19,23), 487 | BND_ICON_SHAPEKEY_DATA = BND_ICONID(20,23), 488 | BND_ICON_CONSTRAINT_BONE = BND_ICONID(21,23), 489 | BND_ICON_CAMERA_STEREO = BND_ICONID(22,23), 490 | BND_ICON_PACKAGE = BND_ICONID(23,23), 491 | BND_ICON_UGLYPACKAGE = BND_ICONID(24,23), 492 | 493 | BND_ICON_BRUSH_DATA = BND_ICONID(0,22), 494 | BND_ICON_IMAGE_DATA = BND_ICONID(1,22), 495 | BND_ICON_FILE = BND_ICONID(2,22), 496 | BND_ICON_FCURVE = BND_ICONID(3,22), 497 | BND_ICON_FONT_DATA = BND_ICONID(4,22), 498 | BND_ICON_RENDER_RESULT = BND_ICONID(5,22), 499 | BND_ICON_SURFACE_DATA = BND_ICONID(6,22), 500 | BND_ICON_EMPTY_DATA = BND_ICONID(7,22), 501 | BND_ICON_SETTINGS = BND_ICONID(8,22), 502 | BND_ICON_RENDER_ANIMATION = BND_ICONID(9,22), 503 | BND_ICON_RENDER_STILL = BND_ICONID(10,22), 504 | BND_ICON_BOIDS = BND_ICONID(12,22), 505 | BND_ICON_STRANDS = BND_ICONID(13,22), 506 | BND_ICON_LIBRARY_DATA_INDIRECT = BND_ICONID(14,22), 507 | BND_ICON_GREASEPENCIL = BND_ICONID(15,22), 508 | BND_ICON_LINE_DATA = BND_ICONID(16,22), 509 | BND_ICON_GROUP_BONE = BND_ICONID(18,22), 510 | BND_ICON_GROUP_VERTEX = BND_ICONID(19,22), 511 | BND_ICON_GROUP_VCOL = BND_ICONID(20,22), 512 | BND_ICON_GROUP_UVS = BND_ICONID(21,22), 513 | BND_ICON_RNA = BND_ICONID(24,22), 514 | BND_ICON_RNA_ADD = BND_ICONID(25,22), 515 | 516 | BND_ICON_OUTLINER_OB_EMPTY = BND_ICONID(0,20), 517 | BND_ICON_OUTLINER_OB_MESH = BND_ICONID(1,20), 518 | BND_ICON_OUTLINER_OB_CURVE = BND_ICONID(2,20), 519 | BND_ICON_OUTLINER_OB_LATTICE = BND_ICONID(3,20), 520 | BND_ICON_OUTLINER_OB_META = BND_ICONID(4,20), 521 | BND_ICON_OUTLINER_OB_LAMP = BND_ICONID(5,20), 522 | BND_ICON_OUTLINER_OB_CAMERA = BND_ICONID(6,20), 523 | BND_ICON_OUTLINER_OB_ARMATURE = BND_ICONID(7,20), 524 | BND_ICON_OUTLINER_OB_FONT = BND_ICONID(8,20), 525 | BND_ICON_OUTLINER_OB_SURFACE = BND_ICONID(9,20), 526 | BND_ICON_OUTLINER_OB_SPEAKER = BND_ICONID(10,20), 527 | BND_ICON_RESTRICT_VIEW_OFF = BND_ICONID(19,20), 528 | BND_ICON_RESTRICT_VIEW_ON = BND_ICONID(20,20), 529 | BND_ICON_RESTRICT_SELECT_OFF = BND_ICONID(21,20), 530 | BND_ICON_RESTRICT_SELECT_ON = BND_ICONID(22,20), 531 | BND_ICON_RESTRICT_RENDER_OFF = BND_ICONID(23,20), 532 | BND_ICON_RESTRICT_RENDER_ON = BND_ICONID(24,20), 533 | 534 | BND_ICON_OUTLINER_DATA_EMPTY = BND_ICONID(0,19), 535 | BND_ICON_OUTLINER_DATA_MESH = BND_ICONID(1,19), 536 | BND_ICON_OUTLINER_DATA_CURVE = BND_ICONID(2,19), 537 | BND_ICON_OUTLINER_DATA_LATTICE = BND_ICONID(3,19), 538 | BND_ICON_OUTLINER_DATA_META = BND_ICONID(4,19), 539 | BND_ICON_OUTLINER_DATA_LAMP = BND_ICONID(5,19), 540 | BND_ICON_OUTLINER_DATA_CAMERA = BND_ICONID(6,19), 541 | BND_ICON_OUTLINER_DATA_ARMATURE = BND_ICONID(7,19), 542 | BND_ICON_OUTLINER_DATA_FONT = BND_ICONID(8,19), 543 | BND_ICON_OUTLINER_DATA_SURFACE = BND_ICONID(9,19), 544 | BND_ICON_OUTLINER_DATA_SPEAKER = BND_ICONID(10,19), 545 | BND_ICON_OUTLINER_DATA_POSE = BND_ICONID(11,19), 546 | 547 | BND_ICON_MESH_PLANE = BND_ICONID(0,18), 548 | BND_ICON_MESH_CUBE = BND_ICONID(1,18), 549 | BND_ICON_MESH_CIRCLE = BND_ICONID(2,18), 550 | BND_ICON_MESH_UVSPHERE = BND_ICONID(3,18), 551 | BND_ICON_MESH_ICOSPHERE = BND_ICONID(4,18), 552 | BND_ICON_MESH_GRID = BND_ICONID(5,18), 553 | BND_ICON_MESH_MONKEY = BND_ICONID(6,18), 554 | BND_ICON_MESH_CYLINDER = BND_ICONID(7,18), 555 | BND_ICON_MESH_TORUS = BND_ICONID(8,18), 556 | BND_ICON_MESH_CONE = BND_ICONID(9,18), 557 | BND_ICON_LAMP_POINT = BND_ICONID(12,18), 558 | BND_ICON_LAMP_SUN = BND_ICONID(13,18), 559 | BND_ICON_LAMP_SPOT = BND_ICONID(14,18), 560 | BND_ICON_LAMP_HEMI = BND_ICONID(15,18), 561 | BND_ICON_LAMP_AREA = BND_ICONID(16,18), 562 | BND_ICON_META_EMPTY = BND_ICONID(19,18), 563 | BND_ICON_META_PLANE = BND_ICONID(20,18), 564 | BND_ICON_META_CUBE = BND_ICONID(21,18), 565 | BND_ICON_META_BALL = BND_ICONID(22,18), 566 | BND_ICON_META_ELLIPSOID = BND_ICONID(23,18), 567 | BND_ICON_META_CAPSULE = BND_ICONID(24,18), 568 | 569 | BND_ICON_SURFACE_NCURVE = BND_ICONID(0,17), 570 | BND_ICON_SURFACE_NCIRCLE = BND_ICONID(1,17), 571 | BND_ICON_SURFACE_NSURFACE = BND_ICONID(2,17), 572 | BND_ICON_SURFACE_NCYLINDER = BND_ICONID(3,17), 573 | BND_ICON_SURFACE_NSPHERE = BND_ICONID(4,17), 574 | BND_ICON_SURFACE_NTORUS = BND_ICONID(5,17), 575 | BND_ICON_CURVE_BEZCURVE = BND_ICONID(9,17), 576 | BND_ICON_CURVE_BEZCIRCLE = BND_ICONID(10,17), 577 | BND_ICON_CURVE_NCURVE = BND_ICONID(11,17), 578 | BND_ICON_CURVE_NCIRCLE = BND_ICONID(12,17), 579 | BND_ICON_CURVE_PATH = BND_ICONID(13,17), 580 | BND_ICON_COLOR_RED = BND_ICONID(19,17), 581 | BND_ICON_COLOR_GREEN = BND_ICONID(20,17), 582 | BND_ICON_COLOR_BLUE = BND_ICONID(21,17), 583 | 584 | BND_ICON_FORCE_FORCE = BND_ICONID(0,16), 585 | BND_ICON_FORCE_WIND = BND_ICONID(1,16), 586 | BND_ICON_FORCE_VORTEX = BND_ICONID(2,16), 587 | BND_ICON_FORCE_MAGNETIC = BND_ICONID(3,16), 588 | BND_ICON_FORCE_HARMONIC = BND_ICONID(4,16), 589 | BND_ICON_FORCE_CHARGE = BND_ICONID(5,16), 590 | BND_ICON_FORCE_LENNARDJONES = BND_ICONID(6,16), 591 | BND_ICON_FORCE_TEXTURE = BND_ICONID(7,16), 592 | BND_ICON_FORCE_CURVE = BND_ICONID(8,16), 593 | BND_ICON_FORCE_BOID = BND_ICONID(9,16), 594 | BND_ICON_FORCE_TURBULENCE = BND_ICONID(10,16), 595 | BND_ICON_FORCE_DRAG = BND_ICONID(11,16), 596 | BND_ICON_FORCE_SMOKEFLOW = BND_ICONID(12,16), 597 | 598 | BND_ICON_MODIFIER = BND_ICONID(0,12), 599 | BND_ICON_MOD_WAVE = BND_ICONID(1,12), 600 | BND_ICON_MOD_BUILD = BND_ICONID(2,12), 601 | BND_ICON_MOD_DECIM = BND_ICONID(3,12), 602 | BND_ICON_MOD_MIRROR = BND_ICONID(4,12), 603 | BND_ICON_MOD_SOFT = BND_ICONID(5,12), 604 | BND_ICON_MOD_SUBSURF = BND_ICONID(6,12), 605 | BND_ICON_HOOK = BND_ICONID(7,12), 606 | BND_ICON_MOD_PHYSICS = BND_ICONID(8,12), 607 | BND_ICON_MOD_PARTICLES = BND_ICONID(9,12), 608 | BND_ICON_MOD_BOOLEAN = BND_ICONID(10,12), 609 | BND_ICON_MOD_EDGESPLIT = BND_ICONID(11,12), 610 | BND_ICON_MOD_ARRAY = BND_ICONID(12,12), 611 | BND_ICON_MOD_UVPROJECT = BND_ICONID(13,12), 612 | BND_ICON_MOD_DISPLACE = BND_ICONID(14,12), 613 | BND_ICON_MOD_CURVE = BND_ICONID(15,12), 614 | BND_ICON_MOD_LATTICE = BND_ICONID(16,12), 615 | BND_ICON_CONSTRAINT_DATA = BND_ICONID(17,12), 616 | BND_ICON_MOD_ARMATURE = BND_ICONID(18,12), 617 | BND_ICON_MOD_SHRINKWRAP = BND_ICONID(19,12), 618 | BND_ICON_MOD_CAST = BND_ICONID(20,12), 619 | BND_ICON_MOD_MESHDEFORM = BND_ICONID(21,12), 620 | BND_ICON_MOD_BEVEL = BND_ICONID(22,12), 621 | BND_ICON_MOD_SMOOTH = BND_ICONID(23,12), 622 | BND_ICON_MOD_SIMPLEDEFORM = BND_ICONID(24,12), 623 | BND_ICON_MOD_MASK = BND_ICONID(25,12), 624 | 625 | BND_ICON_MOD_CLOTH = BND_ICONID(0,11), 626 | BND_ICON_MOD_EXPLODE = BND_ICONID(1,11), 627 | BND_ICON_MOD_FLUIDSIM = BND_ICONID(2,11), 628 | BND_ICON_MOD_MULTIRES = BND_ICONID(3,11), 629 | BND_ICON_MOD_SMOKE = BND_ICONID(4,11), 630 | BND_ICON_MOD_SOLIDIFY = BND_ICONID(5,11), 631 | BND_ICON_MOD_SCREW = BND_ICONID(6,11), 632 | BND_ICON_MOD_VERTEX_WEIGHT = BND_ICONID(7,11), 633 | BND_ICON_MOD_DYNAMICPAINT = BND_ICONID(8,11), 634 | BND_ICON_MOD_REMESH = BND_ICONID(9,11), 635 | BND_ICON_MOD_OCEAN = BND_ICONID(10,11), 636 | BND_ICON_MOD_WARP = BND_ICONID(11,11), 637 | BND_ICON_MOD_SKIN = BND_ICONID(12,11), 638 | BND_ICON_MOD_TRIANGULATE = BND_ICONID(13,11), 639 | BND_ICON_MOD_WIREFRAME = BND_ICONID(14,11), 640 | 641 | BND_ICON_REC = BND_ICONID(0,10), 642 | BND_ICON_PLAY = BND_ICONID(1,10), 643 | BND_ICON_FF = BND_ICONID(2,10), 644 | BND_ICON_REW = BND_ICONID(3,10), 645 | BND_ICON_PAUSE = BND_ICONID(4,10), 646 | BND_ICON_PREV_KEYFRAME = BND_ICONID(5,10), 647 | BND_ICON_NEXT_KEYFRAME = BND_ICONID(6,10), 648 | BND_ICON_PLAY_AUDIO = BND_ICONID(7,10), 649 | BND_ICON_PLAY_REVERSE = BND_ICONID(8,10), 650 | BND_ICON_PREVIEW_RANGE = BND_ICONID(9,10), 651 | BND_ICON_ACTION_TWEAK = BND_ICONID(10,10), 652 | BND_ICON_PMARKER_ACT = BND_ICONID(11,10), 653 | BND_ICON_PMARKER_SEL = BND_ICONID(12,10), 654 | BND_ICON_PMARKER = BND_ICONID(13,10), 655 | BND_ICON_MARKER_HLT = BND_ICONID(14,10), 656 | BND_ICON_MARKER = BND_ICONID(15,10), 657 | BND_ICON_SPACE2 = BND_ICONID(16,10), 658 | BND_ICON_SPACE3 = BND_ICONID(17,10), 659 | BND_ICON_KEYINGSET = BND_ICONID(18,10), 660 | BND_ICON_KEY_DEHLT = BND_ICONID(19,10), 661 | BND_ICON_KEY_HLT = BND_ICONID(20,10), 662 | BND_ICON_MUTE_IPO_OFF = BND_ICONID(21,10), 663 | BND_ICON_MUTE_IPO_ON = BND_ICONID(22,10), 664 | BND_ICON_VISIBLE_IPO_OFF = BND_ICONID(23,10), 665 | BND_ICON_VISIBLE_IPO_ON = BND_ICONID(24,10), 666 | BND_ICON_DRIVER = BND_ICONID(25,10), 667 | 668 | BND_ICON_SOLO_OFF = BND_ICONID(0,9), 669 | BND_ICON_SOLO_ON = BND_ICONID(1,9), 670 | BND_ICON_FRAME_PREV = BND_ICONID(2,9), 671 | BND_ICON_FRAME_NEXT = BND_ICONID(3,9), 672 | BND_ICON_NLA_PUSHDOWN = BND_ICONID(4,9), 673 | BND_ICON_IPO_CONSTANT = BND_ICONID(5,9), 674 | BND_ICON_IPO_LINEAR = BND_ICONID(6,9), 675 | BND_ICON_IPO_BEZIER = BND_ICONID(7,9), 676 | BND_ICON_IPO_SINE = BND_ICONID(8,9), 677 | BND_ICON_IPO_QUAD = BND_ICONID(9,9), 678 | BND_ICON_IPO_CUBIC = BND_ICONID(10,9), 679 | BND_ICON_IPO_QUART = BND_ICONID(11,9), 680 | BND_ICON_IPO_QUINT = BND_ICONID(12,9), 681 | BND_ICON_IPO_EXPO = BND_ICONID(13,9), 682 | BND_ICON_IPO_CIRC = BND_ICONID(14,9), 683 | BND_ICON_IPO_BOUNCE = BND_ICONID(15,9), 684 | BND_ICON_IPO_ELASTIC = BND_ICONID(16,9), 685 | BND_ICON_IPO_BACK = BND_ICONID(17,9), 686 | BND_ICON_IPO_EASE_IN = BND_ICONID(18,9), 687 | BND_ICON_IPO_EASE_OUT = BND_ICONID(19,9), 688 | BND_ICON_IPO_EASE_IN_OUT = BND_ICONID(20,9), 689 | 690 | BND_ICON_VERTEXSEL = BND_ICONID(0,8), 691 | BND_ICON_EDGESEL = BND_ICONID(1,8), 692 | BND_ICON_FACESEL = BND_ICONID(2,8), 693 | BND_ICON_LOOPSEL = BND_ICONID(3,8), 694 | BND_ICON_ROTATE = BND_ICONID(5,8), 695 | BND_ICON_CURSOR = BND_ICONID(6,8), 696 | BND_ICON_ROTATECOLLECTION = BND_ICONID(7,8), 697 | BND_ICON_ROTATECENTER = BND_ICONID(8,8), 698 | BND_ICON_ROTACTIVE = BND_ICONID(9,8), 699 | BND_ICON_ALIGN = BND_ICONID(10,8), 700 | BND_ICON_SMOOTHCURVE = BND_ICONID(12,8), 701 | BND_ICON_SPHERECURVE = BND_ICONID(13,8), 702 | BND_ICON_ROOTCURVE = BND_ICONID(14,8), 703 | BND_ICON_SHARPCURVE = BND_ICONID(15,8), 704 | BND_ICON_LINCURVE = BND_ICONID(16,8), 705 | BND_ICON_NOCURVE = BND_ICONID(17,8), 706 | BND_ICON_RNDCURVE = BND_ICONID(18,8), 707 | BND_ICON_PROP_OFF = BND_ICONID(19,8), 708 | BND_ICON_PROP_ON = BND_ICONID(20,8), 709 | BND_ICON_PROP_CON = BND_ICONID(21,8), 710 | BND_ICON_SCULPT_DYNTOPO = BND_ICONID(22,8), 711 | BND_ICON_PARTICLE_POINT = BND_ICONID(23,8), 712 | BND_ICON_PARTICLE_TIP = BND_ICONID(24,8), 713 | BND_ICON_PARTICLE_PATH = BND_ICONID(25,8), 714 | 715 | BND_ICON_MAN_TRANS = BND_ICONID(0,7), 716 | BND_ICON_MAN_ROT = BND_ICONID(1,7), 717 | BND_ICON_MAN_SCALE = BND_ICONID(2,7), 718 | BND_ICON_MANIPUL = BND_ICONID(3,7), 719 | BND_ICON_SNAP_OFF = BND_ICONID(4,7), 720 | BND_ICON_SNAP_ON = BND_ICONID(5,7), 721 | BND_ICON_SNAP_NORMAL = BND_ICONID(6,7), 722 | BND_ICON_SNAP_INCREMENT = BND_ICONID(7,7), 723 | BND_ICON_SNAP_VERTEX = BND_ICONID(8,7), 724 | BND_ICON_SNAP_EDGE = BND_ICONID(9,7), 725 | BND_ICON_SNAP_FACE = BND_ICONID(10,7), 726 | BND_ICON_SNAP_VOLUME = BND_ICONID(11,7), 727 | BND_ICON_STICKY_UVS_LOC = BND_ICONID(13,7), 728 | BND_ICON_STICKY_UVS_DISABLE = BND_ICONID(14,7), 729 | BND_ICON_STICKY_UVS_VERT = BND_ICONID(15,7), 730 | BND_ICON_CLIPUV_DEHLT = BND_ICONID(16,7), 731 | BND_ICON_CLIPUV_HLT = BND_ICONID(17,7), 732 | BND_ICON_SNAP_PEEL_OBJECT = BND_ICONID(18,7), 733 | BND_ICON_GRID = BND_ICONID(19,7), 734 | 735 | BND_ICON_PASTEDOWN = BND_ICONID(0,6), 736 | BND_ICON_COPYDOWN = BND_ICONID(1,6), 737 | BND_ICON_PASTEFLIPUP = BND_ICONID(2,6), 738 | BND_ICON_PASTEFLIPDOWN = BND_ICONID(3,6), 739 | BND_ICON_SNAP_SURFACE = BND_ICONID(8,6), 740 | BND_ICON_AUTOMERGE_ON = BND_ICONID(9,6), 741 | BND_ICON_AUTOMERGE_OFF = BND_ICONID(10,6), 742 | BND_ICON_RETOPO = BND_ICONID(11,6), 743 | BND_ICON_UV_VERTEXSEL = BND_ICONID(12,6), 744 | BND_ICON_UV_EDGESEL = BND_ICONID(13,6), 745 | BND_ICON_UV_FACESEL = BND_ICONID(14,6), 746 | BND_ICON_UV_ISLANDSEL = BND_ICONID(15,6), 747 | BND_ICON_UV_SYNC_SELECT = BND_ICONID(16,6), 748 | 749 | BND_ICON_BBOX = BND_ICONID(0,5), 750 | BND_ICON_WIRE = BND_ICONID(1,5), 751 | BND_ICON_SOLID = BND_ICONID(2,5), 752 | BND_ICON_SMOOTH = BND_ICONID(3,5), 753 | BND_ICON_POTATO = BND_ICONID(4,5), 754 | BND_ICON_ORTHO = BND_ICONID(6,5), 755 | BND_ICON_LOCKVIEW_OFF = BND_ICONID(9,5), 756 | BND_ICON_LOCKVIEW_ON = BND_ICONID(10,5), 757 | BND_ICON_AXIS_SIDE = BND_ICONID(12,5), 758 | BND_ICON_AXIS_FRONT = BND_ICONID(13,5), 759 | BND_ICON_AXIS_TOP = BND_ICONID(14,5), 760 | BND_ICON_NDOF_DOM = BND_ICONID(15,5), 761 | BND_ICON_NDOF_TURN = BND_ICONID(16,5), 762 | BND_ICON_NDOF_FLY = BND_ICONID(17,5), 763 | BND_ICON_NDOF_TRANS = BND_ICONID(18,5), 764 | BND_ICON_LAYER_USED = BND_ICONID(19,5), 765 | BND_ICON_LAYER_ACTIVE = BND_ICONID(20,5), 766 | 767 | BND_ICON_SORTALPHA = BND_ICONID(0,3), 768 | BND_ICON_SORTBYEXT = BND_ICONID(1,3), 769 | BND_ICON_SORTTIME = BND_ICONID(2,3), 770 | BND_ICON_SORTSIZE = BND_ICONID(3,3), 771 | BND_ICON_LONGDISPLAY = BND_ICONID(4,3), 772 | BND_ICON_SHORTDISPLAY = BND_ICONID(5,3), 773 | BND_ICON_GHOST = BND_ICONID(6,3), 774 | BND_ICON_IMGDISPLAY = BND_ICONID(7,3), 775 | BND_ICON_SAVE_AS = BND_ICONID(8,3), 776 | BND_ICON_SAVE_COPY = BND_ICONID(9,3), 777 | BND_ICON_BOOKMARKS = BND_ICONID(10,3), 778 | BND_ICON_FONTPREVIEW = BND_ICONID(11,3), 779 | BND_ICON_FILTER = BND_ICONID(12,3), 780 | BND_ICON_NEWFOLDER = BND_ICONID(13,3), 781 | BND_ICON_OPEN_RECENT = BND_ICONID(14,3), 782 | BND_ICON_FILE_PARENT = BND_ICONID(15,3), 783 | BND_ICON_FILE_REFRESH = BND_ICONID(16,3), 784 | BND_ICON_FILE_FOLDER = BND_ICONID(17,3), 785 | BND_ICON_FILE_BLANK = BND_ICONID(18,3), 786 | BND_ICON_FILE_BLEND = BND_ICONID(19,3), 787 | BND_ICON_FILE_IMAGE = BND_ICONID(20,3), 788 | BND_ICON_FILE_MOVIE = BND_ICONID(21,3), 789 | BND_ICON_FILE_SCRIPT = BND_ICONID(22,3), 790 | BND_ICON_FILE_SOUND = BND_ICONID(23,3), 791 | BND_ICON_FILE_FONT = BND_ICONID(24,3), 792 | BND_ICON_FILE_TEXT = BND_ICONID(25,3), 793 | 794 | BND_ICON_RECOVER_AUTO = BND_ICONID(0,2), 795 | BND_ICON_SAVE_PREFS = BND_ICONID(1,2), 796 | BND_ICON_LINK_BLEND = BND_ICONID(2,2), 797 | BND_ICON_APPEND_BLEND = BND_ICONID(3,2), 798 | BND_ICON_IMPORT = BND_ICONID(4,2), 799 | BND_ICON_EXPORT = BND_ICONID(5,2), 800 | BND_ICON_EXTERNAL_DATA = BND_ICONID(6,2), 801 | BND_ICON_LOAD_FACTORY = BND_ICONID(7,2), 802 | BND_ICON_LOOP_BACK = BND_ICONID(13,2), 803 | BND_ICON_LOOP_FORWARDS = BND_ICONID(14,2), 804 | BND_ICON_BACK = BND_ICONID(15,2), 805 | BND_ICON_FORWARD = BND_ICONID(16,2), 806 | BND_ICON_FILE_BACKUP = BND_ICONID(24,2), 807 | BND_ICON_DISK_DRIVE = BND_ICONID(25,2), 808 | 809 | BND_ICON_MATPLANE = BND_ICONID(0,1), 810 | BND_ICON_MATSPHERE = BND_ICONID(1,1), 811 | BND_ICON_MATCUBE = BND_ICONID(2,1), 812 | BND_ICON_MONKEY = BND_ICONID(3,1), 813 | BND_ICON_HAIR = BND_ICONID(4,1), 814 | BND_ICON_ALIASED = BND_ICONID(5,1), 815 | BND_ICON_ANTIALIASED = BND_ICONID(6,1), 816 | BND_ICON_MAT_SPHERE_SKY = BND_ICONID(7,1), 817 | BND_ICON_WORDWRAP_OFF = BND_ICONID(12,1), 818 | BND_ICON_WORDWRAP_ON = BND_ICONID(13,1), 819 | BND_ICON_SYNTAX_OFF = BND_ICONID(14,1), 820 | BND_ICON_SYNTAX_ON = BND_ICONID(15,1), 821 | BND_ICON_LINENUMBERS_OFF = BND_ICONID(16,1), 822 | BND_ICON_LINENUMBERS_ON = BND_ICONID(17,1), 823 | BND_ICON_SCRIPTPLUGINS = BND_ICONID(18,1), 824 | 825 | BND_ICON_SEQ_SEQUENCER = BND_ICONID(0,0), 826 | BND_ICON_SEQ_PREVIEW = BND_ICONID(1,0), 827 | BND_ICON_SEQ_LUMA_WAVEFORM = BND_ICONID(2,0), 828 | BND_ICON_SEQ_CHROMA_SCOPE = BND_ICONID(3,0), 829 | BND_ICON_SEQ_HISTOGRAM = BND_ICONID(4,0), 830 | BND_ICON_SEQ_SPLITVIEW = BND_ICONID(5,0), 831 | BND_ICON_IMAGE_RGB = BND_ICONID(9,0), 832 | BND_ICON_IMAGE_RGB_ALPHA = BND_ICONID(10,0), 833 | BND_ICON_IMAGE_ALPHA = BND_ICONID(11,0), 834 | BND_ICON_IMAGE_ZDEPTH = BND_ICONID(12,0), 835 | BND_ICON_IMAGEFILE = BND_ICONID(13,0), 836 | } BNDicon; 837 | 838 | //////////////////////////////////////////////////////////////////////////////// 839 | 840 | // set the current theme all widgets will be drawn with. 841 | // the default Blender 2.6 theme is set by default. 842 | BND_EXPORT void bndSetTheme(BNDtheme theme); 843 | 844 | // Returns the currently set theme 845 | BND_EXPORT const BNDtheme *bndGetTheme(); 846 | 847 | // designates an image handle as returned by nvgCreateImage*() as the themes' 848 | // icon sheet. The icon sheet format must be compatible to Blender 2.6's icon 849 | // sheet; the order of icons does not matter. 850 | // A valid icon sheet is e.g. shown at 851 | // http://wiki.blender.org/index.php/Dev:2.5/Doc/How_to/Add_an_icon 852 | BND_EXPORT void bndSetIconImage(int image); 853 | 854 | // designates an image handle as returned by nvgCreateFont*() as the themes' 855 | // UI font. Blender's original UI font Droid Sans is perfectly suited and 856 | // available here: 857 | // https://svn.blender.org/svnroot/bf-blender/trunk/blender/release/datafiles/fonts/ 858 | BND_EXPORT void bndSetFont(int font); 859 | 860 | //////////////////////////////////////////////////////////////////////////////// 861 | 862 | // High Level Functions 863 | // -------------------- 864 | // Use these functions to draw themed widgets with your NVGcontext. 865 | 866 | // Draw a label with its lower left origin at (x,y) and size of (w,h). 867 | // if iconid >= 0, an icon will be added to the widget 868 | // if label is not NULL, a label will be added to the widget 869 | // widget looks best when height is BND_WIDGET_HEIGHT 870 | BND_EXPORT void bndLabel(NVGcontext *ctx, 871 | float x, float y, float w, float h, int iconid, const char *label); 872 | 873 | // Draw a tool button with its lower left origin at (x,y) and size of (w,h), 874 | // where flags is one or multiple flags from BNDcornerFlags and state denotes 875 | // the widgets current UI state. 876 | // if iconid >= 0, an icon will be added to the widget 877 | // if label is not NULL, a label will be added to the widget 878 | // widget looks best when height is BND_WIDGET_HEIGHT 879 | BND_EXPORT void bndToolButton(NVGcontext *ctx, 880 | float x, float y, float w, float h, int flags, BNDwidgetState state, 881 | int iconid, const char *label); 882 | 883 | // Draw a radio button with its lower left origin at (x,y) and size of (w,h), 884 | // where flags is one or multiple flags from BNDcornerFlags and state denotes 885 | // the widgets current UI state. 886 | // if iconid >= 0, an icon will be added to the widget 887 | // if label is not NULL, a label will be added to the widget 888 | // widget looks best when height is BND_WIDGET_HEIGHT 889 | BND_EXPORT void bndRadioButton(NVGcontext *ctx, 890 | float x, float y, float w, float h, int flags, BNDwidgetState state, 891 | int iconid, const char *label); 892 | 893 | 894 | // Calculate the corresponding text position for given coordinates px/py 895 | // in a text field. 896 | // See bndTextField for more info. 897 | BND_EXPORT int bndTextFieldTextPosition(NVGcontext *ctx, float x, float y, float w, float h, 898 | int iconid, const char *text, int px, int py); 899 | 900 | // Draw a text field with its lower left origin at (x,y) and size of (w,h), 901 | // where flags is one or multiple flags from BNDcornerFlags and state denotes 902 | // the widgets current UI state. 903 | // if iconid >= 0, an icon will be added to the widget 904 | // if text is not NULL, text will be printed to the widget 905 | // cbegin must be >= 0 and <= strlen(text) and denotes the beginning of the caret 906 | // cend must be >= cbegin and <= strlen(text) and denotes the end of the caret 907 | // if cend < cbegin, then no caret will be drawn 908 | // widget looks best when height is BND_WIDGET_HEIGHT 909 | BND_EXPORT void bndTextField(NVGcontext *ctx, 910 | float x, float y, float w, float h, int flags, BNDwidgetState state, 911 | int iconid, const char *text, int cbegin, int cend); 912 | 913 | // Draw an option button with its lower left origin at (x,y) and size of (w,h), 914 | // where flags is one or multiple flags from BNDcornerFlags and state denotes 915 | // the widgets current UI state. 916 | // if label is not NULL, a label will be added to the widget 917 | // widget looks best when height is BND_WIDGET_HEIGHT 918 | BND_EXPORT void bndOptionButton(NVGcontext *ctx, 919 | float x, float y, float w, float h, BNDwidgetState state, 920 | const char *label); 921 | 922 | // Draw a choice button with its lower left origin at (x,y) and size of (w,h), 923 | // where flags is one or multiple flags from BNDcornerFlags and state denotes 924 | // the widgets current UI state. 925 | // if iconid >= 0, an icon will be added to the widget 926 | // if label is not NULL, a label will be added to the widget 927 | // widget looks best when height is BND_WIDGET_HEIGHT 928 | BND_EXPORT void bndChoiceButton(NVGcontext *ctx, 929 | float x, float y, float w, float h, int flags, BNDwidgetState state, 930 | int iconid, const char *label); 931 | 932 | // Draw a color button with its lower left origin at (x,y) and size of (w,h), 933 | // where flags is one or multiple flags from BNDcornerFlags and state denotes 934 | // the widgets current UI state. 935 | // widget looks best when height is BND_WIDGET_HEIGHT 936 | BND_EXPORT void bndColorButton(NVGcontext *ctx, 937 | float x, float y, float w, float h, int flags, NVGcolor color); 938 | 939 | // Draw a number field with its lower left origin at (x,y) and size of (w,h), 940 | // where flags is one or multiple flags from BNDcornerFlags and state denotes 941 | // the widgets current UI state. 942 | // if label is not NULL, a label will be added to the widget 943 | // if value is not NULL, a value will be added to the widget, along with 944 | // a ":" separator 945 | // widget looks best when height is BND_WIDGET_HEIGHT 946 | BND_EXPORT void bndNumberField(NVGcontext *ctx, 947 | float x, float y, float w, float h, int flags, BNDwidgetState state, 948 | const char *label, const char *value); 949 | 950 | // Draw slider control with its lower left origin at (x,y) and size of (w,h), 951 | // where flags is one or multiple flags from BNDcornerFlags and state denotes 952 | // the widgets current UI state. 953 | // progress must be in the range 0..1 and controls the size of the slider bar 954 | // if label is not NULL, a label will be added to the widget 955 | // if value is not NULL, a value will be added to the widget, along with 956 | // a ":" separator 957 | // widget looks best when height is BND_WIDGET_HEIGHT 958 | BND_EXPORT void bndSlider(NVGcontext *ctx, 959 | float x, float y, float w, float h, int flags, BNDwidgetState state, 960 | float progress, const char *label, const char *value); 961 | 962 | // Draw scrollbar with its lower left origin at (x,y) and size of (w,h), 963 | // where state denotes the widgets current UI state. 964 | // offset is in the range 0..1 and controls the position of the scroll handle 965 | // size is in the range 0..1 and controls the size of the scroll handle 966 | // horizontal widget looks best when height is BND_SCROLLBAR_HEIGHT, 967 | // vertical looks best when width is BND_SCROLLBAR_WIDTH 968 | BND_EXPORT void bndScrollBar(NVGcontext *ctx, 969 | float x, float y, float w, float h, BNDwidgetState state, 970 | float offset, float size); 971 | 972 | // Draw a menu background with its lower left origin at (x,y) and size of (w,h), 973 | // where flags is one or multiple flags from BNDcornerFlags. 974 | BND_EXPORT void bndMenuBackground(NVGcontext *ctx, 975 | float x, float y, float w, float h, int flags); 976 | 977 | // Draw a menu label with its lower left origin at (x,y) and size of (w,h). 978 | // if iconid >= 0, an icon will be added to the widget 979 | // if label is not NULL, a label will be added to the widget 980 | // widget looks best when height is BND_WIDGET_HEIGHT 981 | BND_EXPORT void bndMenuLabel(NVGcontext *ctx, 982 | float x, float y, float w, float h, int iconid, const char *label); 983 | 984 | // Draw a menu item with its lower left origin at (x,y) and size of (w,h), 985 | // where state denotes the widgets current UI state. 986 | // if iconid >= 0, an icon will be added to the widget 987 | // if label is not NULL, a label will be added to the widget 988 | // widget looks best when height is BND_WIDGET_HEIGHT 989 | BND_EXPORT void bndMenuItem(NVGcontext *ctx, 990 | float x, float y, float w, float h, BNDwidgetState state, 991 | int iconid, const char *label); 992 | 993 | // Draw a tooltip background with its lower left origin at (x,y) and size of (w,h) 994 | BND_EXPORT void bndTooltipBackground(NVGcontext *ctx, float x, float y, float w, float h); 995 | 996 | // Draw a node port at the given position filled with the given color 997 | BND_EXPORT void bndNodePort(NVGcontext *ctx, float x, float y, BNDwidgetState state, 998 | NVGcolor color); 999 | 1000 | // Draw a node wire originating at (x0,y0) and floating to (x1,y1), with 1001 | // a colored gradient based on the states state0 and state1: 1002 | // BND_DEFAULT: default wire color 1003 | // BND_HOVER: selected wire color 1004 | // BND_ACTIVE: dragged wire color 1005 | BND_EXPORT void bndNodeWire(NVGcontext *ctx, float x0, float y0, float x1, float y1, 1006 | BNDwidgetState state0, BNDwidgetState state1); 1007 | 1008 | // Draw a node wire originating at (x0,y0) and floating to (x1,y1), with 1009 | // a colored gradient based on the two colors color0 and color1 1010 | BND_EXPORT void bndColoredNodeWire(NVGcontext *ctx, float x0, float y0, float x1, float y1, 1011 | NVGcolor color0, NVGcolor color1); 1012 | 1013 | // Draw a node background with its upper left origin at (x,y) and size of (w,h) 1014 | // where titleColor provides the base color for the title bar 1015 | BND_EXPORT void bndNodeBackground(NVGcontext *ctx, float x, float y, float w, float h, 1016 | BNDwidgetState state, int iconid, const char *label, NVGcolor titleColor); 1017 | 1018 | // Draw a window with the upper right and lower left splitter widgets into 1019 | // the rectangle at origin (x,y) and size (w, h) 1020 | BND_EXPORT void bndSplitterWidgets(NVGcontext *ctx, float x, float y, float w, float h); 1021 | 1022 | // Draw the join area overlay stencil into the rectangle 1023 | // at origin (x,y) and size (w,h) 1024 | // vertical is 0 or 1 and designates the arrow orientation, 1025 | // mirror is 0 or 1 and flips the arrow side 1026 | BND_EXPORT void bndJoinAreaOverlay(NVGcontext *ctx, float x, float y, float w, float h, 1027 | int vertical, int mirror); 1028 | 1029 | //////////////////////////////////////////////////////////////////////////////// 1030 | 1031 | // Estimator Functions 1032 | // ------------------- 1033 | // Use these functions to estimate sizes for widgets with your NVGcontext. 1034 | 1035 | // returns the ideal width for a label with given icon and text 1036 | BND_EXPORT float bndLabelWidth(NVGcontext *ctx, int iconid, const char *label); 1037 | 1038 | // returns the height for a label with given icon, text and width; this 1039 | // function is primarily useful in conjunction with multiline labels and textboxes 1040 | BND_EXPORT float bndLabelHeight(NVGcontext *ctx, int iconid, const char *label, 1041 | float width); 1042 | 1043 | //////////////////////////////////////////////////////////////////////////////// 1044 | 1045 | // Low Level Functions 1046 | // ------------------- 1047 | // these are part of the implementation detail and can be used to theme 1048 | // new kinds of controls in a similar fashion. 1049 | 1050 | // make color transparent using the default alpha value 1051 | BND_EXPORT NVGcolor bndTransparent(NVGcolor color); 1052 | 1053 | // offset a color by a given integer delta in the range -100 to 100 1054 | BND_EXPORT NVGcolor bndOffsetColor(NVGcolor color, int delta); 1055 | 1056 | // assigns radius r to the four entries of array radiuses depending on whether 1057 | // the corner is marked as sharp or not; see BNDcornerFlags for possible 1058 | // flag values. 1059 | BND_EXPORT void bndSelectCorners(float *radiuses, float r, int flags); 1060 | 1061 | // computes the upper and lower gradient colors for the inner box from a widget 1062 | // theme and the widgets state. If flipActive is set and the state is 1063 | // BND_ACTIVE, the upper and lower colors will be swapped. 1064 | BND_EXPORT void bndInnerColors(NVGcolor *shade_top, NVGcolor *shade_down, 1065 | const BNDwidgetTheme *theme, BNDwidgetState state, int flipActive); 1066 | 1067 | // computes the text color for a widget label from a widget theme and the 1068 | // widgets state. 1069 | BND_EXPORT NVGcolor bndTextColor(const BNDwidgetTheme *theme, BNDwidgetState state); 1070 | 1071 | // computes the bounds of the scrollbar handle from the scrollbar size 1072 | // and the handles offset and size. 1073 | // offset is in the range 0..1 and defines the position of the scroll handle 1074 | // size is in the range 0..1 and defines the size of the scroll handle 1075 | BND_EXPORT void bndScrollHandleRect(float *x, float *y, float *w, float *h, 1076 | float offset, float size); 1077 | 1078 | // Add a rounded box path at position (x,y) with size (w,h) and a separate 1079 | // radius for each corner listed in clockwise order, so that cr0 = top left, 1080 | // cr1 = top right, cr2 = bottom right, cr3 = bottom left; 1081 | // this is a low level drawing function: the path must be stroked or filled 1082 | // to become visible. 1083 | BND_EXPORT void bndRoundedBox(NVGcontext *ctx, float x, float y, float w, float h, 1084 | float cr0, float cr1, float cr2, float cr3); 1085 | 1086 | // Draw a flat panel without any decorations at position (x,y) with size (w,h) 1087 | // and fills it with backgroundColor 1088 | BND_EXPORT void bndBackground(NVGcontext *ctx, float x, float y, float w, float h); 1089 | 1090 | // Draw a beveled border at position (x,y) with size (w,h) shaded with 1091 | // lighter and darker versions of backgroundColor 1092 | BND_EXPORT void bndBevel(NVGcontext *ctx, float x, float y, float w, float h); 1093 | 1094 | // Draw a lower inset for a rounded box at position (x,y) with size (w,h) 1095 | // that gives the impression the surface has been pushed in. 1096 | // cr2 and cr3 contain the radiuses of the bottom right and bottom left 1097 | // corners of the rounded box. 1098 | BND_EXPORT void bndBevelInset(NVGcontext *ctx, float x, float y, float w, float h, 1099 | float cr2, float cr3); 1100 | 1101 | // Draw an icon with (x,y) as its upper left coordinate; the iconid selects 1102 | // the icon from the sheet; use the BND_ICONID macro to build icon IDs. 1103 | BND_EXPORT void bndIcon(NVGcontext *ctx, float x, float y, int iconid); 1104 | 1105 | // Draw a drop shadow around the rounded box at (x,y) with size (w,h) and 1106 | // radius r, with feather as its maximum range in pixels. 1107 | // No shadow will be painted inside the rounded box. 1108 | BND_EXPORT void bndDropShadow(NVGcontext *ctx, float x, float y, float w, float h, 1109 | float r, float feather, float alpha); 1110 | 1111 | // Draw the inner part of a widget box, with a gradient from shade_top to 1112 | // shade_down. If h>w, the gradient will be horizontal instead of 1113 | // vertical. 1114 | BND_EXPORT void bndInnerBox(NVGcontext *ctx, float x, float y, float w, float h, 1115 | float cr0, float cr1, float cr2, float cr3, 1116 | NVGcolor shade_top, NVGcolor shade_down); 1117 | 1118 | // Draw the outline part of a widget box with the given color 1119 | BND_EXPORT void bndOutlineBox(NVGcontext *ctx, float x, float y, float w, float h, 1120 | float cr0, float cr1, float cr2, float cr3, NVGcolor color); 1121 | 1122 | // Draw an optional icon specified by and an optional label with 1123 | // given alignment (BNDtextAlignment), fontsize and color within a widget box. 1124 | // if iconid is >= 0, an icon will be drawn and the labels remaining space 1125 | // will be adjusted. 1126 | // if label is not NULL, it will be drawn with the specified alignment, fontsize 1127 | // and color. 1128 | // if value is not NULL, label and value will be drawn with a ":" separator 1129 | // inbetween. 1130 | BND_EXPORT void bndIconLabelValue(NVGcontext *ctx, float x, float y, float w, float h, 1131 | int iconid, NVGcolor color, int align, float fontsize, const char *label, 1132 | const char *value); 1133 | 1134 | // Draw an optional icon specified by and an optional label with 1135 | // given alignment (BNDtextAlignment), fontsize and color within a node title bar 1136 | // if iconid is >= 0, an icon will be drawn 1137 | // if label is not NULL, it will be drawn with the specified alignment, fontsize 1138 | // and color. 1139 | BND_EXPORT void bndNodeIconLabel(NVGcontext *ctx, float x, float y, float w, float h, 1140 | int iconid, NVGcolor color, NVGcolor shadowColor, int align, 1141 | float fontsize, const char *label); 1142 | 1143 | // Calculate the corresponding text position for given coordinates px/py 1144 | // in an iconLabel. 1145 | // See bndIconLabelCaret for more info. 1146 | BND_EXPORT int bndIconLabelTextPosition(NVGcontext *ctx, float x, float y, float w, float h, 1147 | int iconid, float fontsize, const char *label, int px, int py); 1148 | 1149 | // Draw an optional icon specified by , an optional label and 1150 | // a caret with given fontsize and color within a widget box. 1151 | // if iconid is >= 0, an icon will be drawn and the labels remaining space 1152 | // will be adjusted. 1153 | // if label is not NULL, it will be drawn with the specified alignment, fontsize 1154 | // and color. 1155 | // cbegin must be >= 0 and <= strlen(text) and denotes the beginning of the caret 1156 | // cend must be >= cbegin and <= strlen(text) and denotes the end of the caret 1157 | // if cend < cbegin, then no caret will be drawn 1158 | BND_EXPORT void bndIconLabelCaret(NVGcontext *ctx, float x, float y, float w, float h, 1159 | int iconid, NVGcolor color, float fontsize, const char *label, 1160 | NVGcolor caretcolor, int cbegin, int cend); 1161 | 1162 | // Draw a checkmark for an option box with the given upper left coordinates 1163 | // (ox,oy) with the specified color. 1164 | BND_EXPORT void bndCheck(NVGcontext *ctx, float ox, float oy, NVGcolor color); 1165 | 1166 | // Draw a horizontal arrow for a number field with its center at (x,y) and 1167 | // size s; if s is negative, the arrow points to the left. 1168 | BND_EXPORT void bndArrow(NVGcontext *ctx, float x, float y, float s, NVGcolor color); 1169 | 1170 | // Draw an up/down arrow for a choice box with its center at (x,y) and size s 1171 | BND_EXPORT void bndUpDownArrow(NVGcontext *ctx, float x, float y, float s, NVGcolor color); 1172 | 1173 | // Draw a node down-arrow with its tip at (x,y) and size s 1174 | BND_EXPORT void bndNodeArrowDown(NVGcontext *ctx, float x, float y, float s, NVGcolor color); 1175 | 1176 | // return the color of a node wire based on state 1177 | // BND_HOVER indicates selected state, 1178 | // BND_ACTIVE indicates dragged state 1179 | BND_EXPORT NVGcolor bndNodeWireColor(const BNDnodeTheme *theme, BNDwidgetState state); 1180 | 1181 | #ifdef __cplusplus 1182 | }; 1183 | #endif 1184 | 1185 | #endif // BLENDISH_H 1186 | -------------------------------------------------------------------------------- /example.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // based on NanoVG's example code by Mikko Mononen 3 | 4 | #include 5 | #ifdef NANOVG_GLEW 6 | # include 7 | #endif 8 | #ifdef __APPLE__ 9 | # define GLFW_INCLUDE_GLCOREARB 10 | #endif 11 | #include 12 | #include "nanovg.h" 13 | #define NANOVG_GL3_IMPLEMENTATION 14 | #include "nanovg_gl.h" 15 | 16 | #define BLENDISH_IMPLEMENTATION 17 | #include "blendish.h" 18 | 19 | #define OUI_IMPLEMENTATION 20 | #include "oui.h" 21 | 22 | //////////////////////////////////////////////////////////////////////////////// 23 | 24 | typedef enum { 25 | // label 26 | ST_LABEL = 0, 27 | // button 28 | ST_BUTTON = 1, 29 | // radio button 30 | ST_RADIO = 2, 31 | // progress slider 32 | ST_SLIDER = 3, 33 | // column 34 | ST_COLUMN = 4, 35 | // row 36 | ST_ROW = 5, 37 | // check button 38 | ST_CHECK = 6, 39 | // panel 40 | ST_PANEL = 7, 41 | // text 42 | ST_TEXT = 8, 43 | // 44 | ST_IGNORE = 9, 45 | 46 | ST_DEMOSTUFF = 10, 47 | // colored rectangle 48 | ST_RECT = 11, 49 | 50 | ST_HBOX = 12, 51 | ST_VBOX = 13, 52 | } SubType; 53 | 54 | typedef struct { 55 | int subtype; 56 | UIhandler handler; 57 | } UIData; 58 | 59 | typedef struct { 60 | UIData head; 61 | const char *label; 62 | NVGcolor color; 63 | } UIRectData; 64 | 65 | typedef struct { 66 | UIData head; 67 | int iconid; 68 | const char *label; 69 | } UIButtonData; 70 | 71 | typedef struct { 72 | UIData head; 73 | const char *label; 74 | int *option; 75 | } UICheckData; 76 | 77 | typedef struct { 78 | UIData head; 79 | int iconid; 80 | const char *label; 81 | int *value; 82 | } UIRadioData; 83 | 84 | typedef struct { 85 | UIData head; 86 | const char *label; 87 | float *progress; 88 | } UISliderData; 89 | 90 | typedef struct { 91 | UIData head; 92 | char *text; 93 | int maxsize; 94 | } UITextData; 95 | 96 | //////////////////////////////////////////////////////////////////////////////// 97 | 98 | void draw_demostuff(NVGcontext *vg, int x, int y, float w, float h); 99 | 100 | static struct NVGcontext* _vg = NULL; 101 | 102 | void ui_handler(int item, UIevent event) { 103 | UIData *data = (UIData *)uiGetHandle(item); 104 | if (data && data->handler) { 105 | data->handler(item, event); 106 | } 107 | } 108 | 109 | void init(NVGcontext *vg) { 110 | bndSetFont(nvgCreateFont(vg, "system", "../DejaVuSans.ttf")); 111 | bndSetIconImage(nvgCreateImage(vg, "../blender_icons16.png", 0)); 112 | } 113 | 114 | void testrect(NVGcontext *vg, UIrect rect) { 115 | #if 0 116 | nvgBeginPath(vg); 117 | nvgRect(vg,rect.x+0.5,rect.y+0.5,rect.w-1,rect.h-1); 118 | nvgStrokeColor(vg,nvgRGBf(1,0,0)); 119 | nvgStrokeWidth(vg,1); 120 | nvgStroke(vg); 121 | #endif 122 | } 123 | 124 | 125 | void drawUI(NVGcontext *vg, int item, int corners); 126 | 127 | void drawUIItems(NVGcontext *vg, int item, int corners) { 128 | int kid = uiFirstChild(item); 129 | while (kid > 0) { 130 | drawUI(vg, kid, corners); 131 | kid = uiNextSibling(kid); 132 | } 133 | } 134 | 135 | void drawUIItemsHbox(NVGcontext *vg, int item) { 136 | int kid = uiFirstChild(item); 137 | if (kid < 0) return; 138 | int nextkid = uiNextSibling(kid); 139 | if (nextkid < 0) { 140 | drawUI(vg, kid, BND_CORNER_NONE); 141 | } else { 142 | drawUI(vg, kid, BND_CORNER_RIGHT); 143 | kid = nextkid; 144 | while (uiNextSibling(kid) > 0) { 145 | drawUI(vg, kid, BND_CORNER_ALL); 146 | kid = uiNextSibling(kid); 147 | } 148 | drawUI(vg, kid, BND_CORNER_LEFT); 149 | } 150 | } 151 | 152 | void drawUIItemsVbox(NVGcontext *vg, int item) { 153 | int kid = uiFirstChild(item); 154 | if (kid < 0) return; 155 | int nextkid = uiNextSibling(kid); 156 | if (nextkid < 0) { 157 | drawUI(vg, kid, BND_CORNER_NONE); 158 | } else { 159 | drawUI(vg, kid, BND_CORNER_DOWN); 160 | kid = nextkid; 161 | while (uiNextSibling(kid) > 0) { 162 | drawUI(vg, kid, BND_CORNER_ALL); 163 | kid = uiNextSibling(kid); 164 | } 165 | drawUI(vg, kid, BND_CORNER_TOP); 166 | } 167 | } 168 | 169 | void drawUI(NVGcontext *vg, int item, int corners) { 170 | const UIData *head = (const UIData *)uiGetHandle(item); 171 | UIrect rect = uiGetRect(item); 172 | if (uiGetState(item) == UI_FROZEN) { 173 | nvgGlobalAlpha(vg, BND_DISABLED_ALPHA); 174 | } 175 | if (head) { 176 | switch(head->subtype) { 177 | default: { 178 | testrect(vg,rect); 179 | drawUIItems(vg,item,corners); 180 | } break; 181 | case ST_HBOX: { 182 | drawUIItemsHbox(vg, item); 183 | } break; 184 | case ST_VBOX: { 185 | drawUIItemsVbox(vg, item); 186 | } break; 187 | case ST_PANEL: { 188 | bndBevel(vg,rect.x,rect.y,rect.w,rect.h); 189 | drawUIItems(vg,item,corners); 190 | } break; 191 | case ST_LABEL: { 192 | assert(head); 193 | const UIButtonData *data = (UIButtonData*)head; 194 | bndLabel(vg,rect.x,rect.y,rect.w,rect.h, 195 | data->iconid,data->label); 196 | } break; 197 | case ST_BUTTON: { 198 | const UIButtonData *data = (UIButtonData*)head; 199 | bndToolButton(vg,rect.x,rect.y,rect.w,rect.h, 200 | corners,(BNDwidgetState)uiGetState(item), 201 | data->iconid,data->label); 202 | } break; 203 | case ST_CHECK: { 204 | const UICheckData *data = (UICheckData*)head; 205 | BNDwidgetState state = (BNDwidgetState)uiGetState(item); 206 | if (*data->option) 207 | state = BND_ACTIVE; 208 | bndOptionButton(vg,rect.x,rect.y,rect.w,rect.h, state, 209 | data->label); 210 | } break; 211 | case ST_RADIO:{ 212 | const UIRadioData *data = (UIRadioData*)head; 213 | BNDwidgetState state = (BNDwidgetState)uiGetState(item); 214 | if (*data->value == item) 215 | state = BND_ACTIVE; 216 | bndRadioButton(vg,rect.x,rect.y,rect.w,rect.h, 217 | corners,state, 218 | data->iconid,data->label); 219 | } break; 220 | case ST_SLIDER:{ 221 | const UISliderData *data = (UISliderData*)head; 222 | BNDwidgetState state = (BNDwidgetState)uiGetState(item); 223 | static char value[32]; 224 | sprintf(value,"%.0f%%",(*data->progress)*100.0f); 225 | bndSlider(vg,rect.x,rect.y,rect.w,rect.h, 226 | corners,state, 227 | *data->progress,data->label,value); 228 | } break; 229 | case ST_TEXT: { 230 | const UITextData *data = (UITextData*)head; 231 | BNDwidgetState state = (BNDwidgetState)uiGetState(item); 232 | int idx = strlen(data->text); 233 | bndTextField(vg,rect.x,rect.y,rect.w,rect.h, 234 | corners,state, -1, data->text, idx, idx); 235 | } break; 236 | case ST_DEMOSTUFF: { 237 | draw_demostuff(vg, rect.x, rect.y, rect.w, rect.h); 238 | } break; 239 | case ST_RECT: { 240 | const UIRectData *data = (UIRectData*)head; 241 | if (rect.w && rect.h) { 242 | BNDwidgetState state = (BNDwidgetState)uiGetState(item); 243 | nvgSave(vg); 244 | nvgStrokeColor(vg, nvgRGBAf(data->color.r,data->color.g,data->color.b,0.9f)); 245 | if (state != BND_DEFAULT) { 246 | nvgFillColor(vg, nvgRGBAf(data->color.r,data->color.g,data->color.b,0.5f)); 247 | } else { 248 | nvgFillColor(vg, nvgRGBAf(data->color.r,data->color.g,data->color.b,0.1f)); 249 | } 250 | nvgStrokeWidth(vg,2); 251 | nvgBeginPath(vg); 252 | #if 0 253 | nvgRect(vg,rect.x,rect.y,rect.w,rect.h); 254 | #else 255 | nvgRoundedRect(vg,rect.x,rect.y,rect.w,rect.h,3); 256 | #endif 257 | nvgFill(vg); 258 | nvgStroke(vg); 259 | 260 | if (state != BND_DEFAULT) { 261 | nvgFillColor(vg, nvgRGBAf(0.0f,0.0f,0.0f,1.0f)); 262 | nvgFontSize(vg, 15.0f); 263 | nvgBeginPath(vg); 264 | nvgTextAlign(vg, NVG_ALIGN_TOP|NVG_ALIGN_CENTER); 265 | nvgTextBox(vg, rect.x, rect.y+rect.h*0.3f, rect.w, data->label, NULL); 266 | } 267 | 268 | nvgRestore(vg); 269 | } 270 | nvgSave(vg); 271 | nvgIntersectScissor(vg, rect.x, rect.y, rect.w, rect.h); 272 | 273 | drawUIItems(vg,item,corners); 274 | 275 | nvgRestore(vg); 276 | } break; 277 | } 278 | } else { 279 | testrect(vg,rect); 280 | drawUIItems(vg,item,corners); 281 | } 282 | 283 | if (uiGetState(item) == UI_FROZEN) { 284 | nvgGlobalAlpha(vg, 1.0); 285 | } 286 | } 287 | 288 | 289 | int colorrect(const char *label, NVGcolor color) { 290 | int item = uiItem(); 291 | UIRectData *data = (UIRectData *)uiAllocHandle(item, sizeof(UIRectData)); 292 | data->head.subtype = ST_RECT; 293 | data->head.handler = NULL; 294 | data->label = label; 295 | data->color = color; 296 | uiSetEvents(item, UI_BUTTON0_DOWN); 297 | return item; 298 | } 299 | 300 | int label(int iconid, const char *label) { 301 | int item = uiItem(); 302 | uiSetSize(item, 0, BND_WIDGET_HEIGHT); 303 | UIButtonData *data = (UIButtonData *)uiAllocHandle(item, sizeof(UIButtonData)); 304 | data->head.subtype = ST_LABEL; 305 | data->head.handler = NULL; 306 | data->iconid = iconid; 307 | data->label = label; 308 | return item; 309 | } 310 | 311 | void demohandler(int item, UIevent event) { 312 | const UIButtonData *data = (const UIButtonData *)uiGetHandle(item); 313 | printf("clicked: %p %s\n", uiGetHandle(item), data->label); 314 | } 315 | 316 | int button(int iconid, const char *label, UIhandler handler) { 317 | // create new ui item 318 | int item = uiItem(); 319 | // set size of wiget; horizontal size is dynamic, vertical is fixed 320 | uiSetSize(item, 0, BND_WIDGET_HEIGHT); 321 | uiSetEvents(item, UI_BUTTON0_HOT_UP); 322 | // store some custom data with the button that we use for styling 323 | UIButtonData *data = (UIButtonData *)uiAllocHandle(item, sizeof(UIButtonData)); 324 | data->head.subtype = ST_BUTTON; 325 | data->head.handler = handler; 326 | data->iconid = iconid; 327 | data->label = label; 328 | return item; 329 | } 330 | 331 | void checkhandler(int item, UIevent event) { 332 | const UICheckData *data = (const UICheckData *)uiGetHandle(item); 333 | *data->option = !(*data->option); 334 | } 335 | 336 | int check(const char *label, int *option) { 337 | // create new ui item 338 | int item = uiItem(); 339 | // set size of wiget; horizontal size is dynamic, vertical is fixed 340 | uiSetSize(item, 0, BND_WIDGET_HEIGHT); 341 | // attach event handler e.g. demohandler above 342 | uiSetEvents(item, UI_BUTTON0_DOWN); 343 | // store some custom data with the button that we use for styling 344 | UICheckData *data = (UICheckData *)uiAllocHandle(item, sizeof(UICheckData)); 345 | data->head.subtype = ST_CHECK; 346 | data->head.handler = checkhandler; 347 | data->label = label; 348 | data->option = option; 349 | return item; 350 | } 351 | 352 | // simple logic for a slider 353 | 354 | // starting offset of the currently active slider 355 | static float sliderstart = 0.0; 356 | 357 | // event handler for slider (same handler for all sliders) 358 | void sliderhandler(int item, UIevent event) { 359 | // retrieve the custom data we saved with the slider 360 | UISliderData *data = (UISliderData *)uiGetHandle(item); 361 | switch(event) { 362 | default: break; 363 | case UI_BUTTON0_DOWN: { 364 | // button was pressed for the first time; capture initial 365 | // slider value. 366 | sliderstart = *data->progress; 367 | } break; 368 | case UI_BUTTON0_CAPTURE: { 369 | // called for every frame that the button is pressed. 370 | // get the delta between the click point and the current 371 | // mouse position 372 | UIvec2 pos = uiGetCursorStartDelta(); 373 | // get the items layouted rectangle 374 | UIrect rc = uiGetRect(item); 375 | // calculate our new offset and clamp 376 | float value = sliderstart + ((float)pos.x / (float)rc.w); 377 | value = (value<0)?0:(value>1)?1:value; 378 | // assign the new value 379 | *data->progress = value; 380 | } break; 381 | } 382 | } 383 | 384 | int slider(const char *label, float *progress) { 385 | // create new ui item 386 | int item = uiItem(); 387 | // set size of wiget; horizontal size is dynamic, vertical is fixed 388 | uiSetSize(item, 0, BND_WIDGET_HEIGHT); 389 | // attach our slider event handler and capture two classes of events 390 | uiSetEvents(item, UI_BUTTON0_DOWN | UI_BUTTON0_CAPTURE); 391 | // store some custom data with the button that we use for styling 392 | // and logic, e.g. the pointer to the data we want to alter. 393 | UISliderData *data = (UISliderData *)uiAllocHandle(item, sizeof(UISliderData)); 394 | data->head.subtype = ST_SLIDER; 395 | data->head.handler = sliderhandler; 396 | data->label = label; 397 | data->progress = progress; 398 | return item; 399 | } 400 | 401 | void textboxhandler(int item, UIevent event) { 402 | UITextData *data = (UITextData *)uiGetHandle(item); 403 | switch(event) { 404 | default: break; 405 | case UI_BUTTON0_DOWN: { 406 | uiFocus(item); 407 | } break; 408 | case UI_KEY_DOWN: { 409 | unsigned int key = uiGetKey(); 410 | switch(key) { 411 | default: break; 412 | case GLFW_KEY_BACKSPACE: { 413 | int size = strlen(data->text); 414 | if (!size) return; 415 | data->text[size-1] = 0; 416 | } break; 417 | case GLFW_KEY_ENTER: { 418 | uiFocus(-1); 419 | } break; 420 | } 421 | } break; 422 | case UI_CHAR: { 423 | unsigned int key = uiGetKey(); 424 | if ((key > 255)||(key < 32)) return; 425 | int size = strlen(data->text); 426 | if (size >= (data->maxsize-1)) return; 427 | data->text[size] = (char)key; 428 | } break; 429 | } 430 | } 431 | 432 | int textbox(char *text, int maxsize) { 433 | int item = uiItem(); 434 | uiSetSize(item, 0, BND_WIDGET_HEIGHT); 435 | uiSetEvents(item, UI_BUTTON0_DOWN | UI_KEY_DOWN | UI_CHAR); 436 | // store some custom data with the button that we use for styling 437 | // and logic, e.g. the pointer to the data we want to alter. 438 | UITextData *data = (UITextData *)uiAllocHandle(item, sizeof(UITextData)); 439 | data->head.subtype = ST_TEXT; 440 | data->head.handler = textboxhandler; 441 | data->text = text; 442 | data->maxsize = maxsize; 443 | return item; 444 | } 445 | 446 | // simple logic for a radio button 447 | void radiohandler(int item, UIevent event) { 448 | UIRadioData *data = (UIRadioData *)uiGetHandle(item); 449 | *data->value = item; 450 | } 451 | 452 | int radio(int iconid, const char *label, int *value) { 453 | int item = uiItem(); 454 | uiSetSize(item, label?0:BND_TOOL_WIDTH, BND_WIDGET_HEIGHT); 455 | UIRadioData *data = (UIRadioData *)uiAllocHandle(item, sizeof(UIRadioData)); 456 | data->head.subtype = ST_RADIO; 457 | data->head.handler = radiohandler; 458 | data->iconid = iconid; 459 | data->label = label; 460 | data->value = value; 461 | uiSetEvents(item, UI_BUTTON0_DOWN); 462 | return item; 463 | } 464 | 465 | int panel() { 466 | int item = uiItem(); 467 | UIData *data = (UIData *)uiAllocHandle(item, sizeof(UIData)); 468 | data->subtype = ST_PANEL; 469 | data->handler = NULL; 470 | return item; 471 | } 472 | 473 | int hbox() { 474 | int item = uiItem(); 475 | UIData *data = (UIData *)uiAllocHandle(item, sizeof(UIData)); 476 | data->subtype = ST_HBOX; 477 | data->handler = NULL; 478 | uiSetBox(item, UI_ROW); 479 | return item; 480 | } 481 | 482 | 483 | int vbox() { 484 | int item = uiItem(); 485 | UIData *data = (UIData *)uiAllocHandle(item, sizeof(UIData)); 486 | data->subtype = ST_VBOX; 487 | data->handler = NULL; 488 | uiSetBox(item, UI_COLUMN); 489 | return item; 490 | } 491 | 492 | 493 | int column_append(int parent, int item) { 494 | uiInsert(parent, item); 495 | // fill parent horizontally, anchor to previous item vertically 496 | uiSetLayout(item, UI_HFILL); 497 | uiSetMargins(item, 0, 1, 0, 0); 498 | return item; 499 | } 500 | 501 | int column() { 502 | int item = uiItem(); 503 | uiSetBox(item, UI_COLUMN); 504 | return item; 505 | } 506 | 507 | int vgroup_append(int parent, int item) { 508 | uiInsert(parent, item); 509 | // fill parent horizontally, anchor to previous item vertically 510 | uiSetLayout(item, UI_HFILL); 511 | return item; 512 | } 513 | 514 | int vgroup() { 515 | int item = uiItem(); 516 | uiSetBox(item, UI_COLUMN); 517 | return item; 518 | } 519 | 520 | int hgroup_append(int parent, int item) { 521 | uiInsert(parent, item); 522 | uiSetLayout(item, UI_HFILL); 523 | return item; 524 | } 525 | 526 | int hgroup_append_fixed(int parent, int item) { 527 | uiInsert(parent, item); 528 | return item; 529 | } 530 | 531 | int hgroup() { 532 | int item = uiItem(); 533 | uiSetBox(item, UI_ROW); 534 | return item; 535 | } 536 | 537 | int row_append(int parent, int item) { 538 | uiInsert(parent, item); 539 | uiSetLayout(item, UI_HFILL); 540 | return item; 541 | } 542 | 543 | int row() { 544 | int item = uiItem(); 545 | uiSetBox(item, UI_ROW); 546 | return item; 547 | } 548 | 549 | void draw_noodles(NVGcontext *vg, int x, int y) { 550 | int w = 200; 551 | int s = 70; 552 | 553 | bndNodeBackground(vg, x+w, y-50, 100, 200, BND_DEFAULT, BND_ICONID(6,3), 554 | "Default", nvgRGBf(0.392f,0.392f,0.392f)); 555 | bndNodeBackground(vg, x+w+120, y-50, 100, 200, BND_HOVER, BND_ICONID(6,3), 556 | "Hover", nvgRGBf(0.392f,0.392f,0.392f)); 557 | bndNodeBackground(vg, x+w+240, y-50, 100, 200, BND_ACTIVE, BND_ICONID(6,3), 558 | "Active", nvgRGBf(0.392f,0.392f,0.392f)); 559 | 560 | for (int i = 0; i < 9; ++i) { 561 | int a = i%3; 562 | int b = i/3; 563 | bndNodeWire(vg, x, y+s*a, x+w, y+s*b, (BNDwidgetState)a, (BNDwidgetState)b); 564 | } 565 | 566 | bndNodePort(vg, x, y, BND_DEFAULT, nvgRGBf(0.5f, 0.5f, 0.5f)); 567 | bndNodePort(vg, x+w, y, BND_DEFAULT, nvgRGBf(0.5f, 0.5f, 0.5f)); 568 | bndNodePort(vg, x, y+s, BND_HOVER, nvgRGBf(0.5f, 0.5f, 0.5f)); 569 | bndNodePort(vg, x+w, y+s, BND_HOVER, nvgRGBf(0.5f, 0.5f, 0.5f)); 570 | bndNodePort(vg, x, y+2*s, BND_ACTIVE, nvgRGBf(0.5f, 0.5f, 0.5f)); 571 | bndNodePort(vg, x+w, y+2*s, BND_ACTIVE, nvgRGBf(0.5f, 0.5f, 0.5f)); 572 | } 573 | 574 | static void roothandler(int parent, UIevent event) { 575 | switch(event) { 576 | default: break; 577 | case UI_SCROLL: { 578 | UIvec2 pos = uiGetScroll(); 579 | printf("scroll! %d %d\n", pos.x, pos.y); 580 | } break; 581 | case UI_BUTTON0_DOWN: { 582 | printf("%d clicks\n", uiGetClicks()); 583 | } break; 584 | } 585 | } 586 | 587 | void draw_demostuff(NVGcontext *vg, int x, int y, float w, float h) { 588 | nvgSave(vg); 589 | nvgTranslate(vg, x, y); 590 | 591 | bndSplitterWidgets(vg, 0, 0, w, h); 592 | 593 | x = 10; 594 | y = 10; 595 | 596 | bndToolButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT, 597 | BND_ICONID(6,3),"Default"); 598 | y += 25; 599 | bndToolButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER, 600 | BND_ICONID(6,3),"Hovered"); 601 | y += 25; 602 | bndToolButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE, 603 | BND_ICONID(6,3),"Active"); 604 | 605 | y += 40; 606 | bndRadioButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT, 607 | -1,"Default"); 608 | y += 25; 609 | bndRadioButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER, 610 | -1,"Hovered"); 611 | y += 25; 612 | bndRadioButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE, 613 | -1,"Active"); 614 | 615 | y += 25; 616 | bndLabel(vg,x,y,120,BND_WIDGET_HEIGHT,-1,"Label:"); 617 | y += BND_WIDGET_HEIGHT; 618 | bndChoiceButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT, 619 | -1, "Default"); 620 | y += 25; 621 | bndChoiceButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER, 622 | -1, "Hovered"); 623 | y += 25; 624 | bndChoiceButton(vg,x,y,80,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE, 625 | -1, "Active"); 626 | 627 | y += 25; 628 | int ry = y; 629 | int rx = x; 630 | 631 | y = 10; 632 | x += 130; 633 | bndOptionButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_DEFAULT,"Default"); 634 | y += 25; 635 | bndOptionButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_HOVER,"Hovered"); 636 | y += 25; 637 | bndOptionButton(vg,x,y,120,BND_WIDGET_HEIGHT,BND_ACTIVE,"Active"); 638 | 639 | y += 40; 640 | bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_DOWN,BND_DEFAULT, 641 | "Top","100"); 642 | y += BND_WIDGET_HEIGHT-2; 643 | bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_ALL,BND_DEFAULT, 644 | "Center","100"); 645 | y += BND_WIDGET_HEIGHT-2; 646 | bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_TOP,BND_DEFAULT, 647 | "Bottom","100"); 648 | 649 | int mx = x-30; 650 | int my = y-12; 651 | int mw = 120; 652 | bndMenuBackground(vg,mx,my,mw,120,BND_CORNER_TOP); 653 | bndMenuLabel(vg,mx,my,mw,BND_WIDGET_HEIGHT,-1,"Menu Title"); 654 | my += BND_WIDGET_HEIGHT-2; 655 | bndMenuItem(vg,mx,my,mw,BND_WIDGET_HEIGHT,BND_DEFAULT, 656 | BND_ICONID(17,3),"Default"); 657 | my += BND_WIDGET_HEIGHT-2; 658 | bndMenuItem(vg,mx,my,mw,BND_WIDGET_HEIGHT,BND_HOVER, 659 | BND_ICONID(18,3),"Hovered"); 660 | my += BND_WIDGET_HEIGHT-2; 661 | bndMenuItem(vg,mx,my,mw,BND_WIDGET_HEIGHT,BND_ACTIVE, 662 | BND_ICONID(19,3),"Active"); 663 | 664 | y = 10; 665 | x += 130; 666 | int ox = x; 667 | bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT, 668 | "Default","100"); 669 | y += 25; 670 | bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER, 671 | "Hovered","100"); 672 | y += 25; 673 | bndNumberField(vg,x,y,120,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE, 674 | "Active","100"); 675 | 676 | y += 40; 677 | bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_RIGHT,BND_DEFAULT, 678 | -1,"One"); 679 | x += 60-1; 680 | bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_ALL,BND_DEFAULT, 681 | -1,"Two"); 682 | x += 60-1; 683 | bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_ALL,BND_DEFAULT, 684 | -1,"Three"); 685 | x += 60-1; 686 | bndRadioButton(vg,x,y,60,BND_WIDGET_HEIGHT,BND_CORNER_LEFT,BND_ACTIVE, 687 | -1,"Butts"); 688 | 689 | x = ox; 690 | y += 40; 691 | float progress_value = fmodf(glfwGetTime()/10.0,1.0); 692 | char progress_label[32]; 693 | sprintf(progress_label, "%d%%", int(progress_value*100+0.5f)); 694 | bndSlider(vg,x,y,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT, 695 | progress_value,"Default",progress_label); 696 | y += 25; 697 | bndSlider(vg,x,y,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER, 698 | progress_value,"Hovered",progress_label); 699 | y += 25; 700 | bndSlider(vg,x,y,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE, 701 | progress_value,"Active",progress_label); 702 | 703 | int rw = x+240-rx; 704 | float s_offset = sinf(glfwGetTime()/2.0)*0.5+0.5; 705 | float s_size = cosf(glfwGetTime()/3.11)*0.5+0.5; 706 | 707 | bndScrollBar(vg,rx,ry,rw,BND_SCROLLBAR_HEIGHT,BND_DEFAULT,s_offset,s_size); 708 | ry += 20; 709 | bndScrollBar(vg,rx,ry,rw,BND_SCROLLBAR_HEIGHT,BND_HOVER,s_offset,s_size); 710 | ry += 20; 711 | bndScrollBar(vg,rx,ry,rw,BND_SCROLLBAR_HEIGHT,BND_ACTIVE,s_offset,s_size); 712 | 713 | const char edit_text[] = "The quick brown fox"; 714 | int textlen = strlen(edit_text)+1; 715 | int t = int(glfwGetTime()*2); 716 | int idx1 = (t/textlen)%textlen; 717 | int idx2 = idx1 + (t%(textlen-idx1)); 718 | 719 | ry += 25; 720 | bndTextField(vg,rx,ry,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_DEFAULT, 721 | -1, edit_text, idx1, idx2); 722 | ry += 25; 723 | bndTextField(vg,rx,ry,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_HOVER, 724 | -1, edit_text, idx1, idx2); 725 | ry += 25; 726 | bndTextField(vg,rx,ry,240,BND_WIDGET_HEIGHT,BND_CORNER_NONE,BND_ACTIVE, 727 | -1, edit_text, idx1, idx2); 728 | 729 | draw_noodles(vg, 20, ry+50); 730 | 731 | rx += rw + 20; 732 | ry = 10; 733 | bndScrollBar(vg,rx,ry,BND_SCROLLBAR_WIDTH,240,BND_DEFAULT,s_offset,s_size); 734 | rx += 20; 735 | bndScrollBar(vg,rx,ry,BND_SCROLLBAR_WIDTH,240,BND_HOVER,s_offset,s_size); 736 | rx += 20; 737 | bndScrollBar(vg,rx,ry,BND_SCROLLBAR_WIDTH,240,BND_ACTIVE,s_offset,s_size); 738 | 739 | x = ox; 740 | y += 40; 741 | bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_RIGHT, 742 | BND_DEFAULT,BND_ICONID(0,10),NULL); 743 | x += BND_TOOL_WIDTH-1; 744 | bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL, 745 | BND_DEFAULT,BND_ICONID(1,10),NULL); 746 | x += BND_TOOL_WIDTH-1; 747 | bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL, 748 | BND_DEFAULT,BND_ICONID(2,10),NULL); 749 | x += BND_TOOL_WIDTH-1; 750 | bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL, 751 | BND_DEFAULT,BND_ICONID(3,10),NULL); 752 | x += BND_TOOL_WIDTH-1; 753 | bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL, 754 | BND_DEFAULT,BND_ICONID(4,10),NULL); 755 | x += BND_TOOL_WIDTH-1; 756 | bndToolButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_LEFT, 757 | BND_DEFAULT,BND_ICONID(5,10),NULL); 758 | x += BND_TOOL_WIDTH-1; 759 | x += 5; 760 | bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_RIGHT, 761 | BND_DEFAULT,BND_ICONID(0,11),NULL); 762 | x += BND_TOOL_WIDTH-1; 763 | bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL, 764 | BND_DEFAULT,BND_ICONID(1,11),NULL); 765 | x += BND_TOOL_WIDTH-1; 766 | bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL, 767 | BND_DEFAULT,BND_ICONID(2,11),NULL); 768 | x += BND_TOOL_WIDTH-1; 769 | bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL, 770 | BND_DEFAULT,BND_ICONID(3,11),NULL); 771 | x += BND_TOOL_WIDTH-1; 772 | bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_ALL, 773 | BND_ACTIVE,BND_ICONID(4,11),NULL); 774 | x += BND_TOOL_WIDTH-1; 775 | bndRadioButton(vg,x,y,BND_TOOL_WIDTH,BND_WIDGET_HEIGHT,BND_CORNER_LEFT, 776 | BND_DEFAULT,BND_ICONID(5,11),NULL); 777 | 778 | nvgRestore(vg); 779 | } 780 | 781 | static int enum1 = -1; 782 | 783 | void build_democontent(int parent) { 784 | // some persistent variables for demonstration 785 | static float progress1 = 0.25f; 786 | static float progress2 = 0.75f; 787 | static int option1 = 1; 788 | static int option2 = 0; 789 | static int option3 = 0; 790 | 791 | int col = column(); 792 | uiInsert(parent, col); 793 | uiSetMargins(col, 10, 10, 10, 10); 794 | uiSetLayout(col, UI_TOP|UI_HFILL); 795 | 796 | column_append(col, button(BND_ICON_GHOST, "Item 1", demohandler)); 797 | if (option3) 798 | column_append(col, button(BND_ICON_GHOST, "Item 2", demohandler)); 799 | 800 | { 801 | int h = column_append(col, hbox()); 802 | hgroup_append(h, radio(BND_ICON_GHOST, "Item 3.0", &enum1)); 803 | if (option2) 804 | uiSetMargins(hgroup_append_fixed(h, radio(BND_ICON_REC, NULL, &enum1)), -1,0,0,0); 805 | uiSetMargins(hgroup_append_fixed(h, radio(BND_ICON_PLAY, NULL, &enum1)), -1,0,0,0); 806 | uiSetMargins(hgroup_append(h, radio(BND_ICON_GHOST, "Item 3.3", &enum1)), -1,0,0,0); 807 | } 808 | 809 | { 810 | int rows = column_append(col, row()); 811 | int coll = row_append(rows, vgroup()); 812 | vgroup_append(coll, label(-1, "Items 4.0:")); 813 | coll = vgroup_append(coll, vbox()); 814 | vgroup_append(coll, button(BND_ICON_GHOST, "Item 4.0.0", demohandler)); 815 | uiSetMargins(vgroup_append(coll, button(BND_ICON_GHOST, "Item 4.0.1", demohandler)),0,-2,0,0); 816 | int colr = row_append(rows, vgroup()); 817 | uiSetMargins(colr, 8, 0, 0, 0); 818 | uiSetFrozen(colr, option1); 819 | vgroup_append(colr, label(-1, "Items 4.1:")); 820 | colr = vgroup_append(colr, vbox()); 821 | vgroup_append(colr, slider("Item 4.1.0", &progress1)); 822 | uiSetMargins(vgroup_append(colr, slider("Item 4.1.1", &progress2)),0,-2,0,0); 823 | } 824 | 825 | column_append(col, button(BND_ICON_GHOST, "Item 5", NULL)); 826 | 827 | static char textbuffer[1024] = "The quick brown fox."; 828 | column_append(col, textbox(textbuffer, 1024)); 829 | 830 | column_append(col, check("Frozen", &option1)); 831 | column_append(col, check("Item 7", &option2)); 832 | column_append(col, check("Item 8", &option3)); 833 | } 834 | 835 | int demorect(int parent, const char *label, float hue, int box, int layout, int w, int h, int m1, int m2, int m3, int m4) { 836 | int item = colorrect(label, nvgHSL(hue, 1.0f, 0.8f)); 837 | uiSetLayout(item, layout); 838 | uiSetBox(item, box); 839 | uiSetMargins(item, m1, m2, m3, m4); 840 | uiSetSize(item, w, h); 841 | uiInsert(parent, item); 842 | return item; 843 | } 844 | 845 | void build_layoutdemo(int parent) { 846 | const int M = 10; 847 | const int S = 150; 848 | 849 | int box = demorect(parent, "Box( UI_LAYOUT )\nLayout( UI_FILL )", 0.6f, UI_LAYOUT, UI_FILL, 0, 0, M, M, M, M); 850 | demorect(box, "Layout( UI_HFILL | UI_TOP )", 0.7f, 0, UI_HFILL|UI_TOP, S, S+M, M, M, M, 0); 851 | demorect(box, "Layout( UI_HFILL )", 0.7f, 0, UI_HFILL, S, S+2*M, M, 0, M, 0); 852 | demorect(box, "Layout( UI_HFILL | UI_DOWN )", 0.7f, 0, UI_HFILL|UI_DOWN, S, S+M, M, 0, M, M); 853 | 854 | demorect(box, "Layout( UI_LEFT | UI_VFILL )", 0.7f, 0, UI_LEFT|UI_VFILL, S+M, S, M, M, 0, M); 855 | demorect(box, "Layout( UI_VFILL )", 0.7f, 0, UI_VFILL, S+2*M, S, 0, M, 0, M); 856 | demorect(box, "Layout( UI_RIGHT | UI_VFILL )", 0.7f, 0, UI_RIGHT|UI_VFILL, S+M, S, 0, M, M, M); 857 | 858 | demorect(box, "Layout( UI_LEFT | UI_TOP )", 0.55f, 0, UI_LEFT|UI_TOP, S, S, M, M, 0, 0); 859 | demorect(box, "Layout( UI_TOP )", 0.57f, 0, UI_TOP, S, S, 0, M, 0, 0); 860 | demorect(box, "Layout( UI_RIGHT | UI_TOP )", 0.55f, 0, UI_RIGHT|UI_TOP, S, S, 0, M, M, 0); 861 | demorect(box, "Layout( UI_LEFT )", 0.57f, 0, UI_LEFT, S, S, M, 0, 0, 0); 862 | demorect(box, "Layout( UI_CENTER )", 0.59f, 0, UI_CENTER, S, S, 0, 0, 0, 0); 863 | demorect(box, "Layout( UI_RIGHT )", 0.57f, 0, UI_RIGHT, S, S, 0, 0, M, 0); 864 | demorect(box, "Layout( UI_LEFT | UI_DOWN )", 0.55f, 0, UI_LEFT|UI_DOWN, S, S, M, 0, 0, M); 865 | demorect(box, "Layout( UI_DOWN)", 0.57f, 0, UI_DOWN, S, S, 0, 0, 0, M); 866 | demorect(box, "Layout( UI_RIGHT | UI_DOWN )", 0.55f, 0, UI_RIGHT|UI_DOWN, S, S, 0, 0, M, M); 867 | } 868 | 869 | void build_rowdemo(int parent) { 870 | uiSetBox(parent, UI_COLUMN); 871 | 872 | const int M = 10; 873 | const int S = 200; 874 | const int T = 100; 875 | 876 | { 877 | int box = demorect(parent, "Box( UI_ROW )\nLayout( UI_LEFT | UI_VFILL )", 0.6f, UI_ROW, UI_LEFT|UI_VFILL, 0, S, M, M, M, M); 878 | 879 | demorect(box, "Layout( UI_TOP )", 0.05f, 0, UI_TOP, T, T, M, M, M, 0); 880 | demorect(box, "Layout( UI_VCENTER )", 0.1f, 0, UI_VCENTER, T, T, 0, 0, M, 0); 881 | demorect(box, "Layout( UI_VFILL )", 0.15f, 0, UI_VFILL, T, T, 0, M, M, M); 882 | demorect(box, "Layout( UI_DOWN )", 0.25f, 0, UI_DOWN, T, T, 0, 0, M, M); 883 | } 884 | { 885 | int box = demorect(parent, "Box( UI_ROW | UI_JUSTIFY )\nLayout( UI_FILL )", 0.6f, UI_ROW|UI_JUSTIFY, UI_FILL, 0, S, M, 0, M, M); 886 | 887 | demorect(box, "Layout( UI_TOP )", 0.05f, 0, UI_TOP, T, T, M, M, M, 0); 888 | demorect(box, "Layout( UI_VCENTER )", 0.1f, 0, UI_VCENTER, T, T, 0, 0, M, 0); 889 | demorect(box, "Layout( UI_VFILL )", 0.15f, 0, UI_VFILL, T, T, 0, M, M, M); 890 | demorect(box, "Layout( UI_DOWN )", 0.25f, 0, UI_DOWN, T, T, 0, 0, M, M); 891 | } 892 | { 893 | int box = demorect(parent, "Box( UI_ROW )\nLayout( UI_FILL )", 0.6f, UI_ROW, UI_FILL, 0, S, M, 0, M, M); 894 | 895 | demorect(box, "Layout( UI_TOP )", 0.05f, 0, UI_TOP, T, T, M, M, M, 0); 896 | demorect(box, "Layout( UI_VCENTER )", 0.1f, 0, UI_VCENTER, T, T, 0, 0, M, 0); 897 | demorect(box, "Layout( UI_VFILL )", 0.15f, 0, UI_VFILL, T, T, 0, M, M, M); 898 | demorect(box, "Layout( UI_HFILL )", 0.2f, 0, UI_HFILL, T, T, 0, 0, M, 0); 899 | demorect(box, "Layout( UI_HFILL )", 0.2f, 0, UI_HFILL, T, T, 0, 0, M, 0); 900 | demorect(box, "Layout( UI_HFILL )", 0.2f, 0, UI_HFILL, T, T, 0, 0, M, 0); 901 | demorect(box, "Layout( UI_DOWN )", 0.25f, 0, UI_DOWN, T, T, 0, 0, M, M); 902 | } 903 | } 904 | 905 | void build_columndemo(int parent) { 906 | uiSetBox(parent, UI_ROW); 907 | 908 | const int M = 10; 909 | const int S = 200; 910 | const int T = 100; 911 | 912 | { 913 | int box = demorect(parent, "Box( UI_COLUMN )\nLayout( UI_TOP | UI_HFILL )", 0.6f, UI_COLUMN, UI_TOP|UI_HFILL, S, 0, M, M, M, M); 914 | 915 | demorect(box, "Layout( UI_LEFT )", 0.05f, 0, UI_LEFT, T, T, M, M, 0, M); 916 | demorect(box, "Layout( UI_HCENTER )", 0.1f, 0, UI_HCENTER, T, T, 0, 0, 0, M); 917 | demorect(box, "Layout( UI_HFILL )", 0.15f, 0, UI_HFILL, T, T, M, 0, M, M); 918 | demorect(box, "Layout( UI_RIGHT )", 0.25f, 0, UI_RIGHT, T, T, 0, 0, M, M); 919 | } 920 | { 921 | int box = demorect(parent, "Box( UI_COLUMN )\nLayout( UI_FILL )", 0.6f, UI_COLUMN, UI_FILL, S, 0, 0, M, M, M); 922 | 923 | demorect(box, "Layout( UI_LEFT )", 0.05f, 0, UI_LEFT, T, T, M, M, 0, M); 924 | demorect(box, "Layout( UI_HCENTER )", 0.1f, 0, UI_HCENTER, T, T, 0, 0, 0, M); 925 | demorect(box, "Layout( UI_HFILL )", 0.15f, 0, UI_HFILL, T, T, M, 0, M, M); 926 | demorect(box, "Layout( UI_RIGHT )", 0.25f, 0, UI_RIGHT, T, T, 0, 0, M, M); 927 | } 928 | { 929 | int box = demorect(parent, "Box( UI_COLUMN )\nLayout( UI_FILL )", 0.6f, UI_COLUMN, UI_FILL, S, 0, 0, M, M, M); 930 | 931 | demorect(box, "Layout( UI_LEFT )", 0.05f, 0, UI_LEFT, T, T, M, M, 0, M); 932 | demorect(box, "Layout( UI_HCENTER )", 0.1f, 0, UI_HCENTER, T, T, 0, 0, 0, M); 933 | demorect(box, "Layout( UI_HFILL )", 0.15f, 0, UI_HFILL, T, T, M, 0, M, M); 934 | demorect(box, "Layout( UI_VFILL )", 0.2f, 0, UI_VFILL, T, T, 0, 0, 0, M); 935 | demorect(box, "Layout( UI_VFILL )", 0.2f, 0, UI_VFILL, T, T, 0, 0, 0, M); 936 | demorect(box, "Layout( UI_VFILL )", 0.2f, 0, UI_VFILL, T, T, 0, 0, 0, M); 937 | demorect(box, "Layout( UI_RIGHT )", 0.25f, 0, UI_RIGHT, T, T, 0, 0, M, M); 938 | } 939 | } 940 | 941 | void fill_wrap_row_box(int box) { 942 | const int M = 5; 943 | const int S = 100; 944 | const int T = 50; 945 | 946 | srand(303); 947 | for (int i = 0; i < 20; ++i) { 948 | float hue = (float)(rand()%360)/360.0f; 949 | int width = 10 + (rand()%5)*10; 950 | 951 | int u; 952 | switch(rand()%4) { 953 | default: break; 954 | case 0: { 955 | u = demorect(box, "Layout( UI_TOP )", 956 | hue, 0, UI_TOP, width, T, M, M, M, M); 957 | } break; 958 | case 1: { 959 | u = demorect(box, "Layout( UI_VCENTER )", 960 | hue, 0, UI_VCENTER, width, T/2, M, M, M, M); 961 | } break; 962 | case 2: { 963 | u = demorect(box, "Layout( UI_VFILL )", 964 | hue, 0, UI_VFILL, width, T, M, M, M, M); 965 | } break; 966 | case 3: { 967 | u = demorect(box, "Layout( UI_DOWN )", 968 | hue, 0, UI_DOWN, width, T/2, M, M, M, M); 969 | } break; 970 | } 971 | 972 | if (rand()%10 == 0) 973 | uiSetLayout(u, uiGetLayout(u)|UI_BREAK); 974 | 975 | } 976 | 977 | } 978 | 979 | void fill_wrap_column_box(int box) { 980 | const int M = 5; 981 | const int S = 100; 982 | const int T = 50; 983 | 984 | srand(303); 985 | for (int i = 0; i < 20; ++i) { 986 | float hue = (float)(rand()%360)/360.0f; 987 | int height = 10 + (rand()%5)*10; 988 | 989 | int u; 990 | switch(rand()%4) { 991 | default: break; 992 | case 0: { 993 | u = demorect(box, "Layout( UI_LEFT )", 994 | hue, 0, UI_LEFT, T, height, M, M, M, M); 995 | } break; 996 | case 1: { 997 | u = demorect(box, "Layout( UI_HCENTER )", 998 | hue, 0, UI_HCENTER, T/2, height, M, M, M, M); 999 | } break; 1000 | case 2: { 1001 | u = demorect(box, "Layout( UI_HFILL )", 1002 | hue, 0, UI_HFILL, T, height, M, M, M, M); 1003 | } break; 1004 | case 3: { 1005 | u = demorect(box, "Layout( UI_RIGHT )", 1006 | hue, 0, UI_RIGHT, T/2, height, M, M, M, M); 1007 | } break; 1008 | } 1009 | 1010 | if (rand()%10 == 0) 1011 | uiSetLayout(u, uiGetLayout(u)|UI_BREAK); 1012 | } 1013 | 1014 | } 1015 | 1016 | void build_wrapdemo(int parent) { 1017 | int col = uiItem(); 1018 | uiInsert(parent, col); 1019 | uiSetBox(col, UI_COLUMN); 1020 | uiSetLayout(col, UI_FILL); 1021 | 1022 | const int M = 5; 1023 | const int S = 100; 1024 | const int T = 50; 1025 | 1026 | int box; 1027 | box = demorect(col, "Box( UI_ROW | UI_WRAP | UI_START )\nLayout( UI_HFILL | UI_TOP )", 1028 | 0.6f, UI_ROW | UI_WRAP | UI_START, UI_TOP, 0, 0, M, M, M, M); 1029 | fill_wrap_row_box(box); 1030 | 1031 | box = demorect(col, "Box( UI_ROW | UI_WRAP | UI_MIDDLE )\nLayout( UI_HFILL | UI_TOP )", 1032 | 0.6f, UI_ROW | UI_WRAP, UI_HFILL | UI_TOP, 0, 0, M, M, M, M); 1033 | fill_wrap_row_box(box); 1034 | 1035 | box = demorect(col, "Box( UI_ROW | UI_WRAP | UI_END )\nLayout( UI_HFILL | UI_TOP )", 1036 | 0.6f, UI_ROW | UI_WRAP | UI_END, UI_HFILL | UI_TOP, 0, 0, M, M, M, M); 1037 | fill_wrap_row_box(box); 1038 | 1039 | box = demorect(col, "Box( UI_ROW | UI_WRAP | UI_JUSTIFY )\nLayout( UI_HFILL | UI_TOP )", 1040 | 0.6f, UI_ROW | UI_WRAP | UI_JUSTIFY, UI_HFILL | UI_TOP, 0, 0, M, M, M, M); 1041 | fill_wrap_row_box(box); 1042 | 1043 | box = demorect(col, "Box( UI_COLUMN | UI_WRAP | UI_START )\nLayout( UI_LEFT | UI_VFILL )", 1044 | 0.6f, UI_COLUMN | UI_WRAP | UI_START, UI_LEFT | UI_VFILL, 0, 0, M, M, M, M); 1045 | fill_wrap_column_box(box); 1046 | } 1047 | 1048 | 1049 | int add_menu_option(int parent, const char *name, int *choice) { 1050 | int opt = radio(-1, name, choice); 1051 | uiInsert(parent, opt); 1052 | uiSetLayout(opt, UI_HFILL|UI_TOP); 1053 | uiSetMargins(opt, 1, 1, 1, 1); 1054 | return opt; 1055 | } 1056 | 1057 | void draw(NVGcontext *vg, float w, float h) { 1058 | bndBackground(vg, 0, 0, w, h); 1059 | 1060 | // some OUI stuff 1061 | 1062 | uiBeginLayout(); 1063 | 1064 | int root = panel(); 1065 | // position root element 1066 | uiSetSize(0,w,h); 1067 | ((UIData*)uiGetHandle(root))->handler = roothandler; 1068 | uiSetEvents(root, UI_SCROLL|UI_BUTTON0_DOWN); 1069 | uiSetBox(root, UI_COLUMN); 1070 | 1071 | static int choice = -1; 1072 | 1073 | int menu = uiItem(); 1074 | uiSetLayout(menu, UI_HFILL|UI_TOP); 1075 | uiSetBox(menu, UI_ROW); 1076 | uiInsert(root, menu); 1077 | 1078 | int opt_blendish_demo = add_menu_option(menu, "Blendish Demo", &choice); 1079 | int opt_oui_demo = add_menu_option(menu, "OUI Demo", &choice); 1080 | int opt_layouts = add_menu_option(menu, "UI_LAYOUT", &choice); 1081 | int opt_row = add_menu_option(menu, "UI_ROW", &choice); 1082 | int opt_column = add_menu_option(menu, "UI_COLUMN", &choice); 1083 | int opt_wrap = add_menu_option(menu, "UI_WRAP", &choice); 1084 | if (choice < 0) 1085 | choice = opt_blendish_demo; 1086 | 1087 | int content = uiItem(); 1088 | uiSetLayout(content, UI_FILL); 1089 | uiInsert(root, content); 1090 | 1091 | if (choice == opt_blendish_demo) { 1092 | int democontent = uiItem(); 1093 | uiSetLayout(democontent, UI_FILL); 1094 | uiInsert(content, democontent); 1095 | 1096 | UIData *data = (UIData *)uiAllocHandle(democontent, sizeof(UIData)); 1097 | data->handler = 0; 1098 | data->subtype = ST_DEMOSTUFF; 1099 | } else if (choice == opt_oui_demo) { 1100 | int democontent = uiItem(); 1101 | uiSetLayout(democontent, UI_TOP); 1102 | uiSetSize(democontent, 250, 0); 1103 | uiInsert(content, democontent); 1104 | 1105 | build_democontent(democontent); 1106 | } else if (choice == opt_layouts) { 1107 | build_layoutdemo(content); 1108 | } else if (choice == opt_row) { 1109 | build_rowdemo(content); 1110 | } else if (choice == opt_column) { 1111 | build_columndemo(content); 1112 | } else if (choice == opt_wrap) { 1113 | build_wrapdemo(content); 1114 | } 1115 | 1116 | uiEndLayout(); 1117 | 1118 | drawUI(vg, 0, BND_CORNER_NONE); 1119 | 1120 | #if 0 1121 | for (int i = 0; i < uiGetLastItemCount(); ++i) { 1122 | if (uiRecoverItem(i) == -1) { 1123 | UIitem *pitem = uiLastItemPtr(i); 1124 | nvgBeginPath(vg); 1125 | nvgRect(vg,pitem->margins[0],pitem->margins[1],pitem->size[0],pitem->size[1]); 1126 | nvgStrokeWidth(vg, 2); 1127 | nvgStrokeColor(vg, nvgRGBAf(1.0f,0.0f,0.0f,0.5f)); 1128 | nvgStroke(vg); 1129 | } 1130 | } 1131 | #endif 1132 | 1133 | if (choice == opt_blendish_demo) { 1134 | UIvec2 cursor = uiGetCursor(); 1135 | cursor.x -= w/2; 1136 | cursor.y -= h/2; 1137 | if (abs(cursor.x) > (w/3)) { 1138 | bndJoinAreaOverlay(vg, 0, 0, w, h, 0, (cursor.x > 0)); 1139 | } else if (abs(cursor.y) > (h/3)) { 1140 | bndJoinAreaOverlay(vg, 0, 0, w, h, 1, (cursor.y > 0)); 1141 | } 1142 | } 1143 | 1144 | uiProcess((int)(glfwGetTime()*1000.0)); 1145 | } 1146 | 1147 | //////////////////////////////////////////////////////////////////////////////// 1148 | 1149 | void errorcb(int error, const char* desc) 1150 | { 1151 | printf("GLFW error %d: %s\n", error, desc); 1152 | } 1153 | 1154 | static void mousebutton(GLFWwindow *window, int button, int action, int mods) { 1155 | NVG_NOTUSED(window); 1156 | switch(button) { 1157 | case 1: button = 2; break; 1158 | case 2: button = 1; break; 1159 | } 1160 | uiSetButton(button, mods, (action==GLFW_PRESS)?1:0); 1161 | } 1162 | 1163 | static void cursorpos(GLFWwindow *window, double x, double y) { 1164 | NVG_NOTUSED(window); 1165 | uiSetCursor((int)x,(int)y); 1166 | } 1167 | 1168 | static void scrollevent(GLFWwindow *window, double x, double y) { 1169 | NVG_NOTUSED(window); 1170 | uiSetScroll((int)x, (int)y); 1171 | } 1172 | 1173 | static void charevent(GLFWwindow *window, unsigned int value) { 1174 | NVG_NOTUSED(window); 1175 | uiSetChar(value); 1176 | } 1177 | 1178 | static void key(GLFWwindow* window, int key, int scancode, int action, int mods) 1179 | { 1180 | NVG_NOTUSED(scancode); 1181 | if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) 1182 | glfwSetWindowShouldClose(window, GL_TRUE); 1183 | uiSetKey(key, mods, action); 1184 | } 1185 | 1186 | int main() 1187 | { 1188 | GLFWwindow* window; 1189 | UIcontext *uictx; 1190 | 1191 | uictx = uiCreateContext(4096, 1<<20); 1192 | uiMakeCurrent(uictx); 1193 | uiSetHandler(ui_handler); 1194 | 1195 | if (!glfwInit()) { 1196 | printf("Failed to init GLFW."); 1197 | return -1; 1198 | } 1199 | 1200 | glfwSetErrorCallback(errorcb); 1201 | #ifndef _WIN32 // don't require this on win32, and works with more cards 1202 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 1203 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); 1204 | glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); 1205 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 1206 | #endif 1207 | glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, 1); 1208 | 1209 | window = glfwCreateWindow(650, 650, "OUI Blendish Demo", NULL, NULL); 1210 | if (!window) { 1211 | glfwTerminate(); 1212 | return -1; 1213 | } 1214 | 1215 | glfwSetKeyCallback(window, key); 1216 | glfwSetCharCallback(window, charevent); 1217 | glfwSetCursorPosCallback(window, cursorpos); 1218 | glfwSetMouseButtonCallback(window, mousebutton); 1219 | glfwSetScrollCallback(window, scrollevent); 1220 | 1221 | glfwMakeContextCurrent(window); 1222 | #ifdef NANOVG_GLEW 1223 | glewExperimental = GL_TRUE; 1224 | if(glewInit() != GLEW_OK) { 1225 | printf("Could not init glew.\n"); 1226 | return -1; 1227 | } 1228 | // GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here. 1229 | glGetError(); 1230 | #endif 1231 | 1232 | //_vg = nvgCreateGL3(NVG_ANTIALIAS | NVG_STENCIL_STROKES); 1233 | _vg = nvgCreateGL3(NVG_ANTIALIAS); 1234 | if (_vg == NULL) { 1235 | printf("Could not init nanovg.\n"); 1236 | return -1; 1237 | } 1238 | 1239 | init(_vg); 1240 | 1241 | printf("sizeof(UIitem)=%lu\n", sizeof(UIitem)); 1242 | 1243 | glfwSwapInterval(0); 1244 | 1245 | glfwSetTime(0); 1246 | 1247 | double c = 0.0; 1248 | int total = 0; 1249 | 1250 | int peak_items = 0; 1251 | unsigned int peak_alloc = 0; 1252 | 1253 | while (!glfwWindowShouldClose(window)) 1254 | { 1255 | double mx, my; 1256 | int winWidth, winHeight; 1257 | int fbWidth, fbHeight; 1258 | float pxRatio; 1259 | 1260 | glfwGetCursorPos(window, &mx, &my); 1261 | glfwGetWindowSize(window, &winWidth, &winHeight); 1262 | glfwGetFramebufferSize(window, &fbWidth, &fbHeight); 1263 | // Calculate pixel ration for hi-dpi devices. 1264 | pxRatio = (float)fbWidth / (float)winWidth; 1265 | 1266 | // Update and render 1267 | glViewport(0, 0, fbWidth, fbHeight); 1268 | glClearColor(0,0,0,1); 1269 | glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); 1270 | 1271 | double t = glfwGetTime(); 1272 | nvgBeginFrame(_vg, winWidth, winHeight, pxRatio); 1273 | 1274 | draw(_vg, winWidth, winHeight); 1275 | peak_items = (peak_items > uiGetItemCount())?peak_items:uiGetItemCount(); 1276 | peak_alloc = (peak_alloc > uiGetAllocSize())?peak_alloc:uiGetAllocSize(); 1277 | 1278 | nvgEndFrame(_vg); 1279 | double t2 = glfwGetTime(); 1280 | c += (t2 - t); 1281 | total++; 1282 | if (total > (1*60)) { 1283 | printf("%fms\n", (c / (double)total)*1000.0); 1284 | total = 0; 1285 | c = 0.0; 1286 | } 1287 | 1288 | glfwSwapBuffers(window); 1289 | glfwPollEvents(); 1290 | } 1291 | printf("Peak item count: %i (%lu bytes)\nPeak allocated handles: %u bytes\n", 1292 | peak_items, peak_items * sizeof(UIitem), peak_alloc); 1293 | 1294 | uiDestroyContext(uictx); 1295 | 1296 | nvgDeleteGL3(_vg); 1297 | 1298 | glfwTerminate(); 1299 | return 0; 1300 | } 1301 | -------------------------------------------------------------------------------- /premake4.lua: -------------------------------------------------------------------------------- 1 | 2 | local action = _ACTION or "" 3 | 4 | solution "blendish" 5 | location ( "build" ) 6 | configurations { "Debug", "Release" } 7 | platforms {"native", "x64", "x32"} 8 | 9 | project "example" 10 | kind "ConsoleApp" 11 | language "C++" 12 | files { "example.cpp", "nanovg/src/nanovg.c" } 13 | includedirs { "nanovg/src" } 14 | targetdir("build") 15 | 16 | configuration { "linux" } 17 | linkoptions { "`pkg-config --libs glfw3 --static`" } 18 | links { "GL", "GLU", "m", "GLEW" } 19 | defines { "NANOVG_GLEW" } 20 | 21 | configuration { "windows" } 22 | links { "glfw3", "gdi32", "winmm", "user32", "GLEW", "glu32","opengl32" } 23 | defines { "NANOVG_GLEW" } 24 | 25 | configuration { "macosx" } 26 | links { "glfw3" } 27 | linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo" } 28 | 29 | configuration "Debug" 30 | defines { "DEBUG" } 31 | flags { "Symbols", "ExtraWarnings"} 32 | 33 | configuration "Release" 34 | defines { "NDEBUG" } 35 | flags { "Optimize", "ExtraWarnings"} 36 | 37 | --------------------------------------------------------------------------------