├── .gitignore ├── README.md ├── auto_image_loading_example.py ├── button_theming_test.py ├── camera_window_test.py ├── colour_picker_test.py ├── data ├── __init__.py ├── fonts │ ├── Amiri-Regular.ttf │ ├── KosugiMaru-Regular.ttf │ ├── MaShanZheng-Regular.ttf │ ├── Montserrat-Bold.ttf │ ├── Montserrat-BoldItalic.ttf │ ├── Montserrat-Italic.ttf │ ├── Montserrat-LICENSE.txt │ ├── Montserrat-Regular.ttf │ ├── NotoRashiHebrew-Regular.ttf │ ├── NotoSerifGeorgian-Regular.ttf │ ├── PermanentMarker-Regular.ttf │ ├── SongMyung-Regular.ttf │ └── __init__.py ├── guiopedia │ ├── aliens.html │ ├── cats.html │ ├── gravel.html │ └── index.html ├── images │ ├── __init__.py │ ├── home_icon.png │ ├── measure.png │ ├── space │ │ ├── __init__.py │ │ ├── space_1.jpg │ │ ├── space_10.jpg │ │ ├── space_11.jpg │ │ ├── space_12.jpg │ │ ├── space_13.jpg │ │ ├── space_14.jpg │ │ ├── space_15.jpg │ │ ├── space_16.jpg │ │ ├── space_2.jpg │ │ ├── space_3.jpg │ │ ├── space_4.jpg │ │ ├── space_5.jpg │ │ ├── space_6.jpg │ │ ├── space_7.jpg │ │ ├── space_8.jpg │ │ └── space_9.jpg │ ├── splat.bmp │ ├── splat.png │ ├── test_emoji.png │ └── test_images │ │ ├── field_of_gold.jpg │ │ ├── london.jpg │ │ └── paris.jpg ├── themes │ ├── __init__.py │ ├── button_theming_test_theme.json │ ├── camera_theme.json │ ├── colour_picker_app_theme.json │ ├── console_theme.json │ ├── documentation_theme.json │ ├── embedded_images_theme.json │ ├── guiopedia_theme.json │ ├── image_load_app_theme.json │ ├── image_loading_test.json │ ├── notepad_theme.json │ ├── pyinstaller_theme.json │ ├── quick_theme.json │ ├── status_bar_theme.json │ ├── text_effects_theme.json │ ├── theme_1.json │ ├── theme_2.json │ ├── theme_3.json │ ├── translations_theme.json │ └── two_sided_border_theme.json └── translations │ ├── examples.ar.json │ ├── examples.de.json │ ├── examples.en.json │ ├── examples.es.json │ ├── examples.fr.json │ ├── examples.ge.json │ ├── examples.he.json │ ├── examples.id.json │ ├── examples.it.json │ ├── examples.ja.json │ ├── examples.ko.json │ ├── examples.pl.json │ ├── examples.pt.json │ ├── examples.ru.json │ ├── examples.uk.json │ ├── examples.vi.json │ └── examples.zh.json ├── docs └── example_1.png ├── documentation_test.py ├── example_auto_scale_button_images.py ├── example_check_box_multi_image.py ├── example_image_positioning.py ├── file_dialog_test.py ├── general_ui_test_app.py ├── gradient_test.py ├── guiopedia.py ├── layout_anchor_test.py ├── new_text_test.py ├── pong ├── ball.py ├── bat.py ├── pong.py ├── score.py └── wall.py ├── pygame_notepad.py ├── pyinstaller_specs ├── pyinstaller_build.spec └── pyinstaller_onefile_build.spec ├── pyinstaller_test.py ├── quick_start.py ├── resizing_test.py ├── scrolling_container_test.py ├── shape_packing_cache_test.py ├── status_bars.py ├── text_console.py ├── text_effects.py ├── text_embedded_images.py ├── text_test.py ├── translations_test.py ├── two_sided_border_button.py ├── ui_element_creation_speed_test.py ├── user_controlled_image_loading_example.py ├── using_ui_form.py └── windowed_mini_games_app.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Python template 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *$py.class 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | pip-wheel-metadata/ 25 | share/python-wheels/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | MANIFEST 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | 53 | # Translations 54 | *.mo 55 | *.pot 56 | 57 | # Django stuff: 58 | *.log 59 | local_settings.py 60 | db.sqlite3 61 | 62 | # Flask stuff: 63 | instance/ 64 | .webassets-cache 65 | 66 | # Scrapy stuff: 67 | .scrapy 68 | 69 | # Sphinx documentation 70 | 71 | # PyBuilder 72 | target/ 73 | 74 | # Jupyter Notebook 75 | .ipynb_checkpoints 76 | 77 | # IPython 78 | profile_default/ 79 | ipython_config.py 80 | 81 | # pyenv 82 | .python-version 83 | 84 | # pipenv 85 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 86 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 87 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 88 | # install all needed dependencies. 89 | #Pipfile.lock 90 | 91 | # celery beat schedule file 92 | celerybeat-schedule 93 | 94 | # SageMath parsed files 95 | *.sage.py 96 | 97 | # Environments 98 | .env 99 | .venv 100 | env/ 101 | venv/ 102 | ENV/ 103 | env.bak/ 104 | venv.bak/ 105 | 106 | # Spyder project settings 107 | .spyderproject 108 | .spyproject 109 | 110 | # Rope project settings 111 | .ropeproject 112 | 113 | # mkdocs documentation 114 | /site 115 | 116 | # mypy 117 | .mypy_cache/ 118 | .dmypy.json 119 | dmypy.json 120 | 121 | # Pyre type checker 122 | .pyre/ 123 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pygame GUI Examples 2 | A few simple programs to demonstrate how to use features of the [pygame_gui](https://github.com/MyreMylar/pygame_gui) module. 3 | 4 | To run these programs you must first have installed the [pygame_gui](https://github.com/MyreMylar/pygame_gui) project (which itself depends on pygame-ce). 5 | 6 | It's also worth noting that [pygame_gui](https://github.com/MyreMylar/pygame_gui) is designed to work with pygame-ce. 7 | 8 | ![alt text](https://github.com/MyreMylar/pygame_gui_examples/raw/master/docs/example_1.png "Screenshot of a pygame_gui example program") 9 | 10 | ![text_test](https://user-images.githubusercontent.com/13382426/75631236-0fdef900-5be9-11ea-8853-14a43ec7aed1.png) 11 | -------------------------------------------------------------------------------- /auto_image_loading_example.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import pygame_gui 3 | 4 | 5 | # 20 * image buttons 6 | # Network drive: Auto Image loading time taken: 14-17 seconds. 7 | 8 | pygame.init() 9 | 10 | 11 | pygame.display.set_caption('Image Loading Test') 12 | window_surface = pygame.display.set_mode((800, 600)) 13 | background = pygame.Surface((800, 600)) 14 | background.fill(pygame.Color('#000000')) 15 | clock = pygame.time.Clock() 16 | load_time_1 = clock.tick() 17 | manager = pygame_gui.UIManager((800, 600), 'data/themes/image_loading_test.json') 18 | 19 | load_time_2 = clock.tick() 20 | 21 | print('Image loading time taken:', load_time_2 / 1000.0, 'seconds.') 22 | 23 | button_row_width = 200 24 | button_row_height = 150 25 | spacing = 0 26 | num_buttons = 1 27 | for j in range(1, 5): 28 | for i in range(1, 5): 29 | position = (i * spacing + ((i - 1) * button_row_width), 30 | (j * spacing + ((j - 1) * button_row_height))) 31 | pygame_gui.elements.UIButton(relative_rect=pygame.Rect(position, 32 | (button_row_width, 33 | button_row_height)), 34 | text=str(num_buttons), 35 | manager=manager, 36 | object_id='#'+str(num_buttons)) 37 | num_buttons += 1 38 | 39 | is_running = True 40 | 41 | while is_running: 42 | time_delta = clock.tick(60)/1000.0 43 | for event in pygame.event.get(): 44 | if event.type == pygame.QUIT: 45 | is_running = False 46 | 47 | manager.process_events(event) 48 | 49 | manager.update(time_delta) 50 | 51 | window_surface.blit(background, (0, 0)) 52 | manager.draw_ui(window_surface) 53 | 54 | pygame.display.update() 55 | -------------------------------------------------------------------------------- /button_theming_test.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import pygame_gui 3 | 4 | # Rough current performance measure - Button creation time taken: 0.08 seconds. 5 | # (54 x rounded rectangles) 6 | 7 | pygame.init() 8 | 9 | 10 | pygame.display.set_caption('Button Theming Test') 11 | window_surface = pygame.display.set_mode((800, 600)) 12 | manager = pygame_gui.UIManager((800, 600), 'data/themes/button_theming_test_theme.json') 13 | clock = pygame.time.Clock() 14 | 15 | background = pygame.Surface((800, 600)) 16 | background.fill(manager.get_theme().get_colour('dark_bg')) 17 | 18 | load_time_1 = clock.tick() 19 | 20 | button_row_width = 100 21 | button_row_height = 40 22 | spacing = 20 23 | for j in range(1, 10): 24 | for i in range(1, 7): 25 | position = (i * spacing + ((i - 1) * button_row_width), 26 | (j * spacing + ((j - 1) * button_row_height))) 27 | pygame_gui.elements.UIButton(relative_rect=pygame.Rect(position, 28 | (button_row_width, 29 | button_row_height)), 30 | text=str(i) + ',' + str(j), 31 | manager=manager, 32 | object_id='#' + str(i) + ',' + str(j)) 33 | 34 | load_time_2 = clock.tick() 35 | print('Button creation time taken:', load_time_2/1000.0, 'seconds.') 36 | 37 | is_running = True 38 | 39 | while is_running: 40 | time_delta = clock.tick(60)/1000.0 41 | for event in pygame.event.get(): 42 | if event.type == pygame.QUIT: 43 | is_running = False 44 | 45 | manager.process_events(event) 46 | 47 | manager.update(time_delta) 48 | 49 | window_surface.blit(background, (0, 0)) 50 | manager.draw_ui(window_surface) 51 | 52 | pygame.display.update() 53 | -------------------------------------------------------------------------------- /camera_window_test.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import pygame.camera 3 | import pygame_gui 4 | 5 | 6 | """ 7 | Uses Pygame Camera module to display a webcam in a window 8 | """ 9 | 10 | 11 | class CameraWindow(pygame_gui.elements.UIWindow): 12 | def __init__(self, 13 | rect: pygame.Rect, 14 | camera_name, 15 | ui_manager: pygame_gui.core.interfaces.IUIManagerInterface): 16 | super().__init__(rect, ui_manager, window_display_title=camera_name, resizable=True) 17 | 18 | self.camera = None 19 | 20 | self.camera = pygame.camera.Camera(camera_name, (640, 480)) 21 | self.camera.start() 22 | 23 | print(self.camera.get_controls()) 24 | 25 | cam_rect = pygame.Rect((0, 0), self.get_container().rect.size) 26 | self.cam_image = pygame_gui.elements.UIImage(relative_rect=cam_rect, 27 | image_surface=self.camera.get_image(), 28 | manager=self.ui_manager, 29 | container=self, 30 | anchors={'left': 'left', 31 | 'right': 'right', 32 | 'top': 'top', 33 | 'bottom': 'bottom'}) 34 | 35 | def update(self, time_delta: float): 36 | super().update(time_delta) 37 | 38 | if self.camera is not None: 39 | 40 | self.cam_image.set_image(pygame.transform.smoothscale(self.camera.get_image(), 41 | self.get_container().rect.size)) 42 | 43 | 44 | pygame.init() 45 | pygame.camera.init() 46 | 47 | print(pygame.camera.get_backends()) 48 | print(pygame.camera.list_cameras()) 49 | 50 | pygame.display.set_caption('Quick Start') 51 | window_surface = pygame.display.set_mode((800, 600)) 52 | manager = pygame_gui.UIManager((800, 600), 'data/themes/camera_theme.json') 53 | 54 | background = pygame.Surface((800, 600)) 55 | background.fill(manager.ui_theme.get_colour('dark_bg')) 56 | 57 | 58 | cam_window_pos = [10, 10] 59 | num_connected_cameras = 1 60 | cam_names = pygame.camera.list_cameras() 61 | for cam_name in cam_names: 62 | cam_window_rect = pygame.Rect(0, 0, 400, 300) 63 | cam_window_rect.topleft = cam_window_pos 64 | CameraWindow(cam_window_rect, cam_name, manager) 65 | cam_window_pos = (cam_window_pos[0] + 420, 66 | cam_window_pos[1]) 67 | 68 | clock = pygame.time.Clock() 69 | is_running = True 70 | 71 | while is_running: 72 | time_delta = clock.tick(60)/1000.0 73 | for event in pygame.event.get(): 74 | if event.type == pygame.QUIT: 75 | is_running = False 76 | 77 | manager.process_events(event) 78 | 79 | manager.update(time_delta) 80 | 81 | window_surface.blit(background, (0, 0)) 82 | manager.draw_ui(window_surface) 83 | 84 | pygame.display.update() 85 | -------------------------------------------------------------------------------- /colour_picker_test.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import pygame_gui 3 | 4 | from pygame_gui.elements import UIButton 5 | from pygame_gui.windows import UIColourPickerDialog 6 | 7 | 8 | class ColourPickingApp: 9 | def __init__(self): 10 | pygame.init() 11 | 12 | pygame.display.set_caption('Colour Picking App') 13 | self.window_surface = pygame.display.set_mode((800, 600)) 14 | self.ui_manager = pygame_gui.UIManager((800, 600), 15 | 'data/themes/colour_picker_app_theme.json') 16 | 17 | self.background = pygame.Surface((800, 600)) 18 | self.background.fill(self.ui_manager.ui_theme.get_colour('dark_bg')) 19 | 20 | self.pick_colour_button = UIButton(relative_rect=pygame.Rect(-180, -60, 150, 30), 21 | text='Pick Colour', 22 | manager=self.ui_manager, 23 | anchors={'left': 'right', 24 | 'right': 'right', 25 | 'top': 'bottom', 26 | 'bottom': 'bottom'}) 27 | 28 | self.colour_picker = None 29 | 30 | self.current_colour = pygame.Color(0, 0, 0) 31 | self.picked_colour_surface = pygame.Surface((400, 400)) 32 | self.picked_colour_surface.fill(self.current_colour) 33 | 34 | self.clock = pygame.time.Clock() 35 | self.is_running = True 36 | 37 | def run(self): 38 | while self.is_running: 39 | time_delta = self.clock.tick(60) / 1000.0 40 | for event in pygame.event.get(): 41 | if event.type == pygame.QUIT: 42 | self.is_running = False 43 | 44 | if (event.type == pygame_gui.UI_BUTTON_PRESSED and 45 | event.ui_element == self.pick_colour_button): 46 | self.colour_picker = UIColourPickerDialog(pygame.Rect(160, 50, 420, 400), 47 | self.ui_manager, 48 | window_title='Change Colour...', 49 | initial_colour=self.current_colour) 50 | self.pick_colour_button.disable() 51 | 52 | if event.type == pygame_gui.UI_COLOUR_PICKER_COLOUR_PICKED: 53 | self.current_colour = event.colour 54 | self.picked_colour_surface.fill(self.current_colour) 55 | 56 | if (event.type == pygame_gui.UI_WINDOW_CLOSE and 57 | event.ui_element == self.colour_picker): 58 | self.pick_colour_button.enable() 59 | self.colour_picker = None 60 | 61 | self.ui_manager.process_events(event) 62 | 63 | self.ui_manager.update(time_delta) 64 | 65 | self.window_surface.blit(self.background, (0, 0)) 66 | self.window_surface.blit(self.picked_colour_surface, (200, 100)) 67 | self.ui_manager.draw_ui(self.window_surface) 68 | 69 | pygame.display.update() 70 | 71 | 72 | if __name__ == "__main__": 73 | app = ColourPickingApp() 74 | app.run() 75 | -------------------------------------------------------------------------------- /data/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/__init__.py -------------------------------------------------------------------------------- /data/fonts/Amiri-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/fonts/Amiri-Regular.ttf -------------------------------------------------------------------------------- /data/fonts/KosugiMaru-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/fonts/KosugiMaru-Regular.ttf -------------------------------------------------------------------------------- /data/fonts/MaShanZheng-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/fonts/MaShanZheng-Regular.ttf -------------------------------------------------------------------------------- /data/fonts/Montserrat-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/fonts/Montserrat-Bold.ttf -------------------------------------------------------------------------------- /data/fonts/Montserrat-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/fonts/Montserrat-BoldItalic.ttf -------------------------------------------------------------------------------- /data/fonts/Montserrat-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/fonts/Montserrat-Italic.ttf -------------------------------------------------------------------------------- /data/fonts/Montserrat-LICENSE.txt: -------------------------------------------------------------------------------- 1 | JulietaUla/Montserrat is licensed under the 2 | 3 | SIL Open Font License 1.1 4 | The Open Font License (OFL) is maintained by SIL International. It attempts to be a compromise between the values of the free software and typeface design communities. It is used for almost all open source font projects, including those by Adobe, Google and Mozilla. 5 | 6 | Permissions 7 | Private use 8 | Commercial use 9 | Modification 10 | Distribution 11 | Limitations 12 | Liability 13 | Warranty 14 | Conditions 15 | License and copyright notice 16 | Same license 17 | This is not legal advice. Learn more about repository licenses. 18 | @m4rc1e m4rc1e Updated vertical metrics and copyright string 19 | 156b817 on 31 Oct 2017 20 | @m4rc1e@graphicore 21 | 94 lines (75 sloc) 4.29 KB 22 | 23 | Copyright 2011 The Montserrat Project Authors (https://github.com/JulietaUla/Montserrat) 24 | 25 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 26 | This license is copied below, and is also available with a FAQ at: 27 | http://scripts.sil.org/OFL 28 | 29 | 30 | ----------------------------------------------------------- 31 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 32 | ----------------------------------------------------------- 33 | 34 | PREAMBLE 35 | The goals of the Open Font License (OFL) are to stimulate worldwide 36 | development of collaborative font projects, to support the font creation 37 | efforts of academic and linguistic communities, and to provide a free and 38 | open framework in which fonts may be shared and improved in partnership 39 | with others. 40 | 41 | The OFL allows the licensed fonts to be used, studied, modified and 42 | redistributed freely as long as they are not sold by themselves. The 43 | fonts, including any derivative works, can be bundled, embedded, 44 | redistributed and/or sold with any software provided that any reserved 45 | names are not used by derivative works. The fonts and derivatives, 46 | however, cannot be released under any other type of license. The 47 | requirement for fonts to remain under this license does not apply 48 | to any document created using the fonts or their derivatives. 49 | 50 | DEFINITIONS 51 | "Font Software" refers to the set of files released by the Copyright 52 | Holder(s) under this license and clearly marked as such. This may 53 | include source files, build scripts and documentation. 54 | 55 | "Reserved Font Name" refers to any names specified as such after the 56 | copyright statement(s). 57 | 58 | "Original Version" refers to the collection of Font Software components as 59 | distributed by the Copyright Holder(s). 60 | 61 | "Modified Version" refers to any derivative made by adding to, deleting, 62 | or substituting -- in part or in whole -- any of the components of the 63 | Original Version, by changing formats or by porting the Font Software to a 64 | new environment. 65 | 66 | "Author" refers to any designer, engineer, programmer, technical 67 | writer or other person who contributed to the Font Software. 68 | 69 | PERMISSION & CONDITIONS 70 | Permission is hereby granted, free of charge, to any person obtaining 71 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 72 | redistribute, and sell modified and unmodified copies of the Font 73 | Software, subject to the following conditions: 74 | 75 | 1) Neither the Font Software nor any of its individual components, 76 | in Original or Modified Versions, may be sold by itself. 77 | 78 | 2) Original or Modified Versions of the Font Software may be bundled, 79 | redistributed and/or sold with any software, provided that each copy 80 | contains the above copyright notice and this license. These can be 81 | included either as stand-alone text files, human-readable headers or 82 | in the appropriate machine-readable metadata fields within text or 83 | binary files as long as those fields can be easily viewed by the user. 84 | 85 | 3) No Modified Version of the Font Software may use the Reserved Font 86 | Name(s) unless explicit written permission is granted by the corresponding 87 | Copyright Holder. This restriction only applies to the primary font name as 88 | presented to the users. 89 | 90 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 91 | Software shall not be used to promote, endorse or advertise any 92 | Modified Version, except to acknowledge the contribution(s) of the 93 | Copyright Holder(s) and the Author(s) or with their explicit written 94 | permission. 95 | 96 | 5) The Font Software, modified or unmodified, in part or in whole, 97 | must be distributed entirely under this license, and must not be 98 | distributed under any other license. The requirement for fonts to 99 | remain under this license does not apply to any document created 100 | using the Font Software. 101 | 102 | TERMINATION 103 | This license becomes null and void if any of the above conditions are 104 | not met. 105 | 106 | DISCLAIMER 107 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 108 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 109 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 110 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 111 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 112 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 113 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 114 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 115 | OTHER DEALINGS IN THE FONT SOFTWARE. -------------------------------------------------------------------------------- /data/fonts/Montserrat-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/fonts/Montserrat-Regular.ttf -------------------------------------------------------------------------------- /data/fonts/NotoRashiHebrew-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/fonts/NotoRashiHebrew-Regular.ttf -------------------------------------------------------------------------------- /data/fonts/NotoSerifGeorgian-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/fonts/NotoSerifGeorgian-Regular.ttf -------------------------------------------------------------------------------- /data/fonts/PermanentMarker-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/fonts/PermanentMarker-Regular.ttf -------------------------------------------------------------------------------- /data/fonts/SongMyung-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/fonts/SongMyung-Regular.ttf -------------------------------------------------------------------------------- /data/fonts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/fonts/__init__.py -------------------------------------------------------------------------------- /data/guiopedia/aliens.html: -------------------------------------------------------------------------------- 1 | Aliens 2 |

3 | Contrary to most popular media, the average alien is quite a boring fellow. By and large they prefer to hang around in cubicles contemplating 4 | the meaning of filing identically shaped cubes. It's best not to bother with them really, terribly dull. 5 | 6 | Why don't you go think about cats instead? -------------------------------------------------------------------------------- /data/guiopedia/cats.html: -------------------------------------------------------------------------------- 1 | Cats! 2 |

3 | The mightiest creatures on planet earth cats are know for their impressive pouncing capabilities, 4 | their soft bellies and unmatched capacity for lurking where you least expect. 5 |

6 | But what is the truth of cats? The very essence of catty cattitude? How many cats can fit in a shoebox? 7 | Do cats get on with gravel? Find out more below. 8 |

9 | Famous Cats 10 |

11 | - Sir Pouncealot: A knight of the round bowl.
12 | - Count Catula: A much maligned hero of the people.
-------------------------------------------------------------------------------- /data/guiopedia/gravel.html: -------------------------------------------------------------------------------- 1 | Gravel: The Full Facts 2 |

3 | For too long they have remained hidden, but now we can exclusively reveal the truth behind the tiny bits of rock. 4 | Some say they were first formed by an ancient alien race, or were the leftovers of an enormous magical ritual that 5 | forever drained planet earth of precious life-giving magic. 6 |

7 | The real facts are more sinister still... -------------------------------------------------------------------------------- /data/guiopedia/index.html: -------------------------------------------------------------------------------- 1 | Welcome to GUI-opedia! 2 |

3 | This is a little test of creating a few hyperlink connected pages that we can display to 4 | the user to give them more information. Maybe it'll have a search bar as well? Oh, hey now it does. 5 |

6 | The point is we have multiple pages of text that we load in from files, and then we can navigate between them via links 7 | all inside of a window. Here are a few of them to try clicking on: 8 |

9 |

10 |

11 |

12 |

13 |

14 |

15 |

16 |

17 |

18 |

19 |

20 |

21 |

22 |

23 |

24 |

25 |

26 |

27 |

28 |

29 | - Cats - A page all about cats.
30 | - Gravel - Gravel: What is the deal.
31 | -------------------------------------------------------------------------------- /data/images/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/__init__.py -------------------------------------------------------------------------------- /data/images/home_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/home_icon.png -------------------------------------------------------------------------------- /data/images/measure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/measure.png -------------------------------------------------------------------------------- /data/images/space/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/space/__init__.py -------------------------------------------------------------------------------- /data/images/space/space_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/space/space_1.jpg -------------------------------------------------------------------------------- /data/images/space/space_10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/space/space_10.jpg -------------------------------------------------------------------------------- /data/images/space/space_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/space/space_11.jpg -------------------------------------------------------------------------------- /data/images/space/space_12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/space/space_12.jpg -------------------------------------------------------------------------------- /data/images/space/space_13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/space/space_13.jpg -------------------------------------------------------------------------------- /data/images/space/space_14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/space/space_14.jpg -------------------------------------------------------------------------------- /data/images/space/space_15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/space/space_15.jpg -------------------------------------------------------------------------------- /data/images/space/space_16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/space/space_16.jpg -------------------------------------------------------------------------------- /data/images/space/space_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/space/space_2.jpg -------------------------------------------------------------------------------- /data/images/space/space_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/space/space_3.jpg -------------------------------------------------------------------------------- /data/images/space/space_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/space/space_4.jpg -------------------------------------------------------------------------------- /data/images/space/space_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/space/space_5.jpg -------------------------------------------------------------------------------- /data/images/space/space_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/space/space_6.jpg -------------------------------------------------------------------------------- /data/images/space/space_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/space/space_7.jpg -------------------------------------------------------------------------------- /data/images/space/space_8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/space/space_8.jpg -------------------------------------------------------------------------------- /data/images/space/space_9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/space/space_9.jpg -------------------------------------------------------------------------------- /data/images/splat.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/splat.bmp -------------------------------------------------------------------------------- /data/images/splat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/splat.png -------------------------------------------------------------------------------- /data/images/test_emoji.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/test_emoji.png -------------------------------------------------------------------------------- /data/images/test_images/field_of_gold.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/test_images/field_of_gold.jpg -------------------------------------------------------------------------------- /data/images/test_images/london.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/test_images/london.jpg -------------------------------------------------------------------------------- /data/images/test_images/paris.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/images/test_images/paris.jpg -------------------------------------------------------------------------------- /data/themes/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/data/themes/__init__.py -------------------------------------------------------------------------------- /data/themes/button_theming_test_theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "#1,1": 3 | { 4 | "misc": 5 | { 6 | "shape": "rounded_rectangle", 7 | "shape_corner_radius": "18", 8 | "border_width": "1", 9 | "shadow_width": "2" 10 | } 11 | }, 12 | "#2,1": 13 | { 14 | "misc": 15 | { 16 | "shape": "rounded_rectangle", 17 | "shape_corner_radius": "14", 18 | "border_width": "1", 19 | "shadow_width": "2" 20 | } 21 | }, 22 | "#3,1": 23 | { 24 | "misc": 25 | { 26 | "shape": "rounded_rectangle", 27 | "shape_corner_radius": "10", 28 | "border_width": "1", 29 | "shadow_width": "2" 30 | } 31 | }, 32 | "#4,1": 33 | { 34 | "misc": 35 | { 36 | "shape": "rounded_rectangle", 37 | "shape_corner_radius": "6", 38 | "border_width": "1", 39 | "shadow_width": "2" 40 | } 41 | }, 42 | "#5,1": 43 | { 44 | "misc": 45 | { 46 | "shape": "rounded_rectangle", 47 | "shape_corner_radius": "4", 48 | "border_width": "1", 49 | "shadow_width": "2" 50 | } 51 | }, 52 | "#6,1": 53 | { 54 | "misc": 55 | { 56 | "shape": "rounded_rectangle", 57 | "shape_corner_radius": "2", 58 | "border_width": "1", 59 | "shadow_width": "2" 60 | } 61 | }, 62 | "#1,2": 63 | { 64 | "misc": 65 | { 66 | "shape": "rounded_rectangle", 67 | "shape_corner_radius": "18", 68 | "border_width": "18", 69 | "shadow_width": "2" 70 | } 71 | }, 72 | "#2,2": 73 | { 74 | "misc": 75 | { 76 | "shape": "rounded_rectangle", 77 | "shape_corner_radius": "14", 78 | "border_width": "14", 79 | "shadow_width": "2" 80 | } 81 | }, 82 | "#3,2": 83 | { 84 | "misc": 85 | { 86 | "shape": "rounded_rectangle", 87 | "shape_corner_radius": "10", 88 | "border_width": "10", 89 | "shadow_width": "2" 90 | } 91 | }, 92 | "#4,2": 93 | { 94 | "misc": 95 | { 96 | "shape": "rounded_rectangle", 97 | "shape_corner_radius": "6", 98 | "border_width": "6", 99 | "shadow_width": "2" 100 | } 101 | }, 102 | "#5,2": 103 | { 104 | "misc": 105 | { 106 | "shape": "rounded_rectangle", 107 | "shape_corner_radius": "4", 108 | "border_width": "4", 109 | "shadow_width": "2" 110 | } 111 | }, 112 | "#6,2": 113 | { 114 | "misc": 115 | { 116 | "shape": "rounded_rectangle", 117 | "shape_corner_radius": "2", 118 | "border_width": "2", 119 | "shadow_width": "2" 120 | } 121 | }, 122 | "#1,3": 123 | { 124 | "misc": 125 | { 126 | "shape": "rounded_rectangle", 127 | "shape_corner_radius": "2", 128 | "border_width": "2", 129 | "shadow_width": "18" 130 | } 131 | }, 132 | "#2,3": 133 | { 134 | "misc": 135 | { 136 | "shape": "rounded_rectangle", 137 | "shape_corner_radius": "2", 138 | "border_width": "2", 139 | "shadow_width": "14" 140 | } 141 | }, 142 | "#3,3": 143 | { 144 | "misc": 145 | { 146 | "shape": "rounded_rectangle", 147 | "shape_corner_radius": "2", 148 | "border_width": "2", 149 | "shadow_width": "10" 150 | } 151 | }, 152 | "#4,3": 153 | { 154 | "misc": 155 | { 156 | "shape": "rounded_rectangle", 157 | "shape_corner_radius": "2", 158 | "border_width": "2", 159 | "shadow_width": "6" 160 | } 161 | }, 162 | "#5,3": 163 | { 164 | "misc": 165 | { 166 | "shape": "rounded_rectangle", 167 | "shape_corner_radius": "2", 168 | "border_width": "2", 169 | "shadow_width": "4" 170 | } 171 | }, 172 | "#6,3": 173 | { 174 | "misc": 175 | { 176 | "shape": "rounded_rectangle", 177 | "shape_corner_radius": "2", 178 | "border_width": "2", 179 | "shadow_width": "2" 180 | } 181 | }, 182 | "#1,4": 183 | { 184 | "colours": 185 | { 186 | "normal_bg": "#30AA30AA,#AA3030,180" 187 | }, 188 | "misc": 189 | { 190 | "shape": "ellipse", 191 | "border_width": "1", 192 | "shadow_width": "2" 193 | } 194 | }, 195 | "#2,4": 196 | { 197 | "colours": 198 | { 199 | "normal_bg": "#30AA30AA,#AA3030,180", 200 | "normal_border": "#30AA30AA,#AA3030,0" 201 | }, 202 | "misc": 203 | { 204 | "shape": "ellipse", 205 | "border_width": "2", 206 | "shadow_width": "2" 207 | } 208 | }, 209 | "#3,4": 210 | { 211 | "misc": 212 | { 213 | "shape": "ellipse", 214 | "border_width": "4", 215 | "shadow_width": "4" 216 | } 217 | }, 218 | "#4,4": 219 | { 220 | "misc": 221 | { 222 | "shape": "ellipse", 223 | "border_width": "8", 224 | "shadow_width": "8" 225 | } 226 | }, 227 | "#5,4": 228 | { 229 | "misc": 230 | { 231 | "shape": "ellipse", 232 | "border_width": "8", 233 | "shadow_width": "2" 234 | } 235 | }, 236 | "#6,4": 237 | { 238 | "misc": 239 | { 240 | "shape": "ellipse", 241 | "border_width": "1", 242 | "shadow_width": "8" 243 | } 244 | }, 245 | "#1,5": 246 | { 247 | "colours": 248 | { 249 | "normal_bg": "#AA3030" 250 | }, 251 | "misc": 252 | { 253 | "shape": "rounded_rectangle", 254 | "shape_corner_radius": "2", 255 | "border_width": "2", 256 | "shadow_width": "2" 257 | } 258 | }, 259 | "#2,5": 260 | { 261 | "colours": 262 | { 263 | "normal_bg": "#30AA30" 264 | }, 265 | "misc": 266 | { 267 | "shape": "rounded_rectangle", 268 | "shape_corner_radius": "10", 269 | "border_width": "2", 270 | "shadow_width": "2" 271 | } 272 | }, 273 | "#3,5": 274 | { 275 | "colours": 276 | { 277 | "normal_bg": "#3030AA" 278 | }, 279 | "misc": 280 | { 281 | "shape": "rounded_rectangle", 282 | "shape_corner_radius": "2", 283 | "border_width": "5", 284 | "shadow_width": "2" 285 | } 286 | }, 287 | "#4,5": 288 | { 289 | "colours": 290 | { 291 | "normal_border": "#AA3030" 292 | }, 293 | "misc": 294 | { 295 | "shape": "rounded_rectangle", 296 | "shape_corner_radius": "2", 297 | "border_width": "2", 298 | "shadow_width": "2" 299 | } 300 | }, 301 | "#5,5": 302 | { 303 | "colours": 304 | { 305 | "normal_border": "#30AA30" 306 | }, 307 | "misc": 308 | { 309 | "shape": "rounded_rectangle", 310 | "shape_corner_radius": "10", 311 | "border_width": "2", 312 | "shadow_width": "2" 313 | } 314 | }, 315 | "#6,5": 316 | { 317 | "colours": 318 | { 319 | "normal_border": "#3030AA" 320 | }, 321 | "misc": 322 | { 323 | "shape": "rounded_rectangle", 324 | "shape_corner_radius": "2", 325 | "border_width": "5", 326 | "shadow_width": "2" 327 | } 328 | }, 329 | "#1,6": 330 | { 331 | "colours": 332 | { 333 | "normal_bg": "#AA303050" 334 | }, 335 | "misc": 336 | { 337 | "shape": "rounded_rectangle", 338 | "shape_corner_radius": "2", 339 | "border_width": "2", 340 | "shadow_width": "2", 341 | "border_overlap": "0" 342 | } 343 | }, 344 | "#2,6": 345 | { 346 | "colours": 347 | { 348 | "normal_bg": "#30AA30AA" 349 | }, 350 | "misc": 351 | { 352 | "shape": "rounded_rectangle", 353 | "shape_corner_radius": "10", 354 | "border_width": "2", 355 | "shadow_width": "2", 356 | "border_overlap": "0" 357 | } 358 | }, 359 | "#3,6": 360 | { 361 | "colours": 362 | { 363 | "normal_bg": "#3030AAEE" 364 | }, 365 | "misc": 366 | { 367 | "shape": "rounded_rectangle", 368 | "shape_corner_radius": "2", 369 | "border_width": "5", 370 | "shadow_width": "2" 371 | } 372 | }, 373 | "#4,6": 374 | { 375 | "colours": 376 | { 377 | "normal_border": "#AA3030EE" 378 | }, 379 | "misc": 380 | { 381 | "shape": "rounded_rectangle", 382 | "shape_corner_radius": "2", 383 | "border_width": "2", 384 | "shadow_width": "2" 385 | } 386 | }, 387 | "#5,6": 388 | { 389 | "colours": 390 | { 391 | "normal_border": "#30AA30AA" 392 | }, 393 | "misc": 394 | { 395 | "shape": "rounded_rectangle", 396 | "shape_corner_radius": "10", 397 | "border_width": "2", 398 | "shadow_width": "2" 399 | } 400 | }, 401 | "#6,6": 402 | { 403 | "colours": 404 | { 405 | "normal_border": "#3030AA50" 406 | }, 407 | "misc": 408 | { 409 | "shape": "rounded_rectangle", 410 | "shape_corner_radius": "2", 411 | "border_width": "5", 412 | "shadow_width": "2" 413 | } 414 | }, 415 | "#1,7": 416 | { 417 | "colours": 418 | { 419 | "normal_bg": "#AA303050,#AA3030,0" 420 | }, 421 | "misc": 422 | { 423 | "shape": "rounded_rectangle", 424 | "shape_corner_radius": "2", 425 | "border_width": "2", 426 | "shadow_width": "2", 427 | "border_overlap": "0" 428 | } 429 | }, 430 | "#2,7": 431 | { 432 | "colours": 433 | { 434 | "normal_bg": "#30AA30AA,#AA3030,180" 435 | }, 436 | "misc": 437 | { 438 | "shape": "rounded_rectangle", 439 | "shape_corner_radius": "10", 440 | "border_width": "2", 441 | "shadow_width": "2", 442 | "border_overlap": "0" 443 | } 444 | }, 445 | "#3,7": 446 | { 447 | "colours": 448 | { 449 | "normal_bg": "#3030AAEE,#AA3030,90" 450 | }, 451 | "misc": 452 | { 453 | "shape": "rounded_rectangle", 454 | "shape_corner_radius": "2", 455 | "border_width": "5", 456 | "shadow_width": "2" 457 | } 458 | }, 459 | "#4,7": 460 | { 461 | "colours": 462 | { 463 | "normal_border": "#AA3030EE,#303AA050,-90" 464 | }, 465 | "misc": 466 | { 467 | "shape": "rounded_rectangle", 468 | "shape_corner_radius": "2", 469 | "border_width": "2", 470 | "shadow_width": "2" 471 | } 472 | }, 473 | "#5,7": 474 | { 475 | "colours": 476 | { 477 | "normal_border": "#30AA30AA,#3030AAAA,-45" 478 | }, 479 | "misc": 480 | { 481 | "shape": "rounded_rectangle", 482 | "shape_corner_radius": "10", 483 | "border_width": "2", 484 | "shadow_width": "2" 485 | } 486 | }, 487 | "#6,7": 488 | { 489 | "colours": 490 | { 491 | "normal_border": "#3030AA50,#3030AAAA,60" 492 | }, 493 | "misc": 494 | { 495 | "shape": "rounded_rectangle", 496 | "shape_corner_radius": "2", 497 | "border_width": "5", 498 | "shadow_width": "2" 499 | } 500 | } 501 | } -------------------------------------------------------------------------------- /data/themes/camera_theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "button": 3 | { 4 | "misc": 5 | { 6 | "shape": "rounded_rectangle", 7 | "shape_corner_radius": "1,20,10,20", 8 | "border_width": "1", 9 | "shadow_width": "2" 10 | } 11 | }, 12 | "window": 13 | { 14 | "misc": 15 | { 16 | "shape": "rounded_rectangle", 17 | "shape_corner_radius": "10,10,0,0" 18 | } 19 | }, 20 | "window.#title_bar": 21 | { 22 | "misc": 23 | { 24 | "shape": "rounded_rectangle", 25 | "shape_corner_radius": "10,0,0,0" 26 | } 27 | }, 28 | "window.#close_button": 29 | { 30 | "misc": 31 | { 32 | "shape": "rounded_rectangle", 33 | "shape_corner_radius": "0,10,0,0" 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /data/themes/colour_picker_app_theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "button": 3 | { 4 | "misc": 5 | { 6 | "shape": "rounded_rectangle", 7 | "shape_corner_radius": "10", 8 | "border_width": "1", 9 | "shadow_width": "2" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /data/themes/console_theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "button": 3 | { 4 | "misc": 5 | { 6 | "shape": "rounded_rectangle", 7 | "shape_corner_radius": "1,20,10,20", 8 | "border_width": "1", 9 | "shadow_width": "2" 10 | } 11 | }, 12 | "window": 13 | { 14 | "misc": 15 | { 16 | "shape": "rounded_rectangle", 17 | "shape_corner_radius": "10,10,0,0" 18 | } 19 | }, 20 | "window.#title_bar": 21 | { 22 | "misc": 23 | { 24 | "shape": "rounded_rectangle", 25 | "shape_corner_radius": "10,0,0,0" 26 | } 27 | }, 28 | "window.#close_button": 29 | { 30 | "misc": 31 | { 32 | "shape": "rounded_rectangle", 33 | "shape_corner_radius": "0,10,0,0" 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /data/themes/documentation_theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaults": 3 | { 4 | "colours": 5 | { 6 | "normal_bg": "#b5b4b5", 7 | "dark_bg": "#A0A0A0", 8 | "normal_text": "#101010", 9 | "normal_border": "#505050" 10 | } 11 | }, 12 | 13 | "drop_down_menu": 14 | { 15 | "colours": 16 | { 17 | "dark_bg": "#A0A0A0" 18 | }, 19 | "misc": 20 | { 21 | "shape": "rounded_rectangle", 22 | "border_width": "5", 23 | "shadow_width": "8", 24 | "shape_corner_radius": "8" 25 | } 26 | }, 27 | "drop_down_menu.button": 28 | { 29 | "colours": 30 | { 31 | "normal_bg": "#9090D000" 32 | }, 33 | "misc": 34 | { 35 | "shape": "rounded_rectangle", 36 | "border_width": "0", 37 | "shadow_width": "0", 38 | "shape_corner_radius": "5" 39 | } 40 | }, 41 | 42 | "screen_space_health_bar": 43 | { 44 | "colours": 45 | { 46 | "normal_text": "#E0E0E0", 47 | "text_shadow": "#202020", 48 | "normal_border": "#202020", 49 | "filled_bar": "#F04040A0,#A03080A0,90", 50 | "unfilled_bar": "#A0A0A0A0,#A0A0A050,270" 51 | }, 52 | "misc": 53 | { 54 | "shape": "rectangle", 55 | "shape_corner_radius": "15" 56 | } 57 | }, 58 | "text_box": 59 | { 60 | "colours": 61 | { 62 | "normal_text": "#202020", 63 | "normal_border": "#202020", 64 | "dark_bg": "#A0A0A0", 65 | "link_text": "#C0E0FF" 66 | }, 67 | "misc": 68 | { 69 | "shape": "rounded_rectangle", 70 | "shape_corner_radius": "15", 71 | "border_width": "3" 72 | } 73 | }, 74 | 75 | "vertical_scroll_bar": 76 | { 77 | "colours": 78 | { 79 | "dark_bg": "#A0A0A0" 80 | }, 81 | "misc": 82 | { 83 | "shape": "rounded_rectangle", 84 | "shape_corner_radius": "13", 85 | "border_width": "2" 86 | } 87 | }, 88 | "vertical_scroll_bar.button": 89 | { 90 | "misc": 91 | { 92 | "shape": "rounded_rectangle", 93 | "border_width": "1", 94 | "shadow_width": "0", 95 | "shape_corner_radius": "9" 96 | } 97 | }, 98 | "world_space_health_bar": 99 | { 100 | "colours": 101 | { 102 | "normal_text": "#E0E0E0", 103 | "text_shadow": "#202020", 104 | "normal_border": "#202020", 105 | "filled_bar": "#F04040A0,#A03080A0,90", 106 | "unfilled_bar": "#A0A0A0A0,#A0A0A050,270" 107 | }, 108 | "misc": 109 | { 110 | "shape": "rounded_rectangle", 111 | "shape_corner_radius": "15", 112 | "border_width": "3" 113 | } 114 | }, 115 | "panel": 116 | { 117 | "misc": 118 | { 119 | "border_width": "5", 120 | "shadow_width": "8", 121 | "shape_corner_radius": "8" 122 | } 123 | }, 124 | 125 | "selection_list": 126 | { 127 | "misc": 128 | { 129 | "border_width": "5", 130 | "shadow_width": "2" 131 | } 132 | }, 133 | 134 | "window": 135 | { 136 | "misc": 137 | { 138 | "border_width": "1" 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /data/themes/embedded_images_theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "text_box": 3 | { 4 | "misc": 5 | { 6 | "shape": "rectangle", 7 | "text_horiz_alignment": "left", 8 | "line_spacing": "1.5" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /data/themes/guiopedia_theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "#guiopedia_window": 3 | { 4 | "colours": 5 | { 6 | "dark_bg": "#4c5052" 7 | }, 8 | "misc": 9 | { 10 | "title_bar_height": "28" 11 | } 12 | }, 13 | 14 | "#guiopedia_window.text_box": 15 | { 16 | "colours": 17 | { 18 | "dark_bg": "#21282d" 19 | }, 20 | "misc": 21 | { 22 | "title_bar_height": "28" 23 | } 24 | }, 25 | "#guiopedia_window.#home_button": 26 | { 27 | "images": 28 | { 29 | "normal_image": { 30 | "path": "data/images/home_icon.png" 31 | } 32 | }, 33 | "misc": 34 | { 35 | "shape": "ellipse" 36 | } 37 | }, 38 | 39 | "#guiopedia_window.label": 40 | { 41 | "colours": 42 | { 43 | "dark_bg": "#4c5052" 44 | } 45 | }, 46 | 47 | "#guiopedia_window.text_entry_line": 48 | { 49 | "colours": 50 | { 51 | "dark_bg": "#21282d" 52 | }, 53 | "misc": 54 | { 55 | "shape": "rounded_rectangle", 56 | "shape_corner_radius": "12" 57 | } 58 | }, 59 | 60 | "#guiopedia_window.#title_bar": 61 | { 62 | "colours": 63 | { 64 | "normal_bg": "#35393e", 65 | "hovered_bg": "#55595e" 66 | }, 67 | 68 | "misc": 69 | { 70 | "text_horiz_alignment": "left", 71 | "text_horiz_alignment_padding": "10" 72 | } 73 | }, 74 | 75 | "#guiopedia_window.#close_button": 76 | { 77 | "colours": 78 | { 79 | "normal_bg": "#35393e", 80 | "hovered_bg": "#55595e" 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /data/themes/image_load_app_theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "button": 3 | { 4 | "misc": 5 | { 6 | "shape": "rounded_rectangle", 7 | "shape_corner_radius": "10", 8 | "border_width": "1", 9 | "shadow_width": "2" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /data/themes/image_loading_test.json: -------------------------------------------------------------------------------- 1 | { 2 | "button": 3 | { 4 | "misc": 5 | { 6 | "shape": "rectangle", 7 | "border_width": "1", 8 | "shadow_width": "2" 9 | } 10 | }, 11 | "#1": 12 | { 13 | "images": 14 | { 15 | "normal_image": { 16 | "package": "data.images.space", 17 | "resource": "space_1.jpg" 18 | } 19 | } 20 | }, 21 | "#2": 22 | { 23 | "images": 24 | { 25 | "normal_image": { 26 | "package": "data.images.space", 27 | "resource": "space_2.jpg" 28 | } 29 | } 30 | }, 31 | "#3": 32 | { 33 | "images": 34 | { 35 | "normal_image": { 36 | "package": "data.images.space", 37 | "resource": "space_3.jpg" 38 | } 39 | } 40 | }, 41 | "#4": 42 | { 43 | "images": 44 | { 45 | "normal_image": { 46 | "package": "data.images.space", 47 | "resource": "space_4.jpg" 48 | } 49 | } 50 | }, 51 | "#5": 52 | { 53 | "images": 54 | { 55 | "normal_image": { 56 | "package": "data.images.space", 57 | "resource": "space_5.jpg" 58 | } 59 | } 60 | }, 61 | "#6": 62 | { 63 | "images": 64 | { 65 | "normal_image": { 66 | "package": "data.images.space", 67 | "resource": "space_6.jpg" 68 | } 69 | } 70 | }, 71 | "#7": 72 | { 73 | "images": 74 | { 75 | "normal_image": { 76 | "package": "data.images.space", 77 | "resource": "space_7.jpg" 78 | } 79 | } 80 | }, 81 | "#8": 82 | { 83 | "images": 84 | { 85 | "normal_image": { 86 | "package": "data.images.space", 87 | "resource": "space_8.jpg" 88 | } 89 | } 90 | }, 91 | "#9": 92 | { 93 | "images": 94 | { 95 | "normal_image": { 96 | "package": "data.images.space", 97 | "resource": "space_9.jpg" 98 | } 99 | } 100 | }, 101 | "#10": 102 | { 103 | "images": 104 | { 105 | "normal_image": { 106 | "package": "data.images.space", 107 | "resource": "space_10.jpg" 108 | } 109 | } 110 | }, 111 | "#11": 112 | { 113 | "images": 114 | { 115 | "normal_image": { 116 | "package": "data.images.space", 117 | "resource": "space_11.jpg" 118 | } 119 | } 120 | }, 121 | "#12": 122 | { 123 | "images": 124 | { 125 | "normal_image": { 126 | "package": "data.images.space", 127 | "resource": "space_12.jpg" 128 | } 129 | } 130 | }, 131 | "#13": 132 | { 133 | "images": 134 | { 135 | "normal_image": { 136 | "package": "data.images.space", 137 | "resource": "space_13.jpg" 138 | } 139 | } 140 | }, 141 | "#14": 142 | { 143 | "images": 144 | { 145 | "normal_image": { 146 | "package": "data.images.space", 147 | "resource": "space_14.jpg" 148 | } 149 | } 150 | }, 151 | "#15": 152 | { 153 | "images": 154 | { 155 | "normal_image": { 156 | "package": "data.images.space", 157 | "resource": "space_15.jpg" 158 | } 159 | } 160 | }, 161 | "#16": 162 | { 163 | "images": 164 | { 165 | "normal_image": { 166 | "package": "data.images.space", 167 | "resource": "space_16.jpg" 168 | } 169 | } 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /data/themes/notepad_theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "text_box": 3 | { 4 | "misc": 5 | { 6 | "border_width": "0", 7 | "shadow_width": "0" 8 | }, 9 | "colours": 10 | { 11 | "text_cursor": "white" 12 | } 13 | }, 14 | "text_entry_box": 15 | { 16 | "misc": 17 | { 18 | "border_width": "0", 19 | "shadow_width": "0" 20 | }, 21 | "colours": 22 | { 23 | "text_cursor": "white" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /data/themes/pyinstaller_theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "button": 3 | { 4 | "misc": 5 | { 6 | "shape": "rounded_rectangle", 7 | "shape_corner_radius": "10", 8 | "border_width": "1", 9 | "shadow_width": "2" 10 | }, 11 | "images": 12 | { 13 | "normal_image": { 14 | "path": "data/images/splat.png", 15 | "sub_surface_rect": "0,0,32,32" 16 | }, 17 | "hovered_image": { 18 | "path": "data/images/splat.png", 19 | "sub_surface_rect": "32,0,32,32" 20 | } 21 | }, 22 | "font": 23 | { 24 | "name": "montserrat", 25 | "size": "12", 26 | "bold": "1", 27 | "italic": "0", 28 | "regular_path": "data/fonts/Montserrat-Regular.ttf", 29 | "bold_path": "data/fonts/Montserrat-Bold.ttf", 30 | "italic_path": "data/fonts/Montserrat-Italic.ttf", 31 | "bold_italic_path": "data/fonts/Montserrat-BoldItalic.ttf" 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /data/themes/quick_theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "button": 3 | { 4 | "misc": 5 | { 6 | "shape": "rounded_rectangle", 7 | "shape_corner_radius": "10", 8 | "border_width": "1", 9 | "shadow_width": "2" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /data/themes/status_bar_theme.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "#progress_bar": 4 | { 5 | "colours": { 6 | "filled_bar": "#D0E0FF,#90A0B0,-90", 7 | "unfilled_bar": "#606060" 8 | }, 9 | "misc": { 10 | "shape": "rounded_rectangle", 11 | "shape_corner_radius": "12" 12 | } 13 | }, 14 | 15 | "@player_status_bars": 16 | { 17 | "misc": 18 | { 19 | "shadow_width": "1", 20 | "border_width": "0" 21 | } 22 | }, 23 | 24 | "#health_bar": 25 | { 26 | "colours": { 27 | "filled_bar": "#AA4040D0", 28 | "unfilled_bar": "#888888D0" 29 | }, 30 | "misc": 31 | { 32 | "follow_sprite_offset": "-14,-20" 33 | } 34 | }, 35 | "#mana_bar": 36 | { 37 | "colours": { 38 | "filled_bar": "#6666AAD0", 39 | "unfilled_bar": "#888888D0" 40 | }, 41 | "misc": 42 | { 43 | "follow_sprite_offset": "-14,-14" 44 | } 45 | }, 46 | "#stamina_bar": 47 | { 48 | "colours": { 49 | "filled_bar": "#77CC77D0", 50 | "unfilled_bar": "#888888D0" 51 | }, 52 | "misc": 53 | { 54 | "follow_sprite_offset": "-14,-8" 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /data/themes/text_effects_theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": 3 | { 4 | "colours":{ 5 | "dark_bg": "#550000ff" 6 | } 7 | 8 | } 9 | } -------------------------------------------------------------------------------- /data/themes/theme_1.json: -------------------------------------------------------------------------------- 1 | { 2 | "text_box": 3 | { 4 | "colours": 5 | { 6 | "link_text":"#F080E0,#8080E0,0", 7 | "link_hover":"#FF8FEF", 8 | "regular_text": "#D0D0D0,#FFFFFF,#D050FF,90" 9 | }, 10 | "misc": 11 | { 12 | "shape": "rounded_rectangle", 13 | "shape_corner_radius": "10", 14 | "border_width": "1", 15 | "padding": "10,10", 16 | "link_normal_underline": "0", 17 | "link_hover_underline": "0", 18 | "line_spacing": "0.9" 19 | 20 | } 21 | }, 22 | "text_box.vertical_scroll_bar": 23 | { 24 | "misc": 25 | { 26 | "shape": "rounded_rectangle", 27 | "shape_corner_radius": "9" 28 | } 29 | }, 30 | "text_box.vertical_scroll_bar.button": 31 | { 32 | "misc": 33 | { 34 | "shape": "rounded_rectangle", 35 | "shape_corner_radius": "7" 36 | } 37 | }, 38 | 39 | "@white_text_box": 40 | { 41 | "colours": 42 | { 43 | "dark_bg":"#EEEFEF", 44 | "normal_border": "#884422" 45 | }, 46 | 47 | "misc": 48 | { 49 | "border_width": "6", 50 | "padding": "5,5" 51 | 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /data/themes/theme_2.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaults": 3 | { 4 | "colours": 5 | { 6 | "normal_bg": "#fb9e91", 7 | "hovered_bg": "#fbda91", 8 | "disabled_bg": "#cb6e61", 9 | "selected_bg": "#fb0091", 10 | "dark_bg": "#fb8691", 11 | "disabled_dark_bg": "#db6671", 12 | "normal_text": "#202020", 13 | "hovered_text": "#303030", 14 | "selected_text": "#404040", 15 | "disabled_text": "#000000", 16 | "link_text": "#0000EE", 17 | "link_hover": "#2020FF", 18 | "link_selected": "#551A8B", 19 | "text_shadow": "#777777", 20 | "normal_border": "#ffB2A5", 21 | "hovered_border": "#ffC2B5", 22 | "disabled_border": "#Df9285", 23 | "selected_border": "#ff00A1", 24 | "filled_bar": "#f4251b", 25 | "unfilled_bar": "#CCCCCC" 26 | } 27 | }, 28 | 29 | "#test_prototype_colours": 30 | { 31 | "colours": 32 | { 33 | "dark_bg": "#fb86fb,#fd92A0,180", 34 | "normal_border": "#ffB2A5", 35 | "normal_bg": "#fb9e91" 36 | } 37 | }, 38 | 39 | "#test_prototype_font": 40 | { 41 | "font": 42 | { 43 | "name": "montserrat", 44 | "size": "12", 45 | "bold": "1", 46 | "italic": "0", 47 | "regular_resource": { "package": "data.fonts", "resource": "Montserrat-Regular.ttf"}, 48 | "bold_resource": { "package": "data.fonts", "resource": "Montserrat-Bold.ttf"}, 49 | "italic_resource": { "package": "data.fonts", "resource": "Montserrat-Italic.ttf"}, 50 | "bold_italic_resource": { "package": "data.fonts", "resource": "Montserrat-BoldItalic.ttf"} 51 | } 52 | }, 53 | 54 | "#test_prototype_image": 55 | { 56 | "images": 57 | { 58 | "normal_image": { 59 | "package": "data.images", 60 | "resource": "splat.bmp", 61 | "sub_surface_rect": "0,0,32,32" 62 | }, 63 | "hovered_image": { 64 | "package": "data.images", 65 | "resource": "splat.bmp", 66 | "sub_surface_rect": "32,0,32,32" 67 | } 68 | } 69 | }, 70 | 71 | "horizontal_slider": 72 | { 73 | "prototype": "#test_prototype_colours", 74 | 75 | "colours": 76 | { 77 | "dark_bg": "#fb86fb,#fd92A0,90" 78 | }, 79 | "misc": 80 | { 81 | "enable_arrow_buttons": "1" 82 | } 83 | }, 84 | "horizontal_slider.@arrow_button": { 85 | "misc": 86 | { 87 | "shape": "rectangle", 88 | "shape_corner_radius": "0", 89 | "padding": "0,0", 90 | "shadow_width": "0", 91 | "border_width": "0", 92 | "text_vert_alignment_padding": "0" 93 | } 94 | }, 95 | "vertical_scroll_bar": 96 | { 97 | "colours": 98 | { 99 | "selected_bg": "#fb9e91", 100 | "dark_bg": "#fb8691" 101 | } 102 | }, 103 | 104 | "tool_tip.text_box": 105 | { 106 | "colours": 107 | { 108 | "dark_bg": "#fb9e91B0" 109 | }, 110 | "misc": 111 | { 112 | "shape": "rounded_rectangle", 113 | "shape_corner_radius": "10", 114 | "padding": "8,8" 115 | } 116 | }, 117 | 118 | "#hover_me_button": 119 | { 120 | "prototype": "#test_prototype_image", 121 | 122 | "misc": 123 | { 124 | "shape": "rounded_rectangle", 125 | "shape_corner_radius": "18", 126 | "shadow_width": "2", 127 | "border_width": "1", 128 | "state_transitions": 129 | { 130 | "normal_hovered": "0.2", 131 | "hovered_normal": "0.5" 132 | } 133 | } 134 | }, 135 | 136 | "#everything_button": 137 | { 138 | "prototype": "#test_prototype_image", 139 | 140 | "colours": 141 | { 142 | "normal_border": "#ffB2A5", 143 | "normal_text": "#FFFFFF,#FFA0A0,90" 144 | }, 145 | "misc": 146 | { 147 | "shape": "ellipse", 148 | "shadow_width": "2", 149 | "border_width": "1" 150 | } 151 | }, 152 | 153 | "text_entry_line": 154 | { 155 | "prototype": "#test_prototype_font", 156 | "colours": 157 | { 158 | "selected_bg": "#fb0091A0,#20fdA0A0,0", 159 | "normal_text": "#FFFFFF,#FFA0A0,90", 160 | "selected_text": "#FFFFFF,#A0A0FF,90", 161 | "text_cursor": "#A0A0FF" 162 | }, 163 | "misc": 164 | { 165 | "shape": "rounded_rectangle", 166 | "shape_corner_radius": "10", 167 | "border_width": "1", 168 | "padding": "2,0" 169 | } 170 | }, 171 | 172 | "#drop_down_shape_prototype": { 173 | "misc": { 174 | "shape": "rounded_rectangle", 175 | "shape_corner_radius": "4" 176 | } 177 | }, 178 | "#drop_down_text_prototype": 179 | { 180 | "font": 181 | { 182 | "name": "montserrat", 183 | "size": "12", 184 | "bold": "0", 185 | "italic": "1", 186 | "regular_resource": { "package": "data.fonts", "resource": "Montserrat-Regular.ttf"}, 187 | "bold_resource": { "package": "data.fonts", "resource": "Montserrat-Bold.ttf"}, 188 | "italic_resource": { "package": "data.fonts", "resource": "Montserrat-Italic.ttf"}, 189 | "bold_italic_resource": { "package": "data.fonts", "resource": "Montserrat-BoldItalic.ttf"} 190 | 191 | } 192 | }, 193 | "drop_down_menu": 194 | { 195 | "prototype": "#drop_down_shape_prototype", 196 | 197 | "colours": 198 | { 199 | "dark_bg": "#fb9e91", 200 | "normal_border": "#FFB0B0,#FFB0FF,0" 201 | }, 202 | "misc": 203 | { 204 | "shadow_width": "2", 205 | "border_width": "1", 206 | "expand_direction": "up", 207 | "open_button_width": "0" 208 | } 209 | }, 210 | 211 | "drop_down_menu.#drop_down_options_list": 212 | { 213 | "prototype": "#drop_down_shape_prototype", 214 | 215 | "misc": 216 | { 217 | "shadow_width": "2", 218 | "border_width": "1" 219 | } 220 | }, 221 | 222 | "drop_down_menu.#drop_down_options_list.vertical_scroll_bar": 223 | { 224 | "misc": 225 | { 226 | "shadow_width": "0", 227 | "border_width": "1", 228 | "enable_arrow_buttons": "0" 229 | } 230 | }, 231 | 232 | "drop_down_menu.#drop_down_options_list.button": 233 | { 234 | "prototype": "#drop_down_shape_prototype", 235 | "prototype": "#drop_down_text_prototype", 236 | 237 | "misc": 238 | { 239 | "shadow_width": "0", 240 | "border_width": "0", 241 | 242 | "state_transitions": 243 | { 244 | "normal_hovered": "0.2", 245 | "hovered_normal": "0.5" 246 | } 247 | } 248 | }, 249 | 250 | "drop_down_menu.button": 251 | { 252 | "prototype": "#drop_down_shape_prototype", 253 | "prototype": "#drop_down_text_prototype", 254 | 255 | "misc": 256 | { 257 | "shadow_width": "0", 258 | "border_width": "0", 259 | "state_transitions": 260 | { 261 | "normal_hovered": "0.2", 262 | "hovered_normal": "0.5" 263 | } 264 | } 265 | }, 266 | 267 | "screen_space_health_bar": 268 | { 269 | "colours": 270 | { 271 | "normal_text": "#FFFFFF" 272 | } 273 | }, 274 | 275 | "#base_window": 276 | { 277 | "misc": 278 | { 279 | "border_width": "8" 280 | } 281 | }, 282 | 283 | "#scaling_window": 284 | { 285 | "prototype": "#base_window", 286 | "misc": 287 | { 288 | "shadow_width": "1" 289 | } 290 | }, 291 | 292 | "#everything_window.horizontal_slider": 293 | { 294 | "colours": 295 | { 296 | "dark_bg": "#fb8691,#fd92A0,180", 297 | "normal_border": "#ffB2A5", 298 | "normal_bg": "#fb9e91" 299 | }, 300 | "misc": 301 | { 302 | "shape": "rounded_rectangle", 303 | "border_width": "2", 304 | "shadow_width": "1", 305 | "enable_arrow_buttons": "1" 306 | } 307 | }, 308 | "#everything_window.horizontal_slider.#sliding_button": 309 | { 310 | "misc": 311 | { 312 | "shape": "ellipse", 313 | "border_width": "1", 314 | "shadow_width": "1" 315 | } 316 | }, 317 | "#everything_window.#title_bar": 318 | { 319 | "font": 320 | { 321 | "name": "montserrat", 322 | "size": "12", 323 | "bold": "0", 324 | "italic": "1", 325 | "regular_resource": { "package": "data.fonts", "resource": "Montserrat-Regular.ttf"}, 326 | "bold_resource": { "package": "data.fonts", "resource": "Montserrat-Bold.ttf"}, 327 | "italic_resource": { "package": "data.fonts", "resource": "Montserrat-Italic.ttf"}, 328 | "bold_italic_resource": { "package": "data.fonts", "resource": "Montserrat-BoldItalic.ttf"} 329 | }, 330 | "misc": 331 | { 332 | "text_horiz_alignment": "left" 333 | } 334 | }, 335 | "#everything_window.label": 336 | { 337 | "colours": 338 | { 339 | "normal_text": "#0091fbFF,#20fdA0FF,90", 340 | "text_shadow": "#10101070" 341 | }, 342 | "misc": 343 | { 344 | "text_shadow_size": "1", 345 | "text_shadow_offset": "0,0" 346 | } 347 | }, 348 | "#everything_window.screen_space_health_bar": 349 | { 350 | "colours": 351 | { 352 | "normal_text": "#FFFFFF", 353 | "filled_bar": "#0091fbAA,#2060A0AA,90", 354 | "unfilled_bar": "#FF505090" 355 | }, 356 | "misc": 357 | { 358 | "shadow_width": "1" 359 | } 360 | }, 361 | "#everything_window.text_entry_line": 362 | { 363 | "prototype": "#test_prototype_font", 364 | "misc": 365 | { 366 | "text_horiz_alignment_padding": "2", 367 | "text_horiz_alignment": "left" 368 | } 369 | }, 370 | 371 | "panel": 372 | { 373 | "images": 374 | { 375 | "background_image": 376 | { 377 | "package": "data.images", 378 | "resource": "splat.bmp", 379 | "sub_surface_rect": "0,0,32,32" 380 | } 381 | } 382 | }, 383 | "#fps_counter": 384 | { 385 | "colours": 386 | { 387 | "normal_text": "#FFFFFF", 388 | "dark_bg": "#fb8691" 389 | }, 390 | "font": 391 | { 392 | "name": "noto_sans", 393 | "size": "32" 394 | } 395 | }, 396 | "#frame_timer": 397 | { 398 | "colours": 399 | { 400 | "normal_text": "#FFFFFF", 401 | "dark_bg": "#00000000" 402 | }, 403 | "font": 404 | { 405 | "name": "noto_sans", 406 | "size": "14" 407 | } 408 | } 409 | } 410 | -------------------------------------------------------------------------------- /data/themes/theme_3.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaults": { 3 | "colours": { 4 | "normal_bg": "#91fb91", 5 | "hovered_bg": "#BBffBB", 6 | "disabled_bg": "#cb6e61", 7 | "selected_bg": "#40B040", 8 | "active_bg": "#409040", 9 | "dark_bg": "#86fb91", 10 | "normal_text": "#202020", 11 | "hovered_text": "#303030", 12 | "selected_text": "#404040", 13 | "disabled_text": "#000000", 14 | "normal_border": "#71db71" 15 | } 16 | }, 17 | "window": 18 | { 19 | "misc": 20 | { 21 | "shape": "rounded_rectangle", 22 | "shape_corner_radius": "10,10,0,0" 23 | } 24 | }, 25 | "window.#title_bar": 26 | { 27 | "misc": 28 | { 29 | "shape": "rounded_rectangle", 30 | "shape_corner_radius": "10,0,0,0" 31 | } 32 | }, 33 | "window.#close_button": 34 | { 35 | "misc": 36 | { 37 | "shape": "rounded_rectangle", 38 | "shape_corner_radius": "0,10,0,0" 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /data/themes/translations_theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": 3 | { 4 | "font": 5 | [ 6 | { 7 | "name": "montserrat", 8 | "size": "16", 9 | "bold": "0", 10 | "italic": "0", 11 | "regular_resource": {"package": "data.fonts", 12 | "resource": "Montserrat-Regular.ttf"} 13 | }, 14 | { 15 | "name": "kosugimaru", 16 | "locale": "ja", 17 | "size": "16", 18 | "bold": "0", 19 | "italic": "0", 20 | "regular_resource": {"package": "data.fonts", 21 | "resource": "KosugiMaru-Regular.ttf"} 22 | }, 23 | { 24 | "name": "amiri", 25 | "locale": "ar", 26 | "size": "16", 27 | "bold": "0", 28 | "italic": "0", 29 | "regular_resource": {"package": "data.fonts", 30 | "resource": "Amiri-Regular.ttf"} 31 | }, 32 | { 33 | "name": "noto_rashi", 34 | "locale": "he", 35 | "size": "24", 36 | "bold": "0", 37 | "italic": "0", 38 | "regular_resource": {"package": "data.fonts", 39 | "resource": "NotoRashiHebrew-Regular.ttf"} 40 | }, 41 | { 42 | "name": "song_myung", 43 | "locale": "ko", 44 | "size": "24", 45 | "bold": "0", 46 | "italic": "0", 47 | "regular_resource": {"package": "data.fonts", 48 | "resource": "SongMyung-Regular.ttf"} 49 | }, 50 | { 51 | "name": "ma_shan_zhang", 52 | "locale": "zh", 53 | "size": "24", 54 | "bold": "0", 55 | "italic": "0", 56 | "regular_resource": {"package": "data.fonts", 57 | "resource": "MaShanZheng-Regular.ttf"} 58 | }, 59 | { 60 | "name": "noto_serif_georgian", 61 | "locale": "ge", 62 | "size": "24", 63 | "bold": "0", 64 | "italic": "0", 65 | "regular_resource": {"package": "data.fonts", 66 | "resource": "NotoSerifGeorgian-Regular.ttf"} 67 | } 68 | ] 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /data/themes/two_sided_border_theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "button": { 3 | "colours": { 4 | "normal_bg": "#45494e", 5 | "hovered_bg": "#35393e", 6 | "disabled_bg": "#25292e", 7 | "selected_bg": "#193754", 8 | "active_bg": "#193754", 9 | "normal_text": "#FFFFFF", 10 | "hovered_text": "#FFFFFF", 11 | "selected_text": "#FFFFFF", 12 | "disabled_text": "#6d736f", 13 | "active_text": "#FFFFFF", 14 | "normal_border": "#AAAAAA", 15 | "hovered_border": "#FFFFFF", 16 | "disabled_border": "#808080", 17 | "selected_border": "#8080B0", 18 | "active_border": "#8080B0" 19 | }, 20 | "misc": { 21 | "border_width": { 22 | "left": 0, 23 | "right": 2, 24 | "top": 1, 25 | "bottom": 3 26 | }, 27 | "shadow_width": 2, 28 | "shape": "rectangle" 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /data/translations/examples.ar.json: -------------------------------------------------------------------------------- 1 | { 2 | "ar": { 3 | "holmes_text_test": "

كان السيد شيرلوك هولمز، الذي عادة ما يصل متأخرًا جدًا في الصباح، باستثناء المناسبات غير المتكررة التي كان يستيقظ فيها طوال الليل، يجلس على مائدة الإفطار. وقفت على بساط المدفأة والتقطت العصا التي تركها زائرنا خلفه في الليلة السابقة. لقد كانت قطعة خشب سميكة وسميكة، ذات رأس منتفخ، من النوع المعروف باسم «محامي بينانج». أسفل الرأس مباشرة كان هناك شريط فضي عريض يبلغ عرضه بوصة واحدة تقريبًا. «إلى جيمس مورتيمر، م.ر.خ.س.، من أصدقائه في خ.خ.ه.،» محفور عليها التاريخ «1884». لقد كانت مجرد عصا كان يحملها ممارس الأسرة من الطراز القديم - كريمة وصلبة ومطمئنة.

", 4 | "hello_world_message_text": "مرحبا بالعالم" 5 | } 6 | } -------------------------------------------------------------------------------- /data/translations/examples.de.json: -------------------------------------------------------------------------------- 1 | { 2 | "de": { 3 | "holmes_text_test": "

   Mr. Sherlock Holmes, der morgens sehr spät aufzustehen pfl egte – wenn man einmal von jenen nicht seltenen Gelegenheiten absah, da er die ganze Nacht aufblieb –, saß am Frühstückstisch, während ich auf dem Kaminvorleger stand und den Spazierstock aufhob, den unser Besucher vergangene Nacht vergessen hatte. Es handelte sich um ein schönes, stabiles Stück Holz mit einem knollenförmigen Griff derjenigen Sorte, die bei uns unter dem Namen „Penang-Anwalt“ bekannt ist. Gleich unterhalb des Griffes war ein gut zwei Zentimeter breites Silberband befestigt, auf welchem die Widmung „Für James Mortimer, M. R. C. S., von seinen Freunden des C. C. H.“ eingraviert war, datiert auf das Jahr 1884; ein Stock, gerade wie ihn ein altmodischer Hausarzt getragen hätte: würdevoll, solide und zuverlässig.

", 4 | "hello_world_message_text": "Hallo Welt" 5 | } 6 | } -------------------------------------------------------------------------------- /data/translations/examples.en.json: -------------------------------------------------------------------------------- 1 | { 2 | "en": { 3 | "holmes_text_test": "

   Mr. Sherlock Holmes, who was usually very late in the mornings, save upon those not infrequent occasions when he was up all night, was seated at the breakfast table. I stood upon the hearth-rug and picked up the stick which our visitor had left behind him the night before. It was a fine, thick piece of wood, bulbous-headed, of the sort which is known as a “Penang lawyer.” Just under the head was a broad silver band nearly an inch across. “To James Mortimer, M.R.C.S., from his friends of the C.C.H.,” was engraved upon it, with the date “1884.” It was just such a stick as the old-fashioned family practitioner used to carry—dignified, solid, and reassuring.

", 4 | "hello_world_message_text": "Hello world" 5 | } 6 | } -------------------------------------------------------------------------------- /data/translations/examples.es.json: -------------------------------------------------------------------------------- 1 | { 2 | "es": { 3 | "holmes_text_test": "

   El señor Sherlock Holmes, que de ordinario se levantaba muy tarde, excepto en las ocasiones nada infrecuentes en que no se acostaba en toda la noche, estaba desayunando. Yo, que me hallaba de pie junto a la chimenea, me agaché para recoger el bastón olvidado por nuestro visitante de la noche anterior. Sólido, de madera de buena calidad y con un abultamiento a modo de empuñadura, era del tipo que se conoce como «abogado de Penang». Inmediatamente debajo de la protuberancia el bastón llevaba una ancha tira de plata, de más de dos centímetros, en la que estaba grabado «A James Mortimer, M.R.C.S., de sus amigos de C.C.H.», y el año, « 1884». Era exactamente la clase de bastón que solían llevar los médicos de cabecera a la antigua usanza: digno, sólido y que inspiraba confianza.

", 4 | "hello_world_message_text": "Hola Mundo" 5 | } 6 | } -------------------------------------------------------------------------------- /data/translations/examples.fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "fr": { 3 | "holmes_text_test": "

   Ce matin-là, M. Sherlock Holmes qui, sauf les cas assez fréquents où il passait les nuits, se levait tard, était assis devant la table de la salle à manger. Je me tenais près de la cheminée, examinant la canne que notre visiteur de la veille avait oubliée. C’était un joli bâton, solide, terminé par une boule — ce qu’on est convenu d'appeler « une permission de minuit ». Immédiatement au-dessous de la pomme, un cercle d’or, large de deux centimètres, portait l’inscription et la date suivantes : « À M. James Mortimer, ses amis du C. C. H. — 1884 ». Cette canne, digne, grave, rassurante, ressemblait à celles dont se servent les médecins « vieux jeu ».

", 4 | "hello_world_message_text": "Bonjour le monde" 5 | } 6 | } -------------------------------------------------------------------------------- /data/translations/examples.ge.json: -------------------------------------------------------------------------------- 1 | { 2 | "ge": { 3 | "holmes_text_test": "

No translation found yet.

", 4 | "hello_world_message_text": "Გამარჯობა მსოფლიო" 5 | } 6 | } -------------------------------------------------------------------------------- /data/translations/examples.he.json: -------------------------------------------------------------------------------- 1 | { 2 | "he": { 3 | "holmes_text_test": "

מר שרלוק הולמס, שבדרך כלל איחר מאוד בבקרים, מלבד אותם מקרים לא נדירים שבהם היה ער כל הלילה, ישב ליד שולחן ארוחת הבוקר. עמדתי על שטיח האח והרמתי את המקל שהאורח שלנו השאיר מאחוריו בלילה הקודם. זה היה חתיכת עץ עדינה ועבה, בעלת ראש בולבי, מהסוג שמכונה עורך דין פנאנג. ממש מתחת לראש הייתה רצועת כסף רחבה בקוטר של כמעט סנטימטר. לג'יימס מורטימר, M.R.C.S., מחבריו ל-C.C.H., נחקק עליו, עם התאריך 1884. זה היה בדיוק מקל כזה שהמתרגל המשפחתי המיושן נהג לשאת מכובד, מוצק ומרגיע.

", 4 | "hello_world_message_text": "שלום עולם" 5 | } 6 | } -------------------------------------------------------------------------------- /data/translations/examples.id.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": { 3 | "holmes_text_test": "

No translation found yet.

", 4 | "hello_world_message_text": "Halo Dunia" 5 | } 6 | } -------------------------------------------------------------------------------- /data/translations/examples.it.json: -------------------------------------------------------------------------------- 1 | { 2 | "it": { 3 | "holmes_text_test": "

   Sherlock Holmes, che olitamente si alzava molto tardi alla mattina - tranne i molto frequenti casi in cui rimaneva in piedi tutta la notte - era seduto al tavolo della prima colazione. Io mi ero chinato sulla stuoia distesa accanto al caminetto e avevo raccolto il bastone da passeggio dimenticato dal nostro ospite della sera prima. Era un bellissimo esemplare di solido legno, dall'impugnatura a bulbo del tipo noto col nome di \"Penang lawyer\". Proprio al disotto del pomo c’era una grossa striscia d'argento, larga quasi un pollice. Vi era inciso sopra: \"A James Mortimer, M.R.C.S., da parte dei suoi amici del C.C.H.\", con data \"1884\". Era proprio il tipo di bastone da passeggio che sono soliti portare i medici di famiglia all'antica: era dignitoso, massiccio, ispirava fiducia.

", 4 | "hello_world_message_text": "Ciao mondo" 5 | } 6 | } -------------------------------------------------------------------------------- /data/translations/examples.ja.json: -------------------------------------------------------------------------------- 1 | { 2 | "ja": { 3 | "holmes_text_test": "

No translation found yet.

", 4 | "hello_world_message_text": "こんにちは世界" 5 | } 6 | } -------------------------------------------------------------------------------- /data/translations/examples.ko.json: -------------------------------------------------------------------------------- 1 | { 2 | "ko": { 3 | "holmes_text_test": "

   미스터. 밤새도록 깨어 있는 경우를 제외하고는 대개 아침에 아주 늦게 도착하는 셜록 홈즈가 아침 식탁에 앉아 있었습니다. 나는 난로 깔개 위에 서서 방문객이 전날 밤에 두고 간 막대기를 집어들었습니다. 그것은 '페낭 변호사'로 알려진 종류의 가늘고 두꺼운 나무 조각으로 머리가 둥그스름했습니다. 머리 바로 아래에는 약 1인치 너비의 넓은 은색 띠가 있었습니다. “C.C.H.의 친구인 M.R.C.S. 제임스 모티머에게” 그 위에는 '1884년'이라는 날짜가 새겨져 있었습니다. 그것은 옛날 가정의가 들고 다니던 막대기와도 같았고, 위엄 있고 견고하며 안심이 되었습니다.

", 4 | "hello_world_message_text": "안녕 세상아" 5 | } 6 | } -------------------------------------------------------------------------------- /data/translations/examples.pl.json: -------------------------------------------------------------------------------- 1 | { 2 | "pl": { 3 | "holmes_text_test": "

   Pan Sherlock Holmes, który zwykle wstawał bardzo późno, z wyjątkiem nierzadkich okazji, kiedy nie spał całą noc, siedział przy stole śniadaniowym. Stałem na dywaniku przy kominku i podniosłem kij, który nasz gość zostawił za sobą poprzedniego wieczoru. Był to cienki, gruby kawałek drewna z bulwiastą głową, z rodzaju znanego jako prawnik z Penang. Tuż pod głową znajdowała się szeroka srebrna opaska o średnicy prawie cala. Do Jamesa Mortimera, M.R.C.S., od jego przyjaciół z C.C.H. był na nim wygrawerowany, z datą 1884. Był to właśnie taki kij, jaki staromodny lekarz rodzinny niósł z godnością, solidnością i pociechą.

", 4 | "hello_world_message_text": "Witaj świecie" 5 | } 6 | } -------------------------------------------------------------------------------- /data/translations/examples.pt.json: -------------------------------------------------------------------------------- 1 | { 2 | "pt": { 3 | "holmes_text_test": "

No translation found yet.

", 4 | "hello_world_message_text": "Olá Mundo" 5 | } 6 | } -------------------------------------------------------------------------------- /data/translations/examples.ru.json: -------------------------------------------------------------------------------- 1 | { 2 | "ru": { 3 | "holmes_text_test": "

   Мистер Шерлок Холмс сидел за столом и завтракал. Обычно он вставал довольно поздно, если не считать тех нередких случаев, когда ему вовсе не приходилось ложиться. Я стоял на коврике у камина и вертел в руках палку, забытую нашим вчерашним посетителем, хорошую толстую палку с набалдашником - из тех, что именуются \"веским доказательством\". Чуть ниже набалдашника было врезано серебряное кольцо шириной около дюйма. На кольце было начертано: \"Джеймсу Мортимеру, Ч. К. X. О., от его друзей по ЧКЛ\" и дата: \"1884\". В прежние времена с такими палками - солидными, увесистыми, надежными - ходили почтенные домашние врачи.

", 4 | "hello_world_message_text": "Привет мир" 5 | } 6 | } -------------------------------------------------------------------------------- /data/translations/examples.uk.json: -------------------------------------------------------------------------------- 1 | { 2 | "uk": { 3 | "holmes_text_test": "

Містер Шерлок Холмс, який вставав, як правило, дуже пізно, за винятком тих досить численних випадків, коли не лягав спати зовсім, сидів за столом і снідав. Я стояв на килимку біля каміна й крутив у руках ціпок, що його напередодні ввечері забув наш відвідувач. Це був гарний, з чималою головкою, дебелий ціпок — з тих, що відомі під назвою «ломака». Під головкою ціпок охоплювало срібне кільце завширшки майже в дюйм. На ньому було вигравірувано: «Джеймсові Мортімеру, Ч.К.Х.Т., від його друзів по ЧКЛ» і рік «1884». З такими ціпками-палицями — показними, масивними й надійними — мали за звичай ходити старомодні домашні лікарі.

", 4 | "hello_world_message_text": "Привіт Світ" 5 | } 6 | } -------------------------------------------------------------------------------- /data/translations/examples.vi.json: -------------------------------------------------------------------------------- 1 | { 2 | "vi": { 3 | "holmes_text_test": "

No translation found yet.

", 4 | "hello_world_message_text": "Chào thế giới" 5 | } 6 | } -------------------------------------------------------------------------------- /data/translations/examples.zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "zh": { 3 | "holmes_text_test": "

   歇洛克·福尔摩斯先生坐在桌旁早餐,他除了时常彻夜不眠之外,早晨总是起得很晚的。我站在壁炉前的小地毯上,拿起了昨晚那位客人遗忘的手杖。这是一根很精致而又沉重的手杖,顶端有个疙疸;这种木料产于槟榔屿,名叫槟榔子木。紧挨顶端的下面是一圈很宽的银箍,宽度约有一英寸。上刻“送给皇家外科医学院学士杰姆士·摩梯末,C.C.H.的朋友们赠”,还刻有“一八八四年”。这不过是一根旧式的私人医生所常用的那种既庄重、坚固而又实用的手杖。

", 4 | "hello_world_message_text": "你好世界" 5 | } 6 | } -------------------------------------------------------------------------------- /docs/example_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MyreMylar/pygame_gui_examples/75ba91f92be3b0fe9396e3c6ec184293bc17bd0c/docs/example_1.png -------------------------------------------------------------------------------- /documentation_test.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import pygame_gui 3 | 4 | 5 | """ 6 | Useful example for building documentation images 7 | """ 8 | 9 | 10 | class TestSprite(pygame.sprite.Sprite): 11 | def __init__(self, *groups): 12 | super().__init__(*groups) 13 | self.health_capacity = 100 14 | self.current_health = 75 15 | self.rect = pygame.Rect(150, 150, 50, 75) 16 | 17 | 18 | pygame.init() 19 | 20 | pygame.display.set_caption('Quick Start') 21 | window_surface = pygame.display.set_mode((800, 600)) 22 | manager = pygame_gui.UIManager((800, 600), 'data/themes/documentation_theme.json') 23 | 24 | background = pygame.Surface((800, 600)) 25 | background.fill(pygame.Color('#fcfcfc')) 26 | 27 | # pygame_gui.elements.UIDropDownMenu(options_list=['Easy', 'Medium', 'Hard', 'Very Hard'], 28 | # starting_option='Medium', 29 | # relative_rect=pygame.Rect((350, 280), (250, 50)), 30 | # manager=manager) 31 | 32 | # pygame_gui.elements.UIHorizontalSlider(relative_rect=pygame.Rect((350, 280), (250, 40)), 33 | # start_value=50, 34 | # value_range=(0, 100), 35 | # manager=manager) 36 | 37 | # pygame_gui.elements.UILabel(relative_rect=pygame.Rect((350, 280), (350, 60)), 38 | # text='label text', 39 | # manager=manager) 40 | 41 | # pygame_gui.elements.UIScreenSpaceHealthBar(relative_rect=pygame.Rect((350, 280), (250, 40)), 42 | # manager=manager) 43 | 44 | # pygame_gui.elements.UITextBox(html_text="This is normal text. This a link", 45 | # relative_rect=pygame.Rect((150, 150), (150, 100)), 46 | # manager=manager) 47 | 48 | # pygame_gui.elements.UITextEntryLine(relative_rect=pygame.Rect((350, 280), (250, 40)), 49 | # manager=manager) 50 | 51 | # pygame_gui.elements.UIVerticalScrollBar(relative_rect=pygame.Rect((280, 150), (30, 250)), 52 | # visible_percentage=0.8, 53 | # manager=manager) 54 | 55 | # test_sprite = TestSprite() 56 | # pygame_gui.elements.UIWorldSpaceHealthBar(relative_rect=pygame.Rect((350, 280), (150, 35)), 57 | # sprite_to_monitor=test_sprite, 58 | # manager=manager) 59 | 60 | pygame_gui.windows.UIColourPickerDialog(rect=pygame.Rect(100, 100, 390, 390), 61 | manager=manager) 62 | 63 | clock = pygame.time.Clock() 64 | is_running = True 65 | 66 | while is_running: 67 | time_delta = clock.tick(60)/1000.0 68 | for event in pygame.event.get(): 69 | if event.type == pygame.QUIT: 70 | is_running = False 71 | 72 | manager.process_events(event) 73 | 74 | manager.update(time_delta) 75 | 76 | window_surface.blit(background, (0, 0)) 77 | manager.draw_ui(window_surface) 78 | 79 | pygame.display.update() 80 | -------------------------------------------------------------------------------- /example_auto_scale_button_images.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Example demonstrating the auto_scale_image functionality for UIButton. 4 | 5 | This example shows how to use the new auto_scale_image theming parameter 6 | to automatically scale button images to fit the button size while maintaining 7 | aspect ratio. 8 | """ 9 | 10 | import pygame 11 | import pygame_gui 12 | import json 13 | import os 14 | 15 | 16 | def main(): 17 | # Initialize pygame 18 | pygame.init() 19 | screen = pygame.display.set_mode((1000, 700)) 20 | pygame.display.set_caption("UIButton Auto-Scale Image Example") 21 | clock = pygame.time.Clock() 22 | 23 | # Create theme with auto_scale_image enabled 24 | theme_data = { 25 | "button": { 26 | "misc": { 27 | "auto_scale_images": "1" # Enable auto-scaling 28 | }, 29 | "images": { 30 | "normal_image": { 31 | "path": "data/images/splat.png" 32 | } 33 | } 34 | }, 35 | "#button_no_scale": { 36 | "misc": { 37 | "auto_scale_images": "0" # Disable auto-scaling for comparison 38 | }, 39 | "images": { 40 | "normal_image": { 41 | "path": "data/images/splat.png" 42 | } 43 | } 44 | } 45 | } 46 | 47 | # Save theme to temporary file 48 | theme_file = "auto_scale_theme.json" 49 | with open(theme_file, "w") as f: 50 | json.dump(theme_data, f, indent=2) 51 | 52 | try: 53 | # Create UI manager with the theme 54 | manager = pygame_gui.UIManager((1000, 700), theme_file) 55 | 56 | # Create title 57 | title = pygame_gui.elements.UILabel( 58 | relative_rect=pygame.Rect(10, 10, 980, 40), 59 | text="UIButton Auto-Scale Image Demonstration", 60 | manager=manager 61 | ) 62 | 63 | # Create subtitle for auto-scaled buttons 64 | subtitle1 = pygame_gui.elements.UILabel( 65 | relative_rect=pygame.Rect(10, 60, 480, 30), 66 | text="Auto-Scaled Images (maintains aspect ratio):", 67 | manager=manager 68 | ) 69 | 70 | # Create subtitle for non-scaled buttons 71 | subtitle2 = pygame_gui.elements.UILabel( 72 | relative_rect=pygame.Rect(510, 60, 480, 30), 73 | text="Original Images (no scaling):", 74 | manager=manager 75 | ) 76 | 77 | # Create buttons with auto-scaling enabled 78 | auto_scale_buttons = [] 79 | 80 | # Small square button 81 | small_button = pygame_gui.elements.UIButton( 82 | relative_rect=pygame.Rect(50, 100, 60, 60), 83 | text="Small", 84 | manager=manager 85 | ) 86 | auto_scale_buttons.append(("Small (60x60)", small_button)) 87 | 88 | # Medium square button 89 | medium_button = pygame_gui.elements.UIButton( 90 | relative_rect=pygame.Rect(130, 100, 100, 100), 91 | text="Medium", 92 | manager=manager 93 | ) 94 | auto_scale_buttons.append(("Medium (100x100)", medium_button)) 95 | 96 | # Large square button 97 | large_button = pygame_gui.elements.UIButton( 98 | relative_rect=pygame.Rect(250, 100, 150, 150), 99 | text="Large", 100 | manager=manager 101 | ) 102 | auto_scale_buttons.append(("Large (150x150)", large_button)) 103 | 104 | # Wide rectangular button 105 | wide_button = pygame_gui.elements.UIButton( 106 | relative_rect=pygame.Rect(50, 270, 200, 80), 107 | text="Wide Rectangle", 108 | manager=manager 109 | ) 110 | auto_scale_buttons.append(("Wide (200x80)", wide_button)) 111 | 112 | # Tall rectangular button 113 | tall_button = pygame_gui.elements.UIButton( 114 | relative_rect=pygame.Rect(270, 270, 80, 150), 115 | text="Tall", 116 | manager=manager 117 | ) 118 | auto_scale_buttons.append(("Tall (80x150)", tall_button)) 119 | 120 | # Very small button 121 | tiny_button = pygame_gui.elements.UIButton( 122 | relative_rect=pygame.Rect(370, 270, 30, 30), 123 | text="", 124 | manager=manager 125 | ) 126 | auto_scale_buttons.append(("Tiny (30x30)", tiny_button)) 127 | 128 | # Create buttons without auto-scaling for comparison 129 | no_scale_buttons = [] 130 | 131 | # Small square button (no scaling) 132 | small_button_ns = pygame_gui.elements.UIButton( 133 | relative_rect=pygame.Rect(550, 100, 60, 60), 134 | text="Small", 135 | manager=manager, 136 | object_id="#button_no_scale" 137 | ) 138 | no_scale_buttons.append(("Small (60x60)", small_button_ns)) 139 | 140 | # Medium square button (no scaling) 141 | medium_button_ns = pygame_gui.elements.UIButton( 142 | relative_rect=pygame.Rect(630, 100, 100, 100), 143 | text="Medium", 144 | manager=manager, 145 | object_id="#button_no_scale" 146 | ) 147 | no_scale_buttons.append(("Medium (100x100)", medium_button_ns)) 148 | 149 | # Large square button (no scaling) 150 | large_button_ns = pygame_gui.elements.UIButton( 151 | relative_rect=pygame.Rect(750, 100, 150, 150), 152 | text="Large", 153 | manager=manager, 154 | object_id="#button_no_scale" 155 | ) 156 | no_scale_buttons.append(("Large (150x150)", large_button_ns)) 157 | 158 | # Wide rectangular button (no scaling) 159 | wide_button_ns = pygame_gui.elements.UIButton( 160 | relative_rect=pygame.Rect(550, 270, 200, 80), 161 | text="Wide Rectangle", 162 | manager=manager, 163 | object_id="#button_no_scale" 164 | ) 165 | no_scale_buttons.append(("Wide (200x80)", wide_button_ns)) 166 | 167 | # Tall rectangular button (no scaling) 168 | tall_button_ns = pygame_gui.elements.UIButton( 169 | relative_rect=pygame.Rect(770, 270, 80, 150), 170 | text="Tall", 171 | manager=manager, 172 | object_id="#button_no_scale" 173 | ) 174 | no_scale_buttons.append(("Tall (80x150)", tall_button_ns)) 175 | 176 | # Very small button (no scaling) 177 | tiny_button_ns = pygame_gui.elements.UIButton( 178 | relative_rect=pygame.Rect(870, 270, 30, 30), 179 | text="", 180 | manager=manager, 181 | object_id="#button_no_scale" 182 | ) 183 | no_scale_buttons.append(("Tiny (30x30)", tiny_button_ns)) 184 | 185 | # Create explanation text 186 | explanation = pygame_gui.elements.UITextBox( 187 | relative_rect=pygame.Rect(50, 450, 900, 200), 188 | html_text=""" 189 | Auto-Scale Image Feature:

190 | 191 | The left side shows buttons with auto_scale_image: "1" enabled. Notice how the images 192 | scale to fit each button size while maintaining their original aspect ratio.

193 | 194 | The right side shows buttons with auto_scale_image: "0" (default). The images appear 195 | at their original size, which may not fit well with different button sizes.

196 | 197 | Key Benefits:
198 | • Images automatically scale to fit button dimensions
199 | • Aspect ratio is preserved to prevent distortion
200 | • Works with all button states (normal, hovered, selected, disabled)
201 | • Improves visual consistency across different button sizes

202 | 203 | Usage: Add "auto_scale_image": "1" to the "misc" block in your button theme. 204 | """, 205 | manager=manager 206 | ) 207 | 208 | print("Auto-Scale Image Example Running") 209 | print("================================") 210 | print("Left side: Auto-scaled images (maintains aspect ratio)") 211 | print("Right side: Original images (no scaling)") 212 | print("Press ESC to exit") 213 | 214 | # Main loop 215 | running = True 216 | while running: 217 | time_delta = clock.tick(60) / 1000.0 218 | 219 | for event in pygame.event.get(): 220 | if event.type == pygame.QUIT: 221 | running = False 222 | elif event.type == pygame.KEYDOWN: 223 | if event.key == pygame.K_ESCAPE: 224 | running = False 225 | elif event.type == pygame_gui.UI_BUTTON_PRESSED: 226 | print(f"Button pressed: {event.ui_element.text}") 227 | 228 | manager.process_events(event) 229 | 230 | manager.update(time_delta) 231 | 232 | # Clear screen 233 | screen.fill((40, 40, 40)) 234 | 235 | # Draw UI 236 | manager.draw_ui(screen) 237 | 238 | # Draw labels for buttons 239 | font = pygame.font.Font(None, 20) 240 | 241 | # Labels for auto-scaled buttons 242 | for i, (label, button) in enumerate(auto_scale_buttons): 243 | text_surface = font.render(label, True, (200, 200, 200)) 244 | screen.blit(text_surface, (button.rect.left, button.rect.bottom + 5)) 245 | 246 | # Labels for non-scaled buttons 247 | for i, (label, button) in enumerate(no_scale_buttons): 248 | text_surface = font.render(label, True, (200, 200, 200)) 249 | screen.blit(text_surface, (button.rect.left, button.rect.bottom + 5)) 250 | 251 | pygame.display.flip() 252 | 253 | finally: 254 | # Cleanup 255 | if os.path.exists(theme_file): 256 | os.remove(theme_file) 257 | pygame.quit() 258 | 259 | 260 | if __name__ == "__main__": 261 | main() -------------------------------------------------------------------------------- /example_check_box_multi_image.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import pygame 4 | import pygame_gui 5 | import tempfile 6 | import json 7 | import os 8 | 9 | 10 | def create_test_images(): 11 | """Create test images for the demo.""" 12 | # Create different colored squares for different layers/states 13 | images = {} 14 | 15 | # Background images (larger, semi-transparent) 16 | bg_normal = pygame.Surface((24, 24), pygame.SRCALPHA) 17 | bg_normal.fill((100, 100, 100, 180)) # Gray background 18 | images['bg_normal'] = bg_normal 19 | 20 | bg_hovered = pygame.Surface((24, 24), pygame.SRCALPHA) 21 | bg_hovered.fill((120, 150, 200, 180)) # Blue background 22 | images['bg_hovered'] = bg_hovered 23 | 24 | bg_selected = pygame.Surface((24, 24), pygame.SRCALPHA) 25 | bg_selected.fill((100, 200, 100, 180)) # Green background 26 | images['bg_selected'] = bg_selected 27 | 28 | bg_disabled = pygame.Surface((24, 24), pygame.SRCALPHA) 29 | bg_disabled.fill((80, 80, 80, 180)) # Dark gray background 30 | images['bg_disabled'] = bg_disabled 31 | 32 | # Border images (medium size) 33 | border_normal = pygame.Surface((20, 20), pygame.SRCALPHA) 34 | pygame.draw.rect(border_normal, (60, 60, 60), (0, 0, 20, 20), 2) 35 | images['border_normal'] = border_normal 36 | 37 | border_hovered = pygame.Surface((20, 20), pygame.SRCALPHA) 38 | pygame.draw.rect(border_hovered, (80, 120, 160), (0, 0, 20, 20), 2) 39 | images['border_hovered'] = border_hovered 40 | 41 | border_selected = pygame.Surface((20, 20), pygame.SRCALPHA) 42 | pygame.draw.rect(border_selected, (60, 160, 60), (0, 0, 20, 20), 2) 43 | images['border_selected'] = border_selected 44 | 45 | border_disabled = pygame.Surface((20, 20), pygame.SRCALPHA) 46 | pygame.draw.rect(border_disabled, (40, 40, 40), (0, 0, 20, 20), 2) 47 | images['border_disabled'] = border_disabled 48 | 49 | # Icon/symbol images (smaller, centered) 50 | # Checkmark for selected state 51 | checkmark = pygame.Surface((16, 16), pygame.SRCALPHA) 52 | pygame.draw.lines(checkmark, (255, 255, 255), False, [(3, 8), (6, 11), (13, 4)], 3) 53 | images['checkmark'] = checkmark 54 | 55 | # Hover highlight 56 | highlight = pygame.Surface((18, 18), pygame.SRCALPHA) 57 | pygame.draw.circle(highlight, (255, 255, 255, 100), (9, 9), 8) 58 | images['highlight'] = highlight 59 | 60 | # Disabled overlay 61 | disabled_overlay = pygame.Surface((22, 22), pygame.SRCALPHA) 62 | pygame.draw.line(disabled_overlay, (255, 0, 0, 150), (2, 2), (20, 20), 2) 63 | pygame.draw.line(disabled_overlay, (255, 0, 0, 150), (20, 2), (2, 20), 2) 64 | images['disabled_overlay'] = disabled_overlay 65 | 66 | return images 67 | 68 | 69 | def save_test_images(images, temp_dir): 70 | """Save test images to temporary files and return paths.""" 71 | image_paths = {} 72 | for name, surface in images.items(): 73 | path = os.path.join(temp_dir, f"{name}.png") 74 | pygame.image.save(surface, path) 75 | image_paths[name] = path 76 | return image_paths 77 | 78 | 79 | def create_multi_image_checkbox_theme(image_paths): 80 | """Create a theme with multi-image support for checkboxes using real image paths.""" 81 | return { 82 | "check_box": { 83 | "images": { 84 | "normal_images": [ 85 | {"id": "background", "path": image_paths['bg_normal'], "layer": 0}, 86 | {"id": "border", "path": image_paths['border_normal'], "layer": 1} 87 | ], 88 | "hovered_images": [ 89 | {"id": "background", "path": image_paths['bg_hovered'], "layer": 0}, 90 | {"id": "border", "path": image_paths['border_hovered'], "layer": 1}, 91 | {"id": "highlight", "path": image_paths['highlight'], "layer": 2} 92 | ], 93 | "selected_images": [ 94 | {"id": "background", "path": image_paths['bg_selected'], "layer": 0}, 95 | {"id": "border", "path": image_paths['border_selected'], "layer": 1}, 96 | {"id": "checkmark", "path": image_paths['checkmark'], "layer": 2} 97 | ], 98 | "disabled_images": [ 99 | {"id": "background", "path": image_paths['bg_disabled'], "layer": 0}, 100 | {"id": "border", "path": image_paths['border_disabled'], "layer": 1}, 101 | {"id": "disabled_overlay", "path": image_paths['disabled_overlay'], "layer": 2} 102 | ] 103 | }, 104 | "misc": { 105 | "text_offset": 10 106 | } 107 | } 108 | } 109 | 110 | 111 | def create_single_image_checkbox_theme(image_paths): 112 | """Create a theme with single-image support for checkboxes.""" 113 | return { 114 | "check_box": { 115 | "images": { 116 | "normal_image": {"path": image_paths['bg_normal']}, 117 | "hovered_image": {"path": image_paths['bg_hovered']}, 118 | "selected_image": {"path": image_paths['bg_selected']}, 119 | "disabled_image": {"path": image_paths['bg_disabled']} 120 | }, 121 | "misc": { 122 | "text_offset": 10 123 | } 124 | } 125 | } 126 | 127 | 128 | def main(): 129 | pygame.init() 130 | 131 | # Set up the display 132 | window_surface = pygame.display.set_mode((800, 600)) 133 | pygame.display.set_caption('Multi-Image Checkbox Demo - Enhanced') 134 | 135 | # Create temporary directory for images 136 | temp_dir = tempfile.mkdtemp() 137 | 138 | try: 139 | # Create and save test images 140 | test_images = create_test_images() 141 | image_paths = save_test_images(test_images, temp_dir) 142 | 143 | # Create theme files 144 | multi_theme_data = create_multi_image_checkbox_theme(image_paths) 145 | with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f: 146 | json.dump(multi_theme_data, f) 147 | multi_theme_file = f.name 148 | 149 | single_theme_data = create_single_image_checkbox_theme(image_paths) 150 | with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f: 151 | json.dump(single_theme_data, f) 152 | single_theme_file = f.name 153 | 154 | # Create UI manager with multi-image theme 155 | manager = pygame_gui.UIManager((800, 600), multi_theme_file) 156 | 157 | # Create multiple checkboxes to demonstrate different states 158 | checkbox1 = pygame_gui.elements.UICheckBox( 159 | relative_rect=pygame.Rect(50, 50, 30, 30), 160 | text="Normal Multi-Image Checkbox", 161 | manager=manager 162 | ) 163 | 164 | checkbox2 = pygame_gui.elements.UICheckBox( 165 | relative_rect=pygame.Rect(50, 100, 30, 30), 166 | text="Pre-checked Checkbox", 167 | manager=manager, 168 | initial_state=True 169 | ) 170 | 171 | checkbox3 = pygame_gui.elements.UICheckBox( 172 | relative_rect=pygame.Rect(50, 150, 30, 30), 173 | text="Disabled Checkbox", 174 | manager=manager 175 | ) 176 | checkbox3.disable() 177 | 178 | # Print initial state information 179 | print("=== Multi-Image Checkbox Demo - Enhanced ===") 180 | print(f"Checkbox 1 - Multi-image mode: {checkbox1.is_multi_image_mode()}") 181 | print(f"Checkbox 1 - Image count: {checkbox1.get_image_count()}") 182 | print(f"Checkbox 1 - Current images: {len(checkbox1.get_current_images())}") 183 | print("Images by state:") 184 | for state in ["normal", "hovered", "selected", "disabled"]: 185 | images = checkbox1.get_images_by_state(state) 186 | print(f" {state}: {len(images)} images") 187 | 188 | # Create control buttons 189 | switch_button = pygame_gui.elements.UIButton( 190 | relative_rect=pygame.Rect(50, 250, 200, 40), 191 | text='Switch Theme Mode', 192 | manager=manager 193 | ) 194 | 195 | toggle_button = pygame_gui.elements.UIButton( 196 | relative_rect=pygame.Rect(50, 300, 200, 40), 197 | text='Toggle Checkbox 1', 198 | manager=manager 199 | ) 200 | 201 | disable_button = pygame_gui.elements.UIButton( 202 | relative_rect=pygame.Rect(50, 350, 200, 40), 203 | text='Toggle Disable Checkbox 1', 204 | manager=manager 205 | ) 206 | 207 | indeterminate_button = pygame_gui.elements.UIButton( 208 | relative_rect=pygame.Rect(50, 400, 200, 40), 209 | text='Set Indeterminate', 210 | manager=manager 211 | ) 212 | 213 | # Create info labels 214 | info_label = pygame_gui.elements.UITextBox( 215 | relative_rect=pygame.Rect(300, 50, 450, 400), 216 | html_text="Multi-Image Checkbox Features:\n\n" 217 | "• Normal state: Background + Border (2 layers)\n" 218 | "• Hovered state: Background + Border + Highlight (3 layers)\n" 219 | "• Selected state: Background + Border + Checkmark (3 layers)\n" 220 | "• Disabled state: Background + Border + X overlay (3 layers)\n\n" 221 | "Hover over checkboxes to see layered effects!\n" 222 | "Click checkboxes to toggle their state.\n" 223 | "Use buttons below to test different features.", 224 | manager=manager 225 | ) 226 | 227 | 228 | status_label = pygame_gui.elements.UILabel( 229 | relative_rect=pygame.Rect(300, 470, 450, 100), 230 | text="Status: Multi-image mode active", 231 | manager=manager 232 | ) 233 | 234 | clock = pygame.time.Clock() 235 | is_running = True 236 | using_multi_theme = True 237 | 238 | print("==================================================") 239 | print("ENHANCED MULTI-IMAGE CHECKBOX DEMONSTRATION") 240 | print("==================================================") 241 | print("• Hover over checkboxes to see layered visual effects") 242 | print("• Click checkboxes directly to toggle their state") 243 | print("• Use control buttons to test different features") 244 | print("• Switch between multi-image and single-image themes") 245 | print("• Press ESC to exit") 246 | print("==================================================") 247 | 248 | while is_running: 249 | time_delta = clock.tick(60) / 1000.0 250 | 251 | for event in pygame.event.get(): 252 | if event.type == pygame.QUIT: 253 | is_running = False 254 | 255 | if event.type == pygame.KEYDOWN: 256 | if event.key == pygame.K_ESCAPE: 257 | is_running = False 258 | 259 | if event.type == pygame_gui.UI_BUTTON_PRESSED: 260 | if event.ui_element == switch_button: 261 | # Switch between themes 262 | if using_multi_theme: 263 | manager.ui_theme.load_theme(single_theme_file) 264 | using_multi_theme = False 265 | theme_status = "Single-image mode active" 266 | print("=== Switched to Single-Image Theme ===") 267 | else: 268 | manager.ui_theme.load_theme(multi_theme_file) 269 | using_multi_theme = True 270 | theme_status = "Multi-image mode active" 271 | print("=== Switched to Multi-Image Theme ===") 272 | 273 | status_label.set_text(f"Status: {theme_status}") 274 | 275 | # Force rebuild to apply new theme 276 | checkbox1.rebuild_from_changed_theme_data() 277 | checkbox2.rebuild_from_changed_theme_data() 278 | checkbox3.rebuild_from_changed_theme_data() 279 | switch_button.rebuild_from_changed_theme_data() 280 | toggle_button.rebuild_from_changed_theme_data() 281 | disable_button.rebuild_from_changed_theme_data() 282 | indeterminate_button.rebuild_from_changed_theme_data() 283 | info_label.rebuild_from_changed_theme_data() 284 | status_label.rebuild_from_changed_theme_data() 285 | 286 | # Print new state 287 | print(f"Multi-image mode: {checkbox1.is_multi_image_mode()}") 288 | print(f"Image count: {checkbox1.get_image_count()}") 289 | print(f"Current images: {len(checkbox1.get_current_images())}") 290 | 291 | elif event.ui_element == toggle_button: 292 | # Toggle checkbox state 293 | current_state = checkbox1.get_state() 294 | if current_state == "indeterminate": 295 | checkbox1.set_state(False) 296 | else: 297 | checkbox1.set_state(not checkbox1.is_checked) 298 | 299 | new_state = checkbox1.get_state() 300 | print(f"Checkbox 1 state: {new_state}") 301 | print(f"Current images: {len(checkbox1.get_current_images())}") 302 | status_label.set_text(f"Status: Checkbox 1 is {new_state}") 303 | 304 | elif event.ui_element == disable_button: 305 | # Toggle enabled/disabled state 306 | if checkbox1.is_enabled: 307 | checkbox1.disable() 308 | print("Checkbox 1 disabled") 309 | status_label.set_text("Status: Checkbox 1 disabled") 310 | else: 311 | checkbox1.enable() 312 | print("Checkbox 1 enabled") 313 | status_label.set_text("Status: Checkbox 1 enabled") 314 | print(f"Current images: {len(checkbox1.get_current_images())}") 315 | 316 | elif event.ui_element == indeterminate_button: 317 | # Set indeterminate state 318 | checkbox1.set_indeterminate(True) 319 | print("Checkbox 1 set to indeterminate") 320 | print(f"Current images: {len(checkbox1.get_current_images())}") 321 | status_label.set_text("Status: Checkbox 1 is indeterminate") 322 | 323 | if event.type == pygame_gui.UI_CHECK_BOX_CHECKED: 324 | print(f"Checkbox checked: {event.ui_element}") 325 | if event.ui_element == checkbox1: 326 | status_label.set_text("Status: Checkbox 1 checked") 327 | elif event.ui_element == checkbox2: 328 | status_label.set_text("Status: Checkbox 2 checked") 329 | 330 | if event.type == pygame_gui.UI_CHECK_BOX_UNCHECKED: 331 | print(f"Checkbox unchecked: {event.ui_element}") 332 | if event.ui_element == checkbox1: 333 | status_label.set_text("Status: Checkbox 1 unchecked") 334 | elif event.ui_element == checkbox2: 335 | status_label.set_text("Status: Checkbox 2 unchecked") 336 | 337 | manager.process_events(event) 338 | 339 | manager.update(time_delta) 340 | 341 | # Draw background 342 | window_surface.fill((40, 40, 40)) 343 | 344 | # Draw UI 345 | manager.draw_ui(window_surface) 346 | 347 | pygame.display.update() 348 | 349 | finally: 350 | # Clean up temporary files 351 | try: 352 | os.unlink(multi_theme_file) 353 | os.unlink(single_theme_file) 354 | # Clean up image files 355 | for path in image_paths.values(): 356 | try: 357 | os.unlink(path) 358 | except: 359 | pass 360 | os.rmdir(temp_dir) 361 | except: 362 | pass 363 | 364 | pygame.quit() 365 | 366 | 367 | if __name__ == '__main__': 368 | main() 369 | -------------------------------------------------------------------------------- /file_dialog_test.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import pygame_gui 3 | 4 | from pygame_gui.elements import UIButton, UIImage 5 | from pygame_gui.windows import UIFileDialog 6 | from pygame_gui.core.utility import create_resource_path 7 | 8 | 9 | class ImageLoadApp: 10 | def __init__(self): 11 | pygame.init() 12 | 13 | pygame.display.set_caption('Image Load App') 14 | self.window_surface = pygame.display.set_mode((800, 600)) 15 | self.ui_manager = pygame_gui.UIManager((800, 600), 'data/themes/image_load_app_theme.json') 16 | 17 | self.background = pygame.Surface((800, 600)) 18 | self.background.fill(self.ui_manager.ui_theme.get_colour('dark_bg')) 19 | 20 | self.load_button = UIButton(relative_rect=pygame.Rect(-180, -60, 150, 30), 21 | text='Load Image', 22 | manager=self.ui_manager, 23 | anchors={'left': 'right', 24 | 'right': 'right', 25 | 'top': 'bottom', 26 | 'bottom': 'bottom'}) 27 | 28 | self.file_dialog = None 29 | 30 | # scale images, if necessary so that their largest dimension does not exceed these values 31 | self.max_image_display_dimensions = (400, 400) 32 | self.display_loaded_image = None 33 | 34 | self.clock = pygame.time.Clock() 35 | self.is_running = True 36 | 37 | def run(self): 38 | while self.is_running: 39 | time_delta = self.clock.tick(60) / 1000.0 40 | for event in pygame.event.get(): 41 | if event.type == pygame.QUIT: 42 | self.is_running = False 43 | 44 | if (event.type == pygame_gui.UI_BUTTON_PRESSED and 45 | event.ui_element == self.load_button): 46 | self.file_dialog = UIFileDialog(pygame.Rect(160, 50, 440, 500), 47 | self.ui_manager, 48 | window_title='Load Image...', 49 | initial_file_path='data/images/', 50 | allow_picking_directories=True, 51 | allow_existing_files_only=True, 52 | allowed_suffixes={""}) 53 | self.load_button.disable() 54 | 55 | if event.type == pygame_gui.UI_FILE_DIALOG_PATH_PICKED: 56 | if self.display_loaded_image is not None: 57 | self.display_loaded_image.kill() 58 | 59 | try: 60 | image_path = create_resource_path(event.text) 61 | loaded_image = pygame.image.load(image_path).convert_alpha() 62 | image_rect = loaded_image.get_rect() 63 | aspect_ratio = image_rect.width / image_rect.height 64 | need_to_scale = False 65 | if image_rect.width > self.max_image_display_dimensions[0]: 66 | image_rect.width = self.max_image_display_dimensions[0] 67 | image_rect.height = int(image_rect.width / aspect_ratio) 68 | need_to_scale = True 69 | 70 | if image_rect.height > self.max_image_display_dimensions[1]: 71 | image_rect.height = self.max_image_display_dimensions[1] 72 | image_rect.width = int(image_rect.height * aspect_ratio) 73 | need_to_scale = True 74 | 75 | if need_to_scale: 76 | loaded_image = pygame.transform.smoothscale(loaded_image, 77 | image_rect.size) 78 | 79 | image_rect.center = (400, 300) 80 | 81 | self.display_loaded_image = UIImage(relative_rect=image_rect, 82 | image_surface=loaded_image, 83 | manager=self.ui_manager) 84 | 85 | except pygame.error: 86 | pass 87 | 88 | if (event.type == pygame_gui.UI_WINDOW_CLOSE 89 | and event.ui_element == self.file_dialog): 90 | self.load_button.enable() 91 | self.file_dialog = None 92 | 93 | self.ui_manager.process_events(event) 94 | 95 | self.ui_manager.update(time_delta) 96 | 97 | self.window_surface.blit(self.background, (0, 0)) 98 | self.ui_manager.draw_ui(self.window_surface) 99 | 100 | pygame.display.update() 101 | 102 | 103 | if __name__ == "__main__": 104 | app = ImageLoadApp() 105 | app.run() 106 | -------------------------------------------------------------------------------- /gradient_test.py: -------------------------------------------------------------------------------- 1 | from typing import Union 2 | 3 | import pygame 4 | import pygame_gui 5 | 6 | from pygame_gui.core.colour_gradient import ColourGradient 7 | 8 | """ 9 | Testing the quality of doing cheaper gradients. 10 | """ 11 | 12 | 13 | class Gradient: 14 | def __init__(self, angle_direction: int, colour_1: pygame.Color, 15 | colour_2: pygame.Color, colour_3: Union[pygame.Color, None] = None): 16 | self.angle_direction = angle_direction 17 | self.colour_1 = colour_1 18 | self.colour_2 = colour_2 19 | self.colour_3 = colour_3 20 | 21 | def make_gradient(self, input_surface): 22 | inverse_rotated_input = pygame.transform.rotate(input_surface, -self.angle_direction) 23 | gradient_size = inverse_rotated_input.get_rect().size 24 | 25 | # create the initial 'pixel coloured' surface with a pixel for each colour 26 | if self.colour_3 is None: 27 | pixel_width = 2 28 | colour_pixels_surf = pygame.Surface((pixel_width, 1), flags=pygame.SRCALPHA) 29 | colour_pixels_surf.fill(self.colour_1, pygame.Rect((0, 0), (1, 1))) 30 | colour_pixels_surf.fill(self.colour_2, pygame.Rect((1, 0), (1, 1))) 31 | else: 32 | pixel_width = 3 33 | colour_pixels_surf = pygame.Surface((pixel_width, 1), flags=pygame.SRCALPHA) 34 | colour_pixels_surf.fill(self.colour_1, pygame.Rect((0, 0), (1, 1))) 35 | colour_pixels_surf.fill(self.colour_2, pygame.Rect((1, 0), (1, 1))) 36 | colour_pixels_surf.fill(self.colour_3, pygame.Rect((2, 0), (1, 1))) 37 | 38 | # create a surface large enough to overlap the input surface at any rotation angle 39 | gradient_surf = pygame.Surface(gradient_size, flags=pygame.SRCALPHA) 40 | 41 | # scale the pixel surface to fill our new large, gradient surface 42 | # pygame.transform.smoothscale Occasionally gives a 43 | # 'Fatal Python error: PyEval_SaveThread: NULL tstate' 44 | # which is apparently a threading issue with the GIL. 45 | 46 | # pygame.transform.smoothscale(colour_pixels_surf, gradient_size, gradient_surf) 47 | 48 | # Try this instead 49 | scale = float(max(gradient_size[0] / pixel_width, gradient_size[1])) 50 | zoomed_surf = pygame.transform.rotozoom(colour_pixels_surf, 0, scale) 51 | pygame.transform.scale(zoomed_surf, gradient_size, gradient_surf) 52 | 53 | # rotate the gradient surface to the correct angle for our gradient 54 | gradient_surf = pygame.transform.rotate(gradient_surf, self.angle_direction) 55 | return gradient_surf 56 | 57 | def make_gradient_2(self, input_surface): 58 | if self.colour_3 is None: 59 | pixel_width = 2 60 | colour_pixels_surf = pygame.Surface((pixel_width, 1), flags=pygame.SRCALPHA) 61 | colour_pixels_surf.fill(self.colour_1, pygame.Rect((0, 0), (1, 1))) 62 | colour_pixels_surf.fill(self.colour_2, pygame.Rect((1, 0), (1, 1))) 63 | else: 64 | pixel_width = 3 65 | colour_pixels_surf = pygame.Surface((pixel_width, 1), flags=pygame.SRCALPHA) 66 | colour_pixels_surf.fill(self.colour_1, pygame.Rect((0, 0), (1, 1))) 67 | colour_pixels_surf.fill(self.colour_2, pygame.Rect((1, 0), (1, 1))) 68 | colour_pixels_surf.fill(self.colour_3, pygame.Rect((2, 0), (1, 1))) 69 | 70 | gradient = pygame.transform.rotozoom(colour_pixels_surf, 0, 30) 71 | 72 | # scale the gradient up to the right size 73 | inverse_rotated_input = pygame.transform.rotate(input_surface, -self.angle_direction) 74 | gradient_size = inverse_rotated_input.get_rect().size 75 | gradient_surf = pygame.Surface(gradient_size, flags=pygame.SRCALPHA) 76 | 77 | pygame.transform.scale(gradient, gradient_size, gradient_surf) 78 | gradient_surf = pygame.transform.rotate(gradient_surf, self.angle_direction) 79 | 80 | return gradient_surf 81 | 82 | 83 | pygame.init() 84 | 85 | 86 | pygame.display.set_caption('Quick Start') 87 | window_surface = pygame.display.set_mode((800, 600)) 88 | manager = pygame_gui.UIManager((800, 600), 'data/themes/quick_theme.json') 89 | 90 | background = pygame.Surface((800, 600)) 91 | background.fill(manager.get_theme().get_colour('dark_bg')) 92 | 93 | test_gradient_1 = ColourGradient(-90, pygame.Color("#FF0000"), pygame.Color("#FF80FF")) 94 | 95 | long_thin_surf = pygame.Surface((300, 25)) 96 | long_thin_surf.fill("white") 97 | test_gradient_1.apply_gradient_to_surface(long_thin_surf) 98 | 99 | tall_thin_surf = pygame.Surface((25, 300)) 100 | tall_thin_surf.fill("white") 101 | test_gradient_1.apply_gradient_to_surface(tall_thin_surf) 102 | 103 | big_surf = pygame.Surface((300, 300)) 104 | big_surf.fill("white") 105 | test_gradient_1.apply_gradient_to_surface(big_surf, pygame.Rect(0, 0, 150, 150)) 106 | 107 | 108 | # gradient 2 109 | 110 | test_gradient_2 = Gradient(45, 111 | pygame.Color("#8070A0"), 112 | pygame.Color("#80E0CF"), 113 | pygame.Color("#F0E0EF")) 114 | 115 | long_thin_surf_2 = pygame.Surface((300, 25)) 116 | long_thin_surf_2 = test_gradient_2.make_gradient_2(long_thin_surf_2) 117 | 118 | tall_thin_surf_2 = pygame.Surface((25, 300)) 119 | tall_thin_surf_2 = test_gradient_2.make_gradient_2(tall_thin_surf_2) 120 | 121 | big_surf_2 = pygame.Surface((300, 300)) 122 | big_surf_2 = test_gradient_2.make_gradient_2(big_surf_2) 123 | 124 | clock = pygame.time.Clock() 125 | is_running = True 126 | 127 | while is_running: 128 | time_delta = clock.tick(60)/1000.0 129 | for event in pygame.event.get(): 130 | if event.type == pygame.QUIT: 131 | is_running = False 132 | 133 | manager.process_events(event) 134 | 135 | manager.update(time_delta) 136 | 137 | window_surface.blit(background, (0, 0)) 138 | manager.draw_ui(window_surface) 139 | 140 | window_surface.blit(long_thin_surf, (10, 10)) 141 | window_surface.blit(tall_thin_surf, (350, 10)) 142 | window_surface.blit(big_surf, (10, 50)) 143 | 144 | window_surface.blit(long_thin_surf_2, (400, 10)) 145 | window_surface.blit(tall_thin_surf_2, (750, 10)) 146 | window_surface.blit(big_surf_2, (360, 50)) 147 | 148 | pygame.display.update() 149 | -------------------------------------------------------------------------------- /guiopedia.py: -------------------------------------------------------------------------------- 1 | import re 2 | from collections import OrderedDict 3 | from os import listdir, linesep 4 | from os.path import isfile, join, basename, splitext 5 | 6 | import pygame 7 | import pygame_gui 8 | 9 | from pygame_gui.elements import UITextBox 10 | 11 | 12 | class GUIopediaWindow(pygame_gui.elements.UIWindow): 13 | def __init__(self, manager): 14 | super().__init__(pygame.Rect((200, 50), (420, 520)), 15 | manager, 16 | window_display_title='GUIopedia!', 17 | object_id="#guiopedia_window") 18 | 19 | search_bar_top_margin = 2 20 | search_bar_bottom_margin = 2 21 | self.search_box = pygame_gui.elements.UITextEntryLine(pygame.Rect((150, 22 | search_bar_top_margin), 23 | (230, 30)), 24 | manager=manager, 25 | container=self, 26 | parent_element=self) 27 | 28 | self.search_label = pygame_gui.elements.UILabel(pygame.Rect((90, 29 | search_bar_top_margin), 30 | (56, 31 | self.search_box.rect.height)), 32 | "Search:", 33 | manager=manager, 34 | container=self, 35 | parent_element=self) 36 | 37 | self.home_button = pygame_gui.elements.UIButton(pygame.Rect((20, search_bar_top_margin), 38 | (29, 29)), 39 | '', 40 | manager=manager, 41 | container=self, 42 | parent_element=self, 43 | object_id='#home_button') 44 | 45 | self.remaining_window_size = (self.get_container().get_size()[0], 46 | (self.get_container().get_size()[1] - 47 | (self.search_box.rect.height + 48 | search_bar_top_margin + 49 | search_bar_bottom_margin))) 50 | 51 | self.pages = {} 52 | page_path = 'data/guiopedia/' 53 | file_paths = [join(page_path, f) for f in listdir(page_path) if isfile(join(page_path, f))] 54 | for file_path in file_paths: 55 | with open(file_path, 'r') as page_file: 56 | file_id = splitext(basename(file_path))[0] 57 | file_data = "" 58 | for line in page_file: 59 | line = line.rstrip(linesep).lstrip() 60 | # kind of hacky way to add back spaces at the end of new lines that 61 | # are removed by the pyCharm HTML 62 | # editor. perhaps our HTML parser needs to handle this case 63 | # (turning new lines into spaces 64 | # but removing spaces at the start of rendered lines?) 65 | if len(line) > 0: 66 | if line[-1] != '>': 67 | line += ' ' 68 | file_data += line 69 | self.pages[file_id] = file_data 70 | 71 | index_page = self.pages['index'] 72 | self.page_y_start_pos = (self.search_box.rect.height + 73 | search_bar_top_margin + 74 | search_bar_bottom_margin) 75 | self.page_display = UITextBox(index_page, 76 | pygame.Rect((0, self.page_y_start_pos), 77 | self.remaining_window_size), 78 | manager=manager, 79 | container=self, 80 | parent_element=self) 81 | 82 | def process_event(self, event): 83 | handled = super().process_event(event) 84 | 85 | if event.type == pygame_gui.UI_TEXT_BOX_LINK_CLICKED: 86 | self.open_new_page(event.link_target) 87 | handled = True 88 | 89 | if (event.type == pygame_gui.UI_TEXT_ENTRY_FINISHED and 90 | event.ui_element == self.search_box): 91 | results = self.search_pages(event.text) 92 | self.create_search_results_page(results) 93 | self.open_new_page('results') 94 | handled = True 95 | 96 | if (event.type == pygame_gui.UI_BUTTON_PRESSED and 97 | event.ui_object_id == '#guiopedia_window.#home_button'): 98 | self.open_new_page('index') 99 | handled = True 100 | 101 | return handled 102 | 103 | def search_pages(self, search_string: str): 104 | results = {} 105 | words = search_string.split() 106 | 107 | for page in self.pages.keys(): 108 | total_occurances_of_search_words = 0 109 | for word in words: 110 | word_occurances = self.search_text_for_occurrences_of_word(word, self.pages[page]) 111 | total_occurances_of_search_words += word_occurances 112 | if total_occurances_of_search_words > 0: 113 | results[page] = total_occurances_of_search_words 114 | 115 | sorted_results = sorted(results.items(), key=lambda item: item[1], reverse=True) 116 | return OrderedDict(sorted_results) 117 | 118 | @staticmethod 119 | def search_text_for_occurrences_of_word(word_to_search_for: str, text_to_search: str) -> int: 120 | return sum(1 for _ in re.finditer(r'\b%s\b' % re.escape(word_to_search_for), 121 | text_to_search, 122 | flags=re.IGNORECASE)) 123 | 124 | def open_new_page(self, page_link: str): 125 | self.page_display.kill() 126 | self.page_display = None 127 | if page_link in self.pages: 128 | text = self.pages[page_link] 129 | 130 | self.page_display = UITextBox(text, 131 | pygame.Rect((0, 132 | self.page_y_start_pos), 133 | self.remaining_window_size), 134 | manager=self.ui_manager, 135 | container=self, 136 | parent_element=self) 137 | 138 | def create_search_results_page(self, results): 139 | results_text = 'Search results' 140 | if len(results) == 0: 141 | results_text += '

No Results Found.' 142 | else: 143 | results_text += '

' + str(len(results)) + ' results found:' 144 | for result in results.keys(): 145 | results_text += '

- ' + result + '' 146 | 147 | self.pages['results'] = results_text 148 | 149 | 150 | class GUIopediaApp: 151 | def __init__(self): 152 | pygame.init() 153 | 154 | pygame.display.set_caption('GUIopedia App') 155 | self.window_surface = pygame.display.set_mode((800, 600)) 156 | 157 | self.background = pygame.Surface((800, 600)) 158 | self.background.fill(pygame.Color('#707070')) 159 | 160 | self.manager = pygame_gui.UIManager((800, 600), "data/themes/guiopedia_theme.json") 161 | self.manager.preload_fonts([{'name': 'noto_sans', 'point_size': 24, 'style': 'bold'}, 162 | {'name': 'noto_sans', 'point_size': 24, 'style': 'bold_italic'}, 163 | {'name': 'noto_sans', 'point_size': 18, 'style': 'bold'}, 164 | {'name': 'noto_sans', 'point_size': 18, 'style': 'regular'}, 165 | {'name': 'noto_sans', 'point_size': 18, 'style': 'bold_italic'}, 166 | {'name': 'noto_sans', 'point_size': 14, 'style': 'bold'} 167 | ]) 168 | 169 | self.guiopedia_window = GUIopediaWindow(manager=self.manager) 170 | 171 | self.clock = pygame.time.Clock() 172 | self.is_running = True 173 | 174 | def run(self): 175 | while self.is_running: 176 | time_delta = self.clock.tick(60) / 1000.0 177 | for event in pygame.event.get(): 178 | if event.type == pygame.QUIT: 179 | self.is_running = False 180 | 181 | if (event.type == pygame.KEYDOWN and 182 | event.key == pygame.K_F1 and 183 | not self.guiopedia_window.alive()): 184 | self.guiopedia_window = GUIopediaWindow(manager=self.manager) 185 | 186 | self.manager.process_events(event) 187 | 188 | self.manager.update(time_delta) 189 | 190 | self.window_surface.blit(self.background, (0, 0)) 191 | self.manager.draw_ui(self.window_surface) 192 | 193 | pygame.display.update() 194 | 195 | 196 | if __name__ == '__main__': 197 | app = GUIopediaApp() 198 | app.run() 199 | -------------------------------------------------------------------------------- /new_text_test.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import pygame_gui 3 | 4 | import pygame_gui.data 5 | 6 | from pygame.color import Color 7 | from pygame.surface import Surface 8 | 9 | from pygame_gui.elements.ui_text_box import UITextBox 10 | 11 | """ 12 | A test bed to tinker with future text features. 13 | """ 14 | 15 | 16 | def test_app(): 17 | pygame.init() 18 | 19 | display_surface = pygame.display.set_mode((800, 600)) 20 | 21 | ui_manager = pygame_gui.UIManager((800, 600), 'data/themes/theme_1.json') 22 | 23 | background = Surface((800, 600), depth=32) 24 | background.fill(Color("#606060")) 25 | 26 | ui_manager.preload_fonts([{'name': 'noto_sans', 'point_size': 14, 'style': 'bold', 'antialiased': '1'}, 27 | {'name': 'noto_sans', 'point_size': 14, 'style': 'italic', 'antialiased': '1'}]) 28 | 29 | text_box = UITextBox( 30 | html_text="hey hey hey " 31 | "what are the haps my " 32 | "brand new friend? These are the " 33 | "days of our disco tent. " 34 | "Why the " 35 | "long night of absolution, " 36 | "shall becometh the man. Lest " 37 | "forth " 38 | "betwixt moon under one nation " 39 | "before and beyond opus grande " 40 | "just in time for the last time " 41 | "three nine nine. Toight." 42 | "

" 43 | "hella toight.
", 44 | relative_rect=pygame.Rect(100, 100, 400, 200), 45 | manager=ui_manager) 46 | 47 | is_running = True 48 | clock = pygame.time.Clock() 49 | 50 | while is_running: 51 | time_delta = clock.tick(60)/1000.0 52 | for event in pygame.event.get(): 53 | if event.type == pygame.QUIT: 54 | is_running = False 55 | 56 | ui_manager.process_events(event) 57 | 58 | display_surface.blit(background, (0, 0)) 59 | 60 | ui_manager.update(0.01) 61 | ui_manager.draw_ui(window_surface=display_surface) 62 | 63 | pygame.display.update() 64 | 65 | 66 | if __name__ == "__main__": 67 | test_app() 68 | -------------------------------------------------------------------------------- /pong/ball.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import math 3 | import random 4 | 5 | 6 | class Ball: 7 | def __init__(self, start_position): 8 | self.rect = pygame.Rect(start_position, (5, 5)) 9 | self.colour = pygame.Color(255, 255, 255) 10 | self.position = [float(start_position[0]), float(start_position[1])] 11 | self.start_position = [self.position[0], self.position[1]] 12 | self.ball_speed = 120.0 13 | self.max_bat_bounce_angle = 5.0 * math.pi/12.0 14 | self.collided = False 15 | 16 | self.velocity = [0.0, 0.0] 17 | self.create_random_start_vector() 18 | 19 | def render(self, screen): 20 | pygame.draw.rect(screen, self.colour, self.rect) 21 | 22 | def create_random_start_vector(self): 23 | y_random = random.uniform(-0.5, 0.5) 24 | x_random = 1.0 - abs(y_random) 25 | if random.randint(0, 1) == 1: 26 | x_random = x_random * -1.0 27 | self.velocity = [x_random * self.ball_speed, y_random * self.ball_speed] 28 | 29 | def reset(self): 30 | self.position = [self.start_position[0], self.start_position[1]] 31 | self.create_random_start_vector() 32 | 33 | def update(self, dt, bats, walls): 34 | self.position[0] += self.velocity[0] * dt 35 | self.position[1] += self.velocity[1] * dt 36 | self.rect.x = self.position[0] 37 | self.rect.y = self.position[1] 38 | 39 | collided_this_frame = False 40 | for wall in walls: 41 | if self.rect.colliderect(wall.rect): 42 | collided_this_frame = True 43 | if not self.collided: 44 | self.collided = True 45 | self.velocity[1] = self.velocity[1] * -1 46 | 47 | for bat in bats: 48 | if self.rect.colliderect(bat.rect): 49 | collided_this_frame = True 50 | if not self.collided: 51 | self.collided = True 52 | bat_y_centre = bat.position[1] + (bat.length/2) 53 | ball_y_centre = self.position[1] + 5 54 | relative_intersect_y = bat_y_centre - ball_y_centre # should be in 'bat space' between -50 and +50 55 | normalized_relative_intersect_y = relative_intersect_y/(bat.length/2) 56 | bounce_angle = normalized_relative_intersect_y * self.max_bat_bounce_angle 57 | 58 | self.velocity[0] = self.velocity[0] * -1 59 | self.velocity[1] = self.ball_speed * -math.sin(bounce_angle) 60 | 61 | if not collided_this_frame: 62 | self.collided = False 63 | -------------------------------------------------------------------------------- /pong/bat.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | from pygame.locals import * 3 | 4 | 5 | class ControlScheme: 6 | def __init__(self): 7 | self.up = K_UP 8 | self.down = K_DOWN 9 | 10 | 11 | class Bat: 12 | def __init__(self, start_pos, control_scheme, court_size): 13 | self.control_scheme = control_scheme 14 | self.move_up = False 15 | self.move_down = False 16 | self.move_speed = 450.0 17 | 18 | self.court_size = court_size 19 | 20 | self.length = 30.0 21 | self.width = 5.0 22 | 23 | self.position = [float(start_pos[0]), float(start_pos[1])] 24 | 25 | self.rect = pygame.Rect((start_pos[0], start_pos[1]), (self.width, self.length)) 26 | self.colour = pygame.Color("#FFFFFF") 27 | 28 | def process_event(self, event): 29 | if event.type == KEYDOWN: 30 | if event.key == self.control_scheme.up: 31 | self.move_up = True 32 | if event.key == self.control_scheme.down: 33 | self.move_down = True 34 | 35 | if event.type == KEYUP: 36 | if event.key == self.control_scheme.up: 37 | self.move_up = False 38 | if event.key == self.control_scheme.down: 39 | self.move_down = False 40 | 41 | def update(self, dt): 42 | if self.move_up: 43 | self.position[1] -= dt * self.move_speed 44 | 45 | if self.position[1] < 10.0: 46 | self.position[1] = 10.0 47 | 48 | self.rect.y = self.position[1] 49 | 50 | if self.move_down: 51 | self.position[1] += dt * self.move_speed 52 | 53 | if self.position[1] > self.court_size[1] - self.length - 10: 54 | self.position[1] = self.court_size[1] - self.length - 10 55 | 56 | self.rect.y = self.position[1] 57 | 58 | def render(self, screen): 59 | pygame.draw.rect(screen, self.colour, self.rect) 60 | -------------------------------------------------------------------------------- /pong/pong.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | from pygame.locals import * 3 | 4 | from pong.wall import Wall 5 | from pong.bat import Bat, ControlScheme 6 | from pong.ball import Ball 7 | from pong.score import Score 8 | 9 | 10 | class PongGame: 11 | def __init__(self, size): 12 | self.size = size 13 | self.background = pygame.Surface(size) # make a background surface 14 | self.background = self.background.convert() 15 | self.background.fill((0, 0, 0)) 16 | 17 | font = pygame.font.Font(None, 24) 18 | 19 | self.score = Score(font) 20 | 21 | self.walls = [Wall((5, 5), (size[0] - 10, 10)), 22 | Wall((5, size[1] - 10), (size[0] - 10, size[1] - 5))] 23 | 24 | self.bats = [] 25 | 26 | control_scheme_1 = ControlScheme() 27 | control_scheme_1.up = K_w 28 | control_scheme_1.down = K_s 29 | 30 | control_scheme_2 = ControlScheme() 31 | control_scheme_2.up = K_UP 32 | control_scheme_2.down = K_DOWN 33 | 34 | self.bats.append(Bat((5, int(size[1]/2)), control_scheme_1, self.size)) 35 | self.bats.append(Bat((size[0] - 10, int(size[1]/2)), control_scheme_2, self.size)) 36 | 37 | self.ball = Ball((int(size[0]/2), int(size[1]/2))) 38 | 39 | def process_event(self, event): 40 | for bat in self.bats: 41 | bat.process_event(event) 42 | 43 | def update(self, time_delta): 44 | for bat in self.bats: 45 | bat.update(time_delta) 46 | 47 | self.ball.update(time_delta, self.bats, self.walls) 48 | 49 | if self.ball.position[0] < 0: 50 | self.ball.reset() 51 | self.score.increase_player_2_score() 52 | elif self.ball.position[0] > self.size[0]: 53 | self.ball.reset() 54 | self.score.increase_player_1_score() 55 | 56 | def draw(self, surface): 57 | surface.blit(self.background, (0, 0)) 58 | 59 | for wall in self.walls: 60 | wall.render(surface) 61 | 62 | for bat in self.bats: 63 | bat.render(surface) 64 | 65 | self.ball.render(surface) 66 | self.score.render(surface, self.size) 67 | -------------------------------------------------------------------------------- /pong/score.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | 3 | 4 | class Score: 5 | def __init__(self, font): 6 | self.player_1_score = 0 7 | self.player_2_score = 0 8 | self.font = font 9 | 10 | self.score_string = None 11 | self.score_text_render = None 12 | 13 | self.update_score_text() 14 | 15 | def update_score_text(self): 16 | self.score_string = str(self.player_1_score) + " - " + str(self.player_2_score) 17 | self.score_text_render = self.font.render(self.score_string, True, pygame.Color(200, 200, 200)) 18 | 19 | def render(self, screen, size): 20 | screen.blit(self.score_text_render, self.score_text_render.get_rect(centerx=size[0]/2, 21 | centery=size[1]/10)) 22 | 23 | def increase_player_1_score(self): 24 | self.player_1_score += 1 25 | self.update_score_text() 26 | 27 | def increase_player_2_score(self): 28 | self.player_2_score += 1 29 | self.update_score_text() 30 | -------------------------------------------------------------------------------- /pong/wall.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | 3 | 4 | class Wall: 5 | def __init__(self, top_left, bottom_right): 6 | self.rect = pygame.Rect(top_left, (bottom_right[0] - top_left[0], bottom_right[1] - top_left[1])) 7 | self.colour = pygame.Color("#C8C8C8") 8 | 9 | def render(self, screen): 10 | pygame.draw.rect(screen, self.colour, self.rect) 11 | -------------------------------------------------------------------------------- /pygame_notepad.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | 3 | from pygame_gui import UIManager, UI_TEXT_ENTRY_CHANGED 4 | from pygame_gui.elements import UIWindow, UITextEntryBox, UITextBox 5 | 6 | 7 | pygame.init() 8 | 9 | 10 | pygame.display.set_caption('Pygame Notepad') 11 | window_surface = pygame.display.set_mode((800, 600)) 12 | manager = UIManager((800, 600), 'data/themes/notepad_theme.json') 13 | 14 | background = pygame.Surface((800, 600)) 15 | background.fill(manager.ui_theme.get_colour('dark_bg')) 16 | 17 | 18 | notepad_window = UIWindow(pygame.Rect(50, 20, 300, 400), window_display_title="Pygame Notepad") 19 | 20 | output_window = UIWindow(pygame.Rect(400, 20, 300, 400), window_display_title="Pygame GUI Formatted Text") 21 | 22 | # swap to editable text box 23 | text_entry_box = UITextEntryBox( 24 | relative_rect=pygame.Rect((0, 0), notepad_window.get_container().get_size()), 25 | initial_text="", 26 | container=notepad_window, 27 | placeholder_text="Enter text here...") 28 | 29 | text_output_box = UITextBox( 30 | relative_rect=pygame.Rect((0, 0), output_window.get_container().get_size()), 31 | html_text="", 32 | container=output_window) 33 | 34 | clock = pygame.time.Clock() 35 | is_running = True 36 | 37 | debug_chunks = False 38 | 39 | while is_running: 40 | time_delta = clock.tick(60)/1000.0 41 | for event in pygame.event.get(): 42 | if event.type == pygame.QUIT: 43 | is_running = False 44 | 45 | if event.type == UI_TEXT_ENTRY_CHANGED and event.ui_element == text_entry_box: 46 | text_output_box.set_text(event.text) 47 | 48 | if event.type == pygame.MOUSEBUTTONDOWN and event.button == pygame.BUTTON_RIGHT: 49 | text_box_offset = (text_entry_box.padding[0] + text_entry_box.border_width + 50 | text_entry_box.shadow_width + 51 | text_entry_box.rounded_corner_width_offsets[0], 52 | text_entry_box.padding[1] + text_entry_box.border_width + 53 | text_entry_box.shadow_width + 54 | text_entry_box.rounded_corner_width_offsets[0]) 55 | for row in text_entry_box.text_box_layout.layout_rows: 56 | for chunk in row.items: 57 | debug_rect = chunk.copy() 58 | debug_rect.top += text_entry_box.rect.top + text_box_offset[1] 59 | debug_rect.left += text_entry_box.rect.left + text_box_offset[0] 60 | print("chunk rect: ", debug_rect) 61 | debug_row = row.copy() 62 | debug_row.top += text_entry_box.rect.top + text_box_offset[1] 63 | debug_row.left += text_entry_box.rect.left + text_box_offset[0] 64 | print("row rect: ", debug_row) 65 | 66 | manager.process_events(event) 67 | 68 | manager.update(time_delta) 69 | 70 | window_surface.blit(background, (0, 0)) 71 | manager.draw_ui(window_surface) 72 | 73 | if debug_chunks: 74 | text_box_offset = (text_entry_box.padding[0] + text_entry_box.border_width + 75 | text_entry_box.shadow_width + 76 | text_entry_box.rounded_corner_width_offsets[0], 77 | text_entry_box.padding[1] + text_entry_box.border_width + 78 | text_entry_box.shadow_width + 79 | text_entry_box.rounded_corner_width_offsets[0]) 80 | for row in text_entry_box.text_box_layout.layout_rows: 81 | for chunk in row.items: 82 | debug_rect = chunk.copy() 83 | debug_rect.top += text_entry_box.rect.top + text_box_offset[1] 84 | debug_rect.left += text_entry_box.rect.left + text_box_offset[0] 85 | pygame.draw.rect(window_surface, pygame.Color('#FF0000'), debug_rect, 1) 86 | debug_row = row.copy() 87 | debug_row.top += text_entry_box.rect.top + text_box_offset[1] 88 | debug_row.left += text_entry_box.rect.left + text_box_offset[0] 89 | pygame.draw.rect(window_surface, pygame.Color('#0000FF'), debug_row, 1) 90 | 91 | layout_rect = text_entry_box.text_box_layout.layout_rect.copy() 92 | layout_rect.top = text_entry_box.rect.top + text_box_offset[1] 93 | layout_rect.left = text_entry_box.rect.left + text_box_offset[0] 94 | pygame.draw.rect(window_surface, pygame.Color('#00FF00'), layout_rect, 1) 95 | 96 | pygame.display.update() 97 | -------------------------------------------------------------------------------- /pyinstaller_specs/pyinstaller_build.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python -*- 2 | 3 | block_cipher = None 4 | 5 | 6 | a = Analysis(['../pyinstaller_test.py'], 7 | pathex=[], 8 | binaries=[], 9 | datas=[], 10 | hiddenimports=[], 11 | hookspath=[], 12 | runtime_hooks=[], 13 | excludes=[], 14 | win_no_prefer_redirects=False, 15 | win_private_assemblies=False, 16 | cipher=block_cipher) 17 | 18 | a.datas += Tree('data', prefix='data') 19 | 20 | pyz = PYZ(a.pure, a.zipped_data, 21 | cipher=block_cipher) 22 | 23 | # enable this to see verbose output 24 | # options = [ ('v', None, 'OPTION')] 25 | exe = EXE(pyz, 26 | a.scripts, 27 | # options, 28 | exclude_binaries=True, 29 | name='pyinstaller_test_release', 30 | debug=False, # set this to True for debug output 31 | strip=False, 32 | upx=True, 33 | console=True ) # set this to False this to remove the console 34 | coll = COLLECT(exe, 35 | a.binaries, 36 | a.zipfiles, 37 | a.datas, 38 | strip=False, 39 | upx=True, 40 | name='pyinstaller_test_release') -------------------------------------------------------------------------------- /pyinstaller_specs/pyinstaller_onefile_build.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python -*- 2 | 3 | block_cipher = None 4 | 5 | 6 | a = Analysis(['../pyinstaller_test.py'], 7 | pathex=[], 8 | binaries=[], 9 | datas=[], 10 | hiddenimports=[], 11 | hookspath=[], 12 | runtime_hooks=[], 13 | excludes=[], 14 | win_no_prefer_redirects=False, 15 | win_private_assemblies=False, 16 | cipher=block_cipher) 17 | 18 | a.datas += Tree('data', prefix='data') 19 | 20 | pyz = PYZ(a.pure, a.zipped_data, 21 | cipher=block_cipher) 22 | 23 | 24 | exe = EXE(pyz, 25 | a.scripts, 26 | a.binaries, 27 | a.zipfiles, 28 | a.datas, 29 | name='pyinstaller_test_release', 30 | debug=True, 31 | strip=False, 32 | upx=True, 33 | runtime_tmpdir=None, 34 | console=True ) -------------------------------------------------------------------------------- /pyinstaller_test.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import pygame 4 | import pygame_gui 5 | 6 | 7 | """ 8 | TO build an executable run: 9 | pip install pyinstaller 10 | 11 | Then: 12 | pyinstaller pyinstaller_specs/pyinstaller_build.spec 13 | 14 | Or: 15 | pyinstaller pyinstaller_specs/pyinstaller_onefile_build.spec 16 | 17 | in the terminal. 18 | """ 19 | 20 | 21 | def resource_path(relative_path): 22 | """ Get absolute path to resource, works for dev and for PyInstaller's 'onefile' mode """ 23 | try: 24 | # PyInstaller creates a temp folder and stores path in _MEIPASS 25 | base_path = sys._MEIPASS 26 | except AttributeError: 27 | base_path = os.path.abspath(".") 28 | 29 | return os.path.join(base_path, relative_path) 30 | 31 | 32 | pygame.init() 33 | 34 | pygame.display.set_caption('Quick Start') 35 | window_surface = pygame.display.set_mode((800, 600)) 36 | manager = pygame_gui.UIManager((800, 600), resource_path('data/themes/pyinstaller_theme.json')) 37 | 38 | background = pygame.Surface((800, 600)) 39 | background.fill(manager.ui_theme.get_colour('dark_bg')) 40 | 41 | hello_button = pygame_gui.elements.UIButton(relative_rect=pygame.Rect((350, 280), (150, 40)), 42 | text='Hello', 43 | manager=manager) 44 | 45 | clock = pygame.time.Clock() 46 | is_running = True 47 | 48 | while is_running: 49 | time_delta = clock.tick(60) / 1000.0 50 | for event in pygame.event.get(): 51 | if event.type == pygame.QUIT: 52 | is_running = False 53 | 54 | if event.type == pygame_gui.UI_BUTTON_PRESSED and event.ui_element == hello_button: 55 | print('Hello World!') 56 | 57 | manager.process_events(event) 58 | 59 | manager.update(time_delta) 60 | 61 | window_surface.blit(background, (0, 0)) 62 | manager.draw_ui(window_surface) 63 | 64 | pygame.display.update() 65 | -------------------------------------------------------------------------------- /quick_start.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | 3 | from pygame_gui import UIManager, UI_BUTTON_PRESSED 4 | from pygame_gui.elements import UIButton 5 | 6 | 7 | pygame.init() 8 | 9 | 10 | pygame.display.set_caption('Quick Start') 11 | window_surface = pygame.display.set_mode((800, 600)) 12 | manager = UIManager((800, 600), 'data/themes/quick_theme.json') 13 | 14 | background = pygame.Surface((800, 600)) 15 | background.fill(manager.ui_theme.get_colour('dark_bg')) 16 | 17 | 18 | hello_button = UIButton((350, 280), 'Hello') 19 | 20 | clock = pygame.time.Clock() 21 | is_running = True 22 | 23 | while is_running: 24 | time_delta = clock.tick(60)/1000.0 25 | for event in pygame.event.get(): 26 | if event.type == pygame.QUIT: 27 | is_running = False 28 | if event.type == UI_BUTTON_PRESSED: 29 | if event.ui_element == hello_button: 30 | print('Hello World!') 31 | manager.process_events(event) 32 | 33 | manager.update(time_delta) 34 | 35 | window_surface.blit(background, (0, 0)) 36 | manager.draw_ui(window_surface) 37 | 38 | pygame.display.update() 39 | -------------------------------------------------------------------------------- /resizing_test.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import pygame_gui 3 | import random 4 | 5 | 6 | class HealthySprite(pygame.sprite.Sprite): 7 | def __init__(self, *groups): 8 | super().__init__(*groups) 9 | self.health_capacity = 100 10 | self.current_health = 75 11 | self.rect = pygame.Rect(150, 150, 50, 75) 12 | 13 | 14 | pygame.init() 15 | 16 | pygame.display.set_caption('Quick Start') 17 | window_surface = pygame.display.set_mode((800, 600)) 18 | manager = pygame_gui.UIManager((800, 600), 'data/themes/quick_theme.json') 19 | 20 | background = pygame.Surface((800, 600)) 21 | background.fill(manager.ui_theme.get_colour('dark_bg')) 22 | 23 | hello_button = pygame_gui.elements.UIButton(relative_rect=pygame.Rect((350, 280), (150, 40)), 24 | text='Hello', 25 | manager=manager) 26 | 27 | drop_down = pygame_gui.elements.UIDropDownMenu(relative_rect=pygame.Rect(200, 100, 200, 30), 28 | manager=manager, options_list=['Dan', 'Trev', 'Bob'], 29 | starting_option='Dan') 30 | 31 | label = pygame_gui.elements.UILabel(relative_rect=pygame.Rect(50, 50, 100, 20), 32 | text='A Label', manager=manager) 33 | 34 | slider = pygame_gui.elements.UIHorizontalSlider(relative_rect=pygame.Rect(40, 540, 150, 40), 35 | start_value=50, 36 | value_range=(0, 200), 37 | manager=manager) 38 | 39 | scroll_bar = pygame_gui.elements.UIVerticalScrollBar(relative_rect=pygame.Rect(80, 100, 30, 200), 40 | visible_percentage=0.25, 41 | manager=manager) 42 | 43 | healthy_sprite = HealthySprite() 44 | 45 | ss_health_bar = pygame_gui.elements.UIScreenSpaceHealthBar(relative_rect=pygame.Rect(100, 500, 46 | 150, 30), 47 | sprite_to_monitor=healthy_sprite, 48 | manager=manager) 49 | 50 | # UITextBox(html_text=text, relative_rect=rect, manager=manager, wrap_to_height=True, 51 | # layer_starting_height=100, object_id="screen_message") 52 | text_box = pygame_gui.elements.UITextBox(html_text='la la LA LA LAL LAL ALALA' 53 | 'LLALAALALA ALALA ALAL ALA' 54 | 'LAALA ALALA ALALA AAaal aa' 55 | 'ALALAa laalal alalal alala' 56 | 'alalalala alalalalalal alal' 57 | 'alalalala alala ' 58 | 'alalala ala' 59 | 'alalalalal lalal alalalal al' 60 | 'al alalalal lfed alal alal alal al' 61 | 'ala lalalal lasda lal a lalalal slapl' 62 | 'alalala lal la blop lal alal aferlal al', 63 | relative_rect=pygame.Rect(500, 0, 68, 361), 64 | manager=manager, 65 | wrap_to_height=True) 66 | 67 | text_entry = pygame_gui.elements.UITextEntryLine(pygame.Rect((500, 500), 68 | (200, -1)), 69 | manager=manager) 70 | 71 | ws_health_bar = pygame_gui.elements.UIWorldSpaceHealthBar(relative_rect=pygame.Rect(100, 500, 72 | 150, 30), 73 | sprite_to_monitor=healthy_sprite, 74 | manager=manager) 75 | 76 | loaded_test_image = pygame.image.load('data/images/splat.png').convert_alpha() 77 | test_image = pygame_gui.elements.UIImage(pygame.Rect((0, 0), 78 | loaded_test_image.get_rect().size), 79 | loaded_test_image, 80 | manager=manager) 81 | 82 | tool_tip = pygame_gui.elements.UITooltip(html_text='What a tip this tool is.', 83 | hover_distance=(0, 10), 84 | manager=manager) 85 | 86 | clock = pygame.time.Clock() 87 | is_running = True 88 | debug_mode = False 89 | 90 | while is_running: 91 | time_delta = clock.tick(60) / 1000.0 92 | for event in pygame.event.get(): 93 | if event.type == pygame.QUIT: 94 | is_running = False 95 | 96 | if event.type == pygame.KEYDOWN: 97 | if event.key == pygame.K_j: 98 | hello_button.set_dimensions((random.randint(50, 200), random.randint(20, 60))) 99 | if event.key == pygame.K_k: 100 | drop_down.set_dimensions((random.randint(50, 200), random.randint(20, 60))) 101 | if event.key == pygame.K_l: 102 | label.set_dimensions((random.randint(50, 200), random.randint(20, 60))) 103 | if event.key == pygame.K_h: 104 | slider.set_dimensions((random.randint(50, 200), random.randint(20, 60))) 105 | if event.key == pygame.K_g: 106 | scroll_bar.set_dimensions((random.randint(20, 60), random.randint(50, 300))) 107 | if event.key == pygame.K_f: 108 | ss_health_bar.set_dimensions((random.randint(50, 200), random.randint(20, 60))) 109 | if event.key == pygame.K_s: 110 | random_dimensions = (random.randint(56, 300), random.randint(80, 400)) 111 | text_box.set_dimensions(random_dimensions) 112 | if event.key == pygame.K_a: 113 | text_entry.set_dimensions((random.randint(50, 300), random.randint(20, 60))) 114 | if event.key == pygame.K_z: 115 | ws_health_bar.set_dimensions((random.randint(50, 200), random.randint(20, 60))) 116 | 117 | if event.key == pygame.K_x: 118 | test_image.set_dimensions((random.randint(32, 256), random.randint(32, 256))) 119 | 120 | if event.key == pygame.K_c: 121 | tool_tip.set_dimensions((random.randint(100, 200), random.randint(60, 200))) 122 | 123 | if event.key == pygame.K_d: 124 | debug_mode = False if debug_mode else True 125 | manager.set_visual_debug_mode(debug_mode) 126 | 127 | if event.key == pygame.K_l: 128 | print(text_entry.get_text()) 129 | 130 | if (event.type == pygame_gui.UI_BUTTON_PRESSED and 131 | event.ui_element == hello_button): 132 | print('Hello World!') 133 | 134 | manager.process_events(event) 135 | 136 | manager.update(time_delta) 137 | 138 | window_surface.blit(background, (0, 0)) 139 | manager.draw_ui(window_surface) 140 | 141 | pygame.display.update() 142 | -------------------------------------------------------------------------------- /scrolling_container_test.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | 3 | from pygame_gui import UIManager, UI_BUTTON_PRESSED 4 | from pygame_gui.elements import UIScrollingContainer, UILabel 5 | 6 | 7 | pygame.init() 8 | 9 | 10 | pygame.display.set_caption('Scrolling Container Test') 11 | window_surface = pygame.display.set_mode((800, 600)) 12 | manager = UIManager((800, 600), 'data/themes/quick_theme.json') 13 | 14 | background = pygame.Surface((800, 600)) 15 | background.fill(manager.ui_theme.get_colour('dark_bg')) 16 | 17 | scrolling_container = UIScrollingContainer(pygame.Rect(50, 50, 700, 500), manager, should_grow_automatically=True) 18 | #scrolling_container.set_scrollable_area_dimensions((1200, 1200)) 19 | 20 | test_label = UILabel(pygame.Rect((50, 50), (200, 40)), "Hello", manager=manager, object_id="#label_1", container=scrolling_container) 21 | test_label_2 = UILabel(pygame.Rect((900, 1000), (200, 40)), "Hello", manager=manager, object_id="#label_2", container=scrolling_container) 22 | 23 | clock = pygame.time.Clock() 24 | is_running = True 25 | 26 | while is_running: 27 | time_delta = clock.tick(60)/1000.0 28 | for event in pygame.event.get(): 29 | if event.type == pygame.QUIT: 30 | is_running = False 31 | 32 | if event.type == pygame.KEYDOWN and event.key == pygame.K_i: 33 | scrolling_container.horiz_scroll_bar.sliding_button.hide() 34 | scrolling_container.horiz_scroll_bar.left_button.hide() 35 | scrolling_container.horiz_scroll_bar.right_button.hide() 36 | 37 | 38 | manager.process_events(event) 39 | 40 | manager.update(time_delta) 41 | 42 | window_surface.blit(background, (0, 0)) 43 | manager.draw_ui(window_surface) 44 | 45 | pygame.display.update() 46 | -------------------------------------------------------------------------------- /shape_packing_cache_test.py: -------------------------------------------------------------------------------- 1 | import random 2 | import math 3 | 4 | import pygame 5 | import pygame_gui 6 | 7 | GOLDEN_RATIO = (math.sqrt(5) - 1) / 2 8 | 9 | 10 | def add_random_rectangle_to_cache(added_surfaces_list): 11 | width = random.randint(20, 200) 12 | height = random.randint(20, 200) 13 | surface = pygame.Surface((width, height)) 14 | color = pygame.Color("#000000") 15 | color.hsla = 360 * ((width * GOLDEN_RATIO) % 1), 50, 70, 100 16 | color.a = 128 17 | surface.fill(color) 18 | 19 | added_surfaces_list.append(str(color.hsla)) 20 | manager.ui_theme.shape_cache.add_surface_to_cache(surface, str(color.hsla)) 21 | 22 | 23 | def remove_use_from_cache_surface(surf_id): 24 | added_surfaces.remove(surf_id) 25 | manager.ui_theme.shape_cache.remove_user_from_cache_item(surf_id) 26 | 27 | 28 | pygame.init() 29 | 30 | pygame.display.set_caption('Quick Start') 31 | window_surface = pygame.display.set_mode((1024, 1024)) 32 | manager = pygame_gui.UIManager((1024, 1024), 'data/themes/quick_theme.json') 33 | 34 | background = pygame.Surface((1024, 1024)) 35 | background.fill(manager.get_theme().get_colour('dark_bg')) 36 | 37 | clock = pygame.time.Clock() 38 | is_running = True 39 | current_surf = 0 40 | added_surfaces = [] 41 | 42 | while is_running: 43 | time_delta = clock.tick(60)/1000.0 44 | for event in pygame.event.get(): 45 | if event.type == pygame.QUIT: 46 | is_running = False 47 | 48 | manager.process_events(event) 49 | 50 | if event.type == pygame.KEYDOWN: 51 | if event.key == pygame.K_RETURN: 52 | add_random_rectangle_to_cache(added_surfaces) 53 | if event.key == pygame.K_BACKSPACE: 54 | if len(added_surfaces) > 0: 55 | remove_use_from_cache_surface(random.choice(added_surfaces)) 56 | if event.key == pygame.K_RIGHT: 57 | if current_surf < len(manager.ui_theme.shape_cache.cache_surfaces) - 1: 58 | current_surf += 1 59 | if event.key == pygame.K_LEFT: 60 | if current_surf > 0: 61 | current_surf -= 1 62 | 63 | manager.update(time_delta) 64 | 65 | window_surface.blit(background, (0, 0)) 66 | manager.draw_ui(window_surface) 67 | 68 | cache_surface = manager.ui_theme.shape_cache.cache_surfaces[current_surf] 69 | window_surface.blit(cache_surface['surface'], 70 | (0, 0)) 71 | for rectangle in cache_surface['free_space_rectangles']: 72 | pygame.draw.rect(window_surface, pygame.Color('#A00000'), rectangle, 2) 73 | 74 | pygame.display.update() 75 | -------------------------------------------------------------------------------- /status_bars.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import pygame_gui 3 | from pygame_gui.core import ObjectID 4 | 5 | 6 | class HappySprite(pygame.sprite.Sprite): 7 | def __init__(self, *groups: pygame.sprite.AbstractGroup): 8 | super().__init__(*groups) 9 | 10 | self.image = pygame.image.load('data/images/test_emoji.png') 11 | 12 | self.position = pygame.Vector2(200.0, 300.0) 13 | self.rect = self.image.get_rect() 14 | self.rect.topleft = (200, 300) 15 | 16 | self.max_health = 100 17 | self.current_health = 75 18 | 19 | self.max_mana = 100 20 | self.current_mana = 30 21 | 22 | self.max_stamina = 100.0 23 | self.current_stamina = 100.0 24 | 25 | self.speed = 100.0 26 | self.moving_left = False 27 | self.moving_right = False 28 | self.moving_up = False 29 | self.moving_down = False 30 | 31 | self.stam_recharge_tick = 0.05 32 | self.stam_recharge_acc = 0.0 33 | 34 | def get_health_percentage(self) -> float: 35 | return self.current_health/self.max_health 36 | 37 | def get_mana_percentage(self) -> float: 38 | return self.current_mana/self.max_mana 39 | 40 | def get_stamina_percentage(self) -> float: 41 | return self.current_stamina/self.max_stamina 42 | 43 | def update(self, time_delta_secs: float) -> None: 44 | 45 | if self.moving_left: 46 | self.position.x -= self.speed * time_delta_secs 47 | self.current_stamina -= 0.4 48 | if self.moving_right: 49 | self.position.x += self.speed * time_delta_secs 50 | self.current_stamina -= 0.4 51 | if self.moving_up: 52 | self.position.y -= self.speed * time_delta_secs 53 | self.current_stamina -= 0.4 54 | if self.moving_down: 55 | self.position.y += self.speed * time_delta_secs 56 | self.current_stamina -= 0.4 57 | 58 | self.current_stamina = max(self.current_stamina, 0) 59 | 60 | if self.current_stamina < self.max_stamina: 61 | self.stam_recharge_acc += time_delta_secs 62 | if self.stam_recharge_acc >= self.stam_recharge_tick: 63 | self.current_stamina += 1 64 | self.stam_recharge_acc = 0.0 65 | 66 | self.current_stamina = min(self.current_stamina, self.max_stamina) 67 | 68 | self.rect.topleft = (int(self.position.x), int(self.position.y)) 69 | 70 | 71 | pygame.init() 72 | 73 | 74 | pygame.display.set_caption('Status Bars') 75 | window_surface = pygame.display.set_mode((800, 600)) 76 | manager = pygame_gui.UIManager((800, 600), 'data/themes/status_bar_theme.json') 77 | 78 | background = pygame.Surface((800, 600)) 79 | background.fill(manager.ui_theme.get_colour('dark_bg')) 80 | 81 | sprite_list = pygame.sprite.Group() 82 | happy_sprite = HappySprite(sprite_list) 83 | 84 | 85 | progress_bar = pygame_gui.elements.UIStatusBar(pygame.Rect((100, 100), (200, 30)), 86 | manager, 87 | None, 88 | object_id=ObjectID('#progress_bar', '@UIStatusBar')) 89 | 90 | health_bar = pygame_gui.elements.UIStatusBar(pygame.Rect((0, 30), (50, 6)), 91 | manager, 92 | sprite=happy_sprite, 93 | percent_method=happy_sprite.get_health_percentage, 94 | object_id=ObjectID( 95 | '#health_bar', '@player_status_bars')) 96 | mana_bar = pygame_gui.elements.UIStatusBar(pygame.Rect((0, 40), (50, 6)), 97 | manager, 98 | sprite=happy_sprite, 99 | percent_method=happy_sprite.get_mana_percentage, 100 | object_id=ObjectID( 101 | '#mana_bar', '@player_status_bars')) 102 | stamina_bar = pygame_gui.elements.UIStatusBar(pygame.Rect((0, 50), (50, 6)), 103 | manager, 104 | sprite=happy_sprite, 105 | percent_method=happy_sprite.get_stamina_percentage, 106 | object_id=ObjectID( 107 | '#stamina_bar', '@player_status_bars')) 108 | 109 | progress = 0 110 | time_acc = 0 111 | clock = pygame.time.Clock() 112 | is_running = True 113 | 114 | while is_running: 115 | time_delta = clock.tick(60)/1000.0 116 | for event in pygame.event.get(): 117 | if event.type == pygame.QUIT: 118 | is_running = False 119 | 120 | if event.type == pygame.KEYDOWN: 121 | if event.key == pygame.K_LEFT: 122 | happy_sprite.moving_left = True 123 | if event.key == pygame.K_RIGHT: 124 | happy_sprite.moving_right = True 125 | if event.key == pygame.K_UP: 126 | happy_sprite.moving_up = True 127 | if event.key == pygame.K_DOWN: 128 | happy_sprite.moving_down = True 129 | 130 | if event.type == pygame.KEYUP: 131 | if event.key == pygame.K_LEFT: 132 | happy_sprite.moving_left = False 133 | if event.key == pygame.K_RIGHT: 134 | happy_sprite.moving_right = False 135 | if event.key == pygame.K_UP: 136 | happy_sprite.moving_up = False 137 | if event.key == pygame.K_DOWN: 138 | happy_sprite.moving_down = False 139 | 140 | manager.process_events(event) 141 | 142 | sprite_list.update(time_delta) 143 | manager.update(time_delta) 144 | 145 | time_acc += time_delta 146 | progress = (time_acc/10.0) 147 | if progress > 1.0: 148 | time_acc = 0.0 149 | progress_bar.percent_full = progress 150 | 151 | window_surface.blit(background, (0, 0)) 152 | sprite_list.draw(window_surface) 153 | manager.draw_ui(window_surface) 154 | 155 | pygame.display.update() 156 | -------------------------------------------------------------------------------- /text_console.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | import pygame 4 | import pygame_gui 5 | 6 | import subprocess 7 | import threading 8 | import os 9 | 10 | 11 | class Output: 12 | def __init__(self): 13 | self.text = '' 14 | 15 | 16 | pygame.init() 17 | 18 | 19 | pygame.display.set_caption('Pygame GUI - Console example') 20 | window_surface = pygame.display.set_mode((800, 600)) 21 | manager = pygame_gui.UIManager((800, 600), 'data/themes/console_theme.json') 22 | 23 | background = pygame.Surface((800, 600)) 24 | background.fill(manager.ui_theme.get_colour('dark_bg')) 25 | 26 | console_window = pygame_gui.windows.UIConsoleWindow(rect=pygame.rect.Rect((50, 50), (700, 500)), 27 | manager=manager) 28 | 29 | clock = pygame.time.Clock() 30 | is_running = True 31 | 32 | python_process = None 33 | 34 | output_str = None 35 | data_lock = None 36 | 37 | while is_running: 38 | time_delta = clock.tick(60)/1000.0 39 | for event in pygame.event.get(): 40 | if event.type == pygame.QUIT: 41 | is_running = False 42 | 43 | if (event.type == pygame_gui.UI_CONSOLE_COMMAND_ENTERED and 44 | event.ui_element == console_window): 45 | command = event.command 46 | 47 | if python_process is not None and output_str is not None: 48 | bytes_command = (command + '\n').encode() 49 | python_process.stdin.write(bytes_command) 50 | python_process.stdin.flush() 51 | 52 | else: 53 | if command == 'python': 54 | console_window.set_log_prefix(" ") 55 | python_process = subprocess.Popen(['python', '-i'], 56 | stdin=subprocess.PIPE, 57 | stdout=subprocess.PIPE, 58 | stderr=subprocess.STDOUT, shell=False) 59 | output_str = Output() 60 | data_lock = threading.Lock() 61 | 62 | def write_all(process, output, lock): 63 | while True: 64 | data = process.stdout.read(1).decode("utf-8") 65 | if not data: 66 | break 67 | with lock: 68 | output.text += data 69 | 70 | 71 | writer = threading.Thread(target=write_all, args=(python_process, 72 | output_str, 73 | data_lock)) 74 | writer.start() 75 | 76 | elif command == 'clear': 77 | console_window.clear_log() 78 | 79 | manager.process_events(event) 80 | 81 | if python_process is not None: 82 | if "\n" in output_str.text: 83 | split_output = output_str.text.split('\n', 1) 84 | with data_lock: 85 | output_str.text = split_output[1] 86 | output_line_to_print = split_output[0].strip() 87 | console_window.add_output_line_to_log(output_line_to_print) 88 | elif len(output_str.text) > 0: 89 | output_line_to_print = output_str.text.strip() 90 | with data_lock: 91 | output_str.text = "" 92 | console_window.add_output_line_to_log(output_line_to_print, remove_line_break=True) 93 | 94 | if python_process.poll() is not None: 95 | print('Python finished') 96 | python_process = None 97 | 98 | manager.update(time_delta) 99 | 100 | window_surface.blit(background, (0, 0)) 101 | manager.draw_ui(window_surface) 102 | 103 | pygame.display.update() 104 | 105 | if python_process is not None: 106 | python_process.kill() -------------------------------------------------------------------------------- /text_effects.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import pygame_gui 3 | 4 | from pygame_gui.elements import UITextBox, UILabel, UIButton, UITooltip 5 | 6 | pygame.init() 7 | 8 | 9 | pygame.display.set_caption('Text Effects') 10 | window_surface = pygame.display.set_mode((800, 600)) 11 | ui_manager = pygame_gui.UIManager((800, 600), 'data/themes/text_effects_theme.json') 12 | 13 | background = pygame.Surface((800, 600)) 14 | background.fill((50, 50, 40)) # ui_manager.get_theme().get_colour('dark_bg') 15 | 16 | ui_manager.add_font_paths("PermanentMarker", 17 | "data/fonts/PermanentMarker-Regular.ttf") 18 | 19 | ui_manager.preload_fonts([{'name': 'PermanentMarker', 'point_size': 14, 'style': 'regular'}]) 20 | 21 | text_box = UITextBox( 22 | html_text="My " 23 | "" 24 | "" 25 | "EARTHQUAKE " 26 | "" 27 | "" 28 | "will " 29 | "SHATTER" 30 | "" 31 | " your bones. Puny Mortals.", 32 | relative_rect=pygame.Rect(100, 100, 200, 100), 33 | manager=ui_manager) 34 | 35 | effect_label = UILabel( 36 | relative_rect=pygame.Rect(500, 100, -1, -1), 37 | text='A row of appearing text', 38 | manager=ui_manager) 39 | 40 | clock = pygame.time.Clock() 41 | is_running = True 42 | 43 | debug_chunks = False 44 | 45 | while is_running: 46 | time_delta = clock.tick(60)/1000.0 47 | for event in pygame.event.get(): 48 | if event.type == pygame.QUIT: 49 | is_running = False 50 | 51 | if event.type == pygame.KEYDOWN and event.key == pygame.K_a: 52 | effect_label.set_active_effect(pygame_gui.TEXT_EFFECT_TYPING_APPEAR, 53 | params={'time_per_letter': 0.01}) 54 | 55 | if event.type == pygame.KEYDOWN and event.key == pygame.K_d: 56 | effect_label.set_active_effect(pygame_gui.TEXT_EFFECT_FADE_IN, 57 | params={'time_per_alpha_change': 0.1}) 58 | 59 | if event.type == pygame.KEYDOWN and event.key == pygame.K_s: 60 | text_box.set_active_effect(pygame_gui.TEXT_EFFECT_TYPING_APPEAR, 61 | params={'time_per_letter': 0.1, 62 | 'time_per_letter_deviation': 0.2}) 63 | 64 | if event.type == pygame.KEYDOWN and event.key == pygame.K_f: 65 | text_box.set_active_effect(pygame_gui.TEXT_EFFECT_TYPING_APPEAR, 66 | params={'time_per_letter': 0.05, 67 | 'time_per_letter_deviation': 0.02}, 68 | effect_tag='whole_block') 69 | 70 | if event.type == pygame.KEYDOWN and event.key == pygame.K_g: 71 | text_box.set_active_effect(pygame_gui.TEXT_EFFECT_FADE_OUT, 72 | effect_tag='test') 73 | 74 | if event.type == pygame.KEYDOWN and event.key == pygame.K_h: 75 | text_box.set_active_effect(pygame_gui.TEXT_EFFECT_FADE_IN, 76 | effect_tag='test') 77 | 78 | if event.type == pygame.KEYDOWN and event.key == pygame.K_j: 79 | text_box.set_active_effect(pygame_gui.TEXT_EFFECT_BOUNCE, 80 | effect_tag='test') 81 | 82 | if event.type == pygame.KEYDOWN and event.key == pygame.K_k: 83 | text_box.set_active_effect(pygame_gui.TEXT_EFFECT_TILT, 84 | effect_tag='test') 85 | 86 | if event.type == pygame.KEYDOWN and event.key == pygame.K_l: 87 | text_box.set_active_effect(pygame_gui.TEXT_EFFECT_SHAKE, 88 | params={'loop': False, 89 | 'frequency': 45, 90 | 'amplitude': 10, 91 | 'duration': 3.0}, 92 | effect_tag='test') 93 | 94 | if event.type == pygame.KEYDOWN and event.key == pygame.K_x: 95 | text_box.set_active_effect(pygame_gui.TEXT_EFFECT_TILT, 96 | effect_tag='shatter') 97 | 98 | if event.type == pygame.KEYDOWN and event.key == pygame.K_z: 99 | debug_chunks = not debug_chunks 100 | 101 | for row in text_box.text_box_layout.layout_rows: 102 | for chunk in row.items: 103 | print(chunk) 104 | 105 | ui_manager.process_events(event) 106 | 107 | ui_manager.update(time_delta) 108 | 109 | window_surface.blit(background, (0, 0)) 110 | ui_manager.draw_ui(window_surface) 111 | 112 | if debug_chunks: 113 | text_box_offset = (text_box.padding[0] + text_box.border_width["left"] + 114 | text_box.shadow_width + 115 | text_box.rounded_corner_width_offsets[0], 116 | text_box.padding[1] + text_box.border_width["top"] + 117 | text_box.shadow_width + 118 | text_box.rounded_corner_width_offsets[0]) 119 | for row in text_box.text_box_layout.layout_rows: 120 | for chunk in row.items: 121 | debug_rect = chunk.copy() 122 | debug_rect.top += text_box.rect.top + text_box_offset[1] 123 | debug_rect.left += text_box.rect.left + text_box_offset[0] 124 | pygame.draw.rect(window_surface, pygame.Color('#FF0000'), debug_rect, 1) 125 | debug_row = row.copy() 126 | debug_row.top += text_box.rect.top + text_box_offset[1] 127 | debug_row.left += text_box.rect.left + text_box_offset[0] 128 | pygame.draw.rect(window_surface, pygame.Color('#0000FF'), debug_row, 1) 129 | 130 | pygame.display.update() 131 | -------------------------------------------------------------------------------- /text_embedded_images.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import pygame_gui 3 | 4 | from pygame_gui.elements import UITextBox 5 | from pygame_gui.core import ObjectID 6 | 7 | pygame.init() 8 | 9 | 10 | pygame.display.set_caption('Embedding images in Text Boxes') 11 | window_surface = pygame.display.set_mode((800, 600)) 12 | manager = pygame_gui.UIManager((800, 600), 'data/themes/embedded_images_theme.json') 13 | 14 | background = pygame.Surface((800, 600)) 15 | background.fill(manager.ui_theme.get_colour('dark_bg')) 16 | 17 | 18 | text_box = UITextBox('' 19 | '' 20 | '' 23 | 'Some test text in a box that will ' 24 | 'hopefully wrap correctly around embedded images. ' 25 | 'Best if we have a lot of text to embed the images into to give it a good testing ' 26 | '. This is ' 27 | 'the first version of embedding images and is based around how HTML used to work, though ' 28 | 'probably does not anymore.

' 29 | 'Some test text in a box that will hopefully wrap correctly around embedded images. ' 30 | 'Best if we have a lot of text to embed the images into to give it a good testing. This is ' 31 | 'the first version of embedding images and is based around how HTML used to work, though ' 32 | 'probably does not anymore.

' 33 | 'Some test text in a box that will hopefully wrap correctly around embedded images. ' 34 | 'Best if we have a lot of text to embed the images into to give it a good testing. This is ' 35 | 'the first version of embedding images and is based around how HTML used to work, though ' 36 | 'probably does not anymore.

' 37 | 'Some test text in a box that will hopefully wrap correctly around embedded images. ' 38 | '' 39 | 'Best if we have a lot of text to embed the images into to give it a good testing. This is ' 40 | 'the first version of embedding images and is based around how HTML used to work, though ' 41 | 'probably does not anymore.

' 42 | 43 | 44 | '
', 45 | pygame.Rect((10, 10), (780, 300)), 46 | manager=manager, 47 | object_id=ObjectID(class_id="@text_box", object_id="#text_box_1")) 48 | 49 | clock = pygame.time.Clock() 50 | is_running = True 51 | 52 | while is_running: 53 | time_delta = clock.tick(60)/1000.0 54 | for event in pygame.event.get(): 55 | if event.type == pygame.QUIT: 56 | is_running = False 57 | 58 | manager.process_events(event) 59 | 60 | manager.update(time_delta) 61 | 62 | window_surface.blit(background, (0, 0)) 63 | manager.draw_ui(window_surface) 64 | 65 | pygame.display.update() 66 | -------------------------------------------------------------------------------- /text_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import pygame 3 | import pygame_gui 4 | 5 | from pygame_gui.ui_manager import UIManager 6 | from pygame_gui.elements import UITextBox, UIScrollingContainer, UIDropDownMenu 7 | from pygame_gui.core import IncrementalThreadedResourceLoader, ObjectID 8 | from pygame_gui import UI_TEXT_BOX_LINK_CLICKED, UI_TEXT_EFFECT_FINISHED 9 | 10 | """ 11 | Font load time taken: 0.911 seconds. 12 | Time taken 1st window: 1.509 seconds. 13 | Time taken 2nd window: 0.181 seconds. 14 | """ 15 | 16 | 17 | def create_large_text_box(): 18 | return UITextBox( 19 | '' 20 | '
Lorem


' 21 | 'ipsum dolor sit amet
,' 22 | ' consectetur ' 23 | 'adipiscing elit. in a flibb de dib do ' 24 | 'rub a la clob slip the perry tin fo glorp yip dorp' 25 | 'skorp si pork flum de dum be dung, slob be robble glurp destination flum kin ' 26 | 'slum. Ram slim gordo, fem ' 27 | 'tulip squirrel slippers save socks certainly.
' 28 | 'Vestibulum in commodo me tellus in nisi finibus a sodales.
Vestibulum ' 29 | 'hendrerit mi sed nulla scelerisque, posuere ullamcorper ' 30 | 'sem pulvinar. ' 31 | 'Nulla at pulvinar a odio, a dictum dolor.
Maecenas at tellus a' 32 | 'tortor. a
' 33 | 'In bibendum orci et velit
gravida lacinia.' 34 | '

' 35 | 'In hac a habitasse to platea dictumst.
' 36 | 'Vivamus I interdum mollis lacus nec porttitor.
Morbi ' 37 | 'accumsan, lectus at ' 38 | 'tincidunt to dictum, neque erat tristique erat, ' 39 | 'sed a tempus for nunc dolor in nibh.
' 40 | 'Suspendisse in viverra dui fringilla dolor laoreet, ' 41 | 'sit amet on pharetra a ante ' 42 | 'sollicitudin.
' 43 | '

' 44 | 'consectetur adipiscing elit. in a
' 45 | 'Vestibulum in commodo me tellus in nisi finibus a sodales.
' 46 | 'Vestibulum hendrerit mi sed nulla scelerisque,' 47 | ' posuere ullamcorper ' 48 | 'sem pulvinar. ' 49 | 'Nulla at pulvinar a odio, a dictum dolor.
' 50 | 'Maepenas at tellus a tortor. a
' 51 | 'In bibendum orci et velit
gravida lacinia.

' 52 | 'In hac a habitasse to platea dictumst.
' 53 | 'Vivamus I interdum mollis lacus nec porttitor.
Morbi ' 54 | 'accumsan, lectus at' 55 | 'tincidunt to dictum, neque erat tristique erat, ' 56 | 'sed a tempus for nunc' 57 | ' dolor in nibh.
' 58 | 'Suspendisse in viverra dui fringilla dolor laoreet, sit amet on' 59 | ' pharetra a ante ' 60 | 'sollicitudin.
', 61 | pygame.Rect(10, 10, 500, 580), 62 | manager=ui_manager, 63 | object_id='#text_box_1') 64 | 65 | 66 | pygame.init() 67 | 68 | pygame.display.set_caption("Text test") 69 | screen_size = (800, 600) 70 | screen = pygame.display.set_mode(screen_size) # FULLSCREEN 71 | 72 | background_surface = pygame.Surface(screen_size) 73 | background_surface.fill(pygame.Color("#000000")) 74 | 75 | loader = IncrementalThreadedResourceLoader() 76 | clock = pygame.time.Clock() 77 | ui_manager = UIManager(screen_size, 'data/themes/theme_1.json', resource_loader=loader) 78 | ui_manager.add_font_paths("Montserrat", 79 | "data/fonts/Montserrat-Regular.ttf", 80 | "data/fonts/Montserrat-Bold.ttf", 81 | "data/fonts/Montserrat-Italic.ttf", 82 | "data/fonts/Montserrat-BoldItalic.ttf") 83 | 84 | load_time_1 = clock.tick() 85 | ui_manager.preload_fonts([{'name': 'Montserrat', 'html_size': 4.5, 'style': 'bold'}, 86 | {'name': 'Montserrat', 'html_size': 4.5, 'style': 'regular'}, 87 | {'name': 'Montserrat', 'html_size': 2, 'style': 'regular'}, 88 | {'name': 'Montserrat', 'html_size': 2, 'style': 'italic'}, 89 | {'name': 'Montserrat', 'html_size': 6, 'style': 'bold'}, 90 | {'name': 'Montserrat', 'html_size': 6, 'style': 'regular'}, 91 | {'name': 'Montserrat', 'html_size': 6, 'style': 'bold_italic'}, 92 | {'name': 'Montserrat', 'html_size': 4, 'style': 'bold'}, 93 | {'name': 'Montserrat', 'html_size': 4, 'style': 'regular'}, 94 | {'name': 'Montserrat', 'html_size': 4, 'style': 'italic'}, 95 | {'name': 'noto_sans', 'html_size': 2, 'style': 'regular'}, 96 | {'name': 'noto_sans', 'html_size': 2, 'style': 'bold'}, 97 | {'name': 'noto_sans', 'html_size': 2, 'style': 'bold_italic'} 98 | ]) 99 | loader.start() 100 | finished_loading = False 101 | while not finished_loading: 102 | finished_loading, progress = loader.update() 103 | load_time_2 = clock.tick() 104 | print('Font load time taken:', load_time_2/1000.0, 'seconds.') 105 | 106 | time_1 = clock.tick() 107 | html_text_line = create_large_text_box() 108 | time_2 = clock.tick() 109 | 110 | 111 | htm_text_block_2 = UITextBox('Hey, What the heck! ' 112 | '

' 113 | 'This is some text ' 114 | 'in a different box,' 115 | ' hooray for variety - ' 116 | 'if you want then you should put a ring upon it. ' 117 | 'What if we do a really long word? ' 118 | 'derp FALALALALALALALXALALALXALALALALAAPaaaaarp gosh' 119 | '
', 120 | pygame.Rect((520, 10), (250, -1)), 121 | manager=ui_manager, 122 | object_id=ObjectID(class_id="@white_text_box", 123 | object_id="#text_box_2")) 124 | htm_text_block_2.set_active_effect(pygame_gui.TEXT_EFFECT_TYPING_APPEAR) 125 | 126 | time_3 = clock.tick() 127 | 128 | print('Time taken 1st window:', time_2/1000.0, 'seconds.') 129 | print('Time taken 2nd window:', time_3/1000.0, 'seconds.') 130 | 131 | 132 | ui_manager.print_unused_fonts() 133 | 134 | scrolling_container = UIScrollingContainer(pygame.Rect(520, 250, 250, 300), 135 | allow_scroll_x=False, 136 | should_grow_automatically=False) 137 | scrolling_container.set_scrollable_area_dimensions((250, 600)) 138 | 139 | 140 | text_box_inside_scrolling_container = UITextBox(html_text="Some text inside a text box, itself" 141 | " inside a container that scrolls", 142 | relative_rect=pygame.Rect(20, 20, 150, 200), 143 | container=scrolling_container) 144 | 145 | scrolling_text_box_inside_scrolling_container = UITextBox(html_text="Some text inside a scrolling text box, itself" 146 | " inside a container that scrolls. " 147 | "scrolling should work correctly with the mousewheel, " 148 | "depending on whether we are hovering this text box, or" 149 | " whether we are hovering other stuff in the " 150 | "scrolling container", 151 | relative_rect=pygame.Rect(20, 280, 180, 200), 152 | container=scrolling_container) 153 | 154 | running = True 155 | 156 | while running: 157 | time_delta = clock.tick(60)/1000.0 158 | 159 | for event in pygame.event.get(): 160 | if event.type == pygame.QUIT: 161 | running = False 162 | if event.type == pygame.KEYDOWN: 163 | if event.key == pygame.K_f: 164 | htm_text_block_2.set_active_effect(pygame_gui.TEXT_EFFECT_FADE_OUT) 165 | if event.key == pygame.K_g: 166 | htm_text_block_2.set_active_effect(pygame_gui.TEXT_EFFECT_FADE_IN) 167 | if event.key == pygame.K_h: 168 | htm_text_block_2.set_active_effect(pygame_gui.TEXT_EFFECT_TYPING_APPEAR) 169 | if event.key == pygame.K_k: 170 | html_text_line.kill() 171 | if event.key == pygame.K_b: 172 | html_text_line = create_large_text_box() 173 | 174 | if event.type == pygame.KEYDOWN and event.key == pygame.K_x: 175 | html_text_line.set_active_effect(pygame_gui.TEXT_EFFECT_TILT, 176 | effect_tag='spin_me') 177 | if event.type == pygame.KEYDOWN and event.key == pygame.K_c: 178 | html_text_line.set_active_effect(pygame_gui.TEXT_EFFECT_EXPAND_CONTRACT, 179 | params={'max_scale': 5.0}, 180 | effect_tag='spin_me') 181 | if event.type == pygame.KEYDOWN and event.key == pygame.K_v: 182 | html_text_line.set_active_effect(pygame_gui.TEXT_EFFECT_BOUNCE, 183 | params={'bounce_max_height': 50, 184 | 'time_to_complete_bounce': 0.8}, 185 | effect_tag='spin_me') 186 | 187 | if event.type == UI_TEXT_BOX_LINK_CLICKED: 188 | if event.ui_element is htm_text_block_2: 189 | if event.link_target == 'test': 190 | print('clicked test link') 191 | else: 192 | print('clicked link in text block 1') 193 | 194 | if event.type == UI_TEXT_EFFECT_FINISHED: 195 | print("finished text effect: " + event.effect) 196 | 197 | ui_manager.process_events(event) 198 | 199 | ui_manager.update(time_delta) 200 | 201 | screen.blit(background_surface, (0, 0)) 202 | ui_manager.draw_ui(screen) 203 | 204 | pygame.display.update() 205 | -------------------------------------------------------------------------------- /translations_test.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import pygame_gui 3 | 4 | 5 | pygame.init() 6 | 7 | 8 | pygame.display.set_caption('Translations Test') 9 | window_surface = pygame.display.set_mode((800, 600)) 10 | manager = pygame_gui.UIManager((800, 600), 11 | theme_path='data/themes/translations_theme.json', 12 | starting_language='en', 13 | translation_directory_paths=['data/translations']) 14 | 15 | background = pygame.Surface((800, 600)) 16 | background.fill(manager.ui_theme.get_colour('dark_bg')) 17 | 18 | languages_list = ['pygame-gui.Arabic', 19 | 'pygame-gui.German', 20 | 'pygame-gui.English', 21 | 'pygame-gui.Spanish', 22 | 'pygame-gui.French', 23 | 'pygame-gui.Hebrew', 24 | 'pygame-gui.Georgian', 25 | 'pygame-gui.Indonesian', 26 | 'pygame-gui.Italian', 27 | 'pygame-gui.Japanese', 28 | 'pygame-gui.Korean', 29 | 'pygame-gui.Polish', 30 | 'pygame-gui.Portuguese', 31 | 'pygame-gui.Russian', 32 | 'pygame-gui.Ukrainian', 33 | 'pygame-gui.Vietnamese', 34 | 'pygame-gui.Chinese'] 35 | 36 | languages_dropdown = pygame_gui.elements.UIDropDownMenu(languages_list, 37 | 'pygame-gui.English', 38 | pygame.Rect((10, 20), (250, 30)), 39 | manager=manager) 40 | 41 | test_label = pygame_gui.elements.UILabel(pygame.Rect((10, 100), (150, 40)), 42 | 'pygame-gui.English', 43 | manager) 44 | 45 | confirmation_dialog = pygame_gui.windows.UIConfirmationDialog( 46 | pygame.Rect((400, 350), (300, 200)), 47 | manager=manager, 48 | action_long_desc="examples.hello_world_message_text", 49 | blocking=False) 50 | 51 | text_box = pygame_gui.elements.UITextBox( 52 | html_text="examples.holmes_text_test", 53 | relative_rect=pygame.Rect(300, 100, 400, 200), 54 | manager=manager) 55 | 56 | 57 | clock = pygame.time.Clock() 58 | is_running = True 59 | debug_mode = False 60 | 61 | while is_running: 62 | time_delta = clock.tick(60)/1000.0 63 | for event in pygame.event.get(): 64 | if event.type == pygame.QUIT: 65 | is_running = False 66 | 67 | if event.type == pygame.KEYDOWN and event.key == pygame.K_d: 68 | debug_mode = False if debug_mode else True 69 | manager.set_visual_debug_mode(debug_mode) 70 | 71 | if event.type == pygame_gui.UI_DROP_DOWN_MENU_CHANGED: 72 | if event.text == 'pygame-gui.Arabic': 73 | manager.set_locale('ar') 74 | elif event.text == 'pygame-gui.German': 75 | manager.set_locale('de') 76 | elif event.text == 'pygame-gui.English': 77 | manager.set_locale('en') 78 | elif event.text == 'pygame-gui.Spanish': 79 | manager.set_locale('es') 80 | elif event.text == 'pygame-gui.French': 81 | manager.set_locale('fr') 82 | elif event.text == 'pygame-gui.Georgian': 83 | manager.set_locale('ge') 84 | elif event.text == 'pygame-gui.Hebrew': 85 | manager.set_locale('he') 86 | elif event.text == 'pygame-gui.Indonesian': 87 | manager.set_locale('id') 88 | elif event.text == 'pygame-gui.Italian': 89 | manager.set_locale('it') 90 | elif event.text == 'pygame-gui.Japanese': 91 | manager.set_locale('ja') 92 | elif event.text == 'pygame-gui.Korean': 93 | manager.set_locale('ko') 94 | elif event.text == 'pygame-gui.Polish': 95 | manager.set_locale('pl') 96 | elif event.text == 'pygame-gui.Portuguese': 97 | manager.set_locale('pt') 98 | elif event.text == 'pygame-gui.Russian': 99 | manager.set_locale('ru') 100 | elif event.text == 'pygame-gui.Ukrainian': 101 | manager.set_locale('uk') 102 | elif event.text == 'pygame-gui.Vietnamese': 103 | manager.set_locale('vi') 104 | elif event.text == 'pygame-gui.Chinese': 105 | manager.set_locale('zh') 106 | 107 | manager.process_events(event) 108 | 109 | manager.update(time_delta) 110 | 111 | window_surface.blit(background, (0, 0)) 112 | manager.draw_ui(window_surface) 113 | 114 | pygame.display.update() 115 | -------------------------------------------------------------------------------- /two_sided_border_button.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import pygame_gui 3 | 4 | 5 | pygame.init() 6 | 7 | pygame.display.set_caption('Two Sided Border Button Example') 8 | window_surface = pygame.display.set_mode((800, 600)) 9 | background = pygame.Surface((800, 600)) 10 | background.fill(pygame.Color('#000000')) 11 | 12 | manager = pygame_gui.UIManager((800, 600), 'data/themes/two_sided_border_theme.json') 13 | 14 | # Create a button with borders only on left and bottom sides 15 | hello_button = pygame_gui.elements.UIButton(relative_rect=pygame.Rect((350, 275), (200, 50)), 16 | text='Hello', 17 | manager=manager) 18 | 19 | clock = pygame.time.Clock() 20 | is_running = True 21 | 22 | while is_running: 23 | time_delta = clock.tick(60)/1000.0 24 | 25 | for event in pygame.event.get(): 26 | if event.type == pygame.QUIT: 27 | is_running = False 28 | 29 | manager.process_events(event) 30 | 31 | manager.update(time_delta) 32 | 33 | window_surface.blit(background, (0, 0)) 34 | manager.draw_ui(window_surface) 35 | 36 | pygame.display.update() 37 | -------------------------------------------------------------------------------- /ui_element_creation_speed_test.py: -------------------------------------------------------------------------------- 1 | from sys import stdout 2 | from pstats import Stats 3 | from cProfile import Profile 4 | 5 | import pygame 6 | import pygame_gui 7 | import os 8 | 9 | # (182 x rounded rectangles) 10 | 11 | # in 0.42 12 | # -------- 13 | # Button creation time taken: 0.092 seconds. 14 | # Clear and recreation time taken: 0.088 seconds. 15 | 16 | # in 0.55 17 | # -------- 18 | # Button creation time taken: 0.21 seconds. 19 | # Clear and recreation time taken: 0.229 seconds. 20 | 21 | # in 0.56 22 | # -------- 23 | # Button creation time taken: 0.078 seconds. 24 | # Clear and recreation time taken: 0.079 seconds. 25 | 26 | # in 0.57 - got slower again, dang. 27 | # -------- 28 | # Button creation time taken: 0.096 seconds. 29 | # Clear and recreation time taken: 0.095 seconds. 30 | 31 | # in 0.6.10 32 | # --------- 33 | # Button creation time taken: 0.062 seconds. 34 | # Clear and recreation time taken: 0.057 seconds. 35 | print(os.getcwd()) 36 | pygame.init() 37 | 38 | 39 | pygame.display.set_caption('Button Theming Test') 40 | window_surface = pygame.display.set_mode((800, 600)) 41 | manager = pygame_gui.UIManager((800, 600), 'data/themes/quick_theme.json') 42 | clock = pygame.time.Clock() 43 | 44 | background = pygame.Surface((800, 600)) 45 | background.fill(manager.get_theme().get_colour('dark_bg')) 46 | 47 | load_time_1 = clock.tick() 48 | 49 | test_container = pygame_gui.core.UIContainer(pygame.Rect(0, 0, 800, 600), 50 | manager=manager) 51 | 52 | 53 | def create_buttons(): 54 | button_row_width = 50 55 | button_row_height = 40 56 | spacing = 10 57 | for j in range(1, 15): 58 | for i in range(1, 14): 59 | position = (i * spacing + ((i - 1) * button_row_width), 60 | (j * spacing + ((j - 1) * button_row_height))) 61 | pygame_gui.elements.UIButton(relative_rect=pygame.Rect(position, 62 | (button_row_width, 63 | button_row_height)), 64 | text=str(i)+',' + str(j), 65 | manager=manager, 66 | container=test_container, 67 | object_id='#'+str(i) + str(j)) 68 | load_time_2 = clock.tick() 69 | print('Button creation time taken:', load_time_2 / 1000.0, 'seconds.') 70 | test_container.clear() 71 | 72 | for j in range(1, 15): 73 | for i in range(1, 14): 74 | position = (i * spacing + ((i - 1) * button_row_width), 75 | (j * spacing + ((j - 1) * button_row_height))) 76 | pygame_gui.elements.UIButton(relative_rect=pygame.Rect(position, 77 | (button_row_width, 78 | button_row_height)), 79 | text=str(i)+',' + str(j), 80 | manager=manager, 81 | container=test_container, 82 | object_id='#'+str(i) + str(j)) 83 | 84 | load_time_3 = clock.tick() 85 | print('Clear and recreation time taken:', load_time_3 / 1000.0, 'seconds.') 86 | 87 | 88 | create_buttons() 89 | is_running = True 90 | 91 | while is_running: 92 | time_delta = clock.tick(60)/1000.0 93 | for event in pygame.event.get(): 94 | if event.type == pygame.QUIT: 95 | is_running = False 96 | 97 | manager.process_events(event) 98 | 99 | manager.update(time_delta) 100 | 101 | window_surface.blit(background, (0, 0)) 102 | manager.draw_ui(window_surface) 103 | 104 | pygame.display.update() 105 | 106 | 107 | if __name__ == '__main__': 108 | profiler = Profile() 109 | profiler.runcall(create_buttons) 110 | stats = Stats(profiler, stream=stdout) 111 | stats.strip_dirs() 112 | stats.sort_stats('cumulative') 113 | stats.print_stats() 114 | -------------------------------------------------------------------------------- /user_controlled_image_loading_example.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import pygame_gui 3 | 4 | from pygame_gui.elements import UIButton 5 | from pygame_gui.core import IncrementalThreadedResourceLoader 6 | 7 | 8 | # 20 * image buttons 9 | # Sequential Image loading time taken: 27.362 seconds. 10 | # 0.6.10 loading time taken: 10.411 seconds 11 | pygame.init() 12 | 13 | 14 | pygame.display.set_caption('Image Loading Test') 15 | window_surface = pygame.display.set_mode((800, 600)) 16 | background = pygame.Surface((800, 600)) 17 | background.fill(pygame.Color('#000000')) 18 | clock = pygame.time.Clock() 19 | load_time_1 = clock.tick() 20 | loader = IncrementalThreadedResourceLoader() 21 | manager = pygame_gui.UIManager((800, 600), 22 | pygame_gui.PackageResource('data.themes', 'image_loading_test.json'), 23 | resource_loader=loader) 24 | 25 | loader.start() 26 | finished = False 27 | last_progress = 0 28 | print("Progress: ", end='') 29 | while not finished: 30 | finished, progress = loader.update() 31 | int_progress = int(10 * progress) 32 | if last_progress != int_progress: 33 | last_progress = int_progress 34 | print('■', end='') 35 | print('',) 36 | load_time_2 = clock.tick() 37 | 38 | print('Image loading time taken:', load_time_2 / 1000.0, 'seconds.') 39 | 40 | button_row_width = 200 41 | button_row_height = 150 42 | spacing = 0 43 | num_buttons = 1 44 | for j in range(1, 5): 45 | for i in range(1, 5): 46 | position = (i * spacing + ((i - 1) * button_row_width), 47 | (j * spacing + ((j - 1) * button_row_height))) 48 | button = UIButton(relative_rect=pygame.Rect(position, (button_row_width, 49 | button_row_height)), 50 | text=str(num_buttons), 51 | manager=manager, 52 | object_id='#'+str(num_buttons)) 53 | num_buttons += 1 54 | 55 | is_running = True 56 | 57 | while is_running: 58 | time_delta = clock.tick(60)/1000.0 59 | for event in pygame.event.get(): 60 | if event.type == pygame.QUIT: 61 | is_running = False 62 | 63 | manager.process_events(event) 64 | 65 | manager.update(time_delta) 66 | 67 | window_surface.blit(background, (0, 0)) 68 | manager.draw_ui(window_surface) 69 | 70 | pygame.display.update() 71 | -------------------------------------------------------------------------------- /using_ui_form.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import pygame_gui 3 | from pygame_gui import UI_FORM_SUBMITTED 4 | from pygame_gui.elements import UIButton, UIForm, UIDropDownMenu 5 | 6 | pygame.init() 7 | 8 | pygame.display.set_caption("UI Form Example") 9 | window_surface = pygame.display.set_mode((800, 600)) 10 | 11 | background = pygame.Surface((800, 600)) 12 | background.fill(pygame.Color("#000000")) 13 | 14 | manager = pygame_gui.UIManager((800, 600)) 15 | 16 | test_rect = pygame.Rect(40, 50, 700, 500) 17 | 18 | questionnaire = { 19 | "Just enter one character:": "character", 20 | "Perhaps some more text:": "short_text", 21 | "Or go wild!": "long_text", 22 | "how about a section?": { 23 | "do you like it?": "boolean", 24 | "well, here, section-ception": { 25 | "do you like it?": "boolean", 26 | "well, here, section-ception": {"finally...": "integer"}, 27 | }, 28 | }, 29 | "Enter a float:": "decimal(default=0.01)", 30 | "You *must* enter something here:": "short_text('here', True)", 31 | "Let's make this form longer:": "long_text", 32 | "let's try a button": UIButton(pygame.Rect(100, 100, 100, 100), "button"), 33 | "Try entering a password!:": "password", 34 | "A dropdown appeared!": UIDropDownMenu( 35 | ["foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo", "foo"], 36 | "foo", 37 | pygame.Rect(100, 100, 100, 100), 38 | ), 39 | } 40 | form_test = UIForm(test_rect, questionnaire, manager) 41 | 42 | print(form_test.combined_element_ids) 43 | print(form_test.get_container().get_most_specific_combined_id()) 44 | print(form_test.parsed_questionnaire["how about a section?"].combined_element_ids) 45 | print(form_test.parsed_questionnaire["how about a section?"].main_expand_button.combined_element_ids) 46 | # print( 47 | # form_test.parsed_questionnaire["how about a section?"] 48 | # .parsed_questionnaire["well, here, section-ception"] 49 | # .combined_element_ids 50 | # ) 51 | 52 | 53 | clock = pygame.time.Clock() 54 | is_running = True 55 | pressed = False 56 | element = None 57 | 58 | while is_running: 59 | time_delta = clock.tick(30) / 1000.0 60 | for event in pygame.event.get(): 61 | if event.type == pygame.QUIT: 62 | is_running = False 63 | 64 | elif event.type == pygame_gui.UI_BUTTON_PRESSED: 65 | print(event.ui_element.most_specific_combined_id) 66 | pressed = False 67 | element = None 68 | 69 | elif event.type == UI_FORM_SUBMITTED: 70 | print(event.form_values) 71 | 72 | manager.process_events(event) 73 | 74 | manager.update(time_delta) 75 | 76 | window_surface.blit(background, (0, 0)) 77 | 78 | manager.draw_ui(window_surface) 79 | pygame.display.update() 80 | -------------------------------------------------------------------------------- /windowed_mini_games_app.py: -------------------------------------------------------------------------------- 1 | import pygame 2 | import pygame_gui 3 | 4 | from pygame_gui.ui_manager import UIManager 5 | from pygame_gui.elements.ui_window import UIWindow 6 | from pygame_gui.elements.ui_image import UIImage 7 | 8 | from pong.pong import PongGame 9 | 10 | PONG_WINDOW_SELECTED = pygame.event.custom_type() 11 | 12 | 13 | class PongWindow(UIWindow): 14 | def __init__(self, position, ui_manager): 15 | super().__init__(pygame.Rect(position, (320, 240)), ui_manager, 16 | window_display_title='Super Awesome Pong!', 17 | object_id='#pong_window') 18 | 19 | game_surface_size = self.get_container().get_size() 20 | self.game_surface_element = UIImage(pygame.Rect((0, 0), 21 | game_surface_size), 22 | pygame.Surface(game_surface_size).convert(), 23 | manager=ui_manager, 24 | container=self, 25 | parent_element=self) 26 | 27 | self.pong_game = PongGame(game_surface_size) 28 | 29 | self.is_active = False 30 | 31 | def process_event(self, event): 32 | handled = super().process_event(event) 33 | if (event.type == pygame_gui.UI_BUTTON_PRESSED and 34 | event.ui_object_id == "#pong_window.#title_bar" and 35 | event.ui_element == self.title_bar): 36 | handled = True 37 | event_data = {'ui_element': self, 38 | 'ui_object_id': self.most_specific_combined_id} 39 | window_selected_event = pygame.event.Event(PONG_WINDOW_SELECTED, 40 | event_data) 41 | pygame.event.post(window_selected_event) 42 | if self.is_active: 43 | handled = self.pong_game.process_event(event) 44 | return handled 45 | 46 | def update(self, time_delta): 47 | if self.alive() and self.is_active: 48 | self.pong_game.update(time_delta) 49 | 50 | super().update(time_delta) 51 | 52 | self.pong_game.draw(self.game_surface_element.image) 53 | 54 | 55 | class MiniGamesApp: 56 | def __init__(self): 57 | pygame.init() 58 | 59 | self.root_window_surface = pygame.display.set_mode((1024, 600)) 60 | 61 | self.background_surface = pygame.Surface((1024, 600)).convert() 62 | self.background_surface.fill(pygame.Color('#505050')) 63 | self.ui_manager = UIManager((1024, 600), 'data/themes/theme_3.json') 64 | self.clock = pygame.time.Clock() 65 | self.is_running = True 66 | 67 | self.pong_window_1 = PongWindow((25, 25), self.ui_manager) 68 | self.pong_window_2 = PongWindow((50, 50), self.ui_manager) 69 | 70 | def run(self): 71 | while self.is_running: 72 | time_delta = self.clock.tick(60)/1000.0 73 | 74 | for event in pygame.event.get(): 75 | if event.type == pygame.QUIT: 76 | self.is_running = False 77 | 78 | self.ui_manager.process_events(event) 79 | 80 | if event.type == PONG_WINDOW_SELECTED: 81 | event.ui_element.is_active = True 82 | if event.ui_element == self.pong_window_1: 83 | self.pong_window_2.is_active = False 84 | elif event.ui_element == self.pong_window_2: 85 | self.pong_window_1.is_active = False 86 | 87 | self.ui_manager.update(time_delta) 88 | 89 | self.root_window_surface.blit(self.background_surface, (0, 0)) 90 | self.ui_manager.draw_ui(self.root_window_surface) 91 | 92 | pygame.display.update() 93 | 94 | 95 | if __name__ == '__main__': 96 | app = MiniGamesApp() 97 | app.run() 98 | --------------------------------------------------------------------------------